if (header.version > JITHEADER_VERSION) {
pr_err("wrong jitdump version %u, expected " __stringify(JITHEADER_VERSION),
header.version); goto error;
}
if (header.flags & JITDUMP_FLAGS_RESERVED) {
pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
(unsignedlonglong)header.flags & JITDUMP_FLAGS_RESERVED); goto error;
}
if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n"); goto error;
}
/* * validate event is using the correct clockid
*/ if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) {
pr_err("error, jitted code must be sampled with perf record -k 1\n"); goto error;
}
bs = header.total_size - sizeof(header);
if (bs > bsz) {
n = realloc(buf, bs); if (!n) goto error;
bsz = bs;
buf = n; /* read extra we do not know about */
ret = fread(buf, bs - bsz, 1, jd->in); if (ret != 1) goto error;
} /* * keep dirname for generating files and mmap records
*/
strcpy(jd->dir, name);
dirname(jd->dir);
free(buf);
if (jd->buf == NULL) {
size_t sz = getpagesize(); if (sz < sizeof(*prefix))
sz = sizeof(*prefix);
jd->buf = malloc(sz); if (jd->buf == NULL) return NULL;
jd->bufsize = sz;
}
prefix = jd->buf;
/* * file is still locked at this point
*/
ret = fread(prefix, sizeof(*prefix), 1, jd->in); if (ret != 1) return NULL;
if (jd->needs_bswap) {
prefix->id = bswap_32(prefix->id);
prefix->total_size = bswap_32(prefix->total_size);
prefix->timestamp = bswap_64(prefix->timestamp);
}
id = prefix->id;
size = prefix->total_size;
bs = (size_t)size; if (bs < sizeof(*prefix)) return NULL;
if (id >= JIT_CODE_MAX) {
pr_warning("next_entry: unknown record type %d, skipping\n", id);
} if (bs > jd->bufsize) { void *n;
n = realloc(jd->buf, bs); if (!n) return NULL;
jd->buf = n;
jd->bufsize = bs;
}
addr = ((void *)jd->buf) + sizeof(*prefix);
ret = fread(addr, bs - sizeof(*prefix), 1, jd->in); if (ret != 1) return NULL;
jr = (union jr_entry *)jd->buf;
switch(id) { case JIT_CODE_DEBUG_INFO: if (jd->needs_bswap) {
uint64_t n;
jr->info.code_addr = bswap_64(jr->info.code_addr);
jr->info.nr_entry = bswap_64(jr->info.nr_entry); for (n = 0 ; n < jr->info.nr_entry; n++) {
jr->info.entries[n].addr = bswap_64(jr->info.entries[n].addr);
jr->info.entries[n].lineno = bswap_32(jr->info.entries[n].lineno);
jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim);
}
} break; case JIT_CODE_UNWINDING_INFO: if (jd->needs_bswap) {
jr->unwinding.unwinding_size = bswap_64(jr->unwinding.unwinding_size);
jr->unwinding.eh_frame_hdr_size = bswap_64(jr->unwinding.eh_frame_hdr_size);
jr->unwinding.mapped_size = bswap_64(jr->unwinding.mapped_size);
} break; case JIT_CODE_CLOSE: break; case JIT_CODE_LOAD: if (jd->needs_bswap) {
jr->load.pid = bswap_32(jr->load.pid);
jr->load.tid = bswap_32(jr->load.tid);
jr->load.vma = bswap_64(jr->load.vma);
jr->load.code_addr = bswap_64(jr->load.code_addr);
jr->load.code_size = bswap_64(jr->load.code_size);
jr->load.code_index= bswap_64(jr->load.code_index);
}
jd->code_load_count++; break; case JIT_CODE_MOVE: if (jd->needs_bswap) {
jr->move.pid = bswap_32(jr->move.pid);
jr->move.tid = bswap_32(jr->move.tid);
jr->move.vma = bswap_64(jr->move.vma);
jr->move.old_code_addr = bswap_64(jr->move.old_code_addr);
jr->move.new_code_addr = bswap_64(jr->move.new_code_addr);
jr->move.code_size = bswap_64(jr->move.code_size);
jr->move.code_index = bswap_64(jr->move.code_index);
} break; case JIT_CODE_MAX: default: /* skip unknown record (we have read them) */ break;
} return jr;
}
staticint
jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
{
ssize_t size;
/* * The event TIME_CONV was extended for the fields from "time_cycles" * when supported cap_user_time_short, for backward compatibility, * checks the event size and assigns these extended fields if these * fields are contained in the event.
*/ if (event_contains(*time_conv, time_cycles)) {
tc.time_cycles = time_conv->time_cycles;
tc.time_mask = time_conv->time_mask;
tc.cap_user_time_zero = time_conv->cap_user_time_zero;
tc.cap_user_time_short = time_conv->cap_user_time_short;
sz = jr->prefix.total_size - sizeof(jr->info);
data = malloc(sz); if (!data) return -1;
memcpy(data, &jr->info.entries, sz);
jd->debug_data = data;
/* * we must use nr_entry instead of size here because * we cannot distinguish actual entry from padding otherwise
*/
jd->nr_debug_entries = jr->info.nr_entry;
staticint
jit_process_dump(struct jit_buf_desc *jd)
{ union jr_entry *jr; int ret = 0;
while ((jr = jit_get_next_entry(jd))) { switch(jr->prefix.id) { case JIT_CODE_LOAD:
ret = jit_repipe_code_load(jd, jr); break; case JIT_CODE_MOVE:
ret = jit_repipe_code_move(jd, jr); break; case JIT_CODE_DEBUG_INFO:
ret = jit_repipe_debug_info(jd, jr); break; case JIT_CODE_UNWINDING_INFO:
ret = jit_repipe_unwinding_info(jd, jr); break; default:
ret = 0; continue;
}
} return ret;
}
staticint
jit_inject(struct jit_buf_desc *jd, constchar *path)
{ int ret;
if (verbose > 0)
fprintf(stderr, "injecting: %s\n", path);
ret = jit_open(jd, path); if (ret) return -1;
ret = jit_process_dump(jd);
jit_close(jd);
if (verbose > 0)
fprintf(stderr, "injected: %s (%d)\n", path, ret);
return 0;
}
/* * File must be with pattern .../jit-XXXX.dump * where XXXX is the PID of the process which did the mmap() * as captured in the RECORD_MMAP record
*/ staticint
jit_detect(constchar *mmap_name, pid_t pid, struct nsinfo *nsi, bool *in_pidns)
{ char *p; char *end = NULL;
pid_t pid2;
if (verbose > 2)
fprintf(stderr, "jit marker trying : %s\n", mmap_name); /* * get file name
*/
p = strrchr(mmap_name, '/'); if (!p) return -1;
/* * match prefix
*/ if (strncmp(p, "/jit-", 5)) return -1;
/* * skip prefix
*/
p += 5;
/* * must be followed by a pid
*/ if (!isdigit(*p)) return -1;
pid2 = (int)strtol(p, &end, 10); if (!end) return -1;
*in_pidns = pid == nsinfo__nstgid(nsi); /* * pid does not match mmap pid * pid==0 in system-wide mode (synthesized) * * If the pid in the file name is equal to the nstgid, then * the agent ran inside a container and perf outside the * container, so record it for further use in jit_inject().
*/ if (pid && !(pid2 == pid || *in_pidns)) return -1; /* * validate suffix
*/ if (strcmp(end, ".dump")) return -1;
if (verbose > 0)
fprintf(stderr, "jit marker found: %s\n", mmap_name);
/* * track sample_type to compute id_all layout * perf sets the same sample type to all events as of now
*/
first = evlist__first(session->evlist);
jd.sample_type = first->core.attr.sample_type;
*nbytes = 0;
ret = jit_inject(&jd, filename); if (!ret) {
jit_add_pid(machine, pid);
*nbytes = jd.bytes_written;
ret = 1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.