jitdump.c (20265B)
1// SPDX-License-Identifier: GPL-2.0 2#include <sys/sysmacros.h> 3#include <sys/types.h> 4#include <errno.h> 5#include <libgen.h> 6#include <stdio.h> 7#include <stdlib.h> 8#include <string.h> 9#include <fcntl.h> 10#include <unistd.h> 11#include <inttypes.h> 12#include <byteswap.h> 13#include <sys/stat.h> 14#include <sys/mman.h> 15#include <linux/stringify.h> 16 17#include "build-id.h" 18#include "event.h" 19#include "debug.h" 20#include "evlist.h" 21#include "namespaces.h" 22#include "symbol.h" 23#include <elf.h> 24 25#include "tsc.h" 26#include "session.h" 27#include "jit.h" 28#include "jitdump.h" 29#include "genelf.h" 30#include "thread.h" 31 32#include <linux/ctype.h> 33#include <linux/zalloc.h> 34 35struct jit_buf_desc { 36 struct perf_data *output; 37 struct perf_session *session; 38 struct machine *machine; 39 struct nsinfo *nsi; 40 union jr_entry *entry; 41 void *buf; 42 uint64_t sample_type; 43 size_t bufsize; 44 FILE *in; 45 bool needs_bswap; /* handles cross-endianness */ 46 bool use_arch_timestamp; 47 void *debug_data; 48 void *unwinding_data; 49 uint64_t unwinding_size; 50 uint64_t unwinding_mapped_size; 51 uint64_t eh_frame_hdr_size; 52 size_t nr_debug_entries; 53 uint32_t code_load_count; 54 u64 bytes_written; 55 struct rb_root code_root; 56 char dir[PATH_MAX]; 57}; 58 59struct debug_line_info { 60 unsigned long vma; 61 unsigned int lineno; 62 /* The filename format is unspecified, absolute path, relative etc. */ 63 char const filename[]; 64}; 65 66struct jit_tool { 67 struct perf_tool tool; 68 struct perf_data output; 69 struct perf_data input; 70 u64 bytes_written; 71}; 72 73#define hmax(a, b) ((a) > (b) ? (a) : (b)) 74#define get_jit_tool(t) (container_of(tool, struct jit_tool, tool)) 75 76static int 77jit_emit_elf(struct jit_buf_desc *jd, 78 char *filename, 79 const char *sym, 80 uint64_t code_addr, 81 const void *code, 82 int csize, 83 void *debug, 84 int nr_debug_entries, 85 void *unwinding, 86 uint32_t unwinding_header_size, 87 uint32_t unwinding_size) 88{ 89 int ret, fd, saved_errno; 90 struct nscookie nsc; 91 92 if (verbose > 0) 93 fprintf(stderr, "write ELF image %s\n", filename); 94 95 nsinfo__mountns_enter(jd->nsi, &nsc); 96 fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); 97 saved_errno = errno; 98 nsinfo__mountns_exit(&nsc); 99 if (fd == -1) { 100 pr_warning("cannot create jit ELF %s: %s\n", filename, strerror(saved_errno)); 101 return -1; 102 } 103 104 ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries, 105 unwinding, unwinding_header_size, unwinding_size); 106 107 close(fd); 108 109 if (ret) { 110 nsinfo__mountns_enter(jd->nsi, &nsc); 111 unlink(filename); 112 nsinfo__mountns_exit(&nsc); 113 } 114 115 return ret; 116} 117 118static void 119jit_close(struct jit_buf_desc *jd) 120{ 121 if (!(jd && jd->in)) 122 return; 123 funlockfile(jd->in); 124 fclose(jd->in); 125 jd->in = NULL; 126} 127 128static int 129jit_validate_events(struct perf_session *session) 130{ 131 struct evsel *evsel; 132 133 /* 134 * check that all events use CLOCK_MONOTONIC 135 */ 136 evlist__for_each_entry(session->evlist, evsel) { 137 if (evsel->core.attr.use_clockid == 0 || evsel->core.attr.clockid != CLOCK_MONOTONIC) 138 return -1; 139 } 140 return 0; 141} 142 143static int 144jit_open(struct jit_buf_desc *jd, const char *name) 145{ 146 struct jitheader header; 147 struct nscookie nsc; 148 struct jr_prefix *prefix; 149 ssize_t bs, bsz = 0; 150 void *n, *buf = NULL; 151 int ret, retval = -1; 152 153 nsinfo__mountns_enter(jd->nsi, &nsc); 154 jd->in = fopen(name, "r"); 155 nsinfo__mountns_exit(&nsc); 156 if (!jd->in) 157 return -1; 158 159 bsz = hmax(sizeof(header), sizeof(*prefix)); 160 161 buf = malloc(bsz); 162 if (!buf) 163 goto error; 164 165 /* 166 * protect from writer modifying the file while we are reading it 167 */ 168 flockfile(jd->in); 169 170 ret = fread(buf, sizeof(header), 1, jd->in); 171 if (ret != 1) 172 goto error; 173 174 memcpy(&header, buf, sizeof(header)); 175 176 if (header.magic != JITHEADER_MAGIC) { 177 if (header.magic != JITHEADER_MAGIC_SW) 178 goto error; 179 jd->needs_bswap = true; 180 } 181 182 if (jd->needs_bswap) { 183 header.version = bswap_32(header.version); 184 header.total_size = bswap_32(header.total_size); 185 header.pid = bswap_32(header.pid); 186 header.elf_mach = bswap_32(header.elf_mach); 187 header.timestamp = bswap_64(header.timestamp); 188 header.flags = bswap_64(header.flags); 189 } 190 191 jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP; 192 193 if (verbose > 2) 194 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n", 195 header.version, 196 header.total_size, 197 (unsigned long long)header.timestamp, 198 header.pid, 199 header.elf_mach, 200 jd->use_arch_timestamp); 201 202 if (header.version > JITHEADER_VERSION) { 203 pr_err("wrong jitdump version %u, expected " __stringify(JITHEADER_VERSION), 204 header.version); 205 goto error; 206 } 207 208 if (header.flags & JITDUMP_FLAGS_RESERVED) { 209 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", 210 (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED); 211 goto error; 212 } 213 214 if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) { 215 pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n"); 216 goto error; 217 } 218 219 /* 220 * validate event is using the correct clockid 221 */ 222 if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) { 223 pr_err("error, jitted code must be sampled with perf record -k 1\n"); 224 goto error; 225 } 226 227 bs = header.total_size - sizeof(header); 228 229 if (bs > bsz) { 230 n = realloc(buf, bs); 231 if (!n) 232 goto error; 233 bsz = bs; 234 buf = n; 235 /* read extra we do not know about */ 236 ret = fread(buf, bs - bsz, 1, jd->in); 237 if (ret != 1) 238 goto error; 239 } 240 /* 241 * keep dirname for generating files and mmap records 242 */ 243 strcpy(jd->dir, name); 244 dirname(jd->dir); 245 246 return 0; 247error: 248 funlockfile(jd->in); 249 fclose(jd->in); 250 return retval; 251} 252 253static union jr_entry * 254jit_get_next_entry(struct jit_buf_desc *jd) 255{ 256 struct jr_prefix *prefix; 257 union jr_entry *jr; 258 void *addr; 259 size_t bs, size; 260 int id, ret; 261 262 if (!(jd && jd->in)) 263 return NULL; 264 265 if (jd->buf == NULL) { 266 size_t sz = getpagesize(); 267 if (sz < sizeof(*prefix)) 268 sz = sizeof(*prefix); 269 270 jd->buf = malloc(sz); 271 if (jd->buf == NULL) 272 return NULL; 273 274 jd->bufsize = sz; 275 } 276 277 prefix = jd->buf; 278 279 /* 280 * file is still locked at this point 281 */ 282 ret = fread(prefix, sizeof(*prefix), 1, jd->in); 283 if (ret != 1) 284 return NULL; 285 286 if (jd->needs_bswap) { 287 prefix->id = bswap_32(prefix->id); 288 prefix->total_size = bswap_32(prefix->total_size); 289 prefix->timestamp = bswap_64(prefix->timestamp); 290 } 291 id = prefix->id; 292 size = prefix->total_size; 293 294 bs = (size_t)size; 295 if (bs < sizeof(*prefix)) 296 return NULL; 297 298 if (id >= JIT_CODE_MAX) { 299 pr_warning("next_entry: unknown record type %d, skipping\n", id); 300 } 301 if (bs > jd->bufsize) { 302 void *n; 303 n = realloc(jd->buf, bs); 304 if (!n) 305 return NULL; 306 jd->buf = n; 307 jd->bufsize = bs; 308 } 309 310 addr = ((void *)jd->buf) + sizeof(*prefix); 311 312 ret = fread(addr, bs - sizeof(*prefix), 1, jd->in); 313 if (ret != 1) 314 return NULL; 315 316 jr = (union jr_entry *)jd->buf; 317 318 switch(id) { 319 case JIT_CODE_DEBUG_INFO: 320 if (jd->needs_bswap) { 321 uint64_t n; 322 jr->info.code_addr = bswap_64(jr->info.code_addr); 323 jr->info.nr_entry = bswap_64(jr->info.nr_entry); 324 for (n = 0 ; n < jr->info.nr_entry; n++) { 325 jr->info.entries[n].addr = bswap_64(jr->info.entries[n].addr); 326 jr->info.entries[n].lineno = bswap_32(jr->info.entries[n].lineno); 327 jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim); 328 } 329 } 330 break; 331 case JIT_CODE_UNWINDING_INFO: 332 if (jd->needs_bswap) { 333 jr->unwinding.unwinding_size = bswap_64(jr->unwinding.unwinding_size); 334 jr->unwinding.eh_frame_hdr_size = bswap_64(jr->unwinding.eh_frame_hdr_size); 335 jr->unwinding.mapped_size = bswap_64(jr->unwinding.mapped_size); 336 } 337 break; 338 case JIT_CODE_CLOSE: 339 break; 340 case JIT_CODE_LOAD: 341 if (jd->needs_bswap) { 342 jr->load.pid = bswap_32(jr->load.pid); 343 jr->load.tid = bswap_32(jr->load.tid); 344 jr->load.vma = bswap_64(jr->load.vma); 345 jr->load.code_addr = bswap_64(jr->load.code_addr); 346 jr->load.code_size = bswap_64(jr->load.code_size); 347 jr->load.code_index= bswap_64(jr->load.code_index); 348 } 349 jd->code_load_count++; 350 break; 351 case JIT_CODE_MOVE: 352 if (jd->needs_bswap) { 353 jr->move.pid = bswap_32(jr->move.pid); 354 jr->move.tid = bswap_32(jr->move.tid); 355 jr->move.vma = bswap_64(jr->move.vma); 356 jr->move.old_code_addr = bswap_64(jr->move.old_code_addr); 357 jr->move.new_code_addr = bswap_64(jr->move.new_code_addr); 358 jr->move.code_size = bswap_64(jr->move.code_size); 359 jr->move.code_index = bswap_64(jr->move.code_index); 360 } 361 break; 362 case JIT_CODE_MAX: 363 default: 364 /* skip unknown record (we have read them) */ 365 break; 366 } 367 return jr; 368} 369 370static int 371jit_inject_event(struct jit_buf_desc *jd, union perf_event *event) 372{ 373 ssize_t size; 374 375 size = perf_data__write(jd->output, event, event->header.size); 376 if (size < 0) 377 return -1; 378 379 jd->bytes_written += size; 380 return 0; 381} 382 383static pid_t jr_entry_pid(struct jit_buf_desc *jd, union jr_entry *jr) 384{ 385 if (jd->nsi && nsinfo__in_pidns(jd->nsi)) 386 return nsinfo__tgid(jd->nsi); 387 return jr->load.pid; 388} 389 390static pid_t jr_entry_tid(struct jit_buf_desc *jd, union jr_entry *jr) 391{ 392 if (jd->nsi && nsinfo__in_pidns(jd->nsi)) 393 return nsinfo__pid(jd->nsi); 394 return jr->load.tid; 395} 396 397static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp) 398{ 399 struct perf_tsc_conversion tc = { .time_shift = 0, }; 400 struct perf_record_time_conv *time_conv = &jd->session->time_conv; 401 402 if (!jd->use_arch_timestamp) 403 return timestamp; 404 405 tc.time_shift = time_conv->time_shift; 406 tc.time_mult = time_conv->time_mult; 407 tc.time_zero = time_conv->time_zero; 408 409 /* 410 * The event TIME_CONV was extended for the fields from "time_cycles" 411 * when supported cap_user_time_short, for backward compatibility, 412 * checks the event size and assigns these extended fields if these 413 * fields are contained in the event. 414 */ 415 if (event_contains(*time_conv, time_cycles)) { 416 tc.time_cycles = time_conv->time_cycles; 417 tc.time_mask = time_conv->time_mask; 418 tc.cap_user_time_zero = time_conv->cap_user_time_zero; 419 tc.cap_user_time_short = time_conv->cap_user_time_short; 420 421 if (!tc.cap_user_time_zero) 422 return 0; 423 } 424 425 return tsc_to_perf_time(timestamp, &tc); 426} 427 428static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) 429{ 430 struct perf_sample sample; 431 union perf_event *event; 432 struct perf_tool *tool = jd->session->tool; 433 uint64_t code, addr; 434 uintptr_t uaddr; 435 char *filename; 436 struct stat st; 437 size_t size; 438 u16 idr_size; 439 const char *sym; 440 uint64_t count; 441 int ret, csize, usize; 442 pid_t nspid, pid, tid; 443 struct { 444 u32 pid, tid; 445 u64 time; 446 } *id; 447 448 nspid = jr->load.pid; 449 pid = jr_entry_pid(jd, jr); 450 tid = jr_entry_tid(jd, jr); 451 csize = jr->load.code_size; 452 usize = jd->unwinding_mapped_size; 453 addr = jr->load.code_addr; 454 sym = (void *)((unsigned long)jr + sizeof(jr->load)); 455 code = (unsigned long)jr + jr->load.p.total_size - csize; 456 count = jr->load.code_index; 457 idr_size = jd->machine->id_hdr_size; 458 459 event = calloc(1, sizeof(*event) + idr_size); 460 if (!event) 461 return -1; 462 463 filename = event->mmap2.filename; 464 size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so", 465 jd->dir, 466 nspid, 467 count); 468 469 size++; /* for \0 */ 470 471 size = PERF_ALIGN(size, sizeof(u64)); 472 uaddr = (uintptr_t)code; 473 ret = jit_emit_elf(jd, filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries, 474 jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size); 475 476 if (jd->debug_data && jd->nr_debug_entries) { 477 zfree(&jd->debug_data); 478 jd->nr_debug_entries = 0; 479 } 480 481 if (jd->unwinding_data && jd->eh_frame_hdr_size) { 482 zfree(&jd->unwinding_data); 483 jd->eh_frame_hdr_size = 0; 484 jd->unwinding_mapped_size = 0; 485 jd->unwinding_size = 0; 486 } 487 488 if (ret) { 489 free(event); 490 return -1; 491 } 492 if (nsinfo__stat(filename, &st, jd->nsi)) 493 memset(&st, 0, sizeof(st)); 494 495 event->mmap2.header.type = PERF_RECORD_MMAP2; 496 event->mmap2.header.misc = PERF_RECORD_MISC_USER; 497 event->mmap2.header.size = (sizeof(event->mmap2) - 498 (sizeof(event->mmap2.filename) - size) + idr_size); 499 500 event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; 501 event->mmap2.start = addr; 502 event->mmap2.len = usize ? ALIGN_8(csize) + usize : csize; 503 event->mmap2.pid = pid; 504 event->mmap2.tid = tid; 505 event->mmap2.ino = st.st_ino; 506 event->mmap2.maj = major(st.st_dev); 507 event->mmap2.min = minor(st.st_dev); 508 event->mmap2.prot = st.st_mode; 509 event->mmap2.flags = MAP_SHARED; 510 event->mmap2.ino_generation = 1; 511 512 id = (void *)((unsigned long)event + event->mmap.header.size - idr_size); 513 if (jd->sample_type & PERF_SAMPLE_TID) { 514 id->pid = pid; 515 id->tid = tid; 516 } 517 if (jd->sample_type & PERF_SAMPLE_TIME) 518 id->time = convert_timestamp(jd, jr->load.p.timestamp); 519 520 /* 521 * create pseudo sample to induce dso hit increment 522 * use first address as sample address 523 */ 524 memset(&sample, 0, sizeof(sample)); 525 sample.cpumode = PERF_RECORD_MISC_USER; 526 sample.pid = pid; 527 sample.tid = tid; 528 sample.time = id->time; 529 sample.ip = addr; 530 531 ret = perf_event__process_mmap2(tool, event, &sample, jd->machine); 532 if (ret) 533 return ret; 534 535 ret = jit_inject_event(jd, event); 536 /* 537 * mark dso as use to generate buildid in the header 538 */ 539 if (!ret) 540 build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine); 541 542 return ret; 543} 544 545static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) 546{ 547 struct perf_sample sample; 548 union perf_event *event; 549 struct perf_tool *tool = jd->session->tool; 550 char *filename; 551 size_t size; 552 struct stat st; 553 int usize; 554 u16 idr_size; 555 int ret; 556 pid_t nspid, pid, tid; 557 struct { 558 u32 pid, tid; 559 u64 time; 560 } *id; 561 562 nspid = jr->load.pid; 563 pid = jr_entry_pid(jd, jr); 564 tid = jr_entry_tid(jd, jr); 565 usize = jd->unwinding_mapped_size; 566 idr_size = jd->machine->id_hdr_size; 567 568 /* 569 * +16 to account for sample_id_all (hack) 570 */ 571 event = calloc(1, sizeof(*event) + 16); 572 if (!event) 573 return -1; 574 575 filename = event->mmap2.filename; 576 size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so", 577 jd->dir, 578 nspid, 579 jr->move.code_index); 580 581 size++; /* for \0 */ 582 583 if (nsinfo__stat(filename, &st, jd->nsi)) 584 memset(&st, 0, sizeof(st)); 585 586 size = PERF_ALIGN(size, sizeof(u64)); 587 588 event->mmap2.header.type = PERF_RECORD_MMAP2; 589 event->mmap2.header.misc = PERF_RECORD_MISC_USER; 590 event->mmap2.header.size = (sizeof(event->mmap2) - 591 (sizeof(event->mmap2.filename) - size) + idr_size); 592 event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; 593 event->mmap2.start = jr->move.new_code_addr; 594 event->mmap2.len = usize ? ALIGN_8(jr->move.code_size) + usize 595 : jr->move.code_size; 596 event->mmap2.pid = pid; 597 event->mmap2.tid = tid; 598 event->mmap2.ino = st.st_ino; 599 event->mmap2.maj = major(st.st_dev); 600 event->mmap2.min = minor(st.st_dev); 601 event->mmap2.prot = st.st_mode; 602 event->mmap2.flags = MAP_SHARED; 603 event->mmap2.ino_generation = 1; 604 605 id = (void *)((unsigned long)event + event->mmap.header.size - idr_size); 606 if (jd->sample_type & PERF_SAMPLE_TID) { 607 id->pid = pid; 608 id->tid = tid; 609 } 610 if (jd->sample_type & PERF_SAMPLE_TIME) 611 id->time = convert_timestamp(jd, jr->load.p.timestamp); 612 613 /* 614 * create pseudo sample to induce dso hit increment 615 * use first address as sample address 616 */ 617 memset(&sample, 0, sizeof(sample)); 618 sample.cpumode = PERF_RECORD_MISC_USER; 619 sample.pid = pid; 620 sample.tid = tid; 621 sample.time = id->time; 622 sample.ip = jr->move.new_code_addr; 623 624 ret = perf_event__process_mmap2(tool, event, &sample, jd->machine); 625 if (ret) 626 return ret; 627 628 ret = jit_inject_event(jd, event); 629 if (!ret) 630 build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine); 631 632 return ret; 633} 634 635static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) 636{ 637 void *data; 638 size_t sz; 639 640 if (!(jd && jr)) 641 return -1; 642 643 sz = jr->prefix.total_size - sizeof(jr->info); 644 data = malloc(sz); 645 if (!data) 646 return -1; 647 648 memcpy(data, &jr->info.entries, sz); 649 650 jd->debug_data = data; 651 652 /* 653 * we must use nr_entry instead of size here because 654 * we cannot distinguish actual entry from padding otherwise 655 */ 656 jd->nr_debug_entries = jr->info.nr_entry; 657 658 return 0; 659} 660 661static int 662jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr) 663{ 664 void *unwinding_data; 665 uint32_t unwinding_data_size; 666 667 if (!(jd && jr)) 668 return -1; 669 670 unwinding_data_size = jr->prefix.total_size - sizeof(jr->unwinding); 671 unwinding_data = malloc(unwinding_data_size); 672 if (!unwinding_data) 673 return -1; 674 675 memcpy(unwinding_data, &jr->unwinding.unwinding_data, 676 unwinding_data_size); 677 678 jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size; 679 jd->unwinding_size = jr->unwinding.unwinding_size; 680 jd->unwinding_mapped_size = jr->unwinding.mapped_size; 681 jd->unwinding_data = unwinding_data; 682 683 return 0; 684} 685 686static int 687jit_process_dump(struct jit_buf_desc *jd) 688{ 689 union jr_entry *jr; 690 int ret = 0; 691 692 while ((jr = jit_get_next_entry(jd))) { 693 switch(jr->prefix.id) { 694 case JIT_CODE_LOAD: 695 ret = jit_repipe_code_load(jd, jr); 696 break; 697 case JIT_CODE_MOVE: 698 ret = jit_repipe_code_move(jd, jr); 699 break; 700 case JIT_CODE_DEBUG_INFO: 701 ret = jit_repipe_debug_info(jd, jr); 702 break; 703 case JIT_CODE_UNWINDING_INFO: 704 ret = jit_repipe_unwinding_info(jd, jr); 705 break; 706 default: 707 ret = 0; 708 continue; 709 } 710 } 711 return ret; 712} 713 714static int 715jit_inject(struct jit_buf_desc *jd, char *path) 716{ 717 int ret; 718 719 if (verbose > 0) 720 fprintf(stderr, "injecting: %s\n", path); 721 722 ret = jit_open(jd, path); 723 if (ret) 724 return -1; 725 726 ret = jit_process_dump(jd); 727 728 jit_close(jd); 729 730 if (verbose > 0) 731 fprintf(stderr, "injected: %s (%d)\n", path, ret); 732 733 return 0; 734} 735 736/* 737 * File must be with pattern .../jit-XXXX.dump 738 * where XXXX is the PID of the process which did the mmap() 739 * as captured in the RECORD_MMAP record 740 */ 741static int 742jit_detect(char *mmap_name, pid_t pid, struct nsinfo *nsi) 743 { 744 char *p; 745 char *end = NULL; 746 pid_t pid2; 747 748 if (verbose > 2) 749 fprintf(stderr, "jit marker trying : %s\n", mmap_name); 750 /* 751 * get file name 752 */ 753 p = strrchr(mmap_name, '/'); 754 if (!p) 755 return -1; 756 757 /* 758 * match prefix 759 */ 760 if (strncmp(p, "/jit-", 5)) 761 return -1; 762 763 /* 764 * skip prefix 765 */ 766 p += 5; 767 768 /* 769 * must be followed by a pid 770 */ 771 if (!isdigit(*p)) 772 return -1; 773 774 pid2 = (int)strtol(p, &end, 10); 775 if (!end) 776 return -1; 777 778 /* 779 * pid does not match mmap pid 780 * pid==0 in system-wide mode (synthesized) 781 */ 782 if (pid && pid2 != nsinfo__nstgid(nsi)) 783 return -1; 784 /* 785 * validate suffix 786 */ 787 if (strcmp(end, ".dump")) 788 return -1; 789 790 if (verbose > 0) 791 fprintf(stderr, "jit marker found: %s\n", mmap_name); 792 793 return 0; 794} 795 796static void jit_add_pid(struct machine *machine, pid_t pid) 797{ 798 struct thread *thread = machine__findnew_thread(machine, pid, pid); 799 800 if (!thread) { 801 pr_err("%s: thread %d not found or created\n", __func__, pid); 802 return; 803 } 804 805 thread->priv = (void *)1; 806} 807 808static bool jit_has_pid(struct machine *machine, pid_t pid) 809{ 810 struct thread *thread = machine__find_thread(machine, pid, pid); 811 812 if (!thread) 813 return 0; 814 815 return (bool)thread->priv; 816} 817 818int 819jit_process(struct perf_session *session, 820 struct perf_data *output, 821 struct machine *machine, 822 char *filename, 823 pid_t pid, 824 pid_t tid, 825 u64 *nbytes) 826{ 827 struct thread *thread; 828 struct nsinfo *nsi; 829 struct evsel *first; 830 struct jit_buf_desc jd; 831 int ret; 832 833 thread = machine__findnew_thread(machine, pid, tid); 834 if (thread == NULL) { 835 pr_err("problem processing JIT mmap event, skipping it.\n"); 836 return 0; 837 } 838 839 nsi = nsinfo__get(thread->nsinfo); 840 thread__put(thread); 841 842 /* 843 * first, detect marker mmap (i.e., the jitdump mmap) 844 */ 845 if (jit_detect(filename, pid, nsi)) { 846 nsinfo__put(nsi); 847 848 // Strip //anon* mmaps if we processed a jitdump for this pid 849 if (jit_has_pid(machine, pid) && (strncmp(filename, "//anon", 6) == 0)) 850 return 1; 851 852 return 0; 853 } 854 855 memset(&jd, 0, sizeof(jd)); 856 857 jd.session = session; 858 jd.output = output; 859 jd.machine = machine; 860 jd.nsi = nsi; 861 862 /* 863 * track sample_type to compute id_all layout 864 * perf sets the same sample type to all events as of now 865 */ 866 first = evlist__first(session->evlist); 867 jd.sample_type = first->core.attr.sample_type; 868 869 *nbytes = 0; 870 871 ret = jit_inject(&jd, filename); 872 if (!ret) { 873 jit_add_pid(machine, pid); 874 *nbytes = jd.bytes_written; 875 ret = 1; 876 } 877 878 nsinfo__put(jd.nsi); 879 880 return ret; 881}