tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
Extension
.c
Size
19187 bytes
Lines
804
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct __arch_relative_insn {
		__u8 op;
		__s32 raddr;
	} __packed *call;
	void *tramp = NULL;

	/* Uprobe gets optimized after first trigger, so let's press twice. */
	trigger();
	trigger();

	/* Make sure bpf program got executed.. */
	ASSERT_EQ(skel->bss->executed, executed, "executed");

	/* .. and check the trampoline is as expected. */
	call = (struct __arch_relative_insn *) addr;
	tramp = (void *) (call + 1) + call->raddr;
	ASSERT_EQ(call->op, 0xe8, "call");
	ASSERT_OK(find_uprobes_trampoline(tramp), "uprobes_trampoline");

	return tramp;
}

static void check_detach(void *addr, void *tramp)
{
	/* [uprobes_trampoline] stays after detach */
	ASSERT_OK(find_uprobes_trampoline(tramp), "uprobes_trampoline");
	ASSERT_OK(memcmp(addr, nop5, 5), "nop5");
}

static void check(struct uprobe_syscall_executed *skel, struct bpf_link *link,
		  trigger_t trigger, void *addr, int executed)
{
	void *tramp;

	tramp = check_attach(skel, trigger, addr, executed);
	bpf_link__destroy(link);
	check_detach(addr, tramp);
}

static void test_uprobe_legacy(void)
{
	struct uprobe_syscall_executed *skel = NULL;
	LIBBPF_OPTS(bpf_uprobe_opts, opts,
		.retprobe = true,
	);
	struct bpf_link *link;
	unsigned long offset;

	offset = get_uprobe_offset(&uprobe_test);
	if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
		goto cleanup;

	/* uprobe */
	skel = uprobe_syscall_executed__open_and_load();
	if (!ASSERT_OK_PTR(skel, "uprobe_syscall_executed__open_and_load"))
		return;

	skel->bss->pid = getpid();

	link = bpf_program__attach_uprobe_opts(skel->progs.test_uprobe,
				0, "/proc/self/exe", offset, NULL);
	if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts"))
		goto cleanup;

	check(skel, link, uprobe_test, uprobe_test, 2);

	/* uretprobe */
	skel->bss->executed = 0;

	link = bpf_program__attach_uprobe_opts(skel->progs.test_uretprobe,
				0, "/proc/self/exe", offset, &opts);
	if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts"))
		goto cleanup;

	check(skel, link, uprobe_test, uprobe_test, 2);

cleanup:
	uprobe_syscall_executed__destroy(skel);
}

static void test_uprobe_multi(void)
{
	struct uprobe_syscall_executed *skel = NULL;
	LIBBPF_OPTS(bpf_uprobe_multi_opts, opts);
	struct bpf_link *link;
	unsigned long offset;

	offset = get_uprobe_offset(&uprobe_test);
	if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
		goto cleanup;

Annotation

Implementation Notes