mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 08:46:41 +08:00
fix address spaces
This commit is contained in:
parent
87f73f3220
commit
73a4eca5ce
13
dwarf.c
13
dwarf.c
@ -1996,13 +1996,14 @@ fail:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
arch_addr_t addr;
|
arch_addr_t addr;
|
||||||
arch_addr_t fde_count = 0;
|
arch_addr_t fde_count = 0;
|
||||||
arch_addr_t eh_frame = 0;
|
arch_addr_t eh_frame = 0;
|
||||||
int ret;
|
int ret;
|
||||||
struct dwarf_addr_space tmp_as;
|
struct dwarf_addr_space tmp_as;
|
||||||
|
struct dwarf_eh_frame_hdr *hdr = (struct dwarf_eh_frame_hdr *)(libref->mmap_addr + libref->eh_frame_hdr);
|
||||||
|
|
||||||
memset(&tmp_as, 0, sizeof(tmp_as));
|
memset(&tmp_as, 0, sizeof(tmp_as));
|
||||||
|
|
||||||
@ -2012,21 +2013,27 @@ int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwar
|
|||||||
|
|
||||||
if (hdr->version != DW_EH_VERSION) {
|
if (hdr->version != DW_EH_VERSION) {
|
||||||
debug(DEBUG_DWARF, "exception table has unexpected version %d", hdr->version);
|
debug(DEBUG_DWARF, "exception table has unexpected version %d", hdr->version);
|
||||||
|
abort();
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = ARCH_ADDR_T(hdr + 1);
|
addr = ARCH_ADDR_T(hdr + 1);
|
||||||
|
|
||||||
/* read eh_frame_ptr: */
|
/* read eh_frame_ptr: */
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->eh_frame_ptr_enc, &eh_frame, 0)) < 0)
|
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->eh_frame_ptr_enc, &eh_frame, 0)) < 0) {
|
||||||
|
abort();
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
|
}
|
||||||
|
|
||||||
/* (Optionally) read fde_count: */
|
/* (Optionally) read fde_count: */
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->fde_count_enc, &fde_count, 0)) < 0)
|
if ((ret = dwarf_read_encoded_pointer_local(&tmp_as, &addr, hdr->fde_count_enc, &fde_count, 0)) < 0) {
|
||||||
|
abort();
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
|
}
|
||||||
|
|
||||||
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) {
|
if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) {
|
||||||
debug(DEBUG_DWARF, "unsupported unwind table encoding.");
|
debug(DEBUG_DWARF, "unsupported unwind table encoding.");
|
||||||
|
abort();
|
||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
dwarf.h
2
dwarf.h
@ -115,7 +115,7 @@ int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip);
|
|||||||
|
|
||||||
int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *valp);
|
int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *valp);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
int dwarf_arch_init(struct dwarf_addr_space *as);
|
int dwarf_arch_init(struct dwarf_addr_space *as);
|
||||||
int dwarf_arch_init_unwind(struct dwarf_addr_space *as);
|
int dwarf_arch_init_unwind(struct dwarf_addr_space *as);
|
||||||
|
|||||||
12
library.c
12
library.c
@ -149,14 +149,14 @@ struct library_symbol *library_find_symbol(struct libref *libref, arch_addr_t ad
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct library *library_find_with_key(struct list_head *list, arch_addr_t key)
|
struct library *library_find_by_dyn(struct list_head *list, arch_addr_t dyn)
|
||||||
{
|
{
|
||||||
struct list_head *it;
|
struct list_head *it;
|
||||||
|
|
||||||
list_for_each(it, list) {
|
list_for_each(it, list) {
|
||||||
struct library *lib = container_of(it, struct library, list);
|
struct library *lib = container_of(it, struct library, list);
|
||||||
|
|
||||||
if (lib->libref->key == key)
|
if (lib->libref->dyn == dyn)
|
||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -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->key, leader->pid);
|
debug(DEBUG_FUNCTION, "%s@%#lx pid=%d ", libref->filename, libref->dyn, 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->key, libref->txt_vaddr, libref->txt_vaddr + libref->txt_size);
|
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx\n", leader->pid, libref->filename, libref->dyn, libref->txt_vaddr, libref->txt_vaddr + libref->txt_size);
|
||||||
|
|
||||||
library_delete(leader, lib);
|
library_delete(leader, lib);
|
||||||
}
|
}
|
||||||
@ -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->key, leader->pid);
|
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", libref->filename, libref->dyn, 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->key, libref->txt_vaddr, libref->txt_vaddr + libref->txt_size);
|
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx\n", leader->pid, libref->filename, libref->dyn, libref->txt_vaddr, libref->txt_vaddr + libref->txt_size);
|
||||||
|
|
||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,9 +43,8 @@ struct library_symbol {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct libref {
|
struct libref {
|
||||||
/* Unique key. Two library objects are considered equal, if
|
/* Unique dynamic entry address */
|
||||||
* they have the same key. */
|
arch_addr_t dyn;
|
||||||
arch_addr_t key;
|
|
||||||
|
|
||||||
/* base address assign by the loader */
|
/* base address assign by the loader */
|
||||||
unsigned long bias;
|
unsigned long bias;
|
||||||
@ -127,8 +126,8 @@ const char *library_execname(struct task *leader);
|
|||||||
/* Iterate through list of symbols of library. */
|
/* Iterate through list of symbols of library. */
|
||||||
struct library_symbol *library_find_symbol(struct libref *libref, arch_addr_t addr);
|
struct library_symbol *library_find_symbol(struct libref *libref, arch_addr_t addr);
|
||||||
|
|
||||||
/* find a library with a given key */
|
/* find a library with a given dynamic entry address */
|
||||||
struct library *library_find_with_key(struct list_head *list, arch_addr_t key);
|
struct library *library_find_by_dyn(struct list_head *list, arch_addr_t dyn);
|
||||||
|
|
||||||
/* create a library reference. */
|
/* create a library reference. */
|
||||||
struct libref *libref_new(unsigned int type);
|
struct libref *libref_new(unsigned int type);
|
||||||
|
|||||||
105
mtelf.c
105
mtelf.c
@ -50,6 +50,33 @@
|
|||||||
#define PAGESIZE 4096
|
#define PAGESIZE 4096
|
||||||
#define PAGEALIGN (PAGESIZE - 1)
|
#define PAGEALIGN (PAGESIZE - 1)
|
||||||
|
|
||||||
|
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;
|
||||||
|
GElf_Ehdr ehdr;
|
||||||
|
Elf_Data *dynsym;
|
||||||
|
size_t dynsym_count;
|
||||||
|
const char *dynstr;
|
||||||
|
Elf_Data *symtab;
|
||||||
|
const char *strtab;
|
||||||
|
size_t symtab_count;
|
||||||
|
GElf_Addr bias;
|
||||||
|
GElf_Addr entry_addr;
|
||||||
|
GElf_Addr base_addr;
|
||||||
|
GElf_Addr interp;
|
||||||
|
GElf_Phdr txt_hdr;
|
||||||
|
GElf_Phdr eh_hdr;
|
||||||
|
GElf_Addr dyn;
|
||||||
|
GElf_Phdr exidx_hdr;
|
||||||
|
GElf_Addr pltgot;
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
@ -242,14 +269,13 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li
|
|||||||
libref->entry = ARCH_ADDR_T(mte->entry_addr);
|
libref->entry = ARCH_ADDR_T(mte->entry_addr);
|
||||||
libref->mmap_offset = mte->loadbase;
|
libref->mmap_offset = mte->loadbase;
|
||||||
libref->mmap_size = mte->loadsize;
|
libref->mmap_size = mte->loadsize;
|
||||||
libref->txt_vaddr = mte->txt_hdr.p_vaddr + mte->bias;
|
libref->txt_vaddr = mte->txt_hdr.p_vaddr - mte->vstart + mte->bias;
|
||||||
libref->txt_size = mte->txt_hdr.p_filesz;
|
libref->txt_size = mte->txt_hdr.p_filesz;
|
||||||
libref->txt_offset = mte->txt_hdr.p_offset;
|
libref->txt_offset = mte->txt_hdr.p_offset - mte->loadbase;
|
||||||
libref->bias = mte->bias;
|
libref->bias = mte->bias;
|
||||||
libref->eh_frame_hdr = mte->eh_hdr.p_offset;
|
libref->eh_frame_hdr = mte->eh_hdr.p_offset - mte->loadbase;
|
||||||
libref->pltgot = mte->pltgot;
|
libref->pltgot = mte->pltgot;
|
||||||
libref->key = mte->dyn;
|
libref->dyn = mte->dyn - mte->vstart + mte->bias;
|
||||||
|
|
||||||
libref->loadsegs = mte->loadsegs;
|
libref->loadsegs = mte->loadsegs;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < libref->loadsegs; ++i)
|
for(unsigned int i = 0; i < libref->loadsegs; ++i)
|
||||||
@ -257,13 +283,13 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li
|
|||||||
|
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
if (mte->exidx_hdr.p_filesz) {
|
if (mte->exidx_hdr.p_filesz) {
|
||||||
libref->exidx_data = libref->mmap_addr + mte->exidx_hdr.p_offset;
|
libref->exidx_data = libref->mmap_addr + mte->exidx_hdr.p_offset - mte->loadbase;
|
||||||
libref->exidx_len = mte->exidx_hdr.p_memsz;
|
libref->exidx_len = mte->exidx_hdr.p_filesz;
|
||||||
}
|
}
|
||||||
#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->mmap_addr - libref->txt_offset + mte->eh_hdr.p_offset)) < 0)
|
if (dwarf_get_unwind_table(task, libref) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,13 +304,18 @@ static void close_elf(struct mt_elf *mte)
|
|||||||
if (mte->fd != -1) {
|
if (mte->fd != -1) {
|
||||||
elf_end(mte->elf);
|
elf_end(mte->elf);
|
||||||
close(mte->fd);
|
close(mte->fd);
|
||||||
|
|
||||||
|
mte->fd = -1;
|
||||||
|
mte->filename = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
unsigned long loadsize = 0;
|
unsigned long loadsize = 0;
|
||||||
unsigned long loadbase = ~0;
|
unsigned long loadbase = ~0;
|
||||||
|
unsigned long align;
|
||||||
|
unsigned long vstart;
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "filename=%s", filename);
|
debug(DEBUG_FUNCTION, "filename=%s", filename);
|
||||||
|
|
||||||
@ -301,7 +332,6 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
|||||||
mte->loadsegs = 0;
|
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->loadsegs >= ARRAY_SIZE(mte->loadseg)) {
|
if (mte->loadsegs >= ARRAY_SIZE(mte->loadseg)) {
|
||||||
@ -311,6 +341,15 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
|||||||
|
|
||||||
mte->loadseg[mte->loadsegs++] = phdr;
|
mte->loadseg[mte->loadsegs++] = phdr;
|
||||||
|
|
||||||
|
align = phdr.p_align;
|
||||||
|
if (align)
|
||||||
|
align -= 1;
|
||||||
|
|
||||||
|
vstart = phdr.p_vaddr & ~align;
|
||||||
|
|
||||||
|
if (mte->vstart > vstart)
|
||||||
|
mte->vstart = vstart;
|
||||||
|
|
||||||
if (loadbase > phdr.p_offset)
|
if (loadbase > phdr.p_offset)
|
||||||
loadbase = phdr.p_offset;
|
loadbase = phdr.p_offset;
|
||||||
|
|
||||||
@ -330,10 +369,10 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case PT_INTERP:
|
case PT_INTERP:
|
||||||
mte->interp = phdr.p_vaddr + bias;
|
mte->interp = phdr.p_vaddr;
|
||||||
break;
|
break;
|
||||||
case PT_DYNAMIC:
|
case PT_DYNAMIC:
|
||||||
mte->dyn = phdr.p_vaddr + bias;
|
mte->dyn = phdr.p_vaddr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -348,12 +387,12 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
|||||||
//fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize);
|
//fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize);
|
||||||
mte->loadbase = loadbase & ~PAGEALIGN;
|
mte->loadbase = loadbase & ~PAGEALIGN;
|
||||||
mte->loadsize = (loadsize + (loadbase - mte->loadbase) + PAGEALIGN) & ~PAGEALIGN;
|
mte->loadsize = (loadsize + (loadbase - mte->loadbase) + PAGEALIGN) & ~PAGEALIGN;
|
||||||
//fprintf(stderr, "%s:%d loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->loadbase, mte->loadsize);
|
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",
|
debug(DEBUG_FUNCTION, "filename=`%s' text 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,
|
||||||
(unsigned long long)mte->txt_hdr.p_filesz);
|
(unsigned long long)mte->txt_hdr.p_filesz);
|
||||||
|
|
||||||
for (i = 1; i < mte->ehdr.e_shnum; ++i) {
|
for (i = 1; i < mte->ehdr.e_shnum; ++i) {
|
||||||
@ -394,16 +433,9 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mte->dyn_addr = shdr.sh_addr + bias;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mte->dyn_addr) {
|
|
||||||
fprintf(stderr, "Couldn't find .dynamic section \"%s\"\n", filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mte->dynsym || !mte->dynstr) {
|
if (!mte->dynsym || !mte->dynstr) {
|
||||||
fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n", filename);
|
fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n", filename);
|
||||||
return -1;
|
return -1;
|
||||||
@ -419,11 +451,11 @@ int elf_read_library(struct task *task, struct libref *libref, const char *filen
|
|||||||
|
|
||||||
libref_set_filename(libref, filename);
|
libref_set_filename(libref, filename);
|
||||||
|
|
||||||
if (elf_read(&mte, task, filename, bias) == -1)
|
if (elf_read(&mte, task, filename) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
mte.bias = bias;
|
mte.bias = bias;
|
||||||
mte.entry_addr = mte.ehdr.e_entry + bias;
|
mte.entry_addr = mte.ehdr.e_entry - mte.vstart + bias;
|
||||||
|
|
||||||
ret = elf_lib_init(&mte, task, libref);
|
ret = elf_lib_init(&mte, task, libref);
|
||||||
|
|
||||||
@ -522,9 +554,11 @@ struct libref *elf_read_main_binary(struct task *task, int was_attached)
|
|||||||
|
|
||||||
fname[ret] = 0;
|
fname[ret] = 0;
|
||||||
|
|
||||||
|
free(filename);
|
||||||
|
|
||||||
libref_set_filename(libref, fname);
|
libref_set_filename(libref, fname);
|
||||||
|
|
||||||
if (elf_read(&mte, task, filename, 0) == -1)
|
if (elf_read(&mte, task, fname) == -1)
|
||||||
goto fail3;
|
goto fail3;
|
||||||
|
|
||||||
task->is_64bit = is_64bit(&mte);
|
task->is_64bit = is_64bit(&mte);
|
||||||
@ -534,10 +568,8 @@ struct libref *elf_read_main_binary(struct task *task, int was_attached)
|
|||||||
goto fail3;
|
goto fail3;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(filename);
|
mte.bias = entry - mte.ehdr.e_entry - mte.vstart;
|
||||||
|
mte.entry_addr = entry;
|
||||||
mte.bias = (GElf_Addr) (uintptr_t) entry - mte.ehdr.e_entry;
|
|
||||||
mte.entry_addr = (GElf_Addr) (uintptr_t) entry;
|
|
||||||
|
|
||||||
if (elf_lib_init(&mte, task, libref))
|
if (elf_lib_init(&mte, task, libref))
|
||||||
goto fail3;
|
goto fail3;
|
||||||
@ -553,12 +585,12 @@ struct libref *elf_read_main_binary(struct task *task, int was_attached)
|
|||||||
|
|
||||||
struct mt_elf mte_ld = { };
|
struct mt_elf mte_ld = { };
|
||||||
|
|
||||||
if (copy_str_from_proc(task, ARCH_ADDR_T(mte.bias + mte.interp), fname, sizeof(fname)) == -1) {
|
if (copy_str_from_proc(task, ARCH_ADDR_T(mte.bias + mte.interp - mte.vstart), fname, sizeof(fname)) == -1) {
|
||||||
fprintf(stderr, "fatal error: cannot get loader name for pid=%d\n", task->pid);
|
fprintf(stderr, "fatal error: cannot get loader name for pid=%d\n", task->pid);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elf_read(&mte_ld, task, fname, (GElf_Addr)base)) {
|
if (!elf_read(&mte_ld, task, fname)) {
|
||||||
struct libref *libref;
|
struct libref *libref;
|
||||||
|
|
||||||
libref = libref_new(LIBTYPE_LOADER);
|
libref = libref_new(LIBTYPE_LOADER);
|
||||||
@ -567,14 +599,14 @@ struct libref *elf_read_main_binary(struct task *task, int was_attached)
|
|||||||
|
|
||||||
libref_set_filename(libref, fname);
|
libref_set_filename(libref, fname);
|
||||||
|
|
||||||
mte_ld.bias = (GElf_Addr)base;
|
mte_ld.bias = base;
|
||||||
mte_ld.entry_addr = mte_ld.ehdr.e_entry + (GElf_Addr)base;
|
mte_ld.entry_addr = base + mte_ld.ehdr.e_entry - mte.vstart;
|
||||||
|
|
||||||
ret = elf_lib_init(&mte_ld, task, libref);
|
ret = elf_lib_init(&mte_ld, task, libref);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
library_add(task, libref);
|
library_add(task, libref);
|
||||||
|
|
||||||
if (linkmap_init(task, ARCH_ADDR_T(mte.bias + mte.dyn))) {
|
if (linkmap_init(task, ARCH_ADDR_T(mte.bias + mte.dyn - mte.vstart))) {
|
||||||
arch_addr_t addr = find_solib_break(&mte_ld);
|
arch_addr_t addr = find_solib_break(&mte_ld);
|
||||||
if (!addr)
|
if (!addr)
|
||||||
addr = ARCH_ADDR_T(entry);
|
addr = ARCH_ADDR_T(entry);
|
||||||
@ -589,7 +621,7 @@ struct libref *elf_read_main_binary(struct task *task, int was_attached)
|
|||||||
else {
|
else {
|
||||||
entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit;
|
entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit;
|
||||||
entry_bp->breakpoint.locked = 1;
|
entry_bp->breakpoint.locked = 1;
|
||||||
entry_bp->dyn_addr = ARCH_ADDR_T(mte.bias + mte.dyn);
|
entry_bp->dyn_addr = ARCH_ADDR_T(mte.bias + mte.dyn - mte.vstart);
|
||||||
|
|
||||||
breakpoint_enable(task, &entry_bp->breakpoint);
|
breakpoint_enable(task, &entry_bp->breakpoint);
|
||||||
}
|
}
|
||||||
@ -625,3 +657,8 @@ fail1:
|
|||||||
return libref;
|
return libref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mte_cmp_machine(struct mt_elf *mte, Elf64_Half type)
|
||||||
|
{
|
||||||
|
return mte->ehdr.e_machine == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
29
mtelf.h
29
mtelf.h
@ -29,37 +29,12 @@
|
|||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
|
|
||||||
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;
|
|
||||||
const char *dynstr;
|
|
||||||
Elf_Data *symtab;
|
|
||||||
const char *strtab;
|
|
||||||
size_t symtab_count;
|
|
||||||
GElf_Addr dyn_addr;
|
|
||||||
GElf_Addr bias;
|
|
||||||
GElf_Addr entry_addr;
|
|
||||||
GElf_Addr base_addr;
|
|
||||||
GElf_Addr interp;
|
|
||||||
GElf_Phdr txt_hdr;
|
|
||||||
GElf_Phdr eh_hdr;
|
|
||||||
GElf_Addr dyn;
|
|
||||||
GElf_Phdr exidx_hdr;
|
|
||||||
GElf_Addr pltgot;
|
|
||||||
};
|
|
||||||
|
|
||||||
int elf_read_library(struct task *task, struct libref *libref, const char *filename, GElf_Addr bias);
|
int elf_read_library(struct task *task, struct libref *libref, const char *filename, GElf_Addr bias);
|
||||||
|
|
||||||
/* Create a library object representing the main binary. */
|
/* Create a library object representing the main binary. */
|
||||||
struct libref *elf_read_main_binary(struct task *task, int was_attached);
|
struct libref *elf_read_main_binary(struct task *task, int was_attached);
|
||||||
|
|
||||||
|
int mte_cmp_machine(struct mt_elf *mte, Elf64_Half type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,6 @@
|
|||||||
|
|
||||||
int is_64bit(struct mt_elf *mte)
|
int is_64bit(struct mt_elf *mte)
|
||||||
{
|
{
|
||||||
return mte->ehdr.e_machine != EM_PPC;
|
return !mte_cmp_machine(mte, EM_PPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -402,7 +402,7 @@ static void linkmap_add(struct task *task, struct lt_r_debug_64 *dbg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do we have that library already? */
|
/* Do we have that library already? */
|
||||||
lib = library_find_with_key(&task->libraries_list, ARCH_ADDR_T(rlm.l_ld));
|
lib = library_find_by_dyn(&task->libraries_list, ARCH_ADDR_T(rlm.l_ld));
|
||||||
if (lib)
|
if (lib)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -468,7 +468,7 @@ static void linkmap_del(struct task *task, struct lt_r_debug_64 *dbg)
|
|||||||
|
|
||||||
addr = ARCH_ADDR_T(rlm.l_next);
|
addr = ARCH_ADDR_T(rlm.l_next);
|
||||||
|
|
||||||
lib = library_find_with_key(&tmp_list, ARCH_ADDR_T(rlm.l_ld));
|
lib = library_find_by_dyn(&tmp_list, ARCH_ADDR_T(rlm.l_ld));
|
||||||
if (lib)
|
if (lib)
|
||||||
list_move_tail(&lib->list, &task->libraries_list);
|
list_move_tail(&lib->list, &task->libraries_list);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -203,7 +203,7 @@ int reset_all_hw_bp(struct task *task)
|
|||||||
|
|
||||||
int is_64bit(struct mt_elf *mte)
|
int is_64bit(struct mt_elf *mte)
|
||||||
{
|
{
|
||||||
return mte->ehdr.e_machine != EM_386;
|
return !mte_cmp_machine(mte, EM_386);
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_task_init(struct task *task)
|
int arch_task_init(struct task *task)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user