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