16bf6affeSStanislav Fomichev /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
27c8dce4bSAndrii Nakryiko #include <iostream>
33e689141SToke Høiland-Jørgensen #include <bpf/libbpf.h>
43e689141SToke Høiland-Jørgensen #include <bpf/bpf.h>
53e689141SToke Høiland-Jørgensen #include <bpf/btf.h>
67c8dce4bSAndrii Nakryiko #include "test_core_extern.skel.h"
76bf6affeSStanislav Fomichev 
8*189e0ecaSAndrii Nakryiko template <typename T>
9*189e0ecaSAndrii Nakryiko class Skeleton {
10*189e0ecaSAndrii Nakryiko private:
11*189e0ecaSAndrii Nakryiko 	T *skel;
12*189e0ecaSAndrii Nakryiko public:
13*189e0ecaSAndrii Nakryiko 	Skeleton(): skel(nullptr) { }
14*189e0ecaSAndrii Nakryiko 
15*189e0ecaSAndrii Nakryiko 	~Skeleton() { if (skel) T::destroy(skel); }
16*189e0ecaSAndrii Nakryiko 
17*189e0ecaSAndrii Nakryiko 	int open(const struct bpf_object_open_opts *opts = nullptr)
18*189e0ecaSAndrii Nakryiko 	{
19*189e0ecaSAndrii Nakryiko 		int err;
20*189e0ecaSAndrii Nakryiko 
21*189e0ecaSAndrii Nakryiko 		if (skel)
22*189e0ecaSAndrii Nakryiko 			return -EBUSY;
23*189e0ecaSAndrii Nakryiko 
24*189e0ecaSAndrii Nakryiko 		skel = T::open(opts);
25*189e0ecaSAndrii Nakryiko 		err = libbpf_get_error(skel);
26*189e0ecaSAndrii Nakryiko 		if (err) {
27*189e0ecaSAndrii Nakryiko 			skel = nullptr;
28*189e0ecaSAndrii Nakryiko 			return err;
29*189e0ecaSAndrii Nakryiko 		}
30*189e0ecaSAndrii Nakryiko 
31*189e0ecaSAndrii Nakryiko 		return 0;
32*189e0ecaSAndrii Nakryiko 	}
33*189e0ecaSAndrii Nakryiko 
34*189e0ecaSAndrii Nakryiko 	int load() { return T::load(skel); }
35*189e0ecaSAndrii Nakryiko 
36*189e0ecaSAndrii Nakryiko 	int attach() { return T::attach(skel); }
37*189e0ecaSAndrii Nakryiko 
38*189e0ecaSAndrii Nakryiko 	void detach() { return T::detach(skel); }
39*189e0ecaSAndrii Nakryiko 
40*189e0ecaSAndrii Nakryiko 	const T* operator->() const { return skel; }
41*189e0ecaSAndrii Nakryiko 
42*189e0ecaSAndrii Nakryiko 	T* operator->() { return skel; }
43*189e0ecaSAndrii Nakryiko 
44*189e0ecaSAndrii Nakryiko 	const T *get() const { return skel; }
45*189e0ecaSAndrii Nakryiko };
466bf6affeSStanislav Fomichev 
47ecf45e60SJiri Olsa static void dump_printf(void *ctx, const char *fmt, va_list args)
48ecf45e60SJiri Olsa {
49ecf45e60SJiri Olsa }
50ecf45e60SJiri Olsa 
51*189e0ecaSAndrii Nakryiko static void try_skeleton_template()
52*189e0ecaSAndrii Nakryiko {
53*189e0ecaSAndrii Nakryiko 	Skeleton<test_core_extern> skel;
54*189e0ecaSAndrii Nakryiko 	std::string prog_name;
55*189e0ecaSAndrii Nakryiko 	int err;
56*189e0ecaSAndrii Nakryiko 	LIBBPF_OPTS(bpf_object_open_opts, opts);
57*189e0ecaSAndrii Nakryiko 
58*189e0ecaSAndrii Nakryiko 	err = skel.open(&opts);
59*189e0ecaSAndrii Nakryiko 	if (err) {
60*189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Skeleton open failed: %d\n", err);
61*189e0ecaSAndrii Nakryiko 		return;
62*189e0ecaSAndrii Nakryiko 	}
63*189e0ecaSAndrii Nakryiko 
64*189e0ecaSAndrii Nakryiko 	skel->data->kern_ver = 123;
65*189e0ecaSAndrii Nakryiko 	skel->data->int_val = skel->data->ushort_val;
66*189e0ecaSAndrii Nakryiko 
67*189e0ecaSAndrii Nakryiko 	err = skel.load();
68*189e0ecaSAndrii Nakryiko 	if (err) {
69*189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Skeleton load failed: %d\n", err);
70*189e0ecaSAndrii Nakryiko 		return;
71*189e0ecaSAndrii Nakryiko 	}
72*189e0ecaSAndrii Nakryiko 
73*189e0ecaSAndrii Nakryiko 	if (!skel->kconfig->CONFIG_BPF_SYSCALL)
74*189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Seems like CONFIG_BPF_SYSCALL isn't set?!\n");
75*189e0ecaSAndrii Nakryiko 
76*189e0ecaSAndrii Nakryiko 	err = skel.attach();
77*189e0ecaSAndrii Nakryiko 	if (err) {
78*189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Skeleton attach failed: %d\n", err);
79*189e0ecaSAndrii Nakryiko 		return;
80*189e0ecaSAndrii Nakryiko 	}
81*189e0ecaSAndrii Nakryiko 
82*189e0ecaSAndrii Nakryiko 	prog_name = bpf_program__name(skel->progs.handle_sys_enter);
83*189e0ecaSAndrii Nakryiko 	if (prog_name != "handle_sys_enter")
84*189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Unexpected program name: %s\n", prog_name.c_str());
85*189e0ecaSAndrii Nakryiko 
86*189e0ecaSAndrii Nakryiko 	bpf_link__destroy(skel->links.handle_sys_enter);
87*189e0ecaSAndrii Nakryiko 	skel->links.handle_sys_enter = bpf_program__attach(skel->progs.handle_sys_enter);
88*189e0ecaSAndrii Nakryiko 
89*189e0ecaSAndrii Nakryiko 	skel.detach();
90*189e0ecaSAndrii Nakryiko 
91*189e0ecaSAndrii Nakryiko 	/* destructor will destory underlying skeleton */
92*189e0ecaSAndrii Nakryiko }
93*189e0ecaSAndrii Nakryiko 
946bf6affeSStanislav Fomichev int main(int argc, char *argv[])
956bf6affeSStanislav Fomichev {
96ecf45e60SJiri Olsa 	struct btf_dump_opts opts = { };
977c8dce4bSAndrii Nakryiko 	struct test_core_extern *skel;
98ecf45e60SJiri Olsa 	struct btf *btf;
997c8dce4bSAndrii Nakryiko 
100*189e0ecaSAndrii Nakryiko 	try_skeleton_template();
101*189e0ecaSAndrii Nakryiko 
1026bf6affeSStanislav Fomichev 	/* libbpf.h */
1036bf6affeSStanislav Fomichev 	libbpf_set_print(NULL);
1046bf6affeSStanislav Fomichev 
1056bf6affeSStanislav Fomichev 	/* bpf.h */
1066bf6affeSStanislav Fomichev 	bpf_prog_get_fd_by_id(0);
1076bf6affeSStanislav Fomichev 
1086bf6affeSStanislav Fomichev 	/* btf.h */
109ecf45e60SJiri Olsa 	btf = btf__new(NULL, 0);
110*189e0ecaSAndrii Nakryiko 	if (!libbpf_get_error(btf))
111ecf45e60SJiri Olsa 		btf_dump__new(btf, dump_printf, nullptr, &opts);
1126bf6affeSStanislav Fomichev 
1137c8dce4bSAndrii Nakryiko 	/* BPF skeleton */
1147c8dce4bSAndrii Nakryiko 	skel = test_core_extern__open_and_load();
1157c8dce4bSAndrii Nakryiko 	test_core_extern__destroy(skel);
1167c8dce4bSAndrii Nakryiko 
1177c8dce4bSAndrii Nakryiko 	std::cout << "DONE!" << std::endl;
1187c8dce4bSAndrii Nakryiko 
1196bf6affeSStanislav Fomichev 	return 0;
1206bf6affeSStanislav Fomichev }
121