1 /* SPDX-License-Identifier: GPL-2.0
2 * Copyright (c) 2018 Jesper Dangaard Brouer, Red Hat Inc.
3 */
4 static const char *__doc__ =
5 "Libbpf test program for loading BPF ELF object files";
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <bpf/libbpf.h>
12 #include <getopt.h>
13
14 static const struct option long_options[] = {
15 {"help", no_argument, NULL, 'h' },
16 {"debug", no_argument, NULL, 'D' },
17 {"quiet", no_argument, NULL, 'q' },
18 {0, 0, NULL, 0 }
19 };
20
usage(char * argv[])21 static void usage(char *argv[])
22 {
23 int i;
24
25 printf("\nDOCUMENTATION:\n%s\n\n", __doc__);
26 printf(" Usage: %s (options-see-below) BPF_FILE\n", argv[0]);
27 printf(" Listing options:\n");
28 for (i = 0; long_options[i].name != 0; i++) {
29 printf(" --%-12s", long_options[i].name);
30 printf(" short-option: -%c",
31 long_options[i].val);
32 printf("\n");
33 }
34 printf("\n");
35 }
36
37 #define DEFINE_PRINT_FN(name, enabled) \
38 static int libbpf_##name(const char *fmt, ...) \
39 { \
40 va_list args; \
41 int ret; \
42 \
43 va_start(args, fmt); \
44 if (enabled) { \
45 fprintf(stderr, "[" #name "] "); \
46 ret = vfprintf(stderr, fmt, args); \
47 } \
48 va_end(args); \
49 return ret; \
50 }
51 DEFINE_PRINT_FN(warning, 1)
52 DEFINE_PRINT_FN(info, 1)
53 DEFINE_PRINT_FN(debug, 1)
54
55 #define EXIT_FAIL_LIBBPF EXIT_FAILURE
56 #define EXIT_FAIL_OPTION 2
57
test_walk_progs(struct bpf_object * obj,bool verbose)58 int test_walk_progs(struct bpf_object *obj, bool verbose)
59 {
60 struct bpf_program *prog;
61 int cnt = 0;
62
63 bpf_object__for_each_program(prog, obj) {
64 cnt++;
65 if (verbose)
66 printf("Prog (count:%d) section_name: %s\n", cnt,
67 bpf_program__title(prog, false));
68 }
69 return 0;
70 }
71
test_walk_maps(struct bpf_object * obj,bool verbose)72 int test_walk_maps(struct bpf_object *obj, bool verbose)
73 {
74 struct bpf_map *map;
75 int cnt = 0;
76
77 bpf_map__for_each(map, obj) {
78 cnt++;
79 if (verbose)
80 printf("Map (count:%d) name: %s\n", cnt,
81 bpf_map__name(map));
82 }
83 return 0;
84 }
85
test_open_file(char * filename,bool verbose)86 int test_open_file(char *filename, bool verbose)
87 {
88 struct bpf_object *bpfobj = NULL;
89 long err;
90
91 if (verbose)
92 printf("Open BPF ELF-file with libbpf: %s\n", filename);
93
94 /* Load BPF ELF object file and check for errors */
95 bpfobj = bpf_object__open(filename);
96 err = libbpf_get_error(bpfobj);
97 if (err) {
98 char err_buf[128];
99 libbpf_strerror(err, err_buf, sizeof(err_buf));
100 if (verbose)
101 printf("Unable to load eBPF objects in file '%s': %s\n",
102 filename, err_buf);
103 return EXIT_FAIL_LIBBPF;
104 }
105 test_walk_progs(bpfobj, verbose);
106 test_walk_maps(bpfobj, verbose);
107
108 if (verbose)
109 printf("Close BPF ELF-file with libbpf: %s\n",
110 bpf_object__name(bpfobj));
111 bpf_object__close(bpfobj);
112
113 return 0;
114 }
115
main(int argc,char ** argv)116 int main(int argc, char **argv)
117 {
118 char filename[1024] = { 0 };
119 bool verbose = 1;
120 int longindex = 0;
121 int opt;
122
123 libbpf_set_print(libbpf_warning, libbpf_info, NULL);
124
125 /* Parse commands line args */
126 while ((opt = getopt_long(argc, argv, "hDq",
127 long_options, &longindex)) != -1) {
128 switch (opt) {
129 case 'D':
130 libbpf_set_print(libbpf_warning, libbpf_info,
131 libbpf_debug);
132 break;
133 case 'q': /* Use in scripting mode */
134 verbose = 0;
135 break;
136 case 'h':
137 default:
138 usage(argv);
139 return EXIT_FAIL_OPTION;
140 }
141 }
142 if (optind >= argc) {
143 usage(argv);
144 printf("ERROR: Expected BPF_FILE argument after options\n");
145 return EXIT_FAIL_OPTION;
146 }
147 snprintf(filename, sizeof(filename), "%s", argv[optind]);
148
149 return test_open_file(filename, verbose);
150 }
151