linux/tools/perf/util/db-export.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * db-export.c: Support for exporting data suitable for import to a database
   4 * Copyright (c) 2014, Intel Corporation.
   5 */
   6
   7#include <errno.h>
   8#include <stdlib.h>
   9
  10#include "dso.h"
  11#include "evsel.h"
  12#include "machine.h"
  13#include "thread.h"
  14#include "comm.h"
  15#include "symbol.h"
  16#include "map.h"
  17#include "event.h"
  18#include "thread-stack.h"
  19#include "callchain.h"
  20#include "call-path.h"
  21#include "db-export.h"
  22#include <linux/zalloc.h>
  23
  24int db_export__init(struct db_export *dbe)
  25{
  26        memset(dbe, 0, sizeof(struct db_export));
  27        return 0;
  28}
  29
  30void db_export__exit(struct db_export *dbe)
  31{
  32        call_return_processor__free(dbe->crp);
  33        dbe->crp = NULL;
  34}
  35
  36int db_export__evsel(struct db_export *dbe, struct evsel *evsel)
  37{
  38        if (evsel->db_id)
  39                return 0;
  40
  41        evsel->db_id = ++dbe->evsel_last_db_id;
  42
  43        if (dbe->export_evsel)
  44                return dbe->export_evsel(dbe, evsel);
  45
  46        return 0;
  47}
  48
  49int db_export__machine(struct db_export *dbe, struct machine *machine)
  50{
  51        if (machine->db_id)
  52                return 0;
  53
  54        machine->db_id = ++dbe->machine_last_db_id;
  55
  56        if (dbe->export_machine)
  57                return dbe->export_machine(dbe, machine);
  58
  59        return 0;
  60}
  61
  62int db_export__thread(struct db_export *dbe, struct thread *thread,
  63                      struct machine *machine, struct thread *main_thread)
  64{
  65        u64 main_thread_db_id = 0;
  66
  67        if (thread->db_id)
  68                return 0;
  69
  70        thread->db_id = ++dbe->thread_last_db_id;
  71
  72        if (main_thread)
  73                main_thread_db_id = main_thread->db_id;
  74
  75        if (dbe->export_thread)
  76                return dbe->export_thread(dbe, thread, main_thread_db_id,
  77                                          machine);
  78
  79        return 0;
  80}
  81
  82static int __db_export__comm(struct db_export *dbe, struct comm *comm,
  83                             struct thread *thread)
  84{
  85        comm->db_id = ++dbe->comm_last_db_id;
  86
  87        if (dbe->export_comm)
  88                return dbe->export_comm(dbe, comm, thread);
  89
  90        return 0;
  91}
  92
  93int db_export__comm(struct db_export *dbe, struct comm *comm,
  94                    struct thread *thread)
  95{
  96        if (comm->db_id)
  97                return 0;
  98
  99        return __db_export__comm(dbe, comm, thread);
 100}
 101
 102/*
 103 * Export the "exec" comm. The "exec" comm is the program / application command
 104 * name at the time it first executes. It is used to group threads for the same
 105 * program. Note that the main thread pid (or thread group id tgid) cannot be
 106 * used because it does not change when a new program is exec'ed.
 107 */
 108int db_export__exec_comm(struct db_export *dbe, struct comm *comm,
 109                         struct thread *main_thread)
 110{
 111        int err;
 112
 113        if (comm->db_id)
 114                return 0;
 115
 116        err = __db_export__comm(dbe, comm, main_thread);
 117        if (err)
 118                return err;
 119
 120        /*
 121         * Record the main thread for this comm. Note that the main thread can
 122         * have many "exec" comms because there will be a new one every time it
 123         * exec's. An "exec" comm however will only ever have 1 main thread.
 124         * That is different to any other threads for that same program because
 125         * exec() will effectively kill them, so the relationship between the
 126         * "exec" comm and non-main threads is 1-to-1. That is why
 127         * db_export__comm_thread() is called here for the main thread, but it
 128         * is called for non-main threads when they are exported.
 129         */
 130        return db_export__comm_thread(dbe, comm, main_thread);
 131}
 132
 133int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
 134                           struct thread *thread)
 135{
 136        u64 db_id;
 137
 138        db_id = ++dbe->comm_thread_last_db_id;
 139
 140        if (dbe->export_comm_thread)
 141                return dbe->export_comm_thread(dbe, db_id, comm, thread);
 142
 143        return 0;
 144}
 145
 146int db_export__dso(struct db_export *dbe, struct dso *dso,
 147                   struct machine *machine)
 148{
 149        if (dso->db_id)
 150                return 0;
 151
 152        dso->db_id = ++dbe->dso_last_db_id;
 153
 154        if (dbe->export_dso)
 155                return dbe->export_dso(dbe, dso, machine);
 156
 157        return 0;
 158}
 159
 160int db_export__symbol(struct db_export *dbe, struct symbol *sym,
 161                      struct dso *dso)
 162{
 163        u64 *sym_db_id = symbol__priv(sym);
 164
 165        if (*sym_db_id)
 166                return 0;
 167
 168        *sym_db_id = ++dbe->symbol_last_db_id;
 169
 170        if (dbe->export_symbol)
 171                return dbe->export_symbol(dbe, sym, dso);
 172
 173        return 0;
 174}
 175
 176static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
 177                          u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
 178{
 179        int err;
 180
 181        if (al->map) {
 182                struct dso *dso = al->map->dso;
 183
 184                err = db_export__dso(dbe, dso, al->maps->machine);
 185                if (err)
 186                        return err;
 187                *dso_db_id = dso->db_id;
 188
 189                if (!al->sym) {
 190                        al->sym = symbol__new(al->addr, 0, 0, 0, "unknown");
 191                        if (al->sym)
 192                                dso__insert_symbol(dso, al->sym);
 193                }
 194
 195                if (al->sym) {
 196                        u64 *db_id = symbol__priv(al->sym);
 197
 198                        err = db_export__symbol(dbe, al->sym, dso);
 199                        if (err)
 200                                return err;
 201                        *sym_db_id = *db_id;
 202                        *offset = al->addr - al->sym->start;
 203                }
 204        }
 205
 206        return 0;
 207}
 208
 209static struct call_path *call_path_from_sample(struct db_export *dbe,
 210                                               struct machine *machine,
 211                                               struct thread *thread,
 212                                               struct perf_sample *sample,
 213                                               struct evsel *evsel)
 214{
 215        u64 kernel_start = machine__kernel_start(machine);
 216        struct call_path *current = &dbe->cpr->call_path;
 217        enum chain_order saved_order = callchain_param.order;
 218        int err;
 219
 220        if (!symbol_conf.use_callchain || !sample->callchain)
 221                return NULL;
 222
 223        /*
 224         * Since the call path tree must be built starting with the root, we
 225         * must use ORDER_CALL for call chain resolution, in order to process
 226         * the callchain starting with the root node and ending with the leaf.
 227         */
 228        callchain_param.order = ORDER_CALLER;
 229        err = thread__resolve_callchain(thread, &callchain_cursor, evsel,
 230                                        sample, NULL, NULL, PERF_MAX_STACK_DEPTH);
 231        if (err) {
 232                callchain_param.order = saved_order;
 233                return NULL;
 234        }
 235        callchain_cursor_commit(&callchain_cursor);
 236
 237        while (1) {
 238                struct callchain_cursor_node *node;
 239                struct addr_location al;
 240                u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
 241
 242                memset(&al, 0, sizeof(al));
 243
 244                node = callchain_cursor_current(&callchain_cursor);
 245                if (!node)
 246                        break;
 247                /*
 248                 * Handle export of symbol and dso for this node by
 249                 * constructing an addr_location struct and then passing it to
 250                 * db_ids_from_al() to perform the export.
 251                 */
 252                al.sym = node->ms.sym;
 253                al.map = node->ms.map;
 254                al.maps = thread->maps;
 255                al.addr = node->ip;
 256
 257                if (al.map && !al.sym)
 258                        al.sym = dso__find_symbol(al.map->dso, al.addr);
 259
 260                db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
 261
 262                /* add node to the call path tree if it doesn't exist */
 263                current = call_path__findnew(dbe->cpr, current,
 264                                             al.sym, node->ip,
 265                                             kernel_start);
 266
 267                callchain_cursor_advance(&callchain_cursor);
 268        }
 269
 270        /* Reset the callchain order to its prior value. */
 271        callchain_param.order = saved_order;
 272
 273        if (current == &dbe->cpr->call_path) {
 274                /* Bail because the callchain was empty. */
 275                return NULL;
 276        }
 277
 278        return current;
 279}
 280
 281int db_export__branch_type(struct db_export *dbe, u32 branch_type,
 282                           const char *name)
 283{
 284        if (dbe->export_branch_type)
 285                return dbe->export_branch_type(dbe, branch_type, name);
 286
 287        return 0;
 288}
 289
 290static int db_export__threads(struct db_export *dbe, struct thread *thread,
 291                              struct thread *main_thread,
 292                              struct machine *machine, struct comm **comm_ptr)
 293{
 294        struct comm *comm = NULL;
 295        struct comm *curr_comm;
 296        int err;
 297
 298        if (main_thread) {
 299                /*
 300                 * A thread has a reference to the main thread, so export the
 301                 * main thread first.
 302                 */
 303                err = db_export__thread(dbe, main_thread, machine, main_thread);
 304                if (err)
 305                        return err;
 306                /*
 307                 * Export comm before exporting the non-main thread because
 308                 * db_export__comm_thread() can be called further below.
 309                 */
 310                comm = machine__thread_exec_comm(machine, main_thread);
 311                if (comm) {
 312                        err = db_export__exec_comm(dbe, comm, main_thread);
 313                        if (err)
 314                                return err;
 315                        *comm_ptr = comm;
 316                }
 317        }
 318
 319        if (thread != main_thread) {
 320                /*
 321                 * For a non-main thread, db_export__comm_thread() must be
 322                 * called only if thread has not previously been exported.
 323                 */
 324                bool export_comm_thread = comm && !thread->db_id;
 325
 326                err = db_export__thread(dbe, thread, machine, main_thread);
 327                if (err)
 328                        return err;
 329
 330                if (export_comm_thread) {
 331                        err = db_export__comm_thread(dbe, comm, thread);
 332                        if (err)
 333                                return err;
 334                }
 335        }
 336
 337        curr_comm = thread__comm(thread);
 338        if (curr_comm)
 339                return db_export__comm(dbe, curr_comm, thread);
 340
 341        return 0;
 342}
 343
 344int db_export__sample(struct db_export *dbe, union perf_event *event,
 345                      struct perf_sample *sample, struct evsel *evsel,
 346                      struct addr_location *al)
 347{
 348        struct thread *thread = al->thread;
 349        struct export_sample es = {
 350                .event = event,
 351                .sample = sample,
 352                .evsel = evsel,
 353                .al = al,
 354        };
 355        struct thread *main_thread;
 356        struct comm *comm = NULL;
 357        int err;
 358
 359        err = db_export__evsel(dbe, evsel);
 360        if (err)
 361                return err;
 362
 363        err = db_export__machine(dbe, al->maps->machine);
 364        if (err)
 365                return err;
 366
 367        main_thread = thread__main_thread(al->maps->machine, thread);
 368
 369        err = db_export__threads(dbe, thread, main_thread, al->maps->machine, &comm);
 370        if (err)
 371                goto out_put;
 372
 373        if (comm)
 374                es.comm_db_id = comm->db_id;
 375
 376        es.db_id = ++dbe->sample_last_db_id;
 377
 378        err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
 379        if (err)
 380                goto out_put;
 381
 382        if (dbe->cpr) {
 383                struct call_path *cp = call_path_from_sample(dbe, al->maps->machine,
 384                                                             thread, sample,
 385                                                             evsel);
 386                if (cp) {
 387                        db_export__call_path(dbe, cp);
 388                        es.call_path_id = cp->db_id;
 389                }
 390        }
 391
 392        if ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
 393            sample_addr_correlates_sym(&evsel->core.attr)) {
 394                struct addr_location addr_al;
 395
 396                thread__resolve(thread, &addr_al, sample);
 397                err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
 398                                     &es.addr_sym_db_id, &es.addr_offset);
 399                if (err)
 400                        goto out_put;
 401                if (dbe->crp) {
 402                        err = thread_stack__process(thread, comm, sample, al,
 403                                                    &addr_al, es.db_id,
 404                                                    dbe->crp);
 405                        if (err)
 406                                goto out_put;
 407                }
 408        }
 409
 410        if (dbe->export_sample)
 411                err = dbe->export_sample(dbe, &es);
 412
 413out_put:
 414        thread__put(main_thread);
 415        return err;
 416}
 417
 418static struct {
 419        u32 branch_type;
 420        const char *name;
 421} branch_types[] = {
 422        {0, "no branch"},
 423        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
 424        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
 425        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
 426        {PERF_IP_FLAG_BRANCH, "unconditional jump"},
 427        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
 428         "software interrupt"},
 429        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
 430         "return from interrupt"},
 431        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
 432         "system call"},
 433        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
 434         "return from system call"},
 435        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
 436        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
 437         PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
 438        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
 439        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
 440        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
 441        {0, NULL}
 442};
 443
 444int db_export__branch_types(struct db_export *dbe)
 445{
 446        int i, err = 0;
 447
 448        for (i = 0; branch_types[i].name ; i++) {
 449                err = db_export__branch_type(dbe, branch_types[i].branch_type,
 450                                             branch_types[i].name);
 451                if (err)
 452                        break;
 453        }
 454
 455        /* Add trace begin / end variants */
 456        for (i = 0; branch_types[i].name ; i++) {
 457                const char *name = branch_types[i].name;
 458                u32 type = branch_types[i].branch_type;
 459                char buf[64];
 460
 461                if (type == PERF_IP_FLAG_BRANCH ||
 462                    (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
 463                        continue;
 464
 465                snprintf(buf, sizeof(buf), "trace begin / %s", name);
 466                err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
 467                if (err)
 468                        break;
 469
 470                snprintf(buf, sizeof(buf), "%s / trace end", name);
 471                err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
 472                if (err)
 473                        break;
 474        }
 475
 476        return err;
 477}
 478
 479int db_export__call_path(struct db_export *dbe, struct call_path *cp)
 480{
 481        int err;
 482
 483        if (cp->db_id)
 484                return 0;
 485
 486        if (cp->parent) {
 487                err = db_export__call_path(dbe, cp->parent);
 488                if (err)
 489                        return err;
 490        }
 491
 492        cp->db_id = ++dbe->call_path_last_db_id;
 493
 494        if (dbe->export_call_path)
 495                return dbe->export_call_path(dbe, cp);
 496
 497        return 0;
 498}
 499
 500int db_export__call_return(struct db_export *dbe, struct call_return *cr,
 501                           u64 *parent_db_id)
 502{
 503        int err;
 504
 505        err = db_export__call_path(dbe, cr->cp);
 506        if (err)
 507                return err;
 508
 509        if (!cr->db_id)
 510                cr->db_id = ++dbe->call_return_last_db_id;
 511
 512        if (parent_db_id) {
 513                if (!*parent_db_id)
 514                        *parent_db_id = ++dbe->call_return_last_db_id;
 515                cr->parent_db_id = *parent_db_id;
 516        }
 517
 518        if (dbe->export_call_return)
 519                return dbe->export_call_return(dbe, cr);
 520
 521        return 0;
 522}
 523
 524static int db_export__pid_tid(struct db_export *dbe, struct machine *machine,
 525                              pid_t pid, pid_t tid, u64 *db_id,
 526                              struct comm **comm_ptr, bool *is_idle)
 527{
 528        struct thread *thread = machine__find_thread(machine, pid, tid);
 529        struct thread *main_thread;
 530        int err = 0;
 531
 532        if (!thread || !thread->comm_set)
 533                goto out_put;
 534
 535        *is_idle = !thread->pid_ && !thread->tid;
 536
 537        main_thread = thread__main_thread(machine, thread);
 538
 539        err = db_export__threads(dbe, thread, main_thread, machine, comm_ptr);
 540
 541        *db_id = thread->db_id;
 542
 543        thread__put(main_thread);
 544out_put:
 545        thread__put(thread);
 546
 547        return err;
 548}
 549
 550int db_export__switch(struct db_export *dbe, union perf_event *event,
 551                      struct perf_sample *sample, struct machine *machine)
 552{
 553        bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
 554        bool out_preempt = out &&
 555                (event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT);
 556        int flags = out | (out_preempt << 1);
 557        bool is_idle_a = false, is_idle_b = false;
 558        u64 th_a_id = 0, th_b_id = 0;
 559        u64 comm_out_id, comm_in_id;
 560        struct comm *comm_a = NULL;
 561        struct comm *comm_b = NULL;
 562        u64 th_out_id, th_in_id;
 563        u64 db_id;
 564        int err;
 565
 566        err = db_export__machine(dbe, machine);
 567        if (err)
 568                return err;
 569
 570        err = db_export__pid_tid(dbe, machine, sample->pid, sample->tid,
 571                                 &th_a_id, &comm_a, &is_idle_a);
 572        if (err)
 573                return err;
 574
 575        if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
 576                pid_t pid = event->context_switch.next_prev_pid;
 577                pid_t tid = event->context_switch.next_prev_tid;
 578
 579                err = db_export__pid_tid(dbe, machine, pid, tid, &th_b_id,
 580                                         &comm_b, &is_idle_b);
 581                if (err)
 582                        return err;
 583        }
 584
 585        /*
 586         * Do not export if both threads are unknown (i.e. not being traced),
 587         * or one is unknown and the other is the idle task.
 588         */
 589        if ((!th_a_id || is_idle_a) && (!th_b_id || is_idle_b))
 590                return 0;
 591
 592        db_id = ++dbe->context_switch_last_db_id;
 593
 594        if (out) {
 595                th_out_id   = th_a_id;
 596                th_in_id    = th_b_id;
 597                comm_out_id = comm_a ? comm_a->db_id : 0;
 598                comm_in_id  = comm_b ? comm_b->db_id : 0;
 599        } else {
 600                th_out_id   = th_b_id;
 601                th_in_id    = th_a_id;
 602                comm_out_id = comm_b ? comm_b->db_id : 0;
 603                comm_in_id  = comm_a ? comm_a->db_id : 0;
 604        }
 605
 606        if (dbe->export_context_switch)
 607                return dbe->export_context_switch(dbe, db_id, machine, sample,
 608                                                  th_out_id, comm_out_id,
 609                                                  th_in_id, comm_in_id, flags);
 610        return 0;
 611}
 612