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