xref: /aosp_15_r20/external/bpftool/src/main.c (revision 858ea5e570667251cdc31d3fe7b846b591105938)
1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3*858ea5e5SAndroid Build Coastguard Worker 
4*858ea5e5SAndroid Build Coastguard Worker #include <ctype.h>
5*858ea5e5SAndroid Build Coastguard Worker #include <errno.h>
6*858ea5e5SAndroid Build Coastguard Worker #include <getopt.h>
7*858ea5e5SAndroid Build Coastguard Worker #include <linux/bpf.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
10*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
11*858ea5e5SAndroid Build Coastguard Worker 
12*858ea5e5SAndroid Build Coastguard Worker #include <bpf/bpf.h>
13*858ea5e5SAndroid Build Coastguard Worker #include <bpf/btf.h>
14*858ea5e5SAndroid Build Coastguard Worker #include <bpf/hashmap.h>
15*858ea5e5SAndroid Build Coastguard Worker #include <bpf/libbpf.h>
16*858ea5e5SAndroid Build Coastguard Worker 
17*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
18*858ea5e5SAndroid Build Coastguard Worker 
19*858ea5e5SAndroid Build Coastguard Worker #define BATCH_LINE_LEN_MAX 65536
20*858ea5e5SAndroid Build Coastguard Worker #define BATCH_ARG_NB_MAX 4096
21*858ea5e5SAndroid Build Coastguard Worker 
22*858ea5e5SAndroid Build Coastguard Worker const char *bin_name;
23*858ea5e5SAndroid Build Coastguard Worker static int last_argc;
24*858ea5e5SAndroid Build Coastguard Worker static char **last_argv;
25*858ea5e5SAndroid Build Coastguard Worker static int (*last_do_help)(int argc, char **argv);
26*858ea5e5SAndroid Build Coastguard Worker json_writer_t *json_wtr;
27*858ea5e5SAndroid Build Coastguard Worker bool pretty_output;
28*858ea5e5SAndroid Build Coastguard Worker bool json_output;
29*858ea5e5SAndroid Build Coastguard Worker bool show_pinned;
30*858ea5e5SAndroid Build Coastguard Worker bool block_mount;
31*858ea5e5SAndroid Build Coastguard Worker bool verifier_logs;
32*858ea5e5SAndroid Build Coastguard Worker bool relaxed_maps;
33*858ea5e5SAndroid Build Coastguard Worker bool use_loader;
34*858ea5e5SAndroid Build Coastguard Worker struct btf *base_btf;
35*858ea5e5SAndroid Build Coastguard Worker struct hashmap *refs_table;
36*858ea5e5SAndroid Build Coastguard Worker 
clean_and_exit(int i)37*858ea5e5SAndroid Build Coastguard Worker static void __noreturn clean_and_exit(int i)
38*858ea5e5SAndroid Build Coastguard Worker {
39*858ea5e5SAndroid Build Coastguard Worker 	if (json_output)
40*858ea5e5SAndroid Build Coastguard Worker 		jsonw_destroy(&json_wtr);
41*858ea5e5SAndroid Build Coastguard Worker 
42*858ea5e5SAndroid Build Coastguard Worker 	exit(i);
43*858ea5e5SAndroid Build Coastguard Worker }
44*858ea5e5SAndroid Build Coastguard Worker 
usage(void)45*858ea5e5SAndroid Build Coastguard Worker void usage(void)
46*858ea5e5SAndroid Build Coastguard Worker {
47*858ea5e5SAndroid Build Coastguard Worker 	last_do_help(last_argc - 1, last_argv + 1);
48*858ea5e5SAndroid Build Coastguard Worker 
49*858ea5e5SAndroid Build Coastguard Worker 	clean_and_exit(-1);
50*858ea5e5SAndroid Build Coastguard Worker }
51*858ea5e5SAndroid Build Coastguard Worker 
do_help(int argc,char ** argv)52*858ea5e5SAndroid Build Coastguard Worker static int do_help(int argc, char **argv)
53*858ea5e5SAndroid Build Coastguard Worker {
54*858ea5e5SAndroid Build Coastguard Worker 	if (json_output) {
55*858ea5e5SAndroid Build Coastguard Worker 		jsonw_null(json_wtr);
56*858ea5e5SAndroid Build Coastguard Worker 		return 0;
57*858ea5e5SAndroid Build Coastguard Worker 	}
58*858ea5e5SAndroid Build Coastguard Worker 
59*858ea5e5SAndroid Build Coastguard Worker 	fprintf(stderr,
60*858ea5e5SAndroid Build Coastguard Worker 		"Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n"
61*858ea5e5SAndroid Build Coastguard Worker 		"       %s batch file FILE\n"
62*858ea5e5SAndroid Build Coastguard Worker 		"       %s version\n"
63*858ea5e5SAndroid Build Coastguard Worker 		"\n"
64*858ea5e5SAndroid Build Coastguard Worker 		"       OBJECT := { prog | map | link | cgroup | perf | net | feature | btf | gen | struct_ops | iter }\n"
65*858ea5e5SAndroid Build Coastguard Worker 		"       " HELP_SPEC_OPTIONS " |\n"
66*858ea5e5SAndroid Build Coastguard Worker 		"                    {-V|--version} }\n"
67*858ea5e5SAndroid Build Coastguard Worker 		"",
68*858ea5e5SAndroid Build Coastguard Worker 		bin_name, bin_name, bin_name);
69*858ea5e5SAndroid Build Coastguard Worker 
70*858ea5e5SAndroid Build Coastguard Worker 	return 0;
71*858ea5e5SAndroid Build Coastguard Worker }
72*858ea5e5SAndroid Build Coastguard Worker 
73*858ea5e5SAndroid Build Coastguard Worker static int do_batch(int argc, char **argv);
74*858ea5e5SAndroid Build Coastguard Worker static int do_version(int argc, char **argv);
75*858ea5e5SAndroid Build Coastguard Worker 
76*858ea5e5SAndroid Build Coastguard Worker static const struct cmd commands[] = {
77*858ea5e5SAndroid Build Coastguard Worker 	{ "help",	do_help },
78*858ea5e5SAndroid Build Coastguard Worker 	{ "batch",	do_batch },
79*858ea5e5SAndroid Build Coastguard Worker 	{ "prog",	do_prog },
80*858ea5e5SAndroid Build Coastguard Worker 	{ "map",	do_map },
81*858ea5e5SAndroid Build Coastguard Worker 	{ "link",	do_link },
82*858ea5e5SAndroid Build Coastguard Worker 	{ "cgroup",	do_cgroup },
83*858ea5e5SAndroid Build Coastguard Worker 	{ "perf",	do_perf },
84*858ea5e5SAndroid Build Coastguard Worker 	{ "net",	do_net },
85*858ea5e5SAndroid Build Coastguard Worker 	{ "feature",	do_feature },
86*858ea5e5SAndroid Build Coastguard Worker 	{ "btf",	do_btf },
87*858ea5e5SAndroid Build Coastguard Worker 	{ "gen",	do_gen },
88*858ea5e5SAndroid Build Coastguard Worker 	{ "struct_ops",	do_struct_ops },
89*858ea5e5SAndroid Build Coastguard Worker 	{ "iter",	do_iter },
90*858ea5e5SAndroid Build Coastguard Worker 	{ "version",	do_version },
91*858ea5e5SAndroid Build Coastguard Worker 	{ 0 }
92*858ea5e5SAndroid Build Coastguard Worker };
93*858ea5e5SAndroid Build Coastguard Worker 
94*858ea5e5SAndroid Build Coastguard Worker #ifndef BPFTOOL_VERSION
95*858ea5e5SAndroid Build Coastguard Worker /* bpftool's major and minor version numbers are aligned on libbpf's. There is
96*858ea5e5SAndroid Build Coastguard Worker  * an offset of 6 for the version number, because bpftool's version was higher
97*858ea5e5SAndroid Build Coastguard Worker  * than libbpf's when we adopted this scheme. The patch number remains at 0
98*858ea5e5SAndroid Build Coastguard Worker  * for now. Set BPFTOOL_VERSION to override.
99*858ea5e5SAndroid Build Coastguard Worker  */
100*858ea5e5SAndroid Build Coastguard Worker #define BPFTOOL_MAJOR_VERSION (LIBBPF_MAJOR_VERSION + 6)
101*858ea5e5SAndroid Build Coastguard Worker #define BPFTOOL_MINOR_VERSION LIBBPF_MINOR_VERSION
102*858ea5e5SAndroid Build Coastguard Worker #define BPFTOOL_PATCH_VERSION 0
103*858ea5e5SAndroid Build Coastguard Worker #endif
104*858ea5e5SAndroid Build Coastguard Worker 
105*858ea5e5SAndroid Build Coastguard Worker static void
print_feature(const char * feature,bool state,unsigned int * nb_features)106*858ea5e5SAndroid Build Coastguard Worker print_feature(const char *feature, bool state, unsigned int *nb_features)
107*858ea5e5SAndroid Build Coastguard Worker {
108*858ea5e5SAndroid Build Coastguard Worker 	if (state) {
109*858ea5e5SAndroid Build Coastguard Worker 		printf("%s %s", *nb_features ? "," : "", feature);
110*858ea5e5SAndroid Build Coastguard Worker 		*nb_features = *nb_features + 1;
111*858ea5e5SAndroid Build Coastguard Worker 	}
112*858ea5e5SAndroid Build Coastguard Worker }
113*858ea5e5SAndroid Build Coastguard Worker 
do_version(int argc,char ** argv)114*858ea5e5SAndroid Build Coastguard Worker static int do_version(int argc, char **argv)
115*858ea5e5SAndroid Build Coastguard Worker {
116*858ea5e5SAndroid Build Coastguard Worker #ifdef HAVE_LIBBFD_SUPPORT
117*858ea5e5SAndroid Build Coastguard Worker 	const bool has_libbfd = true;
118*858ea5e5SAndroid Build Coastguard Worker #else
119*858ea5e5SAndroid Build Coastguard Worker 	const bool has_libbfd = false;
120*858ea5e5SAndroid Build Coastguard Worker #endif
121*858ea5e5SAndroid Build Coastguard Worker #ifdef HAVE_LLVM_SUPPORT
122*858ea5e5SAndroid Build Coastguard Worker 	const bool has_llvm = true;
123*858ea5e5SAndroid Build Coastguard Worker #else
124*858ea5e5SAndroid Build Coastguard Worker 	const bool has_llvm = false;
125*858ea5e5SAndroid Build Coastguard Worker #endif
126*858ea5e5SAndroid Build Coastguard Worker #ifdef BPFTOOL_WITHOUT_SKELETONS
127*858ea5e5SAndroid Build Coastguard Worker 	const bool has_skeletons = false;
128*858ea5e5SAndroid Build Coastguard Worker #else
129*858ea5e5SAndroid Build Coastguard Worker 	const bool has_skeletons = true;
130*858ea5e5SAndroid Build Coastguard Worker #endif
131*858ea5e5SAndroid Build Coastguard Worker 	bool bootstrap = false;
132*858ea5e5SAndroid Build Coastguard Worker 	int i;
133*858ea5e5SAndroid Build Coastguard Worker 
134*858ea5e5SAndroid Build Coastguard Worker 	for (i = 0; commands[i].cmd; i++) {
135*858ea5e5SAndroid Build Coastguard Worker 		if (!strcmp(commands[i].cmd, "prog")) {
136*858ea5e5SAndroid Build Coastguard Worker 			/* Assume we run a bootstrap version if "bpftool prog"
137*858ea5e5SAndroid Build Coastguard Worker 			 * is not available.
138*858ea5e5SAndroid Build Coastguard Worker 			 */
139*858ea5e5SAndroid Build Coastguard Worker 			bootstrap = !commands[i].func;
140*858ea5e5SAndroid Build Coastguard Worker 			break;
141*858ea5e5SAndroid Build Coastguard Worker 		}
142*858ea5e5SAndroid Build Coastguard Worker 	}
143*858ea5e5SAndroid Build Coastguard Worker 
144*858ea5e5SAndroid Build Coastguard Worker 	if (json_output) {
145*858ea5e5SAndroid Build Coastguard Worker 		jsonw_start_object(json_wtr);	/* root object */
146*858ea5e5SAndroid Build Coastguard Worker 
147*858ea5e5SAndroid Build Coastguard Worker 		jsonw_name(json_wtr, "version");
148*858ea5e5SAndroid Build Coastguard Worker #ifdef BPFTOOL_VERSION
149*858ea5e5SAndroid Build Coastguard Worker 		jsonw_printf(json_wtr, "\"%s\"", BPFTOOL_VERSION);
150*858ea5e5SAndroid Build Coastguard Worker #else
151*858ea5e5SAndroid Build Coastguard Worker 		jsonw_printf(json_wtr, "\"%d.%d.%d\"", BPFTOOL_MAJOR_VERSION,
152*858ea5e5SAndroid Build Coastguard Worker 			     BPFTOOL_MINOR_VERSION, BPFTOOL_PATCH_VERSION);
153*858ea5e5SAndroid Build Coastguard Worker #endif
154*858ea5e5SAndroid Build Coastguard Worker 		jsonw_name(json_wtr, "libbpf_version");
155*858ea5e5SAndroid Build Coastguard Worker 		jsonw_printf(json_wtr, "\"%d.%d\"",
156*858ea5e5SAndroid Build Coastguard Worker 			     libbpf_major_version(), libbpf_minor_version());
157*858ea5e5SAndroid Build Coastguard Worker 
158*858ea5e5SAndroid Build Coastguard Worker 		jsonw_name(json_wtr, "features");
159*858ea5e5SAndroid Build Coastguard Worker 		jsonw_start_object(json_wtr);	/* features */
160*858ea5e5SAndroid Build Coastguard Worker 		jsonw_bool_field(json_wtr, "libbfd", has_libbfd);
161*858ea5e5SAndroid Build Coastguard Worker 		jsonw_bool_field(json_wtr, "llvm", has_llvm);
162*858ea5e5SAndroid Build Coastguard Worker 		jsonw_bool_field(json_wtr, "skeletons", has_skeletons);
163*858ea5e5SAndroid Build Coastguard Worker 		jsonw_bool_field(json_wtr, "bootstrap", bootstrap);
164*858ea5e5SAndroid Build Coastguard Worker 		jsonw_end_object(json_wtr);	/* features */
165*858ea5e5SAndroid Build Coastguard Worker 
166*858ea5e5SAndroid Build Coastguard Worker 		jsonw_end_object(json_wtr);	/* root object */
167*858ea5e5SAndroid Build Coastguard Worker 	} else {
168*858ea5e5SAndroid Build Coastguard Worker 		unsigned int nb_features = 0;
169*858ea5e5SAndroid Build Coastguard Worker 
170*858ea5e5SAndroid Build Coastguard Worker #ifdef BPFTOOL_VERSION
171*858ea5e5SAndroid Build Coastguard Worker 		printf("%s v%s\n", bin_name, BPFTOOL_VERSION);
172*858ea5e5SAndroid Build Coastguard Worker #else
173*858ea5e5SAndroid Build Coastguard Worker 		printf("%s v%d.%d.%d\n", bin_name, BPFTOOL_MAJOR_VERSION,
174*858ea5e5SAndroid Build Coastguard Worker 		       BPFTOOL_MINOR_VERSION, BPFTOOL_PATCH_VERSION);
175*858ea5e5SAndroid Build Coastguard Worker #endif
176*858ea5e5SAndroid Build Coastguard Worker 		printf("using libbpf %s\n", libbpf_version_string());
177*858ea5e5SAndroid Build Coastguard Worker 		printf("features:");
178*858ea5e5SAndroid Build Coastguard Worker 		print_feature("libbfd", has_libbfd, &nb_features);
179*858ea5e5SAndroid Build Coastguard Worker 		print_feature("llvm", has_llvm, &nb_features);
180*858ea5e5SAndroid Build Coastguard Worker 		print_feature("skeletons", has_skeletons, &nb_features);
181*858ea5e5SAndroid Build Coastguard Worker 		print_feature("bootstrap", bootstrap, &nb_features);
182*858ea5e5SAndroid Build Coastguard Worker 		printf("\n");
183*858ea5e5SAndroid Build Coastguard Worker 	}
184*858ea5e5SAndroid Build Coastguard Worker 	return 0;
185*858ea5e5SAndroid Build Coastguard Worker }
186*858ea5e5SAndroid Build Coastguard Worker 
cmd_select(const struct cmd * cmds,int argc,char ** argv,int (* help)(int argc,char ** argv))187*858ea5e5SAndroid Build Coastguard Worker int cmd_select(const struct cmd *cmds, int argc, char **argv,
188*858ea5e5SAndroid Build Coastguard Worker 	       int (*help)(int argc, char **argv))
189*858ea5e5SAndroid Build Coastguard Worker {
190*858ea5e5SAndroid Build Coastguard Worker 	unsigned int i;
191*858ea5e5SAndroid Build Coastguard Worker 
192*858ea5e5SAndroid Build Coastguard Worker 	last_argc = argc;
193*858ea5e5SAndroid Build Coastguard Worker 	last_argv = argv;
194*858ea5e5SAndroid Build Coastguard Worker 	last_do_help = help;
195*858ea5e5SAndroid Build Coastguard Worker 
196*858ea5e5SAndroid Build Coastguard Worker 	if (argc < 1 && cmds[0].func)
197*858ea5e5SAndroid Build Coastguard Worker 		return cmds[0].func(argc, argv);
198*858ea5e5SAndroid Build Coastguard Worker 
199*858ea5e5SAndroid Build Coastguard Worker 	for (i = 0; cmds[i].cmd; i++) {
200*858ea5e5SAndroid Build Coastguard Worker 		if (is_prefix(*argv, cmds[i].cmd)) {
201*858ea5e5SAndroid Build Coastguard Worker 			if (!cmds[i].func) {
202*858ea5e5SAndroid Build Coastguard Worker 				p_err("command '%s' is not supported in bootstrap mode",
203*858ea5e5SAndroid Build Coastguard Worker 				      cmds[i].cmd);
204*858ea5e5SAndroid Build Coastguard Worker 				return -1;
205*858ea5e5SAndroid Build Coastguard Worker 			}
206*858ea5e5SAndroid Build Coastguard Worker 			return cmds[i].func(argc - 1, argv + 1);
207*858ea5e5SAndroid Build Coastguard Worker 		}
208*858ea5e5SAndroid Build Coastguard Worker 	}
209*858ea5e5SAndroid Build Coastguard Worker 
210*858ea5e5SAndroid Build Coastguard Worker 	help(argc - 1, argv + 1);
211*858ea5e5SAndroid Build Coastguard Worker 
212*858ea5e5SAndroid Build Coastguard Worker 	return -1;
213*858ea5e5SAndroid Build Coastguard Worker }
214*858ea5e5SAndroid Build Coastguard Worker 
is_prefix(const char * pfx,const char * str)215*858ea5e5SAndroid Build Coastguard Worker bool is_prefix(const char *pfx, const char *str)
216*858ea5e5SAndroid Build Coastguard Worker {
217*858ea5e5SAndroid Build Coastguard Worker 	if (!pfx)
218*858ea5e5SAndroid Build Coastguard Worker 		return false;
219*858ea5e5SAndroid Build Coastguard Worker 	if (strlen(str) < strlen(pfx))
220*858ea5e5SAndroid Build Coastguard Worker 		return false;
221*858ea5e5SAndroid Build Coastguard Worker 
222*858ea5e5SAndroid Build Coastguard Worker 	return !memcmp(str, pfx, strlen(pfx));
223*858ea5e5SAndroid Build Coastguard Worker }
224*858ea5e5SAndroid Build Coastguard Worker 
225*858ea5e5SAndroid Build Coastguard Worker /* Last argument MUST be NULL pointer */
detect_common_prefix(const char * arg,...)226*858ea5e5SAndroid Build Coastguard Worker int detect_common_prefix(const char *arg, ...)
227*858ea5e5SAndroid Build Coastguard Worker {
228*858ea5e5SAndroid Build Coastguard Worker 	unsigned int count = 0;
229*858ea5e5SAndroid Build Coastguard Worker 	const char *ref;
230*858ea5e5SAndroid Build Coastguard Worker 	char msg[256];
231*858ea5e5SAndroid Build Coastguard Worker 	va_list ap;
232*858ea5e5SAndroid Build Coastguard Worker 
233*858ea5e5SAndroid Build Coastguard Worker 	snprintf(msg, sizeof(msg), "ambiguous prefix: '%s' could be '", arg);
234*858ea5e5SAndroid Build Coastguard Worker 	va_start(ap, arg);
235*858ea5e5SAndroid Build Coastguard Worker 	while ((ref = va_arg(ap, const char *))) {
236*858ea5e5SAndroid Build Coastguard Worker 		if (!is_prefix(arg, ref))
237*858ea5e5SAndroid Build Coastguard Worker 			continue;
238*858ea5e5SAndroid Build Coastguard Worker 		count++;
239*858ea5e5SAndroid Build Coastguard Worker 		if (count > 1)
240*858ea5e5SAndroid Build Coastguard Worker 			strncat(msg, "' or '", sizeof(msg) - strlen(msg) - 1);
241*858ea5e5SAndroid Build Coastguard Worker 		strncat(msg, ref, sizeof(msg) - strlen(msg) - 1);
242*858ea5e5SAndroid Build Coastguard Worker 	}
243*858ea5e5SAndroid Build Coastguard Worker 	va_end(ap);
244*858ea5e5SAndroid Build Coastguard Worker 	strncat(msg, "'", sizeof(msg) - strlen(msg) - 1);
245*858ea5e5SAndroid Build Coastguard Worker 
246*858ea5e5SAndroid Build Coastguard Worker 	if (count >= 2) {
247*858ea5e5SAndroid Build Coastguard Worker 		p_err("%s", msg);
248*858ea5e5SAndroid Build Coastguard Worker 		return -1;
249*858ea5e5SAndroid Build Coastguard Worker 	}
250*858ea5e5SAndroid Build Coastguard Worker 
251*858ea5e5SAndroid Build Coastguard Worker 	return 0;
252*858ea5e5SAndroid Build Coastguard Worker }
253*858ea5e5SAndroid Build Coastguard Worker 
fprint_hex(FILE * f,void * arg,unsigned int n,const char * sep)254*858ea5e5SAndroid Build Coastguard Worker void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
255*858ea5e5SAndroid Build Coastguard Worker {
256*858ea5e5SAndroid Build Coastguard Worker 	unsigned char *data = arg;
257*858ea5e5SAndroid Build Coastguard Worker 	unsigned int i;
258*858ea5e5SAndroid Build Coastguard Worker 
259*858ea5e5SAndroid Build Coastguard Worker 	for (i = 0; i < n; i++) {
260*858ea5e5SAndroid Build Coastguard Worker 		const char *pfx = "";
261*858ea5e5SAndroid Build Coastguard Worker 
262*858ea5e5SAndroid Build Coastguard Worker 		if (!i)
263*858ea5e5SAndroid Build Coastguard Worker 			/* nothing */;
264*858ea5e5SAndroid Build Coastguard Worker 		else if (!(i % 16))
265*858ea5e5SAndroid Build Coastguard Worker 			fprintf(f, "\n");
266*858ea5e5SAndroid Build Coastguard Worker 		else if (!(i % 8))
267*858ea5e5SAndroid Build Coastguard Worker 			fprintf(f, "  ");
268*858ea5e5SAndroid Build Coastguard Worker 		else
269*858ea5e5SAndroid Build Coastguard Worker 			pfx = sep;
270*858ea5e5SAndroid Build Coastguard Worker 
271*858ea5e5SAndroid Build Coastguard Worker 		fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
272*858ea5e5SAndroid Build Coastguard Worker 	}
273*858ea5e5SAndroid Build Coastguard Worker }
274*858ea5e5SAndroid Build Coastguard Worker 
275*858ea5e5SAndroid Build Coastguard Worker /* Split command line into argument vector. */
make_args(char * line,char * n_argv[],int maxargs,int cmd_nb)276*858ea5e5SAndroid Build Coastguard Worker static int make_args(char *line, char *n_argv[], int maxargs, int cmd_nb)
277*858ea5e5SAndroid Build Coastguard Worker {
278*858ea5e5SAndroid Build Coastguard Worker 	static const char ws[] = " \t\r\n";
279*858ea5e5SAndroid Build Coastguard Worker 	char *cp = line;
280*858ea5e5SAndroid Build Coastguard Worker 	int n_argc = 0;
281*858ea5e5SAndroid Build Coastguard Worker 
282*858ea5e5SAndroid Build Coastguard Worker 	while (*cp) {
283*858ea5e5SAndroid Build Coastguard Worker 		/* Skip leading whitespace. */
284*858ea5e5SAndroid Build Coastguard Worker 		cp += strspn(cp, ws);
285*858ea5e5SAndroid Build Coastguard Worker 
286*858ea5e5SAndroid Build Coastguard Worker 		if (*cp == '\0')
287*858ea5e5SAndroid Build Coastguard Worker 			break;
288*858ea5e5SAndroid Build Coastguard Worker 
289*858ea5e5SAndroid Build Coastguard Worker 		if (n_argc >= (maxargs - 1)) {
290*858ea5e5SAndroid Build Coastguard Worker 			p_err("too many arguments to command %d", cmd_nb);
291*858ea5e5SAndroid Build Coastguard Worker 			return -1;
292*858ea5e5SAndroid Build Coastguard Worker 		}
293*858ea5e5SAndroid Build Coastguard Worker 
294*858ea5e5SAndroid Build Coastguard Worker 		/* Word begins with quote. */
295*858ea5e5SAndroid Build Coastguard Worker 		if (*cp == '\'' || *cp == '"') {
296*858ea5e5SAndroid Build Coastguard Worker 			char quote = *cp++;
297*858ea5e5SAndroid Build Coastguard Worker 
298*858ea5e5SAndroid Build Coastguard Worker 			n_argv[n_argc++] = cp;
299*858ea5e5SAndroid Build Coastguard Worker 			/* Find ending quote. */
300*858ea5e5SAndroid Build Coastguard Worker 			cp = strchr(cp, quote);
301*858ea5e5SAndroid Build Coastguard Worker 			if (!cp) {
302*858ea5e5SAndroid Build Coastguard Worker 				p_err("unterminated quoted string in command %d",
303*858ea5e5SAndroid Build Coastguard Worker 				      cmd_nb);
304*858ea5e5SAndroid Build Coastguard Worker 				return -1;
305*858ea5e5SAndroid Build Coastguard Worker 			}
306*858ea5e5SAndroid Build Coastguard Worker 		} else {
307*858ea5e5SAndroid Build Coastguard Worker 			n_argv[n_argc++] = cp;
308*858ea5e5SAndroid Build Coastguard Worker 
309*858ea5e5SAndroid Build Coastguard Worker 			/* Find end of word. */
310*858ea5e5SAndroid Build Coastguard Worker 			cp += strcspn(cp, ws);
311*858ea5e5SAndroid Build Coastguard Worker 			if (*cp == '\0')
312*858ea5e5SAndroid Build Coastguard Worker 				break;
313*858ea5e5SAndroid Build Coastguard Worker 		}
314*858ea5e5SAndroid Build Coastguard Worker 
315*858ea5e5SAndroid Build Coastguard Worker 		/* Separate words. */
316*858ea5e5SAndroid Build Coastguard Worker 		*cp++ = 0;
317*858ea5e5SAndroid Build Coastguard Worker 	}
318*858ea5e5SAndroid Build Coastguard Worker 	n_argv[n_argc] = NULL;
319*858ea5e5SAndroid Build Coastguard Worker 
320*858ea5e5SAndroid Build Coastguard Worker 	return n_argc;
321*858ea5e5SAndroid Build Coastguard Worker }
322*858ea5e5SAndroid Build Coastguard Worker 
do_batch(int argc,char ** argv)323*858ea5e5SAndroid Build Coastguard Worker static int do_batch(int argc, char **argv)
324*858ea5e5SAndroid Build Coastguard Worker {
325*858ea5e5SAndroid Build Coastguard Worker 	char buf[BATCH_LINE_LEN_MAX], contline[BATCH_LINE_LEN_MAX];
326*858ea5e5SAndroid Build Coastguard Worker 	char *n_argv[BATCH_ARG_NB_MAX];
327*858ea5e5SAndroid Build Coastguard Worker 	unsigned int lines = 0;
328*858ea5e5SAndroid Build Coastguard Worker 	int n_argc;
329*858ea5e5SAndroid Build Coastguard Worker 	FILE *fp;
330*858ea5e5SAndroid Build Coastguard Worker 	char *cp;
331*858ea5e5SAndroid Build Coastguard Worker 	int err = 0;
332*858ea5e5SAndroid Build Coastguard Worker 	int i;
333*858ea5e5SAndroid Build Coastguard Worker 
334*858ea5e5SAndroid Build Coastguard Worker 	if (argc < 2) {
335*858ea5e5SAndroid Build Coastguard Worker 		p_err("too few parameters for batch");
336*858ea5e5SAndroid Build Coastguard Worker 		return -1;
337*858ea5e5SAndroid Build Coastguard Worker 	} else if (argc > 2) {
338*858ea5e5SAndroid Build Coastguard Worker 		p_err("too many parameters for batch");
339*858ea5e5SAndroid Build Coastguard Worker 		return -1;
340*858ea5e5SAndroid Build Coastguard Worker 	} else if (!is_prefix(*argv, "file")) {
341*858ea5e5SAndroid Build Coastguard Worker 		p_err("expected 'file', got: %s", *argv);
342*858ea5e5SAndroid Build Coastguard Worker 		return -1;
343*858ea5e5SAndroid Build Coastguard Worker 	}
344*858ea5e5SAndroid Build Coastguard Worker 	NEXT_ARG();
345*858ea5e5SAndroid Build Coastguard Worker 
346*858ea5e5SAndroid Build Coastguard Worker 	if (!strcmp(*argv, "-"))
347*858ea5e5SAndroid Build Coastguard Worker 		fp = stdin;
348*858ea5e5SAndroid Build Coastguard Worker 	else
349*858ea5e5SAndroid Build Coastguard Worker 		fp = fopen(*argv, "r");
350*858ea5e5SAndroid Build Coastguard Worker 	if (!fp) {
351*858ea5e5SAndroid Build Coastguard Worker 		p_err("Can't open file (%s): %s", *argv, strerror(errno));
352*858ea5e5SAndroid Build Coastguard Worker 		return -1;
353*858ea5e5SAndroid Build Coastguard Worker 	}
354*858ea5e5SAndroid Build Coastguard Worker 
355*858ea5e5SAndroid Build Coastguard Worker 	if (json_output)
356*858ea5e5SAndroid Build Coastguard Worker 		jsonw_start_array(json_wtr);
357*858ea5e5SAndroid Build Coastguard Worker 	while (fgets(buf, sizeof(buf), fp)) {
358*858ea5e5SAndroid Build Coastguard Worker 		cp = strchr(buf, '#');
359*858ea5e5SAndroid Build Coastguard Worker 		if (cp)
360*858ea5e5SAndroid Build Coastguard Worker 			*cp = '\0';
361*858ea5e5SAndroid Build Coastguard Worker 
362*858ea5e5SAndroid Build Coastguard Worker 		if (strlen(buf) == sizeof(buf) - 1) {
363*858ea5e5SAndroid Build Coastguard Worker 			errno = E2BIG;
364*858ea5e5SAndroid Build Coastguard Worker 			break;
365*858ea5e5SAndroid Build Coastguard Worker 		}
366*858ea5e5SAndroid Build Coastguard Worker 
367*858ea5e5SAndroid Build Coastguard Worker 		/* Append continuation lines if any (coming after a line ending
368*858ea5e5SAndroid Build Coastguard Worker 		 * with '\' in the batch file).
369*858ea5e5SAndroid Build Coastguard Worker 		 */
370*858ea5e5SAndroid Build Coastguard Worker 		while ((cp = strstr(buf, "\\\n")) != NULL) {
371*858ea5e5SAndroid Build Coastguard Worker 			if (!fgets(contline, sizeof(contline), fp) ||
372*858ea5e5SAndroid Build Coastguard Worker 			    strlen(contline) == 0) {
373*858ea5e5SAndroid Build Coastguard Worker 				p_err("missing continuation line on command %d",
374*858ea5e5SAndroid Build Coastguard Worker 				      lines);
375*858ea5e5SAndroid Build Coastguard Worker 				err = -1;
376*858ea5e5SAndroid Build Coastguard Worker 				goto err_close;
377*858ea5e5SAndroid Build Coastguard Worker 			}
378*858ea5e5SAndroid Build Coastguard Worker 
379*858ea5e5SAndroid Build Coastguard Worker 			cp = strchr(contline, '#');
380*858ea5e5SAndroid Build Coastguard Worker 			if (cp)
381*858ea5e5SAndroid Build Coastguard Worker 				*cp = '\0';
382*858ea5e5SAndroid Build Coastguard Worker 
383*858ea5e5SAndroid Build Coastguard Worker 			if (strlen(buf) + strlen(contline) + 1 > sizeof(buf)) {
384*858ea5e5SAndroid Build Coastguard Worker 				p_err("command %d is too long", lines);
385*858ea5e5SAndroid Build Coastguard Worker 				err = -1;
386*858ea5e5SAndroid Build Coastguard Worker 				goto err_close;
387*858ea5e5SAndroid Build Coastguard Worker 			}
388*858ea5e5SAndroid Build Coastguard Worker 			buf[strlen(buf) - 2] = '\0';
389*858ea5e5SAndroid Build Coastguard Worker 			strcat(buf, contline);
390*858ea5e5SAndroid Build Coastguard Worker 		}
391*858ea5e5SAndroid Build Coastguard Worker 
392*858ea5e5SAndroid Build Coastguard Worker 		n_argc = make_args(buf, n_argv, BATCH_ARG_NB_MAX, lines);
393*858ea5e5SAndroid Build Coastguard Worker 		if (!n_argc)
394*858ea5e5SAndroid Build Coastguard Worker 			continue;
395*858ea5e5SAndroid Build Coastguard Worker 		if (n_argc < 0) {
396*858ea5e5SAndroid Build Coastguard Worker 			err = n_argc;
397*858ea5e5SAndroid Build Coastguard Worker 			goto err_close;
398*858ea5e5SAndroid Build Coastguard Worker 		}
399*858ea5e5SAndroid Build Coastguard Worker 
400*858ea5e5SAndroid Build Coastguard Worker 		if (json_output) {
401*858ea5e5SAndroid Build Coastguard Worker 			jsonw_start_object(json_wtr);
402*858ea5e5SAndroid Build Coastguard Worker 			jsonw_name(json_wtr, "command");
403*858ea5e5SAndroid Build Coastguard Worker 			jsonw_start_array(json_wtr);
404*858ea5e5SAndroid Build Coastguard Worker 			for (i = 0; i < n_argc; i++)
405*858ea5e5SAndroid Build Coastguard Worker 				jsonw_string(json_wtr, n_argv[i]);
406*858ea5e5SAndroid Build Coastguard Worker 			jsonw_end_array(json_wtr);
407*858ea5e5SAndroid Build Coastguard Worker 			jsonw_name(json_wtr, "output");
408*858ea5e5SAndroid Build Coastguard Worker 		}
409*858ea5e5SAndroid Build Coastguard Worker 
410*858ea5e5SAndroid Build Coastguard Worker 		err = cmd_select(commands, n_argc, n_argv, do_help);
411*858ea5e5SAndroid Build Coastguard Worker 
412*858ea5e5SAndroid Build Coastguard Worker 		if (json_output)
413*858ea5e5SAndroid Build Coastguard Worker 			jsonw_end_object(json_wtr);
414*858ea5e5SAndroid Build Coastguard Worker 
415*858ea5e5SAndroid Build Coastguard Worker 		if (err)
416*858ea5e5SAndroid Build Coastguard Worker 			goto err_close;
417*858ea5e5SAndroid Build Coastguard Worker 
418*858ea5e5SAndroid Build Coastguard Worker 		lines++;
419*858ea5e5SAndroid Build Coastguard Worker 	}
420*858ea5e5SAndroid Build Coastguard Worker 
421*858ea5e5SAndroid Build Coastguard Worker 	if (errno && errno != ENOENT) {
422*858ea5e5SAndroid Build Coastguard Worker 		p_err("reading batch file failed: %s", strerror(errno));
423*858ea5e5SAndroid Build Coastguard Worker 		err = -1;
424*858ea5e5SAndroid Build Coastguard Worker 	} else {
425*858ea5e5SAndroid Build Coastguard Worker 		if (!json_output)
426*858ea5e5SAndroid Build Coastguard Worker 			printf("processed %d commands\n", lines);
427*858ea5e5SAndroid Build Coastguard Worker 	}
428*858ea5e5SAndroid Build Coastguard Worker err_close:
429*858ea5e5SAndroid Build Coastguard Worker 	if (fp != stdin)
430*858ea5e5SAndroid Build Coastguard Worker 		fclose(fp);
431*858ea5e5SAndroid Build Coastguard Worker 
432*858ea5e5SAndroid Build Coastguard Worker 	if (json_output)
433*858ea5e5SAndroid Build Coastguard Worker 		jsonw_end_array(json_wtr);
434*858ea5e5SAndroid Build Coastguard Worker 
435*858ea5e5SAndroid Build Coastguard Worker 	return err;
436*858ea5e5SAndroid Build Coastguard Worker }
437*858ea5e5SAndroid Build Coastguard Worker 
main(int argc,char ** argv)438*858ea5e5SAndroid Build Coastguard Worker int main(int argc, char **argv)
439*858ea5e5SAndroid Build Coastguard Worker {
440*858ea5e5SAndroid Build Coastguard Worker 	static const struct option options[] = {
441*858ea5e5SAndroid Build Coastguard Worker 		{ "json",	no_argument,	NULL,	'j' },
442*858ea5e5SAndroid Build Coastguard Worker 		{ "help",	no_argument,	NULL,	'h' },
443*858ea5e5SAndroid Build Coastguard Worker 		{ "pretty",	no_argument,	NULL,	'p' },
444*858ea5e5SAndroid Build Coastguard Worker 		{ "version",	no_argument,	NULL,	'V' },
445*858ea5e5SAndroid Build Coastguard Worker 		{ "bpffs",	no_argument,	NULL,	'f' },
446*858ea5e5SAndroid Build Coastguard Worker 		{ "mapcompat",	no_argument,	NULL,	'm' },
447*858ea5e5SAndroid Build Coastguard Worker 		{ "nomount",	no_argument,	NULL,	'n' },
448*858ea5e5SAndroid Build Coastguard Worker 		{ "debug",	no_argument,	NULL,	'd' },
449*858ea5e5SAndroid Build Coastguard Worker 		{ "use-loader",	no_argument,	NULL,	'L' },
450*858ea5e5SAndroid Build Coastguard Worker 		{ "base-btf",	required_argument, NULL, 'B' },
451*858ea5e5SAndroid Build Coastguard Worker 		{ 0 }
452*858ea5e5SAndroid Build Coastguard Worker 	};
453*858ea5e5SAndroid Build Coastguard Worker 	bool version_requested = false;
454*858ea5e5SAndroid Build Coastguard Worker 	int opt, ret;
455*858ea5e5SAndroid Build Coastguard Worker 
456*858ea5e5SAndroid Build Coastguard Worker 	setlinebuf(stdout);
457*858ea5e5SAndroid Build Coastguard Worker 
458*858ea5e5SAndroid Build Coastguard Worker #ifdef USE_LIBCAP
459*858ea5e5SAndroid Build Coastguard Worker 	/* Libcap < 2.63 hooks before main() to compute the number of
460*858ea5e5SAndroid Build Coastguard Worker 	 * capabilities of the running kernel, and doing so it calls prctl()
461*858ea5e5SAndroid Build Coastguard Worker 	 * which may fail and set errno to non-zero.
462*858ea5e5SAndroid Build Coastguard Worker 	 * Let's reset errno to make sure this does not interfere with the
463*858ea5e5SAndroid Build Coastguard Worker 	 * batch mode.
464*858ea5e5SAndroid Build Coastguard Worker 	 */
465*858ea5e5SAndroid Build Coastguard Worker 	errno = 0;
466*858ea5e5SAndroid Build Coastguard Worker #endif
467*858ea5e5SAndroid Build Coastguard Worker 
468*858ea5e5SAndroid Build Coastguard Worker 	last_do_help = do_help;
469*858ea5e5SAndroid Build Coastguard Worker 	pretty_output = false;
470*858ea5e5SAndroid Build Coastguard Worker 	json_output = false;
471*858ea5e5SAndroid Build Coastguard Worker 	show_pinned = false;
472*858ea5e5SAndroid Build Coastguard Worker 	block_mount = false;
473*858ea5e5SAndroid Build Coastguard Worker 	bin_name = "bpftool";
474*858ea5e5SAndroid Build Coastguard Worker 
475*858ea5e5SAndroid Build Coastguard Worker 	opterr = 0;
476*858ea5e5SAndroid Build Coastguard Worker 	while ((opt = getopt_long(argc, argv, "VhpjfLmndB:l",
477*858ea5e5SAndroid Build Coastguard Worker 				  options, NULL)) >= 0) {
478*858ea5e5SAndroid Build Coastguard Worker 		switch (opt) {
479*858ea5e5SAndroid Build Coastguard Worker 		case 'V':
480*858ea5e5SAndroid Build Coastguard Worker 			version_requested = true;
481*858ea5e5SAndroid Build Coastguard Worker 			break;
482*858ea5e5SAndroid Build Coastguard Worker 		case 'h':
483*858ea5e5SAndroid Build Coastguard Worker 			return do_help(argc, argv);
484*858ea5e5SAndroid Build Coastguard Worker 		case 'p':
485*858ea5e5SAndroid Build Coastguard Worker 			pretty_output = true;
486*858ea5e5SAndroid Build Coastguard Worker 			/* fall through */
487*858ea5e5SAndroid Build Coastguard Worker 		case 'j':
488*858ea5e5SAndroid Build Coastguard Worker 			if (!json_output) {
489*858ea5e5SAndroid Build Coastguard Worker 				json_wtr = jsonw_new(stdout);
490*858ea5e5SAndroid Build Coastguard Worker 				if (!json_wtr) {
491*858ea5e5SAndroid Build Coastguard Worker 					p_err("failed to create JSON writer");
492*858ea5e5SAndroid Build Coastguard Worker 					return -1;
493*858ea5e5SAndroid Build Coastguard Worker 				}
494*858ea5e5SAndroid Build Coastguard Worker 				json_output = true;
495*858ea5e5SAndroid Build Coastguard Worker 			}
496*858ea5e5SAndroid Build Coastguard Worker 			jsonw_pretty(json_wtr, pretty_output);
497*858ea5e5SAndroid Build Coastguard Worker 			break;
498*858ea5e5SAndroid Build Coastguard Worker 		case 'f':
499*858ea5e5SAndroid Build Coastguard Worker 			show_pinned = true;
500*858ea5e5SAndroid Build Coastguard Worker 			break;
501*858ea5e5SAndroid Build Coastguard Worker 		case 'm':
502*858ea5e5SAndroid Build Coastguard Worker 			relaxed_maps = true;
503*858ea5e5SAndroid Build Coastguard Worker 			break;
504*858ea5e5SAndroid Build Coastguard Worker 		case 'n':
505*858ea5e5SAndroid Build Coastguard Worker 			block_mount = true;
506*858ea5e5SAndroid Build Coastguard Worker 			break;
507*858ea5e5SAndroid Build Coastguard Worker 		case 'd':
508*858ea5e5SAndroid Build Coastguard Worker 			libbpf_set_print(print_all_levels);
509*858ea5e5SAndroid Build Coastguard Worker 			verifier_logs = true;
510*858ea5e5SAndroid Build Coastguard Worker 			break;
511*858ea5e5SAndroid Build Coastguard Worker 		case 'B':
512*858ea5e5SAndroid Build Coastguard Worker 			base_btf = btf__parse(optarg, NULL);
513*858ea5e5SAndroid Build Coastguard Worker 			if (!base_btf) {
514*858ea5e5SAndroid Build Coastguard Worker 				p_err("failed to parse base BTF at '%s': %d\n",
515*858ea5e5SAndroid Build Coastguard Worker 				      optarg, -errno);
516*858ea5e5SAndroid Build Coastguard Worker 				return -1;
517*858ea5e5SAndroid Build Coastguard Worker 			}
518*858ea5e5SAndroid Build Coastguard Worker 			break;
519*858ea5e5SAndroid Build Coastguard Worker 		case 'L':
520*858ea5e5SAndroid Build Coastguard Worker 			use_loader = true;
521*858ea5e5SAndroid Build Coastguard Worker 			break;
522*858ea5e5SAndroid Build Coastguard Worker 		default:
523*858ea5e5SAndroid Build Coastguard Worker 			p_err("unrecognized option '%s'", argv[optind - 1]);
524*858ea5e5SAndroid Build Coastguard Worker 			if (json_output)
525*858ea5e5SAndroid Build Coastguard Worker 				clean_and_exit(-1);
526*858ea5e5SAndroid Build Coastguard Worker 			else
527*858ea5e5SAndroid Build Coastguard Worker 				usage();
528*858ea5e5SAndroid Build Coastguard Worker 		}
529*858ea5e5SAndroid Build Coastguard Worker 	}
530*858ea5e5SAndroid Build Coastguard Worker 
531*858ea5e5SAndroid Build Coastguard Worker 	argc -= optind;
532*858ea5e5SAndroid Build Coastguard Worker 	argv += optind;
533*858ea5e5SAndroid Build Coastguard Worker 	if (argc < 0)
534*858ea5e5SAndroid Build Coastguard Worker 		usage();
535*858ea5e5SAndroid Build Coastguard Worker 
536*858ea5e5SAndroid Build Coastguard Worker 	if (version_requested)
537*858ea5e5SAndroid Build Coastguard Worker 		return do_version(argc, argv);
538*858ea5e5SAndroid Build Coastguard Worker 
539*858ea5e5SAndroid Build Coastguard Worker 	ret = cmd_select(commands, argc, argv, do_help);
540*858ea5e5SAndroid Build Coastguard Worker 
541*858ea5e5SAndroid Build Coastguard Worker 	if (json_output)
542*858ea5e5SAndroid Build Coastguard Worker 		jsonw_destroy(&json_wtr);
543*858ea5e5SAndroid Build Coastguard Worker 
544*858ea5e5SAndroid Build Coastguard Worker 	btf__free(base_btf);
545*858ea5e5SAndroid Build Coastguard Worker 
546*858ea5e5SAndroid Build Coastguard Worker 	return ret;
547*858ea5e5SAndroid Build Coastguard Worker }
548