code cleanup

This commit is contained in:
Stefani Seibold 2018-04-12 13:03:16 +02:00
parent dc6b85bd8b
commit a6c7ba8fcc
8 changed files with 116 additions and 66 deletions

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.9)
set(MT "mtrace-ng")
project(${MT} C)
set(MT_VERSION_STRING "0.8")
set(MT_VERSION_STRING "0.8.1")
option(DISABLE_CLIENT "whether to disable client support" OFF)

40
dwarf.c
View File

@ -463,7 +463,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
{
struct dwarf_addr_space *indirect_as = as;
arch_addr_t val, initial_addr = *addr;
arch_addr_t gp = as->cursor.libref->gp;
arch_addr_t gp = as->cursor.libref->pltgot;
int is_64bit = as->is_64bit;
void *tmp_ptr;
int ret;
@ -481,10 +481,10 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
struct dwarf_cursor *c = &as->cursor;
struct libref *libref = c->libref;
if (*addr < ARCH_ADDR_T(libref->image_addr))
fatal("invalid access mem: addr %#lx < %p", *addr, libref->image_addr);
if (*addr >= ARCH_ADDR_T(libref->image_addr + libref->load_size))
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->image_addr + libref->load_size);
if (*addr < ARCH_ADDR_T(libref->mmap_addr))
fatal("invalid access mem: addr %#lx < %p", *addr, libref->mmap_addr);
if (*addr >= ARCH_ADDR_T(libref->mmap_addr + libref->txt_size))
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->mmap_addr + libref->txt_size);
#endif
memset(&tmp, 0, sizeof(tmp));
@ -873,7 +873,7 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
static inline int lib_addr_match(struct libref *libref, arch_addr_t ip)
{
return ip >= libref->load_addr && ip < libref->load_addr + libref->load_size;
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)
@ -895,16 +895,16 @@ int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip)
return 0;
}
static const struct table_entry *lookup(const struct table_entry *table, size_t table_len, int32_t rel_ip)
static const struct table_entry *lookup(const struct table_entry *table, size_t fde_count, int32_t rel_ip)
{
const struct table_entry *e, *f;
unsigned long lo, hi;
if (!table_len)
if (!fde_count)
return NULL;
lo = 0;
hi = table_len;
hi = fde_count;
f = NULL;
do {
unsigned long mid = (lo + hi) / 2;
@ -922,7 +922,7 @@ static const struct table_entry *lookup(const struct table_entry *table, size_t
return f;
}
static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip, void *table_data, unsigned long table_len)
static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip, void *fde_tab, unsigned long fde_count)
{
const struct table_entry *e;
void *fde_addr;
@ -930,19 +930,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(table_data, table_len, ip - libref->load_addr - libref->seg_offset);
e = lookup(fde_tab, fde_count, ip - libref->txt_vaddr - libref->eh_frame_hdr);
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->image_addr - libref->load_offset + e->fde_offset + libref->seg_offset;
fde_addr = libref->mmap_addr - libref->mmap_offset + e->fde_offset + libref->eh_frame_hdr;
if (unlikely((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0))
return ret;
dci->start_ip -= ARCH_ADDR_T(libref->image_addr) - libref->load_addr;
dci->start_ip -= ARCH_ADDR_T(libref->mmap_addr) - libref->txt_vaddr;
if (!as->is_64bit)
dci->start_ip &= 0xffffffff;
@ -1808,7 +1808,7 @@ static int fetch_proc_info(struct dwarf_addr_space *as, arch_addr_t ip)
struct libref *libref = c->libref;
int ret;
ret = dwarf_search_unwind_table(as, ip, libref->table_data, libref->table_len);
ret = dwarf_search_unwind_table(as, ip, libref->fde_tab, libref->fde_count);
if (ret < 0)
return ret;
@ -1998,7 +1998,9 @@ fail:
int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwarf_eh_frame_hdr *hdr)
{
arch_addr_t addr, fde_count;
arch_addr_t addr;
arch_addr_t fde_count = 0;
arch_addr_t eh_frame = 0;
int ret;
struct dwarf_addr_space tmp_as;
@ -2015,8 +2017,8 @@ int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwar
addr = ARCH_ADDR_T(hdr + 1);
/* (Optionally) read eh_frame_ptr: */
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->eh_frame_ptr_enc, NULL, 0)) < 0)
/* read eh_frame_ptr: */
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->eh_frame_ptr_enc, &eh_frame, 0)) < 0)
return -DWARF_ENOINFO;
/* (Optionally) read fde_count: */
@ -2028,8 +2030,8 @@ int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwar
return -DWARF_EINVAL;
}
libref->table_data = (void *)addr;
libref->table_len = fde_count;
libref->fde_tab = (void *)addr;
libref->fde_count = fde_count;
return 0;
}

View File

