Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <sys/sysmacros.h>
0003 #include <sys/types.h>
0004 #include <errno.h>
0005 #include <libgen.h>
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009 #include <fcntl.h>
0010 #include <unistd.h>
0011 #include <inttypes.h>
0012 #include <byteswap.h>
0013 #include <sys/stat.h>
0014 #include <sys/mman.h>
0015 #include <linux/stringify.h>
0016 
0017 #include "build-id.h"
0018 #include "event.h"
0019 #include "debug.h"
0020 #include "evlist.h"
0021 #include "namespaces.h"
0022 #include "symbol.h"
0023 #include <elf.h>
0024 
0025 #include "tsc.h"
0026 #include "session.h"
0027 #include "jit.h"
0028 #include "jitdump.h"
0029 #include "genelf.h"
0030 #include "thread.h"
0031 
0032 #include <linux/ctype.h>
0033 #include <linux/zalloc.h>
0034 
0035 struct jit_buf_desc {
0036     struct perf_data *output;
0037     struct perf_session *session;
0038     struct machine *machine;
0039     struct nsinfo  *nsi;
0040     union jr_entry   *entry;
0041     void             *buf;
0042     uint64_t     sample_type;
0043     size_t           bufsize;
0044     FILE             *in;
0045     bool         needs_bswap; /* handles cross-endianness */
0046     bool         use_arch_timestamp;
0047     void         *debug_data;
0048     void         *unwinding_data;
0049     uint64_t     unwinding_size;
0050     uint64_t     unwinding_mapped_size;
0051     uint64_t         eh_frame_hdr_size;
0052     size_t       nr_debug_entries;
0053     uint32_t         code_load_count;
0054     u64      bytes_written;
0055     struct rb_root   code_root;
0056     char         dir[PATH_MAX];
0057 };
0058 
0059 struct debug_line_info {
0060     unsigned long vma;
0061     unsigned int lineno;
0062     /* The filename format is unspecified, absolute path, relative etc. */
0063     char const filename[];
0064 };
0065 
0066 struct jit_tool {
0067     struct perf_tool tool;
0068     struct perf_data    output;
0069     struct perf_data    input;
0070     u64 bytes_written;
0071 };
0072 
0073 #define hmax(a, b) ((a) > (b) ? (a) : (b))
0074 #define get_jit_tool(t) (container_of(tool, struct jit_tool, tool))
0075 
0076 static int
0077 jit_emit_elf(struct jit_buf_desc *jd,
0078          char *filename,
0079          const char *sym,
0080          uint64_t code_addr,
0081          const void *code,
0082          int csize,
0083          void *debug,
0084          int nr_debug_entries,
0085          void *unwinding,
0086          uint32_t unwinding_header_size,
0087          uint32_t unwinding_size)
0088 {
0089     int ret, fd, saved_errno;
0090     struct nscookie nsc;
0091 
0092     if (verbose > 0)
0093         fprintf(stderr, "write ELF image %s\n", filename);
0094 
0095     nsinfo__mountns_enter(jd->nsi, &nsc);
0096     fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
0097     saved_errno = errno;
0098     nsinfo__mountns_exit(&nsc);
0099     if (fd == -1) {
0100         pr_warning("cannot create jit ELF %s: %s\n", filename, strerror(saved_errno));
0101         return -1;
0102     }
0103 
0104     ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries,
0105                 unwinding, unwinding_header_size, unwinding_size);
0106 
0107         close(fd);
0108 
0109     if (ret) {
0110         nsinfo__mountns_enter(jd->nsi, &nsc);
0111         unlink(filename);
0112         nsinfo__mountns_exit(&nsc);
0113     }
0114 
0115     return ret;
0116 }
0117 
0118 static void
0119 jit_close(struct jit_buf_desc *jd)
0120 {
0121     if (!(jd && jd->in))
0122         return;
0123     funlockfile(jd->in);
0124     fclose(jd->in);
0125     jd->in = NULL;
0126 }
0127 
0128 static int
0129 jit_validate_events(struct perf_session *session)
0130 {
0131     struct evsel *evsel;
0132 
0133     /*
0134      * check that all events use CLOCK_MONOTONIC
0135      */
0136     evlist__for_each_entry(session->evlist, evsel) {
0137         if (evsel->core.attr.use_clockid == 0 || evsel->core.attr.clockid != CLOCK_MONOTONIC)
0138             return -1;
0139     }
0140     return 0;
0141 }
0142 
0143 static int
0144 jit_open(struct jit_buf_desc *jd, const char *name)
0145 {
0146     struct jitheader header;
0147     struct nscookie nsc;
0148     struct jr_prefix *prefix;
0149     ssize_t bs, bsz = 0;
0150     void *n, *buf = NULL;
0151     int ret, retval = -1;
0152 
0153     nsinfo__mountns_enter(jd->nsi, &nsc);
0154     jd->in = fopen(name, "r");
0155     nsinfo__mountns_exit(&nsc);
0156     if (!jd->in)
0157         return -1;
0158 
0159     bsz = hmax(sizeof(header), sizeof(*prefix));
0160 
0161     buf = malloc(bsz);
0162     if (!buf)
0163         goto error;
0164 
0165     /*
0166      * protect from writer modifying the file while we are reading it
0167      */
0168     flockfile(jd->in);
0169 
0170     ret = fread(buf, sizeof(header), 1, jd->in);
0171     if (ret != 1)
0172         goto error;
0173 
0174     memcpy(&header, buf, sizeof(header));
0175 
0176     if (header.magic != JITHEADER_MAGIC) {
0177         if (header.magic != JITHEADER_MAGIC_SW)
0178             goto error;
0179         jd->needs_bswap = true;
0180     }
0181 
0182     if (jd->needs_bswap) {
0183         header.version    = bswap_32(header.version);
0184         header.total_size = bswap_32(header.total_size);
0185         header.pid    = bswap_32(header.pid);
0186         header.elf_mach   = bswap_32(header.elf_mach);
0187         header.timestamp  = bswap_64(header.timestamp);
0188         header.flags      = bswap_64(header.flags);
0189     }
0190 
0191     jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP;
0192 
0193     if (verbose > 2)
0194         pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n",
0195             header.version,
0196             header.total_size,
0197             (unsigned long long)header.timestamp,
0198             header.pid,
0199             header.elf_mach,
0200             jd->use_arch_timestamp);
0201 
0202     if (header.version > JITHEADER_VERSION) {
0203         pr_err("wrong jitdump version %u, expected " __stringify(JITHEADER_VERSION),
0204             header.version);
0205         goto error;
0206     }
0207 
0208     if (header.flags & JITDUMP_FLAGS_RESERVED) {
0209         pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
0210                (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED);
0211         goto error;
0212     }
0213 
0214     if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
0215         pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n");
0216         goto error;
0217     }
0218 
0219     /*
0220      * validate event is using the correct clockid
0221      */
0222     if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) {
0223         pr_err("error, jitted code must be sampled with perf record -k 1\n");
0224         goto error;
0225     }
0226 
0227     bs = header.total_size - sizeof(header);
0228 
0229     if (bs > bsz) {
0230         n = realloc(buf, bs);
0231         if (!n)
0232             goto error;
0233         bsz = bs;
0234         buf = n;
0235         /* read extra we do not know about */
0236         ret = fread(buf, bs - bsz, 1, jd->in);
0237         if (ret != 1)
0238             goto error;
0239     }
0240     /*
0241      * keep dirname for generating files and mmap records
0242      */
0243     strcpy(jd->dir, name);
0244     dirname(jd->dir);
0245 
0246     return 0;
0247 error:
0248     funlockfile(jd->in);
0249     fclose(jd->in);
0250     return retval;
0251 }
0252 
0253 static union jr_entry *
0254 jit_get_next_entry(struct jit_buf_desc *jd)
0255 {
0256     struct jr_prefix *prefix;
0257     union jr_entry *jr;
0258     void *addr;
0259     size_t bs, size;
0260     int id, ret;
0261 
0262     if (!(jd && jd->in))
0263         return NULL;
0264 
0265     if (jd->buf == NULL) {
0266         size_t sz = getpagesize();
0267         if (sz < sizeof(*prefix))
0268             sz = sizeof(*prefix);
0269 
0270         jd->buf = malloc(sz);
0271         if (jd->buf == NULL)
0272             return NULL;
0273 
0274         jd->bufsize = sz;
0275     }
0276 
0277     prefix = jd->buf;
0278 
0279     /*
0280      * file is still locked at this point
0281      */
0282     ret = fread(prefix, sizeof(*prefix), 1, jd->in);
0283     if (ret  != 1)
0284         return NULL;
0285 
0286     if (jd->needs_bswap) {
0287         prefix->id         = bswap_32(prefix->id);
0288         prefix->total_size = bswap_32(prefix->total_size);
0289         prefix->timestamp  = bswap_64(prefix->timestamp);
0290     }
0291     id   = prefix->id;
0292     size = prefix->total_size;
0293 
0294     bs = (size_t)size;
0295     if (bs < sizeof(*prefix))
0296         return NULL;
0297 
0298     if (id >= JIT_CODE_MAX) {
0299         pr_warning("next_entry: unknown record type %d, skipping\n", id);
0300     }
0301     if (bs > jd->bufsize) {
0302         void *n;
0303         n = realloc(jd->buf, bs);
0304         if (!n)
0305             return NULL;
0306         jd->buf = n;
0307         jd->bufsize = bs;
0308     }
0309 
0310     addr = ((void *)jd->buf) + sizeof(*prefix);
0311 
0312     ret = fread(addr, bs - sizeof(*prefix), 1, jd->in);
0313     if (ret != 1)
0314         return NULL;
0315 
0316     jr = (union jr_entry *)jd->buf;
0317 
0318     switch(id) {
0319     case JIT_CODE_DEBUG_INFO:
0320         if (jd->needs_bswap) {
0321             uint64_t n;
0322             jr->info.code_addr = bswap_64(jr->info.code_addr);
0323             jr->info.nr_entry  = bswap_64(jr->info.nr_entry);
0324             for (n = 0 ; n < jr->info.nr_entry; n++) {
0325                 jr->info.entries[n].addr    = bswap_64(jr->info.entries[n].addr);
0326                 jr->info.entries[n].lineno  = bswap_32(jr->info.entries[n].lineno);
0327                 jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim);
0328             }
0329         }
0330         break;
0331     case JIT_CODE_UNWINDING_INFO:
0332         if (jd->needs_bswap) {
0333             jr->unwinding.unwinding_size = bswap_64(jr->unwinding.unwinding_size);
0334             jr->unwinding.eh_frame_hdr_size = bswap_64(jr->unwinding.eh_frame_hdr_size);
0335             jr->unwinding.mapped_size = bswap_64(jr->unwinding.mapped_size);
0336         }
0337         break;
0338     case JIT_CODE_CLOSE:
0339         break;
0340     case JIT_CODE_LOAD:
0341         if (jd->needs_bswap) {
0342             jr->load.pid       = bswap_32(jr->load.pid);
0343             jr->load.tid       = bswap_32(jr->load.tid);
0344             jr->load.vma       = bswap_64(jr->load.vma);
0345             jr->load.code_addr = bswap_64(jr->load.code_addr);
0346             jr->load.code_size = bswap_64(jr->load.code_size);
0347             jr->load.code_index= bswap_64(jr->load.code_index);
0348         }
0349         jd->code_load_count++;
0350         break;
0351     case JIT_CODE_MOVE:
0352         if (jd->needs_bswap) {
0353             jr->move.pid           = bswap_32(jr->move.pid);
0354             jr->move.tid           = bswap_32(jr->move.tid);
0355             jr->move.vma           = bswap_64(jr->move.vma);
0356             jr->move.old_code_addr = bswap_64(jr->move.old_code_addr);
0357             jr->move.new_code_addr = bswap_64(jr->move.new_code_addr);
0358             jr->move.code_size     = bswap_64(jr->move.code_size);
0359             jr->move.code_index    = bswap_64(jr->move.code_index);
0360         }
0361         break;
0362     case JIT_CODE_MAX:
0363     default:
0364         /* skip unknown record (we have read them) */
0365         break;
0366     }
0367     return jr;
0368 }
0369 
0370 static int
0371 jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
0372 {
0373     ssize_t size;
0374 
0375     size = perf_data__write(jd->output, event, event->header.size);
0376     if (size < 0)
0377         return -1;
0378 
0379     jd->bytes_written += size;
0380     return 0;
0381 }
0382 
0383 static pid_t jr_entry_pid(struct jit_buf_desc *jd, union jr_entry *jr)
0384 {
0385     if (jd->nsi && nsinfo__in_pidns(jd->nsi))
0386         return nsinfo__tgid(jd->nsi);
0387     return jr->load.pid;
0388 }
0389 
0390 static pid_t jr_entry_tid(struct jit_buf_desc *jd, union jr_entry *jr)
0391 {
0392     if (jd->nsi && nsinfo__in_pidns(jd->nsi))
0393         return nsinfo__pid(jd->nsi);
0394     return jr->load.tid;
0395 }
0396 
0397 static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp)
0398 {
0399     struct perf_tsc_conversion tc = { .time_shift = 0, };
0400     struct perf_record_time_conv *time_conv = &jd->session->time_conv;
0401 
0402     if (!jd->use_arch_timestamp)
0403         return timestamp;
0404 
0405     tc.time_shift = time_conv->time_shift;
0406     tc.time_mult  = time_conv->time_mult;
0407     tc.time_zero  = time_conv->time_zero;
0408 
0409     /*
0410      * The event TIME_CONV was extended for the fields from "time_cycles"
0411      * when supported cap_user_time_short, for backward compatibility,
0412      * checks the event size and assigns these extended fields if these
0413      * fields are contained in the event.
0414      */
0415     if (event_contains(*time_conv, time_cycles)) {
0416         tc.time_cycles         = time_conv->time_cycles;
0417         tc.time_mask           = time_conv->time_mask;
0418         tc.cap_user_time_zero  = time_conv->cap_user_time_zero;
0419         tc.cap_user_time_short = time_conv->cap_user_time_short;
0420 
0421         if (!tc.cap_user_time_zero)
0422             return 0;
0423     }
0424 
0425     return tsc_to_perf_time(timestamp, &tc);
0426 }
0427 
0428 static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
0429 {
0430     struct perf_sample sample;
0431     union perf_event *event;
0432     struct perf_tool *tool = jd->session->tool;
0433     uint64_t code, addr;
0434     uintptr_t uaddr;
0435     char *filename;
0436     struct stat st;
0437     size_t size;
0438     u16 idr_size;
0439     const char *sym;
0440     uint64_t count;
0441     int ret, csize, usize;
0442     pid_t nspid, pid, tid;
0443     struct {
0444         u32 pid, tid;
0445         u64 time;
0446     } *id;
0447 
0448     nspid = jr->load.pid;
0449     pid   = jr_entry_pid(jd, jr);
0450     tid   = jr_entry_tid(jd, jr);
0451     csize = jr->load.code_size;
0452     usize = jd->unwinding_mapped_size;
0453     addr  = jr->load.code_addr;
0454     sym   = (void *)((unsigned long)jr + sizeof(jr->load));
0455     code  = (unsigned long)jr + jr->load.p.total_size - csize;
0456     count = jr->load.code_index;
0457     idr_size = jd->machine->id_hdr_size;
0458 
0459     event = calloc(1, sizeof(*event) + idr_size);
0460     if (!event)
0461         return -1;
0462 
0463     filename = event->mmap2.filename;
0464     size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so",
0465             jd->dir,
0466             nspid,
0467             count);
0468 
0469     size++; /* for \0 */
0470 
0471     size = PERF_ALIGN(size, sizeof(u64));
0472     uaddr = (uintptr_t)code;
0473     ret = jit_emit_elf(jd, filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries,
0474                jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size);
0475 
0476     if (jd->debug_data && jd->nr_debug_entries) {
0477         zfree(&jd->debug_data);
0478         jd->nr_debug_entries = 0;
0479     }
0480 
0481     if (jd->unwinding_data && jd->eh_frame_hdr_size) {
0482         zfree(&jd->unwinding_data);
0483         jd->eh_frame_hdr_size = 0;
0484         jd->unwinding_mapped_size = 0;
0485         jd->unwinding_size = 0;
0486     }
0487 
0488     if (ret) {
0489         free(event);
0490         return -1;
0491     }
0492     if (nsinfo__stat(filename, &st, jd->nsi))
0493         memset(&st, 0, sizeof(st));
0494 
0495     event->mmap2.header.type = PERF_RECORD_MMAP2;
0496     event->mmap2.header.misc = PERF_RECORD_MISC_USER;
0497     event->mmap2.header.size = (sizeof(event->mmap2) -
0498             (sizeof(event->mmap2.filename) - size) + idr_size);
0499 
0500     event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
0501     event->mmap2.start = addr;
0502     event->mmap2.len   = usize ? ALIGN_8(csize) + usize : csize;
0503     event->mmap2.pid   = pid;
0504     event->mmap2.tid   = tid;
0505     event->mmap2.ino   = st.st_ino;
0506     event->mmap2.maj   = major(st.st_dev);
0507     event->mmap2.min   = minor(st.st_dev);
0508     event->mmap2.prot  = st.st_mode;
0509     event->mmap2.flags = MAP_SHARED;
0510     event->mmap2.ino_generation = 1;
0511 
0512     id = (void *)((unsigned long)event + event->mmap.header.size - idr_size);
0513     if (jd->sample_type & PERF_SAMPLE_TID) {
0514         id->pid  = pid;
0515         id->tid  = tid;
0516     }
0517     if (jd->sample_type & PERF_SAMPLE_TIME)
0518         id->time = convert_timestamp(jd, jr->load.p.timestamp);
0519 
0520     /*
0521      * create pseudo sample to induce dso hit increment
0522      * use first address as sample address
0523      */
0524     memset(&sample, 0, sizeof(sample));
0525     sample.cpumode = PERF_RECORD_MISC_USER;
0526     sample.pid  = pid;
0527     sample.tid  = tid;
0528     sample.time = id->time;
0529     sample.ip   = addr;
0530 
0531     ret = perf_event__process_mmap2(tool, event, &sample, jd->machine);
0532     if (ret)
0533         return ret;
0534 
0535     ret = jit_inject_event(jd, event);
0536     /*
0537      * mark dso as use to generate buildid in the header
0538      */
0539     if (!ret)
0540         build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine);
0541 
0542     return ret;
0543 }
0544 
0545 static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
0546 {
0547     struct perf_sample sample;
0548     union perf_event *event;
0549     struct perf_tool *tool = jd->session->tool;
0550     char *filename;
0551     size_t size;
0552     struct stat st;
0553     int usize;
0554     u16 idr_size;
0555     int ret;
0556     pid_t nspid, pid, tid;
0557     struct {
0558         u32 pid, tid;
0559         u64 time;
0560     } *id;
0561 
0562     nspid = jr->load.pid;
0563     pid   = jr_entry_pid(jd, jr);
0564     tid   = jr_entry_tid(jd, jr);
0565     usize = jd->unwinding_mapped_size;
0566     idr_size = jd->machine->id_hdr_size;
0567 
0568     /*
0569      * +16 to account for sample_id_all (hack)
0570      */
0571     event = calloc(1, sizeof(*event) + 16);
0572     if (!event)
0573         return -1;
0574 
0575     filename = event->mmap2.filename;
0576     size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so",
0577              jd->dir,
0578          nspid,
0579          jr->move.code_index);
0580 
0581     size++; /* for \0 */
0582 
0583     if (nsinfo__stat(filename, &st, jd->nsi))
0584         memset(&st, 0, sizeof(st));
0585 
0586     size = PERF_ALIGN(size, sizeof(u64));
0587 
0588     event->mmap2.header.type = PERF_RECORD_MMAP2;
0589     event->mmap2.header.misc = PERF_RECORD_MISC_USER;
0590     event->mmap2.header.size = (sizeof(event->mmap2) -
0591             (sizeof(event->mmap2.filename) - size) + idr_size);
0592     event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
0593     event->mmap2.start = jr->move.new_code_addr;
0594     event->mmap2.len   = usize ? ALIGN_8(jr->move.code_size) + usize
0595                    : jr->move.code_size;
0596     event->mmap2.pid   = pid;
0597     event->mmap2.tid   = tid;
0598     event->mmap2.ino   = st.st_ino;
0599     event->mmap2.maj   = major(st.st_dev);
0600     event->mmap2.min   = minor(st.st_dev);
0601     event->mmap2.prot  = st.st_mode;
0602     event->mmap2.flags = MAP_SHARED;
0603     event->mmap2.ino_generation = 1;
0604 
0605     id = (void *)((unsigned long)event + event->mmap.header.size - idr_size);
0606     if (jd->sample_type & PERF_SAMPLE_TID) {
0607         id->pid  = pid;
0608         id->tid  = tid;
0609     }
0610     if (jd->sample_type & PERF_SAMPLE_TIME)
0611         id->time = convert_timestamp(jd, jr->load.p.timestamp);
0612 
0613     /*
0614      * create pseudo sample to induce dso hit increment
0615      * use first address as sample address
0616      */
0617     memset(&sample, 0, sizeof(sample));
0618     sample.cpumode = PERF_RECORD_MISC_USER;
0619     sample.pid  = pid;
0620     sample.tid  = tid;
0621     sample.time = id->time;
0622     sample.ip   = jr->move.new_code_addr;
0623 
0624     ret = perf_event__process_mmap2(tool, event, &sample, jd->machine);
0625     if (ret)
0626         return ret;
0627 
0628     ret = jit_inject_event(jd, event);
0629     if (!ret)
0630         build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine);
0631 
0632     return ret;
0633 }
0634 
0635 static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr)
0636 {
0637     void *data;
0638     size_t sz;
0639 
0640     if (!(jd && jr))
0641         return -1;
0642 
0643     sz  = jr->prefix.total_size - sizeof(jr->info);
0644     data = malloc(sz);
0645     if (!data)
0646         return -1;
0647 
0648     memcpy(data, &jr->info.entries, sz);
0649 
0650     jd->debug_data       = data;
0651 
0652     /*
0653      * we must use nr_entry instead of size here because
0654      * we cannot distinguish actual entry from padding otherwise
0655      */
0656     jd->nr_debug_entries = jr->info.nr_entry;
0657 
0658     return 0;
0659 }
0660 
0661 static int
0662 jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr)
0663 {
0664     void *unwinding_data;
0665     uint32_t unwinding_data_size;
0666 
0667     if (!(jd && jr))
0668         return -1;
0669 
0670     unwinding_data_size  = jr->prefix.total_size - sizeof(jr->unwinding);
0671     unwinding_data = malloc(unwinding_data_size);
0672     if (!unwinding_data)
0673         return -1;
0674 
0675     memcpy(unwinding_data, &jr->unwinding.unwinding_data,
0676            unwinding_data_size);
0677 
0678     jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size;
0679     jd->unwinding_size = jr->unwinding.unwinding_size;
0680     jd->unwinding_mapped_size = jr->unwinding.mapped_size;
0681     jd->unwinding_data = unwinding_data;
0682 
0683     return 0;
0684 }
0685 
0686 static int
0687 jit_process_dump(struct jit_buf_desc *jd)
0688 {
0689     union jr_entry *jr;
0690     int ret = 0;
0691 
0692     while ((jr = jit_get_next_entry(jd))) {
0693         switch(jr->prefix.id) {
0694         case JIT_CODE_LOAD:
0695             ret = jit_repipe_code_load(jd, jr);
0696             break;
0697         case JIT_CODE_MOVE:
0698             ret = jit_repipe_code_move(jd, jr);
0699             break;
0700         case JIT_CODE_DEBUG_INFO:
0701             ret = jit_repipe_debug_info(jd, jr);
0702             break;
0703         case JIT_CODE_UNWINDING_INFO:
0704             ret = jit_repipe_unwinding_info(jd, jr);
0705             break;
0706         default:
0707             ret = 0;
0708             continue;
0709         }
0710     }
0711     return ret;
0712 }
0713 
0714 static int
0715 jit_inject(struct jit_buf_desc *jd, char *path)
0716 {
0717     int ret;
0718 
0719     if (verbose > 0)
0720         fprintf(stderr, "injecting: %s\n", path);
0721 
0722     ret = jit_open(jd, path);
0723     if (ret)
0724         return -1;
0725 
0726     ret = jit_process_dump(jd);
0727 
0728     jit_close(jd);
0729 
0730     if (verbose > 0)
0731         fprintf(stderr, "injected: %s (%d)\n", path, ret);
0732 
0733     return 0;
0734 }
0735 
0736 /*
0737  * File must be with pattern .../jit-XXXX.dump
0738  * where XXXX is the PID of the process which did the mmap()
0739  * as captured in the RECORD_MMAP record
0740  */
0741 static int
0742 jit_detect(char *mmap_name, pid_t pid, struct nsinfo *nsi)
0743  {
0744     char *p;
0745     char *end = NULL;
0746     pid_t pid2;
0747 
0748     if (verbose > 2)
0749         fprintf(stderr, "jit marker trying : %s\n", mmap_name);
0750     /*
0751      * get file name
0752      */
0753     p = strrchr(mmap_name, '/');
0754     if (!p)
0755         return -1;
0756 
0757     /*
0758      * match prefix
0759      */
0760     if (strncmp(p, "/jit-", 5))
0761         return -1;
0762 
0763     /*
0764      * skip prefix
0765      */
0766     p += 5;
0767 
0768     /*
0769      * must be followed by a pid
0770      */
0771     if (!isdigit(*p))
0772         return -1;
0773 
0774     pid2 = (int)strtol(p, &end, 10);
0775     if (!end)
0776         return -1;
0777 
0778     /*
0779      * pid does not match mmap pid
0780      * pid==0 in system-wide mode (synthesized)
0781      */
0782     if (pid && pid2 != nsinfo__nstgid(nsi))
0783         return -1;
0784     /*
0785      * validate suffix
0786      */
0787     if (strcmp(end, ".dump"))
0788         return -1;
0789 
0790     if (verbose > 0)
0791         fprintf(stderr, "jit marker found: %s\n", mmap_name);
0792 
0793     return 0;
0794 }
0795 
0796 static void jit_add_pid(struct machine *machine, pid_t pid)
0797 {
0798     struct thread *thread = machine__findnew_thread(machine, pid, pid);
0799 
0800     if (!thread) {
0801         pr_err("%s: thread %d not found or created\n", __func__, pid);
0802         return;
0803     }
0804 
0805     thread->priv = (void *)1;
0806 }
0807 
0808 static bool jit_has_pid(struct machine *machine, pid_t pid)
0809 {
0810     struct thread *thread = machine__find_thread(machine, pid, pid);
0811 
0812     if (!thread)
0813         return 0;
0814 
0815     return (bool)thread->priv;
0816 }
0817 
0818 int
0819 jit_process(struct perf_session *session,
0820         struct perf_data *output,
0821         struct machine *machine,
0822         char *filename,
0823         pid_t pid,
0824         pid_t tid,
0825         u64 *nbytes)
0826 {
0827     struct thread *thread;
0828     struct nsinfo *nsi;
0829     struct evsel *first;
0830     struct jit_buf_desc jd;
0831     int ret;
0832 
0833     thread = machine__findnew_thread(machine, pid, tid);
0834     if (thread == NULL) {
0835         pr_err("problem processing JIT mmap event, skipping it.\n");
0836         return 0;
0837     }
0838 
0839     nsi = nsinfo__get(thread->nsinfo);
0840     thread__put(thread);
0841 
0842     /*
0843      * first, detect marker mmap (i.e., the jitdump mmap)
0844      */
0845     if (jit_detect(filename, pid, nsi)) {
0846         nsinfo__put(nsi);
0847 
0848         /*
0849          * Strip //anon*, [anon:* and /memfd:* mmaps if we processed a jitdump for this pid
0850          */
0851         if (jit_has_pid(machine, pid) &&
0852             ((strncmp(filename, "//anon", 6) == 0) ||
0853              (strncmp(filename, "[anon:", 6) == 0) ||
0854              (strncmp(filename, "/memfd:", 7) == 0)))
0855             return 1;
0856 
0857         return 0;
0858     }
0859 
0860     memset(&jd, 0, sizeof(jd));
0861 
0862     jd.session = session;
0863     jd.output  = output;
0864     jd.machine = machine;
0865     jd.nsi = nsi;
0866 
0867     /*
0868      * track sample_type to compute id_all layout
0869      * perf sets the same sample type to all events as of now
0870      */
0871     first = evlist__first(session->evlist);
0872     jd.sample_type = first->core.attr.sample_type;
0873 
0874     *nbytes = 0;
0875 
0876     ret = jit_inject(&jd, filename);
0877     if (!ret) {
0878         jit_add_pid(machine, pid);
0879         *nbytes = jd.bytes_written;
0880         ret = 1;
0881     }
0882 
0883     nsinfo__put(jd.nsi);
0884 
0885     return ret;
0886 }