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