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:
Skeleton()20 Skeleton(): skel(nullptr) { }
21
~Skeleton()22 ~Skeleton() { if (skel) T::destroy(skel); }
23
open(const struct bpf_object_open_opts * opts=nullptr)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
load()41 int load() { return T::load(skel); }
42
attach()43 int attach() { return T::attach(skel); }
44
detach()45 void detach() { return T::detach(skel); }
46
operator ->() const47 const T* operator->() const { return skel; }
48
operator ->()49 T* operator->() { return skel; }
50
get() const51 const T *get() const { return skel; }
52 };
53
dump_printf(void * ctx,const char * fmt,va_list args)54 static void dump_printf(void *ctx, const char *fmt, va_list args)
55 {
56 }
57
try_skeleton_template()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
main(int argc,char * argv[])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