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 @@
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()
......@@ -14,7 +14,7 @@ int hello(void *ctx) {
# 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"))
......
......@@ -32,7 +32,7 @@ int hello(struct pt_regs *ctx) {
# 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
......
......@@ -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")
# format output
......
......@@ -15,6 +15,6 @@ int hello(void *ctx) {
}
"""
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}")
......@@ -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 @@ int kprobe__sys_clone(void *ctx) {
}
"""
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()
......@@ -522,6 +522,19 @@ class BPF(object):
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)
......
......@@ -54,7 +54,7 @@ class TestArray(TestCase):
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 @@ int kprobe__sys_nanosleep(void *ctx) {
}
"""
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 @@ int kprobe__sys_nanosleep(void *ctx) {
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 @@ int kprobe__sys_nanosleep(void *ctx) {
}
"""
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:
......
......@@ -295,7 +295,7 @@ struct args_t {
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 @@ int kprobe__sys_open(struct pt_regs *ctx, const char *filename,
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 @@ void do_trace(struct pt_regs *ctx) {
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)
......
......@@ -33,7 +33,8 @@ class TestLru(unittest.TestCase):
"""
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 @@ class TestLru(unittest.TestCase):
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()
......@@ -36,7 +36,8 @@ class TestPercpu(unittest.TestCase):
"""
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 @@ class TestPercpu(unittest.TestCase):
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 @@ class TestPercpu(unittest.TestCase):
"""
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 @@ class TestPercpu(unittest.TestCase):
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 @@ class TestPercpu(unittest.TestCase):
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 @@ class TestPercpu(unittest.TestCase):
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__":
......
......@@ -15,7 +15,7 @@ class TestPerfCounter(unittest.TestCase):
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 @@ int kprobe__sys_getuid(void *ctx) {
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 @@ int kretprobe__sys_getuid(void *ctx) {
"""
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)
......
......@@ -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):
......
......@@ -22,8 +22,10 @@ class TestKprobeRgx(TestCase):
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)
......
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