1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 #include <iostream>
3 #include <unistd.h>
4 #include <linux/bpf.h>
5 #include <linux/btf.h>
6 #include <bpf/libbpf.h>
7 #include <bpf/bpf.h>
8 #include <bpf/btf.h>
9 
10 #ifndef _Bool
11 #define _Bool bool
12 #endif
13 #include "test_core_extern.skel.h"
14 
15 template <typename T>
16 class Skeleton {
17 private:
18 	T *skel;
19 public:
20 	Skeleton(): skel(nullptr) { }
21 
22 	~Skeleton() { if (skel) T::destroy(skel); }
23 
24 	int open(const struct bpf_object_open_opts *opts = nullptr)
25 	{
26 		int err;
27 
28 		if (skel)
29 			return -EBUSY;
30 
31 		skel = T::open(opts);
32 		err = libbpf_get_error(skel);
33 		if (err) {
34 			skel = nullptr;
35 			return err;
36 		}
37 
38 		return 0;
39 	}
40 
41 	int load() { return T::load(skel); }
42 
43 	int attach() { return T::attach(skel); }
44 
45 	void detach() { return T::detach(skel); }
46 
47 	const T* operator->() const { return skel; }
48 
49 	T* operator->() { return skel; }
50 
51 	const T *get() const { return skel; }
52 };
53 
54 static void dump_printf(void *ctx, const char *fmt, va_list args)
55 {
56 }
57 
58 static void try_skeleton_template()
59 {
60 	Skeleton<test_core_extern> skel;
61 	std::string prog_name;
62 	int err;
63 	LIBBPF_OPTS(bpf_object_open_opts, opts);
64 
65 	err = skel.open(&opts);
66 	if (err) {
67 		fprintf(stderr, "Skeleton open failed: %d\n", err);
68 		return;
69 	}
70 
71 	skel->data->kern_ver = 123;
72 	skel->data->int_val = skel->data->ushort_val;
73 
74 	err = skel.load();
75 	if (err) {
76 		fprintf(stderr, "Skeleton load failed: %d\n", err);
77 		return;
78 	}
79 
80 	if (!skel->kconfig->CONFIG_BPF_SYSCALL)
81 		fprintf(stderr, "Seems like CONFIG_BPF_SYSCALL isn't set?!\n");
82 
83 	err = skel.attach();
84 	if (err) {
85 		fprintf(stderr, "Skeleton attach failed: %d\n", err);
86 		return;
87 	}
88 
89 	prog_name = bpf_program__name(skel->progs.handle_sys_enter);
90 	if (prog_name != "handle_sys_enter")
91 		fprintf(stderr, "Unexpected program name: %s\n", prog_name.c_str());
92 
93 	bpf_link__destroy(skel->links.handle_sys_enter);
94 	skel->links.handle_sys_enter = bpf_program__attach(skel->progs.handle_sys_enter);
95 
96 	skel.detach();
97 
98 	/* destructor will destroy underlying skeleton */
99 }
100 
101 int main(int argc, char *argv[])
102 {
103 	struct btf_dump_opts opts = { };
104 	struct test_core_extern *skel;
105 	struct btf *btf;
106 	int fd;
107 
108 	try_skeleton_template();
109 
110 	/* libbpf.h */
111 	libbpf_set_print(NULL);
112 
113 	/* bpf.h */
114 	bpf_prog_get_fd_by_id(0);
115 
116 	/* btf.h */
117 	btf = btf__new(NULL, 0);
118 	if (!libbpf_get_error(btf))
119 		btf_dump__new(btf, dump_printf, nullptr, &opts);
120 
121 	/* BPF skeleton */
122 	skel = test_core_extern__open_and_load();
123 	test_core_extern__destroy(skel);
124 
125 	fd = bpf_enable_stats(BPF_STATS_RUN_TIME);
126 	if (fd < 0)
127 		std::cout << "FAILED to enable stats: " << fd << std::endl;
128 	else
129 		::close(fd);
130 
131 	std::cout << "DONE!" << std::endl;
132 
133 	return 0;
134 }
135