linux/tools/perf/builtin-report.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * builtin-report.c
   4 *
   5 * Builtin report command: Analyze the perf.data input file,
   6 * look up and read DSOs and symbol information and display
   7 * a histogram of results, along various sorting keys.
   8 */
   9#include "builtin.h"
  10
  11#include "util/config.h"
  12
  13#include "util/annotate.h"
  14#include "util/color.h"
  15#include "util/dso.h"
  16#include <linux/list.h>
  17#include <linux/rbtree.h>
  18#include <linux/err.h>
  19#include <linux/zalloc.h>
  20#include "util/map.h"
  21#include "util/symbol.h"
  22#include "util/map_symbol.h"
  23#include "util/mem-events.h"
  24#include "util/branch.h"
  25#include "util/callchain.h"
  26#include "util/values.h"
  27
  28#include "perf.h"
  29#include "util/debug.h"
  30#include "util/evlist.h"
  31#include "util/evsel.h"
  32#include "util/evswitch.h"
  33#include "util/header.h"
  34#include "util/session.h"
  35#include "util/srcline.h"
  36#include "util/tool.h"
  37
  38#include <subcmd/parse-options.h>
  39#include <subcmd/exec-cmd.h>
  40#include "util/parse-events.h"
  41
  42#include "util/thread.h"
  43#include "util/sort.h"
  44#include "util/hist.h"
  45#include "util/data.h"
  46#include "arch/common.h"
  47#include "util/time-utils.h"
  48#include "util/auxtrace.h"
  49#include "util/units.h"
  50#include "util/util.h" // perf_tip()
  51#include "ui/ui.h"
  52#include "ui/progress.h"
  53#include "util/block-info.h"
  54
  55#include <dlfcn.h>
  56#include <errno.h>
  57#include <inttypes.h>
  58#include <regex.h>
  59#include <linux/ctype.h>
  60#include <signal.h>
  61#include <linux/bitmap.h>
  62#include <linux/string.h>
  63#include <linux/stringify.h>
  64#include <linux/time64.h>
  65#include <sys/types.h>
  66#include <sys/stat.h>
  67#include <unistd.h>
  68#include <linux/mman.h>
  69
  70struct report {
  71        struct perf_tool        tool;
  72        struct perf_session     *session;
  73        struct evswitch         evswitch;
  74        bool                    use_tui, use_gtk, use_stdio;
  75        bool                    show_full_info;
  76        bool                    show_threads;
  77        bool                    inverted_callchain;
  78        bool                    mem_mode;
  79        bool                    stats_mode;
  80        bool                    tasks_mode;
  81        bool                    mmaps_mode;
  82        bool                    header;
  83        bool                    header_only;
  84        bool                    nonany_branch_mode;
  85        bool                    group_set;
  86        bool                    stitch_lbr;
  87        bool                    disable_order;
  88        bool                    skip_empty;
  89        int                     max_stack;
  90        struct perf_read_values show_threads_values;
  91        struct annotation_options annotation_opts;
  92        const char              *pretty_printing_style;
  93        const char              *cpu_list;
  94        const char              *symbol_filter_str;
  95        const char              *time_str;
  96        struct perf_time_interval *ptime_range;
  97        int                     range_size;
  98        int                     range_num;
  99        float                   min_percent;
 100        u64                     nr_entries;
 101        u64                     queue_size;
 102        u64                     total_cycles;
 103        int                     socket_filter;
 104        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 105        struct branch_type_stat brtype_stat;
 106        bool                    symbol_ipc;
 107        bool                    total_cycles_mode;
 108        struct block_report     *block_reports;
 109        int                     nr_block_reports;
 110};
 111
 112static int report__config(const char *var, const char *value, void *cb)
 113{
 114        struct report *rep = cb;
 115
 116        if (!strcmp(var, "report.group")) {
 117                symbol_conf.event_group = perf_config_bool(var, value);
 118                return 0;
 119        }
 120        if (!strcmp(var, "report.percent-limit")) {
 121                double pcnt = strtof(value, NULL);
 122
 123                rep->min_percent = pcnt;
 124                callchain_param.min_percent = pcnt;
 125                return 0;
 126        }
 127        if (!strcmp(var, "report.children")) {
 128                symbol_conf.cumulate_callchain = perf_config_bool(var, value);
 129                return 0;
 130        }
 131        if (!strcmp(var, "report.queue-size"))
 132                return perf_config_u64(&rep->queue_size, var, value);
 133
 134        if (!strcmp(var, "report.sort_order")) {
 135                default_sort_order = strdup(value);
 136                return 0;
 137        }
 138
 139        if (!strcmp(var, "report.skip-empty")) {
 140                rep->skip_empty = perf_config_bool(var, value);
 141                return 0;
 142        }
 143
 144        return 0;
 145}
 146
 147static int hist_iter__report_callback(struct hist_entry_iter *iter,
 148                                      struct addr_location *al, bool single,
 149                                      void *arg)
 150{
 151        int err = 0;
 152        struct report *rep = arg;
 153        struct hist_entry *he = iter->he;
 154        struct evsel *evsel = iter->evsel;
 155        struct perf_sample *sample = iter->sample;
 156        struct mem_info *mi;
 157        struct branch_info *bi;
 158
 159        if (!ui__has_annotation() && !rep->symbol_ipc)
 160                return 0;
 161
 162        if (sort__mode == SORT_MODE__BRANCH) {
 163                bi = he->branch_info;
 164                err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
 165                if (err)
 166                        goto out;
 167
 168                err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
 169
 170        } else if (rep->mem_mode) {
 171                mi = he->mem_info;
 172                err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel);
 173                if (err)
 174                        goto out;
 175
 176                err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
 177
 178        } else if (symbol_conf.cumulate_callchain) {
 179                if (single)
 180                        err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
 181        } else {
 182                err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
 183        }
 184
 185out:
 186        return err;
 187}
 188
 189static int hist_iter__branch_callback(struct hist_entry_iter *iter,
 190                                      struct addr_location *al __maybe_unused,
 191                                      bool single __maybe_unused,
 192                                      void *arg)
 193{
 194        struct hist_entry *he = iter->he;
 195        struct report *rep = arg;
 196        struct branch_info *bi = he->branch_info;
 197        struct perf_sample *sample = iter->sample;
 198        struct evsel *evsel = iter->evsel;
 199        int err;
 200
 201        branch_type_count(&rep->brtype_stat, &bi->flags,
 202                          bi->from.addr, bi->to.addr);
 203
 204        if (!ui__has_annotation() && !rep->symbol_ipc)
 205                return 0;
 206
 207        err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
 208        if (err)
 209                goto out;
 210
 211        err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
 212
 213out:
 214        return err;
 215}
 216
 217static void setup_forced_leader(struct report *report,
 218                                struct evlist *evlist)
 219{
 220        if (report->group_set)
 221                evlist__force_leader(evlist);
 222}
 223
 224static int process_feature_event(struct perf_session *session,
 225                                 union perf_event *event)
 226{
 227        struct report *rep = container_of(session->tool, struct report, tool);
 228
 229        if (event->feat.feat_id < HEADER_LAST_FEATURE)
 230                return perf_event__process_feature(session, event);
 231
 232        if (event->feat.feat_id != HEADER_LAST_FEATURE) {
 233                pr_err("failed: wrong feature ID: %" PRI_lu64 "\n",
 234                       event->feat.feat_id);
 235                return -1;
 236        } else if (rep->header_only) {
 237                session_done = 1;
 238        }
 239
 240        /*
 241         * (feat_id = HEADER_LAST_FEATURE) is the end marker which
 242         * means all features are received, now we can force the
 243         * group if needed.
 244         */
 245        setup_forced_leader(rep, session->evlist);
 246        return 0;
 247}
 248
 249static int process_sample_event(struct perf_tool *tool,
 250                                union perf_event *event,
 251                                struct perf_sample *sample,
 252                                struct evsel *evsel,
 253                                struct machine *machine)
 254{
 255        struct report *rep = container_of(tool, struct report, tool);
 256        struct addr_location al;
 257        struct hist_entry_iter iter = {
 258                .evsel                  = evsel,
 259                .sample                 = sample,
 260                .hide_unresolved        = symbol_conf.hide_unresolved,
 261                .add_entry_cb           = hist_iter__report_callback,
 262        };
 263        int ret = 0;
 264
 265        if (perf_time__ranges_skip_sample(rep->ptime_range, rep->range_num,
 266                                          sample->time)) {
 267                return 0;
 268        }
 269
 270        if (evswitch__discard(&rep->evswitch, evsel))
 271                return 0;
 272
 273        if (machine__resolve(machine, &al, sample) < 0) {
 274                pr_debug("problem processing %d event, skipping it.\n",
 275                         event->header.type);
 276                return -1;
 277        }
 278
 279        if (rep->stitch_lbr)
 280                al.thread->lbr_stitch_enable = true;
 281
 282        if (symbol_conf.hide_unresolved && al.sym == NULL)
 283                goto out_put;
 284
 285        if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
 286                goto out_put;
 287
 288        if (sort__mode == SORT_MODE__BRANCH) {
 289                /*
 290                 * A non-synthesized event might not have a branch stack if
 291                 * branch stacks have been synthesized (using itrace options).
 292                 */
 293                if (!sample->branch_stack)
 294                        goto out_put;
 295
 296                iter.add_entry_cb = hist_iter__branch_callback;
 297                iter.ops = &hist_iter_branch;
 298        } else if (rep->mem_mode) {
 299                iter.ops = &hist_iter_mem;
 300        } else if (symbol_conf.cumulate_callchain) {
 301                iter.ops = &hist_iter_cumulative;
 302        } else {
 303                iter.ops = &hist_iter_normal;
 304        }
 305
 306        if (al.map != NULL)
 307                al.map->dso->hit = 1;
 308
 309        if (ui__has_annotation() || rep->symbol_ipc || rep->total_cycles_mode) {
 310                hist__account_cycles(sample->branch_stack, &al, sample,
 311                                     rep->nonany_branch_mode,
 312                                     &rep->total_cycles);
 313        }
 314
 315        ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
 316        if (ret < 0)
 317                pr_debug("problem adding hist entry, skipping event\n");
 318out_put:
 319        addr_location__put(&al);
 320        return ret;
 321}
 322
 323static int process_read_event(struct perf_tool *tool,
 324                              union perf_event *event,
 325                              struct perf_sample *sample __maybe_unused,
 326                              struct evsel *evsel,
 327                              struct machine *machine __maybe_unused)
 328{
 329        struct report *rep = container_of(tool, struct report, tool);
 330
 331        if (rep->show_threads) {
 332                const char *name = evsel__name(evsel);
 333                int err = perf_read_values_add_value(&rep->show_threads_values,
 334                                           event->read.pid, event->read.tid,
 335                                           evsel->core.idx,
 336                                           name,
 337                                           event->read.value);
 338
 339                if (err)
 340                        return err;
 341        }
 342
 343        return 0;
 344}
 345
 346/* For pipe mode, sample_type is not currently set */
 347static int report__setup_sample_type(struct report *rep)
 348{
 349        struct perf_session *session = rep->session;
 350        u64 sample_type = evlist__combined_sample_type(session->evlist);
 351        bool is_pipe = perf_data__is_pipe(session->data);
 352
 353        if (session->itrace_synth_opts->callchain ||
 354            session->itrace_synth_opts->add_callchain ||
 355            (!is_pipe &&
 356             perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
 357             !session->itrace_synth_opts->set))
 358                sample_type |= PERF_SAMPLE_CALLCHAIN;
 359
 360        if (session->itrace_synth_opts->last_branch ||
 361            session->itrace_synth_opts->add_last_branch)
 362                sample_type |= PERF_SAMPLE_BRANCH_STACK;
 363
 364        if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
 365                if (perf_hpp_list.parent) {
 366                        ui__error("Selected --sort parent, but no "
 367                                    "callchain data. Did you call "
 368                                    "'perf record' without -g?\n");
 369                        return -EINVAL;
 370                }
 371                if (symbol_conf.use_callchain &&
 372                        !symbol_conf.show_branchflag_count) {
 373                        ui__error("Selected -g or --branch-history.\n"
 374                                  "But no callchain or branch data.\n"
 375                                  "Did you call 'perf record' without -g or -b?\n");
 376                        return -1;
 377                }
 378        } else if (!callchain_param.enabled &&
 379                   callchain_param.mode != CHAIN_NONE &&
 380                   !symbol_conf.use_callchain) {
 381                        symbol_conf.use_callchain = true;
 382                        if (callchain_register_param(&callchain_param) < 0) {
 383                                ui__error("Can't register callchain params.\n");
 384                                return -EINVAL;
 385                        }
 386        }
 387
 388        if (symbol_conf.cumulate_callchain) {
 389                /* Silently ignore if callchain is missing */
 390                if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
 391                        symbol_conf.cumulate_callchain = false;
 392                        perf_hpp__cancel_cumulate();
 393                }
 394        }
 395
 396        if (sort__mode == SORT_MODE__BRANCH) {
 397                if (!is_pipe &&
 398                    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
 399                        ui__error("Selected -b but no branch data. "
 400                                  "Did you call perf record without -b?\n");
 401                        return -1;
 402                }
 403        }
 404
 405        if (sort__mode == SORT_MODE__MEMORY) {
 406                if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) {
 407                        ui__error("Selected --mem-mode but no mem data. "
 408                                  "Did you call perf record without -d?\n");
 409                        return -1;
 410                }
 411        }
 412
 413        callchain_param_setup(sample_type);
 414
 415        if (rep->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) {
 416                ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
 417                            "Please apply --call-graph lbr when recording.\n");
 418                rep->stitch_lbr = false;
 419        }
 420
 421        /* ??? handle more cases than just ANY? */
 422        if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY))
 423                rep->nonany_branch_mode = true;
 424
 425#if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT)
 426        if (dwarf_callchain_users) {
 427                ui__warning("Please install libunwind or libdw "
 428                            "development packages during the perf build.\n");
 429        }
 430#endif
 431
 432        return 0;
 433}
 434
 435static void sig_handler(int sig __maybe_unused)
 436{
 437        session_done = 1;
 438}
 439
 440static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
 441                                              const char *evname, FILE *fp)
 442{
 443        size_t ret;
 444        char unit;
 445        unsigned long nr_samples = hists->stats.nr_samples;
 446        u64 nr_events = hists->stats.total_period;
 447        struct evsel *evsel = hists_to_evsel(hists);
 448        char buf[512];
 449        size_t size = sizeof(buf);
 450        int socked_id = hists->socket_filter;
 451
 452        if (quiet)
 453                return 0;
 454
 455        if (symbol_conf.filter_relative) {
 456                nr_samples = hists->stats.nr_non_filtered_samples;
 457                nr_events = hists->stats.total_non_filtered_period;
 458        }
 459
 460        if (evsel__is_group_event(evsel)) {
 461                struct evsel *pos;
 462
 463                evsel__group_desc(evsel, buf, size);
 464                evname = buf;
 465
 466                for_each_group_member(pos, evsel) {
 467                        const struct hists *pos_hists = evsel__hists(pos);
 468
 469                        if (symbol_conf.filter_relative) {
 470                                nr_samples += pos_hists->stats.nr_non_filtered_samples;
 471                                nr_events += pos_hists->stats.total_non_filtered_period;
 472                        } else {
 473                                nr_samples += pos_hists->stats.nr_samples;
 474                                nr_events += pos_hists->stats.total_period;
 475                        }
 476                }
 477        }
 478
 479        nr_samples = convert_unit(nr_samples, &unit);
 480        ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
 481        if (evname != NULL) {
 482                ret += fprintf(fp, " of event%s '%s'",
 483                               evsel->core.nr_members > 1 ? "s" : "", evname);
 484        }
 485
 486        if (rep->time_str)
 487                ret += fprintf(fp, " (time slices: %s)", rep->time_str);
 488
 489        if (symbol_conf.show_ref_callgraph && evname && strstr(evname, "call-graph=no")) {
 490                ret += fprintf(fp, ", show reference callgraph");
 491        }
 492
 493        if (rep->mem_mode) {
 494                ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
 495                ret += fprintf(fp, "\n# Sort order   : %s", sort_order ? : default_mem_sort_order);
 496        } else
 497                ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
 498
 499        if (socked_id > -1)
 500                ret += fprintf(fp, "\n# Processor Socket: %d", socked_id);
 501
 502        return ret + fprintf(fp, "\n#\n");
 503}
 504
 505static int evlist__tui_block_hists_browse(struct evlist *evlist, struct report *rep)
 506{
 507        struct evsel *pos;
 508        int i = 0, ret;
 509
 510        evlist__for_each_entry(evlist, pos) {
 511                ret = report__browse_block_hists(&rep->block_reports[i++].hist,
 512                                                 rep->min_percent, pos,
 513                                                 &rep->session->header.env,
 514                                                 &rep->annotation_opts);
 515                if (ret != 0)
 516                        return ret;
 517        }
 518
 519        return 0;
 520}
 521
 522static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, const char *help)
 523{
 524        struct evsel *pos;
 525        int i = 0;
 526
 527        if (!quiet) {
 528                fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n",
 529                        evlist->stats.total_lost_samples);
 530        }
 531
 532        evlist__for_each_entry(evlist, pos) {
 533                struct hists *hists = evsel__hists(pos);
 534                const char *evname = evsel__name(pos);
 535
 536                if (symbol_conf.event_group && !evsel__is_group_leader(pos))
 537                        continue;
 538
 539                if (rep->skip_empty && !hists->stats.nr_samples)
 540                        continue;
 541
 542                hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
 543
 544                if (rep->total_cycles_mode) {
 545                        report__browse_block_hists(&rep->block_reports[i++].hist,
 546                                                   rep->min_percent, pos,
 547                                                   NULL, NULL);
 548                        continue;
 549                }
 550
 551                hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
 552                               !(symbol_conf.use_callchain ||
 553                                 symbol_conf.show_branchflag_count));
 554                fprintf(stdout, "\n\n");
 555        }
 556
 557        if (!quiet)
 558                fprintf(stdout, "#\n# (%s)\n#\n", help);
 559
 560        if (rep->show_threads) {
 561                bool style = !strcmp(rep->pretty_printing_style, "raw");
 562                perf_read_values_display(stdout, &rep->show_threads_values,
 563                                         style);
 564                perf_read_values_destroy(&rep->show_threads_values);
 565        }
 566
 567        if (sort__mode == SORT_MODE__BRANCH)
 568                branch_type_stat_display(stdout, &rep->brtype_stat);
 569
 570        return 0;
 571}
 572
 573static void report__warn_kptr_restrict(const struct report *rep)
 574{
 575        struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
 576        struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
 577
 578        if (evlist__exclude_kernel(rep->session->evlist))
 579                return;
 580
 581        if (kernel_map == NULL ||
 582            (kernel_map->dso->hit &&
 583             (kernel_kmap->ref_reloc_sym == NULL ||
 584              kernel_kmap->ref_reloc_sym->addr == 0))) {
 585                const char *desc =
 586                    "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
 587                    "can't be resolved.";
 588
 589                if (kernel_map && map__has_symbols(kernel_map)) {
 590                        desc = "If some relocation was applied (e.g. "
 591                               "kexec) symbols may be misresolved.";
 592                }
 593
 594                ui__warning(
 595"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
 596"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
 597"Samples in kernel modules can't be resolved as well.\n\n",
 598                desc);
 599        }
 600}
 601
 602static int report__gtk_browse_hists(struct report *rep, const char *help)
 603{
 604        int (*hist_browser)(struct evlist *evlist, const char *help,
 605                            struct hist_browser_timer *timer, float min_pcnt);
 606
 607        hist_browser = dlsym(perf_gtk_handle, "evlist__gtk_browse_hists");
 608
 609        if (hist_browser == NULL) {
 610                ui__error("GTK browser not found!\n");
 611                return -1;
 612        }
 613
 614        return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
 615}
 616
 617static int report__browse_hists(struct report *rep)
 618{
 619        int ret;
 620        struct perf_session *session = rep->session;
 621        struct evlist *evlist = session->evlist;
 622        const char *help = perf_tip(system_path(TIPDIR));
 623
 624        if (help == NULL) {
 625                /* fallback for people who don't install perf ;-) */
 626                help = perf_tip(DOCDIR);
 627                if (help == NULL)
 628                        help = "Cannot load tips.txt file, please install perf!";
 629        }
 630
 631        switch (use_browser) {
 632        case 1:
 633                if (rep->total_cycles_mode) {
 634                        ret = evlist__tui_block_hists_browse(evlist, rep);
 635                        break;
 636                }
 637
 638                ret = evlist__tui_browse_hists(evlist, help, NULL, rep->min_percent,
 639                                               &session->header.env, true, &rep->annotation_opts);
 640                /*
 641                 * Usually "ret" is the last pressed key, and we only
 642                 * care if the key notifies us to switch data file.
 643                 */
 644                if (ret != K_SWITCH_INPUT_DATA && ret != K_RELOAD)
 645                        ret = 0;
 646                break;
 647        case 2:
 648                ret = report__gtk_browse_hists(rep, help);
 649                break;
 650        default:
 651                ret = evlist__tty_browse_hists(evlist, rep, help);
 652                break;
 653        }
 654
 655        return ret;
 656}
 657
 658static int report__collapse_hists(struct report *rep)
 659{
 660        struct ui_progress prog;
 661        struct evsel *pos;
 662        int ret = 0;
 663
 664        ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
 665
 666        evlist__for_each_entry(rep->session->evlist, pos) {
 667                struct hists *hists = evsel__hists(pos);
 668
 669                if (pos->core.idx == 0)
 670                        hists->symbol_filter_str = rep->symbol_filter_str;
 671
 672                hists->socket_filter = rep->socket_filter;
 673
 674                ret = hists__collapse_resort(hists, &prog);
 675                if (ret < 0)
 676                        break;
 677
 678                /* Non-group events are considered as leader */
 679                if (symbol_conf.event_group && !evsel__is_group_leader(pos)) {
 680                        struct hists *leader_hists = evsel__hists(evsel__leader(pos));
 681
 682                        hists__match(leader_hists, hists);
 683                        hists__link(leader_hists, hists);
 684                }
 685        }
 686
 687        ui_progress__finish();
 688        return ret;
 689}
 690
 691static int hists__resort_cb(struct hist_entry *he, void *arg)
 692{
 693        struct report *rep = arg;
 694        struct symbol *sym = he->ms.sym;
 695
 696        if (rep->symbol_ipc && sym && !sym->annotate2) {
 697                struct evsel *evsel = hists_to_evsel(he->hists);
 698
 699                symbol__annotate2(&he->ms, evsel,
 700                                  &annotation__default_options, NULL);
 701        }
 702
 703        return 0;
 704}
 705
 706static void report__output_resort(struct report *rep)
 707{
 708        struct ui_progress prog;
 709        struct evsel *pos;
 710
 711        ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
 712
 713        evlist__for_each_entry(rep->session->evlist, pos) {
 714                evsel__output_resort_cb(pos, &prog, hists__resort_cb, rep);
 715        }
 716
 717        ui_progress__finish();
 718}
 719
 720static int count_sample_event(struct perf_tool *tool __maybe_unused,
 721                              union perf_event *event __maybe_unused,
 722                              struct perf_sample *sample __maybe_unused,
 723                              struct evsel *evsel,
 724                              struct machine *machine __maybe_unused)
 725{
 726        struct hists *hists = evsel__hists(evsel);
 727
 728        hists__inc_nr_events(hists);
 729        return 0;
 730}
 731
 732static int process_attr(struct perf_tool *tool __maybe_unused,
 733                        union perf_event *event,
 734                        struct evlist **pevlist);
 735
 736static void stats_setup(struct report *rep)
 737{
 738        memset(&rep->tool, 0, sizeof(rep->tool));
 739        rep->tool.attr = process_attr;
 740        rep->tool.sample = count_sample_event;
 741        rep->tool.no_warn = true;
 742}
 743
 744static int stats_print(struct report *rep)
 745{
 746        struct perf_session *session = rep->session;
 747
 748        perf_session__fprintf_nr_events(session, stdout, rep->skip_empty);
 749        evlist__fprintf_nr_events(session->evlist, stdout, rep->skip_empty);
 750        return 0;
 751}
 752
 753static void tasks_setup(struct report *rep)
 754{
 755        memset(&rep->tool, 0, sizeof(rep->tool));
 756        rep->tool.ordered_events = true;
 757        if (rep->mmaps_mode) {
 758                rep->tool.mmap = perf_event__process_mmap;
 759                rep->tool.mmap2 = perf_event__process_mmap2;
 760        }
 761        rep->tool.attr = process_attr;
 762        rep->tool.comm = perf_event__process_comm;
 763        rep->tool.exit = perf_event__process_exit;
 764        rep->tool.fork = perf_event__process_fork;
 765        rep->tool.no_warn = true;
 766}
 767
 768struct task {
 769        struct thread           *thread;
 770        struct list_head         list;
 771        struct list_head         children;
 772};
 773
 774static struct task *tasks_list(struct task *task, struct machine *machine)
 775{
 776        struct thread *parent_thread, *thread = task->thread;
 777        struct task   *parent_task;
 778
 779        /* Already listed. */
 780        if (!list_empty(&task->list))
 781                return NULL;
 782
 783        /* Last one in the chain. */
 784        if (thread->ppid == -1)
 785                return task;
 786
 787        parent_thread = machine__find_thread(machine, -1, thread->ppid);
 788        if (!parent_thread)
 789                return ERR_PTR(-ENOENT);
 790
 791        parent_task = thread__priv(parent_thread);
 792        list_add_tail(&task->list, &parent_task->children);
 793        return tasks_list(parent_task, machine);
 794}
 795
 796static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp)
 797{
 798        size_t printed = 0;
 799        struct map *map;
 800
 801        maps__for_each_entry(maps, map) {
 802                printed += fprintf(fp, "%*s  %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n",
 803                                   indent, "", map->start, map->end,
 804                                   map->prot & PROT_READ ? 'r' : '-',
 805                                   map->prot & PROT_WRITE ? 'w' : '-',
 806                                   map->prot & PROT_EXEC ? 'x' : '-',
 807                                   map->flags & MAP_SHARED ? 's' : 'p',
 808                                   map->pgoff,
 809                                   map->dso->id.ino, map->dso->name);
 810        }
 811
 812        return printed;
 813}
 814
 815static void task__print_level(struct task *task, FILE *fp, int level)
 816{
 817        struct thread *thread = task->thread;
 818        struct task *child;
 819        int comm_indent = fprintf(fp, "  %8d %8d %8d |%*s",
 820                                  thread->pid_, thread->tid, thread->ppid,
 821                                  level, "");
 822
 823        fprintf(fp, "%s\n", thread__comm_str(thread));
 824
 825        maps__fprintf_task(thread->maps, comm_indent, fp);
 826
 827        if (!list_empty(&task->children)) {
 828                list_for_each_entry(child, &task->children, list)
 829                        task__print_level(child, fp, level + 1);
 830        }
 831}
 832
 833static int tasks_print(struct report *rep, FILE *fp)
 834{
 835        struct perf_session *session = rep->session;
 836        struct machine      *machine = &session->machines.host;
 837        struct task *tasks, *task;
 838        unsigned int nr = 0, itask = 0, i;
 839        struct rb_node *nd;
 840        LIST_HEAD(list);
 841
 842        /*
 843         * No locking needed while accessing machine->threads,
 844         * because --tasks is single threaded command.
 845         */
 846
 847        /* Count all the threads. */
 848        for (i = 0; i < THREADS__TABLE_SIZE; i++)
 849                nr += machine->threads[i].nr;
 850
 851        tasks = malloc(sizeof(*tasks) * nr);
 852        if (!tasks)
 853                return -ENOMEM;
 854
 855        for (i = 0; i < THREADS__TABLE_SIZE; i++) {
 856                struct threads *threads = &machine->threads[i];
 857
 858                for (nd = rb_first_cached(&threads->entries); nd;
 859                     nd = rb_next(nd)) {
 860                        task = tasks + itask++;
 861
 862                        task->thread = rb_entry(nd, struct thread, rb_node);
 863                        INIT_LIST_HEAD(&task->children);
 864                        INIT_LIST_HEAD(&task->list);
 865                        thread__set_priv(task->thread, task);
 866                }
 867        }
 868
 869        /*
 870         * Iterate every task down to the unprocessed parent
 871         * and link all in task children list. Task with no
 872         * parent is added into 'list'.
 873         */
 874        for (itask = 0; itask < nr; itask++) {
 875                task = tasks + itask;
 876
 877                if (!list_empty(&task->list))
 878                        continue;
 879
 880                task = tasks_list(task, machine);
 881                if (IS_ERR(task)) {
 882                        pr_err("Error: failed to process tasks\n");
 883                        free(tasks);
 884                        return PTR_ERR(task);
 885                }
 886
 887                if (task)
 888                        list_add_tail(&task->list, &list);
 889        }
 890
 891        fprintf(fp, "# %8s %8s %8s  %s\n", "pid", "tid", "ppid", "comm");
 892
 893        list_for_each_entry(task, &list, list)
 894                task__print_level(task, fp, 0);
 895
 896        free(tasks);
 897        return 0;
 898}
 899
 900static int __cmd_report(struct report *rep)
 901{
 902        int ret;
 903        struct perf_session *session = rep->session;
 904        struct evsel *pos;
 905        struct perf_data *data = session->data;
 906
 907        signal(SIGINT, sig_handler);
 908
 909        if (rep->cpu_list) {
 910                ret = perf_session__cpu_bitmap(session, rep->cpu_list,
 911                                               rep->cpu_bitmap);
 912                if (ret) {
 913                        ui__error("failed to set cpu bitmap\n");
 914                        return ret;
 915                }
 916                session->itrace_synth_opts->cpu_bitmap = rep->cpu_bitmap;
 917        }
 918
 919        if (rep->show_threads) {
 920                ret = perf_read_values_init(&rep->show_threads_values);
 921                if (ret)
 922                        return ret;
 923        }
 924
 925        ret = report__setup_sample_type(rep);
 926        if (ret) {
 927                /* report__setup_sample_type() already showed error message */
 928                return ret;
 929        }
 930
 931        if (rep->stats_mode)
 932                stats_setup(rep);
 933
 934        if (rep->tasks_mode)
 935                tasks_setup(rep);
 936
 937        ret = perf_session__process_events(session);
 938        if (ret) {
 939                ui__error("failed to process sample\n");
 940                return ret;
 941        }
 942
 943        evlist__check_mem_load_aux(session->evlist);
 944
 945        if (rep->stats_mode)
 946                return stats_print(rep);
 947
 948        if (rep->tasks_mode)
 949                return tasks_print(rep, stdout);
 950
 951        report__warn_kptr_restrict(rep);
 952
 953        evlist__for_each_entry(session->evlist, pos)
 954                rep->nr_entries += evsel__hists(pos)->nr_entries;
 955
 956        if (use_browser == 0) {
 957                if (verbose > 3)
 958                        perf_session__fprintf(session, stdout);
 959
 960                if (verbose > 2)
 961                        perf_session__fprintf_dsos(session, stdout);
 962
 963                if (dump_trace) {
 964                        perf_session__fprintf_nr_events(session, stdout,
 965                                                        rep->skip_empty);
 966                        evlist__fprintf_nr_events(session->evlist, stdout,
 967                                                  rep->skip_empty);
 968                        return 0;
 969                }
 970        }
 971
 972        ret = report__collapse_hists(rep);
 973        if (ret) {
 974                ui__error("failed to process hist entry\n");
 975                return ret;
 976        }
 977
 978        if (session_done())
 979                return 0;
 980
 981        /*
 982         * recalculate number of entries after collapsing since it
 983         * might be changed during the collapse phase.
 984         */
 985        rep->nr_entries = 0;
 986        evlist__for_each_entry(session->evlist, pos)
 987                rep->nr_entries += evsel__hists(pos)->nr_entries;
 988
 989        if (rep->nr_entries == 0) {
 990                ui__error("The %s data has no samples!\n", data->path);
 991                return 0;
 992        }
 993
 994        report__output_resort(rep);
 995
 996        if (rep->total_cycles_mode) {
 997                int block_hpps[6] = {
 998                        PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT,
 999                        PERF_HPP_REPORT__BLOCK_LBR_CYCLES,
1000                        PERF_HPP_REPORT__BLOCK_CYCLES_PCT,
1001                        PERF_HPP_REPORT__BLOCK_AVG_CYCLES,
1002                        PERF_HPP_REPORT__BLOCK_RANGE,
1003                        PERF_HPP_REPORT__BLOCK_DSO,
1004                };
1005
1006                rep->block_reports = block_info__create_report(session->evlist,
1007                                                               rep->total_cycles,
1008                                                               block_hpps, 6,
1009                                                               &rep->nr_block_reports);
1010                if (!rep->block_reports)
1011                        return -1;
1012        }
1013
1014        return report__browse_hists(rep);
1015}
1016
1017static int
1018report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1019{
1020        struct callchain_param *callchain = opt->value;
1021
1022        callchain->enabled = !unset;
1023        /*
1024         * --no-call-graph
1025         */
1026        if (unset) {
1027                symbol_conf.use_callchain = false;
1028                callchain->mode = CHAIN_NONE;
1029                return 0;
1030        }
1031
1032        return parse_callchain_report_opt(arg);
1033}
1034
1035static int
1036parse_time_quantum(const struct option *opt, const char *arg,
1037                   int unset __maybe_unused)
1038{
1039        unsigned long *time_q = opt->value;
1040        char *end;
1041
1042        *time_q = strtoul(arg, &end, 0);
1043        if (end == arg)
1044                goto parse_err;
1045        if (*time_q == 0) {
1046                pr_err("time quantum cannot be 0");
1047                return -1;
1048        }
1049        end = skip_spaces(end);
1050        if (*end == 0)
1051                return 0;
1052        if (!strcmp(end, "s")) {
1053                *time_q *= NSEC_PER_SEC;
1054                return 0;
1055        }
1056        if (!strcmp(end, "ms")) {
1057                *time_q *= NSEC_PER_MSEC;
1058                return 0;
1059        }
1060        if (!strcmp(end, "us")) {
1061                *time_q *= NSEC_PER_USEC;
1062                return 0;
1063        }
1064        if (!strcmp(end, "ns"))
1065                return 0;
1066parse_err:
1067        pr_err("Cannot parse time quantum `%s'\n", arg);
1068        return -1;
1069}
1070
1071int
1072report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
1073                                const char *arg, int unset __maybe_unused)
1074{
1075        if (arg) {
1076                int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
1077                if (err) {
1078                        char buf[BUFSIZ];
1079                        regerror(err, &ignore_callees_regex, buf, sizeof(buf));
1080                        pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
1081                        return -1;
1082                }
1083                have_ignore_callees = 1;
1084        }
1085
1086        return 0;
1087}
1088
1089static int
1090parse_branch_mode(const struct option *opt,
1091                  const char *str __maybe_unused, int unset)
1092{
1093        int *branch_mode = opt->value;
1094
1095        *branch_mode = !unset;
1096        return 0;
1097}
1098
1099static int
1100parse_percent_limit(const struct option *opt, const char *str,
1101                    int unset __maybe_unused)
1102{
1103        struct report *rep = opt->value;
1104        double pcnt = strtof(str, NULL);
1105
1106        rep->min_percent = pcnt;
1107        callchain_param.min_percent = pcnt;
1108        return 0;
1109}
1110
1111static int process_attr(struct perf_tool *tool __maybe_unused,
1112                        union perf_event *event,
1113                        struct evlist **pevlist)
1114{
1115        u64 sample_type;
1116        int err;
1117
1118        err = perf_event__process_attr(tool, event, pevlist);
1119        if (err)
1120                return err;
1121
1122        /*
1123         * Check if we need to enable callchains based
1124         * on events sample_type.
1125         */
1126        sample_type = evlist__combined_sample_type(*pevlist);
1127        callchain_param_setup(sample_type);
1128        return 0;
1129}
1130
1131int cmd_report(int argc, const char **argv)
1132{
1133        struct perf_session *session;
1134        struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
1135        struct stat st;
1136        bool has_br_stack = false;
1137        int branch_mode = -1;
1138        int last_key = 0;
1139        bool branch_call_mode = false;
1140#define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
1141        static const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
1142                                                    CALLCHAIN_REPORT_HELP
1143                                                    "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
1144        char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
1145        const char * const report_usage[] = {
1146                "perf report [<options>]",
1147                NULL
1148        };
1149        struct report report = {
1150                .tool = {
1151                        .sample          = process_sample_event,
1152                        .mmap            = perf_event__process_mmap,
1153                        .mmap2           = perf_event__process_mmap2,
1154                        .comm            = perf_event__process_comm,
1155                        .namespaces      = perf_event__process_namespaces,
1156                        .cgroup          = perf_event__process_cgroup,
1157                        .exit            = perf_event__process_exit,
1158                        .fork            = perf_event__process_fork,
1159                        .lost            = perf_event__process_lost,
1160                        .read            = process_read_event,
1161                        .attr            = process_attr,
1162                        .tracing_data    = perf_event__process_tracing_data,
1163                        .build_id        = perf_event__process_build_id,
1164                        .id_index        = perf_event__process_id_index,
1165                        .auxtrace_info   = perf_event__process_auxtrace_info,
1166                        .auxtrace        = perf_event__process_auxtrace,
1167                        .event_update    = perf_event__process_event_update,
1168                        .feature         = process_feature_event,
1169                        .ordered_events  = true,
1170                        .ordering_requires_timestamps = true,
1171                },
1172                .max_stack               = PERF_MAX_STACK_DEPTH,
1173                .pretty_printing_style   = "normal",
1174                .socket_filter           = -1,
1175                .annotation_opts         = annotation__default_options,
1176                .skip_empty              = true,
1177        };
1178        char *sort_order_help = sort_help("sort by key(s):");
1179        char *field_order_help = sort_help("output field(s): overhead period sample ");
1180        const struct option options[] = {
1181        OPT_STRING('i', "input", &input_name, "file",
1182                    "input file name"),
1183        OPT_INCR('v', "verbose", &verbose,
1184                    "be more verbose (show symbol address, etc)"),
1185        OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any message"),
1186        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1187                    "dump raw trace in ASCII"),
1188        OPT_BOOLEAN(0, "stats", &report.stats_mode, "Display event stats"),
1189        OPT_BOOLEAN(0, "tasks", &report.tasks_mode, "Display recorded tasks"),
1190        OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"),
1191        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1192                   "file", "vmlinux pathname"),
1193        OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1194                    "don't load vmlinux even if found"),
1195        OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
1196                   "file", "kallsyms pathname"),
1197        OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
1198        OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
1199                    "load module symbols - WARNING: use only with -k and LIVE kernel"),
1200        OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1201                    "Show a column with the number of samples"),
1202        OPT_BOOLEAN('T', "threads", &report.show_threads,
1203                    "Show per-thread event counters"),
1204        OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
1205                   "pretty printing style key: normal raw"),
1206        OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
1207        OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
1208        OPT_BOOLEAN(0, "stdio", &report.use_stdio,
1209                    "Use the stdio interface"),
1210        OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
1211        OPT_BOOLEAN(0, "header-only", &report.header_only,
1212                    "Show only data header."),
1213        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1214                   sort_order_help),
1215        OPT_STRING('F', "fields", &field_order, "key[,keys...]",
1216                   field_order_help),
1217        OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
1218                    "Show sample percentage for different cpu modes"),
1219        OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
1220                    "Show sample percentage for different cpu modes", PARSE_OPT_HIDDEN),
1221        OPT_STRING('p', "parent", &parent_pattern, "regex",
1222                   "regex filter to identify parent, see: '--sort parent'"),
1223        OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
1224                    "Only display entries with parent-match"),
1225        OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
1226                             "print_type,threshold[,print_limit],order,sort_key[,branch],value",
1227                             report_callchain_help, &report_parse_callchain_opt,
1228                             callchain_default_opt),
1229        OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1230                    "Accumulate callchains of children and show total overhead as well. "
1231                    "Enabled by default, use --no-children to disable."),
1232        OPT_INTEGER(0, "max-stack", &report.max_stack,
1233                    "Set the maximum stack depth when parsing the callchain, "
1234                    "anything beyond the specified depth will be ignored. "
1235                    "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
1236        OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
1237                    "alias for inverted call graph"),
1238        OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1239                   "ignore callees of these functions in call graphs",
1240                   report_parse_ignore_callees_opt),
1241        OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
1242                   "only consider symbols in these dsos"),
1243        OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1244                   "only consider symbols in these comms"),
1245        OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
1246                   "only consider symbols in these pids"),
1247        OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
1248                   "only consider symbols in these tids"),
1249        OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
1250                   "only consider these symbols"),
1251        OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
1252                   "only show symbols that (partially) match with this filter"),
1253        OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1254                   "width[,width...]",
1255                   "don't try to adjust column width, use these fixed values"),
1256        OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
1257                   "separator for columns, no spaces will be added between "
1258                   "columns '.' is reserved."),
1259        OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
1260                    "Only display entries resolved to a symbol"),
1261        OPT_CALLBACK(0, "symfs", NULL, "directory",
1262                     "Look for files with symbols relative to this directory",
1263                     symbol__config_symfs),
1264        OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
1265                   "list of cpus to profile"),
1266        OPT_BOOLEAN('I', "show-info", &report.show_full_info,
1267                    "Display extended information about perf.data file"),
1268        OPT_BOOLEAN(0, "source", &report.annotation_opts.annotate_src,
1269                    "Interleave source code with assembly code (default)"),
1270        OPT_BOOLEAN(0, "asm-raw", &report.annotation_opts.show_asm_raw,
1271                    "Display raw encoding of assembly instructions (default)"),
1272        OPT_STRING('M', "disassembler-style", &report.annotation_opts.disassembler_style, "disassembler style",
1273                   "Specify disassembler style (e.g. -M intel for intel syntax)"),
1274        OPT_STRING(0, "prefix", &report.annotation_opts.prefix, "prefix",
1275                    "Add prefix to source file path names in programs (with --prefix-strip)"),
1276        OPT_STRING(0, "prefix-strip", &report.annotation_opts.prefix_strip, "N",
1277                    "Strip first N entries of source file path name in programs (with --prefix)"),
1278        OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1279                    "Show a column with the sum of periods"),
1280        OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
1281                    "Show event group information together"),
1282        OPT_INTEGER(0, "group-sort-idx", &symbol_conf.group_sort_idx,
1283                    "Sort the output by the event at the index n in group. "
1284                    "If n is invalid, sort by the first event. "
1285                    "WARNING: should be used on grouped events."),
1286        OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
1287                    "use branch records for per branch histogram filling",
1288                    parse_branch_mode),
1289        OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
1290                    "add last branch records to call history"),
1291        OPT_STRING(0, "objdump", &report.annotation_opts.objdump_path, "path",
1292                   "objdump binary to use for disassembly and annotations"),
1293        OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
1294                    "Disable symbol demangling"),
1295        OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1296                    "Enable kernel symbol demangling"),
1297        OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
1298        OPT_INTEGER(0, "samples", &symbol_conf.res_sample,
1299                    "Number of samples to save per histogram entry for individual browsing"),
1300        OPT_CALLBACK(0, "percent-limit", &report, "percent",
1301                     "Don't show entries under that percent", parse_percent_limit),
1302        OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1303                     "how to display percentage of filtered entries", parse_filter_percentage),
1304        OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1305                            "Instruction Tracing options\n" ITRACE_HELP,
1306                            itrace_parse_synth_opts),
1307        OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
1308                        "Show full source file name path for source lines"),
1309        OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
1310                    "Show callgraph from reference event"),
1311        OPT_BOOLEAN(0, "stitch-lbr", &report.stitch_lbr,
1312                    "Enable LBR callgraph stitching approach"),
1313        OPT_INTEGER(0, "socket-filter", &report.socket_filter,
1314                    "only show processor socket that match with this filter"),
1315        OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
1316                    "Show raw trace event output (do not use print fmt or plugins)"),
1317        OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
1318                    "Show entries in a hierarchy"),
1319        OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
1320                             "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
1321                             stdio__config_color, "always"),
1322        OPT_STRING(0, "time", &report.time_str, "str",
1323                   "Time span of interest (start,stop)"),
1324        OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
1325                    "Show inline function"),
1326        OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period",
1327                     "Set percent type local/global-period/hits",
1328                     annotate_parse_percent_type),
1329        OPT_BOOLEAN(0, "ns", &symbol_conf.nanosecs, "Show times in nanosecs"),
1330        OPT_CALLBACK(0, "time-quantum", &symbol_conf.time_quantum, "time (ms|us|ns|s)",
1331                     "Set time quantum for time sort key (default 100ms)",
1332                     parse_time_quantum),
1333        OPTS_EVSWITCH(&report.evswitch),
1334        OPT_BOOLEAN(0, "total-cycles", &report.total_cycles_mode,
1335                    "Sort all blocks by 'Sampled Cycles%'"),
1336        OPT_BOOLEAN(0, "disable-order", &report.disable_order,
1337                    "Disable raw trace ordering"),
1338        OPT_BOOLEAN(0, "skip-empty", &report.skip_empty,
1339                    "Do not display empty (or dummy) events in the output"),
1340        OPT_END()
1341        };
1342        struct perf_data data = {
1343                .mode  = PERF_DATA_MODE_READ,
1344        };
1345        int ret = hists__init();
1346        char sort_tmp[128];
1347
1348        if (ret < 0)
1349                goto exit;
1350
1351        ret = perf_config(report__config, &report);
1352        if (ret)
1353                goto exit;
1354
1355        argc = parse_options(argc, argv, options, report_usage, 0);
1356        if (argc) {
1357                /*
1358                 * Special case: if there's an argument left then assume that
1359                 * it's a symbol filter:
1360                 */
1361                if (argc > 1)
1362                        usage_with_options(report_usage, options);
1363
1364                report.symbol_filter_str = argv[0];
1365        }
1366
1367        if (annotate_check_args(&report.annotation_opts) < 0) {
1368                ret = -EINVAL;
1369                goto exit;
1370        }
1371
1372        if (report.mmaps_mode)
1373                report.tasks_mode = true;
1374
1375        if (dump_trace && report.disable_order)
1376                report.tool.ordered_events = false;
1377
1378        if (quiet)
1379                perf_quiet_option();
1380
1381        if (symbol_conf.vmlinux_name &&
1382            access(symbol_conf.vmlinux_name, R_OK)) {
1383                pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name);
1384                ret = -EINVAL;
1385                goto exit;
1386        }
1387        if (symbol_conf.kallsyms_name &&
1388            access(symbol_conf.kallsyms_name, R_OK)) {
1389                pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name);
1390                ret = -EINVAL;
1391                goto exit;
1392        }
1393
1394        if (report.inverted_callchain)
1395                callchain_param.order = ORDER_CALLER;
1396        if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
1397                callchain_param.order = ORDER_CALLER;
1398
1399        if ((itrace_synth_opts.callchain || itrace_synth_opts.add_callchain) &&
1400            (int)itrace_synth_opts.callchain_sz > report.max_stack)
1401                report.max_stack = itrace_synth_opts.callchain_sz;
1402
1403        if (!input_name || !strlen(input_name)) {
1404                if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
1405                        input_name = "-";
1406                else
1407                        input_name = "perf.data";
1408        }
1409
1410        data.path  = input_name;
1411        data.force = symbol_conf.force;
1412
1413repeat:
1414        session = perf_session__new(&data, &report.tool);
1415        if (IS_ERR(session)) {
1416                ret = PTR_ERR(session);
1417                goto exit;
1418        }
1419
1420        ret = evswitch__init(&report.evswitch, session->evlist, stderr);
1421        if (ret)
1422                goto exit;
1423
1424        if (zstd_init(&(session->zstd_data), 0) < 0)
1425                pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
1426
1427        if (report.queue_size) {
1428                ordered_events__set_alloc_size(&session->ordered_events,
1429                                               report.queue_size);
1430        }
1431
1432        session->itrace_synth_opts = &itrace_synth_opts;
1433
1434        report.session = session;
1435
1436        has_br_stack = perf_header__has_feat(&session->header,
1437                                             HEADER_BRANCH_STACK);
1438        if (evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER)
1439                has_br_stack = false;
1440
1441        setup_forced_leader(&report, session->evlist);
1442
1443        if (symbol_conf.group_sort_idx && !session->evlist->core.nr_groups) {
1444                parse_options_usage(NULL, options, "group-sort-idx", 0);
1445                ret = -EINVAL;
1446                goto error;
1447        }
1448
1449        if (itrace_synth_opts.last_branch || itrace_synth_opts.add_last_branch)
1450                has_br_stack = true;
1451
1452        if (has_br_stack && branch_call_mode)
1453                symbol_conf.show_branchflag_count = true;
1454
1455        memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
1456
1457        /*
1458         * Branch mode is a tristate:
1459         * -1 means default, so decide based on the file having branch data.
1460         * 0/1 means the user chose a mode.
1461         */
1462        if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
1463            !branch_call_mode) {
1464                sort__mode = SORT_MODE__BRANCH;
1465                symbol_conf.cumulate_callchain = false;
1466        }
1467        if (branch_call_mode) {
1468                callchain_param.key = CCKEY_ADDRESS;
1469                callchain_param.branch_callstack = true;
1470                symbol_conf.use_callchain = true;
1471                callchain_register_param(&callchain_param);
1472                if (sort_order == NULL)
1473                        sort_order = "srcline,symbol,dso";
1474        }
1475
1476        if (report.mem_mode) {
1477                if (sort__mode == SORT_MODE__BRANCH) {
1478                        pr_err("branch and mem mode incompatible\n");
1479                        goto error;
1480                }
1481                sort__mode = SORT_MODE__MEMORY;
1482                symbol_conf.cumulate_callchain = false;
1483        }
1484
1485        if (symbol_conf.report_hierarchy) {
1486                /* disable incompatible options */
1487                symbol_conf.cumulate_callchain = false;
1488
1489                if (field_order) {
1490                        pr_err("Error: --hierarchy and --fields options cannot be used together\n");
1491                        parse_options_usage(report_usage, options, "F", 1);
1492                        parse_options_usage(NULL, options, "hierarchy", 0);
1493                        goto error;
1494                }
1495
1496                perf_hpp_list.need_collapse = true;
1497        }
1498
1499        if (report.use_stdio)
1500                use_browser = 0;
1501        else if (report.use_tui)
1502                use_browser = 1;
1503        else if (report.use_gtk)
1504                use_browser = 2;
1505
1506        /* Force tty output for header output and per-thread stat. */
1507        if (report.header || report.header_only || report.show_threads)
1508                use_browser = 0;
1509        if (report.header || report.header_only)
1510                report.tool.show_feat_hdr = SHOW_FEAT_HEADER;
1511        if (report.show_full_info)
1512                report.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
1513        if (report.stats_mode || report.tasks_mode)
1514                use_browser = 0;
1515        if (report.stats_mode && report.tasks_mode) {
1516                pr_err("Error: --tasks and --mmaps can't be used together with --stats\n");
1517                goto error;
1518        }
1519
1520        if (report.total_cycles_mode) {
1521                if (sort__mode != SORT_MODE__BRANCH)
1522                        report.total_cycles_mode = false;
1523                else
1524                        sort_order = NULL;
1525        }
1526
1527        if (strcmp(input_name, "-") != 0)
1528                setup_browser(true);
1529        else
1530                use_browser = 0;
1531
1532        if (sort_order && strstr(sort_order, "ipc")) {
1533                parse_options_usage(report_usage, options, "s", 1);
1534                goto error;
1535        }
1536
1537        if (sort_order && strstr(sort_order, "symbol")) {
1538                if (sort__mode == SORT_MODE__BRANCH) {
1539                        snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s",
1540                                 sort_order, "ipc_lbr");
1541                        report.symbol_ipc = true;
1542                } else {
1543                        snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s",
1544                                 sort_order, "ipc_null");
1545                }
1546
1547                sort_order = sort_tmp;
1548        }
1549
1550        if ((last_key != K_SWITCH_INPUT_DATA && last_key != K_RELOAD) &&
1551            (setup_sorting(session->evlist) < 0)) {
1552                if (sort_order)
1553                        parse_options_usage(report_usage, options, "s", 1);
1554                if (field_order)
1555                        parse_options_usage(sort_order ? NULL : report_usage,
1556                                            options, "F", 1);
1557                goto error;
1558        }
1559
1560        if ((report.header || report.header_only) && !quiet) {
1561                perf_session__fprintf_info(session, stdout,
1562                                           report.show_full_info);
1563                if (report.header_only) {
1564                        if (data.is_pipe) {
1565                                /*
1566                                 * we need to process first few records
1567                                 * which contains PERF_RECORD_HEADER_FEATURE.
1568                                 */
1569                                perf_session__process_events(session);
1570                        }
1571                        ret = 0;
1572                        goto error;
1573                }
1574        } else if (use_browser == 0 && !quiet &&
1575                   !report.stats_mode && !report.tasks_mode) {
1576                fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
1577                      stdout);
1578        }
1579
1580        /*
1581         * Only in the TUI browser we are doing integrated annotation,
1582         * so don't allocate extra space that won't be used in the stdio
1583         * implementation.
1584         */
1585        if (ui__has_annotation() || report.symbol_ipc ||
1586            report.total_cycles_mode) {
1587                ret = symbol__annotation_init();
1588                if (ret < 0)
1589                        goto error;
1590                /*
1591                 * For searching by name on the "Browse map details".
1592                 * providing it only in verbose mode not to bloat too
1593                 * much struct symbol.
1594                 */
1595                if (verbose > 0) {
1596                        /*
1597                         * XXX: Need to provide a less kludgy way to ask for
1598                         * more space per symbol, the u32 is for the index on
1599                         * the ui browser.
1600                         * See symbol__browser_index.
1601                         */
1602                        symbol_conf.priv_size += sizeof(u32);
1603                        symbol_conf.sort_by_name = true;
1604                }
1605                annotation_config__init(&report.annotation_opts);
1606        }
1607
1608        if (symbol__init(&session->header.env) < 0)
1609                goto error;
1610
1611        if (report.time_str) {
1612                ret = perf_time__parse_for_ranges(report.time_str, session,
1613                                                  &report.ptime_range,
1614                                                  &report.range_size,
1615                                                  &report.range_num);
1616                if (ret < 0)
1617                        goto error;
1618
1619                itrace_synth_opts__set_time_range(&itrace_synth_opts,
1620                                                  report.ptime_range,
1621                                                  report.range_num);
1622        }
1623
1624        if (session->tevent.pevent &&
1625            tep_set_function_resolver(session->tevent.pevent,
1626                                      machine__resolve_kernel_addr,
1627                                      &session->machines.host) < 0) {
1628                pr_err("%s: failed to set libtraceevent function resolver\n",
1629                       __func__);
1630                return -1;
1631        }
1632
1633        sort__setup_elide(stdout);
1634
1635        ret = __cmd_report(&report);
1636        if (ret == K_SWITCH_INPUT_DATA || ret == K_RELOAD) {
1637                perf_session__delete(session);
1638                last_key = K_SWITCH_INPUT_DATA;
1639                goto repeat;
1640        } else
1641                ret = 0;
1642
1643error:
1644        if (report.ptime_range) {
1645                itrace_synth_opts__clear_time_range(&itrace_synth_opts);
1646                zfree(&report.ptime_range);
1647        }
1648
1649        if (report.block_reports) {
1650                block_info__free_report(report.block_reports,
1651                                        report.nr_block_reports);
1652                report.block_reports = NULL;
1653        }
1654
1655        zstd_fini(&(session->zstd_data));
1656        perf_session__delete(session);
1657exit:
1658        free(sort_order_help);
1659        free(field_order_help);
1660        return ret;
1661}
1662