From 83b49ad6cd9efba88f922c2e7b892fc275208514 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Tue, 24 Apr 2018 10:15:24 -0700 Subject: [PATCH] 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_ and SyS_ 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: Yonghong Song --- examples/hello_world.py | 1 + examples/tracing/hello_fields.py | 2 +- examples/tracing/hello_perf_output.py | 2 +- examples/tracing/sync_timing.py | 2 +- examples/tracing/trace_fields.py | 2 +- examples/tracing/trace_perf_output.py | 6 ++++-- src/python/bcc/__init__.py | 13 +++++++++++++ tests/python/test_array.py | 8 ++++++-- tests/python/test_clang.py | 6 ++++-- tests/python/test_lru.py | 5 +++-- tests/python/test_percpu.py | 15 +++++++++------ tests/python/test_perf_event.py | 7 +++++-- tests/python/test_trace1.py | 4 ++-- tests/python/test_trace4.py | 6 ++++-- 14 files changed, 55 insertions(+), 24 deletions(-) diff --git a/examples/hello_world.py b/examples/hello_world.py index c23ed1cf1dc6..49c55353bea1 100755 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -8,4 +8,5 @@ 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() diff --git a/examples/tracing/hello_fields.py b/examples/tracing/hello_fields.py index 1525f0409a90..bad1a22982ba 100755 --- a/examples/tracing/hello_fields.py +++ b/examples/tracing/hello_fields.py @@ -14,7 +14,7 @@ # load BPF program 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 print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE")) diff --git a/examples/tracing/hello_perf_output.py b/examples/tracing/hello_perf_output.py index f88028014594..eb1e9979be9c 100755 --- a/examples/tracing/hello_perf_output.py +++ b/examples/tracing/hello_perf_output.py @@ -32,7 +32,7 @@ # load BPF program 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 TASK_COMM_LEN = 16 # linux/sched.h diff --git a/examples/tracing/sync_timing.py b/examples/tracing/sync_timing.py index f68031d1ccb0..675ad14c8923 100755 --- a/examples/tracing/sync_timing.py +++ b/examples/tracing/sync_timing.py @@ -38,7 +38,7 @@ } """) -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") # format output diff --git a/examples/tracing/trace_fields.py b/examples/tracing/trace_fields.py index 173f21f4c1d2..0baf03dcf574 100755 --- a/examples/tracing/trace_fields.py +++ b/examples/tracing/trace_fields.py @@ -15,6 +15,6 @@ } """ 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" b.trace_print(fmt="{1} {5}") diff --git a/examples/tracing/trace_perf_output.py b/examples/tracing/trace_perf_output.py index 5ce87d946304..865a4593520d 100755 --- a/examples/tracing/trace_perf_output.py +++ b/examples/tracing/trace_perf_output.py @@ -25,7 +25,7 @@ def cb(cpu, data, size): prog = """ BPF_PERF_OUTPUT(events); BPF_ARRAY(counters, u64, 10); -int kprobe__sys_clone(void *ctx) { +int do_sys_clone(void *ctx) { struct { u64 ts; u64 magic; @@ -40,6 +40,8 @@ def cb(cpu, data, size): } """ 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) @atexit.register @@ -48,7 +50,7 @@ def print_counter(): global b 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.") while 1: b.perf_buffer_poll() diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py index 27cbb45772cc..a1552e708c41 100644 --- a/src/python/bcc/__init__.py +++ b/src/python/bcc/__init__.py @@ -522,6 +522,19 @@ def _del_uprobe_fd(self, name): global _num_open_probes del self.uprobe_fds[name] _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""): event = _assert_is_bytes(event) diff --git a/tests/python/test_array.py b/tests/python/test_array.py index b76831a4a73b..eb8712b569c1 100755 --- a/tests/python/test_array.py +++ b/tests/python/test_array.py @@ -54,7 +54,7 @@ def lost_cb(lost): text = """ BPF_PERF_OUTPUT(events); -int kprobe__sys_nanosleep(void *ctx) { +int do_sys_nanosleep(void *ctx) { struct { u64 ts; } data = {bpf_ktime_get_ns()}; @@ -63,6 +63,8 @@ def lost_cb(lost): } """ 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) time.sleep(0.1) b.perf_buffer_poll() @@ -85,7 +87,7 @@ def lost_cb(lost): text = """ BPF_PERF_OUTPUT(events); -int kprobe__sys_nanosleep(void *ctx) { +int do_sys_nanosleep(void *ctx) { struct { u64 cpu; } data = {bpf_get_smp_processor_id()}; @@ -94,6 +96,8 @@ def lost_cb(lost): } """ 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) online_cpus = get_online_cpus() for cpu in online_cpus: diff --git a/tests/python/test_clang.py b/tests/python/test_clang.py index 1bb2098c3218..6f55df27a311 100755 --- a/tests/python/test_clang.py +++ b/tests/python/test_clang.py @@ -295,7 +295,7 @@ def test_probe_struct_assign(self): int flags; 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) { struct args_t args = {}; args.filename = filename; @@ -305,6 +305,8 @@ def test_probe_struct_assign(self): return 0; }; """) + b.attach_kprobe(event=b.get_syscall_fnname("open"), + fn_name="do_sys_open") def test_task_switch(self): b = BPF(text=""" @@ -599,7 +601,7 @@ def test_map_insert(self): c_val = ct.c_ulong(1) b["dummy"][ct.c_ulong(0)] = 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.sync() self.assertEqual(1, b["dummy"][ct.c_ulong(0)].value) diff --git a/tests/python/test_lru.py b/tests/python/test_lru.py index f900bcb13f3c..fd279c1c3de6 100644 --- a/tests/python/test_lru.py +++ b/tests/python/test_lru.py @@ -33,7 +33,8 @@ def test_lru_percpu_hash(self): """ b = BPF(text=test_prog1) 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() for i in range(0, multiprocessing.cpu_count()): ini[i] = 0 @@ -53,7 +54,7 @@ def test_lru_percpu_hash(self): max = stats_map.max(stats_map.Key(0)) self.assertGreater(sum.value, 0L) self.assertGreater(max.value, 0L) - b.detach_kprobe("sys_clone") + b.detach_kprobe(event_name) if __name__ == "__main__": unittest.main() diff --git a/tests/python/test_percpu.py b/tests/python/test_percpu.py index 5ab36918f2f1..39a3bbc4373d 100755 --- a/tests/python/test_percpu.py +++ b/tests/python/test_percpu.py @@ -36,7 +36,8 @@ def test_u64(self): """ bpf_code = BPF(text=test_prog1) 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() for i in range(0, multiprocessing.cpu_count()): ini[i] = 0 @@ -50,7 +51,7 @@ def test_u64(self): max = stats_map.max(stats_map.Key(0)) self.assertGreater(sum.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): test_prog1 = """ @@ -65,7 +66,8 @@ def test_u32(self): """ bpf_code = BPF(text=test_prog1) 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() for i in range(0, multiprocessing.cpu_count()): ini[i] = 0 @@ -79,7 +81,7 @@ def test_u32(self): max = stats_map.max(stats_map.Key(0)) self.assertGreater(sum.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): test_prog2 = """ @@ -100,7 +102,8 @@ def test_struct_custom_func(self): bpf_code = BPF(text=test_prog2) stats_map = bpf_code.get_table("stats", 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() for i in ini: i = stats_map.sLeaf(0,0) @@ -110,7 +113,7 @@ def test_struct_custom_func(self): self.assertEqual(len(stats_map),1) k = stats_map[ stats_map.Key(0) ] self.assertGreater(k.c1, int(0)) - bpf_code.detach_kprobe("sys_clone") + bpf_code.detach_kprobe(event_name) if __name__ == "__main__": diff --git a/tests/python/test_perf_event.py b/tests/python/test_perf_event.py index a7c8721eb55a..3f78f5b38d91 100755 --- a/tests/python/test_perf_event.py +++ b/tests/python/test_perf_event.py @@ -15,7 +15,7 @@ def test_cycles(self): BPF_PERF_ARRAY(cnt1, NUM_CPUS); BPF_ARRAY(prev, u64, NUM_CPUS); BPF_HISTOGRAM(dist); -int kprobe__sys_getuid(void *ctx) { +int do_sys_getuid(void *ctx) { u32 cpu = bpf_get_smp_processor_id(); u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER); @@ -25,7 +25,7 @@ def test_cycles(self): prev.update(&cpu, &val); return 0; } -int kretprobe__sys_getuid(void *ctx) { +int do_ret_sys_getuid(void *ctx) { u32 cpu = bpf_get_smp_processor_id(); u64 val = cnt1.perf_read(CUR_CPU_IDENTIFIER); @@ -40,6 +40,9 @@ def test_cycles(self): """ b = bcc.BPF(text=text, debug=0, 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"] try: cnt1.open_perf_event(bcc.PerfType.HARDWARE, bcc.PerfHWConfig.CPU_CYCLES) diff --git a/tests/python/test_trace1.py b/tests/python/test_trace1.py index c7256ec23cb3..dc005c5c0c77 100755 --- a/tests/python/test_trace1.py +++ b/tests/python/test_trace1.py @@ -27,8 +27,8 @@ class TestKprobe(TestCase): def setUp(self): b = BPF(arg1, arg2, debug=0) self.stats = b.get_table("stats", Key, Leaf) - b.attach_kprobe(event="sys_write", fn_name="sys_wr") - b.attach_kprobe(event="sys_read", fn_name="sys_rd") + b.attach_kprobe(event=b.get_syscall_fnname("write"), fn_name="sys_wr") + 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") def test_trace1(self): diff --git a/tests/python/test_trace4.py b/tests/python/test_trace4.py index 49e3d23154de..68497b3143d0 100755 --- a/tests/python/test_trace4.py +++ b/tests/python/test_trace4.py @@ -22,8 +22,10 @@ def setUp(self): return 0; } """) - self.b.attach_kprobe(event_re="^SyS_bp.*", fn_name="hello") - self.b.attach_kretprobe(event_re="^SyS_bp.*", fn_name="goodbye") + self.b.attach_kprobe(event_re="^" + self.b.get_syscall_prefix() + "bp.*", + fn_name="hello") + self.b.attach_kretprobe(event_re="^" + self.b.get_syscall_prefix() + "bp.*", + fn_name="goodbye") def test_send1(self): k1 = self.b["stats"].Key(1)