1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * builtin-inject.c 4 * 5 * Builtin inject command: Examine the live mode (stdin) event stream 6 * and repipe it to stdout while optionally injecting additional 7 * events into it. 8 */ 9 #include "builtin.h" 10 11 #include "util/color.h" 12 #include "util/dso.h" 13 #include "util/vdso.h" 14 #include "util/evlist.h" 15 #include "util/evsel.h" 16 #include "util/map.h" 17 #include "util/session.h" 18 #include "util/tool.h" 19 #include "util/debug.h" 20 #include "util/build-id.h" 21 #include "util/data.h" 22 #include "util/auxtrace.h" 23 #include "util/jit.h" 24 #include "util/string2.h" 25 #include "util/symbol.h" 26 #include "util/synthetic-events.h" 27 #include "util/thread.h" 28 #include "util/namespaces.h" 29 #include "util/util.h" 30 #include "util/tsc.h" 31 32 #include <internal/lib.h> 33 34 #include <linux/err.h> 35 #include <subcmd/parse-options.h> 36 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 37 38 #include <linux/list.h> 39 #include <linux/string.h> 40 #include <linux/zalloc.h> 41 #include <linux/hash.h> 42 #include <ctype.h> 43 #include <errno.h> 44 #include <signal.h> 45 #include <inttypes.h> 46 47 struct guest_event { 48 struct perf_sample sample; 49 union perf_event *event; 50 char *event_buf; 51 }; 52 53 struct guest_id { 54 /* hlist_node must be first, see free_hlist() */ 55 struct hlist_node node; 56 u64 id; 57 u64 host_id; 58 u32 vcpu; 59 }; 60 61 struct guest_tid { 62 /* hlist_node must be first, see free_hlist() */ 63 struct hlist_node node; 64 /* Thread ID of QEMU thread */ 65 u32 tid; 66 u32 vcpu; 67 }; 68 69 struct guest_vcpu { 70 /* Current host CPU */ 71 u32 cpu; 72 /* Thread ID of QEMU thread */ 73 u32 tid; 74 }; 75 76 struct guest_session { 77 char *perf_data_file; 78 u32 machine_pid; 79 u64 time_offset; 80 double time_scale; 81 struct perf_tool tool; 82 struct perf_data data; 83 struct perf_session *session; 84 char *tmp_file_name; 85 int tmp_fd; 86 struct perf_tsc_conversion host_tc; 87 struct perf_tsc_conversion guest_tc; 88 bool copy_kcore_dir; 89 bool have_tc; 90 bool fetched; 91 bool ready; 92 u16 dflt_id_hdr_size; 93 u64 dflt_id; 94 u64 highest_id; 95 /* Array of guest_vcpu */ 96 struct guest_vcpu *vcpu; 97 size_t vcpu_cnt; 98 /* Hash table for guest_id */ 99 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 100 /* Hash table for guest_tid */ 101 struct hlist_head tids[PERF_EVLIST__HLIST_SIZE]; 102 /* Place to stash next guest event */ 103 struct guest_event ev; 104 }; 105 106 enum build_id_rewrite_style { 107 BID_RWS__NONE = 0, 108 BID_RWS__INJECT_HEADER_LAZY, 109 BID_RWS__INJECT_HEADER_ALL, 110 BID_RWS__MMAP2_BUILDID_ALL, 111 BID_RWS__MMAP2_BUILDID_LAZY, 112 }; 113 114 struct perf_inject { 115 struct perf_tool tool; 116 struct perf_session *session; 117 enum build_id_rewrite_style build_id_style; 118 bool sched_stat; 119 bool have_auxtrace; 120 bool strip; 121 bool jit_mode; 122 bool in_place_update; 123 bool in_place_update_dry_run; 124 bool copy_kcore_dir; 125 bool convert_callchain; 126 const char *input_name; 127 struct perf_data output; 128 u64 bytes_written; 129 u64 aux_id; 130 struct list_head samples; 131 struct itrace_synth_opts itrace_synth_opts; 132 char *event_copy; 133 struct perf_file_section secs[HEADER_FEAT_BITS]; 134 struct guest_session guest_session; 135 struct strlist *known_build_ids; 136 struct evsel *mmap_evsel; 137 struct ip_callchain *raw_callchain; 138 }; 139 140 struct event_entry { 141 struct list_head node; 142 u32 tid; 143 union perf_event event[]; 144 }; 145 146 static int tool__inject_build_id(const struct perf_tool *tool, 147 struct perf_sample *sample, 148 struct machine *machine, 149 const struct evsel *evsel, 150 __u16 misc, 151 const char *filename, 152 struct dso *dso, u32 flags); 153 static int tool__inject_mmap2_build_id(const struct perf_tool *tool, 154 struct perf_sample *sample, 155 struct machine *machine, 156 const struct evsel *evsel, 157 __u16 misc, 158 __u32 pid, __u32 tid, 159 __u64 start, __u64 len, __u64 pgoff, 160 struct dso *dso, 161 __u32 prot, __u32 flags, 162 const char *filename); 163 164 static int output_bytes(struct perf_inject *inject, void *buf, size_t sz) 165 { 166 ssize_t size; 167 168 size = perf_data__write(&inject->output, buf, sz); 169 if (size < 0) 170 return -errno; 171 172 inject->bytes_written += size; 173 return 0; 174 } 175 176 static int perf_event__repipe_synth(const struct perf_tool *tool, 177 union perf_event *event) 178 179 { 180 struct perf_inject *inject = container_of(tool, struct perf_inject, 181 tool); 182 183 return output_bytes(inject, event, event->header.size); 184 } 185 186 static int perf_event__repipe_oe_synth(const struct perf_tool *tool, 187 union perf_event *event, 188 struct ordered_events *oe __maybe_unused) 189 { 190 return perf_event__repipe_synth(tool, event); 191 } 192 193 #ifdef HAVE_JITDUMP 194 static int perf_event__drop_oe(const struct perf_tool *tool __maybe_unused, 195 union perf_event *event __maybe_unused, 196 struct ordered_events *oe __maybe_unused) 197 { 198 return 0; 199 } 200 #endif 201 202 static int perf_event__repipe_op2_synth(const struct perf_tool *tool, 203 struct perf_session *session __maybe_unused, 204 union perf_event *event) 205 { 206 return perf_event__repipe_synth(tool, event); 207 } 208 209 static int perf_event__repipe_op4_synth(const struct perf_tool *tool, 210 struct perf_session *session __maybe_unused, 211 union perf_event *event, 212 u64 data __maybe_unused, 213 const char *str __maybe_unused) 214 { 215 return perf_event__repipe_synth(tool, event); 216 } 217 218 static int perf_event__repipe_attr(const struct perf_tool *tool, 219 union perf_event *event, 220 struct evlist **pevlist) 221 { 222 struct perf_inject *inject = container_of(tool, struct perf_inject, 223 tool); 224 int ret; 225 226 ret = perf_event__process_attr(tool, event, pevlist); 227 if (ret) 228 return ret; 229 230 /* If the output isn't a pipe then the attributes will be written as part of the header. */ 231 if (!inject->output.is_pipe) 232 return 0; 233 234 return perf_event__repipe_synth(tool, event); 235 } 236 237 static int perf_event__repipe_event_update(const struct perf_tool *tool, 238 union perf_event *event, 239 struct evlist **pevlist __maybe_unused) 240 { 241 return perf_event__repipe_synth(tool, event); 242 } 243 244 static int copy_bytes(struct perf_inject *inject, struct perf_data *data, off_t size) 245 { 246 char buf[4096]; 247 ssize_t ssz; 248 int ret; 249 250 while (size > 0) { 251 ssz = perf_data__read(data, buf, min(size, (off_t)sizeof(buf))); 252 if (ssz < 0) 253 return -errno; 254 ret = output_bytes(inject, buf, ssz); 255 if (ret) 256 return ret; 257 size -= ssz; 258 } 259 260 return 0; 261 } 262 263 static s64 perf_event__repipe_auxtrace(const struct perf_tool *tool, 264 struct perf_session *session, 265 union perf_event *event) 266 { 267 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 268 int ret; 269 270 inject->have_auxtrace = true; 271 272 if (!inject->output.is_pipe) { 273 off_t offset = perf_data__seek(&inject->output, 0, SEEK_CUR); 274 275 if (offset == -1) 276 return -errno; 277 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index, 278 event, offset); 279 if (ret < 0) 280 return ret; 281 } 282 283 if (perf_data__is_pipe(session->data) || !session->one_mmap) { 284 ret = output_bytes(inject, event, event->header.size); 285 if (ret < 0) 286 return ret; 287 ret = copy_bytes(inject, session->data, 288 event->auxtrace.size); 289 } else { 290 ret = output_bytes(inject, event, 291 event->header.size + event->auxtrace.size); 292 } 293 if (ret < 0) 294 return ret; 295 296 return event->auxtrace.size; 297 } 298 299 static int perf_event__repipe(const struct perf_tool *tool, 300 union perf_event *event, 301 struct perf_sample *sample __maybe_unused, 302 struct machine *machine __maybe_unused) 303 { 304 return perf_event__repipe_synth(tool, event); 305 } 306 307 static int perf_event__drop(const struct perf_tool *tool __maybe_unused, 308 union perf_event *event __maybe_unused, 309 struct perf_sample *sample __maybe_unused, 310 struct machine *machine __maybe_unused) 311 { 312 return 0; 313 } 314 315 static int perf_event__drop_aux(const struct perf_tool *tool, 316 union perf_event *event __maybe_unused, 317 struct perf_sample *sample, 318 struct machine *machine __maybe_unused) 319 { 320 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 321 322 if (!inject->aux_id) 323 inject->aux_id = sample->id; 324 325 return 0; 326 } 327 328 static union perf_event * 329 perf_inject__cut_auxtrace_sample(struct perf_inject *inject, 330 union perf_event *event, 331 struct perf_sample *sample) 332 { 333 size_t sz1 = sample->aux_sample.data - (void *)event; 334 size_t sz2 = event->header.size - sample->aux_sample.size - sz1; 335 union perf_event *ev; 336 337 if (inject->event_copy == NULL) { 338 inject->event_copy = malloc(PERF_SAMPLE_MAX_SIZE); 339 if (!inject->event_copy) 340 return ERR_PTR(-ENOMEM); 341 } 342 ev = (union perf_event *)inject->event_copy; 343 if (sz1 > event->header.size || sz2 > event->header.size || 344 sz1 + sz2 > event->header.size || 345 sz1 < sizeof(struct perf_event_header) + sizeof(u64)) 346 return event; 347 348 memcpy(ev, event, sz1); 349 memcpy((void *)ev + sz1, (void *)event + event->header.size - sz2, sz2); 350 ev->header.size = sz1 + sz2; 351 ((u64 *)((void *)ev + sz1))[-1] = 0; 352 353 return ev; 354 } 355 356 typedef int (*inject_handler)(const struct perf_tool *tool, 357 union perf_event *event, 358 struct perf_sample *sample, 359 struct evsel *evsel, 360 struct machine *machine); 361 362 static int perf_event__repipe_sample(const struct perf_tool *tool, 363 union perf_event *event, 364 struct perf_sample *sample, 365 struct evsel *evsel, 366 struct machine *machine) 367 { 368 struct perf_inject *inject = container_of(tool, struct perf_inject, 369 tool); 370 371 if (evsel && evsel->handler) { 372 inject_handler f = evsel->handler; 373 return f(tool, event, sample, evsel, machine); 374 } 375 376 build_id__mark_dso_hit(tool, event, sample, evsel, machine); 377 378 if (inject->itrace_synth_opts.set && sample->aux_sample.size) { 379 event = perf_inject__cut_auxtrace_sample(inject, event, sample); 380 if (IS_ERR(event)) 381 return PTR_ERR(event); 382 } 383 384 return perf_event__repipe_synth(tool, event); 385 } 386 387 static int perf_event__convert_sample_callchain(const struct perf_tool *tool, 388 union perf_event *event, 389 struct perf_sample *sample, 390 struct evsel *evsel, 391 struct machine *machine) 392 { 393 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 394 struct callchain_cursor *cursor = get_tls_callchain_cursor(); 395 union perf_event *event_copy = (void *)inject->event_copy; 396 struct callchain_cursor_node *node; 397 struct thread *thread; 398 u64 sample_type = evsel->core.attr.sample_type; 399 u32 sample_size = event->header.size; 400 u64 i, k; 401 int ret; 402 403 if (event_copy == NULL) { 404 inject->event_copy = malloc(PERF_SAMPLE_MAX_SIZE); 405 if (!inject->event_copy) 406 return -ENOMEM; 407 408 event_copy = (void *)inject->event_copy; 409 } 410 411 if (cursor == NULL) 412 return -ENOMEM; 413 414 callchain_cursor_reset(cursor); 415 416 thread = machine__find_thread(machine, sample->tid, sample->pid); 417 if (thread == NULL) 418 goto out; 419 420 /* this will parse DWARF using stack and register data */ 421 ret = thread__resolve_callchain(thread, cursor, evsel, sample, 422 /*parent=*/NULL, /*root_al=*/NULL, 423 PERF_MAX_STACK_DEPTH); 424 thread__put(thread); 425 if (ret != 0) 426 goto out; 427 428 /* copy kernel callchain and context entries */ 429 for (i = 0; i < sample->callchain->nr; i++) { 430 inject->raw_callchain->ips[i] = sample->callchain->ips[i]; 431 if (sample->callchain->ips[i] == PERF_CONTEXT_USER) { 432 i++; 433 break; 434 } 435 } 436 if (i == 0 || inject->raw_callchain->ips[i - 1] != PERF_CONTEXT_USER) 437 inject->raw_callchain->ips[i++] = PERF_CONTEXT_USER; 438 439 node = cursor->first; 440 for (k = 0; k < cursor->nr && i < PERF_MAX_STACK_DEPTH; k++) { 441 if (machine__kernel_ip(machine, node->ip)) 442 /* kernel IPs were added already */; 443 else if (node->ms.sym && node->ms.sym->inlined) 444 /* we can't handle inlined callchains */; 445 else 446 inject->raw_callchain->ips[i++] = node->ip; 447 448 node = node->next; 449 } 450 451 inject->raw_callchain->nr = i; 452 sample->callchain = inject->raw_callchain; 453 454 out: 455 memcpy(event_copy, event, sizeof(event->header)); 456 457 /* adjust sample size for stack and regs */ 458 sample_size -= sample->user_stack.size; 459 sample_size -= (hweight64(evsel->core.attr.sample_regs_user) + 1) * sizeof(u64); 460 sample_size += (sample->callchain->nr + 1) * sizeof(u64); 461 event_copy->header.size = sample_size; 462 463 /* remove sample_type {STACK,REGS}_USER for synthesize */ 464 sample_type &= ~(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER); 465 466 perf_event__synthesize_sample(event_copy, sample_type, 467 evsel->core.attr.read_format, sample); 468 return perf_event__repipe_synth(tool, event_copy); 469 } 470 471 static struct dso *findnew_dso(int pid, int tid, const char *filename, 472 const struct dso_id *id, struct machine *machine) 473 { 474 struct thread *thread; 475 struct nsinfo *nsi = NULL; 476 struct nsinfo *nnsi; 477 struct dso *dso; 478 bool vdso; 479 480 thread = machine__findnew_thread(machine, pid, tid); 481 if (thread == NULL) { 482 pr_err("cannot find or create a task %d/%d.\n", tid, pid); 483 return NULL; 484 } 485 486 vdso = is_vdso_map(filename); 487 nsi = nsinfo__get(thread__nsinfo(thread)); 488 489 if (vdso) { 490 /* The vdso maps are always on the host and not the 491 * container. Ensure that we don't use setns to look 492 * them up. 493 */ 494 nnsi = nsinfo__copy(nsi); 495 if (nnsi) { 496 nsinfo__put(nsi); 497 nsinfo__clear_need_setns(nnsi); 498 nsi = nnsi; 499 } 500 dso = machine__findnew_vdso(machine, thread); 501 } else { 502 dso = machine__findnew_dso_id(machine, filename, id); 503 } 504 505 if (dso) { 506 mutex_lock(dso__lock(dso)); 507 dso__set_nsinfo(dso, nsi); 508 mutex_unlock(dso__lock(dso)); 509 } else 510 nsinfo__put(nsi); 511 512 thread__put(thread); 513 return dso; 514 } 515 516 /* 517 * The evsel used for the sample ID for mmap events. Typically stashed when 518 * processing mmap events. If not stashed, search the evlist for the first mmap 519 * gathering event. 520 */ 521 static struct evsel *inject__mmap_evsel(struct perf_inject *inject) 522 { 523 struct evsel *pos; 524 525 if (inject->mmap_evsel) 526 return inject->mmap_evsel; 527 528 evlist__for_each_entry(inject->session->evlist, pos) { 529 if (pos->core.attr.mmap) { 530 inject->mmap_evsel = pos; 531 return pos; 532 } 533 } 534 pr_err("No mmap events found\n"); 535 return NULL; 536 } 537 538 static int perf_event__repipe_common_mmap(const struct perf_tool *tool, 539 union perf_event *event, 540 struct perf_sample *sample, 541 struct machine *machine, 542 __u32 pid, __u32 tid, 543 __u64 start, __u64 len, __u64 pgoff, 544 __u32 flags, __u32 prot, 545 const char *filename, 546 const struct dso_id *dso_id, 547 int (*perf_event_process)(const struct perf_tool *tool, 548 union perf_event *event, 549 struct perf_sample *sample, 550 struct machine *machine)) 551 { 552 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 553 struct dso *dso = NULL; 554 bool dso_sought = false; 555 556 #ifdef HAVE_JITDUMP 557 if (inject->jit_mode) { 558 u64 n = 0; 559 int ret; 560 561 /* If jit marker, then inject jit mmaps and generate ELF images. */ 562 ret = jit_process(inject->session, &inject->output, machine, 563 filename, pid, tid, &n); 564 if (ret < 0) 565 return ret; 566 if (ret) { 567 inject->bytes_written += n; 568 return 0; 569 } 570 } 571 #endif 572 if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) { 573 dso = findnew_dso(pid, tid, filename, dso_id, machine); 574 dso_sought = true; 575 if (dso) { 576 /* mark it not to inject build-id */ 577 dso__set_hit(dso); 578 } 579 } 580 if (inject->build_id_style == BID_RWS__INJECT_HEADER_ALL) { 581 if (!dso_sought) { 582 dso = findnew_dso(pid, tid, filename, dso_id, machine); 583 dso_sought = true; 584 } 585 586 if (dso && !dso__hit(dso)) { 587 struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event); 588 589 if (evsel) { 590 dso__set_hit(dso); 591 tool__inject_build_id(tool, sample, machine, evsel, 592 /*misc=*/sample->cpumode, 593 filename, dso, flags); 594 } 595 } 596 } else { 597 int err; 598 599 /* 600 * Remember the evsel for lazy build id generation. It is used 601 * for the sample id header type. 602 */ 603 if ((inject->build_id_style == BID_RWS__INJECT_HEADER_LAZY || 604 inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) && 605 !inject->mmap_evsel) 606 inject->mmap_evsel = evlist__event2evsel(inject->session->evlist, event); 607 608 /* Create the thread, map, etc. Not done for the unordered inject all case. */ 609 err = perf_event_process(tool, event, sample, machine); 610 611 if (err) { 612 dso__put(dso); 613 return err; 614 } 615 } 616 if ((inject->build_id_style == BID_RWS__MMAP2_BUILDID_ALL) && 617 !(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) { 618 struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event); 619 620 if (evsel && !dso_sought) { 621 dso = findnew_dso(pid, tid, filename, dso_id, machine); 622 dso_sought = true; 623 } 624 if (evsel && dso && 625 !tool__inject_mmap2_build_id(tool, sample, machine, evsel, 626 sample->cpumode | PERF_RECORD_MISC_MMAP_BUILD_ID, 627 pid, tid, start, len, pgoff, 628 dso, 629 prot, flags, 630 filename)) { 631 /* Injected mmap2 so no need to repipe. */ 632 dso__put(dso); 633 return 0; 634 } 635 } 636 dso__put(dso); 637 if (inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) 638 return 0; 639 640 return perf_event__repipe(tool, event, sample, machine); 641 } 642 643 static int perf_event__repipe_mmap(const struct perf_tool *tool, 644 union perf_event *event, 645 struct perf_sample *sample, 646 struct machine *machine) 647 { 648 return perf_event__repipe_common_mmap( 649 tool, event, sample, machine, 650 event->mmap.pid, event->mmap.tid, 651 event->mmap.start, event->mmap.len, event->mmap.pgoff, 652 /*flags=*/0, PROT_EXEC, 653 event->mmap.filename, /*dso_id=*/NULL, 654 perf_event__process_mmap); 655 } 656 657 static int perf_event__repipe_mmap2(const struct perf_tool *tool, 658 union perf_event *event, 659 struct perf_sample *sample, 660 struct machine *machine) 661 { 662 struct dso_id id = dso_id_empty; 663 664 if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) { 665 build_id__init(&id.build_id, event->mmap2.build_id, event->mmap2.build_id_size); 666 } else { 667 id.maj = event->mmap2.maj; 668 id.min = event->mmap2.min; 669 id.ino = event->mmap2.ino; 670 id.ino_generation = event->mmap2.ino_generation; 671 id.mmap2_valid = true; 672 id.mmap2_ino_generation_valid = true; 673 } 674 675 return perf_event__repipe_common_mmap( 676 tool, event, sample, machine, 677 event->mmap2.pid, event->mmap2.tid, 678 event->mmap2.start, event->mmap2.len, event->mmap2.pgoff, 679 event->mmap2.flags, event->mmap2.prot, 680 event->mmap2.filename, &id, 681 perf_event__process_mmap2); 682 } 683 684 static int perf_event__repipe_fork(const struct perf_tool *tool, 685 union perf_event *event, 686 struct perf_sample *sample, 687 struct machine *machine) 688 { 689 int err; 690 691 err = perf_event__process_fork(tool, event, sample, machine); 692 perf_event__repipe(tool, event, sample, machine); 693 694 return err; 695 } 696 697 static int perf_event__repipe_comm(const struct perf_tool *tool, 698 union perf_event *event, 699 struct perf_sample *sample, 700 struct machine *machine) 701 { 702 int err; 703 704 err = perf_event__process_comm(tool, event, sample, machine); 705 perf_event__repipe(tool, event, sample, machine); 706 707 return err; 708 } 709 710 static int perf_event__repipe_namespaces(const struct perf_tool *tool, 711 union perf_event *event, 712 struct perf_sample *sample, 713 struct machine *machine) 714 { 715 int err = perf_event__process_namespaces(tool, event, sample, machine); 716 717 perf_event__repipe(tool, event, sample, machine); 718 719 return err; 720 } 721 722 static int perf_event__repipe_exit(const struct perf_tool *tool, 723 union perf_event *event, 724 struct perf_sample *sample, 725 struct machine *machine) 726 { 727 int err; 728 729 err = perf_event__process_exit(tool, event, sample, machine); 730 perf_event__repipe(tool, event, sample, machine); 731 732 return err; 733 } 734 735 #ifdef HAVE_LIBTRACEEVENT 736 static int perf_event__repipe_tracing_data(const struct perf_tool *tool, 737 struct perf_session *session, 738 union perf_event *event) 739 { 740 perf_event__repipe_synth(tool, event); 741 742 return perf_event__process_tracing_data(tool, session, event); 743 } 744 #endif 745 746 static int dso__read_build_id(struct dso *dso) 747 { 748 struct nscookie nsc; 749 struct build_id bid = { .size = 0, }; 750 751 if (dso__has_build_id(dso)) 752 return 0; 753 754 mutex_lock(dso__lock(dso)); 755 nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 756 if (filename__read_build_id(dso__long_name(dso), &bid) > 0) 757 dso__set_build_id(dso, &bid); 758 else if (dso__nsinfo(dso)) { 759 char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); 760 761 if (new_name && filename__read_build_id(new_name, &bid) > 0) 762 dso__set_build_id(dso, &bid); 763 free(new_name); 764 } 765 nsinfo__mountns_exit(&nsc); 766 mutex_unlock(dso__lock(dso)); 767 768 return dso__has_build_id(dso) ? 0 : -1; 769 } 770 771 static struct strlist *perf_inject__parse_known_build_ids( 772 const char *known_build_ids_string) 773 { 774 struct str_node *pos, *tmp; 775 struct strlist *known_build_ids; 776 int bid_len; 777 778 known_build_ids = strlist__new(known_build_ids_string, NULL); 779 if (known_build_ids == NULL) 780 return NULL; 781 strlist__for_each_entry_safe(pos, tmp, known_build_ids) { 782 const char *build_id, *dso_name; 783 784 build_id = skip_spaces(pos->s); 785 dso_name = strchr(build_id, ' '); 786 if (dso_name == NULL) { 787 strlist__remove(known_build_ids, pos); 788 continue; 789 } 790 bid_len = dso_name - pos->s; 791 dso_name = skip_spaces(dso_name); 792 if (bid_len % 2 != 0 || bid_len >= SBUILD_ID_SIZE) { 793 strlist__remove(known_build_ids, pos); 794 continue; 795 } 796 for (int ix = 0; 2 * ix + 1 < bid_len; ++ix) { 797 if (!isxdigit(build_id[2 * ix]) || 798 !isxdigit(build_id[2 * ix + 1])) { 799 strlist__remove(known_build_ids, pos); 800 break; 801 } 802 } 803 } 804 return known_build_ids; 805 } 806 807 static bool perf_inject__lookup_known_build_id(struct perf_inject *inject, 808 struct dso *dso) 809 { 810 struct str_node *pos; 811 812 strlist__for_each_entry(pos, inject->known_build_ids) { 813 struct build_id bid; 814 const char *build_id, *dso_name; 815 size_t bid_len; 816 817 build_id = skip_spaces(pos->s); 818 dso_name = strchr(build_id, ' '); 819 bid_len = dso_name - pos->s; 820 if (bid_len > sizeof(bid.data)) 821 bid_len = sizeof(bid.data); 822 dso_name = skip_spaces(dso_name); 823 if (strcmp(dso__long_name(dso), dso_name)) 824 continue; 825 for (size_t ix = 0; 2 * ix + 1 < bid_len; ++ix) { 826 bid.data[ix] = (hex(build_id[2 * ix]) << 4 | 827 hex(build_id[2 * ix + 1])); 828 } 829 bid.size = bid_len / 2; 830 dso__set_build_id(dso, &bid); 831 return true; 832 } 833 return false; 834 } 835 836 static int tool__inject_build_id(const struct perf_tool *tool, 837 struct perf_sample *sample, 838 struct machine *machine, 839 const struct evsel *evsel, 840 __u16 misc, 841 const char *filename, 842 struct dso *dso, u32 flags) 843 { 844 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 845 int err; 846 847 if (is_anon_memory(filename) || flags & MAP_HUGETLB) 848 return 0; 849 if (is_no_dso_memory(filename)) 850 return 0; 851 852 if (inject->known_build_ids != NULL && 853 perf_inject__lookup_known_build_id(inject, dso)) 854 return 1; 855 856 if (dso__read_build_id(dso) < 0) { 857 pr_debug("no build_id found for %s\n", filename); 858 return -1; 859 } 860 861 err = perf_event__synthesize_build_id(tool, sample, machine, 862 perf_event__repipe, 863 evsel, misc, dso__bid(dso), 864 filename); 865 if (err) { 866 pr_err("Can't synthesize build_id event for %s\n", filename); 867 return -1; 868 } 869 870 return 0; 871 } 872 873 static int tool__inject_mmap2_build_id(const struct perf_tool *tool, 874 struct perf_sample *sample, 875 struct machine *machine, 876 const struct evsel *evsel, 877 __u16 misc, 878 __u32 pid, __u32 tid, 879 __u64 start, __u64 len, __u64 pgoff, 880 struct dso *dso, 881 __u32 prot, __u32 flags, 882 const char *filename) 883 { 884 int err; 885 886 /* Return to repipe anonymous maps. */ 887 if (is_anon_memory(filename) || flags & MAP_HUGETLB) 888 return 1; 889 if (is_no_dso_memory(filename)) 890 return 1; 891 892 if (dso__read_build_id(dso)) { 893 pr_debug("no build_id found for %s\n", filename); 894 return -1; 895 } 896 897 err = perf_event__synthesize_mmap2_build_id(tool, sample, machine, 898 perf_event__repipe, 899 evsel, 900 misc, pid, tid, 901 start, len, pgoff, 902 dso__bid(dso), 903 prot, flags, 904 filename); 905 if (err) { 906 pr_err("Can't synthesize build_id event for %s\n", filename); 907 return -1; 908 } 909 return 0; 910 } 911 912 static int mark_dso_hit(const struct perf_inject *inject, 913 const struct perf_tool *tool, 914 struct perf_sample *sample, 915 struct machine *machine, 916 const struct evsel *mmap_evsel, 917 struct map *map, bool sample_in_dso) 918 { 919 struct dso *dso; 920 u16 misc = sample->cpumode; 921 922 if (!map) 923 return 0; 924 925 if (!sample_in_dso) { 926 u16 guest_mask = PERF_RECORD_MISC_GUEST_KERNEL | 927 PERF_RECORD_MISC_GUEST_USER; 928 929 if ((misc & guest_mask) != 0) { 930 misc &= PERF_RECORD_MISC_HYPERVISOR; 931 misc |= __map__is_kernel(map) 932 ? PERF_RECORD_MISC_GUEST_KERNEL 933 : PERF_RECORD_MISC_GUEST_USER; 934 } else { 935 misc &= PERF_RECORD_MISC_HYPERVISOR; 936 misc |= __map__is_kernel(map) 937 ? PERF_RECORD_MISC_KERNEL 938 : PERF_RECORD_MISC_USER; 939 } 940 } 941 dso = map__dso(map); 942 if (inject->build_id_style == BID_RWS__INJECT_HEADER_LAZY) { 943 if (dso && !dso__hit(dso)) { 944 dso__set_hit(dso); 945 tool__inject_build_id(tool, sample, machine, 946 mmap_evsel, misc, dso__long_name(dso), dso, 947 map__flags(map)); 948 } 949 } else if (inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) { 950 if (!map__hit(map)) { 951 const struct build_id null_bid = { .size = 0 }; 952 const struct build_id *bid = dso ? dso__bid(dso) : &null_bid; 953 const char *filename = dso ? dso__long_name(dso) : ""; 954 955 map__set_hit(map); 956 perf_event__synthesize_mmap2_build_id(tool, sample, machine, 957 perf_event__repipe, 958 mmap_evsel, 959 misc, 960 sample->pid, sample->tid, 961 map__start(map), 962 map__end(map) - map__start(map), 963 map__pgoff(map), 964 bid, 965 map__prot(map), 966 map__flags(map), 967 filename); 968 } 969 } 970 return 0; 971 } 972 973 struct mark_dso_hit_args { 974 const struct perf_inject *inject; 975 const struct perf_tool *tool; 976 struct perf_sample *sample; 977 struct machine *machine; 978 const struct evsel *mmap_evsel; 979 }; 980 981 static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data) 982 { 983 struct mark_dso_hit_args *args = data; 984 struct map *map = node->ms.map; 985 986 return mark_dso_hit(args->inject, args->tool, args->sample, args->machine, 987 args->mmap_evsel, map, /*sample_in_dso=*/false); 988 } 989 990 int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *event, 991 struct perf_sample *sample, 992 struct evsel *evsel __maybe_unused, 993 struct machine *machine) 994 { 995 struct addr_location al; 996 struct thread *thread; 997 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 998 struct mark_dso_hit_args args = { 999 .inject = inject, 1000 .tool = tool, 1001 /* 1002 * Use the parsed sample data of the sample event, which will 1003 * have a later timestamp than the mmap event. 1004 */ 1005 .sample = sample, 1006 .machine = machine, 1007 .mmap_evsel = inject__mmap_evsel(inject), 1008 }; 1009 1010 addr_location__init(&al); 1011 thread = machine__findnew_thread(machine, sample->pid, sample->tid); 1012 if (thread == NULL) { 1013 pr_err("problem processing %d event, skipping it.\n", 1014 event->header.type); 1015 goto repipe; 1016 } 1017 1018 if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) { 1019 mark_dso_hit(inject, tool, sample, machine, args.mmap_evsel, al.map, 1020 /*sample_in_dso=*/true); 1021 } 1022 1023 sample__for_each_callchain_node(thread, evsel, sample, PERF_MAX_STACK_DEPTH, 1024 /*symbols=*/false, mark_dso_hit_callback, &args); 1025 thread__put(thread); 1026 repipe: 1027 perf_event__repipe(tool, event, sample, machine); 1028 addr_location__exit(&al); 1029 return 0; 1030 } 1031 1032 static int perf_inject__sched_process_exit(const struct perf_tool *tool, 1033 union perf_event *event __maybe_unused, 1034 struct perf_sample *sample, 1035 struct evsel *evsel __maybe_unused, 1036 struct machine *machine __maybe_unused) 1037 { 1038 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1039 struct event_entry *ent; 1040 1041 list_for_each_entry(ent, &inject->samples, node) { 1042 if (sample->tid == ent->tid) { 1043 list_del_init(&ent->node); 1044 free(ent); 1045 break; 1046 } 1047 } 1048 1049 return 0; 1050 } 1051 1052 static int perf_inject__sched_switch(const struct perf_tool *tool, 1053 union perf_event *event, 1054 struct perf_sample *sample, 1055 struct evsel *evsel, 1056 struct machine *machine) 1057 { 1058 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1059 struct event_entry *ent; 1060 1061 perf_inject__sched_process_exit(tool, event, sample, evsel, machine); 1062 1063 ent = malloc(event->header.size + sizeof(struct event_entry)); 1064 if (ent == NULL) { 1065 color_fprintf(stderr, PERF_COLOR_RED, 1066 "Not enough memory to process sched switch event!"); 1067 return -1; 1068 } 1069 1070 ent->tid = sample->tid; 1071 memcpy(&ent->event, event, event->header.size); 1072 list_add(&ent->node, &inject->samples); 1073 return 0; 1074 } 1075 1076 #ifdef HAVE_LIBTRACEEVENT 1077 static int perf_inject__sched_stat(const struct perf_tool *tool, 1078 union perf_event *event __maybe_unused, 1079 struct perf_sample *sample, 1080 struct evsel *evsel, 1081 struct machine *machine) 1082 { 1083 struct event_entry *ent; 1084 union perf_event *event_sw; 1085 struct perf_sample sample_sw; 1086 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1087 u32 pid = evsel__intval(evsel, sample, "pid"); 1088 int ret; 1089 1090 list_for_each_entry(ent, &inject->samples, node) { 1091 if (pid == ent->tid) 1092 goto found; 1093 } 1094 1095 return 0; 1096 found: 1097 event_sw = &ent->event[0]; 1098 evsel__parse_sample(evsel, event_sw, &sample_sw); 1099 1100 sample_sw.period = sample->period; 1101 sample_sw.time = sample->time; 1102 perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type, 1103 evsel->core.attr.read_format, &sample_sw); 1104 build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); 1105 ret = perf_event__repipe(tool, event_sw, &sample_sw, machine); 1106 perf_sample__exit(&sample_sw); 1107 return ret; 1108 } 1109 #endif 1110 1111 static struct guest_vcpu *guest_session__vcpu(struct guest_session *gs, u32 vcpu) 1112 { 1113 if (realloc_array_as_needed(gs->vcpu, gs->vcpu_cnt, vcpu, NULL)) 1114 return NULL; 1115 return &gs->vcpu[vcpu]; 1116 } 1117 1118 static int guest_session__output_bytes(struct guest_session *gs, void *buf, size_t sz) 1119 { 1120 ssize_t ret = writen(gs->tmp_fd, buf, sz); 1121 1122 return ret < 0 ? ret : 0; 1123 } 1124 1125 static int guest_session__repipe(const struct perf_tool *tool, 1126 union perf_event *event, 1127 struct perf_sample *sample __maybe_unused, 1128 struct machine *machine __maybe_unused) 1129 { 1130 struct guest_session *gs = container_of(tool, struct guest_session, tool); 1131 1132 return guest_session__output_bytes(gs, event, event->header.size); 1133 } 1134 1135 static int guest_session__map_tid(struct guest_session *gs, u32 tid, u32 vcpu) 1136 { 1137 struct guest_tid *guest_tid = zalloc(sizeof(*guest_tid)); 1138 int hash; 1139 1140 if (!guest_tid) 1141 return -ENOMEM; 1142 1143 guest_tid->tid = tid; 1144 guest_tid->vcpu = vcpu; 1145 hash = hash_32(guest_tid->tid, PERF_EVLIST__HLIST_BITS); 1146 hlist_add_head(&guest_tid->node, &gs->tids[hash]); 1147 1148 return 0; 1149 } 1150 1151 static int host_peek_vm_comms_cb(struct perf_session *session __maybe_unused, 1152 union perf_event *event, 1153 u64 offset __maybe_unused, void *data) 1154 { 1155 struct guest_session *gs = data; 1156 unsigned int vcpu; 1157 struct guest_vcpu *guest_vcpu; 1158 int ret; 1159 1160 if (event->header.type != PERF_RECORD_COMM || 1161 event->comm.pid != gs->machine_pid) 1162 return 0; 1163 1164 /* 1165 * QEMU option -name debug-threads=on, causes thread names formatted as 1166 * below, although it is not an ABI. Also libvirt seems to use this by 1167 * default. Here we rely on it to tell us which thread is which VCPU. 1168 */ 1169 ret = sscanf(event->comm.comm, "CPU %u/KVM", &vcpu); 1170 if (ret <= 0) 1171 return ret; 1172 pr_debug("Found VCPU: tid %u comm %s vcpu %u\n", 1173 event->comm.tid, event->comm.comm, vcpu); 1174 if (vcpu > INT_MAX) { 1175 pr_err("Invalid VCPU %u\n", vcpu); 1176 return -EINVAL; 1177 } 1178 guest_vcpu = guest_session__vcpu(gs, vcpu); 1179 if (!guest_vcpu) 1180 return -ENOMEM; 1181 if (guest_vcpu->tid && guest_vcpu->tid != event->comm.tid) { 1182 pr_err("Fatal error: Two threads found with the same VCPU\n"); 1183 return -EINVAL; 1184 } 1185 guest_vcpu->tid = event->comm.tid; 1186 1187 return guest_session__map_tid(gs, event->comm.tid, vcpu); 1188 } 1189 1190 static int host_peek_vm_comms(struct perf_session *session, struct guest_session *gs) 1191 { 1192 return perf_session__peek_events(session, session->header.data_offset, 1193 session->header.data_size, 1194 host_peek_vm_comms_cb, gs); 1195 } 1196 1197 static bool evlist__is_id_used(struct evlist *evlist, u64 id) 1198 { 1199 return evlist__id2sid(evlist, id); 1200 } 1201 1202 static u64 guest_session__allocate_new_id(struct guest_session *gs, struct evlist *host_evlist) 1203 { 1204 do { 1205 gs->highest_id += 1; 1206 } while (!gs->highest_id || evlist__is_id_used(host_evlist, gs->highest_id)); 1207 1208 return gs->highest_id; 1209 } 1210 1211 static int guest_session__map_id(struct guest_session *gs, u64 id, u64 host_id, u32 vcpu) 1212 { 1213 struct guest_id *guest_id = zalloc(sizeof(*guest_id)); 1214 int hash; 1215 1216 if (!guest_id) 1217 return -ENOMEM; 1218 1219 guest_id->id = id; 1220 guest_id->host_id = host_id; 1221 guest_id->vcpu = vcpu; 1222 hash = hash_64(guest_id->id, PERF_EVLIST__HLIST_BITS); 1223 hlist_add_head(&guest_id->node, &gs->heads[hash]); 1224 1225 return 0; 1226 } 1227 1228 static u64 evlist__find_highest_id(struct evlist *evlist) 1229 { 1230 struct evsel *evsel; 1231 u64 highest_id = 1; 1232 1233 evlist__for_each_entry(evlist, evsel) { 1234 u32 j; 1235 1236 for (j = 0; j < evsel->core.ids; j++) { 1237 u64 id = evsel->core.id[j]; 1238 1239 if (id > highest_id) 1240 highest_id = id; 1241 } 1242 } 1243 1244 return highest_id; 1245 } 1246 1247 static int guest_session__map_ids(struct guest_session *gs, struct evlist *host_evlist) 1248 { 1249 struct evlist *evlist = gs->session->evlist; 1250 struct evsel *evsel; 1251 int ret; 1252 1253 evlist__for_each_entry(evlist, evsel) { 1254 u32 j; 1255 1256 for (j = 0; j < evsel->core.ids; j++) { 1257 struct perf_sample_id *sid; 1258 u64 host_id; 1259 u64 id; 1260 1261 id = evsel->core.id[j]; 1262 sid = evlist__id2sid(evlist, id); 1263 if (!sid || sid->cpu.cpu == -1) 1264 continue; 1265 host_id = guest_session__allocate_new_id(gs, host_evlist); 1266 ret = guest_session__map_id(gs, id, host_id, sid->cpu.cpu); 1267 if (ret) 1268 return ret; 1269 } 1270 } 1271 1272 return 0; 1273 } 1274 1275 static struct guest_id *guest_session__lookup_id(struct guest_session *gs, u64 id) 1276 { 1277 struct hlist_head *head; 1278 struct guest_id *guest_id; 1279 int hash; 1280 1281 hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 1282 head = &gs->heads[hash]; 1283 1284 hlist_for_each_entry(guest_id, head, node) 1285 if (guest_id->id == id) 1286 return guest_id; 1287 1288 return NULL; 1289 } 1290 1291 static int process_attr(const struct perf_tool *tool, union perf_event *event, 1292 struct perf_sample *sample __maybe_unused, 1293 struct machine *machine __maybe_unused) 1294 { 1295 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1296 1297 return perf_event__process_attr(tool, event, &inject->session->evlist); 1298 } 1299 1300 static int guest_session__add_attr(struct guest_session *gs, struct evsel *evsel) 1301 { 1302 struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session); 1303 struct perf_event_attr attr = evsel->core.attr; 1304 u64 *id_array; 1305 u32 *vcpu_array; 1306 int ret = -ENOMEM; 1307 u32 i; 1308 1309 id_array = calloc(evsel->core.ids, sizeof(*id_array)); 1310 if (!id_array) 1311 return -ENOMEM; 1312 1313 vcpu_array = calloc(evsel->core.ids, sizeof(*vcpu_array)); 1314 if (!vcpu_array) 1315 goto out; 1316 1317 for (i = 0; i < evsel->core.ids; i++) { 1318 u64 id = evsel->core.id[i]; 1319 struct guest_id *guest_id = guest_session__lookup_id(gs, id); 1320 1321 if (!guest_id) { 1322 pr_err("Failed to find guest id %"PRIu64"\n", id); 1323 ret = -EINVAL; 1324 goto out; 1325 } 1326 id_array[i] = guest_id->host_id; 1327 vcpu_array[i] = guest_id->vcpu; 1328 } 1329 1330 attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 1331 attr.exclude_host = 1; 1332 attr.exclude_guest = 0; 1333 1334 ret = perf_event__synthesize_attr(&inject->tool, &attr, evsel->core.ids, 1335 id_array, process_attr); 1336 if (ret) 1337 pr_err("Failed to add guest attr.\n"); 1338 1339 for (i = 0; i < evsel->core.ids; i++) { 1340 struct perf_sample_id *sid; 1341 u32 vcpu = vcpu_array[i]; 1342 1343 sid = evlist__id2sid(inject->session->evlist, id_array[i]); 1344 /* Guest event is per-thread from the host point of view */ 1345 sid->cpu.cpu = -1; 1346 sid->tid = gs->vcpu[vcpu].tid; 1347 sid->machine_pid = gs->machine_pid; 1348 sid->vcpu.cpu = vcpu; 1349 } 1350 out: 1351 free(vcpu_array); 1352 free(id_array); 1353 return ret; 1354 } 1355 1356 static int guest_session__add_attrs(struct guest_session *gs) 1357 { 1358 struct evlist *evlist = gs->session->evlist; 1359 struct evsel *evsel; 1360 int ret; 1361 1362 evlist__for_each_entry(evlist, evsel) { 1363 ret = guest_session__add_attr(gs, evsel); 1364 if (ret) 1365 return ret; 1366 } 1367 1368 return 0; 1369 } 1370 1371 static int synthesize_id_index(struct perf_inject *inject, size_t new_cnt) 1372 { 1373 struct perf_session *session = inject->session; 1374 struct evlist *evlist = session->evlist; 1375 struct machine *machine = &session->machines.host; 1376 size_t from = evlist->core.nr_entries - new_cnt; 1377 1378 return __perf_event__synthesize_id_index(&inject->tool, perf_event__repipe, 1379 evlist, machine, from); 1380 } 1381 1382 static struct guest_tid *guest_session__lookup_tid(struct guest_session *gs, u32 tid) 1383 { 1384 struct hlist_head *head; 1385 struct guest_tid *guest_tid; 1386 int hash; 1387 1388 hash = hash_32(tid, PERF_EVLIST__HLIST_BITS); 1389 head = &gs->tids[hash]; 1390 1391 hlist_for_each_entry(guest_tid, head, node) 1392 if (guest_tid->tid == tid) 1393 return guest_tid; 1394 1395 return NULL; 1396 } 1397 1398 static bool dso__is_in_kernel_space(struct dso *dso) 1399 { 1400 if (dso__is_vdso(dso)) 1401 return false; 1402 1403 return dso__is_kcore(dso) || 1404 dso__kernel(dso) || 1405 is_kernel_module(dso__long_name(dso), PERF_RECORD_MISC_CPUMODE_UNKNOWN); 1406 } 1407 1408 static u64 evlist__first_id(struct evlist *evlist) 1409 { 1410 struct evsel *evsel; 1411 1412 evlist__for_each_entry(evlist, evsel) { 1413 if (evsel->core.ids) 1414 return evsel->core.id[0]; 1415 } 1416 return 0; 1417 } 1418 1419 static int process_build_id(const struct perf_tool *tool, 1420 union perf_event *event, 1421 struct perf_sample *sample __maybe_unused, 1422 struct machine *machine __maybe_unused) 1423 { 1424 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1425 1426 return perf_event__process_build_id(tool, inject->session, event); 1427 } 1428 1429 static int synthesize_build_id(struct perf_inject *inject, struct dso *dso, pid_t machine_pid) 1430 { 1431 struct machine *machine = perf_session__findnew_machine(inject->session, machine_pid); 1432 struct perf_sample synth_sample = { 1433 .evsel = inject__mmap_evsel(inject), 1434 .pid = -1, 1435 .tid = -1, 1436 .time = -1, 1437 .stream_id = -1, 1438 .cpu = -1, 1439 .period = 1, 1440 .cpumode = dso__is_in_kernel_space(dso) 1441 ? PERF_RECORD_MISC_GUEST_KERNEL 1442 : PERF_RECORD_MISC_GUEST_USER, 1443 }; 1444 1445 if (!machine) 1446 return -ENOMEM; 1447 1448 dso__set_hit(dso); 1449 1450 return perf_event__synthesize_build_id(&inject->tool, &synth_sample, machine, 1451 process_build_id, inject__mmap_evsel(inject), 1452 /*misc=*/synth_sample.cpumode, 1453 dso__bid(dso), dso__long_name(dso)); 1454 } 1455 1456 static int guest_session__add_build_ids_cb(struct dso *dso, void *data) 1457 { 1458 struct guest_session *gs = data; 1459 struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session); 1460 1461 if (!dso__has_build_id(dso)) 1462 return 0; 1463 1464 return synthesize_build_id(inject, dso, gs->machine_pid); 1465 1466 } 1467 1468 static int guest_session__add_build_ids(struct guest_session *gs) 1469 { 1470 struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session); 1471 1472 /* Build IDs will be put in the Build ID feature section */ 1473 perf_header__set_feat(&inject->session->header, HEADER_BUILD_ID); 1474 1475 return dsos__for_each_dso(&gs->session->machines.host.dsos, 1476 guest_session__add_build_ids_cb, 1477 gs); 1478 } 1479 1480 static int guest_session__ksymbol_event(const struct perf_tool *tool, 1481 union perf_event *event, 1482 struct perf_sample *sample __maybe_unused, 1483 struct machine *machine __maybe_unused) 1484 { 1485 struct guest_session *gs = container_of(tool, struct guest_session, tool); 1486 1487 /* Only support out-of-line i.e. no BPF support */ 1488 if (event->ksymbol.ksym_type != PERF_RECORD_KSYMBOL_TYPE_OOL) 1489 return 0; 1490 1491 return guest_session__output_bytes(gs, event, event->header.size); 1492 } 1493 1494 static int guest_session__start(struct guest_session *gs, const char *name, bool force) 1495 { 1496 char tmp_file_name[] = "/tmp/perf-inject-guest_session-XXXXXX"; 1497 struct perf_session *session; 1498 int ret; 1499 1500 /* Only these events will be injected */ 1501 gs->tool.mmap = guest_session__repipe; 1502 gs->tool.mmap2 = guest_session__repipe; 1503 gs->tool.comm = guest_session__repipe; 1504 gs->tool.fork = guest_session__repipe; 1505 gs->tool.exit = guest_session__repipe; 1506 gs->tool.lost = guest_session__repipe; 1507 gs->tool.context_switch = guest_session__repipe; 1508 gs->tool.ksymbol = guest_session__ksymbol_event; 1509 gs->tool.text_poke = guest_session__repipe; 1510 /* 1511 * Processing a build ID creates a struct dso with that build ID. Later, 1512 * all guest dsos are iterated and the build IDs processed into the host 1513 * session where they will be output to the Build ID feature section 1514 * when the perf.data file header is written. 1515 */ 1516 gs->tool.build_id = perf_event__process_build_id; 1517 /* Process the id index to know what VCPU an ID belongs to */ 1518 gs->tool.id_index = perf_event__process_id_index; 1519 1520 gs->tool.ordered_events = true; 1521 gs->tool.ordering_requires_timestamps = true; 1522 1523 gs->data.path = name; 1524 gs->data.force = force; 1525 gs->data.mode = PERF_DATA_MODE_READ; 1526 1527 session = perf_session__new(&gs->data, &gs->tool); 1528 if (IS_ERR(session)) 1529 return PTR_ERR(session); 1530 gs->session = session; 1531 1532 /* 1533 * Initial events have zero'd ID samples. Get default ID sample size 1534 * used for removing them. 1535 */ 1536 gs->dflt_id_hdr_size = session->machines.host.id_hdr_size; 1537 /* And default ID for adding back a host-compatible ID sample */ 1538 gs->dflt_id = evlist__first_id(session->evlist); 1539 if (!gs->dflt_id) { 1540 pr_err("Guest data has no sample IDs"); 1541 return -EINVAL; 1542 } 1543 1544 /* Temporary file for guest events */ 1545 gs->tmp_file_name = strdup(tmp_file_name); 1546 if (!gs->tmp_file_name) 1547 return -ENOMEM; 1548 gs->tmp_fd = mkstemp(gs->tmp_file_name); 1549 if (gs->tmp_fd < 0) 1550 return -errno; 1551 1552 if (zstd_init(&gs->session->zstd_data, 0) < 0) 1553 pr_warning("Guest session decompression initialization failed.\n"); 1554 1555 /* 1556 * perf does not support processing 2 sessions simultaneously, so output 1557 * guest events to a temporary file. 1558 */ 1559 ret = perf_session__process_events(gs->session); 1560 if (ret) 1561 return ret; 1562 1563 if (lseek(gs->tmp_fd, 0, SEEK_SET)) 1564 return -errno; 1565 1566 return 0; 1567 } 1568 1569 /* Free hlist nodes assuming hlist_node is the first member of hlist entries */ 1570 static void free_hlist(struct hlist_head *heads, size_t hlist_sz) 1571 { 1572 struct hlist_node *pos, *n; 1573 size_t i; 1574 1575 for (i = 0; i < hlist_sz; ++i) { 1576 hlist_for_each_safe(pos, n, &heads[i]) { 1577 hlist_del(pos); 1578 free(pos); 1579 } 1580 } 1581 } 1582 1583 static void guest_session__exit(struct guest_session *gs) 1584 { 1585 if (gs->session) { 1586 perf_session__delete(gs->session); 1587 free_hlist(gs->heads, PERF_EVLIST__HLIST_SIZE); 1588 free_hlist(gs->tids, PERF_EVLIST__HLIST_SIZE); 1589 } 1590 if (gs->tmp_file_name) { 1591 if (gs->tmp_fd >= 0) 1592 close(gs->tmp_fd); 1593 unlink(gs->tmp_file_name); 1594 zfree(&gs->tmp_file_name); 1595 } 1596 zfree(&gs->vcpu); 1597 zfree(&gs->perf_data_file); 1598 } 1599 1600 static void get_tsc_conv(struct perf_tsc_conversion *tc, struct perf_record_time_conv *time_conv) 1601 { 1602 tc->time_shift = time_conv->time_shift; 1603 tc->time_mult = time_conv->time_mult; 1604 tc->time_zero = time_conv->time_zero; 1605 tc->time_cycles = time_conv->time_cycles; 1606 tc->time_mask = time_conv->time_mask; 1607 tc->cap_user_time_zero = time_conv->cap_user_time_zero; 1608 tc->cap_user_time_short = time_conv->cap_user_time_short; 1609 } 1610 1611 static void guest_session__get_tc(struct guest_session *gs) 1612 { 1613 struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session); 1614 1615 get_tsc_conv(&gs->host_tc, &inject->session->time_conv); 1616 get_tsc_conv(&gs->guest_tc, &gs->session->time_conv); 1617 } 1618 1619 static void guest_session__convert_time(struct guest_session *gs, u64 guest_time, u64 *host_time) 1620 { 1621 u64 tsc; 1622 1623 if (!guest_time) { 1624 *host_time = 0; 1625 return; 1626 } 1627 1628 if (gs->guest_tc.cap_user_time_zero) 1629 tsc = perf_time_to_tsc(guest_time, &gs->guest_tc); 1630 else 1631 tsc = guest_time; 1632 1633 /* 1634 * This is the correct order of operations for x86 if the TSC Offset and 1635 * Multiplier values are used. 1636 */ 1637 tsc -= gs->time_offset; 1638 tsc /= gs->time_scale; 1639 1640 if (gs->host_tc.cap_user_time_zero) 1641 *host_time = tsc_to_perf_time(tsc, &gs->host_tc); 1642 else 1643 *host_time = tsc; 1644 } 1645 1646 static int guest_session__fetch(struct guest_session *gs) 1647 { 1648 void *buf; 1649 struct perf_event_header *hdr; 1650 size_t hdr_sz = sizeof(*hdr); 1651 ssize_t ret; 1652 1653 perf_sample__init(&gs->ev.sample, /*all=*/false); 1654 buf = gs->ev.event_buf; 1655 if (!buf) { 1656 buf = malloc(PERF_SAMPLE_MAX_SIZE); 1657 if (!buf) 1658 return -ENOMEM; 1659 gs->ev.event_buf = buf; 1660 } 1661 hdr = buf; 1662 ret = readn(gs->tmp_fd, buf, hdr_sz); 1663 if (ret < 0) 1664 return ret; 1665 1666 if (!ret) { 1667 /* Zero size means EOF */ 1668 hdr->size = 0; 1669 return 0; 1670 } 1671 1672 buf += hdr_sz; 1673 1674 ret = readn(gs->tmp_fd, buf, hdr->size - hdr_sz); 1675 if (ret < 0) 1676 return ret; 1677 1678 gs->ev.event = (union perf_event *)gs->ev.event_buf; 1679 gs->ev.sample.time = 0; 1680 1681 if (hdr->type >= PERF_RECORD_USER_TYPE_START) { 1682 pr_err("Unexpected type fetching guest event"); 1683 return 0; 1684 } 1685 1686 ret = evlist__parse_sample(gs->session->evlist, gs->ev.event, &gs->ev.sample); 1687 if (ret) { 1688 pr_err("Parse failed fetching guest event"); 1689 return ret; 1690 } 1691 1692 if (!gs->have_tc) { 1693 guest_session__get_tc(gs); 1694 gs->have_tc = true; 1695 } 1696 1697 guest_session__convert_time(gs, gs->ev.sample.time, &gs->ev.sample.time); 1698 1699 return 0; 1700 } 1701 1702 static int evlist__append_id_sample(struct evlist *evlist, union perf_event *ev, 1703 const struct perf_sample *sample) 1704 { 1705 struct evsel *evsel; 1706 void *array; 1707 int ret; 1708 1709 evsel = evlist__id2evsel(evlist, sample->id); 1710 array = ev; 1711 1712 if (!evsel) { 1713 pr_err("No evsel for id %"PRIu64"\n", sample->id); 1714 return -EINVAL; 1715 } 1716 1717 array += ev->header.size; 1718 ret = perf_event__synthesize_id_sample(array, evsel->core.attr.sample_type, sample); 1719 if (ret < 0) 1720 return ret; 1721 1722 if (ret & 7) { 1723 pr_err("Bad id sample size %d\n", ret); 1724 return -EINVAL; 1725 } 1726 1727 ev->header.size += ret; 1728 1729 return 0; 1730 } 1731 1732 static int guest_session__inject_events(struct guest_session *gs, u64 timestamp) 1733 { 1734 struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session); 1735 int ret; 1736 1737 if (!gs->ready) 1738 return 0; 1739 1740 while (1) { 1741 struct perf_sample *sample; 1742 struct guest_id *guest_id; 1743 union perf_event *ev; 1744 u16 id_hdr_size; 1745 u8 cpumode; 1746 u64 id; 1747 1748 if (!gs->fetched) { 1749 ret = guest_session__fetch(gs); 1750 if (ret) 1751 break; 1752 gs->fetched = true; 1753 } 1754 1755 ev = gs->ev.event; 1756 sample = &gs->ev.sample; 1757 1758 if (!ev->header.size) { 1759 /* EOF */ 1760 perf_sample__exit(&gs->ev.sample); 1761 gs->fetched = false; 1762 ret = 0; 1763 break; 1764 } 1765 if (sample->time > timestamp) { 1766 ret = 0; 1767 break; 1768 } 1769 1770 /* Change cpumode to guest */ 1771 cpumode = ev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1772 if (cpumode & PERF_RECORD_MISC_USER) 1773 cpumode = PERF_RECORD_MISC_GUEST_USER; 1774 else 1775 cpumode = PERF_RECORD_MISC_GUEST_KERNEL; 1776 ev->header.misc &= ~PERF_RECORD_MISC_CPUMODE_MASK; 1777 ev->header.misc |= cpumode; 1778 1779 id = sample->id; 1780 if (!id) { 1781 id = gs->dflt_id; 1782 id_hdr_size = gs->dflt_id_hdr_size; 1783 } else { 1784 struct evsel *evsel = evlist__id2evsel(gs->session->evlist, id); 1785 1786 id_hdr_size = evsel__id_hdr_size(evsel); 1787 } 1788 1789 if (id_hdr_size & 7) { 1790 pr_err("Bad id_hdr_size %u\n", id_hdr_size); 1791 ret = -EINVAL; 1792 break; 1793 } 1794 1795 if (ev->header.size & 7) { 1796 pr_err("Bad event size %u\n", ev->header.size); 1797 ret = -EINVAL; 1798 break; 1799 } 1800 1801 /* Remove guest id sample */ 1802 ev->header.size -= id_hdr_size; 1803 1804 if (ev->header.size & 7) { 1805 pr_err("Bad raw event size %u\n", ev->header.size); 1806 ret = -EINVAL; 1807 break; 1808 } 1809 1810 guest_id = guest_session__lookup_id(gs, id); 1811 if (!guest_id) { 1812 pr_err("Guest event with unknown id %llu\n", 1813 (unsigned long long)id); 1814 ret = -EINVAL; 1815 break; 1816 } 1817 1818 /* Change to host ID to avoid conflicting ID values */ 1819 sample->id = guest_id->host_id; 1820 sample->stream_id = guest_id->host_id; 1821 1822 if (sample->cpu != (u32)-1) { 1823 if (sample->cpu >= gs->vcpu_cnt) { 1824 pr_err("Guest event with unknown VCPU %u\n", 1825 sample->cpu); 1826 return -EINVAL; 1827 } 1828 /* Change to host CPU instead of guest VCPU */ 1829 sample->cpu = gs->vcpu[sample->cpu].cpu; 1830 } 1831 1832 /* New id sample with new ID and CPU */ 1833 ret = evlist__append_id_sample(inject->session->evlist, ev, sample); 1834 if (ret) 1835 break; 1836 1837 if (ev->header.size & 7) { 1838 pr_err("Bad new event size %u\n", ev->header.size); 1839 ret = -EINVAL; 1840 break; 1841 } 1842 1843 ret = output_bytes(inject, ev, ev->header.size); 1844 if (ret) 1845 break; 1846 1847 /* Reset for next guest session event fetch. */ 1848 perf_sample__exit(sample); 1849 gs->fetched = false; 1850 } 1851 if (ret && gs->fetched) { 1852 /* Clear saved sample state on error. */ 1853 perf_sample__exit(&gs->ev.sample); 1854 gs->fetched = false; 1855 } 1856 return ret; 1857 } 1858 1859 static int guest_session__flush_events(struct guest_session *gs) 1860 { 1861 return guest_session__inject_events(gs, -1); 1862 } 1863 1864 static int host__repipe(const struct perf_tool *tool, 1865 union perf_event *event, 1866 struct perf_sample *sample, 1867 struct machine *machine) 1868 { 1869 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1870 int ret; 1871 1872 ret = guest_session__inject_events(&inject->guest_session, sample->time); 1873 if (ret) 1874 return ret; 1875 1876 return perf_event__repipe(tool, event, sample, machine); 1877 } 1878 1879 static int host__finished_init(const struct perf_tool *tool, struct perf_session *session, 1880 union perf_event *event) 1881 { 1882 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1883 struct guest_session *gs = &inject->guest_session; 1884 int ret; 1885 1886 /* 1887 * Peek through host COMM events to find QEMU threads and the VCPU they 1888 * are running. 1889 */ 1890 ret = host_peek_vm_comms(session, gs); 1891 if (ret) 1892 return ret; 1893 1894 if (!gs->vcpu_cnt) { 1895 pr_err("No VCPU threads found for pid %u\n", gs->machine_pid); 1896 return -EINVAL; 1897 } 1898 1899 /* 1900 * Allocate new (unused) host sample IDs and map them to the guest IDs. 1901 */ 1902 gs->highest_id = evlist__find_highest_id(session->evlist); 1903 ret = guest_session__map_ids(gs, session->evlist); 1904 if (ret) 1905 return ret; 1906 1907 ret = guest_session__add_attrs(gs); 1908 if (ret) 1909 return ret; 1910 1911 ret = synthesize_id_index(inject, gs->session->evlist->core.nr_entries); 1912 if (ret) { 1913 pr_err("Failed to synthesize id_index\n"); 1914 return ret; 1915 } 1916 1917 ret = guest_session__add_build_ids(gs); 1918 if (ret) { 1919 pr_err("Failed to add guest build IDs\n"); 1920 return ret; 1921 } 1922 1923 gs->ready = true; 1924 1925 ret = guest_session__inject_events(gs, 0); 1926 if (ret) 1927 return ret; 1928 1929 return perf_event__repipe_op2_synth(tool, session, event); 1930 } 1931 1932 /* 1933 * Obey finished-round ordering. The FINISHED_ROUND event is first processed 1934 * which flushes host events to file up until the last flush time. Then inject 1935 * guest events up to the same time. Finally write out the FINISHED_ROUND event 1936 * itself. 1937 */ 1938 static int host__finished_round(const struct perf_tool *tool, 1939 union perf_event *event, 1940 struct ordered_events *oe) 1941 { 1942 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1943 int ret = perf_event__process_finished_round(tool, event, oe); 1944 u64 timestamp = ordered_events__last_flush_time(oe); 1945 1946 if (ret) 1947 return ret; 1948 1949 ret = guest_session__inject_events(&inject->guest_session, timestamp); 1950 if (ret) 1951 return ret; 1952 1953 return perf_event__repipe_oe_synth(tool, event, oe); 1954 } 1955 1956 static int host__context_switch(const struct perf_tool *tool, 1957 union perf_event *event, 1958 struct perf_sample *sample, 1959 struct machine *machine) 1960 { 1961 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 1962 bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT; 1963 struct guest_session *gs = &inject->guest_session; 1964 u32 pid = event->context_switch.next_prev_pid; 1965 u32 tid = event->context_switch.next_prev_tid; 1966 struct guest_tid *guest_tid; 1967 u32 vcpu; 1968 1969 if (out || pid != gs->machine_pid) 1970 goto out; 1971 1972 guest_tid = guest_session__lookup_tid(gs, tid); 1973 if (!guest_tid) 1974 goto out; 1975 1976 if (sample->cpu == (u32)-1) { 1977 pr_err("Switch event does not have CPU\n"); 1978 return -EINVAL; 1979 } 1980 1981 vcpu = guest_tid->vcpu; 1982 if (vcpu >= gs->vcpu_cnt) 1983 return -EINVAL; 1984 1985 /* Guest is switching in, record which CPU the VCPU is now running on */ 1986 gs->vcpu[vcpu].cpu = sample->cpu; 1987 out: 1988 return host__repipe(tool, event, sample, machine); 1989 } 1990 1991 static void sig_handler(int sig __maybe_unused) 1992 { 1993 session_done = 1; 1994 } 1995 1996 static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg) 1997 { 1998 struct perf_event_attr *attr = &evsel->core.attr; 1999 const char *name = evsel__name(evsel); 2000 2001 if (!(attr->sample_type & sample_type)) { 2002 pr_err("Samples for %s event do not have %s attribute set.", 2003 name, sample_msg); 2004 return -EINVAL; 2005 } 2006 2007 return 0; 2008 } 2009 2010 static int drop_sample(const struct perf_tool *tool __maybe_unused, 2011 union perf_event *event __maybe_unused, 2012 struct perf_sample *sample __maybe_unused, 2013 struct evsel *evsel __maybe_unused, 2014 struct machine *machine __maybe_unused) 2015 { 2016 return 0; 2017 } 2018 2019 static void strip_init(struct perf_inject *inject) 2020 { 2021 struct evlist *evlist = inject->session->evlist; 2022 struct evsel *evsel; 2023 2024 inject->tool.context_switch = perf_event__drop; 2025 2026 evlist__for_each_entry(evlist, evsel) 2027 evsel->handler = drop_sample; 2028 } 2029 2030 static int parse_vm_time_correlation(const struct option *opt, const char *str, int unset) 2031 { 2032 struct perf_inject *inject = opt->value; 2033 const char *args; 2034 char *dry_run; 2035 2036 if (unset) 2037 return 0; 2038 2039 inject->itrace_synth_opts.set = true; 2040 inject->itrace_synth_opts.vm_time_correlation = true; 2041 inject->in_place_update = true; 2042 2043 if (!str) 2044 return 0; 2045 2046 dry_run = skip_spaces(str); 2047 if (!strncmp(dry_run, "dry-run", strlen("dry-run"))) { 2048 inject->itrace_synth_opts.vm_tm_corr_dry_run = true; 2049 inject->in_place_update_dry_run = true; 2050 args = dry_run + strlen("dry-run"); 2051 } else { 2052 args = str; 2053 } 2054 2055 inject->itrace_synth_opts.vm_tm_corr_args = strdup(args); 2056 2057 return inject->itrace_synth_opts.vm_tm_corr_args ? 0 : -ENOMEM; 2058 } 2059 2060 static int parse_guest_data(const struct option *opt, const char *str, int unset) 2061 { 2062 struct perf_inject *inject = opt->value; 2063 struct guest_session *gs = &inject->guest_session; 2064 char *tok; 2065 char *s; 2066 2067 if (unset) 2068 return 0; 2069 2070 if (!str) 2071 goto bad_args; 2072 2073 s = strdup(str); 2074 if (!s) 2075 return -ENOMEM; 2076 2077 gs->perf_data_file = strsep(&s, ","); 2078 if (!gs->perf_data_file) 2079 goto bad_args; 2080 2081 gs->copy_kcore_dir = has_kcore_dir(gs->perf_data_file); 2082 if (gs->copy_kcore_dir) 2083 inject->output.is_dir = true; 2084 2085 tok = strsep(&s, ","); 2086 if (!tok) 2087 goto bad_args; 2088 gs->machine_pid = strtoul(tok, NULL, 0); 2089 if (!inject->guest_session.machine_pid) 2090 goto bad_args; 2091 2092 gs->time_scale = 1; 2093 2094 tok = strsep(&s, ","); 2095 if (!tok) 2096 goto out; 2097 gs->time_offset = strtoull(tok, NULL, 0); 2098 2099 tok = strsep(&s, ","); 2100 if (!tok) 2101 goto out; 2102 gs->time_scale = strtod(tok, NULL); 2103 if (!gs->time_scale) 2104 goto bad_args; 2105 out: 2106 return 0; 2107 2108 bad_args: 2109 pr_err("--guest-data option requires guest perf.data file name, " 2110 "guest machine PID, and optionally guest timestamp offset, " 2111 "and guest timestamp scale factor, separated by commas.\n"); 2112 return -1; 2113 } 2114 2115 static int save_section_info_cb(struct perf_file_section *section, 2116 struct perf_header *ph __maybe_unused, 2117 int feat, int fd __maybe_unused, void *data) 2118 { 2119 struct perf_inject *inject = data; 2120 2121 inject->secs[feat] = *section; 2122 return 0; 2123 } 2124 2125 static int save_section_info(struct perf_inject *inject) 2126 { 2127 struct perf_header *header = &inject->session->header; 2128 int fd = perf_data__fd(inject->session->data); 2129 2130 return perf_header__process_sections(header, fd, inject, save_section_info_cb); 2131 } 2132 2133 static bool keep_feat(struct perf_inject *inject, int feat) 2134 { 2135 switch (feat) { 2136 /* Keep original information that describes the machine or software */ 2137 case HEADER_TRACING_DATA: 2138 case HEADER_HOSTNAME: 2139 case HEADER_OSRELEASE: 2140 case HEADER_VERSION: 2141 case HEADER_ARCH: 2142 case HEADER_NRCPUS: 2143 case HEADER_CPUDESC: 2144 case HEADER_CPUID: 2145 case HEADER_TOTAL_MEM: 2146 case HEADER_CPU_TOPOLOGY: 2147 case HEADER_NUMA_TOPOLOGY: 2148 case HEADER_PMU_MAPPINGS: 2149 case HEADER_CACHE: 2150 case HEADER_MEM_TOPOLOGY: 2151 case HEADER_CLOCKID: 2152 case HEADER_BPF_PROG_INFO: 2153 case HEADER_BPF_BTF: 2154 case HEADER_CPU_PMU_CAPS: 2155 case HEADER_CLOCK_DATA: 2156 case HEADER_HYBRID_TOPOLOGY: 2157 case HEADER_PMU_CAPS: 2158 case HEADER_CPU_DOMAIN_INFO: 2159 case HEADER_CLN_SIZE: 2160 return true; 2161 /* Information that can be updated */ 2162 case HEADER_BUILD_ID: 2163 return inject->build_id_style == BID_RWS__NONE; 2164 case HEADER_CMDLINE: 2165 case HEADER_EVENT_DESC: 2166 case HEADER_BRANCH_STACK: 2167 case HEADER_GROUP_DESC: 2168 case HEADER_AUXTRACE: 2169 case HEADER_STAT: 2170 case HEADER_SAMPLE_TIME: 2171 case HEADER_DIR_FORMAT: 2172 case HEADER_COMPRESSED: 2173 default: 2174 return false; 2175 }; 2176 } 2177 2178 static int read_file(int fd, u64 offs, void *buf, size_t sz) 2179 { 2180 ssize_t ret = preadn(fd, buf, sz, offs); 2181 2182 if (ret < 0) 2183 return -errno; 2184 if ((size_t)ret != sz) 2185 return -EINVAL; 2186 return 0; 2187 } 2188 2189 static int feat_copy(struct perf_inject *inject, int feat, struct feat_writer *fw) 2190 { 2191 int fd = perf_data__fd(inject->session->data); 2192 u64 offs = inject->secs[feat].offset; 2193 size_t sz = inject->secs[feat].size; 2194 void *buf = malloc(sz); 2195 int ret; 2196 2197 if (!buf) 2198 return -ENOMEM; 2199 2200 ret = read_file(fd, offs, buf, sz); 2201 if (ret) 2202 goto out_free; 2203 2204 ret = fw->write(fw, buf, sz); 2205 out_free: 2206 free(buf); 2207 return ret; 2208 } 2209 2210 struct inject_fc { 2211 struct feat_copier fc; 2212 struct perf_inject *inject; 2213 }; 2214 2215 static int feat_copy_cb(struct feat_copier *fc, int feat, struct feat_writer *fw) 2216 { 2217 struct inject_fc *inj_fc = container_of(fc, struct inject_fc, fc); 2218 struct perf_inject *inject = inj_fc->inject; 2219 int ret; 2220 2221 if (!inject->secs[feat].offset || 2222 !keep_feat(inject, feat)) 2223 return 0; 2224 2225 ret = feat_copy(inject, feat, fw); 2226 if (ret < 0) 2227 return ret; 2228 2229 return 1; /* Feature section copied */ 2230 } 2231 2232 static int copy_kcore_dir(struct perf_inject *inject) 2233 { 2234 char *cmd; 2235 int ret; 2236 2237 ret = asprintf(&cmd, "cp -r -n %s/kcore_dir* %s >/dev/null 2>&1", 2238 inject->input_name, inject->output.path); 2239 if (ret < 0) 2240 return ret; 2241 pr_debug("%s\n", cmd); 2242 ret = system(cmd); 2243 free(cmd); 2244 return ret; 2245 } 2246 2247 static int guest_session__copy_kcore_dir(struct guest_session *gs) 2248 { 2249 struct perf_inject *inject = container_of(gs, struct perf_inject, guest_session); 2250 char *cmd; 2251 int ret; 2252 2253 ret = asprintf(&cmd, "cp -r -n %s/kcore_dir %s/kcore_dir__%u >/dev/null 2>&1", 2254 gs->perf_data_file, inject->output.path, gs->machine_pid); 2255 if (ret < 0) 2256 return ret; 2257 pr_debug("%s\n", cmd); 2258 ret = system(cmd); 2259 free(cmd); 2260 return ret; 2261 } 2262 2263 static int output_fd(struct perf_inject *inject) 2264 { 2265 return inject->in_place_update ? -1 : perf_data__fd(&inject->output); 2266 } 2267 2268 static int __cmd_inject(struct perf_inject *inject) 2269 { 2270 int ret = -EINVAL; 2271 struct guest_session *gs = &inject->guest_session; 2272 struct perf_session *session = inject->session; 2273 int fd = output_fd(inject); 2274 u64 output_data_offset = perf_session__data_offset(session->evlist); 2275 /* 2276 * Pipe input hasn't loaded the attributes and will handle them as 2277 * events. So that the attributes don't overlap the data, write the 2278 * attributes after the data. 2279 */ 2280 bool write_attrs_after_data = !inject->output.is_pipe && inject->session->data->is_pipe; 2281 2282 signal(SIGINT, sig_handler); 2283 2284 if (inject->build_id_style != BID_RWS__NONE || inject->sched_stat || 2285 inject->itrace_synth_opts.set) { 2286 inject->tool.mmap = perf_event__repipe_mmap; 2287 inject->tool.mmap2 = perf_event__repipe_mmap2; 2288 inject->tool.fork = perf_event__repipe_fork; 2289 #ifdef HAVE_LIBTRACEEVENT 2290 inject->tool.tracing_data = perf_event__repipe_tracing_data; 2291 #endif 2292 } 2293 2294 if (inject->build_id_style == BID_RWS__INJECT_HEADER_LAZY || 2295 inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) { 2296 inject->tool.sample = perf_event__inject_buildid; 2297 } else if (inject->sched_stat) { 2298 struct evsel *evsel; 2299 2300 evlist__for_each_entry(session->evlist, evsel) { 2301 const char *name = evsel__name(evsel); 2302 2303 if (!strcmp(name, "sched:sched_switch")) { 2304 if (evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID")) 2305 return -EINVAL; 2306 2307 evsel->handler = perf_inject__sched_switch; 2308 } else if (!strcmp(name, "sched:sched_process_exit")) 2309 evsel->handler = perf_inject__sched_process_exit; 2310 #ifdef HAVE_LIBTRACEEVENT 2311 else if (!strncmp(name, "sched:sched_stat_", 17)) 2312 evsel->handler = perf_inject__sched_stat; 2313 #endif 2314 } 2315 } else if (inject->itrace_synth_opts.vm_time_correlation) { 2316 session->itrace_synth_opts = &inject->itrace_synth_opts; 2317 memset(&inject->tool, 0, sizeof(inject->tool)); 2318 inject->tool.id_index = perf_event__process_id_index; 2319 inject->tool.auxtrace_info = perf_event__process_auxtrace_info; 2320 inject->tool.auxtrace = perf_event__process_auxtrace; 2321 inject->tool.auxtrace_error = perf_event__process_auxtrace_error; 2322 inject->tool.ordered_events = true; 2323 inject->tool.ordering_requires_timestamps = true; 2324 } else if (inject->itrace_synth_opts.set) { 2325 session->itrace_synth_opts = &inject->itrace_synth_opts; 2326 inject->itrace_synth_opts.inject = true; 2327 inject->tool.comm = perf_event__repipe_comm; 2328 inject->tool.namespaces = perf_event__repipe_namespaces; 2329 inject->tool.exit = perf_event__repipe_exit; 2330 inject->tool.id_index = perf_event__process_id_index; 2331 inject->tool.auxtrace_info = perf_event__process_auxtrace_info; 2332 inject->tool.auxtrace = perf_event__process_auxtrace; 2333 inject->tool.aux = perf_event__drop_aux; 2334 inject->tool.itrace_start = perf_event__drop_aux; 2335 inject->tool.aux_output_hw_id = perf_event__drop_aux; 2336 inject->tool.ordered_events = true; 2337 inject->tool.ordering_requires_timestamps = true; 2338 /* Allow space in the header for new attributes */ 2339 output_data_offset = roundup(8192 + session->header.data_offset, 4096); 2340 if (inject->strip) 2341 strip_init(inject); 2342 } else if (gs->perf_data_file) { 2343 char *name = gs->perf_data_file; 2344 2345 /* 2346 * Not strictly necessary, but keep these events in order wrt 2347 * guest events. 2348 */ 2349 inject->tool.mmap = host__repipe; 2350 inject->tool.mmap2 = host__repipe; 2351 inject->tool.comm = host__repipe; 2352 inject->tool.fork = host__repipe; 2353 inject->tool.exit = host__repipe; 2354 inject->tool.lost = host__repipe; 2355 inject->tool.context_switch = host__repipe; 2356 inject->tool.ksymbol = host__repipe; 2357 inject->tool.text_poke = host__repipe; 2358 /* 2359 * Once the host session has initialized, set up sample ID 2360 * mapping and feed in guest attrs, build IDs and initial 2361 * events. 2362 */ 2363 inject->tool.finished_init = host__finished_init; 2364 /* Obey finished round ordering */ 2365 inject->tool.finished_round = host__finished_round; 2366 /* Keep track of which CPU a VCPU is runnng on */ 2367 inject->tool.context_switch = host__context_switch; 2368 /* 2369 * Must order events to be able to obey finished round 2370 * ordering. 2371 */ 2372 inject->tool.ordered_events = true; 2373 inject->tool.ordering_requires_timestamps = true; 2374 /* Set up a separate session to process guest perf.data file */ 2375 ret = guest_session__start(gs, name, session->data->force); 2376 if (ret) { 2377 pr_err("Failed to process %s, error %d\n", name, ret); 2378 return ret; 2379 } 2380 /* Allow space in the header for guest attributes */ 2381 output_data_offset += gs->session->header.data_offset; 2382 output_data_offset = roundup(output_data_offset, 4096); 2383 } else if (inject->convert_callchain) { 2384 inject->tool.sample = perf_event__convert_sample_callchain; 2385 inject->tool.fork = perf_event__repipe_fork; 2386 inject->tool.comm = perf_event__repipe_comm; 2387 inject->tool.exit = perf_event__repipe_exit; 2388 inject->tool.mmap = perf_event__repipe_mmap; 2389 inject->tool.mmap2 = perf_event__repipe_mmap2; 2390 inject->tool.ordered_events = true; 2391 inject->tool.ordering_requires_timestamps = true; 2392 } 2393 2394 if (!inject->itrace_synth_opts.set) 2395 auxtrace_index__free(&session->auxtrace_index); 2396 2397 if (!inject->output.is_pipe && !inject->in_place_update) 2398 lseek(fd, output_data_offset, SEEK_SET); 2399 2400 ret = perf_session__process_events(session); 2401 if (ret) 2402 return ret; 2403 2404 if (gs->session) { 2405 /* 2406 * Remaining guest events have later timestamps. Flush them 2407 * out to file. 2408 */ 2409 ret = guest_session__flush_events(gs); 2410 if (ret) { 2411 pr_err("Failed to flush guest events\n"); 2412 return ret; 2413 } 2414 } 2415 2416 if (!inject->output.is_pipe && !inject->in_place_update) { 2417 struct inject_fc inj_fc = { 2418 .fc.copy = feat_copy_cb, 2419 .inject = inject, 2420 }; 2421 2422 if (inject->build_id_style == BID_RWS__INJECT_HEADER_LAZY || 2423 inject->build_id_style == BID_RWS__INJECT_HEADER_ALL) 2424 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 2425 /* 2426 * Keep all buildids when there is unprocessed AUX data because 2427 * it is not known which ones the AUX trace hits. 2428 */ 2429 if (perf_header__has_feat(&session->header, HEADER_BUILD_ID) && 2430 inject->have_auxtrace && !inject->itrace_synth_opts.set) 2431 perf_session__dsos_hit_all(session); 2432 /* 2433 * The AUX areas have been removed and replaced with 2434 * synthesized hardware events, so clear the feature flag. 2435 */ 2436 if (inject->itrace_synth_opts.set) { 2437 perf_header__clear_feat(&session->header, 2438 HEADER_AUXTRACE); 2439 if (inject->itrace_synth_opts.last_branch || 2440 inject->itrace_synth_opts.add_last_branch) 2441 perf_header__set_feat(&session->header, 2442 HEADER_BRANCH_STACK); 2443 } 2444 2445 /* 2446 * The converted data file won't have stack and registers. 2447 * Update the perf_event_attr to remove them before writing. 2448 */ 2449 if (inject->convert_callchain) { 2450 struct evsel *evsel; 2451 2452 evlist__for_each_entry(session->evlist, evsel) { 2453 evsel__reset_sample_bit(evsel, REGS_USER); 2454 evsel__reset_sample_bit(evsel, STACK_USER); 2455 evsel->core.attr.sample_regs_user = 0; 2456 evsel->core.attr.sample_stack_user = 0; 2457 evsel->core.attr.exclude_callchain_user = 0; 2458 } 2459 } 2460 2461 session->header.data_offset = output_data_offset; 2462 session->header.data_size = inject->bytes_written; 2463 perf_session__inject_header(session, session->evlist, fd, &inj_fc.fc, 2464 write_attrs_after_data); 2465 2466 if (inject->copy_kcore_dir) { 2467 ret = copy_kcore_dir(inject); 2468 if (ret) { 2469 pr_err("Failed to copy kcore\n"); 2470 return ret; 2471 } 2472 } 2473 if (gs->copy_kcore_dir) { 2474 ret = guest_session__copy_kcore_dir(gs); 2475 if (ret) { 2476 pr_err("Failed to copy guest kcore\n"); 2477 return ret; 2478 } 2479 } 2480 } 2481 2482 return ret; 2483 } 2484 2485 static bool evsel__has_dwarf_callchain(struct evsel *evsel) 2486 { 2487 struct perf_event_attr *attr = &evsel->core.attr; 2488 const u64 dwarf_callchain_flags = 2489 PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_CALLCHAIN; 2490 2491 if (!attr->exclude_callchain_user) 2492 return false; 2493 2494 return (attr->sample_type & dwarf_callchain_flags) == dwarf_callchain_flags; 2495 } 2496 2497 int cmd_inject(int argc, const char **argv) 2498 { 2499 struct perf_inject inject = { 2500 .input_name = "-", 2501 .samples = LIST_HEAD_INIT(inject.samples), 2502 .output = { 2503 .path = "-", 2504 .mode = PERF_DATA_MODE_WRITE, 2505 .file.use_stdio = true, 2506 }, 2507 }; 2508 struct perf_data data = { 2509 .mode = PERF_DATA_MODE_READ, 2510 .file.use_stdio = true, 2511 }; 2512 int ret; 2513 const char *known_build_ids = NULL; 2514 bool build_ids = false; 2515 bool build_id_all = false; 2516 bool mmap2_build_ids = false; 2517 bool mmap2_build_id_all = false; 2518 2519 struct option options[] = { 2520 OPT_BOOLEAN('b', "build-ids", &build_ids, 2521 "Inject build-ids into the output stream"), 2522 OPT_BOOLEAN(0, "buildid-all", &build_id_all, 2523 "Inject build-ids of all DSOs into the output stream"), 2524 OPT_BOOLEAN('B', "mmap2-buildids", &mmap2_build_ids, 2525 "Drop unused mmap events, make others mmap2 with build IDs"), 2526 OPT_BOOLEAN(0, "mmap2-buildid-all", &mmap2_build_id_all, 2527 "Rewrite all mmap events as mmap2 events with build IDs"), 2528 OPT_STRING(0, "known-build-ids", &known_build_ids, 2529 "buildid path [,buildid path...]", 2530 "build-ids to use for given paths"), 2531 OPT_STRING('i', "input", &inject.input_name, "file", 2532 "input file name"), 2533 OPT_STRING('o', "output", &inject.output.path, "file", 2534 "output file name"), 2535 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, 2536 "Merge sched-stat and sched-switch for getting events " 2537 "where and how long tasks slept"), 2538 #ifdef HAVE_JITDUMP 2539 OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"), 2540 #endif 2541 OPT_INCR('v', "verbose", &verbose, 2542 "be more verbose (show build ids, etc)"), 2543 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 2544 "file", "vmlinux pathname"), 2545 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux, 2546 "don't load vmlinux even if found"), 2547 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", 2548 "kallsyms pathname"), 2549 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), 2550 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 2551 NULL, "opts", "Instruction Tracing options\n" 2552 ITRACE_HELP, 2553 itrace_parse_synth_opts), 2554 OPT_BOOLEAN(0, "strip", &inject.strip, 2555 "strip non-synthesized events (use with --itrace)"), 2556 OPT_CALLBACK_OPTARG(0, "vm-time-correlation", &inject, NULL, "opts", 2557 "correlate time between VM guests and the host", 2558 parse_vm_time_correlation), 2559 OPT_CALLBACK_OPTARG(0, "guest-data", &inject, NULL, "opts", 2560 "inject events from a guest perf.data file", 2561 parse_guest_data), 2562 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory", 2563 "guest mount directory under which every guest os" 2564 " instance has a subdir"), 2565 OPT_BOOLEAN(0, "convert-callchain", &inject.convert_callchain, 2566 "Generate callchains using DWARF and drop register/stack data"), 2567 OPT_END() 2568 }; 2569 const char * const inject_usage[] = { 2570 "perf inject [<options>]", 2571 NULL 2572 }; 2573 bool ordered_events; 2574 2575 if (!inject.itrace_synth_opts.set) { 2576 /* Disable eager loading of kernel symbols that adds overhead to perf inject. */ 2577 symbol_conf.lazy_load_kernel_maps = true; 2578 } 2579 2580 #ifndef HAVE_JITDUMP 2581 set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true); 2582 #endif 2583 #ifndef HAVE_LIBDW_SUPPORT 2584 set_option_nobuild(options, 0, "convert-callchain", "NO_LIBDW=1", true); 2585 #endif 2586 argc = parse_options(argc, argv, options, inject_usage, 0); 2587 2588 /* 2589 * Any (unrecognized) arguments left? 2590 */ 2591 if (argc) 2592 usage_with_options(inject_usage, options); 2593 2594 if (inject.strip && !inject.itrace_synth_opts.set) { 2595 pr_err("--strip option requires --itrace option\n"); 2596 return -1; 2597 } 2598 2599 if (symbol__validate_sym_arguments()) 2600 return -1; 2601 2602 if (inject.in_place_update) { 2603 if (!strcmp(inject.input_name, "-")) { 2604 pr_err("Input file name required for in-place updating\n"); 2605 return -1; 2606 } 2607 if (strcmp(inject.output.path, "-")) { 2608 pr_err("Output file name must not be specified for in-place updating\n"); 2609 return -1; 2610 } 2611 if (!data.force && !inject.in_place_update_dry_run) { 2612 pr_err("The input file would be updated in place, " 2613 "the --force option is required.\n"); 2614 return -1; 2615 } 2616 if (!inject.in_place_update_dry_run) 2617 data.in_place_update = true; 2618 } else { 2619 if (strcmp(inject.output.path, "-") && !inject.strip && 2620 has_kcore_dir(inject.input_name)) { 2621 inject.output.is_dir = true; 2622 inject.copy_kcore_dir = true; 2623 } 2624 if (perf_data__open(&inject.output)) { 2625 perror("failed to create output file"); 2626 return -1; 2627 } 2628 } 2629 if (mmap2_build_ids) 2630 inject.build_id_style = BID_RWS__MMAP2_BUILDID_LAZY; 2631 if (mmap2_build_id_all) 2632 inject.build_id_style = BID_RWS__MMAP2_BUILDID_ALL; 2633 if (build_ids) 2634 inject.build_id_style = BID_RWS__INJECT_HEADER_LAZY; 2635 if (build_id_all) 2636 inject.build_id_style = BID_RWS__INJECT_HEADER_ALL; 2637 2638 data.path = inject.input_name; 2639 2640 ordered_events = inject.jit_mode || inject.sched_stat || 2641 inject.build_id_style == BID_RWS__INJECT_HEADER_LAZY || 2642 inject.build_id_style == BID_RWS__MMAP2_BUILDID_LAZY; 2643 perf_tool__init(&inject.tool, ordered_events); 2644 inject.tool.sample = perf_event__repipe_sample; 2645 inject.tool.read = perf_event__repipe_sample; 2646 inject.tool.mmap = perf_event__repipe; 2647 inject.tool.mmap2 = perf_event__repipe; 2648 inject.tool.comm = perf_event__repipe; 2649 inject.tool.namespaces = perf_event__repipe; 2650 inject.tool.cgroup = perf_event__repipe; 2651 inject.tool.fork = perf_event__repipe; 2652 inject.tool.exit = perf_event__repipe; 2653 inject.tool.lost = perf_event__repipe; 2654 inject.tool.lost_samples = perf_event__repipe; 2655 inject.tool.aux = perf_event__repipe; 2656 inject.tool.itrace_start = perf_event__repipe; 2657 inject.tool.aux_output_hw_id = perf_event__repipe; 2658 inject.tool.context_switch = perf_event__repipe; 2659 inject.tool.throttle = perf_event__repipe; 2660 inject.tool.unthrottle = perf_event__repipe; 2661 inject.tool.ksymbol = perf_event__repipe; 2662 inject.tool.bpf = perf_event__repipe; 2663 inject.tool.text_poke = perf_event__repipe; 2664 inject.tool.attr = perf_event__repipe_attr; 2665 inject.tool.event_update = perf_event__repipe_event_update; 2666 inject.tool.tracing_data = perf_event__repipe_op2_synth; 2667 inject.tool.finished_round = perf_event__repipe_oe_synth; 2668 inject.tool.build_id = perf_event__repipe_op2_synth; 2669 inject.tool.id_index = perf_event__repipe_op2_synth; 2670 inject.tool.auxtrace_info = perf_event__repipe_op2_synth; 2671 inject.tool.auxtrace_error = perf_event__repipe_op2_synth; 2672 inject.tool.time_conv = perf_event__repipe_op2_synth; 2673 inject.tool.thread_map = perf_event__repipe_op2_synth; 2674 inject.tool.cpu_map = perf_event__repipe_op2_synth; 2675 inject.tool.stat_config = perf_event__repipe_op2_synth; 2676 inject.tool.stat = perf_event__repipe_op2_synth; 2677 inject.tool.stat_round = perf_event__repipe_op2_synth; 2678 inject.tool.feature = perf_event__repipe_op2_synth; 2679 inject.tool.finished_init = perf_event__repipe_op2_synth; 2680 inject.tool.compressed = perf_event__repipe_op4_synth; 2681 inject.tool.auxtrace = perf_event__repipe_auxtrace; 2682 inject.tool.bpf_metadata = perf_event__repipe_op2_synth; 2683 inject.tool.schedstat_cpu = perf_event__repipe_op2_synth; 2684 inject.tool.schedstat_domain = perf_event__repipe_op2_synth; 2685 inject.tool.dont_split_sample_group = true; 2686 inject.tool.merge_deferred_callchains = false; 2687 inject.session = __perf_session__new(&data, &inject.tool, 2688 /*trace_event_repipe=*/inject.output.is_pipe, 2689 /*host_env=*/NULL); 2690 2691 if (IS_ERR(inject.session)) { 2692 ret = PTR_ERR(inject.session); 2693 goto out_close_output; 2694 } 2695 2696 if (zstd_init(&(inject.session->zstd_data), 0) < 0) 2697 pr_warning("Decompression initialization failed.\n"); 2698 2699 /* Save original section info before feature bits change */ 2700 ret = save_section_info(&inject); 2701 if (ret) 2702 goto out_delete; 2703 2704 if (inject.output.is_pipe) { 2705 ret = perf_header__write_pipe(perf_data__fd(&inject.output)); 2706 if (ret < 0) { 2707 pr_err("Couldn't write a new pipe header.\n"); 2708 goto out_delete; 2709 } 2710 2711 /* 2712 * If the input is already a pipe then the features and 2713 * attributes don't need synthesizing, they will be present in 2714 * the input. 2715 */ 2716 if (!data.is_pipe) { 2717 ret = perf_event__synthesize_for_pipe(&inject.tool, 2718 inject.session, 2719 &inject.output, 2720 perf_event__repipe); 2721 if (ret < 0) 2722 goto out_delete; 2723 } 2724 } 2725 2726 if (inject.build_id_style == BID_RWS__INJECT_HEADER_LAZY || 2727 inject.build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) { 2728 /* 2729 * to make sure the mmap records are ordered correctly 2730 * and so that the correct especially due to jitted code 2731 * mmaps. We cannot generate the buildid hit list and 2732 * inject the jit mmaps at the same time for now. 2733 */ 2734 inject.tool.ordering_requires_timestamps = true; 2735 } 2736 if (inject.build_id_style != BID_RWS__NONE && known_build_ids != NULL) { 2737 inject.known_build_ids = 2738 perf_inject__parse_known_build_ids(known_build_ids); 2739 2740 if (inject.known_build_ids == NULL) { 2741 pr_err("Couldn't parse known build ids.\n"); 2742 goto out_delete; 2743 } 2744 } 2745 2746 if (inject.convert_callchain) { 2747 struct evsel *evsel; 2748 2749 if (inject.output.is_pipe || inject.session->data->is_pipe) { 2750 pr_err("--convert-callchain cannot work with pipe\n"); 2751 goto out_delete; 2752 } 2753 2754 evlist__for_each_entry(inject.session->evlist, evsel) { 2755 if (!evsel__has_dwarf_callchain(evsel) && !evsel__is_dummy_event(evsel)) { 2756 pr_err("--convert-callchain requires DWARF call graph.\n"); 2757 goto out_delete; 2758 } 2759 } 2760 2761 inject.raw_callchain = calloc(PERF_MAX_STACK_DEPTH, sizeof(u64)); 2762 if (inject.raw_callchain == NULL) { 2763 pr_err("callchain allocation failed\n"); 2764 goto out_delete; 2765 } 2766 } 2767 2768 #ifdef HAVE_JITDUMP 2769 if (inject.jit_mode) { 2770 inject.tool.mmap2 = perf_event__repipe_mmap2; 2771 inject.tool.mmap = perf_event__repipe_mmap; 2772 inject.tool.ordering_requires_timestamps = true; 2773 /* 2774 * JIT MMAP injection injects all MMAP events in one go, so it 2775 * does not obey finished_round semantics. 2776 */ 2777 inject.tool.finished_round = perf_event__drop_oe; 2778 } 2779 #endif 2780 ret = symbol__init(perf_session__env(inject.session)); 2781 if (ret < 0) 2782 goto out_delete; 2783 2784 ret = __cmd_inject(&inject); 2785 2786 guest_session__exit(&inject.guest_session); 2787 2788 out_delete: 2789 strlist__delete(inject.known_build_ids); 2790 zstd_fini(&(inject.session->zstd_data)); 2791 perf_session__delete(inject.session); 2792 out_close_output: 2793 if (!inject.in_place_update) 2794 perf_data__close(&inject.output); 2795 free(inject.itrace_synth_opts.vm_tm_corr_args); 2796 free(inject.event_copy); 2797 free(inject.guest_session.ev.event_buf); 2798 free(inject.raw_callchain); 2799 return ret; 2800 } 2801