OSDN Git Service

clk: at91: fix masterck name
[uclinux-h8/linux.git] / tools / bpf / bpftool / prog.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3
4 #define _GNU_SOURCE
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12 #include <unistd.h>
13 #include <net/if.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16
17 #include <linux/err.h>
18
19 #include <bpf.h>
20 #include <btf.h>
21 #include <libbpf.h>
22
23 #include "cfg.h"
24 #include "main.h"
25 #include "xlated_dumper.h"
26
27 static const char * const attach_type_strings[] = {
28         [BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
29         [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
30         [BPF_SK_MSG_VERDICT] = "msg_verdict",
31         [BPF_FLOW_DISSECTOR] = "flow_dissector",
32         [__MAX_BPF_ATTACH_TYPE] = NULL,
33 };
34
35 static enum bpf_attach_type parse_attach_type(const char *str)
36 {
37         enum bpf_attach_type type;
38
39         for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
40                 if (attach_type_strings[type] &&
41                     is_prefix(str, attach_type_strings[type]))
42                         return type;
43         }
44
45         return __MAX_BPF_ATTACH_TYPE;
46 }
47
48 static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
49 {
50         struct timespec real_time_ts, boot_time_ts;
51         time_t wallclock_secs;
52         struct tm load_tm;
53
54         buf[--size] = '\0';
55
56         if (clock_gettime(CLOCK_REALTIME, &real_time_ts) ||
57             clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) {
58                 perror("Can't read clocks");
59                 snprintf(buf, size, "%llu", nsecs / 1000000000);
60                 return;
61         }
62
63         wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
64                 (real_time_ts.tv_nsec - boot_time_ts.tv_nsec + nsecs) /
65                 1000000000;
66
67
68         if (!localtime_r(&wallclock_secs, &load_tm)) {
69                 snprintf(buf, size, "%llu", nsecs / 1000000000);
70                 return;
71         }
72
73         if (json_output)
74                 strftime(buf, size, "%s", &load_tm);
75         else
76                 strftime(buf, size, "%FT%T%z", &load_tm);
77 }
78
79 static int prog_fd_by_tag(unsigned char *tag)
80 {
81         struct bpf_prog_info info = {};
82         __u32 len = sizeof(info);
83         unsigned int id = 0;
84         int err;
85         int fd;
86
87         while (true) {
88                 err = bpf_prog_get_next_id(id, &id);
89                 if (err) {
90                         p_err("%s", strerror(errno));
91                         return -1;
92                 }
93
94                 fd = bpf_prog_get_fd_by_id(id);
95                 if (fd < 0) {
96                         p_err("can't get prog by id (%u): %s",
97                               id, strerror(errno));
98                         return -1;
99                 }
100
101                 err = bpf_obj_get_info_by_fd(fd, &info, &len);
102                 if (err) {
103                         p_err("can't get prog info (%u): %s",
104                               id, strerror(errno));
105                         close(fd);
106                         return -1;
107                 }
108
109                 if (!memcmp(tag, info.tag, BPF_TAG_SIZE))
110                         return fd;
111
112                 close(fd);
113         }
114 }
115
116 int prog_parse_fd(int *argc, char ***argv)
117 {
118         int fd;
119
120         if (is_prefix(**argv, "id")) {
121                 unsigned int id;
122                 char *endptr;
123
124                 NEXT_ARGP();
125
126                 id = strtoul(**argv, &endptr, 0);
127                 if (*endptr) {
128                         p_err("can't parse %s as ID", **argv);
129                         return -1;
130                 }
131                 NEXT_ARGP();
132
133                 fd = bpf_prog_get_fd_by_id(id);
134                 if (fd < 0)
135                         p_err("get by id (%u): %s", id, strerror(errno));
136                 return fd;
137         } else if (is_prefix(**argv, "tag")) {
138                 unsigned char tag[BPF_TAG_SIZE];
139
140                 NEXT_ARGP();
141
142                 if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2,
143                            tag + 3, tag + 4, tag + 5, tag + 6, tag + 7)
144                     != BPF_TAG_SIZE) {
145                         p_err("can't parse tag");
146                         return -1;
147                 }
148                 NEXT_ARGP();
149
150                 return prog_fd_by_tag(tag);
151         } else if (is_prefix(**argv, "pinned")) {
152                 char *path;
153
154                 NEXT_ARGP();
155
156                 path = **argv;
157                 NEXT_ARGP();
158
159                 return open_obj_pinned_any(path, BPF_OBJ_PROG);
160         }
161
162         p_err("expected 'id', 'tag' or 'pinned', got: '%s'?", **argv);
163         return -1;
164 }
165
166 static void show_prog_maps(int fd, u32 num_maps)
167 {
168         struct bpf_prog_info info = {};
169         __u32 len = sizeof(info);
170         __u32 map_ids[num_maps];
171         unsigned int i;
172         int err;
173
174         info.nr_map_ids = num_maps;
175         info.map_ids = ptr_to_u64(map_ids);
176
177         err = bpf_obj_get_info_by_fd(fd, &info, &len);
178         if (err || !info.nr_map_ids)
179                 return;
180
181         if (json_output) {
182                 jsonw_name(json_wtr, "map_ids");
183                 jsonw_start_array(json_wtr);
184                 for (i = 0; i < info.nr_map_ids; i++)
185                         jsonw_uint(json_wtr, map_ids[i]);
186                 jsonw_end_array(json_wtr);
187         } else {
188                 printf("  map_ids ");
189                 for (i = 0; i < info.nr_map_ids; i++)
190                         printf("%u%s", map_ids[i],
191                                i == info.nr_map_ids - 1 ? "" : ",");
192         }
193 }
194
195 static void print_prog_json(struct bpf_prog_info *info, int fd)
196 {
197         char *memlock;
198
199         jsonw_start_object(json_wtr);
200         jsonw_uint_field(json_wtr, "id", info->id);
201         if (info->type < ARRAY_SIZE(prog_type_name))
202                 jsonw_string_field(json_wtr, "type",
203                                    prog_type_name[info->type]);
204         else
205                 jsonw_uint_field(json_wtr, "type", info->type);
206
207         if (*info->name)
208                 jsonw_string_field(json_wtr, "name", info->name);
209
210         jsonw_name(json_wtr, "tag");
211         jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"",
212                      info->tag[0], info->tag[1], info->tag[2], info->tag[3],
213                      info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
214
215         jsonw_bool_field(json_wtr, "gpl_compatible", info->gpl_compatible);
216
217         print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
218
219         if (info->load_time) {
220                 char buf[32];
221
222                 print_boot_time(info->load_time, buf, sizeof(buf));
223
224                 /* Piggy back on load_time, since 0 uid is a valid one */
225                 jsonw_name(json_wtr, "loaded_at");
226                 jsonw_printf(json_wtr, "%s", buf);
227                 jsonw_uint_field(json_wtr, "uid", info->created_by_uid);
228         }
229
230         jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len);
231
232         if (info->jited_prog_len) {
233                 jsonw_bool_field(json_wtr, "jited", true);
234                 jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len);
235         } else {
236                 jsonw_bool_field(json_wtr, "jited", false);
237         }
238
239         memlock = get_fdinfo(fd, "memlock");
240         if (memlock)
241                 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
242         free(memlock);
243
244         if (info->nr_map_ids)
245                 show_prog_maps(fd, info->nr_map_ids);
246
247         if (!hash_empty(prog_table.table)) {
248                 struct pinned_obj *obj;
249
250                 jsonw_name(json_wtr, "pinned");
251                 jsonw_start_array(json_wtr);
252                 hash_for_each_possible(prog_table.table, obj, hash, info->id) {
253                         if (obj->id == info->id)
254                                 jsonw_string(json_wtr, obj->path);
255                 }
256                 jsonw_end_array(json_wtr);
257         }
258
259         jsonw_end_object(json_wtr);
260 }
261
262 static void print_prog_plain(struct bpf_prog_info *info, int fd)
263 {
264         char *memlock;
265
266         printf("%u: ", info->id);
267         if (info->type < ARRAY_SIZE(prog_type_name))
268                 printf("%s  ", prog_type_name[info->type]);
269         else
270                 printf("type %u  ", info->type);
271
272         if (*info->name)
273                 printf("name %s  ", info->name);
274
275         printf("tag ");
276         fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
277         print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
278         printf("%s", info->gpl_compatible ? "  gpl" : "");
279         printf("\n");
280
281         if (info->load_time) {
282                 char buf[32];
283
284                 print_boot_time(info->load_time, buf, sizeof(buf));
285
286                 /* Piggy back on load_time, since 0 uid is a valid one */
287                 printf("\tloaded_at %s  uid %u\n", buf, info->created_by_uid);
288         }
289
290         printf("\txlated %uB", info->xlated_prog_len);
291
292         if (info->jited_prog_len)
293                 printf("  jited %uB", info->jited_prog_len);
294         else
295                 printf("  not jited");
296
297         memlock = get_fdinfo(fd, "memlock");
298         if (memlock)
299                 printf("  memlock %sB", memlock);
300         free(memlock);
301
302         if (info->nr_map_ids)
303                 show_prog_maps(fd, info->nr_map_ids);
304
305         if (!hash_empty(prog_table.table)) {
306                 struct pinned_obj *obj;
307
308                 hash_for_each_possible(prog_table.table, obj, hash, info->id) {
309                         if (obj->id == info->id)
310                                 printf("\n\tpinned %s", obj->path);
311                 }
312         }
313
314         printf("\n");
315 }
316
317 static int show_prog(int fd)
318 {
319         struct bpf_prog_info info = {};
320         __u32 len = sizeof(info);
321         int err;
322
323         err = bpf_obj_get_info_by_fd(fd, &info, &len);
324         if (err) {
325                 p_err("can't get prog info: %s", strerror(errno));
326                 return -1;
327         }
328
329         if (json_output)
330                 print_prog_json(&info, fd);
331         else
332                 print_prog_plain(&info, fd);
333
334         return 0;
335 }
336
337 static int do_show(int argc, char **argv)
338 {
339         __u32 id = 0;
340         int err;
341         int fd;
342
343         if (show_pinned)
344                 build_pinned_obj_table(&prog_table, BPF_OBJ_PROG);
345
346         if (argc == 2) {
347                 fd = prog_parse_fd(&argc, &argv);
348                 if (fd < 0)
349                         return -1;
350
351                 return show_prog(fd);
352         }
353
354         if (argc)
355                 return BAD_ARG();
356
357         if (json_output)
358                 jsonw_start_array(json_wtr);
359         while (true) {
360                 err = bpf_prog_get_next_id(id, &id);
361                 if (err) {
362                         if (errno == ENOENT) {
363                                 err = 0;
364                                 break;
365                         }
366                         p_err("can't get next program: %s%s", strerror(errno),
367                               errno == EINVAL ? " -- kernel too old?" : "");
368                         err = -1;
369                         break;
370                 }
371
372                 fd = bpf_prog_get_fd_by_id(id);
373                 if (fd < 0) {
374                         if (errno == ENOENT)
375                                 continue;
376                         p_err("can't get prog by id (%u): %s",
377                               id, strerror(errno));
378                         err = -1;
379                         break;
380                 }
381
382                 err = show_prog(fd);
383                 close(fd);
384                 if (err)
385                         break;
386         }
387
388         if (json_output)
389                 jsonw_end_array(json_wtr);
390
391         return err;
392 }
393
394 static int do_dump(int argc, char **argv)
395 {
396         unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size;
397         void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL;
398         unsigned int nr_finfo, nr_linfo = 0, nr_jited_linfo = 0;
399         struct bpf_prog_linfo *prog_linfo = NULL;
400         unsigned long *func_ksyms = NULL;
401         struct bpf_prog_info info = {};
402         unsigned int *func_lens = NULL;
403         const char *disasm_opt = NULL;
404         unsigned int nr_func_ksyms;
405         unsigned int nr_func_lens;
406         struct dump_data dd = {};
407         __u32 len = sizeof(info);
408         struct btf *btf = NULL;
409         unsigned int buf_size;
410         char *filepath = NULL;
411         bool opcodes = false;
412         bool visual = false;
413         char func_sig[1024];
414         unsigned char *buf;
415         bool linum = false;
416         __u32 *member_len;
417         __u64 *member_ptr;
418         ssize_t n;
419         int err;
420         int fd;
421
422         if (is_prefix(*argv, "jited")) {
423                 if (disasm_init())
424                         return -1;
425
426                 member_len = &info.jited_prog_len;
427                 member_ptr = &info.jited_prog_insns;
428         } else if (is_prefix(*argv, "xlated")) {
429                 member_len = &info.xlated_prog_len;
430                 member_ptr = &info.xlated_prog_insns;
431         } else {
432                 p_err("expected 'xlated' or 'jited', got: %s", *argv);
433                 return -1;
434         }
435         NEXT_ARG();
436
437         if (argc < 2)
438                 usage();
439
440         fd = prog_parse_fd(&argc, &argv);
441         if (fd < 0)
442                 return -1;
443
444         if (is_prefix(*argv, "file")) {
445                 NEXT_ARG();
446                 if (!argc) {
447                         p_err("expected file path");
448                         return -1;
449                 }
450
451                 filepath = *argv;
452                 NEXT_ARG();
453         } else if (is_prefix(*argv, "opcodes")) {
454                 opcodes = true;
455                 NEXT_ARG();
456         } else if (is_prefix(*argv, "visual")) {
457                 visual = true;
458                 NEXT_ARG();
459         } else if (is_prefix(*argv, "linum")) {
460                 linum = true;
461                 NEXT_ARG();
462         }
463
464         if (argc) {
465                 usage();
466                 return -1;
467         }
468
469         err = bpf_obj_get_info_by_fd(fd, &info, &len);
470         if (err) {
471                 p_err("can't get prog info: %s", strerror(errno));
472                 return -1;
473         }
474
475         if (!*member_len) {
476                 p_info("no instructions returned");
477                 close(fd);
478                 return 0;
479         }
480
481         buf_size = *member_len;
482
483         buf = malloc(buf_size);
484         if (!buf) {
485                 p_err("mem alloc failed");
486                 close(fd);
487                 return -1;
488         }
489
490         nr_func_ksyms = info.nr_jited_ksyms;
491         if (nr_func_ksyms) {
492                 func_ksyms = malloc(nr_func_ksyms * sizeof(__u64));
493                 if (!func_ksyms) {
494                         p_err("mem alloc failed");
495                         close(fd);
496                         goto err_free;
497                 }
498         }
499
500         nr_func_lens = info.nr_jited_func_lens;
501         if (nr_func_lens) {
502                 func_lens = malloc(nr_func_lens * sizeof(__u32));
503                 if (!func_lens) {
504                         p_err("mem alloc failed");
505                         close(fd);
506                         goto err_free;
507                 }
508         }
509
510         nr_finfo = info.nr_func_info;
511         finfo_rec_size = info.func_info_rec_size;
512         if (nr_finfo && finfo_rec_size) {
513                 func_info = malloc(nr_finfo * finfo_rec_size);
514                 if (!func_info) {
515                         p_err("mem alloc failed");
516                         close(fd);
517                         goto err_free;
518                 }
519         }
520
521         linfo_rec_size = info.line_info_rec_size;
522         if (info.nr_line_info && linfo_rec_size && info.btf_id) {
523                 nr_linfo = info.nr_line_info;
524                 linfo = malloc(nr_linfo * linfo_rec_size);
525                 if (!linfo) {
526                         p_err("mem alloc failed");
527                         close(fd);
528                         goto err_free;
529                 }
530         }
531
532         jited_linfo_rec_size = info.jited_line_info_rec_size;
533         if (info.nr_jited_line_info &&
534             jited_linfo_rec_size &&
535             info.nr_jited_ksyms &&
536             info.nr_jited_func_lens &&
537             info.btf_id) {
538                 nr_jited_linfo = info.nr_jited_line_info;
539                 jited_linfo = malloc(nr_jited_linfo * jited_linfo_rec_size);
540                 if (!jited_linfo) {
541                         p_err("mem alloc failed");
542                         close(fd);
543                         goto err_free;
544                 }
545         }
546
547         memset(&info, 0, sizeof(info));
548
549         *member_ptr = ptr_to_u64(buf);
550         *member_len = buf_size;
551         info.jited_ksyms = ptr_to_u64(func_ksyms);
552         info.nr_jited_ksyms = nr_func_ksyms;
553         info.jited_func_lens = ptr_to_u64(func_lens);
554         info.nr_jited_func_lens = nr_func_lens;
555         info.nr_func_info = nr_finfo;
556         info.func_info_rec_size = finfo_rec_size;
557         info.func_info = ptr_to_u64(func_info);
558         info.nr_line_info = nr_linfo;
559         info.line_info_rec_size = linfo_rec_size;
560         info.line_info = ptr_to_u64(linfo);
561         info.nr_jited_line_info = nr_jited_linfo;
562         info.jited_line_info_rec_size = jited_linfo_rec_size;
563         info.jited_line_info = ptr_to_u64(jited_linfo);
564
565         err = bpf_obj_get_info_by_fd(fd, &info, &len);
566         close(fd);
567         if (err) {
568                 p_err("can't get prog info: %s", strerror(errno));
569                 goto err_free;
570         }
571
572         if (*member_len > buf_size) {
573                 p_err("too many instructions returned");
574                 goto err_free;
575         }
576
577         if (info.nr_jited_ksyms > nr_func_ksyms) {
578                 p_err("too many addresses returned");
579                 goto err_free;
580         }
581
582         if (info.nr_jited_func_lens > nr_func_lens) {
583                 p_err("too many values returned");
584                 goto err_free;
585         }
586
587         if (info.nr_func_info != nr_finfo) {
588                 p_err("incorrect nr_func_info %d vs. expected %d",
589                       info.nr_func_info, nr_finfo);
590                 goto err_free;
591         }
592
593         if (info.func_info_rec_size != finfo_rec_size) {
594                 p_err("incorrect func_info_rec_size %d vs. expected %d",
595                       info.func_info_rec_size, finfo_rec_size);
596                 goto err_free;
597         }
598
599         if (linfo && info.nr_line_info != nr_linfo) {
600                 p_err("incorrect nr_line_info %u vs. expected %u",
601                       info.nr_line_info, nr_linfo);
602                 goto err_free;
603         }
604
605         if (info.line_info_rec_size != linfo_rec_size) {
606                 p_err("incorrect line_info_rec_size %u vs. expected %u",
607                       info.line_info_rec_size, linfo_rec_size);
608                 goto err_free;
609         }
610
611         if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) {
612                 p_err("incorrect nr_jited_line_info %u vs. expected %u",
613                       info.nr_jited_line_info, nr_jited_linfo);
614                 goto err_free;
615         }
616
617         if (info.jited_line_info_rec_size != jited_linfo_rec_size) {
618                 p_err("incorrect jited_line_info_rec_size %u vs. expected %u",
619                       info.jited_line_info_rec_size, jited_linfo_rec_size);
620                 goto err_free;
621         }
622
623         if ((member_len == &info.jited_prog_len &&
624              info.jited_prog_insns == 0) ||
625             (member_len == &info.xlated_prog_len &&
626              info.xlated_prog_insns == 0)) {
627                 p_err("error retrieving insn dump: kernel.kptr_restrict set?");
628                 goto err_free;
629         }
630
631         if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) {
632                 p_err("failed to get btf");
633                 goto err_free;
634         }
635
636         if (nr_linfo) {
637                 prog_linfo = bpf_prog_linfo__new(&info);
638                 if (!prog_linfo)
639                         p_info("error in processing bpf_line_info.  continue without it.");
640         }
641
642         if (filepath) {
643                 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
644                 if (fd < 0) {
645                         p_err("can't open file %s: %s", filepath,
646                               strerror(errno));
647                         goto err_free;
648                 }
649
650                 n = write(fd, buf, *member_len);
651                 close(fd);
652                 if (n != *member_len) {
653                         p_err("error writing output file: %s",
654                               n < 0 ? strerror(errno) : "short write");
655                         goto err_free;
656                 }
657
658                 if (json_output)
659                         jsonw_null(json_wtr);
660         } else if (member_len == &info.jited_prog_len) {
661                 const char *name = NULL;
662
663                 if (info.ifindex) {
664                         name = ifindex_to_bfd_params(info.ifindex,
665                                                      info.netns_dev,
666                                                      info.netns_ino,
667                                                      &disasm_opt);
668                         if (!name)
669                                 goto err_free;
670                 }
671
672                 if (info.nr_jited_func_lens && info.jited_func_lens) {
673                         struct kernel_sym *sym = NULL;
674                         struct bpf_func_info *record;
675                         char sym_name[SYM_MAX_NAME];
676                         unsigned char *img = buf;
677                         __u64 *ksyms = NULL;
678                         __u32 *lens;
679                         __u32 i;
680
681                         if (info.nr_jited_ksyms) {
682                                 kernel_syms_load(&dd);
683                                 ksyms = (__u64 *) info.jited_ksyms;
684                         }
685
686                         if (json_output)
687                                 jsonw_start_array(json_wtr);
688
689                         lens = (__u32 *) info.jited_func_lens;
690                         for (i = 0; i < info.nr_jited_func_lens; i++) {
691                                 if (ksyms) {
692                                         sym = kernel_syms_search(&dd, ksyms[i]);
693                                         if (sym)
694                                                 sprintf(sym_name, "%s", sym->name);
695                                         else
696                                                 sprintf(sym_name, "0x%016llx", ksyms[i]);
697                                 } else {
698                                         strcpy(sym_name, "unknown");
699                                 }
700
701                                 if (func_info) {
702                                         record = func_info + i * finfo_rec_size;
703                                         btf_dumper_type_only(btf, record->type_id,
704                                                              func_sig,
705                                                              sizeof(func_sig));
706                                 }
707
708                                 if (json_output) {
709                                         jsonw_start_object(json_wtr);
710                                         if (func_info && func_sig[0] != '\0') {
711                                                 jsonw_name(json_wtr, "proto");
712                                                 jsonw_string(json_wtr, func_sig);
713                                         }
714                                         jsonw_name(json_wtr, "name");
715                                         jsonw_string(json_wtr, sym_name);
716                                         jsonw_name(json_wtr, "insns");
717                                 } else {
718                                         if (func_info && func_sig[0] != '\0')
719                                                 printf("%s:\n", func_sig);
720                                         printf("%s:\n", sym_name);
721                                 }
722
723                                 disasm_print_insn(img, lens[i], opcodes,
724                                                   name, disasm_opt, btf,
725                                                   prog_linfo, ksyms[i], i,
726                                                   linum);
727
728                                 img += lens[i];
729
730                                 if (json_output)
731                                         jsonw_end_object(json_wtr);
732                                 else
733                                         printf("\n");
734                         }
735
736                         if (json_output)
737                                 jsonw_end_array(json_wtr);
738                 } else {
739                         disasm_print_insn(buf, *member_len, opcodes, name,
740                                           disasm_opt, btf, NULL, 0, 0, false);
741                 }
742         } else if (visual) {
743                 if (json_output)
744                         jsonw_null(json_wtr);
745                 else
746                         dump_xlated_cfg(buf, *member_len);
747         } else {
748                 kernel_syms_load(&dd);
749                 dd.nr_jited_ksyms = info.nr_jited_ksyms;
750                 dd.jited_ksyms = (__u64 *) info.jited_ksyms;
751                 dd.btf = btf;
752                 dd.func_info = func_info;
753                 dd.finfo_rec_size = finfo_rec_size;
754                 dd.prog_linfo = prog_linfo;
755
756                 if (json_output)
757                         dump_xlated_json(&dd, buf, *member_len, opcodes,
758                                          linum);
759                 else
760                         dump_xlated_plain(&dd, buf, *member_len, opcodes,
761                                           linum);
762                 kernel_syms_destroy(&dd);
763         }
764
765         free(buf);
766         free(func_ksyms);
767         free(func_lens);
768         free(func_info);
769         free(linfo);
770         free(jited_linfo);
771         bpf_prog_linfo__free(prog_linfo);
772         return 0;
773
774 err_free:
775         free(buf);
776         free(func_ksyms);
777         free(func_lens);
778         free(func_info);
779         free(linfo);
780         free(jited_linfo);
781         bpf_prog_linfo__free(prog_linfo);
782         return -1;
783 }
784
785 static int do_pin(int argc, char **argv)
786 {
787         int err;
788
789         err = do_pin_any(argc, argv, bpf_prog_get_fd_by_id);
790         if (!err && json_output)
791                 jsonw_null(json_wtr);
792         return err;
793 }
794
795 struct map_replace {
796         int idx;
797         int fd;
798         char *name;
799 };
800
801 static int map_replace_compar(const void *p1, const void *p2)
802 {
803         const struct map_replace *a = p1, *b = p2;
804
805         return a->idx - b->idx;
806 }
807
808 static int parse_attach_detach_args(int argc, char **argv, int *progfd,
809                                     enum bpf_attach_type *attach_type,
810                                     int *mapfd)
811 {
812         if (!REQ_ARGS(3))
813                 return -EINVAL;
814
815         *progfd = prog_parse_fd(&argc, &argv);
816         if (*progfd < 0)
817                 return *progfd;
818
819         *attach_type = parse_attach_type(*argv);
820         if (*attach_type == __MAX_BPF_ATTACH_TYPE) {
821                 p_err("invalid attach/detach type");
822                 return -EINVAL;
823         }
824
825         if (*attach_type == BPF_FLOW_DISSECTOR) {
826                 *mapfd = -1;
827                 return 0;
828         }
829
830         NEXT_ARG();
831         if (!REQ_ARGS(2))
832                 return -EINVAL;
833
834         *mapfd = map_parse_fd(&argc, &argv);
835         if (*mapfd < 0)
836                 return *mapfd;
837
838         return 0;
839 }
840
841 static int do_attach(int argc, char **argv)
842 {
843         enum bpf_attach_type attach_type;
844         int err, progfd;
845         int mapfd;
846
847         err = parse_attach_detach_args(argc, argv,
848                                        &progfd, &attach_type, &mapfd);
849         if (err)
850                 return err;
851
852         err = bpf_prog_attach(progfd, mapfd, attach_type, 0);
853         if (err) {
854                 p_err("failed prog attach to map");
855                 return -EINVAL;
856         }
857
858         if (json_output)
859                 jsonw_null(json_wtr);
860         return 0;
861 }
862
863 static int do_detach(int argc, char **argv)
864 {
865         enum bpf_attach_type attach_type;
866         int err, progfd;
867         int mapfd;
868
869         err = parse_attach_detach_args(argc, argv,
870                                        &progfd, &attach_type, &mapfd);
871         if (err)
872                 return err;
873
874         err = bpf_prog_detach2(progfd, mapfd, attach_type);
875         if (err) {
876                 p_err("failed prog detach from map");
877                 return -EINVAL;
878         }
879
880         if (json_output)
881                 jsonw_null(json_wtr);
882         return 0;
883 }
884
885 static int load_with_options(int argc, char **argv, bool first_prog_only)
886 {
887         enum bpf_attach_type expected_attach_type;
888         struct bpf_object_open_attr attr = {
889                 .prog_type      = BPF_PROG_TYPE_UNSPEC,
890         };
891         struct map_replace *map_replace = NULL;
892         struct bpf_program *prog = NULL, *pos;
893         unsigned int old_map_fds = 0;
894         const char *pinmaps = NULL;
895         struct bpf_object *obj;
896         struct bpf_map *map;
897         const char *pinfile;
898         unsigned int i, j;
899         __u32 ifindex = 0;
900         int idx, err;
901
902         if (!REQ_ARGS(2))
903                 return -1;
904         attr.file = GET_ARG();
905         pinfile = GET_ARG();
906
907         while (argc) {
908                 if (is_prefix(*argv, "type")) {
909                         char *type;
910
911                         NEXT_ARG();
912
913                         if (attr.prog_type != BPF_PROG_TYPE_UNSPEC) {
914                                 p_err("program type already specified");
915                                 goto err_free_reuse_maps;
916                         }
917                         if (!REQ_ARGS(1))
918                                 goto err_free_reuse_maps;
919
920                         /* Put a '/' at the end of type to appease libbpf */
921                         type = malloc(strlen(*argv) + 2);
922                         if (!type) {
923                                 p_err("mem alloc failed");
924                                 goto err_free_reuse_maps;
925                         }
926                         *type = 0;
927                         strcat(type, *argv);
928                         strcat(type, "/");
929
930                         err = libbpf_prog_type_by_name(type, &attr.prog_type,
931                                                        &expected_attach_type);
932                         free(type);
933                         if (err < 0) {
934                                 p_err("unknown program type '%s'", *argv);
935                                 goto err_free_reuse_maps;
936                         }
937                         NEXT_ARG();
938                 } else if (is_prefix(*argv, "map")) {
939                         void *new_map_replace;
940                         char *endptr, *name;
941                         int fd;
942
943                         NEXT_ARG();
944
945                         if (!REQ_ARGS(4))
946                                 goto err_free_reuse_maps;
947
948                         if (is_prefix(*argv, "idx")) {
949                                 NEXT_ARG();
950
951                                 idx = strtoul(*argv, &endptr, 0);
952                                 if (*endptr) {
953                                         p_err("can't parse %s as IDX", *argv);
954                                         goto err_free_reuse_maps;
955                                 }
956                                 name = NULL;
957                         } else if (is_prefix(*argv, "name")) {
958                                 NEXT_ARG();
959
960                                 name = *argv;
961                                 idx = -1;
962                         } else {
963                                 p_err("expected 'idx' or 'name', got: '%s'?",
964                                       *argv);
965                                 goto err_free_reuse_maps;
966                         }
967                         NEXT_ARG();
968
969                         fd = map_parse_fd(&argc, &argv);
970                         if (fd < 0)
971                                 goto err_free_reuse_maps;
972
973                         new_map_replace = reallocarray(map_replace,
974                                                        old_map_fds + 1,
975                                                        sizeof(*map_replace));
976                         if (!new_map_replace) {
977                                 p_err("mem alloc failed");
978                                 goto err_free_reuse_maps;
979                         }
980                         map_replace = new_map_replace;
981
982                         map_replace[old_map_fds].idx = idx;
983                         map_replace[old_map_fds].name = name;
984                         map_replace[old_map_fds].fd = fd;
985                         old_map_fds++;
986                 } else if (is_prefix(*argv, "dev")) {
987                         NEXT_ARG();
988
989                         if (ifindex) {
990                                 p_err("offload device already specified");
991                                 goto err_free_reuse_maps;
992                         }
993                         if (!REQ_ARGS(1))
994                                 goto err_free_reuse_maps;
995
996                         ifindex = if_nametoindex(*argv);
997                         if (!ifindex) {
998                                 p_err("unrecognized netdevice '%s': %s",
999                                       *argv, strerror(errno));
1000                                 goto err_free_reuse_maps;
1001                         }
1002                         NEXT_ARG();
1003                 } else if (is_prefix(*argv, "pinmaps")) {
1004                         NEXT_ARG();
1005
1006                         if (!REQ_ARGS(1))
1007                                 goto err_free_reuse_maps;
1008
1009                         pinmaps = GET_ARG();
1010                 } else {
1011                         p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?",
1012                               *argv);
1013                         goto err_free_reuse_maps;
1014                 }
1015         }
1016
1017         obj = __bpf_object__open_xattr(&attr, bpf_flags);
1018         if (IS_ERR_OR_NULL(obj)) {
1019                 p_err("failed to open object file");
1020                 goto err_free_reuse_maps;
1021         }
1022
1023         bpf_object__for_each_program(pos, obj) {
1024                 enum bpf_prog_type prog_type = attr.prog_type;
1025
1026                 if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) {
1027                         const char *sec_name = bpf_program__title(pos, false);
1028
1029                         err = libbpf_prog_type_by_name(sec_name, &prog_type,
1030                                                        &expected_attach_type);
1031                         if (err < 0) {
1032                                 p_err("failed to guess program type based on section name %s\n",
1033                                       sec_name);
1034                                 goto err_close_obj;
1035                         }
1036                 }
1037
1038                 bpf_program__set_ifindex(pos, ifindex);
1039                 bpf_program__set_type(pos, prog_type);
1040                 bpf_program__set_expected_attach_type(pos, expected_attach_type);
1041         }
1042
1043         qsort(map_replace, old_map_fds, sizeof(*map_replace),
1044               map_replace_compar);
1045
1046         /* After the sort maps by name will be first on the list, because they
1047          * have idx == -1.  Resolve them.
1048          */
1049         j = 0;
1050         while (j < old_map_fds && map_replace[j].name) {
1051                 i = 0;
1052                 bpf_map__for_each(map, obj) {
1053                         if (!strcmp(bpf_map__name(map), map_replace[j].name)) {
1054                                 map_replace[j].idx = i;
1055                                 break;
1056                         }
1057                         i++;
1058                 }
1059                 if (map_replace[j].idx == -1) {
1060                         p_err("unable to find map '%s'", map_replace[j].name);
1061                         goto err_close_obj;
1062                 }
1063                 j++;
1064         }
1065         /* Resort if any names were resolved */
1066         if (j)
1067                 qsort(map_replace, old_map_fds, sizeof(*map_replace),
1068                       map_replace_compar);
1069
1070         /* Set ifindex and name reuse */
1071         j = 0;
1072         idx = 0;
1073         bpf_map__for_each(map, obj) {
1074                 if (!bpf_map__is_offload_neutral(map))
1075                         bpf_map__set_ifindex(map, ifindex);
1076
1077                 if (j < old_map_fds && idx == map_replace[j].idx) {
1078                         err = bpf_map__reuse_fd(map, map_replace[j++].fd);
1079                         if (err) {
1080                                 p_err("unable to set up map reuse: %d", err);
1081                                 goto err_close_obj;
1082                         }
1083
1084                         /* Next reuse wants to apply to the same map */
1085                         if (j < old_map_fds && map_replace[j].idx == idx) {
1086                                 p_err("replacement for map idx %d specified more than once",
1087                                       idx);
1088                                 goto err_close_obj;
1089                         }
1090                 }
1091
1092                 idx++;
1093         }
1094         if (j < old_map_fds) {
1095                 p_err("map idx '%d' not used", map_replace[j].idx);
1096                 goto err_close_obj;
1097         }
1098
1099         set_max_rlimit();
1100
1101         err = bpf_object__load(obj);
1102         if (err) {
1103                 p_err("failed to load object file");
1104                 goto err_close_obj;
1105         }
1106
1107         err = mount_bpffs_for_pin(pinfile);
1108         if (err)
1109                 goto err_close_obj;
1110
1111         if (first_prog_only) {
1112                 prog = bpf_program__next(NULL, obj);
1113                 if (!prog) {
1114                         p_err("object file doesn't contain any bpf program");
1115                         goto err_close_obj;
1116                 }
1117
1118                 err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
1119                 if (err) {
1120                         p_err("failed to pin program %s",
1121                               bpf_program__title(prog, false));
1122                         goto err_close_obj;
1123                 }
1124         } else {
1125                 err = bpf_object__pin_programs(obj, pinfile);
1126                 if (err) {
1127                         p_err("failed to pin all programs");
1128                         goto err_close_obj;
1129                 }
1130         }
1131
1132         if (pinmaps) {
1133                 err = bpf_object__pin_maps(obj, pinmaps);
1134                 if (err) {
1135                         p_err("failed to pin all maps");
1136                         goto err_unpin;
1137                 }
1138         }
1139
1140         if (json_output)
1141                 jsonw_null(json_wtr);
1142
1143         bpf_object__close(obj);
1144         for (i = 0; i < old_map_fds; i++)
1145                 close(map_replace[i].fd);
1146         free(map_replace);
1147
1148         return 0;
1149
1150 err_unpin:
1151         if (first_prog_only)
1152                 unlink(pinfile);
1153         else
1154                 bpf_object__unpin_programs(obj, pinfile);
1155 err_close_obj:
1156         bpf_object__close(obj);
1157 err_free_reuse_maps:
1158         for (i = 0; i < old_map_fds; i++)
1159                 close(map_replace[i].fd);
1160         free(map_replace);
1161         return -1;
1162 }
1163
1164 static int do_load(int argc, char **argv)
1165 {
1166         return load_with_options(argc, argv, true);
1167 }
1168
1169 static int do_loadall(int argc, char **argv)
1170 {
1171         return load_with_options(argc, argv, false);
1172 }
1173
1174 static int do_help(int argc, char **argv)
1175 {
1176         if (json_output) {
1177                 jsonw_null(json_wtr);
1178                 return 0;
1179         }
1180
1181         fprintf(stderr,
1182                 "Usage: %s %s { show | list } [PROG]\n"
1183                 "       %s %s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n"
1184                 "       %s %s dump jited  PROG [{ file FILE | opcodes | linum }]\n"
1185                 "       %s %s pin   PROG FILE\n"
1186                 "       %s %s { load | loadall } OBJ  PATH \\\n"
1187                 "                         [type TYPE] [dev NAME] \\\n"
1188                 "                         [map { idx IDX | name NAME } MAP]\\\n"
1189                 "                         [pinmaps MAP_DIR]\n"
1190                 "       %s %s attach PROG ATTACH_TYPE [MAP]\n"
1191                 "       %s %s detach PROG ATTACH_TYPE [MAP]\n"
1192                 "       %s %s tracelog\n"
1193                 "       %s %s help\n"
1194                 "\n"
1195                 "       " HELP_SPEC_MAP "\n"
1196                 "       " HELP_SPEC_PROGRAM "\n"
1197                 "       TYPE := { socket | kprobe | kretprobe | classifier | action |\n"
1198                 "                 tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n"
1199                 "                 cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n"
1200                 "                 lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n"
1201                 "                 sk_reuseport | flow_dissector |\n"
1202                 "                 cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
1203                 "                 cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
1204                 "                 cgroup/sendmsg4 | cgroup/sendmsg6 }\n"
1205                 "       ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse |\n"
1206                 "                        flow_dissector }\n"
1207                 "       " HELP_SPEC_OPTIONS "\n"
1208                 "",
1209                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1210                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1211                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
1212
1213         return 0;
1214 }
1215
1216 static const struct cmd cmds[] = {
1217         { "show",       do_show },
1218         { "list",       do_show },
1219         { "help",       do_help },
1220         { "dump",       do_dump },
1221         { "pin",        do_pin },
1222         { "load",       do_load },
1223         { "loadall",    do_loadall },
1224         { "attach",     do_attach },
1225         { "detach",     do_detach },
1226         { "tracelog",   do_tracelog },
1227         { 0 }
1228 };
1229
1230 int do_prog(int argc, char **argv)
1231 {
1232         return cmd_select(cmds, argc, argv, do_help);
1233 }