Skip to content

Commit fc4c3df

Browse files
alan-maguireKernel Patches Daemon
authored andcommitted
libbpf: add support for BTF location attachment
Add support for BTF-based location attachment via multiple kprobes attaching to each instance of an inline site. Note this is not kprobe multi attach since that requires fprobe on entry and sites are within functions. Implementation similar to USDT manager where we use BTF to create a location manager and populate expected arg values with metadata based upon BTF_KIND_LOC_PARAM/LOC_PROTOs. Add new auto-attach SEC("kloc/module:name") where the module is vmlinux/kernel module and the name is the name of the associated location; all sites associated with that name will be attached via kprobes for tracing. Signed-off-by: Alan Maguire <[email protected]>
1 parent 23eafe7 commit fc4c3df

File tree

8 files changed

+1062
-3
lines changed

8 files changed

+1062
-3
lines changed

tools/lib/bpf/Build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_utils.o \
22
netlink.o bpf_prog_linfo.o libbpf_probes.o hashmap.o \
33
btf_dump.o ringbuf.o strset.o linker.o gen_loader.o relo_core.o \
4-
usdt.o zip.o elf.o features.o btf_iter.o btf_relocate.o
4+
usdt.o zip.o elf.o features.o btf_iter.o btf_relocate.o loc.o

tools/lib/bpf/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ install_lib: all_cmd
234234

235235
SRC_HDRS := bpf.h libbpf.h btf.h libbpf_common.h libbpf_legacy.h \
236236
bpf_helpers.h bpf_tracing.h bpf_endian.h bpf_core_read.h \
237-
skel_internal.h libbpf_version.h usdt.bpf.h
237+
skel_internal.h libbpf_version.h usdt.bpf.h loc.bpf.h
238238
GEN_HDRS := $(BPF_GENERATED)
239239

240240
INSTALL_PFX := $(DESTDIR)$(prefix)/include/bpf

tools/lib/bpf/libbpf.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ enum sec_def_flags {
407407
SEC_XDP_FRAGS = 16,
408408
/* Setup proper attach type for usdt probes. */
409409
SEC_USDT = 32,
410+
SEC_LOC = 33,
410411
};
411412

