From: Xu Kuohai Collect SDT probe BTF IDs from BTF decl tags matching name pattern "bpf_sdt::". The IDs are ultimately stored in each probe entry of the SDT map. Signed-off-by: Xu Kuohai --- include/uapi/linux/bpf.h | 1 + kernel/bpf/bpf_insn_array.c | 1 + tools/include/uapi/linux/bpf.h | 1 + tools/lib/bpf/libbpf.c | 55 ++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 6a03e3f0506e..773a7def0fbd 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -7739,6 +7739,7 @@ struct bpf_insn_array_value { __u32 orig_off; __u32 xlated_off; __u32 jitted_off; + __u32 btf_id; /* BTF FUNC_PROTO type ID (0 if none) */ __u8 nargs; /* argument count (0..5) */ __u8 arg_reg[5]; /* BPF register for each argument */ __u8 pad[2]; diff --git a/kernel/bpf/bpf_insn_array.c b/kernel/bpf/bpf_insn_array.c index f43777c5cd07..aca8676ab563 100644 --- a/kernel/bpf/bpf_insn_array.c +++ b/kernel/bpf/bpf_insn_array.c @@ -103,6 +103,7 @@ static long insn_array_update_elem(struct bpf_map *map, void *key, void *value, insn_array->values[index].orig_off = val.orig_off; if (insn_array->subtype == BPF_INSN_ARRAY_SUBTYPE_SDT) { + insn_array->values[index].btf_id = val.btf_id; insn_array->values[index].nargs = val.nargs; memcpy(insn_array->values[index].arg_reg, val.arg_reg, sizeof(val.arg_reg)); } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 6a03e3f0506e..773a7def0fbd 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -7739,6 +7739,7 @@ struct bpf_insn_array_value { __u32 orig_off; __u32 xlated_off; __u32 jitted_off; + __u32 btf_id; /* BTF FUNC_PROTO type ID (0 if none) */ __u8 nargs; /* argument count (0..5) */ __u8 arg_reg[5]; /* BPF register for each argument */ __u8 pad[2]; diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 3f8b12a1eb8b..badac128e8ad 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -715,6 +715,7 @@ struct sdt_entry { __u64 insn_idx; /* insn index of probe site within its ELF section */ __u8 nargs; /* how many arguments */ __u8 arg_reg[5]; /* which register the argument locates in */ + __u32 btf_id; /* BTF FUNC_PROTO type ID from decl tag */ }; struct bpf_object { @@ -6692,6 +6693,57 @@ static int create_jt_map(struct bpf_object *obj, struct bpf_program *prog, struc return err; } +static void sdt_collect_btf_ids(struct bpf_object *obj) +{ + int n = btf__type_cnt(obj->btf); + const struct btf_type *t; + int i; + + for (i = 1; i < n; i++) { + const char *tag, *colon; + size_t name_len; + __u32 func_proto_id; + int j; + + t = btf_type_by_id(obj->btf, i); + if (!btf_is_decl_tag(t) || btf_decl_tag(t)->component_idx != -1) + continue; + + tag = btf__str_by_offset(obj->btf, t->name_off); + if (strncmp(tag, "bpf_sdt:", 8) != 0) + continue; + + /* tag format: "bpf_sdt::"; has no colons */ + colon = strchr(tag + 8, ':'); + if (!colon) + continue; + name_len = colon - tag - 8; + + /* type chain: DECL_TAG -> VAR -> (CONST) -> PTR -> FUNC_PROTO */ + t = btf_type_by_id(obj->btf, t->type); + if (!btf_is_var(t)) + continue; + t = btf_type_by_id(obj->btf, t->type); + if (btf_kind(t) == BTF_KIND_CONST) + t = btf_type_by_id(obj->btf, t->type); + if (!btf_is_ptr(t)) + continue; + func_proto_id = t->type; + t = btf_type_by_id(obj->btf, func_proto_id); + if (!btf_is_func_proto(t)) + continue; + + /* match by name (tag format: "bpf_sdt::") */ + for (j = 0; j < obj->sdt_entry_cnt; j++) { + struct sdt_entry *e = &obj->sdt_entries[j]; + + if (!e->btf_id && strlen(e->name) == name_len && + strncmp(tag + 8, e->name, name_len) == 0) + e->btf_id = func_proto_id; + } + } +} + static int bpf_object__resolve_sdt_progs(struct bpf_object *obj) { int i, j; @@ -6749,6 +6801,8 @@ static int bpf_object__create_sdt_maps(struct bpf_object *obj) if (err) return err; + sdt_collect_btf_ids(obj); + prog_sdt = calloc(obj->nr_programs, sizeof(*prog_sdt)); if (!prog_sdt) return -ENOMEM; @@ -6785,6 +6839,7 @@ static int bpf_object__create_sdt_maps(struct bpf_object *obj) key = prog_sdt[e->prog_idx].next_key++; memset(&val, 0, sizeof(val)); + val.btf_id = e->btf_id; val.nargs = e->nargs; val.orig_off = e->insn_idx - prog->sec_insn_off; memcpy(val.arg_reg, e->arg_reg, sizeof(val.arg_reg)); -- 2.47.3