mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 16:56:41 +08:00
code cleanup
This commit is contained in:
parent
dc6b85bd8b
commit
a6c7ba8fcc
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.9)
|
|||||||
set(MT "mtrace-ng")
|
set(MT "mtrace-ng")
|
||||||
project(${MT} C)
|
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)
|
option(DISABLE_CLIENT "whether to disable client support" OFF)
|
||||||
|
|
||||||
|
|||||||
40
dwarf.c
40
dwarf.c
@ -463,7 +463,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
|||||||
{
|
{
|
||||||
struct dwarf_addr_space *indirect_as = as;
|
struct dwarf_addr_space *indirect_as = as;
|
||||||
arch_addr_t val, initial_addr = *addr;
|
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;
|
int is_64bit = as->is_64bit;
|
||||||
void *tmp_ptr;
|
void *tmp_ptr;
|
||||||
int ret;
|
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 dwarf_cursor *c = &as->cursor;
|
||||||
struct libref *libref = c->libref;
|
struct libref *libref = c->libref;
|
||||||
|
|
||||||
if (*addr < ARCH_ADDR_T(libref->image_addr))
|
if (*addr < ARCH_ADDR_T(libref->mmap_addr))
|
||||||
fatal("invalid access mem: addr %#lx < %p", *addr, libref->image_addr);
|
fatal("invalid access mem: addr %#lx < %p", *addr, libref->mmap_addr);
|
||||||
if (*addr >= ARCH_ADDR_T(libref->image_addr + libref->load_size))
|
if (*addr >= ARCH_ADDR_T(libref->mmap_addr + libref->txt_size))
|
||||||
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->image_addr + libref->load_size);
|
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->mmap_addr + libref->txt_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
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)
|
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)
|
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;
|
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;
|
const struct table_entry *e, *f;
|
||||||
unsigned long lo, hi;
|
unsigned long lo, hi;
|
||||||
|
|
||||||
if (!table_len)
|
if (!fde_count)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
lo = 0;
|
lo = 0;
|
||||||
hi = table_len;
|
hi = fde_count;
|
||||||
f = NULL;
|
f = NULL;
|
||||||
do {
|
do {
|
||||||
unsigned long mid = (lo + hi) / 2;
|
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;
|
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;
|
const struct table_entry *e;
|
||||||
void *fde_addr;
|
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 dwarf_cie_info *dci = &as->cursor.dci;
|
||||||
struct libref *libref = as->cursor.libref;
|
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)) {
|
if (unlikely(!e)) {
|
||||||
/* IP is inside this table's range, but there is no explicit unwind info. */
|
/* 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);
|
debug(DEBUG_DWARF, "no unwind info found for IP %#lx", ip);
|
||||||
return -DWARF_ENOINFO;
|
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))
|
if (unlikely((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0))
|
||||||
return ret;
|
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)
|
if (!as->is_64bit)
|
||||||
dci->start_ip &= 0xffffffff;
|
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;
|
struct libref *libref = c->libref;
|
||||||
int ret;
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1998,7 +1998,9 @@ fail:
|
|||||||
|
|
||||||
int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwarf_eh_frame_hdr *hdr)
|
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;
|
int ret;
|
||||||
struct dwarf_addr_space tmp_as;
|
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);
|
addr = ARCH_ADDR_T(hdr + 1);
|
||||||
|
|
||||||
/* (Optionally) read eh_frame_ptr: */
|
/* read eh_frame_ptr: */
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->eh_frame_ptr_enc, NULL, 0)) < 0)
|
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->eh_frame_ptr_enc, &eh_frame, 0)) < 0)
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
|
|
||||||
/* (Optionally) read fde_count: */
|
/* (Optionally) read fde_count: */
|
||||||
@ -2028,8 +2030,8 @@ int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwar
|
|||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
libref->table_data = (void *)addr;
|
libref->fde_tab = (void *)addr;
|
||||||
libref->table_len = fde_count;
|
libref->fde_count = fde_count;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
30
library.c
30
library.c
@ -66,8 +66,8 @@ void libref_delete(struct libref *libref)
|
|||||||
free(sym);
|
free(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libref->image_addr)
|
if (libref->mmap_addr)
|
||||||
munmap(libref->image_addr, libref->load_size);
|
munmap(libref->mmap_addr, libref->txt_size);
|
||||||
|
|
||||||
free((void *)libref->filename);
|
free((void *)libref->filename);
|
||||||
free(libref);
|
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 library *lib = container_of(it, struct library, list);
|
||||||
struct libref *libref = lib->libref;
|
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))
|
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);
|
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)
|
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)
|
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))
|
if (lib_addr_match(this, addr))
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
if (this->load_addr < addr)
|
if (this->txt_vaddr < addr)
|
||||||
new = &((*new)->rb_left);
|
new = &((*new)->rb_left);
|
||||||
else
|
else
|
||||||
new = &((*new)->rb_right);
|
new = &((*new)->rb_right);
|
||||||
@ -245,7 +245,7 @@ static void insert_lib(struct task *leader, struct library *lib)
|
|||||||
|
|
||||||
parent = *new;
|
parent = *new;
|
||||||
|
|
||||||
if (this->libref->load_addr < lib->libref->load_addr)
|
if (this->libref->txt_vaddr < lib->libref->txt_vaddr)
|
||||||
new = &((*new)->rb_left);
|
new = &((*new)->rb_left);
|
||||||
else
|
else
|
||||||
new = &((*new)->rb_right);
|
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)
|
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);
|
assert(leader->leader == leader);
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ static struct library *_library_add(struct task *leader, struct libref *libref)
|
|||||||
insert_lib(leader, lib);
|
insert_lib(leader, lib);
|
||||||
|
|
||||||
if (unlikely(options.verbose > 1))
|
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;
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
30
library.h
30
library.h
@ -47,8 +47,8 @@ struct libref {
|
|||||||
* they have the same key. */
|
* they have the same key. */
|
||||||
arch_addr_t key;
|
arch_addr_t key;
|
||||||
|
|
||||||
/* Address where the library is mapped. */
|
/* base address assign by the loader */
|
||||||
arch_addr_t base;
|
unsigned long bias;
|
||||||
|
|
||||||
/* Absolute address of the entry point. Useful for main
|
/* Absolute address of the entry point. Useful for main
|
||||||
* binary, though I suppose the value might be useful for the
|
* binary, though I suppose the value might be useful for the
|
||||||
@ -59,19 +59,24 @@ struct libref {
|
|||||||
const char *filename;
|
const char *filename;
|
||||||
|
|
||||||
/* executable segment */
|
/* executable segment */
|
||||||
unsigned long load_offset;
|
unsigned long txt_vaddr;
|
||||||
unsigned long load_addr;
|
unsigned long txt_size;
|
||||||
unsigned long load_size;
|
|
||||||
unsigned long bias;
|
/* loadable segments */
|
||||||
|
unsigned int loadsegs;
|
||||||
|
GElf_Phdr loadseg[4];
|
||||||
|
|
||||||
/* mapped image */
|
/* mapped image */
|
||||||
void *image_addr;
|
void *mmap_addr;
|
||||||
|
unsigned long mmap_offset;
|
||||||
|
unsigned long mmap_size;
|
||||||
|
|
||||||
/* global-pointer */
|
/* global-pointer */
|
||||||
arch_addr_t gp;
|
arch_addr_t pltgot;
|
||||||
unsigned long seg_offset;
|
unsigned long eh_frame_hdr;
|
||||||
void *table_data;
|
void *fde_tab;
|
||||||
unsigned long table_len;
|
unsigned long fde_count;
|
||||||
|
unsigned long eh_frame;
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
|
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
@ -136,5 +141,8 @@ void libref_set_filename(struct libref *libref, const char *new_name);
|
|||||||
/* find library by address */
|
/* find library by address */
|
||||||
struct libref *addr2libref(struct task *leader, arch_addr_t addr);
|
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
|
#endif
|
||||||
|
|
||||||
|
|||||||
66
mtelf.c
66
mtelf.c
@ -47,6 +47,9 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "report.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)
|
static int open_elf(struct mt_elf *mte, struct task *task, const char *filename)
|
||||||
{
|
{
|
||||||
char *cwd;
|
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);
|
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;
|
void *addr;
|
||||||
volatile char *p;
|
|
||||||
|
|
||||||
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
|
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
|
||||||
if (addr == MAP_FAILED) {
|
if (addr == MAP_FAILED) {
|
||||||
@ -227,39 +229,40 @@ static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*image_addr = addr;
|
*mmap_addr = addr;
|
||||||
|
|
||||||
/* prefetch */
|
|
||||||
for(p = addr; (void *)p <= addr + mte->txt_hdr.p_filesz; p += PAGE_SIZE)
|
|
||||||
*p;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *libref)
|
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;
|
return -1;
|
||||||
|
|
||||||
libref->base = ARCH_ADDR_T(mte->base_addr);
|
|
||||||
libref->entry = ARCH_ADDR_T(mte->entry_addr);
|
libref->entry = ARCH_ADDR_T(mte->entry_addr);
|
||||||
libref->load_offset = mte->txt_hdr.p_offset;
|
libref->mmap_offset = mte->txt_hdr.p_offset;
|
||||||
libref->load_addr = mte->txt_hdr.p_vaddr + mte->bias;
|
libref->mmap_size = mte->loadsize;
|
||||||
libref->load_size = mte->txt_hdr.p_filesz;
|
libref->txt_vaddr = mte->txt_hdr.p_vaddr + mte->bias;
|
||||||
|
libref->txt_size = mte->txt_hdr.p_filesz;
|
||||||
libref->bias = mte->bias;
|
libref->bias = mte->bias;
|
||||||
libref->seg_offset = mte->eh_hdr.p_offset;
|
libref->eh_frame_hdr = mte->eh_hdr.p_offset;
|
||||||
libref->gp = mte->pltgot;
|
libref->pltgot = mte->pltgot;
|
||||||
libref->key = mte->dyn;
|
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__
|
#ifdef __arm__
|
||||||
if (mte->exidx_hdr.p_filesz) {
|
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;
|
libref->exidx_len = mte->exidx_hdr.p_memsz;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mte->eh_hdr.p_filesz && mte->dyn) {
|
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;
|
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)
|
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);
|
debug(DEBUG_FUNCTION, "filename=%s", filename);
|
||||||
|
|
||||||
if (open_elf(mte, task, filename) < 0)
|
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->eh_hdr, 0, sizeof(mte->eh_hdr));
|
||||||
memset(&mte->exidx_hdr, 0, sizeof(mte->exidx_hdr));
|
memset(&mte->exidx_hdr, 0, sizeof(mte->exidx_hdr));
|
||||||
|
|
||||||
|
mte->loadsegs = 0;
|
||||||
|
|
||||||
for (i = 0; gelf_getphdr(mte->elf, i, &phdr) != NULL; ++i) {
|
for (i = 0; gelf_getphdr(mte->elf, i, &phdr) != NULL; ++i) {
|
||||||
|
|
||||||
switch (phdr.p_type) {
|
switch (phdr.p_type) {
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
if (!mte->base_addr || mte->base_addr > phdr.p_vaddr + bias)
|
if (mte->loadsegs >= ARRAY_SIZE(mte->loadseg)) {
|
||||||
mte->base_addr = phdr.p_vaddr + bias;
|
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)
|
if ((phdr.p_flags & (PF_X | PF_W)) == PF_X)
|
||||||
mte->txt_hdr = phdr;
|
mte->txt_hdr = phdr;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PT_GNU_EH_FRAME:
|
case PT_GNU_EH_FRAME:
|
||||||
mte->eh_hdr = phdr;
|
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) {
|
if (!mte->loadsegs) {
|
||||||
fprintf(stderr, "Couldn't determine base address of %s\n", filename);
|
fprintf(stderr, "No loadable segemnts in %s\n", filename);
|
||||||
return -1;
|
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,
|
filename,
|
||||||
(unsigned long long)mte->txt_hdr.p_offset,
|
(unsigned long long)mte->txt_hdr.p_offset,
|
||||||
(unsigned long long)mte->txt_hdr.p_vaddr + bias,
|
(unsigned long long)mte->txt_hdr.p_vaddr + bias,
|
||||||
|
|||||||
4
mtelf.h
4
mtelf.h
@ -33,6 +33,10 @@ struct mt_elf {
|
|||||||
int fd;
|
int fd;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
Elf *elf;
|
Elf *elf;
|
||||||
|
unsigned int loadsegs;
|
||||||
|
GElf_Phdr loadseg[4];
|
||||||
|
unsigned long loadbase;
|
||||||
|
unsigned long loadsize;
|
||||||
GElf_Ehdr ehdr;
|
GElf_Ehdr ehdr;
|
||||||
Elf_Data *dynsym;
|
Elf_Data *dynsym;
|
||||||
size_t dynsym_count;
|
size_t dynsym_count;
|
||||||
|
|||||||
6
report.c
6
report.c
@ -439,9 +439,9 @@ int _report_map(struct task *task, struct library *lib, enum mt_operation op)
|
|||||||
size_t len = strlen(libref->filename) + 1;
|
size_t len = strlen(libref->filename) + 1;
|
||||||
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
|
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
|
||||||
|
|
||||||
payload->addr = libref->load_addr;
|
payload->addr = libref->txt_vaddr;
|
||||||
payload->offset = libref->load_offset;
|
payload->offset = libref->mmap_offset;
|
||||||
payload->size = libref->load_size;
|
payload->size = libref->txt_size;
|
||||||
payload->bias = libref->bias;
|
payload->bias = libref->bias;
|
||||||
|
|
||||||
memcpy(payload->filename, libref->filename, len);
|
memcpy(payload->filename, libref->filename, len);
|
||||||
|
|||||||
@ -330,9 +330,9 @@ int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip)
|
|||||||
struct libref *libref = c->libref;
|
struct libref *libref = c->libref;
|
||||||
|
|
||||||
for(p = call_op; p->len; ++p) {
|
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 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) {
|
for(i = 0; i < p->len; ++i) {
|
||||||
if (unlikely((addr[i] & p->mask[i]) != p->op[i]))
|
if (unlikely((addr[i] & p->mask[i]) != p->op[i]))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user