@ -66,8 +66,8 @@ void libref_delete(struct libref *libref)
free(sym);
}
if (libref->image_addr)
munmap(libref->image_addr, libref->load_size);
if (libref->mmap_addr)
munmap(libref->mmap_addr, libref->txt_size);
free((void *)libref->filename);
free(libref);
@ -170,10 +170,10 @@ void library_delete_list(struct task *leader, struct list_head *list)
struct library *lib = container_of(it, struct library, list);
struct libref *libref = lib->libref;
debug(DEBUG_FUNCTION, "%s@%#lx pid=%d ", libref->filename, libref->base, leader->pid);
debug(DEBUG_FUNCTION, "%s@%#lx pid=%d ", libref->filename, libref->key, leader->pid);
if (unlikely(options.verbose > 1))
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx\n", leader->pid, libref->filename, libref->base, libref->load_addr, libref->load_addr + libref->load_size);
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx\n", leader->pid, libref->filename, libref->key, libref->txt_vaddr, libref->txt_vaddr + libref->txt_size);
library_delete(leader, lib);
}
@ -212,7 +212,7 @@ 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->load_addr && addr < libref->load_addr + libref->load_size;
return addr >= libref->txt_vaddr && addr < libref->txt_vaddr + libref->txt_size;
}
struct libref *addr2libref(struct task *leader, arch_addr_t addr)
@ -226,7 +226,7 @@ struct libref *addr2libref(struct task *leader, arch_addr_t addr)
if (lib_addr_match(this, addr))
return this;
if (this->load_addr < addr)
if (this->txt_vaddr < addr)
new = &((*new)->rb_left);
else
new = &((*new)->rb_right);
@ -245,7 +245,7 @@ static void insert_lib(struct task *leader, struct library *lib)
parent = *new;
if (this->libref->load_addr < lib->libref->load_addr)
if (this->libref->txt_vaddr < lib->libref->txt_vaddr)
new = &((*new)->rb_left);
else
new = &((*new)->rb_right);
@ -258,7 +258,7 @@ static void insert_lib(struct task *leader, struct library *lib)
static struct library *_library_add(struct task *leader, struct libref *libref)
{
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", libref->filename, libref->base, leader->pid);
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", libref->filename, libref->key, leader->pid);
assert(leader->leader == leader);
@ -273,7 +273,7 @@ static struct library *_library_add(struct task *leader, struct libref *libref)
insert_lib(leader, lib);
if (unlikely(options.verbose > 1))
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx\n", leader->pid, libref->filename, libref->base, libref->load_addr, libref->load_addr + libref->load_size);
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx\n", leader->pid, libref->filename, libref->key, libref->txt_vaddr, libref->txt_vaddr + libref->txt_size);
return lib;
}
@ -321,3 +321,15 @@ 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;
}

View File

