static int64_t sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) { if (!left->srcline) { if (!left->ms.map) left->srcline = SRCLINE_UNKNOWN; else { struct map *map = left->ms.map; left->srcline = get_srcline(map->dso, map__rip_2objdump(map, left->ip), left->ms.sym, true); } } if (!right->srcline) { if (!right->ms.map) right->srcline = SRCLINE_UNKNOWN; else { struct map *map = right->ms.map; right->srcline = get_srcline(map->dso, map__rip_2objdump(map, right->ip), right->ms.sym, true); } } return strcmp(right->srcline, left->srcline); }
static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym, struct map *map, struct disasm_line *dl) { u64 start = map__rip_2objdump(map, sym->start); strcpy(buf, ""); if (dl->offset == (s64) -1) return 0; return scnprintf(buf, size, "%"PRIx64, start + dl->offset); }
int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, FILE *fp) { char *srcline; int ret = 0; if (map && map->dso) { srcline = get_srcline(map->dso, map__rip_2objdump(map, addr)); if (srcline != SRCLINE_UNKNOWN) ret = fprintf(fp, "%s%s", prefix, srcline); free_srcline(srcline); } return ret; }
static char *get_srcfile(struct hist_entry *e) { char *sf, *p; struct map *map = e->ms.map; sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), e->ms.sym, false, true); if (!strcmp(sf, SRCLINE_UNKNOWN)) return no_srcfile; p = strchr(sf, ':'); if (p && *sf) { *p = 0; return sf; } free(sf); return no_srcfile; }
static int read_object_code(u64 addr, size_t len, u8 cpumode, struct thread *thread, struct machine *machine, struct state *state) { struct addr_location al; unsigned char buf1[BUFSZ]; unsigned char buf2[BUFSZ]; size_t ret_len; u64 objdump_addr; int ret; pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, &al); if (!al.map || !al.map->dso) { pr_debug("thread__find_addr_map failed\n"); return -1; } pr_debug("File is: %s\n", al.map->dso->long_name); if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(al.map->dso)) { pr_debug("Unexpected kernel address - skipping\n"); return 0; } pr_debug("On file address is: %#"PRIx64"\n", al.addr); if (len > BUFSZ) len = BUFSZ; /* Do not go off the map */ if (addr + len > al.map->end) len = al.map->end - addr; /* Read the object code using perf */ ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1, len); if (ret_len != len) { pr_debug("dso__data_read_offset failed\n"); return -1; } /* * Converting addresses for use by objdump requires more information. * map__load() does that. See map__rip_2objdump() for details. */ if (map__load(al.map, NULL)) return -1; /* objdump struggles with kcore - try each map only once */ if (dso__is_kcore(al.map->dso)) { size_t d; for (d = 0; d < state->done_cnt; d++) { if (state->done[d] == al.map->start) { pr_debug("kcore map tested already"); pr_debug(" - skipping\n"); return 0; } } if (state->done_cnt >= ARRAY_SIZE(state->done)) { pr_debug("Too many kcore maps - skipping\n"); return 0; } state->done[state->done_cnt++] = al.map->start; } /* Read the object code using objdump */ objdump_addr = map__rip_2objdump(al.map, al.addr); ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len); if (ret > 0) { /* * The kernel maps are inaccurate - assume objdump is right in * that case. */ if (cpumode == PERF_RECORD_MISC_KERNEL || cpumode == PERF_RECORD_MISC_GUEST_KERNEL) { len -= ret; if (len) { pr_debug("Reducing len to %zu\n", len); } else if (dso__is_kcore(al.map->dso)) { /* * objdump cannot handle very large segments * that may be found in kcore. */ pr_debug("objdump failed for kcore"); pr_debug(" - skipping\n"); return 0; } else { return -1; } } } if (ret < 0) { pr_debug("read_via_objdump failed\n"); return -1; } /* The results should be identical */ if (memcmp(buf1, buf2, len)) { pr_debug("Bytes read differ from those read by objdump\n"); return -1; } pr_debug("Bytes read match those read by objdump\n"); return 0; }