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 static bool debug = 0;
libbpf_debug_print(enum libbpf_print_level level,const char * fmt,va_list args)40 static int libbpf_debug_print(enum libbpf_print_level level,
41 			      const char *fmt, va_list args)
42 {
43 	if (level == LIBBPF_DEBUG && !debug)
44 		return 0;
45 
46 	fprintf(stderr, "[%d] ", level);
47 	return vfprintf(stderr, fmt, args);
48 }
49 
50 #define EXIT_FAIL_LIBBPF EXIT_FAILURE
51 #define EXIT_FAIL_OPTION 2
52 
test_walk_progs(struct bpf_object * obj,bool verbose)53 int test_walk_progs(struct bpf_object *obj, bool verbose)
54 {
55 	struct bpf_program *prog;
56 	int cnt = 0;
57 
58 	bpf_object__for_each_program(prog, obj) {
59 		cnt++;
60 		if (verbose)
61 			printf("Prog (count:%d) section_name: %s\n", cnt,
62 			       bpf_program__title(prog, false));
63 	}
64 	return 0;
65 }
66 
test_walk_maps(struct bpf_object * obj,bool verbose)67 int test_walk_maps(struct bpf_object *obj, bool verbose)
68 {
69 	struct bpf_map *map;
70 	int cnt = 0;
71 
72 	bpf_object__for_each_map(map, obj) {
73 		cnt++;
74 		if (verbose)
75 			printf("Map (count:%d) name: %s\n", cnt,
76 			       bpf_map__name(map));
77 	}
78 	return 0;
79 }
80 
test_open_file(char * filename,bool verbose)81 int test_open_file(char *filename, bool verbose)
82 {
83 	struct bpf_object *bpfobj = NULL;
84 	long err;
85 
86 	if (verbose)
87 		printf("Open BPF ELF-file with libbpf: %s\n", filename);
88 
89 	/* Load BPF ELF object file and check for errors */
90 	bpfobj = bpf_object__open(filename);
91 	err = libbpf_get_error(bpfobj);
92 	if (err) {
93 		char err_buf[128];
94 		libbpf_strerror(err, err_buf, sizeof(err_buf));
95 		if (verbose)
96 			printf("Unable to load eBPF objects in file '%s': %s\n",
97 			       filename, err_buf);
98 		return EXIT_FAIL_LIBBPF;
99 	}
100 	test_walk_progs(bpfobj, verbose);
101 	test_walk_maps(bpfobj, verbose);
102 
103 	if (verbose)
104 		printf("Close BPF ELF-file with libbpf: %s\n",
105 		       bpf_object__name(bpfobj));
106 	bpf_object__close(bpfobj);
107 
108 	return 0;
109 }
110 
main(int argc,char ** argv)111 int main(int argc, char **argv)
112 {
113 	char filename[1024] = { 0 };
114 	bool verbose = 1;
115 	int longindex = 0;
116 	int opt;
117 
118 	libbpf_set_print(libbpf_debug_print);
119 
120 	/* Parse commands line args */
121 	while ((opt = getopt_long(argc, argv, "hDq",
122 				  long_options, &longindex)) != -1) {
123 		switch (opt) {
124 		case 'D':
125 			debug = 1;
126 			break;
127 		case 'q': /* Use in scripting mode */
128 			verbose = 0;
129 			break;
130 		case 'h':
131 		default:
132 			usage(argv);
133 			return EXIT_FAIL_OPTION;
134 		}
135 	}
136 	if (optind >= argc) {
137 		usage(argv);
138 		printf("ERROR: Expected BPF_FILE argument after options\n");
139 		return EXIT_FAIL_OPTION;
140 	}
141 	snprintf(filename, sizeof(filename), "%s", argv[optind]);
142 
143 	return test_open_file(filename, verbose);
144 }
145