412413
struct bpf_sec_def {
@@ -671,6 +672,8 @@ struct elf_state {
671672

672673
struct usdt_manager;
673674

675+
struct loc_manager;
676+
674677
enum bpf_object_state {
675678
OBJ_OPEN,
676679
OBJ_PREPARED,
@@ -733,6 +736,7 @@ struct bpf_object {
733736
size_t fd_array_cnt;
734737

735738
struct usdt_manager *usdt_man;
739+
struct loc_manager *loc_man;
736740

737741
int arena_map_idx;
738742
void *arena_data;
@@ -9190,6 +9194,8 @@ void bpf_object__close(struct bpf_object *obj)
91909194

91919195
usdt_manager_free(obj->usdt_man);
91929196
obj->usdt_man = NULL;
9197+
loc_manager_free(obj->loc_man);
9198+
obj->loc_man = NULL;
91939199

91949200
bpf_gen__free(obj->gen_loader);
91959201
bpf_object__elf_finish(obj);
@@ -9561,6 +9567,7 @@ static int attach_kprobe_session(const struct bpf_program *prog, long cookie, st
95619567
static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
95629568
static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
95639569
static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);
9570+
static int attach_kloc(const struct bpf_program *prog, long cookie, struct bpf_link **link);
95649571

95659572
static const struct bpf_sec_def section_defs[] = {
95669573
SEC_DEF("socket", SOCKET_FILTER, 0, SEC_NONE),
@@ -9666,6 +9673,7 @@ static const struct bpf_sec_def section_defs[] = {
96669673
SEC_DEF("struct_ops.s+", STRUCT_OPS, 0, SEC_SLEEPABLE),
96679674
SEC_DEF("sk_lookup", SK_LOOKUP, BPF_SK_LOOKUP, SEC_ATTACHABLE),
96689675
SEC_DEF("netfilter", NETFILTER, BPF_NETFILTER, SEC_NONE),
9676+
SEC_DEF("kloc+", KPROBE, 0, SEC_NONE, attach_kloc),
96699677
};
96709678

96719679
int libbpf_register_prog_handler(const char *sec,
@@ -11155,7 +11163,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
1115511163
attr.size = attr_sz;
1115611164
attr.type = type;
1115711165
attr.config |= (__u64)ref_ctr_off << PERF_UPROBE_REF_CTR_OFFSET_SHIFT;
11158-
attr.config1 = ptr_to_u64(name); /* kprobe_func or uprobe_path */
11166+
attr.config1 = name ? ptr_to_u64(name) : 0; /* kprobe_func or uprobe_path */
1115911167
attr.config2 = offset; /* kprobe_addr or probe_offset */
1116011168

1116111169
/* pid filter is meaningful only for uprobes */
@@ -12601,6 +12609,72 @@ static int attach_usdt(const struct bpf_program *prog, long cookie, struct bpf_l
1260112609
return err;
1260212610
}
1260312611

12612+
struct bpf_link *bpf_program__attach_kloc(const struct bpf_program *prog,
12613+
const char *module, const char *name,
12614+
const struct bpf_kloc_opts *opts)
12615+
{
12616+
struct bpf_object *obj = prog->obj;
12617+
struct bpf_link *link;
12618+
__u64 loc_cookie;
12619+
int err;
12620+
12621+
if (!OPTS_VALID(opts, bpf_kloc_opts))
12622+
return libbpf_err_ptr(-EINVAL);
12623+
12624+
if (bpf_program__fd(prog) < 0) {
12625+
pr_warn("prog '%s': can't attach BPF program without FD (was it loaded?)\n",
12626+
prog->name);
12627+
return libbpf_err_ptr(-EINVAL);
12628+
}
12629+
if (!module || !name)
12630+
return libbpf_err_ptr(-EINVAL);
12631+
12632+
/* loc manager is instantiated lazily on first loc attach. It will
12633+
* be destroyed together with BPF object in bpf_object__close().
12634+
*/
12635+
if (IS_ERR(obj->loc_man))
12636+
return libbpf_ptr(obj->loc_man);
12637+
if (!obj->loc_man) {
12638+
obj->loc_man = loc_manager_new(obj);
12639+
if (IS_ERR(obj->loc_man))
12640+
return libbpf_ptr(obj->loc_man);
12641+
}
12642+
12643+
loc_cookie = OPTS_GET(opts, loc_cookie, 0);
12644+
link = loc_manager_attach_kloc(obj->loc_man, prog, module, name, loc_cookie);
12645+
err = libbpf_get_error(link);
12646+
if (err)
12647+
return libbpf_err_ptr(err);
12648+
return link;
12649+
}
12650+
12651+
static int attach_kloc(const struct bpf_program *prog, long cookie, struct bpf_link **link)
12652+
{
12653+
char *module = NULL, *name = NULL;
12654+
const char *sec_name;
12655+
int n, err;
12656+
12657+
sec_name = bpf_program__section_name(prog);
12658+
if (strcmp(sec_name, "kloc") == 0) {
12659+
/* no auto-attach for just SEC("kloc") */
12660+
*link = NULL;
12661+
return 0;
12662+
}
12663+
12664+
n = sscanf(sec_name, "kloc/%m[^:]:%m[^:]", &module, &name);
12665+
if (n != 2) {
12666+
pr_warn("invalid section '%s', expected SEC(\"kloc/<module>:<name>\")\n",
12667+
sec_name);
12668+
err = -EINVAL;
12669+
} else {
12670+
*link = bpf_program__attach_kloc(prog, module, name, NULL);
12671+
err = libbpf_get_error(*link);
12672+
}
12673+
free(module);
12674+
free(name);
12675+
return err;
12676+
}
12677+
1260412678
static int determine_tracepoint_id(const char *tp_category,
1260512679
const char *tp_name)
1260612680
{

tools/lib/bpf/libbpf.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,33 @@ bpf_program__attach_usdt(const struct bpf_program *prog,
799799
const char *usdt_provider, const char *usdt_name,
800800
const struct bpf_usdt_opts *opts);
801801

802+
struct bpf_kloc_opts {
803+
/* size of this struct, for forward/backward compatibility */
804+
size_t sz;
805+
/* custom user-provided value fetchable through loc_cookie() */
806+
__u64 loc_cookie;
807+
size_t:0;
808+
};
809+
#define bpf_kloc_opts__last_field loc_cookie
810+
811+
/**
812+
* @brief **bpf_program__attach_kloc()** attaches to the location
813+
* named *name* in *module* (which can be "vmlinux" or a module name).
814+
* Attaches to all locations associated with *name*.
815+
*
816+
* @param prog BPF program to attach
817+
* @param module name
818+
* @param name Location name
819+
* @param opts Options for altering program attachment
820+
* @return Reference to the newly created BPF link: or NULL is returned on error
821+
*
822+
* error code is stored in errno
823+
*/
824+
LIBBPF_API struct bpf_link *
825+
bpf_program__attach_kloc(const struct bpf_program *prog,
826+
const char *module, const char *name,
827+
const struct bpf_kloc_opts *opts);
828+
802829
struct bpf_tracepoint_opts {
803830
/* size of this struct, for forward/backward compatibility */
804831
size_t sz;

tools/lib/bpf/libbpf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,4 +457,5 @@ LIBBPF_1.7.0 {
457457
btf__add_locsec;
458458
btf__add_locsec_loc;
459459
btf__load_btf_extra;
460+
bpf_program__attach_kloc;
460461
} LIBBPF_1.6.0;

tools/lib/bpf/libbpf_internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,13 @@ struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man,
719719
const char *usdt_provider, const char *usdt_name,
720720
__u64 usdt_cookie);
721721

722+
struct loc_manager *loc_manager_new(struct bpf_object *obj);
723+
void loc_manager_free(struct loc_manager *man);
724+
struct bpf_link *loc_manager_attach_kloc(struct loc_manager *man,
725+
const struct bpf_program *prog,
726+
const char *loc_mod, const char *loc_name,
727+
__u64 loc_cookie);
728+
722729
static inline bool is_pow_of_2(size_t x)
723730
{
724731
return x && (x & (x - 1)) == 0;

0 commit comments

Comments
 (0)