On 2022/3/30 11:10 AM, Hengqi Chen wrote: > On 2022/3/25 1:29 PM, Andrii Nakryiko wrote: >> Add BPF-side implementation of libbpf-provided USDT support. This >> consists of single header library, usdt.bpf.h, which is meant to be used >> from user's BPF-side source code. This header is added to the list of >> installed libbpf header, along bpf_helpers.h and others. >> >> BPF-side implementation consists of two BPF maps: >> - spec map, which contains "a USDT spec" which encodes information ... >> +} >> + >> +/* Fetch USDT argument *arg* (zero-indexed) and put its value into *res. >> + * Returns 0 on success; negative error, otherwise. >> + * On error *res is guaranteed to be set to zero. >> + */ >> +__hidden __weak >> +int bpf_usdt_arg(struct pt_regs *ctx, int arg, long *res) >> +{ >> + struct __bpf_usdt_spec *spec; >> + struct __bpf_usdt_arg_spec *arg_spec; >> + unsigned long val; >> + int err, spec_id; >> + >> + *res = 0; >> + >> + spec_id = __bpf_usdt_spec_id(ctx); >> + if (spec_id < 0) >> + return -ESRCH; >> + >> + spec = bpf_map_lookup_elem(&__bpf_usdt_specs, &spec_id); >> + if (!spec) >> + return -ESRCH; >> + >> + if (arg >= spec->arg_cnt) >> + return -ENOENT; >> + >> + arg_spec = &spec->args[arg]; >> + switch (arg_spec->arg_type) { >> + case BPF_USDT_ARG_CONST: >> + val = arg_spec->val_off; >> + break; >> + case BPF_USDT_ARG_REG: >> + err = bpf_probe_read_kernel(&val, sizeof(val), (void *)ctx + arg_spec->reg_off); >> + if (err) >> + return err; >> + break; >> + case BPF_USDT_ARG_REG_DEREF: >> + err = bpf_probe_read_kernel(&val, sizeof(val), (void *)ctx + arg_spec->reg_off); >> + if (err) >> + return err; >> + err = bpf_probe_read_user(&val, sizeof(val), (void *)val + arg_spec->val_off); >> + if (err) >> + return err; Can you elaborate more on these two probe read call ? I replace bpf_probe_read_kernel with bpf_probe_read_user, it also works. Thanks. >> + break; >> + default: >> + return -EINVAL; >> + } >> + >> + val <<= arg_spec->arg_bitshift; >> + if (arg_spec->arg_signed) >> + val = ((long)val) >> arg_spec->arg_bitshift; >> + * BPF_USDT serves the same purpose for USDT handlers as BPF_PROG for >> + * tp_btf/fentry/fexit BPF programs and BPF_KPROBE for kprobes. >> + * Original struct pt_regs * context is preserved as 'ctx' argument. >> + */ >> +#define BPF_USDT(name, args...) \ >> +name(struct pt_regs *ctx); \ >> +static __attribute__((always_inline)) typeof(name(0)) \ >> +____##name(struct pt_regs *ctx, ##args); \ >> +typeof(name(0)) name(struct pt_regs *ctx) \ >> +{ \ >> + _Pragma("GCC diagnostic push") \ >> + _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \ >> + return ____##name(___bpf_usdt_args(args)); \ >> + _Pragma("GCC diagnostic pop") \ >> +} \ >> +static __attribute__((always_inline)) typeof(name(0)) \ >> +____##name(struct pt_regs *ctx, ##args) >> + >> +#endif /* __USDT_BPF_H__ */