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 finfo_cnt, linfo_cnt = 0, jited_linfo_cnt = 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 finfo_cnt = info.func_info_cnt; 541 finfo_rec_size = info.func_info_rec_size; 542 if (finfo_cnt && finfo_rec_size) { 543 func_info = malloc(finfo_cnt * 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.line_info_cnt && linfo_rec_size && info.btf_id) { 553 linfo_cnt = info.line_info_cnt; 554 linfo = malloc(linfo_cnt * 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.jited_line_info_cnt && 564 jited_linfo_rec_size && 565 info.nr_jited_ksyms && 566 info.nr_jited_func_lens && 567 info.btf_id) { 568 jited_linfo_cnt = info.jited_line_info_cnt; 569 jited_linfo = malloc(jited_linfo_cnt * 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.func_info_cnt = finfo_cnt; 586 info.func_info_rec_size = finfo_rec_size; 587 info.func_info = ptr_to_u64(func_info); 588 info.line_info_cnt = linfo_cnt; 589 info.line_info_rec_size = linfo_rec_size; 590 info.line_info = ptr_to_u64(linfo); 591 info.jited_line_info_cnt = jited_linfo_cnt; 592 info.jited_line_info_rec_size = jited_linfo_rec_size; 593 info.jited_line_info = ptr_to_u64(jited_linfo); 594 595 596 err = bpf_obj_get_info_by_fd(fd, &info, &len); 597 close(fd); 598 if (err) { 599 p_err("can't get prog info: %s", strerror(errno)); 600 goto err_free; 601 } 602 603 if (*member_len > buf_size) { 604 p_err("too many instructions returned"); 605 goto err_free; 606 } 607 608 if (info.nr_jited_ksyms > nr_func_ksyms) { 609 p_err("too many addresses returned"); 610 goto err_free; 611 } 612 613 if (info.nr_jited_func_lens > nr_func_lens) { 614 p_err("too many values returned"); 615 goto err_free; 616 } 617 618 if (info.func_info_cnt != finfo_cnt) { 619 p_err("incorrect func_info_cnt %d vs. expected %d", 620 info.func_info_cnt, finfo_cnt); 621 goto err_free; 622 } 623 624 if (info.func_info_rec_size != finfo_rec_size) { 625 p_err("incorrect func_info_rec_size %d vs. expected %d", 626 info.func_info_rec_size, finfo_rec_size); 627 goto err_free; 628 } 629 630 if (func_info && !info.func_info) { 631 /* kernel.kptr_restrict is set. No func_info available. */ 632 free(func_info); 633 func_info = NULL; 634 finfo_cnt = 0; 635 } 636 637 if (linfo && info.line_info_cnt != linfo_cnt) { 638 p_err("incorrect line_info_cnt %u vs. expected %u", 639 info.line_info_cnt, linfo_cnt); 640 goto err_free; 641 } 642 643 if (info.line_info_rec_size != linfo_rec_size) { 644 p_err("incorrect line_info_rec_size %u vs. expected %u", 645 info.line_info_rec_size, linfo_rec_size); 646 goto err_free; 647 } 648 649 if (jited_linfo && info.jited_line_info_cnt != jited_linfo_cnt) { 650 p_err("incorrect jited_line_info_cnt %u vs. expected %u", 651 info.jited_line_info_cnt, jited_linfo_cnt); 652 goto err_free; 653 } 654 655 if (info.jited_line_info_rec_size != jited_linfo_rec_size) { 656 p_err("incorrect jited_line_info_rec_size %u vs. expected %u", 657 info.jited_line_info_rec_size, jited_linfo_rec_size); 658 goto err_free; 659 } 660 661 if ((member_len == &info.jited_prog_len && 662 info.jited_prog_insns == 0) || 663 (member_len == &info.xlated_prog_len && 664 info.xlated_prog_insns == 0)) { 665 p_err("error retrieving insn dump: kernel.kptr_restrict set?"); 666 goto err_free; 667 } 668 669 if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) { 670 p_err("failed to get btf"); 671 goto err_free; 672 } 673 674 if (linfo_cnt) { 675 prog_linfo = bpf_prog_linfo__new(&info); 676 if (!prog_linfo) 677 p_err("error in processing bpf_line_info. continue without it."); 678 } 679 680 if (filepath) { 681 fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600); 682 if (fd < 0) { 683 p_err("can't open file %s: %s", filepath, 684 strerror(errno)); 685 goto err_free; 686 } 687 688 n = write(fd, buf, *member_len); 689 close(fd); 690 if (n != *member_len) { 691 p_err("error writing output file: %s", 692 n < 0 ? strerror(errno) : "short write"); 693 goto err_free; 694 } 695 696 if (json_output) 697 jsonw_null(json_wtr); 698 } else if (member_len == &info.jited_prog_len) { 699 const char *name = NULL; 700 701 if (info.ifindex) { 702 name = ifindex_to_bfd_params(info.ifindex, 703 info.netns_dev, 704 info.netns_ino, 705 &disasm_opt); 706 if (!name) 707 goto err_free; 708 } 709 710 if (info.nr_jited_func_lens && info.jited_func_lens) { 711 struct kernel_sym *sym = NULL; 712 struct bpf_func_info *record; 713 char sym_name[SYM_MAX_NAME]; 714 unsigned char *img = buf; 715 __u64 *ksyms = NULL; 716 __u32 *lens; 717 __u32 i; 718 719 if (info.nr_jited_ksyms) { 720 kernel_syms_load(&dd); 721 ksyms = (__u64 *) info.jited_ksyms; 722 } 723 724 if (json_output) 725 jsonw_start_array(json_wtr); 726 727 lens = (__u32 *) info.jited_func_lens; 728 for (i = 0; i < info.nr_jited_func_lens; i++) { 729 if (ksyms) { 730 sym = kernel_syms_search(&dd, ksyms[i]); 731 if (sym) 732 sprintf(sym_name, "%s", sym->name); 733 else 734 sprintf(sym_name, "0x%016llx", ksyms[i]); 735 } else { 736 strcpy(sym_name, "unknown"); 737 } 738 739 if (func_info) { 740 record = func_info + i * finfo_rec_size; 741 btf_dumper_type_only(btf, record->type_id, 742 func_sig, 743 sizeof(func_sig)); 744 } 745 746 if (json_output) { 747 jsonw_start_object(json_wtr); 748 if (func_info && func_sig[0] != '\0') { 749 jsonw_name(json_wtr, "proto"); 750 jsonw_string(json_wtr, func_sig); 751 } 752 jsonw_name(json_wtr, "name"); 753 jsonw_string(json_wtr, sym_name); 754 jsonw_name(json_wtr, "insns"); 755 } else { 756 if (func_info && func_sig[0] != '\0') 757 printf("%s:\n", func_sig); 758 printf("%s:\n", sym_name); 759 } 760 761 disasm_print_insn(img, lens[i], opcodes, 762 name, disasm_opt, btf, 763 prog_linfo, ksyms[i], i, 764 linum); 765 766 img += lens[i]; 767 768 if (json_output) 769 jsonw_end_object(json_wtr); 770 else 771 printf("\n"); 772 } 773 774 if (json_output) 775 jsonw_end_array(json_wtr); 776 } else { 777 disasm_print_insn(buf, *member_len, opcodes, name, 778 disasm_opt, btf, NULL, 0, 0, false); 779 } 780 } else if (visual) { 781 if (json_output) 782 jsonw_null(json_wtr); 783 else 784 dump_xlated_cfg(buf, *member_len); 785 } else { 786 kernel_syms_load(&dd); 787 dd.nr_jited_ksyms = info.nr_jited_ksyms; 788 dd.jited_ksyms = (__u64 *) info.jited_ksyms; 789 dd.btf = btf; 790 dd.func_info = func_info; 791 dd.finfo_rec_size = finfo_rec_size; 792 dd.prog_linfo = prog_linfo; 793 794 if (json_output) 795 dump_xlated_json(&dd, buf, *member_len, opcodes, 796 linum); 797 else 798 dump_xlated_plain(&dd, buf, *member_len, opcodes, 799 linum); 800 kernel_syms_destroy(&dd); 801 } 802 803 free(buf); 804 free(func_ksyms); 805 free(func_lens); 806 free(func_info); 807 free(linfo); 808 free(jited_linfo); 809 bpf_prog_linfo__free(prog_linfo); 810 return 0; 811 812 err_free: 813 free(buf); 814 free(func_ksyms); 815 free(func_lens); 816 free(func_info); 817 free(linfo); 818 free(jited_linfo); 819 bpf_prog_linfo__free(prog_linfo); 820 return -1; 821 } 822 823 static int do_pin(int argc, char **argv) 824 { 825 int err; 826 827 err = do_pin_any(argc, argv, bpf_prog_get_fd_by_id); 828 if (!err && json_output) 829 jsonw_null(json_wtr); 830 return err; 831 } 832 833 struct map_replace { 834 int idx; 835 int fd; 836 char *name; 837 }; 838 839 int map_replace_compar(const void *p1, const void *p2) 840 { 841 const struct map_replace *a = p1, *b = p2; 842 843 return a->idx - b->idx; 844 } 845 846 static int parse_attach_detach_args(int argc, char **argv, int *progfd, 847 enum bpf_attach_type *attach_type, 848 int *mapfd) 849 { 850 if (!REQ_ARGS(3)) 851 return -EINVAL; 852 853 *progfd = prog_parse_fd(&argc, &argv); 854 if (*progfd < 0) 855 return *progfd; 856 857 *attach_type = parse_attach_type(*argv); 858 if (*attach_type == __MAX_BPF_ATTACH_TYPE) { 859 p_err("invalid attach/detach type"); 860 return -EINVAL; 861 } 862 863 if (*attach_type == BPF_FLOW_DISSECTOR) { 864 *mapfd = -1; 865 return 0; 866 } 867 868 NEXT_ARG(); 869 if (!REQ_ARGS(2)) 870 return -EINVAL; 871 872 *mapfd = map_parse_fd(&argc, &argv); 873 if (*mapfd < 0) 874 return *mapfd; 875 876 return 0; 877 } 878 879 static int do_attach(int argc, char **argv) 880 { 881 enum bpf_attach_type attach_type; 882 int err, progfd; 883 int mapfd; 884 885 err = parse_attach_detach_args(argc, argv, 886 &progfd, &attach_type, &mapfd); 887 if (err) 888 return err; 889 890 err = bpf_prog_attach(progfd, mapfd, attach_type, 0); 891 if (err) { 892 p_err("failed prog attach to map"); 893 return -EINVAL; 894 } 895 896 if (json_output) 897 jsonw_null(json_wtr); 898 return 0; 899 } 900 901 static int do_detach(int argc, char **argv) 902 { 903 enum bpf_attach_type attach_type; 904 int err, progfd; 905 int mapfd; 906 907 err = parse_attach_detach_args(argc, argv, 908 &progfd, &attach_type, &mapfd); 909 if (err) 910 return err; 911 912 err = bpf_prog_detach2(progfd, mapfd, attach_type); 913 if (err) { 914 p_err("failed prog detach from map"); 915 return -EINVAL; 916 } 917 918 if (json_output) 919 jsonw_null(json_wtr); 920 return 0; 921 } 922 923 static int load_with_options(int argc, char **argv, bool first_prog_only) 924 { 925 enum bpf_attach_type expected_attach_type; 926 struct bpf_object_open_attr attr = { 927 .prog_type = BPF_PROG_TYPE_UNSPEC, 928 }; 929 struct map_replace *map_replace = NULL; 930 struct bpf_program *prog = NULL, *pos; 931 unsigned int old_map_fds = 0; 932 const char *pinmaps = NULL; 933 struct bpf_object *obj; 934 struct bpf_map *map; 935 const char *pinfile; 936 unsigned int i, j; 937 __u32 ifindex = 0; 938 int idx, err; 939 940 if (!REQ_ARGS(2)) 941 return -1; 942 attr.file = GET_ARG(); 943 pinfile = GET_ARG(); 944 945 while (argc) { 946 if (is_prefix(*argv, "type")) { 947 char *type; 948 949 NEXT_ARG(); 950 951 if (attr.prog_type != BPF_PROG_TYPE_UNSPEC) { 952 p_err("program type already specified"); 953 goto err_free_reuse_maps; 954 } 955 if (!REQ_ARGS(1)) 956 goto err_free_reuse_maps; 957 958 /* Put a '/' at the end of type to appease libbpf */ 959 type = malloc(strlen(*argv) + 2); 960 if (!type) { 961 p_err("mem alloc failed"); 962 goto err_free_reuse_maps; 963 } 964 *type = 0; 965 strcat(type, *argv); 966 strcat(type, "/"); 967 968 err = libbpf_prog_type_by_name(type, &attr.prog_type, 969 &expected_attach_type); 970 free(type); 971 if (err < 0) { 972 p_err("unknown program type '%s'", *argv); 973 goto err_free_reuse_maps; 974 } 975 NEXT_ARG(); 976 } else if (is_prefix(*argv, "map")) { 977 void *new_map_replace; 978 char *endptr, *name; 979 int fd; 980 981 NEXT_ARG(); 982 983 if (!REQ_ARGS(4)) 984 goto err_free_reuse_maps; 985 986 if (is_prefix(*argv, "idx")) { 987 NEXT_ARG(); 988 989 idx = strtoul(*argv, &endptr, 0); 990 if (*endptr) { 991 p_err("can't parse %s as IDX", *argv); 992 goto err_free_reuse_maps; 993 } 994 name = NULL; 995 } else if (is_prefix(*argv, "name")) { 996 NEXT_ARG(); 997 998 name = *argv; 999 idx = -1; 1000 } else { 1001 p_err("expected 'idx' or 'name', got: '%s'?", 1002 *argv); 1003 goto err_free_reuse_maps; 1004 } 1005 NEXT_ARG(); 1006 1007 fd = map_parse_fd(&argc, &argv); 1008 if (fd < 0) 1009 goto err_free_reuse_maps; 1010 1011 new_map_replace = reallocarray(map_replace, 1012 old_map_fds + 1, 1013 sizeof(*map_replace)); 1014 if (!new_map_replace) { 1015 p_err("mem alloc failed"); 1016 goto err_free_reuse_maps; 1017 } 1018 map_replace = new_map_replace; 1019 1020 map_replace[old_map_fds].idx = idx; 1021 map_replace[old_map_fds].name = name; 1022 map_replace[old_map_fds].fd = fd; 1023 old_map_fds++; 1024 } else if (is_prefix(*argv, "dev")) { 1025 NEXT_ARG(); 1026 1027 if (ifindex) { 1028 p_err("offload device already specified"); 1029 goto err_free_reuse_maps; 1030 } 1031 if (!REQ_ARGS(1)) 1032 goto err_free_reuse_maps; 1033 1034 ifindex = if_nametoindex(*argv); 1035 if (!ifindex) { 1036 p_err("unrecognized netdevice '%s': %s", 1037 *argv, strerror(errno)); 1038 goto err_free_reuse_maps; 1039 } 1040 NEXT_ARG(); 1041 } else if (is_prefix(*argv, "pinmaps")) { 1042 NEXT_ARG(); 1043 1044 if (!REQ_ARGS(1)) 1045 goto err_free_reuse_maps; 1046 1047 pinmaps = GET_ARG(); 1048 } else { 1049 p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?", 1050 *argv); 1051 goto err_free_reuse_maps; 1052 } 1053 } 1054 1055 obj = __bpf_object__open_xattr(&attr, bpf_flags); 1056 if (IS_ERR_OR_NULL(obj)) { 1057 p_err("failed to open object file"); 1058 goto err_free_reuse_maps; 1059 } 1060 1061 bpf_object__for_each_program(pos, obj) { 1062 enum bpf_prog_type prog_type = attr.prog_type; 1063 1064 if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { 1065 const char *sec_name = bpf_program__title(pos, false); 1066 1067 err = libbpf_prog_type_by_name(sec_name, &prog_type, 1068 &expected_attach_type); 1069 if (err < 0) { 1070 p_err("failed to guess program type based on section name %s\n", 1071 sec_name); 1072 goto err_close_obj; 1073 } 1074 } 1075 1076 bpf_program__set_ifindex(pos, ifindex); 1077 bpf_program__set_type(pos, prog_type); 1078 bpf_program__set_expected_attach_type(pos, expected_attach_type); 1079 } 1080 1081 qsort(map_replace, old_map_fds, sizeof(*map_replace), 1082 map_replace_compar); 1083 1084 /* After the sort maps by name will be first on the list, because they 1085 * have idx == -1. Resolve them. 1086 */ 1087 j = 0; 1088 while (j < old_map_fds && map_replace[j].name) { 1089 i = 0; 1090 bpf_map__for_each(map, obj) { 1091 if (!strcmp(bpf_map__name(map), map_replace[j].name)) { 1092 map_replace[j].idx = i; 1093 break; 1094 } 1095 i++; 1096 } 1097 if (map_replace[j].idx == -1) { 1098 p_err("unable to find map '%s'", map_replace[j].name); 1099 goto err_close_obj; 1100 } 1101 j++; 1102 } 1103 /* Resort if any names were resolved */ 1104 if (j) 1105 qsort(map_replace, old_map_fds, sizeof(*map_replace), 1106 map_replace_compar); 1107 1108 /* Set ifindex and name reuse */ 1109 j = 0; 1110 idx = 0; 1111 bpf_map__for_each(map, obj) { 1112 if (!bpf_map__is_offload_neutral(map)) 1113 bpf_map__set_ifindex(map, ifindex); 1114 1115 if (j < old_map_fds && idx == map_replace[j].idx) { 1116 err = bpf_map__reuse_fd(map, map_replace[j++].fd); 1117 if (err) { 1118 p_err("unable to set up map reuse: %d", err); 1119 goto err_close_obj; 1120 } 1121 1122 /* Next reuse wants to apply to the same map */ 1123 if (j < old_map_fds && map_replace[j].idx == idx) { 1124 p_err("replacement for map idx %d specified more than once", 1125 idx); 1126 goto err_close_obj; 1127 } 1128 } 1129 1130 idx++; 1131 } 1132 if (j < old_map_fds) { 1133 p_err("map idx '%d' not used", map_replace[j].idx); 1134 goto err_close_obj; 1135 } 1136 1137 set_max_rlimit(); 1138 1139 err = bpf_object__load(obj); 1140 if (err) { 1141 p_err("failed to load object file"); 1142 goto err_close_obj; 1143 } 1144 1145 err = mount_bpffs_for_pin(pinfile); 1146 if (err) 1147 goto err_close_obj; 1148 1149 if (first_prog_only) { 1150 prog = bpf_program__next(NULL, obj); 1151 if (!prog) { 1152 p_err("object file doesn't contain any bpf program"); 1153 goto err_close_obj; 1154 } 1155 1156 err = bpf_obj_pin(bpf_program__fd(prog), pinfile); 1157 if (err) { 1158 p_err("failed to pin program %s", 1159 bpf_program__title(prog, false)); 1160 goto err_close_obj; 1161 } 1162 } else { 1163 err = bpf_object__pin_programs(obj, pinfile); 1164 if (err) { 1165 p_err("failed to pin all programs"); 1166 goto err_close_obj; 1167 } 1168 } 1169 1170 if (pinmaps) { 1171 err = bpf_object__pin_maps(obj, pinmaps); 1172 if (err) { 1173 p_err("failed to pin all maps"); 1174 goto err_unpin; 1175 } 1176 } 1177 1178 if (json_output) 1179 jsonw_null(json_wtr); 1180 1181 bpf_object__close(obj); 1182 for (i = 0; i < old_map_fds; i++) 1183 close(map_replace[i].fd); 1184 free(map_replace); 1185 1186 return 0; 1187 1188 err_unpin: 1189 if (first_prog_only) 1190 unlink(pinfile); 1191 else 1192 bpf_object__unpin_programs(obj, pinfile); 1193 err_close_obj: 1194 bpf_object__close(obj); 1195 err_free_reuse_maps: 1196 for (i = 0; i < old_map_fds; i++) 1197 close(map_replace[i].fd); 1198 free(map_replace); 1199 return -1; 1200 } 1201 1202 static int do_load(int argc, char **argv) 1203 { 1204 return load_with_options(argc, argv, true); 1205 } 1206 1207 static int do_loadall(int argc, char **argv) 1208 { 1209 return load_with_options(argc, argv, false); 1210 } 1211 1212 static int do_help(int argc, char **argv) 1213 { 1214 if (json_output) { 1215 jsonw_null(json_wtr); 1216 return 0; 1217 } 1218 1219 fprintf(stderr, 1220 "Usage: %s %s { show | list } [PROG]\n" 1221 " %s %s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n" 1222 " %s %s dump jited PROG [{ file FILE | opcodes | linum }]\n" 1223 " %s %s pin PROG FILE\n" 1224 " %s %s { load | loadall } OBJ PATH \\\n" 1225 " [type TYPE] [dev NAME] \\\n" 1226 " [map { idx IDX | name NAME } MAP]\\\n" 1227 " [pinmaps MAP_DIR]\n" 1228 " %s %s attach PROG ATTACH_TYPE [MAP]\n" 1229 " %s %s detach PROG ATTACH_TYPE [MAP]\n" 1230 " %s %s tracelog\n" 1231 " %s %s help\n" 1232 "\n" 1233 " " HELP_SPEC_MAP "\n" 1234 " " HELP_SPEC_PROGRAM "\n" 1235 " TYPE := { socket | kprobe | kretprobe | classifier | action |\n" 1236 " tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n" 1237 " cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n" 1238 " lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n" 1239 " sk_reuseport | flow_dissector |\n" 1240 " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" 1241 " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" 1242 " cgroup/sendmsg4 | cgroup/sendmsg6 }\n" 1243 " ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse |\n" 1244 " flow_dissector }\n" 1245 " " HELP_SPEC_OPTIONS "\n" 1246 "", 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 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1250 1251 return 0; 1252 } 1253 1254 static const struct cmd cmds[] = { 1255 { "show", do_show }, 1256 { "list", do_show }, 1257 { "help", do_help }, 1258 { "dump", do_dump }, 1259 { "pin", do_pin }, 1260 { "load", do_load }, 1261 { "loadall", do_loadall }, 1262 { "attach", do_attach }, 1263 { "detach", do_detach }, 1264 { "tracelog", do_tracelog }, 1265 { 0 } 1266 }; 1267 1268 int do_prog(int argc, char **argv) 1269 { 1270 return cmd_select(cmds, argc, argv, do_help); 1271 } 1272