linux/tools/bpf/bpftool/prog.c
<<
>>
Prefs
   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 <signal.h>
   8#include <stdarg.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <time.h>
  13#include <unistd.h>
  14#include <net/if.h>
  15#include <sys/ioctl.h>
  16#include <sys/types.h>
  17#include <sys/stat.h>
  18#include <sys/syscall.h>
  19
  20#include <linux/err.h>
  21#include <linux/perf_event.h>
  22#include <linux/sizes.h>
  23
  24#include <bpf/bpf.h>
  25#include <bpf/btf.h>
  26#include <bpf/libbpf.h>
  27
  28#include "cfg.h"
  29#include "main.h"
  30#include "xlated_dumper.h"
  31
  32#define BPF_METADATA_PREFIX "bpf_metadata_"
  33#define BPF_METADATA_PREFIX_LEN (sizeof(BPF_METADATA_PREFIX) - 1)
  34
  35const char * const prog_type_name[] = {
  36        [BPF_PROG_TYPE_UNSPEC]                  = "unspec",
  37        [BPF_PROG_TYPE_SOCKET_FILTER]           = "socket_filter",
  38        [BPF_PROG_TYPE_KPROBE]                  = "kprobe",
  39        [BPF_PROG_TYPE_SCHED_CLS]               = "sched_cls",
  40        [BPF_PROG_TYPE_SCHED_ACT]               = "sched_act",
  41        [BPF_PROG_TYPE_TRACEPOINT]              = "tracepoint",
  42        [BPF_PROG_TYPE_XDP]                     = "xdp",
  43        [BPF_PROG_TYPE_PERF_EVENT]              = "perf_event",
  44        [BPF_PROG_TYPE_CGROUP_SKB]              = "cgroup_skb",
  45        [BPF_PROG_TYPE_CGROUP_SOCK]             = "cgroup_sock",
  46        [BPF_PROG_TYPE_LWT_IN]                  = "lwt_in",
  47        [BPF_PROG_TYPE_LWT_OUT]                 = "lwt_out",
  48        [BPF_PROG_TYPE_LWT_XMIT]                = "lwt_xmit",
  49        [BPF_PROG_TYPE_SOCK_OPS]                = "sock_ops",
  50        [BPF_PROG_TYPE_SK_SKB]                  = "sk_skb",
  51        [BPF_PROG_TYPE_CGROUP_DEVICE]           = "cgroup_device",
  52        [BPF_PROG_TYPE_SK_MSG]                  = "sk_msg",
  53        [BPF_PROG_TYPE_RAW_TRACEPOINT]          = "raw_tracepoint",
  54        [BPF_PROG_TYPE_CGROUP_SOCK_ADDR]        = "cgroup_sock_addr",
  55        [BPF_PROG_TYPE_LWT_SEG6LOCAL]           = "lwt_seg6local",
  56        [BPF_PROG_TYPE_LIRC_MODE2]              = "lirc_mode2",
  57        [BPF_PROG_TYPE_SK_REUSEPORT]            = "sk_reuseport",
  58        [BPF_PROG_TYPE_FLOW_DISSECTOR]          = "flow_dissector",
  59        [BPF_PROG_TYPE_CGROUP_SYSCTL]           = "cgroup_sysctl",
  60        [BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE] = "raw_tracepoint_writable",
  61        [BPF_PROG_TYPE_CGROUP_SOCKOPT]          = "cgroup_sockopt",
  62        [BPF_PROG_TYPE_TRACING]                 = "tracing",
  63        [BPF_PROG_TYPE_STRUCT_OPS]              = "struct_ops",
  64        [BPF_PROG_TYPE_EXT]                     = "ext",
  65        [BPF_PROG_TYPE_LSM]                     = "lsm",
  66        [BPF_PROG_TYPE_SK_LOOKUP]               = "sk_lookup",
  67};
  68
  69const size_t prog_type_name_size = ARRAY_SIZE(prog_type_name);
  70
  71enum dump_mode {
  72        DUMP_JITED,
  73        DUMP_XLATED,
  74};
  75
  76static const char * const attach_type_strings[] = {
  77        [BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
  78        [BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
  79        [BPF_SK_MSG_VERDICT] = "msg_verdict",
  80        [BPF_FLOW_DISSECTOR] = "flow_dissector",
  81        [__MAX_BPF_ATTACH_TYPE] = NULL,
  82};
  83
  84static enum bpf_attach_type parse_attach_type(const char *str)
  85{
  86        enum bpf_attach_type type;
  87
  88        for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
  89                if (attach_type_strings[type] &&
  90                    is_prefix(str, attach_type_strings[type]))
  91                        return type;
  92        }
  93
  94        return __MAX_BPF_ATTACH_TYPE;
  95}
  96
  97static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
  98{
  99        struct timespec real_time_ts, boot_time_ts;
 100        time_t wallclock_secs;
 101        struct tm load_tm;
 102
 103        buf[--size] = '\0';
 104
 105        if (clock_gettime(CLOCK_REALTIME, &real_time_ts) ||
 106            clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) {
 107                perror("Can't read clocks");
 108                snprintf(buf, size, "%llu", nsecs / 1000000000);
 109                return;
 110        }
 111
 112        wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
 113                (real_time_ts.tv_nsec - boot_time_ts.tv_nsec + nsecs) /
 114                1000000000;
 115
 116
 117        if (!localtime_r(&wallclock_secs, &load_tm)) {
 118                snprintf(buf, size, "%llu", nsecs / 1000000000);
 119                return;
 120        }
 121
 122        if (json_output)
 123                strftime(buf, size, "%s", &load_tm);
 124        else
 125                strftime(buf, size, "%FT%T%z", &load_tm);
 126}
 127
 128static void show_prog_maps(int fd, __u32 num_maps)
 129{
 130        struct bpf_prog_info info = {};
 131        __u32 len = sizeof(info);
 132        __u32 map_ids[num_maps];
 133        unsigned int i;
 134        int err;
 135
 136        info.nr_map_ids = num_maps;
 137        info.map_ids = ptr_to_u64(map_ids);
 138
 139        err = bpf_obj_get_info_by_fd(fd, &info, &len);
 140        if (err || !info.nr_map_ids)
 141                return;
 142
 143        if (json_output) {
 144                jsonw_name(json_wtr, "map_ids");
 145                jsonw_start_array(json_wtr);
 146                for (i = 0; i < info.nr_map_ids; i++)
 147                        jsonw_uint(json_wtr, map_ids[i]);
 148                jsonw_end_array(json_wtr);
 149        } else {
 150                printf("  map_ids ");
 151                for (i = 0; i < info.nr_map_ids; i++)
 152                        printf("%u%s", map_ids[i],
 153                               i == info.nr_map_ids - 1 ? "" : ",");
 154        }
 155}
 156
 157static void *find_metadata(int prog_fd, struct bpf_map_info *map_info)
 158{
 159        struct bpf_prog_info prog_info;
 160        __u32 prog_info_len;
 161        __u32 map_info_len;
 162        void *value = NULL;
 163        __u32 *map_ids;
 164        int nr_maps;
 165        int key = 0;
 166        int map_fd;
 167        int ret;
 168        __u32 i;
 169
 170        memset(&prog_info, 0, sizeof(prog_info));
 171        prog_info_len = sizeof(prog_info);
 172        ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len);
 173        if (ret)
 174                return NULL;
 175
 176        if (!prog_info.nr_map_ids)
 177                return NULL;
 178
 179        map_ids = calloc(prog_info.nr_map_ids, sizeof(__u32));
 180        if (!map_ids)
 181                return NULL;
 182
 183        nr_maps = prog_info.nr_map_ids;
 184        memset(&prog_info, 0, sizeof(prog_info));
 185        prog_info.nr_map_ids = nr_maps;
 186        prog_info.map_ids = ptr_to_u64(map_ids);
 187        prog_info_len = sizeof(prog_info);
 188
 189        ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len);
 190        if (ret)
 191                goto free_map_ids;
 192
 193        for (i = 0; i < prog_info.nr_map_ids; i++) {
 194                map_fd = bpf_map_get_fd_by_id(map_ids[i]);
 195                if (map_fd < 0)
 196                        goto free_map_ids;
 197
 198                memset(map_info, 0, sizeof(*map_info));
 199                map_info_len = sizeof(*map_info);
 200                ret = bpf_obj_get_info_by_fd(map_fd, map_info, &map_info_len);
 201                if (ret < 0) {
 202                        close(map_fd);
 203                        goto free_map_ids;
 204                }
 205
 206                if (map_info->type != BPF_MAP_TYPE_ARRAY ||
 207                    map_info->key_size != sizeof(int) ||
 208                    map_info->max_entries != 1 ||
 209                    !map_info->btf_value_type_id ||
 210                    !strstr(map_info->name, ".rodata")) {
 211                        close(map_fd);
 212                        continue;
 213                }
 214
 215                value = malloc(map_info->value_size);
 216                if (!value) {
 217                        close(map_fd);
 218                        goto free_map_ids;
 219                }
 220
 221                if (bpf_map_lookup_elem(map_fd, &key, value)) {
 222                        close(map_fd);
 223                        free(value);
 224                        value = NULL;
 225                        goto free_map_ids;
 226                }
 227
 228                close(map_fd);
 229                break;
 230        }
 231
 232free_map_ids:
 233        free(map_ids);
 234        return value;
 235}
 236
 237static bool has_metadata_prefix(const char *s)
 238{
 239        return strncmp(s, BPF_METADATA_PREFIX, BPF_METADATA_PREFIX_LEN) == 0;
 240}
 241
 242static void show_prog_metadata(int fd, __u32 num_maps)
 243{
 244        const struct btf_type *t_datasec, *t_var;
 245        struct bpf_map_info map_info;
 246        struct btf_var_secinfo *vsi;
 247        bool printed_header = false;
 248        struct btf *btf = NULL;
 249        unsigned int i, vlen;
 250        void *value = NULL;
 251        const char *name;
 252        int err;
 253
 254        if (!num_maps)
 255                return;
 256
 257        memset(&map_info, 0, sizeof(map_info));
 258        value = find_metadata(fd, &map_info);
 259        if (!value)
 260                return;
 261
 262        err = btf__get_from_id(map_info.btf_id, &btf);
 263        if (err || !btf)
 264                goto out_free;
 265
 266        t_datasec = btf__type_by_id(btf, map_info.btf_value_type_id);
 267        if (!btf_is_datasec(t_datasec))
 268                goto out_free;
 269
 270        vlen = btf_vlen(t_datasec);
 271        vsi = btf_var_secinfos(t_datasec);
 272
 273        /* We don't proceed to check the kinds of the elements of the DATASEC.
 274         * The verifier enforces them to be BTF_KIND_VAR.
 275         */
 276
 277        if (json_output) {
 278                struct btf_dumper d = {
 279                        .btf = btf,
 280                        .jw = json_wtr,
 281                        .is_plain_text = false,
 282                };
 283
 284                for (i = 0; i < vlen; i++, vsi++) {
 285                        t_var = btf__type_by_id(btf, vsi->type);
 286                        name = btf__name_by_offset(btf, t_var->name_off);
 287
 288                        if (!has_metadata_prefix(name))
 289                                continue;
 290
 291                        if (!printed_header) {
 292                                jsonw_name(json_wtr, "metadata");
 293                                jsonw_start_object(json_wtr);
 294                                printed_header = true;
 295                        }
 296
 297                        jsonw_name(json_wtr, name + BPF_METADATA_PREFIX_LEN);
 298                        err = btf_dumper_type(&d, t_var->type, value + vsi->offset);
 299                        if (err) {
 300                                p_err("btf dump failed: %d", err);
 301                                break;
 302                        }
 303                }
 304                if (printed_header)
 305                        jsonw_end_object(json_wtr);
 306        } else {
 307                json_writer_t *btf_wtr = jsonw_new(stdout);
 308                struct btf_dumper d = {
 309                        .btf = btf,
 310                        .jw = btf_wtr,
 311                        .is_plain_text = true,
 312                };
 313
 314                if (!btf_wtr) {
 315                        p_err("jsonw alloc failed");
 316                        goto out_free;
 317                }
 318
 319                for (i = 0; i < vlen; i++, vsi++) {
 320                        t_var = btf__type_by_id(btf, vsi->type);
 321                        name = btf__name_by_offset(btf, t_var->name_off);
 322
 323                        if (!has_metadata_prefix(name))
 324                                continue;
 325
 326                        if (!printed_header) {
 327                                printf("\tmetadata:");
 328                                printed_header = true;
 329                        }
 330
 331                        printf("\n\t\t%s = ", name + BPF_METADATA_PREFIX_LEN);
 332
 333                        jsonw_reset(btf_wtr);
 334                        err = btf_dumper_type(&d, t_var->type, value + vsi->offset);
 335                        if (err) {
 336                                p_err("btf dump failed: %d", err);
 337                                break;
 338                        }
 339                }
 340                if (printed_header)
 341                        jsonw_destroy(&btf_wtr);
 342        }
 343
 344out_free:
 345        btf__free(btf);
 346        free(value);
 347}
 348
 349static void print_prog_header_json(struct bpf_prog_info *info)
 350{
 351        jsonw_uint_field(json_wtr, "id", info->id);
 352        if (info->type < ARRAY_SIZE(prog_type_name))
 353                jsonw_string_field(json_wtr, "type",
 354                                   prog_type_name[info->type]);
 355        else
 356                jsonw_uint_field(json_wtr, "type", info->type);
 357
 358        if (*info->name)
 359                jsonw_string_field(json_wtr, "name", info->name);
 360
 361        jsonw_name(json_wtr, "tag");
 362        jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"",
 363                     info->tag[0], info->tag[1], info->tag[2], info->tag[3],
 364                     info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
 365
 366        jsonw_bool_field(json_wtr, "gpl_compatible", info->gpl_compatible);
 367        if (info->run_time_ns) {
 368                jsonw_uint_field(json_wtr, "run_time_ns", info->run_time_ns);
 369                jsonw_uint_field(json_wtr, "run_cnt", info->run_cnt);
 370        }
 371}
 372
 373static void print_prog_json(struct bpf_prog_info *info, int fd)
 374{
 375        char *memlock;
 376
 377        jsonw_start_object(json_wtr);
 378        print_prog_header_json(info);
 379        print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
 380
 381        if (info->load_time) {
 382                char buf[32];
 383
 384                print_boot_time(info->load_time, buf, sizeof(buf));
 385
 386                /* Piggy back on load_time, since 0 uid is a valid one */
 387                jsonw_name(json_wtr, "loaded_at");
 388                jsonw_printf(json_wtr, "%s", buf);
 389                jsonw_uint_field(json_wtr, "uid", info->created_by_uid);
 390        }
 391
 392        jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len);
 393
 394        if (info->jited_prog_len) {
 395                jsonw_bool_field(json_wtr, "jited", true);
 396                jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len);
 397        } else {
 398                jsonw_bool_field(json_wtr, "jited", false);
 399        }
 400
 401        memlock = get_fdinfo(fd, "memlock");
 402        if (memlock)
 403                jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
 404        free(memlock);
 405
 406        if (info->nr_map_ids)
 407                show_prog_maps(fd, info->nr_map_ids);
 408
 409        if (info->btf_id)
 410                jsonw_int_field(json_wtr, "btf_id", info->btf_id);
 411
 412        if (!hash_empty(prog_table.table)) {
 413                struct pinned_obj *obj;
 414
 415                jsonw_name(json_wtr, "pinned");
 416                jsonw_start_array(json_wtr);
 417                hash_for_each_possible(prog_table.table, obj, hash, info->id) {
 418                        if (obj->id == info->id)
 419                                jsonw_string(json_wtr, obj->path);
 420                }
 421                jsonw_end_array(json_wtr);
 422        }
 423
 424        emit_obj_refs_json(&refs_table, info->id, json_wtr);
 425
 426        show_prog_metadata(fd, info->nr_map_ids);
 427
 428        jsonw_end_object(json_wtr);
 429}
 430
 431static void print_prog_header_plain(struct bpf_prog_info *info)
 432{
 433        printf("%u: ", info->id);
 434        if (info->type < ARRAY_SIZE(prog_type_name))
 435                printf("%s  ", prog_type_name[info->type]);
 436        else
 437                printf("type %u  ", info->type);
 438
 439        if (*info->name)
 440                printf("name %s  ", info->name);
 441
 442        printf("tag ");
 443        fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
 444        print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
 445        printf("%s", info->gpl_compatible ? "  gpl" : "");
 446        if (info->run_time_ns)
 447                printf(" run_time_ns %lld run_cnt %lld",
 448                       info->run_time_ns, info->run_cnt);
 449        printf("\n");
 450}
 451
 452static void print_prog_plain(struct bpf_prog_info *info, int fd)
 453{
 454        char *memlock;
 455
 456        print_prog_header_plain(info);
 457
 458        if (info->load_time) {
 459                char buf[32];
 460
 461                print_boot_time(info->load_time, buf, sizeof(buf));
 462
 463                /* Piggy back on load_time, since 0 uid is a valid one */
 464                printf("\tloaded_at %s  uid %u\n", buf, info->created_by_uid);
 465        }
 466
 467        printf("\txlated %uB", info->xlated_prog_len);
 468
 469        if (info->jited_prog_len)
 470                printf("  jited %uB", info->jited_prog_len);
 471        else
 472                printf("  not jited");
 473
 474        memlock = get_fdinfo(fd, "memlock");
 475        if (memlock)
 476                printf("  memlock %sB", memlock);
 477        free(memlock);
 478
 479        if (info->nr_map_ids)
 480                show_prog_maps(fd, info->nr_map_ids);
 481
 482        if (!hash_empty(prog_table.table)) {
 483                struct pinned_obj *obj;
 484
 485                hash_for_each_possible(prog_table.table, obj, hash, info->id) {
 486                        if (obj->id == info->id)
 487                                printf("\n\tpinned %s", obj->path);
 488                }
 489        }
 490
 491        if (info->btf_id)
 492                printf("\n\tbtf_id %d", info->btf_id);
 493
 494        emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");
 495
 496        printf("\n");
 497
 498        show_prog_metadata(fd, info->nr_map_ids);
 499}
 500
 501static int show_prog(int fd)
 502{
 503        struct bpf_prog_info info = {};
 504        __u32 len = sizeof(info);
 505        int err;
 506
 507        err = bpf_obj_get_info_by_fd(fd, &info, &len);
 508        if (err) {
 509                p_err("can't get prog info: %s", strerror(errno));
 510                return -1;
 511        }
 512
 513        if (json_output)
 514                print_prog_json(&info, fd);
 515        else
 516                print_prog_plain(&info, fd);
 517
 518        return 0;
 519}
 520
 521static int do_show_subset(int argc, char **argv)
 522{
 523        int *fds = NULL;
 524        int nb_fds, i;
 525        int err = -1;
 526
 527        fds = malloc(sizeof(int));
 528        if (!fds) {
 529                p_err("mem alloc failed");
 530                return -1;
 531        }
 532        nb_fds = prog_parse_fds(&argc, &argv, &fds);
 533        if (nb_fds < 1)
 534                goto exit_free;
 535
 536        if (json_output && nb_fds > 1)
 537                jsonw_start_array(json_wtr);    /* root array */
 538        for (i = 0; i < nb_fds; i++) {
 539                err = show_prog(fds[i]);
 540                if (err) {
 541                        for (; i < nb_fds; i++)
 542                                close(fds[i]);
 543                        break;
 544                }
 545                close(fds[i]);
 546        }
 547        if (json_output && nb_fds > 1)
 548                jsonw_end_array(json_wtr);      /* root array */
 549
 550exit_free:
 551        free(fds);
 552        return err;
 553}
 554
 555static int do_show(int argc, char **argv)
 556{
 557        __u32 id = 0;
 558        int err;
 559        int fd;
 560
 561        if (show_pinned)
 562                build_pinned_obj_table(&prog_table, BPF_OBJ_PROG);
 563        build_obj_refs_table(&refs_table, BPF_OBJ_PROG);
 564
 565        if (argc == 2)
 566                return do_show_subset(argc, argv);
 567
 568        if (argc)
 569                return BAD_ARG();
 570
 571        if (json_output)
 572                jsonw_start_array(json_wtr);
 573        while (true) {
 574                err = bpf_prog_get_next_id(id, &id);
 575                if (err) {
 576                        if (errno == ENOENT) {
 577                                err = 0;
 578                                break;
 579                        }
 580                        p_err("can't get next program: %s%s", strerror(errno),
 581                              errno == EINVAL ? " -- kernel too old?" : "");
 582                        err = -1;
 583                        break;
 584                }
 585
 586                fd = bpf_prog_get_fd_by_id(id);
 587                if (fd < 0) {
 588                        if (errno == ENOENT)
 589                                continue;
 590                        p_err("can't get prog by id (%u): %s",
 591                              id, strerror(errno));
 592                        err = -1;
 593                        break;
 594                }
 595
 596                err = show_prog(fd);
 597                close(fd);
 598                if (err)
 599                        break;
 600        }
 601
 602        if (json_output)
 603                jsonw_end_array(json_wtr);
 604
 605        delete_obj_refs_table(&refs_table);
 606
 607        return err;
 608}
 609
 610static int
 611prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
 612          char *filepath, bool opcodes, bool visual, bool linum)
 613{
 614        struct bpf_prog_linfo *prog_linfo = NULL;
 615        const char *disasm_opt = NULL;
 616        struct dump_data dd = {};
 617        void *func_info = NULL;
 618        struct btf *btf = NULL;
 619        char func_sig[1024];
 620        unsigned char *buf;
 621        __u32 member_len;
 622        ssize_t n;
 623        int fd;
 624
 625        if (mode == DUMP_JITED) {
 626                if (info->jited_prog_len == 0 || !info->jited_prog_insns) {
 627                        p_info("no instructions returned");
 628                        return -1;
 629                }
 630                buf = u64_to_ptr(info->jited_prog_insns);
 631                member_len = info->jited_prog_len;
 632        } else {        /* DUMP_XLATED */
 633                if (info->xlated_prog_len == 0 || !info->xlated_prog_insns) {
 634                        p_err("error retrieving insn dump: kernel.kptr_restrict set?");
 635                        return -1;
 636                }
 637                buf = u64_to_ptr(info->xlated_prog_insns);
 638                member_len = info->xlated_prog_len;
 639        }
 640
 641        if (info->btf_id && btf__get_from_id(info->btf_id, &btf)) {
 642                p_err("failed to get btf");
 643                return -1;
 644        }
 645
 646        func_info = u64_to_ptr(info->func_info);
 647
 648        if (info->nr_line_info) {
 649                prog_linfo = bpf_prog_linfo__new(info);
 650                if (!prog_linfo)
 651                        p_info("error in processing bpf_line_info.  continue without it.");
 652        }
 653
 654        if (filepath) {
 655                fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
 656                if (fd < 0) {
 657                        p_err("can't open file %s: %s", filepath,
 658                              strerror(errno));
 659                        return -1;
 660                }
 661
 662                n = write(fd, buf, member_len);
 663                close(fd);
 664                if (n != (ssize_t)member_len) {
 665                        p_err("error writing output file: %s",
 666                              n < 0 ? strerror(errno) : "short write");
 667                        return -1;
 668                }
 669
 670                if (json_output)
 671                        jsonw_null(json_wtr);
 672        } else if (mode == DUMP_JITED) {
 673                const char *name = NULL;
 674
 675                if (info->ifindex) {
 676                        name = ifindex_to_bfd_params(info->ifindex,
 677                                                     info->netns_dev,
 678                                                     info->netns_ino,
 679                                                     &disasm_opt);
 680                        if (!name)
 681                                return -1;
 682                }
 683
 684                if (info->nr_jited_func_lens && info->jited_func_lens) {
 685                        struct kernel_sym *sym = NULL;
 686                        struct bpf_func_info *record;
 687                        char sym_name[SYM_MAX_NAME];
 688                        unsigned char *img = buf;
 689                        __u64 *ksyms = NULL;
 690                        __u32 *lens;
 691                        __u32 i;
 692                        if (info->nr_jited_ksyms) {
 693                                kernel_syms_load(&dd);
 694                                ksyms = u64_to_ptr(info->jited_ksyms);
 695                        }
 696
 697                        if (json_output)
 698                                jsonw_start_array(json_wtr);
 699
 700                        lens = u64_to_ptr(info->jited_func_lens);
 701                        for (i = 0; i < info->nr_jited_func_lens; i++) {
 702                                if (ksyms) {
 703                                        sym = kernel_syms_search(&dd, ksyms[i]);
 704                                        if (sym)
 705                                                sprintf(sym_name, "%s", sym->name);
 706                                        else
 707                                                sprintf(sym_name, "0x%016llx", ksyms[i]);
 708                                } else {
 709                                        strcpy(sym_name, "unknown");
 710                                }
 711
 712                                if (func_info) {
 713                                        record = func_info + i * info->func_info_rec_size;
 714                                        btf_dumper_type_only(btf, record->type_id,
 715                                                             func_sig,
 716                                                             sizeof(func_sig));
 717                                }
 718
 719                                if (json_output) {
 720                                        jsonw_start_object(json_wtr);
 721                                        if (func_info && func_sig[0] != '\0') {
 722                                                jsonw_name(json_wtr, "proto");
 723                                                jsonw_string(json_wtr, func_sig);
 724                                        }
 725                                        jsonw_name(json_wtr, "name");
 726                                        jsonw_string(json_wtr, sym_name);
 727                                        jsonw_name(json_wtr, "insns");
 728                                } else {
 729                                        if (func_info && func_sig[0] != '\0')
 730                                                printf("%s:\n", func_sig);
 731                                        printf("%s:\n", sym_name);
 732                                }
 733
 734                                disasm_print_insn(img, lens[i], opcodes,
 735                                                  name, disasm_opt, btf,
 736                                                  prog_linfo, ksyms[i], i,
 737                                                  linum);
 738
 739                                img += lens[i];
 740
 741                                if (json_output)
 742                                        jsonw_end_object(json_wtr);
 743                                else
 744                                        printf("\n");
 745                        }
 746
 747                        if (json_output)
 748                                jsonw_end_array(json_wtr);
 749                } else {
 750                        disasm_print_insn(buf, member_len, opcodes, name,
 751                                          disasm_opt, btf, NULL, 0, 0, false);
 752                }
 753        } else if (visual) {
 754                if (json_output)
 755                        jsonw_null(json_wtr);
 756                else
 757                        dump_xlated_cfg(buf, member_len);
 758        } else {
 759                kernel_syms_load(&dd);
 760                dd.nr_jited_ksyms = info->nr_jited_ksyms;
 761                dd.jited_ksyms = u64_to_ptr(info->jited_ksyms);
 762                dd.btf = btf;
 763                dd.func_info = func_info;
 764                dd.finfo_rec_size = info->func_info_rec_size;
 765                dd.prog_linfo = prog_linfo;
 766
 767                if (json_output)
 768                        dump_xlated_json(&dd, buf, member_len, opcodes,
 769                                         linum);
 770                else
 771                        dump_xlated_plain(&dd, buf, member_len, opcodes,
 772                                          linum);
 773                kernel_syms_destroy(&dd);
 774        }
 775
 776        return 0;
 777}
 778
 779static int do_dump(int argc, char **argv)
 780{
 781        struct bpf_prog_info_linear *info_linear;
 782        char *filepath = NULL;
 783        bool opcodes = false;
 784        bool visual = false;
 785        enum dump_mode mode;
 786        bool linum = false;
 787        int *fds = NULL;
 788        int nb_fds, i = 0;
 789        int err = -1;
 790        __u64 arrays;
 791
 792        if (is_prefix(*argv, "jited")) {
 793                if (disasm_init())
 794                        return -1;
 795                mode = DUMP_JITED;
 796        } else if (is_prefix(*argv, "xlated")) {
 797                mode = DUMP_XLATED;
 798        } else {
 799                p_err("expected 'xlated' or 'jited', got: %s", *argv);
 800                return -1;
 801        }
 802        NEXT_ARG();
 803
 804        if (argc < 2)
 805                usage();
 806
 807        fds = malloc(sizeof(int));
 808        if (!fds) {
 809                p_err("mem alloc failed");
 810                return -1;
 811        }
 812        nb_fds = prog_parse_fds(&argc, &argv, &fds);
 813        if (nb_fds < 1)
 814                goto exit_free;
 815
 816        if (is_prefix(*argv, "file")) {
 817                NEXT_ARG();
 818                if (!argc) {
 819                        p_err("expected file path");
 820                        goto exit_close;
 821                }
 822                if (nb_fds > 1) {
 823                        p_err("several programs matched");
 824                        goto exit_close;
 825                }
 826
 827                filepath = *argv;
 828                NEXT_ARG();
 829        } else if (is_prefix(*argv, "opcodes")) {
 830                opcodes = true;
 831                NEXT_ARG();
 832        } else if (is_prefix(*argv, "visual")) {
 833                if (nb_fds > 1) {
 834                        p_err("several programs matched");
 835                        goto exit_close;
 836                }
 837
 838                visual = true;
 839                NEXT_ARG();
 840        } else if (is_prefix(*argv, "linum")) {
 841                linum = true;
 842                NEXT_ARG();
 843        }
 844
 845        if (argc) {
 846                usage();
 847                goto exit_close;
 848        }
 849
 850        if (mode == DUMP_JITED)
 851                arrays = 1UL << BPF_PROG_INFO_JITED_INSNS;
 852        else
 853                arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS;
 854
 855        arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS;
 856        arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
 857        arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
 858        arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
 859        arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
 860
 861        if (json_output && nb_fds > 1)
 862                jsonw_start_array(json_wtr);    /* root array */
 863        for (i = 0; i < nb_fds; i++) {
 864                info_linear = bpf_program__get_prog_info_linear(fds[i], arrays);
 865                if (IS_ERR_OR_NULL(info_linear)) {
 866                        p_err("can't get prog info: %s", strerror(errno));
 867                        break;
 868                }
 869
 870                if (json_output && nb_fds > 1) {
 871                        jsonw_start_object(json_wtr);   /* prog object */
 872                        print_prog_header_json(&info_linear->info);
 873                        jsonw_name(json_wtr, "insns");
 874                } else if (nb_fds > 1) {
 875                        print_prog_header_plain(&info_linear->info);
 876                }
 877
 878                err = prog_dump(&info_linear->info, mode, filepath, opcodes,
 879                                visual, linum);
 880
 881                if (json_output && nb_fds > 1)
 882                        jsonw_end_object(json_wtr);     /* prog object */
 883                else if (i != nb_fds - 1 && nb_fds > 1)
 884                        printf("\n");
 885
 886                free(info_linear);
 887                if (err)
 888                        break;
 889                close(fds[i]);
 890        }
 891        if (json_output && nb_fds > 1)
 892                jsonw_end_array(json_wtr);      /* root array */
 893
 894exit_close:
 895        for (; i < nb_fds; i++)
 896                close(fds[i]);
 897exit_free:
 898        free(fds);
 899        return err;
 900}
 901
 902static int do_pin(int argc, char **argv)
 903{
 904        int err;
 905
 906        err = do_pin_any(argc, argv, prog_parse_fd);
 907        if (!err && json_output)
 908                jsonw_null(json_wtr);
 909        return err;
 910}
 911
 912struct map_replace {
 913        int idx;
 914        int fd;
 915        char *name;
 916};
 917
 918static int map_replace_compar(const void *p1, const void *p2)
 919{
 920        const struct map_replace *a = p1, *b = p2;
 921
 922        return a->idx - b->idx;
 923}
 924
 925static int parse_attach_detach_args(int argc, char **argv, int *progfd,
 926                                    enum bpf_attach_type *attach_type,
 927                                    int *mapfd)
 928{
 929        if (!REQ_ARGS(3))
 930                return -EINVAL;
 931
 932        *progfd = prog_parse_fd(&argc, &argv);
 933        if (*progfd < 0)
 934                return *progfd;
 935
 936        *attach_type = parse_attach_type(*argv);
 937        if (*attach_type == __MAX_BPF_ATTACH_TYPE) {
 938                p_err("invalid attach/detach type");
 939                return -EINVAL;
 940        }
 941
 942        if (*attach_type == BPF_FLOW_DISSECTOR) {
 943                *mapfd = 0;
 944                return 0;
 945        }
 946
 947        NEXT_ARG();
 948        if (!REQ_ARGS(2))
 949                return -EINVAL;
 950
 951        *mapfd = map_parse_fd(&argc, &argv);
 952        if (*mapfd < 0)
 953                return *mapfd;
 954
 955        return 0;
 956}
 957
 958static int do_attach(int argc, char **argv)
 959{
 960        enum bpf_attach_type attach_type;
 961        int err, progfd;
 962        int mapfd;
 963
 964        err = parse_attach_detach_args(argc, argv,
 965                                       &progfd, &attach_type, &mapfd);
 966        if (err)
 967                return err;
 968
 969        err = bpf_prog_attach(progfd, mapfd, attach_type, 0);
 970        if (err) {
 971                p_err("failed prog attach to map");
 972                return -EINVAL;
 973        }
 974
 975        if (json_output)
 976                jsonw_null(json_wtr);
 977        return 0;
 978}
 979
 980static int do_detach(int argc, char **argv)
 981{
 982        enum bpf_attach_type attach_type;
 983        int err, progfd;
 984        int mapfd;
 985
 986        err = parse_attach_detach_args(argc, argv,
 987                                       &progfd, &attach_type, &mapfd);
 988        if (err)
 989                return err;
 990
 991        err = bpf_prog_detach2(progfd, mapfd, attach_type);
 992        if (err) {
 993                p_err("failed prog detach from map");
 994                return -EINVAL;
 995        }
 996
 997        if (json_output)
 998                jsonw_null(json_wtr);
 999        return 0;
1000}
1001
1002static int check_single_stdin(char *file_data_in, char *file_ctx_in)
1003{
1004        if (file_data_in && file_ctx_in &&
1005            !strcmp(file_data_in, "-") && !strcmp(file_ctx_in, "-")) {
1006                p_err("cannot use standard input for both data_in and ctx_in");
1007                return -1;
1008        }
1009
1010        return 0;
1011}
1012
1013static int get_run_data(const char *fname, void **data_ptr, unsigned int *size)
1014{
1015        size_t block_size = 256;
1016        size_t buf_size = block_size;
1017        size_t nb_read = 0;
1018        void *tmp;
1019        FILE *f;
1020
1021        if (!fname) {
1022                *data_ptr = NULL;
1023                *size = 0;
1024                return 0;
1025        }
1026
1027        if (!strcmp(fname, "-"))
1028                f = stdin;
1029        else
1030                f = fopen(fname, "r");
1031        if (!f) {
1032                p_err("failed to open %s: %s", fname, strerror(errno));
1033                return -1;
1034        }
1035
1036        *data_ptr = malloc(block_size);
1037        if (!*data_ptr) {
1038                p_err("failed to allocate memory for data_in/ctx_in: %s",
1039                      strerror(errno));
1040                goto err_fclose;
1041        }
1042
1043        while ((nb_read += fread(*data_ptr + nb_read, 1, block_size, f))) {
1044                if (feof(f))
1045                        break;
1046                if (ferror(f)) {
1047                        p_err("failed to read data_in/ctx_in from %s: %s",
1048                              fname, strerror(errno));
1049                        goto err_free;
1050                }
1051                if (nb_read > buf_size - block_size) {
1052                        if (buf_size == UINT32_MAX) {
1053                                p_err("data_in/ctx_in is too long (max: %d)",
1054                                      UINT32_MAX);
1055                                goto err_free;
1056                        }
1057                        /* No space for fread()-ing next chunk; realloc() */
1058                        buf_size *= 2;
1059                        tmp = realloc(*data_ptr, buf_size);
1060                        if (!tmp) {
1061                                p_err("failed to reallocate data_in/ctx_in: %s",
1062                                      strerror(errno));
1063                                goto err_free;
1064                        }
1065                        *data_ptr = tmp;
1066                }
1067        }
1068        if (f != stdin)
1069                fclose(f);
1070
1071        *size = nb_read;
1072        return 0;
1073
1074err_free:
1075        free(*data_ptr);
1076        *data_ptr = NULL;
1077err_fclose:
1078        if (f != stdin)
1079                fclose(f);
1080        return -1;
1081}
1082
1083static void hex_print(void *data, unsigned int size, FILE *f)
1084{
1085        size_t i, j;
1086        char c;
1087
1088        for (i = 0; i < size; i += 16) {
1089                /* Row offset */
1090                fprintf(f, "%07zx\t", i);
1091
1092                /* Hexadecimal values */
1093                for (j = i; j < i + 16 && j < size; j++)
1094                        fprintf(f, "%02x%s", *(uint8_t *)(data + j),
1095                                j % 2 ? " " : "");
1096                for (; j < i + 16; j++)
1097                        fprintf(f, "  %s", j % 2 ? " " : "");
1098
1099                /* ASCII values (if relevant), '.' otherwise */
1100                fprintf(f, "| ");
1101                for (j = i; j < i + 16 && j < size; j++) {
1102                        c = *(char *)(data + j);
1103                        if (c < ' ' || c > '~')
1104                                c = '.';
1105                        fprintf(f, "%c%s", c, j == i + 7 ? " " : "");
1106                }
1107
1108                fprintf(f, "\n");
1109        }
1110}
1111
1112static int
1113print_run_output(void *data, unsigned int size, const char *fname,
1114                 const char *json_key)
1115{
1116        size_t nb_written;
1117        FILE *f;
1118
1119        if (!fname)
1120                return 0;
1121
1122        if (!strcmp(fname, "-")) {
1123                f = stdout;
1124                if (json_output) {
1125                        jsonw_name(json_wtr, json_key);
1126                        print_data_json(data, size);
1127                } else {
1128                        hex_print(data, size, f);
1129                }
1130                return 0;
1131        }
1132
1133        f = fopen(fname, "w");
1134        if (!f) {
1135                p_err("failed to open %s: %s", fname, strerror(errno));
1136                return -1;
1137        }
1138
1139        nb_written = fwrite(data, 1, size, f);
1140        fclose(f);
1141        if (nb_written != size) {
1142                p_err("failed to write output data/ctx: %s", strerror(errno));
1143                return -1;
1144        }
1145
1146        return 0;
1147}
1148
1149static int alloc_run_data(void **data_ptr, unsigned int size_out)
1150{
1151        *data_ptr = calloc(size_out, 1);
1152        if (!*data_ptr) {
1153                p_err("failed to allocate memory for output data/ctx: %s",
1154                      strerror(errno));
1155                return -1;
1156        }
1157
1158        return 0;
1159}
1160
1161static int do_run(int argc, char **argv)
1162{
1163        char *data_fname_in = NULL, *data_fname_out = NULL;
1164        char *ctx_fname_in = NULL, *ctx_fname_out = NULL;
1165        struct bpf_prog_test_run_attr test_attr = {0};
1166        const unsigned int default_size = SZ_32K;
1167        void *data_in = NULL, *data_out = NULL;
1168        void *ctx_in = NULL, *ctx_out = NULL;
1169        unsigned int repeat = 1;
1170        int fd, err;
1171
1172        if (!REQ_ARGS(4))
1173                return -1;
1174
1175        fd = prog_parse_fd(&argc, &argv);
1176        if (fd < 0)
1177                return -1;
1178
1179        while (argc) {
1180                if (detect_common_prefix(*argv, "data_in", "data_out",
1181                                         "data_size_out", NULL))
1182                        return -1;
1183                if (detect_common_prefix(*argv, "ctx_in", "ctx_out",
1184                                         "ctx_size_out", NULL))
1185                        return -1;
1186
1187                if (is_prefix(*argv, "data_in")) {
1188                        NEXT_ARG();
1189                        if (!REQ_ARGS(1))
1190                                return -1;
1191
1192                        data_fname_in = GET_ARG();
1193                        if (check_single_stdin(data_fname_in, ctx_fname_in))
1194                                return -1;
1195                } else if (is_prefix(*argv, "data_out")) {
1196                        NEXT_ARG();
1197                        if (!REQ_ARGS(1))
1198                                return -1;
1199
1200                        data_fname_out = GET_ARG();
1201                } else if (is_prefix(*argv, "data_size_out")) {
1202                        char *endptr;
1203
1204                        NEXT_ARG();
1205                        if (!REQ_ARGS(1))
1206                                return -1;
1207
1208                        test_attr.data_size_out = strtoul(*argv, &endptr, 0);
1209                        if (*endptr) {
1210                                p_err("can't parse %s as output data size",
1211                                      *argv);
1212                                return -1;
1213                        }
1214                        NEXT_ARG();
1215                } else if (is_prefix(*argv, "ctx_in")) {
1216                        NEXT_ARG();
1217                        if (!REQ_ARGS(1))
1218                                return -1;
1219
1220                        ctx_fname_in = GET_ARG();
1221                        if (check_single_stdin(data_fname_in, ctx_fname_in))
1222                                return -1;
1223                } else if (is_prefix(*argv, "ctx_out")) {
1224                        NEXT_ARG();
1225                        if (!REQ_ARGS(1))
1226                                return -1;
1227
1228                        ctx_fname_out = GET_ARG();
1229                } else if (is_prefix(*argv, "ctx_size_out")) {
1230                        char *endptr;
1231
1232                        NEXT_ARG();
1233                        if (!REQ_ARGS(1))
1234                                return -1;
1235
1236                        test_attr.ctx_size_out = strtoul(*argv, &endptr, 0);
1237                        if (*endptr) {
1238                                p_err("can't parse %s as output context size",
1239                                      *argv);
1240                                return -1;
1241                        }
1242                        NEXT_ARG();
1243                } else if (is_prefix(*argv, "repeat")) {
1244                        char *endptr;
1245
1246                        NEXT_ARG();
1247                        if (!REQ_ARGS(1))
1248                                return -1;
1249
1250                        repeat = strtoul(*argv, &endptr, 0);
1251                        if (*endptr) {
1252                                p_err("can't parse %s as repeat number",
1253                                      *argv);
1254                                return -1;
1255                        }
1256                        NEXT_ARG();
1257                } else {
1258                        p_err("expected no more arguments, 'data_in', 'data_out', 'data_size_out', 'ctx_in', 'ctx_out', 'ctx_size_out' or 'repeat', got: '%s'?",
1259                              *argv);
1260                        return -1;
1261                }
1262        }
1263
1264        err = get_run_data(data_fname_in, &data_in, &test_attr.data_size_in);
1265        if (err)
1266                return -1;
1267
1268        if (data_in) {
1269                if (!test_attr.data_size_out)
1270                        test_attr.data_size_out = default_size;
1271                err = alloc_run_data(&data_out, test_attr.data_size_out);
1272                if (err)
1273                        goto free_data_in;
1274        }
1275
1276        err = get_run_data(ctx_fname_in, &ctx_in, &test_attr.ctx_size_in);
1277        if (err)
1278                goto free_data_out;
1279
1280        if (ctx_in) {
1281                if (!test_attr.ctx_size_out)
1282                        test_attr.ctx_size_out = default_size;
1283                err = alloc_run_data(&ctx_out, test_attr.ctx_size_out);
1284                if (err)
1285                        goto free_ctx_in;
1286        }
1287
1288        test_attr.prog_fd       = fd;
1289        test_attr.repeat        = repeat;
1290        test_attr.data_in       = data_in;
1291        test_attr.data_out      = data_out;
1292        test_attr.ctx_in        = ctx_in;
1293        test_attr.ctx_out       = ctx_out;
1294
1295        err = bpf_prog_test_run_xattr(&test_attr);
1296        if (err) {
1297                p_err("failed to run program: %s", strerror(errno));
1298                goto free_ctx_out;
1299        }
1300
1301        err = 0;
1302
1303        if (json_output)
1304                jsonw_start_object(json_wtr);   /* root */
1305
1306        /* Do not exit on errors occurring when printing output data/context,
1307         * we still want to print return value and duration for program run.
1308         */
1309        if (test_attr.data_size_out)
1310                err += print_run_output(test_attr.data_out,
1311                                        test_attr.data_size_out,
1312                                        data_fname_out, "data_out");
1313        if (test_attr.ctx_size_out)
1314                err += print_run_output(test_attr.ctx_out,
1315                                        test_attr.ctx_size_out,
1316                                        ctx_fname_out, "ctx_out");
1317
1318        if (json_output) {
1319                jsonw_uint_field(json_wtr, "retval", test_attr.retval);
1320                jsonw_uint_field(json_wtr, "duration", test_attr.duration);
1321                jsonw_end_object(json_wtr);     /* root */
1322        } else {
1323                fprintf(stdout, "Return value: %u, duration%s: %uns\n",
1324                        test_attr.retval,
1325                        repeat > 1 ? " (average)" : "", test_attr.duration);
1326        }
1327
1328free_ctx_out:
1329        free(ctx_out);
1330free_ctx_in:
1331        free(ctx_in);
1332free_data_out:
1333        free(data_out);
1334free_data_in:
1335        free(data_in);
1336
1337        return err;
1338}
1339
1340static int
1341get_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
1342                      enum bpf_attach_type *expected_attach_type)
1343{
1344        libbpf_print_fn_t print_backup;
1345        int ret;
1346
1347        ret = libbpf_prog_type_by_name(name, prog_type, expected_attach_type);
1348        if (!ret)
1349                return ret;
1350
1351        /* libbpf_prog_type_by_name() failed, let's re-run with debug level */
1352        print_backup = libbpf_set_print(print_all_levels);
1353        ret = libbpf_prog_type_by_name(name, prog_type, expected_attach_type);
1354        libbpf_set_print(print_backup);
1355
1356        return ret;
1357}
1358
1359static int load_with_options(int argc, char **argv, bool first_prog_only)
1360{
1361        enum bpf_prog_type common_prog_type = BPF_PROG_TYPE_UNSPEC;
1362        DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts,
1363                .relaxed_maps = relaxed_maps,
1364        );
1365        struct bpf_object_load_attr load_attr = { 0 };
1366        enum bpf_attach_type expected_attach_type;
1367        struct map_replace *map_replace = NULL;
1368        struct bpf_program *prog = NULL, *pos;
1369        unsigned int old_map_fds = 0;
1370        const char *pinmaps = NULL;
1371        struct bpf_object *obj;
1372        struct bpf_map *map;
1373        const char *pinfile;
1374        unsigned int i, j;
1375        __u32 ifindex = 0;
1376        const char *file;
1377        int idx, err;
1378
1379
1380        if (!REQ_ARGS(2))
1381                return -1;
1382        file = GET_ARG();
1383        pinfile = GET_ARG();
1384
1385        while (argc) {
1386                if (is_prefix(*argv, "type")) {
1387                        char *type;
1388
1389                        NEXT_ARG();
1390
1391                        if (common_prog_type != BPF_PROG_TYPE_UNSPEC) {
1392                                p_err("program type already specified");
1393                                goto err_free_reuse_maps;
1394                        }
1395                        if (!REQ_ARGS(1))
1396                                goto err_free_reuse_maps;
1397
1398                        /* Put a '/' at the end of type to appease libbpf */
1399                        type = malloc(strlen(*argv) + 2);
1400                        if (!type) {
1401                                p_err("mem alloc failed");
1402                                goto err_free_reuse_maps;
1403                        }
1404                        *type = 0;
1405                        strcat(type, *argv);
1406                        strcat(type, "/");
1407
1408                        err = get_prog_type_by_name(type, &common_prog_type,
1409                                                    &expected_attach_type);
1410                        free(type);
1411                        if (err < 0)
1412                                goto err_free_reuse_maps;
1413
1414                        NEXT_ARG();
1415                } else if (is_prefix(*argv, "map")) {
1416                        void *new_map_replace;
1417                        char *endptr, *name;
1418                        int fd;
1419
1420                        NEXT_ARG();
1421
1422                        if (!REQ_ARGS(4))
1423                                goto err_free_reuse_maps;
1424
1425                        if (is_prefix(*argv, "idx")) {
1426                                NEXT_ARG();
1427
1428                                idx = strtoul(*argv, &endptr, 0);
1429                                if (*endptr) {
1430                                        p_err("can't parse %s as IDX", *argv);
1431                                        goto err_free_reuse_maps;
1432                                }
1433                                name = NULL;
1434                        } else if (is_prefix(*argv, "name")) {
1435                                NEXT_ARG();
1436
1437                                name = *argv;
1438                                idx = -1;
1439                        } else {
1440                                p_err("expected 'idx' or 'name', got: '%s'?",
1441                                      *argv);
1442                                goto err_free_reuse_maps;
1443                        }
1444                        NEXT_ARG();
1445
1446                        fd = map_parse_fd(&argc, &argv);
1447                        if (fd < 0)
1448                                goto err_free_reuse_maps;
1449
1450                        new_map_replace = reallocarray(map_replace,
1451                                                       old_map_fds + 1,
1452                                                       sizeof(*map_replace));
1453                        if (!new_map_replace) {
1454                                p_err("mem alloc failed");
1455                                goto err_free_reuse_maps;
1456                        }
1457                        map_replace = new_map_replace;
1458
1459                        map_replace[old_map_fds].idx = idx;
1460                        map_replace[old_map_fds].name = name;
1461                        map_replace[old_map_fds].fd = fd;
1462                        old_map_fds++;
1463                } else if (is_prefix(*argv, "dev")) {
1464                        NEXT_ARG();
1465
1466                        if (ifindex) {
1467                                p_err("offload device already specified");
1468                                goto err_free_reuse_maps;
1469                        }
1470                        if (!REQ_ARGS(1))
1471                                goto err_free_reuse_maps;
1472
1473                        ifindex = if_nametoindex(*argv);
1474                        if (!ifindex) {
1475                                p_err("unrecognized netdevice '%s': %s",
1476                                      *argv, strerror(errno));
1477                                goto err_free_reuse_maps;
1478                        }
1479                        NEXT_ARG();
1480                } else if (is_prefix(*argv, "pinmaps")) {
1481                        NEXT_ARG();
1482
1483                        if (!REQ_ARGS(1))
1484                                goto err_free_reuse_maps;
1485
1486                        pinmaps = GET_ARG();
1487                } else {
1488                        p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?",
1489                              *argv);
1490                        goto err_free_reuse_maps;
1491                }
1492        }
1493
1494        set_max_rlimit();
1495
1496        obj = bpf_object__open_file(file, &open_opts);
1497        if (IS_ERR_OR_NULL(obj)) {
1498                p_err("failed to open object file");
1499                goto err_free_reuse_maps;
1500        }
1501
1502        bpf_object__for_each_program(pos, obj) {
1503                enum bpf_prog_type prog_type = common_prog_type;
1504
1505                if (prog_type == BPF_PROG_TYPE_UNSPEC) {
1506                        const char *sec_name = bpf_program__section_name(pos);
1507
1508                        err = get_prog_type_by_name(sec_name, &prog_type,
1509                                                    &expected_attach_type);
1510                        if (err < 0)
1511                                goto err_close_obj;
1512                }
1513
1514                bpf_program__set_ifindex(pos, ifindex);
1515                bpf_program__set_type(pos, prog_type);
1516                bpf_program__set_expected_attach_type(pos, expected_attach_type);
1517        }
1518
1519        qsort(map_replace, old_map_fds, sizeof(*map_replace),
1520              map_replace_compar);
1521
1522        /* After the sort maps by name will be first on the list, because they
1523         * have idx == -1.  Resolve them.
1524         */
1525        j = 0;
1526        while (j < old_map_fds && map_replace[j].name) {
1527                i = 0;
1528                bpf_object__for_each_map(map, obj) {
1529                        if (!strcmp(bpf_map__name(map), map_replace[j].name)) {
1530                                map_replace[j].idx = i;
1531                                break;
1532                        }
1533                        i++;
1534                }
1535                if (map_replace[j].idx == -1) {
1536                        p_err("unable to find map '%s'", map_replace[j].name);
1537                        goto err_close_obj;
1538                }
1539                j++;
1540        }
1541        /* Resort if any names were resolved */
1542        if (j)
1543                qsort(map_replace, old_map_fds, sizeof(*map_replace),
1544                      map_replace_compar);
1545
1546        /* Set ifindex and name reuse */
1547        j = 0;
1548        idx = 0;
1549        bpf_object__for_each_map(map, obj) {
1550                if (!bpf_map__is_offload_neutral(map))
1551                        bpf_map__set_ifindex(map, ifindex);
1552
1553                if (j < old_map_fds && idx == map_replace[j].idx) {
1554                        err = bpf_map__reuse_fd(map, map_replace[j++].fd);
1555                        if (err) {
1556                                p_err("unable to set up map reuse: %d", err);
1557                                goto err_close_obj;
1558                        }
1559
1560                        /* Next reuse wants to apply to the same map */
1561                        if (j < old_map_fds && map_replace[j].idx == idx) {
1562                                p_err("replacement for map idx %d specified more than once",
1563                                      idx);
1564                                goto err_close_obj;
1565                        }
1566                }
1567
1568                idx++;
1569        }
1570        if (j < old_map_fds) {
1571                p_err("map idx '%d' not used", map_replace[j].idx);
1572                goto err_close_obj;
1573        }
1574
1575        load_attr.obj = obj;
1576        if (verifier_logs)
1577                /* log_level1 + log_level2 + stats, but not stable UAPI */
1578                load_attr.log_level = 1 + 2 + 4;
1579
1580        err = bpf_object__load_xattr(&load_attr);
1581        if (err) {
1582                p_err("failed to load object file");
1583                goto err_close_obj;
1584        }
1585
1586        err = mount_bpffs_for_pin(pinfile);
1587        if (err)
1588                goto err_close_obj;
1589
1590        if (first_prog_only) {
1591                prog = bpf_program__next(NULL, obj);
1592                if (!prog) {
1593                        p_err("object file doesn't contain any bpf program");
1594                        goto err_close_obj;
1595                }
1596
1597                err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
1598                if (err) {
1599                        p_err("failed to pin program %s",
1600                              bpf_program__section_name(prog));
1601                        goto err_close_obj;
1602                }
1603        } else {
1604                err = bpf_object__pin_programs(obj, pinfile);
1605                if (err) {
1606                        p_err("failed to pin all programs");
1607                        goto err_close_obj;
1608                }
1609        }
1610
1611        if (pinmaps) {
1612                err = bpf_object__pin_maps(obj, pinmaps);
1613                if (err) {
1614                        p_err("failed to pin all maps");
1615                        goto err_unpin;
1616                }
1617        }
1618
1619        if (json_output)
1620                jsonw_null(json_wtr);
1621
1622        bpf_object__close(obj);
1623        for (i = 0; i < old_map_fds; i++)
1624                close(map_replace[i].fd);
1625        free(map_replace);
1626
1627        return 0;
1628
1629err_unpin:
1630        if (first_prog_only)
1631                unlink(pinfile);
1632        else
1633                bpf_object__unpin_programs(obj, pinfile);
1634err_close_obj:
1635        bpf_object__close(obj);
1636err_free_reuse_maps:
1637        for (i = 0; i < old_map_fds; i++)
1638                close(map_replace[i].fd);
1639        free(map_replace);
1640        return -1;
1641}
1642
1643static int do_load(int argc, char **argv)
1644{
1645        return load_with_options(argc, argv, true);
1646}
1647
1648static int do_loadall(int argc, char **argv)
1649{
1650        return load_with_options(argc, argv, false);
1651}
1652
1653#ifdef BPFTOOL_WITHOUT_SKELETONS
1654
1655static int do_profile(int argc, char **argv)
1656{
1657        p_err("bpftool prog profile command is not supported. Please build bpftool with clang >= 10.0.0");
1658        return 0;
1659}
1660
1661#else /* BPFTOOL_WITHOUT_SKELETONS */
1662
1663#include "profiler.skel.h"
1664
1665struct profile_metric {
1666        const char *name;
1667        struct bpf_perf_event_value val;
1668        struct perf_event_attr attr;
1669        bool selected;
1670
1671        /* calculate ratios like instructions per cycle */
1672        const int ratio_metric; /* 0 for N/A, 1 for index 0 (cycles) */
1673        const char *ratio_desc;
1674        const float ratio_mul;
1675} metrics[] = {
1676        {
1677                .name = "cycles",
1678                .attr = {
1679                        .type = PERF_TYPE_HARDWARE,
1680                        .config = PERF_COUNT_HW_CPU_CYCLES,
1681                        .exclude_user = 1,
1682                },
1683        },
1684        {
1685                .name = "instructions",
1686                .attr = {
1687                        .type = PERF_TYPE_HARDWARE,
1688                        .config = PERF_COUNT_HW_INSTRUCTIONS,
1689                        .exclude_user = 1,
1690                },
1691                .ratio_metric = 1,
1692                .ratio_desc = "insns per cycle",
1693                .ratio_mul = 1.0,
1694        },
1695        {
1696                .name = "l1d_loads",
1697                .attr = {
1698                        .type = PERF_TYPE_HW_CACHE,
1699                        .config =
1700                                PERF_COUNT_HW_CACHE_L1D |
1701                                (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1702                                (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
1703                        .exclude_user = 1,
1704                },
1705        },
1706        {
1707                .name = "llc_misses",
1708                .attr = {
1709                        .type = PERF_TYPE_HW_CACHE,
1710                        .config =
1711                                PERF_COUNT_HW_CACHE_LL |
1712                                (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1713                                (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
1714                        .exclude_user = 1
1715                },
1716                .ratio_metric = 2,
1717                .ratio_desc = "LLC misses per million insns",
1718                .ratio_mul = 1e6,
1719        },
1720};
1721
1722static __u64 profile_total_count;
1723
1724#define MAX_NUM_PROFILE_METRICS 4
1725
1726static int profile_parse_metrics(int argc, char **argv)
1727{
1728        unsigned int metric_cnt;
1729        int selected_cnt = 0;
1730        unsigned int i;
1731
1732        metric_cnt = sizeof(metrics) / sizeof(struct profile_metric);
1733
1734        while (argc > 0) {
1735                for (i = 0; i < metric_cnt; i++) {
1736                        if (is_prefix(argv[0], metrics[i].name)) {
1737                                if (!metrics[i].selected)
1738                                        selected_cnt++;
1739                                metrics[i].selected = true;
1740                                break;
1741                        }
1742                }
1743                if (i == metric_cnt) {
1744                        p_err("unknown metric %s", argv[0]);
1745                        return -1;
1746                }
1747                NEXT_ARG();
1748        }
1749        if (selected_cnt > MAX_NUM_PROFILE_METRICS) {
1750                p_err("too many (%d) metrics, please specify no more than %d metrics at at time",
1751                      selected_cnt, MAX_NUM_PROFILE_METRICS);
1752                return -1;
1753        }
1754        return selected_cnt;
1755}
1756
1757static void profile_read_values(struct profiler_bpf *obj)
1758{
1759        __u32 m, cpu, num_cpu = obj->rodata->num_cpu;
1760        int reading_map_fd, count_map_fd;
1761        __u64 counts[num_cpu];
1762        __u32 key = 0;
1763        int err;
1764
1765        reading_map_fd = bpf_map__fd(obj->maps.accum_readings);
1766        count_map_fd = bpf_map__fd(obj->maps.counts);
1767        if (reading_map_fd < 0 || count_map_fd < 0) {
1768                p_err("failed to get fd for map");
1769                return;
1770        }
1771
1772        err = bpf_map_lookup_elem(count_map_fd, &key, counts);
1773        if (err) {
1774                p_err("failed to read count_map: %s", strerror(errno));
1775                return;
1776        }
1777
1778        profile_total_count = 0;
1779        for (cpu = 0; cpu < num_cpu; cpu++)
1780                profile_total_count += counts[cpu];
1781
1782        for (m = 0; m < ARRAY_SIZE(metrics); m++) {
1783                struct bpf_perf_event_value values[num_cpu];
1784
1785                if (!metrics[m].selected)
1786                        continue;
1787
1788                err = bpf_map_lookup_elem(reading_map_fd, &key, values);
1789                if (err) {
1790                        p_err("failed to read reading_map: %s",
1791                              strerror(errno));
1792                        return;
1793                }
1794                for (cpu = 0; cpu < num_cpu; cpu++) {
1795                        metrics[m].val.counter += values[cpu].counter;
1796                        metrics[m].val.enabled += values[cpu].enabled;
1797                        metrics[m].val.running += values[cpu].running;
1798                }
1799                key++;
1800        }
1801}
1802
1803static void profile_print_readings_json(void)
1804{
1805        __u32 m;
1806
1807        jsonw_start_array(json_wtr);
1808        for (m = 0; m < ARRAY_SIZE(metrics); m++) {
1809                if (!metrics[m].selected)
1810                        continue;
1811                jsonw_start_object(json_wtr);
1812                jsonw_string_field(json_wtr, "metric", metrics[m].name);
1813                jsonw_lluint_field(json_wtr, "run_cnt", profile_total_count);
1814                jsonw_lluint_field(json_wtr, "value", metrics[m].val.counter);
1815                jsonw_lluint_field(json_wtr, "enabled", metrics[m].val.enabled);
1816                jsonw_lluint_field(json_wtr, "running", metrics[m].val.running);
1817
1818                jsonw_end_object(json_wtr);
1819        }
1820        jsonw_end_array(json_wtr);
1821}
1822
1823static void profile_print_readings_plain(void)
1824{
1825        __u32 m;
1826
1827        printf("\n%18llu %-20s\n", profile_total_count, "run_cnt");
1828        for (m = 0; m < ARRAY_SIZE(metrics); m++) {
1829                struct bpf_perf_event_value *val = &metrics[m].val;
1830                int r;
1831
1832                if (!metrics[m].selected)
1833                        continue;
1834                printf("%18llu %-20s", val->counter, metrics[m].name);
1835
1836                r = metrics[m].ratio_metric - 1;
1837                if (r >= 0 && metrics[r].selected &&
1838                    metrics[r].val.counter > 0) {
1839                        printf("# %8.2f %-30s",
1840                               val->counter * metrics[m].ratio_mul /
1841                               metrics[r].val.counter,
1842                               metrics[m].ratio_desc);
1843                } else {
1844                        printf("%-41s", "");
1845                }
1846
1847                if (val->enabled > val->running)
1848                        printf("(%4.2f%%)",
1849                               val->running * 100.0 / val->enabled);
1850                printf("\n");
1851        }
1852}
1853
1854static void profile_print_readings(void)
1855{
1856        if (json_output)
1857                profile_print_readings_json();
1858        else
1859                profile_print_readings_plain();
1860}
1861
1862static char *profile_target_name(int tgt_fd)
1863{
1864        struct bpf_prog_info_linear *info_linear;
1865        struct bpf_func_info *func_info;
1866        const struct btf_type *t;
1867        char *name = NULL;
1868        struct btf *btf;
1869
1870        info_linear = bpf_program__get_prog_info_linear(
1871                tgt_fd, 1UL << BPF_PROG_INFO_FUNC_INFO);
1872        if (IS_ERR_OR_NULL(info_linear)) {
1873                p_err("failed to get info_linear for prog FD %d", tgt_fd);
1874                return NULL;
1875        }
1876
1877        if (info_linear->info.btf_id == 0 ||
1878            btf__get_from_id(info_linear->info.btf_id, &btf)) {
1879                p_err("prog FD %d doesn't have valid btf", tgt_fd);
1880                goto out;
1881        }
1882
1883        func_info = u64_to_ptr(info_linear->info.func_info);
1884        t = btf__type_by_id(btf, func_info[0].type_id);
1885        if (!t) {
1886                p_err("btf %d doesn't have type %d",
1887                      info_linear->info.btf_id, func_info[0].type_id);
1888                goto out;
1889        }
1890        name = strdup(btf__name_by_offset(btf, t->name_off));
1891out:
1892        free(info_linear);
1893        return name;
1894}
1895
1896static struct profiler_bpf *profile_obj;
1897static int profile_tgt_fd = -1;
1898static char *profile_tgt_name;
1899static int *profile_perf_events;
1900static int profile_perf_event_cnt;
1901
1902static void profile_close_perf_events(struct profiler_bpf *obj)
1903{
1904        int i;
1905
1906        for (i = profile_perf_event_cnt - 1; i >= 0; i--)
1907                close(profile_perf_events[i]);
1908
1909        free(profile_perf_events);
1910        profile_perf_event_cnt = 0;
1911}
1912
1913static int profile_open_perf_events(struct profiler_bpf *obj)
1914{
1915        unsigned int cpu, m;
1916        int map_fd, pmu_fd;
1917
1918        profile_perf_events = calloc(
1919                sizeof(int), obj->rodata->num_cpu * obj->rodata->num_metric);
1920        if (!profile_perf_events) {
1921                p_err("failed to allocate memory for perf_event array: %s",
1922                      strerror(errno));
1923                return -1;
1924        }
1925        map_fd = bpf_map__fd(obj->maps.events);
1926        if (map_fd < 0) {
1927                p_err("failed to get fd for events map");
1928                return -1;
1929        }
1930
1931        for (m = 0; m < ARRAY_SIZE(metrics); m++) {
1932                if (!metrics[m].selected)
1933                        continue;
1934                for (cpu = 0; cpu < obj->rodata->num_cpu; cpu++) {
1935                        pmu_fd = syscall(__NR_perf_event_open, &metrics[m].attr,
1936                                         -1/*pid*/, cpu, -1/*group_fd*/, 0);
1937                        if (pmu_fd < 0 ||
1938                            bpf_map_update_elem(map_fd, &profile_perf_event_cnt,
1939                                                &pmu_fd, BPF_ANY) ||
1940                            ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0)) {
1941                                p_err("failed to create event %s on cpu %d",
1942                                      metrics[m].name, cpu);
1943                                return -1;
1944                        }
1945                        profile_perf_events[profile_perf_event_cnt++] = pmu_fd;
1946                }
1947        }
1948        return 0;
1949}
1950
1951static void profile_print_and_cleanup(void)
1952{
1953        profile_close_perf_events(profile_obj);
1954        profile_read_values(profile_obj);
1955        profile_print_readings();
1956        profiler_bpf__destroy(profile_obj);
1957
1958        close(profile_tgt_fd);
1959        free(profile_tgt_name);
1960}
1961
1962static void int_exit(int signo)
1963{
1964        profile_print_and_cleanup();
1965        exit(0);
1966}
1967
1968static int do_profile(int argc, char **argv)
1969{
1970        int num_metric, num_cpu, err = -1;
1971        struct bpf_program *prog;
1972        unsigned long duration;
1973        char *endptr;
1974
1975        /* we at least need two args for the prog and one metric */
1976        if (!REQ_ARGS(3))
1977                return -EINVAL;
1978
1979        /* parse target fd */
1980        profile_tgt_fd = prog_parse_fd(&argc, &argv);
1981        if (profile_tgt_fd < 0) {
1982                p_err("failed to parse fd");
1983                return -1;
1984        }
1985
1986        /* parse profiling optional duration */
1987        if (argc > 2 && is_prefix(argv[0], "duration")) {
1988                NEXT_ARG();
1989                duration = strtoul(*argv, &endptr, 0);
1990                if (*endptr)
1991                        usage();
1992                NEXT_ARG();
1993        } else {
1994                duration = UINT_MAX;
1995        }
1996
1997        num_metric = profile_parse_metrics(argc, argv);
1998        if (num_metric <= 0)
1999                goto out;
2000
2001        num_cpu = libbpf_num_possible_cpus();
2002        if (num_cpu <= 0) {
2003                p_err("failed to identify number of CPUs");
2004                goto out;
2005        }
2006
2007        profile_obj = profiler_bpf__open();
2008        if (!profile_obj) {
2009                p_err("failed to open and/or load BPF object");
2010                goto out;
2011        }
2012
2013        profile_obj->rodata->num_cpu = num_cpu;
2014        profile_obj->rodata->num_metric = num_metric;
2015
2016        /* adjust map sizes */
2017        bpf_map__resize(profile_obj->maps.events, num_metric * num_cpu);
2018        bpf_map__resize(profile_obj->maps.fentry_readings, num_metric);
2019        bpf_map__resize(profile_obj->maps.accum_readings, num_metric);
2020        bpf_map__resize(profile_obj->maps.counts, 1);
2021
2022        /* change target name */
2023        profile_tgt_name = profile_target_name(profile_tgt_fd);
2024        if (!profile_tgt_name)
2025                goto out;
2026
2027        bpf_object__for_each_program(prog, profile_obj->obj) {
2028                err = bpf_program__set_attach_target(prog, profile_tgt_fd,
2029                                                     profile_tgt_name);
2030                if (err) {
2031                        p_err("failed to set attach target\n");
2032                        goto out;
2033                }
2034        }
2035
2036        set_max_rlimit();
2037        err = profiler_bpf__load(profile_obj);
2038        if (err) {
2039                p_err("failed to load profile_obj");
2040                goto out;
2041        }
2042
2043        err = profile_open_perf_events(profile_obj);
2044        if (err)
2045                goto out;
2046
2047        err = profiler_bpf__attach(profile_obj);
2048        if (err) {
2049                p_err("failed to attach profile_obj");
2050                goto out;
2051        }
2052        signal(SIGINT, int_exit);
2053
2054        sleep(duration);
2055        profile_print_and_cleanup();
2056        return 0;
2057
2058out:
2059        profile_close_perf_events(profile_obj);
2060        if (profile_obj)
2061                profiler_bpf__destroy(profile_obj);
2062        close(profile_tgt_fd);
2063        free(profile_tgt_name);
2064        return err;
2065}
2066
2067#endif /* BPFTOOL_WITHOUT_SKELETONS */
2068
2069static int do_help(int argc, char **argv)
2070{
2071        if (json_output) {
2072                jsonw_null(json_wtr);
2073                return 0;
2074        }
2075
2076        fprintf(stderr,
2077                "Usage: %1$s %2$s { show | list } [PROG]\n"
2078                "       %1$s %2$s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n"
2079                "       %1$s %2$s dump jited  PROG [{ file FILE | opcodes | linum }]\n"
2080                "       %1$s %2$s pin   PROG FILE\n"
2081                "       %1$s %2$s { load | loadall } OBJ  PATH \\\n"
2082                "                         [type TYPE] [dev NAME] \\\n"
2083                "                         [map { idx IDX | name NAME } MAP]\\\n"
2084                "                         [pinmaps MAP_DIR]\n"
2085                "       %1$s %2$s attach PROG ATTACH_TYPE [MAP]\n"
2086                "       %1$s %2$s detach PROG ATTACH_TYPE [MAP]\n"
2087                "       %1$s %2$s run PROG \\\n"
2088                "                         data_in FILE \\\n"
2089                "                         [data_out FILE [data_size_out L]] \\\n"
2090                "                         [ctx_in FILE [ctx_out FILE [ctx_size_out M]]] \\\n"
2091                "                         [repeat N]\n"
2092                "       %1$s %2$s profile PROG [duration DURATION] METRICs\n"
2093                "       %1$s %2$s tracelog\n"
2094                "       %1$s %2$s help\n"
2095                "\n"
2096                "       " HELP_SPEC_MAP "\n"
2097                "       " HELP_SPEC_PROGRAM "\n"
2098                "       TYPE := { socket | kprobe | kretprobe | classifier | action |\n"
2099                "                 tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n"
2100                "                 cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n"
2101                "                 lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n"
2102                "                 sk_reuseport | flow_dissector | cgroup/sysctl |\n"
2103                "                 cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
2104                "                 cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
2105                "                 cgroup/getpeername4 | cgroup/getpeername6 |\n"
2106                "                 cgroup/getsockname4 | cgroup/getsockname6 | cgroup/sendmsg4 |\n"
2107                "                 cgroup/sendmsg6 | cgroup/recvmsg4 | cgroup/recvmsg6 |\n"
2108                "                 cgroup/getsockopt | cgroup/setsockopt |\n"
2109                "                 struct_ops | fentry | fexit | freplace | sk_lookup }\n"
2110                "       ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n"
2111                "                        flow_dissector }\n"
2112                "       METRIC := { cycles | instructions | l1d_loads | llc_misses }\n"
2113                "       " HELP_SPEC_OPTIONS "\n"
2114                "",
2115                bin_name, argv[-2]);
2116
2117        return 0;
2118}
2119
2120static const struct cmd cmds[] = {
2121        { "show",       do_show },
2122        { "list",       do_show },
2123        { "help",       do_help },
2124        { "dump",       do_dump },
2125        { "pin",        do_pin },
2126        { "load",       do_load },
2127        { "loadall",    do_loadall },
2128        { "attach",     do_attach },
2129        { "detach",     do_detach },
2130        { "tracelog",   do_tracelog },
2131        { "run",        do_run },
2132        { "profile",    do_profile },
2133        { 0 }
2134};
2135
2136int do_prog(int argc, char **argv)
2137{
2138        return cmd_select(cmds, argc, argv, do_help);
2139}
2140