@ -47,8 +47,8 @@ struct libref {
* they have the same key. */
arch_addr_t key;
/* Address where the library is mapped. */
arch_addr_t base;
/* base address assign by the loader */
unsigned long bias;
/* Absolute address of the entry point. Useful for main
* binary, though I suppose the value might be useful for the
@ -59,19 +59,24 @@ struct libref {
const char *filename;
/* executable segment */
unsigned long load_offset;
unsigned long load_addr;
unsigned long load_size;
unsigned long bias;
unsigned long txt_vaddr;
unsigned long txt_size;
/* loadable segments */
unsigned int loadsegs;
GElf_Phdr loadseg[4];
/* mapped image */
void *image_addr;
void *mmap_addr;
unsigned long mmap_offset;
unsigned long mmap_size;
/* global-pointer */
arch_addr_t gp;
unsigned long seg_offset;
void *table_data;
unsigned long table_len;
arch_addr_t pltgot;
unsigned long eh_frame_hdr;
void *fde_tab;
unsigned long fde_count;
unsigned long eh_frame;
unsigned int type;
#ifdef __arm__
@ -136,5 +141,8 @@ 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

66
mtelf.c
View File

@ -47,6 +47,9 @@
#include "common.h"
#include "report.h"
#define PAGESIZE 4096
#define PAGEALIGN (PAGESIZE - 1)
static int open_elf(struct mt_elf *mte, struct task *task, const char *filename)
{
char *cwd;
@ -216,10 +219,9 @@ static int populate_symtab(struct mt_elf *mte, struct libref *libref)
return populate_this_symtab(mte, libref, mte->dynsym, mte->dynstr, mte->dynsym_count);
}
static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
static inline int elf_map_image(struct mt_elf *mte, void **mmap_addr)
{
void *addr;
volatile char *p;
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
if (addr == MAP_FAILED) {
@ -227,39 +229,40 @@ static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
return -1;
}
*image_addr = addr;
/* prefetch */
for(p = addr; (void *)p <= addr + mte->txt_hdr.p_filesz; p += PAGE_SIZE)
*p;
*mmap_addr = addr;
return 0;
}
static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *libref)
{
if (elf_map_image(mte, &libref->image_addr))
if (elf_map_image(mte, &libref->mmap_addr))
return -1;
libref->base = ARCH_ADDR_T(mte->base_addr);
libref->entry = ARCH_ADDR_T(mte->entry_addr);
libref->load_offset = mte->txt_hdr.p_offset;
libref->load_addr = mte->txt_hdr.p_vaddr + mte->bias;
libref->load_size = mte->txt_hdr.p_filesz;
libref->mmap_offset = mte->txt_hdr.p_offset;
libref->mmap_size = mte->loadsize;
libref->txt_vaddr = mte->txt_hdr.p_vaddr + mte->bias;
libref->txt_size = mte->txt_hdr.p_filesz;
libref->bias = mte->bias;
libref->seg_offset = mte->eh_hdr.p_offset;
libref->gp = mte->pltgot;
libref->eh_frame_hdr = mte->eh_hdr.p_offset;
libref->pltgot = mte->pltgot;
libref->key = mte->dyn;
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) {
libref->exidx_data = libref->image_addr + mte->exidx_hdr.p_offset;
libref->exidx_data = libref->mmap_addr + mte->exidx_hdr.p_offset;
libref->exidx_len = mte->exidx_hdr.p_memsz;
}
#endif
if (mte->eh_hdr.p_filesz && mte->dyn) {
if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->image_addr - libref->load_offset + mte->eh_hdr.p_offset)) < 0)
if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->mmap_addr - libref->mmap_offset + mte->eh_hdr.p_offset)) < 0)
return -1;
}
@ -279,6 +282,9 @@ static void close_elf(struct mt_elf *mte)
static int elf_read(struct mt_elf *mte, struct task *task, const char *filename, GElf_Addr bias)
{
unsigned long loadsize = 0;
unsigned long loadbase = ~0;
debug(DEBUG_FUNCTION, "filename=%s", filename);
if (open_elf(mte, task, filename) < 0)
@ -291,15 +297,28 @@ 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->base_addr || mte->base_addr > phdr.p_vaddr + bias)
mte->base_addr = phdr.p_vaddr + bias;
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;
if (loadbase > phdr.p_vaddr)
loadbase = phdr.p_vaddr;
if (loadsize < phdr.p_offset + phdr.p_filesz)
loadsize = phdr.p_offset + phdr.p_filesz;
if ((phdr.p_flags & (PF_X | PF_W)) == PF_X)
mte->txt_hdr = phdr;
break;
case PT_GNU_EH_FRAME:
mte->eh_hdr = phdr;
@ -320,12 +339,17 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
}
}
if (!mte->base_addr) {
fprintf(stderr, "Couldn't determine base address of %s\n", filename);
if (!mte->loadsegs) {
fprintf(stderr, "No loadable segemnts in %s\n", filename);
return -1;
}
debug(DEBUG_FUNCTION, "filename=`%s' load_offset=%#llx addr=%#llx size=%#llx",
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 loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->loadbase, mte->loadsize);
debug(DEBUG_FUNCTION, "filename=`%s' mmap_offset=%#llx addr=%#llx size=%#llx",
filename,
(unsigned long long)mte->txt_hdr.p_offset,
(unsigned long long)mte->txt_hdr.p_vaddr + bias,

View File

@ -33,6 +33,10 @@ struct mt_elf {
int fd;
const char *filename;
Elf *elf;
unsigned int loadsegs;
GElf_Phdr loadseg[4];
unsigned long loadbase;
unsigned long loadsize;
GElf_Ehdr ehdr;
Elf_Data *dynsym;
size_t dynsym_count;

View File

@ -439,9 +439,9 @@ int _report_map(struct task *task, struct library *lib, enum mt_operation op)
size_t len = strlen(libref->filename) + 1;
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
payload->addr = libref->load_addr;
payload->offset = libref->load_offset;
payload->size = libref->load_size;
payload->addr = libref->txt_vaddr;
payload->offset = libref->mmap_offset;
payload->size = libref->txt_size;
payload->bias = libref->bias;
memcpy(payload->filename, libref->filename, len);

View File

@ -330,9 +330,9 @@ int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip)
struct libref *libref = c->libref;
for(p = call_op; p->len; ++p) {
if (likely(ip - ARCH_ADDR_T(libref->load_addr) >= p->off)) {
if (likely(ip - ARCH_ADDR_T(libref->txt_vaddr) >= p->off)) {
unsigned int i;
unsigned char *addr = libref->image_addr + ip - p->off - libref->load_addr;
unsigned char *addr = libref->mmap_addr + ip - p->off - libref->txt_vaddr;
for(i = 0; i < p->len; ++i) {
if (unlikely((addr[i] & p->mask[i]) != p->op[i]))