1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Google */
3 
4 #include <test_progs.h>
5 #include <bpf/libbpf.h>
6 #include <bpf/btf.h>
7 #include "test_ksyms_btf.skel.h"
8 #include "test_ksyms_btf_null_check.skel.h"
9 #include "test_ksyms_weak.skel.h"
10 
11 static int duration;
12 
13 static void test_basic(void)
14 {
15 	__u64 runqueues_addr, bpf_prog_active_addr;
16 	__u32 this_rq_cpu;
17 	int this_bpf_prog_active;
18 	struct test_ksyms_btf *skel = NULL;
19 	struct test_ksyms_btf__data *data;
20 	int err;
21 
22 	err = kallsyms_find("runqueues", &runqueues_addr);
23 	if (CHECK(err == -EINVAL, "kallsyms_fopen", "failed to open: %d\n", errno))
24 		return;
25 	if (CHECK(err == -ENOENT, "ksym_find", "symbol 'runqueues' not found\n"))
26 		return;
27 
28 	err = kallsyms_find("bpf_prog_active", &bpf_prog_active_addr);
29 	if (CHECK(err == -EINVAL, "kallsyms_fopen", "failed to open: %d\n", errno))
30 		return;
31 	if (CHECK(err == -ENOENT, "ksym_find", "symbol 'bpf_prog_active' not found\n"))
32 		return;
33 
34 	skel = test_ksyms_btf__open_and_load();
35 	if (CHECK(!skel, "skel_open", "failed to open and load skeleton\n"))
36 		goto cleanup;
37 
38 	err = test_ksyms_btf__attach(skel);
39 	if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
40 		goto cleanup;
41 
42 	/* trigger tracepoint */
43 	usleep(1);
44 
45 	data = skel->data;
46 	CHECK(data->out__runqueues_addr != runqueues_addr, "runqueues_addr",
47 	      "got %llu, exp %llu\n",
48 	      (unsigned long long)data->out__runqueues_addr,
49 	      (unsigned long long)runqueues_addr);
50 	CHECK(data->out__bpf_prog_active_addr != bpf_prog_active_addr, "bpf_prog_active_addr",
51 	      "got %llu, exp %llu\n",
52 	      (unsigned long long)data->out__bpf_prog_active_addr,
53 	      (unsigned long long)bpf_prog_active_addr);
54 
55 	CHECK(data->out__rq_cpu == -1, "rq_cpu",
56 	      "got %u, exp != -1\n", data->out__rq_cpu);
57 	CHECK(data->out__bpf_prog_active < 0, "bpf_prog_active",
58 	      "got %d, exp >= 0\n", data->out__bpf_prog_active);
59 	CHECK(data->out__cpu_0_rq_cpu != 0, "cpu_rq(0)->cpu",
60 	      "got %u, exp 0\n", data->out__cpu_0_rq_cpu);
61 
62 	this_rq_cpu = data->out__this_rq_cpu;
63 	CHECK(this_rq_cpu != data->out__rq_cpu, "this_rq_cpu",
64 	      "got %u, exp %u\n", this_rq_cpu, data->out__rq_cpu);
65 
66 	this_bpf_prog_active = data->out__this_bpf_prog_active;
67 	CHECK(this_bpf_prog_active != data->out__bpf_prog_active, "this_bpf_prog_active",
68 	      "got %d, exp %d\n", this_bpf_prog_active,
69 	      data->out__bpf_prog_active);
70 
71 cleanup:
72 	test_ksyms_btf__destroy(skel);
73 }
74 
75 static void test_null_check(void)
76 {
77 	struct test_ksyms_btf_null_check *skel;
78 
79 	skel = test_ksyms_btf_null_check__open_and_load();
80 	CHECK(skel, "skel_open", "unexpected load of a prog missing null check\n");
81 
82 	test_ksyms_btf_null_check__destroy(skel);
83 }
84 
85 static void test_weak_syms(void)
86 {
87 	struct test_ksyms_weak *skel;
88 	struct test_ksyms_weak__data *data;
89 	int err;
90 
91 	skel = test_ksyms_weak__open_and_load();
92 	if (CHECK(!skel, "test_ksyms_weak__open_and_load", "failed\n"))
93 		return;
94 
95 	err = test_ksyms_weak__attach(skel);
96 	if (CHECK(err, "test_ksyms_weak__attach", "skeleton attach failed: %d\n", err))
97 		goto cleanup;
98 
99 	/* trigger tracepoint */
100 	usleep(1);
101 
102 	data = skel->data;
103 	ASSERT_EQ(data->out__existing_typed, 0, "existing typed ksym");
104 	ASSERT_NEQ(data->out__existing_typeless, -1, "existing typeless ksym");
105 	ASSERT_EQ(data->out__non_existent_typeless, 0, "nonexistent typeless ksym");
106 	ASSERT_EQ(data->out__non_existent_typed, 0, "nonexistent typed ksym");
107 
108 cleanup:
109 	test_ksyms_weak__destroy(skel);
110 }
111 
112 void test_ksyms_btf(void)
113 {
114 	int percpu_datasec;
115 	struct btf *btf;
116 
117 	btf = libbpf_find_kernel_btf();
118 	if (!ASSERT_OK_PTR(btf, "btf_exists"))
119 		return;
120 
121 	percpu_datasec = btf__find_by_name_kind(btf, ".data..percpu",
122 						BTF_KIND_DATASEC);
123 	btf__free(btf);
124 	if (percpu_datasec < 0) {
125 		printf("%s:SKIP:no PERCPU DATASEC in kernel btf\n",
126 		       __func__);
127 		test__skip();
128 		return;
129 	}
130 
131 	if (test__start_subtest("basic"))
132 		test_basic();
133 
134 	if (test__start_subtest("null_check"))
135 		test_null_check();
136 
137 	if (test__start_subtest("weak_ksyms"))
138 		test_weak_syms();
139 }
140