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, struct addr_location *addr_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 (addr_al) {
 393                err = db_ids_from_al(dbe, addr_al, &es.addr_dso_db_id,
 394                                     &es.addr_sym_db_id, &es.addr_offset);
 395                if (err)
 396                        goto out_put;
 397                if (dbe->crp) {
 398                        err = thread_stack__process(thread, comm, sample, al,
 399                                                    addr_al, es.db_id,
 400                                                    dbe->crp);
 401                        if (err)
 402                                goto out_put;
 403                }
 404        }
 405
 406        if (dbe->export_sample)
 407                err = dbe->export_sample(dbe, &es);
 408
 409out_put:
 410        thread__put(main_thread);
 411        return err;
 412}
 413
 414static struct {
 415        u32 branch_type;
 416        const char *name;
 417} branch_types[] = {
 418        {0, "no branch"},
 419        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
 420        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
 421        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
 422        {PERF_IP_FLAG_BRANCH, "unconditional jump"},
 423        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
 424         "software interrupt"},
 425        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
 426         "return from interrupt"},
 427        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
 428         "system call"},
 429        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
 430         "return from system call"},
 431        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
 432        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
 433         PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
 434        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
 435        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
 436        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
 437        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vm entry"},
 438        {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vm exit"},
 439        {0, NULL}
 440};
 441
 442int db_export__branch_types(struct db_export *dbe)
 443{
 444        int i, err = 0;
 445
 446        for (i = 0; branch_types[i].name ; i++) {
 447                err = db_export__branch_type(dbe, branch_types[i].branch_type,
 448                                             branch_types[i].name);
 449                if (err)
 450                        break;
 451        }
 452
 453        /* Add trace begin / end variants */
 454        for (i = 0; branch_types[i].name ; i++) {
 455                const char *name = branch_types[i].name;
 456                u32 type = branch_types[i].branch_type;
 457                char buf[64];
 458
 459                if (type == PERF_IP_FLAG_BRANCH ||
 460                    (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
 461                        continue;
 462
 463                snprintf(buf, sizeof(buf), "trace begin / %s", name);
 464                err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
 465                if (err)
 466                        break;
 467
 468                snprintf(buf, sizeof(buf), "%s / trace end", name);
 469                err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
 470                if (err)
 471                        break;
 472        }
 473
 474        return err;
 475}
 476
 477int db_export__call_path(struct db_export *dbe, struct call_path *cp)
 478{
 479        int err;
 480
 481        if (cp->db_id)
 482                return 0;
 483
 484        if (cp->parent) {
 485                err = db_export__call_path(dbe, cp->parent);
 486                if (err)
 487                        return err;
 488        }
 489
 490        cp->db_id = ++dbe->call_path_last_db_id;
 491
 492        if (dbe->export_call_path)
 493                return dbe->export_call_path(dbe, cp);
 494
 495        return 0;
 496}
 497
 498int db_export__call_return(struct db_export *dbe, struct call_return *cr,
 499                           u64 *parent_db_id)
 500{
 501        int err;
 502
 503        err = db_export__call_path(dbe, cr->cp);
 504        if (err)
 505                return err;
 506
 507        if (!cr->db_id)
 508                cr->db_id = ++dbe->call_return_last_db_id;
 509
 510        if (parent_db_id) {
 511                if (!*parent_db_id)
 512                        *parent_db_id = ++dbe->call_return_last_db_id;
 513                cr->parent_db_id = *parent_db_id;
 514        }
 515
 516        if (dbe->export_call_return)
 517                return dbe->export_call_return(dbe, cr);
 518
 519        return 0;
 520}
 521
 522static int db_export__pid_tid(struct db_export *dbe, struct machine *machine,
 523                              pid_t pid, pid_t tid, u64 *db_id,
 524                              struct comm **comm_ptr, bool *is_idle)
 525{
 526        struct thread *thread = machine__find_thread(machine, pid, tid);
 527        struct thread *main_thread;
 528        int err = 0;
 529
 530        if (!thread || !thread->comm_set)
 531                goto out_put;
 532
 533        *is_idle = !thread->pid_ && !thread->tid;
 534
 535        main_thread = thread__main_thread(machine, thread);
 536
 537        err = db_export__threads(dbe, thread, main_thread, machine, comm_ptr);
 538
 539        *db_id = thread->db_id;
 540
 541        thread__put(main_thread);
 542out_put:
 543        thread__put(thread);
 544
 545        return err;
 546}
 547
 548int db_export__switch(struct db_export *dbe, union perf_event *event,
 549                      struct perf_sample *sample, struct machine *machine)
 550{
 551        bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
 552        bool out_preempt = out &&
 553                (event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT);
 554        int flags = out | (out_preempt << 1);
 555        bool is_idle_a = false, is_idle_b = false;
 556        u64 th_a_id = 0, th_b_id = 0;
 557        u64 comm_out_id, comm_in_id;
 558        struct comm *comm_a = NULL;
 559        struct comm *comm_b = NULL;
 560        u64 th_out_id, th_in_id;
 561        u64 db_id;
 562        int err;
 563
 564        err = db_export__machine(dbe, machine);
 565        if (err)
 566                return err;
 567
 568        err = db_export__pid_tid(dbe, machine, sample->pid, sample->tid,
 569                                 &th_a_id, &comm_a, &is_idle_a);
 570        if (err)
 571                return err;
 572
 573        if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
 574                pid_t pid = event->context_switch.next_prev_pid;
 575                pid_t tid = event->context_switch.next_prev_tid;
 576
 577                err = db_export__pid_tid(dbe, machine, pid, tid, &th_b_id,
 578                                         &comm_b, &is_idle_b);
 579                if (err)
 580                        return err;
 581        }
 582
 583        /*
 584         * Do not export if both threads are unknown (i.e. not being traced),
 585         * or one is unknown and the other is the idle task.
 586         */
 587        if ((!th_a_id || is_idle_a) && (!th_b_id || is_idle_b))
 588                return 0;
 589
 590        db_id = ++dbe->context_switch_last_db_id;
 591
 592        if (out) {
 593                th_out_id   = th_a_id;
 594                th_in_id    = th_b_id;
 595                comm_out_id = comm_a ? comm_a->db_id : 0;
 596                comm_in_id  = comm_b ? comm_b->db_id : 0;
 597        } else {
 598                th_out_id   = th_b_id;
 599                th_in_id    = th_a_id;
 600                comm_out_id = comm_b ? comm_b->db_id : 0;
 601                comm_in_id  = comm_a ? comm_a->db_id : 0;
 602        }
 603
 604        if (dbe->export_context_switch)
 605                return dbe->export_context_switch(dbe, db_id, machine, sample,
 606                                                  th_out_id, comm_out_id,
 607                                                  th_in_id, comm_in_id, flags);
 608        return 0;
 609}
 610