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