Re: Extracting data from tracepoints (and anything else)


Andrii Nakryiko
 

Adding back mailing list.

On Mon, Mar 23, 2020 at 12:33 PM <mayfieldtristan@...> wrote:

Thanks for the reply. All of your suggestions make sense. Because I'm targeting a kernel 4.15 for this specific bit of code, I can't use bpf_probe_read_str().. I think? The way I'm developing is that I cloned the kernel src of kernel 4.15 to a certain depth, and then compiled libbpf. Should I use the standalone libbpf repo instead? I've tried that but have struggled to get samples/bpf/ to compile taking that approach.
bpf_probe_read_str() has been there for a long time, at least 4.12 or
even older.

samples/bpf are part of kernel, so yes, they are using libbpf from
kernel sources. For stand-alone application I'd go with
github.com/libbpf/libbpf


Regardless, I took your advice, and my code now looks like:

struct data_t {
u32 pid;
char program_name[256]; // max comm length is arbitrary
comm is 16 and unlikely to ever change. No need to waste 256 bytes here.

char *file;
};

struct bpf_map_def SEC("maps") events = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
.max_entries = MAX_CPUS,
};



struct sys_enter_openat_args {
u16 common_type;
u8 common_flags;
u8 common_preempt_count;
int common_pid;
int __syscall_nr;
int dfd;
char *filename;
int flags;
__mode_t mode;
};

SEC("tracepoint/syscalls/sys_enter_openat")
int bpf_prog(struct sys_enter_openat_args *ctx) {
struct data_t data;
data has to be initialized here:

struct data_t data = {};

struct sys_enter_openat_args args;

int res = bpf_probe_read(&args, sizeof(args), ctx); // read the ctx into bpf space
if(!res) {
data.file = "couldn't get file";
} else {
data.file = args.filename;
}

data.pid = bpf_get_current_pid_tgid();
bpf_get_current_comm(data.program_name, sizeof(data.program_name));

bpf_perf_event_output(ctx, &events, 0, &data, sizeof(data));
return 0;
}

char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;

---
With a new error code

bpf_load_program() err=13
0: (bf) r6 = r1
1: (bf) r1 = r10
2: (07) r1 += -304
3: (b7) r2 = 32
4: (bf) r3 = r6
5: (85) call bpf_probe_read#4
6: (67) r0 <<= 32
7: (77) r0 >>= 32
8: (55) if r0 != 0x0 goto pc+3
R0=inv0 R6=ctx(id=0,off=0,imm=0) R10=fp0
9: (18) r1 = 0xffff88ac7c953000
11: (05) goto pc+1
13: (7b) *(u64 *)(r10 -8) = r1
14: (85) call bpf_get_current_pid_tgid#14
15: (63) *(u32 *)(r10 -272) = r0
16: (bf) r1 = r10
17: (07) r1 += -268
18: (b7) r2 = 256
19: (85) call bpf_get_current_comm#16
20: (bf) r4 = r10
21: (07) r4 += -272
22: (bf) r1 = r6
23: (18) r2 = 0xffff88ac7c953000
25: (b7) r3 = 0
26: (b7) r5 = 272
27: (85) call bpf_perf_event_output#25
invalid indirect read from stack off -272+260 size 272
The kernel didn't load the BPF program
---

Thanks for the pointer about the libbpf-tools in the BCC repo! I had seen it before but for some reason didn't make any kind of note about it. It's extremely helpful.

I will change the map declaration, just trying to understand getting data from the tracepoint right now.
data is not completely initialized, see above.

Please keep this discussion on mailing list, though, it might benefit
someone else.

Join iovisor-dev@lists.iovisor.org to automatically receive all group messages.