diff --git a/client/process.c b/client/process.c index 6b82895..8237fad 100644 --- a/client/process.c +++ b/client/process.c @@ -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 : ""); - 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 (dump_printf(" leaked at 0x%08lx (%lu bytes)\n", (unsigned long)block->addr, (unsigned long)block->size) == -1) - break; + 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; } diff --git a/dwarf.c b/dwarf.c index 60d3fbb..76ee067 100644 --- a/dwarf.c +++ b/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,7 +1981,8 @@ fail: break; } #endif - debug(DEBUG_DWARF, "error %d", ret); + 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)); diff --git a/dwarf.h b/dwarf.h index c418f3d..f40702c 100644 --- a/dwarf.h +++ b/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 */ diff --git a/library.c b/library.c index 19585a2..e81fdd0 100644 --- a/library.c +++ b/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; -} diff --git a/library.h b/library.h index 82e3929..a5ade69 100644 --- a/library.h +++ b/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 diff --git a/mtelf.c b/mtelf.c index 7c9e702..ecb76eb 100644 --- a/mtelf.c +++ b/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,