mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 08:46:41 +08:00
fix dwarf unwinding
This commit is contained in:
parent
73a4eca5ce
commit
495a9d535d
@ -1035,7 +1035,7 @@ static int sort_total(const struct rb_stack **p, const struct rb_stack **q)
|
||||
|
||||
static void _process_dump(struct process *process, int (*sortby)(const struct rb_stack **, const struct rb_stack **), int (*skipfunc)(struct rb_stack *), FILE *file, int lflag)
|
||||
{
|
||||
struct rb_stack **arr;
|
||||
struct rb_stack **arr = NULL;
|
||||
unsigned long i;
|
||||
void *data;
|
||||
unsigned long stack_trees = process->stack_trees;
|
||||
@ -1045,9 +1045,12 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
||||
if (dump_init(file) == -1)
|
||||
return;
|
||||
|
||||
if (!stack_trees)
|
||||
goto skip;
|
||||
|
||||
arr = malloc(sizeof(struct rb_stack *) * stack_trees);
|
||||
if (!arr)
|
||||
return;
|
||||
goto skip;
|
||||
|
||||
for(i = 0, data = rb_first(&process->stack_table); data; data = rb_next(data)) {
|
||||
struct rb_stack *stack_node = container_of(data, struct rb_stack, node);
|
||||
@ -1060,9 +1063,6 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
||||
|
||||
dump_printf("Process dump %d %s\n", process->pid, process->filename ? process->filename : "<unknown>");
|
||||
|
||||
if (!stack_trees)
|
||||
goto skip;
|
||||
|
||||
qsort(arr, stack_trees, sizeof(struct rb_stack *), (void *)sortby);
|
||||
|
||||
if (file == stderr) {
|
||||
@ -1245,8 +1245,10 @@ int process_scan(struct process *process, void *leaks, uint32_t payload_len)
|
||||
for(i = 0; i < new; ++i) {
|
||||
struct rb_block *block = process_rb_search(&process->block_table, process->get_ulong(new_leaks));
|
||||
|
||||
if (options.verbose > 1) {
|
||||
if (dump_printf(" leaked at 0x%08lx (%lu bytes)\n", (unsigned long)block->addr, (unsigned long)block->size) == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
new_leaks += process->ptr_size;
|
||||
}
|
||||
|
||||
20
dwarf.c
20
dwarf.c
@ -871,20 +871,16 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lib_addr_match(struct libref *libref, arch_addr_t ip)
|
||||
{
|
||||
return ip >= libref->txt_vaddr && ip < libref->txt_vaddr + libref->txt_size;
|
||||
}
|
||||
|
||||
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip)
|
||||
{
|
||||
struct dwarf_cursor *c = &as->cursor;
|
||||
struct libref *libref = c->libref;
|
||||
|
||||
if (c->use_prev_instr)
|
||||
ip -= 1;
|
||||
|
||||
if (likely(c->libref)) {
|
||||
if (lib_addr_match(c->libref, ip))
|
||||
if (ip >= libref->txt_vaddr && ip < libref->txt_vaddr + libref->txt_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -930,20 +926,19 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
||||
struct dwarf_cie_info *dci = &as->cursor.dci;
|
||||
struct libref *libref = as->cursor.libref;
|
||||
|
||||
e = lookup(fde_tab, fde_count, ip - libref->txt_vaddr - libref->eh_frame_hdr);
|
||||
e = lookup(fde_tab, fde_count, ip - libref->eh_hdr_vaddr);
|
||||
if (unlikely(!e)) {
|
||||
/* IP is inside this table's range, but there is no explicit unwind info. */
|
||||
debug(DEBUG_DWARF, "no unwind info found for IP %#lx", ip);
|
||||
return -DWARF_ENOINFO;
|
||||
}
|
||||
|
||||
fde_addr = libref->mmap_addr - (libref->txt_offset - libref->mmap_offset) + e->fde_offset + libref->eh_frame_hdr;
|
||||
fde_addr = libref->mmap_addr + e->fde_offset + libref->eh_hdr_offset;
|
||||
|
||||
if (unlikely((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0))
|
||||
return ret;
|
||||
|
||||
dci->start_ip -= ARCH_ADDR_T(libref->mmap_addr) - libref->txt_vaddr;
|
||||
|
||||
dci->start_ip = dci->start_ip - (arch_addr_t)libref->mmap_addr + libref->txt_vaddr;
|
||||
if (!as->is_64bit)
|
||||
dci->start_ip &= 0xffffffff;
|
||||
|
||||
@ -1942,8 +1937,6 @@ fail:
|
||||
c->ip = ip;
|
||||
|
||||
if (ret == -DWARF_ENOINFO) {
|
||||
debug(DEBUG_DWARF, "try arch specific step");
|
||||
|
||||
ret = dwarf_arch_step(as);
|
||||
if (!ret) {
|
||||
if (dwarf_locate_map(as, c->ip) < 0)
|
||||
@ -1988,6 +1981,7 @@ fail:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (ret != -DWARF_ENOINFO && ret != -DWARF_EBADFRAME)
|
||||
debug(DEBUG_DWARF, "error %d", ret);
|
||||
|
||||
c->valid = 0;
|
||||
@ -2003,7 +1997,7 @@ int dwarf_get_unwind_table(struct task *task, struct libref *libref)
|
||||
arch_addr_t eh_frame = 0;
|
||||
int ret;
|
||||
struct dwarf_addr_space tmp_as;
|
||||
struct dwarf_eh_frame_hdr *hdr = (struct dwarf_eh_frame_hdr *)(libref->mmap_addr + libref->eh_frame_hdr);
|
||||
struct dwarf_eh_frame_hdr *hdr = (struct dwarf_eh_frame_hdr *)(libref->mmap_addr + libref->eh_hdr_offset);
|
||||
|
||||
memset(&tmp_as, 0, sizeof(tmp_as));
|
||||
|
||||
|
||||
1
dwarf.h
1
dwarf.h
@ -58,7 +58,6 @@
|
||||
#define DWARF_EINVAL 4 /* unsupported operation or bad value */
|
||||
#define DWARF_EBADVERSION 5 /* unwind info has unsupported version */
|
||||
#define DWARF_ENOINFO 6 /* no unwind info found */
|
||||
#define DWARF_STOPUNWIND 7 /* no unwind info found */
|
||||
|
||||
struct dwarf_cie_info {
|
||||
arch_addr_t start_ip; /* first IP covered by this procedure */
|
||||
|
||||
19
library.c
19
library.c
@ -210,11 +210,6 @@ static void library_each_symbol(struct libref *libref, void (*cb)(struct library
|
||||
}
|
||||
}
|
||||
|
||||
static inline int lib_addr_match(struct libref *libref, arch_addr_t addr)
|
||||
{
|
||||
return addr >= libref->txt_vaddr && addr < libref->txt_vaddr + libref->txt_size;
|
||||
}
|
||||
|
||||
struct libref *addr2libref(struct task *leader, arch_addr_t addr)
|
||||
{
|
||||
struct rb_node **new = &(leader->libraries_tree.rb_node);
|
||||
@ -223,7 +218,7 @@ struct libref *addr2libref(struct task *leader, arch_addr_t addr)
|
||||
while (*new) {
|
||||
struct libref *this = container_of(*new, struct library, rb_node)->libref;
|
||||
|
||||
if (lib_addr_match(this, addr))
|
||||
if (addr >= this->txt_vaddr && addr < this->txt_vaddr + this->txt_size)
|
||||
return this;
|
||||
|
||||
if (this->txt_vaddr < addr)
|
||||
@ -321,15 +316,3 @@ const char *library_execname(struct task *leader)
|
||||
return container_of(leader->libraries_list.next, struct library, list)->libref->filename;
|
||||
}
|
||||
|
||||
arch_addr_t vaddr_to_off(struct libref *libref, arch_addr_t addr)
|
||||
{
|
||||
for(unsigned int i = 0; i < libref->loadsegs; ++i) {
|
||||
GElf_Phdr *phdr = &libref->loadseg[i];
|
||||
|
||||
if (phdr->p_vaddr >= addr && phdr->p_vaddr + phdr->p_filesz < addr)
|
||||
return phdr->p_offset + addr - phdr->p_vaddr;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%d\n", __func__, __LINE__);
|
||||
return ~0LU;
|
||||
}
|
||||
|
||||
11
library.h
11
library.h
@ -62,10 +62,6 @@ struct libref {
|
||||
unsigned long txt_size;
|
||||
unsigned long txt_offset;
|
||||
|
||||
/* loadable segments */
|
||||
unsigned int loadsegs;
|
||||
GElf_Phdr loadseg[4];
|
||||
|
||||
/* mapped image */
|
||||
void *mmap_addr;
|
||||
unsigned long mmap_offset;
|
||||
@ -73,10 +69,10 @@ struct libref {
|
||||
|
||||
/* global-pointer */
|
||||
arch_addr_t pltgot;
|
||||
unsigned long eh_frame_hdr;
|
||||
unsigned long eh_hdr_offset;
|
||||
unsigned long eh_hdr_vaddr;
|
||||
void *fde_tab;
|
||||
unsigned long fde_count;
|
||||
unsigned long eh_frame;
|
||||
unsigned int type;
|
||||
|
||||
#ifdef __arm__
|
||||
@ -141,8 +137,5 @@ void libref_set_filename(struct libref *libref, const char *new_name);
|
||||
/* find library by address */
|
||||
struct libref *addr2libref(struct task *leader, arch_addr_t addr);
|
||||
|
||||
/* return offset for virtual address */
|
||||
arch_addr_t vaddr_to_off(struct libref *libref, arch_addr_t addr);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
25
mtelf.c
25
mtelf.c
@ -54,8 +54,6 @@ struct mt_elf {
|
||||
int fd;
|
||||
const char *filename;
|
||||
Elf *elf;
|
||||
unsigned int loadsegs;
|
||||
GElf_Phdr loadseg[4];
|
||||
unsigned long loadbase;
|
||||
unsigned long loadsize;
|
||||
unsigned long vstart;
|
||||
@ -273,13 +271,10 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li
|
||||
libref->txt_size = mte->txt_hdr.p_filesz;
|
||||
libref->txt_offset = mte->txt_hdr.p_offset - mte->loadbase;
|
||||
libref->bias = mte->bias;
|
||||
libref->eh_frame_hdr = mte->eh_hdr.p_offset - mte->loadbase;
|
||||
libref->pltgot = mte->pltgot;
|
||||
libref->eh_hdr_offset = mte->eh_hdr.p_offset - mte->loadbase;
|
||||
libref->eh_hdr_vaddr = mte->eh_hdr.p_vaddr - mte->vstart + mte->bias;
|
||||
libref->pltgot = mte->pltgot - mte->vstart + mte->bias;
|
||||
libref->dyn = mte->dyn - mte->vstart + mte->bias;
|
||||
libref->loadsegs = mte->loadsegs;
|
||||
|
||||
for(unsigned int i = 0; i < libref->loadsegs; ++i)
|
||||
libref->loadseg[i] = mte->loadseg[i];
|
||||
|
||||
#ifdef __arm__
|
||||
if (mte->exidx_hdr.p_filesz) {
|
||||
@ -316,6 +311,7 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename)
|
||||
unsigned long loadbase = ~0;
|
||||
unsigned long align;
|
||||
unsigned long vstart;
|
||||
unsigned int loadsegs = 0;
|
||||
|
||||
debug(DEBUG_FUNCTION, "filename=%s", filename);
|
||||
|
||||
@ -329,17 +325,10 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename)
|
||||
memset(&mte->eh_hdr, 0, sizeof(mte->eh_hdr));
|
||||
memset(&mte->exidx_hdr, 0, sizeof(mte->exidx_hdr));
|
||||
|
||||
mte->loadsegs = 0;
|
||||
|
||||
for (i = 0; gelf_getphdr(mte->elf, i, &phdr) != NULL; ++i) {
|
||||
switch (phdr.p_type) {
|
||||
case PT_LOAD:
|
||||
if (mte->loadsegs >= ARRAY_SIZE(mte->loadseg)) {
|
||||
fprintf(stderr, "Unable to handle more than %lu loadable segments in %s\n", ARRAY_SIZE(mte->loadseg), filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mte->loadseg[mte->loadsegs++] = phdr;
|
||||
loadsegs++;
|
||||
|
||||
align = phdr.p_align;
|
||||
if (align)
|
||||
@ -379,15 +368,13 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
if (!mte->loadsegs) {
|
||||
if (!loadsegs) {
|
||||
fprintf(stderr, "No loadable segemnts in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize);
|
||||
mte->loadbase = loadbase & ~PAGEALIGN;
|
||||
mte->loadsize = (loadsize + (loadbase - mte->loadbase) + PAGEALIGN) & ~PAGEALIGN;
|
||||
fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->filename, mte->loadbase, mte->loadsize);
|
||||
|
||||
debug(DEBUG_FUNCTION, "filename=`%s' text offset=%#llx addr=%#llx size=%#llx",
|
||||
filename,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user