mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	libbpf: Allow specification of "kprobe/function+offset"
kprobes can be placed on most instructions in a function, not
just entry, and ftrace and bpftrace support the function+offset
notification for probe placement.  Adding parsing of func_name
into func+offset to bpf_program__attach_kprobe() allows the
user to specify
SEC("kprobe/bpf_fentry_test5+0x6")
...for example, and the offset can be passed to perf_event_open_probe()
to support kprobe attachment.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210714094400.396467-8-jolsa@kernel.org
			
			
This commit is contained in:
		
							parent
							
								
									ac0ed48829
								
							
						
					
					
						commit
						a2488b5f48
					
				
					 1 changed files with 22 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -10348,6 +10348,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
 | 
			
		|||
 | 
			
		||||
struct bpf_program_attach_kprobe_opts {
 | 
			
		||||
	bool retprobe;
 | 
			
		||||
	unsigned long offset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct bpf_link*
 | 
			
		||||
| 
						 | 
				
			
			@ -10360,7 +10361,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog,
 | 
			
		|||
	int pfd, err;
 | 
			
		||||
 | 
			
		||||
	pfd = perf_event_open_probe(false /* uprobe */, opts->retprobe, func_name,
 | 
			
		||||
				    0 /* offset */, -1 /* pid */);
 | 
			
		||||
				    opts->offset, -1 /* pid */);
 | 
			
		||||
	if (pfd < 0) {
 | 
			
		||||
		pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n",
 | 
			
		||||
			prog->name, opts->retprobe ? "kretprobe" : "kprobe", func_name,
 | 
			
		||||
| 
						 | 
				
			
			@ -10394,12 +10395,31 @@ static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec,
 | 
			
		|||
				      struct bpf_program *prog)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_program_attach_kprobe_opts opts;
 | 
			
		||||
	unsigned long offset = 0;
 | 
			
		||||
	struct bpf_link *link;
 | 
			
		||||
	const char *func_name;
 | 
			
		||||
	char *func;
 | 
			
		||||
	int n, err;
 | 
			
		||||
 | 
			
		||||
	func_name = prog->sec_name + sec->len;
 | 
			
		||||
	opts.retprobe = strcmp(sec->sec, "kretprobe/") == 0;
 | 
			
		||||
 | 
			
		||||
	return bpf_program__attach_kprobe_opts(prog, func_name, &opts);
 | 
			
		||||
	n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%lx", &func, &offset);
 | 
			
		||||
	if (n < 1) {
 | 
			
		||||
		err = -EINVAL;
 | 
			
		||||
		pr_warn("kprobe name is invalid: %s\n", func_name);
 | 
			
		||||
		return libbpf_err_ptr(err);
 | 
			
		||||
	}
 | 
			
		||||
	if (opts.retprobe && offset != 0) {
 | 
			
		||||
		err = -EINVAL;
 | 
			
		||||
		pr_warn("kretprobes do not support offset specification\n");
 | 
			
		||||
		return libbpf_err_ptr(err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	opts.offset = offset;
 | 
			
		||||
	link = bpf_program__attach_kprobe_opts(prog, func, &opts);
 | 
			
		||||
	free(func);
 | 
			
		||||
	return link;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue