Commit 83b49ad6 authored by Yonghong Song's avatar Yonghong Song

introduce new BPF APIs to get kernel syscall entry func name/prefix

As described in issue #1695, on 4.17 for syscalls on x86,
both sys_<fnname> and SyS_<fnname> are gone, the replacements
are __ia32_sys_sync and __x64_sys_sync.
The commit in Linus tree:
https://github.com/torvalds/linux/commit/d5a00528b58cdb2c71206e18bd021e34c4eab878

This patch introduced two APIs for python BPF object.
The API get_syscall_prefix() returns the prefix "sys_"/"__x64_sys_".
The API get_syscall_fnname(name) returns kernel function name for the syscall,
e.g., on x64, get_syscall_fnname("clone") will return "sys_clone" if kernel
has it, otherwise, "__x64_sys_clone".
get_syscall_prefix() is mostly useful for the regex func specifier of
attach_kprobe().

This patch only fixed the code using python API on examples and tests directory.

TOTO: python on tools directory, C++ and lua
Signed-off-by: default avatarYonghong Song <yhs@fb.com>
parent 435dded9
...@@ -8,4 +8,5 @@ ...@@ -8,4 +8,5 @@
from bcc import BPF from bcc import BPF
# This may not work for 4.17 on x64, you need replace kprobe__sys_clone with kprobe____x64_sys_clone
BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print() BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print()
...@@ -14,7 +14,7 @@ int hello(void *ctx) { ...@@ -14,7 +14,7 @@ int hello(void *ctx) {
# load BPF program # load BPF program
b = BPF(text=prog) b = BPF(text=prog)
b.attach_kprobe(event="sys_clone", fn_name="hello") b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello")
# header # header
print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE")) print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE"))
......
...@@ -32,7 +32,7 @@ int hello(struct pt_regs *ctx) { ...@@ -32,7 +32,7 @@ int hello(struct pt_regs *ctx) {
# load BPF program # load BPF program
b = BPF(text=prog) b = BPF(text=prog)
b.attach_kprobe(event="sys_clone", fn_name="hello") b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello")
# define output data structure in Python # define output data structure in Python
TASK_COMM_LEN = 16 # linux/sched.h TASK_COMM_LEN = 16 # linux/sched.h
......
...@@ -38,7 +38,7 @@ int do_trace(struct pt_regs *ctx) { ...@@ -38,7 +38,7 @@ int do_trace(struct pt_regs *ctx) {
} }
""") """)
b.attach_kprobe(event="sys_sync", fn_name="do_trace") b.attach_kprobe(event=b.get_syscall_fnname("sync"), fn_name="do_trace")
print("Tracing for quick sync's... Ctrl-C to end") print("Tracing for quick sync's... Ctrl-C to end")
# format output # format output
......
...@@ -15,6 +15,6 @@ int hello(void *ctx) { ...@@ -15,6 +15,6 @@ int hello(void *ctx) {
} }
""" """
b = BPF(text=prog) b = BPF(text=prog)
b.attach_kprobe(event="sys_clone", fn_name="hello") b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello")
print "PID MESSAGE" print "PID MESSAGE"
b.trace_print(fmt="{1} {5}") b.trace_print(fmt="{1} {5}")
...@@ -25,7 +25,7 @@ def cb(cpu, data, size): ...@@ -25,7 +25,7 @@ def cb(cpu, data, size):
prog = """ prog = """
BPF_PERF_OUTPUT(events); BPF_PERF_OUTPUT(events);
BPF_ARRAY(counters, u64, 10); BPF_ARRAY(counters, u64, 10);
int kprobe__sys_clone(void *ctx) { int do_sys_clone(void *ctx) {
struct { struct {
u64 ts; u64 ts;
u64 magic; u64 magic;
...@@ -40,6 +40,8 @@ int kprobe__sys_clone(void *ctx) { ...@@ -40,6 +40,8 @@ int kprobe__sys_clone(void *ctx) {
} }
""" """
b = BPF(text=prog) b = BPF(text=prog)
event_name = b.get_syscall_fnname("clone")
b.attach_kprobe(event=event_name, fn_name="do_sys_clone")
b["events"].open_perf_buffer(cb) b["events"].open_perf_buffer(cb)
@atexit.register @atexit.register
...@@ -48,7 +50,7 @@ def print_counter(): ...@@ -48,7 +50,7 @@ def print_counter():
global b global b
print("counter = %d vs %d" % (counter, b["counters"][ct.c_int(0)].value)) print("counter = %d vs %d" % (counter, b["counters"][ct.c_int(0)].value))
print("Tracing sys_write, try `dd if=/dev/zero of=/dev/null`") print("Tracing " + event_name + ", try `dd if=/dev/zero of=/dev/null`")
print("Tracing... Hit Ctrl-C to end.") print("Tracing... Hit Ctrl-C to end.")
while 1: while 1:
b.perf_buffer_poll() b.perf_buffer_poll()
...@@ -522,6 +522,19 @@ class BPF(object): ...@@ -522,6 +522,19 @@ class BPF(object):
global _num_open_probes global _num_open_probes
del self.uprobe_fds[name] del self.uprobe_fds[name]
_num_open_probes -= 1 _num_open_probes -= 1
def get_syscall_prefix(self):
# test bpf syscall kernel func name
if self.ksymname("sys_bpf") != -1:
return "sys_"
if self.ksymname("__x64_sys_bpf") != -1:
return "__x64_sys_"
# none of them, just return "sys_", later API
# calls will return error
return "sys_"
def get_syscall_fnname(self, name):
return self.get_syscall_prefix() + name
def attach_kprobe(self, event=b"", fn_name=b"", event_re=b""): def attach_kprobe(self, event=b"", fn_name=b"", event_re=b""):
event = _assert_is_bytes(event) event = _assert_is_bytes(event)
......
...@@ -54,7 +54,7 @@ class TestArray(TestCase): ...@@ -54,7 +54,7 @@ class TestArray(TestCase):
text = """ text = """
BPF_PERF_OUTPUT(events); BPF_PERF_OUTPUT(events);
int kprobe__sys_nanosleep(void *ctx) { int do_sys_nanosleep(void *ctx) {
struct { struct {
u64 ts; u64 ts;
} data = {bpf_ktime_get_ns()}; } data = {bpf_ktime_get_ns()};
...@@ -63,6 +63,8 @@ int kprobe__sys_nanosleep(void *ctx) { ...@@ -63,6 +63,8 @@ int kprobe__sys_nanosleep(void *ctx) {
} }
""" """
b = BPF(text=text) b = BPF(text=text)
b.attach_kprobe(event=b.get_syscall_fnname("nanosleep"),
fn_name="do_sys_nanosleep")
b["events"].open_perf_buffer(cb, lost_cb=lost_cb) b["events"].open_perf_buffer(cb, lost_cb=lost_cb)
time.sleep(0.1) time.sleep(0.1)
b.perf_buffer_poll() b.perf_buffer_poll()
...@@ -85,7 +87,7 @@ int kprobe__sys_nanosleep(void *ctx) { ...@@ -85,7 +87,7 @@ int kprobe__sys_nanosleep(void *ctx) {
text = """ text = """
BPF_PERF_OUTPUT(events); BPF_PERF_OUTPUT(events);
int kprobe__sys_nanosleep(void *ctx) { int do_sys_nanosleep(void *ctx) {
struct { struct {
u64 cpu; u64 cpu;
} data = {bpf_get_smp_processor_id()}; } data = {bpf_get_smp_processor_id()};
...@@ -94,6 +96,8 @@ int kprobe__sys_nanosleep(void *ctx) { ...@@ -94,6 +96,8 @@ int kprobe__sys_nanosleep(void *ctx) {
} }
""" """
b = BPF(text=text) b = BPF(text=text)
b.attach_kprobe(event=b.get_syscall_fnname("nanosleep"),
fn_name="do_sys_nanosleep")
b["events"].open_perf_buffer(cb, lost_cb=lost_cb) b["events"].open_perf_buffer(cb, lost_cb=lost_cb)
online_cpus = get_online_cpus() online_cpus = get_online_cpus()
for cpu in online_cpus: for cpu in online_cpus:
......
...@@ -295,7 +295,7 @@ struct args_t { ...@@ -295,7 +295,7 @@ struct args_t {
int flags; int flags;
int mode; int mode;
}; };
int kprobe__sys_open(struct pt_regs *ctx, const char *filename, int do_sys_open(struct pt_regs *ctx, const char *filename,
int flags, int mode) { int flags, int mode) {
struct args_t args = {}; struct args_t args = {};
args.filename = filename; args.filename = filename;
...@@ -305,6 +305,8 @@ int kprobe__sys_open(struct pt_regs *ctx, const char *filename, ...@@ -305,6 +305,8 @@ int kprobe__sys_open(struct pt_regs *ctx, const char *filename,
return 0; return 0;
}; };
""") """)
b.attach_kprobe(event=b.get_syscall_fnname("open"),
fn_name="do_sys_open")
def test_task_switch(self): def test_task_switch(self):
b = BPF(text=""" b = BPF(text="""
...@@ -599,7 +601,7 @@ void do_trace(struct pt_regs *ctx) { ...@@ -599,7 +601,7 @@ void do_trace(struct pt_regs *ctx) {
c_val = ct.c_ulong(1) c_val = ct.c_ulong(1)
b["dummy"][ct.c_ulong(0)] = c_val b["dummy"][ct.c_ulong(0)] = c_val
b["dummy"][ct.c_ulong(1)] = c_val b["dummy"][ct.c_ulong(1)] = c_val
b.attach_kprobe(event="sys_sync", fn_name="do_trace") b.attach_kprobe(event=b.get_syscall_fnname("sync"), fn_name="do_trace")
libc = ct.CDLL("libc.so.6") libc = ct.CDLL("libc.so.6")
libc.sync() libc.sync()
self.assertEqual(1, b["dummy"][ct.c_ulong(0)].value) self.assertEqual(1, b["dummy"][ct.c_ulong(0)].value)
......
...@@ -33,7 +33,8 @@ class TestLru(unittest.TestCase): ...@@ -33,7 +33,8 @@ class TestLru(unittest.TestCase):
""" """
b = BPF(text=test_prog1) b = BPF(text=test_prog1)
stats_map = b.get_table("stats") stats_map = b.get_table("stats")
b.attach_kprobe(event="sys_clone", fn_name="hello_world") event_name = b.get_syscall_fnname("clone")
b.attach_kprobe(event=event_name, fn_name="hello_world")
ini = stats_map.Leaf() ini = stats_map.Leaf()
for i in range(0, multiprocessing.cpu_count()): for i in range(0, multiprocessing.cpu_count()):
ini[i] = 0 ini[i] = 0
...@@ -53,7 +54,7 @@ class TestLru(unittest.TestCase): ...@@ -53,7 +54,7 @@ class TestLru(unittest.TestCase):
max = stats_map.max(stats_map.Key(0)) max = stats_map.max(stats_map.Key(0))
self.assertGreater(sum.value, 0L) self.assertGreater(sum.value, 0L)
self.assertGreater(max.value, 0L) self.assertGreater(max.value, 0L)
b.detach_kprobe("sys_clone") b.detach_kprobe(event_name)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
...@@ -36,7 +36,8 @@ class TestPercpu(unittest.TestCase): ...@@ -36,7 +36,8 @@ class TestPercpu(unittest.TestCase):
""" """
bpf_code = BPF(text=test_prog1) bpf_code = BPF(text=test_prog1)
stats_map = bpf_code.get_table("stats") stats_map = bpf_code.get_table("stats")
bpf_code.attach_kprobe(event="sys_clone", fn_name="hello_world") event_name = bpf_code.get_syscall_fnname("clone")
bpf_code.attach_kprobe(event=event_name, fn_name="hello_world")
ini = stats_map.Leaf() ini = stats_map.Leaf()
for i in range(0, multiprocessing.cpu_count()): for i in range(0, multiprocessing.cpu_count()):
ini[i] = 0 ini[i] = 0
...@@ -50,7 +51,7 @@ class TestPercpu(unittest.TestCase): ...@@ -50,7 +51,7 @@ class TestPercpu(unittest.TestCase):
max = stats_map.max(stats_map.Key(0)) max = stats_map.max(stats_map.Key(0))
self.assertGreater(sum.value, int(0)) self.assertGreater(sum.value, int(0))
self.assertGreater(max.value, int(0)) self.assertGreater(max.value, int(0))
bpf_code.detach_kprobe("sys_clone") bpf_code.detach_kprobe(event_name)
def test_u32(self): def test_u32(self):
test_prog1 = """ test_prog1 = """
...@@ -65,7 +66,8 @@ class TestPercpu(unittest.TestCase): ...@@ -65,7 +66,8 @@ class TestPercpu(unittest.TestCase):
""" """
bpf_code = BPF(text=test_prog1) bpf_code = BPF(text=test_prog1)
stats_map = bpf_code.get_table("stats") stats_map = bpf_code.get_table("stats")
bpf_code.attach_kprobe(event="sys_clone", fn_name="hello_world") event_name = bpf_code.get_syscall_fnname("clone")
bpf_code.attach_kprobe(event=event_name, fn_name="hello_world")
ini = stats_map.Leaf() ini = stats_map.Leaf()
for i in range(0, multiprocessing.cpu_count()): for i in range(0, multiprocessing.cpu_count()):
ini[i] = 0 ini[i] = 0
...@@ -79,7 +81,7 @@ class TestPercpu(unittest.TestCase): ...@@ -79,7 +81,7 @@ class TestPercpu(unittest.TestCase):
max = stats_map.max(stats_map.Key(0)) max = stats_map.max(stats_map.Key(0))
self.assertGreater(sum.value, int(0)) self.assertGreater(sum.value, int(0))
self.assertGreater(max.value, int(0)) self.assertGreater(max.value, int(0))
bpf_code.detach_kprobe("sys_clone") bpf_code.detach_kprobe(event_name)
def test_struct_custom_func(self): def test_struct_custom_func(self):
test_prog2 = """ test_prog2 = """
...@@ -100,7 +102,8 @@ class TestPercpu(unittest.TestCase): ...@@ -100,7 +102,8 @@ class TestPercpu(unittest.TestCase):
bpf_code = BPF(text=test_prog2) bpf_code = BPF(text=test_prog2)
stats_map = bpf_code.get_table("stats", stats_map = bpf_code.get_table("stats",
reducer=lambda x,y: stats_map.sLeaf(x.c1+y.c1)) reducer=lambda x,y: stats_map.sLeaf(x.c1+y.c1))
bpf_code.attach_kprobe(event="sys_clone", fn_name="hello_world") event_name = bpf_code.get_syscall_fnname("clone")
bpf_code.attach_kprobe(event=event_name, fn_name="hello_world")
ini = stats_map.Leaf() ini = stats_map.Leaf()
for i in ini: for i in ini:
i = stats_map.sLeaf(0,0) i = stats_map.sLeaf(0,0)
...@@ -110,7 +113,7 @@ class TestPercpu(unittest.TestCase): ...@@ -110,7 +113,7 @@ class TestPercpu(unittest.TestCase):
self.assertEqual(len(stats_map),1) self.assertEqual(len(stats_map),1)
k = stats_map[ stats_map.Key(0) ] k = stats_map[ stats_map.Key(0) ]
self.assertGreater(k.c1, int(0)) self.assertGreater(k.c1, int(0))
bpf_code.detach_kprobe("sys_clone") bpf_code.detach_kprobe(event_name)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -15,7 +15,7 @@ class TestPerfCounter(unittest.TestCase): ...@@ -15,7 +15,7 @@ class TestPerfCounter(unittest.TestCase):
BPF_PERF_ARRAY(cnt1, NUM_CPUS); BPF_PERF_ARRAY(cnt1, NUM_CPUS);
BPF_ARRAY(prev, u64, NUM_CPUS); BPF_ARRAY(prev, u64, NUM_CPUS);
BPF_HISTOGRAM(dist); BPF_HISTOGRAM(dist);
int kprobe__sys_getuid(void *ctx) { int do_sys_getuid(void *ctx) {
u32 cpu = bpf_get_smp_processor_id(); u32 cpu = bpf_get_smp_processor_id();
u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER); u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER);
...@@ -25,7 +25,7 @@ int kprobe__sys_getuid(void *ctx) { ...@@ -25,7 +25,7 @@ int kprobe__sys_getuid(void *ctx) {
prev.update(&cpu, &val); prev.update(&cpu, &val);
return 0; return 0;
} }
int kretprobe__sys_getuid(void *ctx) { int do_ret_sys_getuid(void *ctx) {
u32 cpu = bpf_get_smp_processor_id(); u32 cpu = bpf_get_smp_processor_id();
u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER); u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER);
...@@ -40,6 +40,9 @@ int kretprobe__sys_getuid(void *ctx) { ...@@ -40,6 +40,9 @@ int kretprobe__sys_getuid(void *ctx) {
""" """
b = bcc.BPF(text=text, debug=0, b = bcc.BPF(text=text, debug=0,
cflags=["-DNUM_CPUS=%d" % multiprocessing.cpu_count()]) cflags=["-DNUM_CPUS=%d" % multiprocessing.cpu_count()])
event_name = b.get_syscall_fnname("getuid")
b.attach_kprobe(event=event_name, fn_name="do_sys_getuid")
b.attach_kretprobe(event=event_name, fn_name="do_ret_sys_getuid")
cnt1 = b["cnt1"] cnt1 = b["cnt1"]
try: try:
cnt1.open_perf_event(bcc.PerfType.HARDWARE, bcc.PerfHWConfig.CPU_CYCLES) cnt1.open_perf_event(bcc.PerfType.HARDWARE, bcc.PerfHWConfig.CPU_CYCLES)
......
...@@ -27,8 +27,8 @@ class TestKprobe(TestCase): ...@@ -27,8 +27,8 @@ class TestKprobe(TestCase):
def setUp(self): def setUp(self):
b = BPF(arg1, arg2, debug=0) b = BPF(arg1, arg2, debug=0)
self.stats = b.get_table("stats", Key, Leaf) self.stats = b.get_table("stats", Key, Leaf)
b.attach_kprobe(event="sys_write", fn_name="sys_wr") b.attach_kprobe(event=b.get_syscall_fnname("write"), fn_name="sys_wr")
b.attach_kprobe(event="sys_read", fn_name="sys_rd") b.attach_kprobe(event=b.get_syscall_fnname("read"), fn_name="sys_rd")
b.attach_kprobe(event="htab_map_get_next_key", fn_name="sys_rd") b.attach_kprobe(event="htab_map_get_next_key", fn_name="sys_rd")
def test_trace1(self): def test_trace1(self):
......
...@@ -22,8 +22,10 @@ class TestKprobeRgx(TestCase): ...@@ -22,8 +22,10 @@ class TestKprobeRgx(TestCase):
return 0; return 0;
} }
""") """)
self.b.attach_kprobe(event_re="^SyS_bp.*", fn_name="hello") self.b.attach_kprobe(event_re="^" + self.b.get_syscall_prefix() + "bp.*",
self.b.attach_kretprobe(event_re="^SyS_bp.*", fn_name="goodbye") fn_name="hello")
self.b.attach_kretprobe(event_re="^" + self.b.get_syscall_prefix() + "bp.*",
fn_name="goodbye")
def test_send1(self): def test_send1(self):
k1 = self.b["stats"].Key(1) k1 = self.b["stats"].Key(1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment