format/elf: fix paddr2vaddr and vaddr2paddr conversions

This commit is contained in:
Riccardo Schirone 2015-08-25 00:53:49 +02:00 committed by pancake
parent 9aafea2e23
commit 18eaf1c8c5
6 changed files with 105 additions and 85 deletions

View File

@ -1150,6 +1150,10 @@ R_API int r_bin_list(RBin *bin) {
return R_FALSE;
}
R_API ut64 r_binfile_get_baddr (RBinFile *binfile) {
return binfile && binfile->o ? binfile->o->baddr : 0LL;
}
R_API ut64 r_bin_get_baddr(RBin *bin) {
RBinObject *o = r_bin_cur_object (bin);
if (o) return o->baddr;

View File

@ -281,7 +281,7 @@ static int Elf_(r_bin_elf_init_dynamic_section) (struct Elf_(r_bin_elf_obj_t) *b
}
for (i = 0; i < entries; i++) {
switch (dyn[i].d_tag){
case DT_STRTAB: strtabaddr = dyn[i].d_un.d_ptr - bin->baddr; break;
case DT_STRTAB: strtabaddr = Elf_(r_bin_elf_v2p) (bin, dyn[i].d_un.d_ptr); break;
case DT_STRSZ: strsize = dyn[i].d_un.d_val; break;
default: break;
}
@ -572,8 +572,12 @@ ut64 Elf_(r_bin_elf_get_init_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
return 0;
}
if (buf[0] == 0x68) { // push // x86 only
ut64 addr;
memmove (buf, buf+1, 4);
return (ut64)((int)(buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24)))-bin->baddr;
addr = (ut64)((int)(buf[0] + (buf[1] << 8) +
(buf[2] << 16) + (buf[3] << 24)));
return Elf_(r_bin_elf_v2p) (bin, addr);
}
return 0;
}
@ -588,9 +592,12 @@ ut64 Elf_(r_bin_elf_get_fini_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
return 0;
}
if (*buf == 0x68) { // push // x86/32 only
ut64 addr;
memmove (buf, buf+1, 4);
return (ut64)((int)(buf[0]+(buf[1]<<8)+
(buf[2]<<16)+(buf[3]<<24)))-bin->baddr;
addr = (ut64)((int)(buf[0] + (buf[1] << 8) +
(buf[2] << 16) + (buf[3] << 24)));
return Elf_(r_bin_elf_v2p) (bin, addr);
}
return 0;
}
@ -608,9 +615,7 @@ ut64 Elf_(r_bin_elf_get_entry_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
entry = Elf_(r_bin_elf_get_section_offset)(bin, ".init");
if (entry != UT64_MAX) return entry;
}
if (bin->ehdr.e_entry < bin->baddr)
return bin->ehdr.e_entry;
return bin->ehdr.e_entry - bin->baddr;
return Elf_(r_bin_elf_v2p) (bin, bin->ehdr.e_entry);
}
ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
@ -637,8 +642,9 @@ ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
0x00012000 00b0a0e3 mov fp, 0
0x00012004 00e0a0e3 mov lr, 0
*/
if (*addr > text && *addr < (text_end))
return *addr - bin->baddr;
if (*addr > text && *addr < (text_end)) {
return Elf_(r_bin_elf_v2p) (bin, *addr);
}
}
// MIPS
@ -669,7 +675,7 @@ ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
if ((instr & 0xffff0000) == 0x8f840000) { // lw a0, offset(gp)
const short delta = instr & 0x0000ffff;
r_buf_read_at (bin->b, /* got_entry_offset = */ gp + delta, buf, 4);
return (/* main_vaddr = */ BUF_U32(0)) - bin->baddr;
return Elf_(r_bin_elf_v2p) (bin, BUF_U32(0));
}
}
@ -680,8 +686,10 @@ ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
}
// ARM
if (!memcmp (buf, "\x24\xc0\x9f\xe5\x00\xb0\xa0\xe3", 8)) {
return (ut64)((int)(buf[48+0]+(buf[48+1]<<8)+
(buf[48+2]<<16)+(buf[48+3]<<24)))-bin->baddr;
ut64 addr = (ut64)((int)(buf[48] +
(buf[48 + 1] << 8) + (buf[48 + 2] << 16) +
(buf[48 + 3] << 24)));
return Elf_(r_bin_elf_v2p) (bin, addr);
}
// X86-PIE
if (buf[0x1d] == 0x48 && buf[0x1e] == 0x8b) {
@ -704,17 +712,22 @@ ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
}
// X86-NONPIE
#if R_BIN_ELF64
if (!memcmp (buf, "\x49\x89\xd9", 3) && buf[156] == 0xe8) {// openbsd
return (ut64)((int)(buf[157+0]+(buf[157+1]<<8)+
(buf[157+2]<<16)+(buf[157+3]<<24)))+ entry + 156 + 5;
if (!memcmp (buf, "\x49\x89\xd9", 3) && buf[156] == 0xe8) { // openbsd
return (ut64)((int)(buf[157 + 0] + (buf[157 + 1] << 8) +
(buf[157 + 2] << 16) + (buf[157 + 3] << 24))) +
entry + 156 + 5;
}
if (!memcmp (buf+29, "\x48\xc7\xc7", 3)) { // linux
ut64 addr = (ut64)((int)(buf[29 + 3] + (buf[29 + 4] << 8) +
(buf[29 + 5] << 16) + (buf[29 + 6] << 24))) ;
return Elf_(r_bin_elf_v2p) (bin, addr);
}
if (!memcmp (buf+29, "\x48\xc7\xc7", 3)) // linux
return (ut64)((int)(buf[29+3]+(buf[29+4]<<8)+
(buf[29+5]<<16)+(buf[29+6]<<24)))-bin->baddr;
#else
if (buf[23] == '\x68')
return (ut64)((int)(buf[23+1]+(buf[23+2]<<8)+
(buf[23+3]<<16)+(buf[23+4]<<24)))-bin->baddr;
if (buf[23] == '\x68') {
ut64 addr = (ut64)((int)(buf[23 + 1] + (buf[23 + 2] << 8) +
(buf[23 + 3] << 16) + (buf[23 + 4] << 24)));
return Elf_(r_bin_elf_v2p) (bin, addr);
}
#endif
/* linux64 pie main */
if (buf[29] == 0x48 && buf[30] == 0x8d) { // lea rdi, qword [rip-0x21c4]
@ -1172,7 +1185,7 @@ struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t
1, bin->shdr[i].sh_offset + j);
ret[rel].rva = ret[rel].offset + section_text_offset;
ret[rel].sto = section_text_offset;
ret[rel].offset = ret[rel].offset - bin->baddr;
ret[rel].offset = Elf_(r_bin_elf_v2p) (bin, ret[rel].offset);
ret[rel].last = 0;
if (res < 0)
break;
@ -1185,7 +1198,7 @@ struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t
res = Elf_(r_bin_elf_read_reloc) (bin, &ret[rel],
0, bin->shdr[i].sh_offset + j);
ret[rel].rva = ret[rel].offset;
ret[rel].offset = ret[rel].offset - bin->baddr;
ret[rel].offset = Elf_(r_bin_elf_v2p) (bin, ret[rel].offset);
ret[rel].last = 0;
if (res < 0)
break;
@ -1323,7 +1336,7 @@ static struct r_bin_elf_symbol_t* get_symbols_from_phdr (struct Elf_(r_bin_elf_o
for (j = 0; j < bin->dyn_entries; j++) {
if (bin->dyn_buf[j].d_tag == DT_SYMTAB){
addr_sym_table = bin->dyn_buf[j].d_un.d_ptr - bin->baddr;
addr_sym_table = Elf_(r_bin_elf_v2p) (bin, bin->dyn_buf[j].d_un.d_ptr);
break;
}
}
@ -1385,7 +1398,7 @@ static struct r_bin_elf_symbol_t* get_symbols_from_phdr (struct Elf_(r_bin_elf_o
// is not a symbol so is the end
goto done;
ret[ret_ctr].offset = (toffset >= bin->baddr ? toffset -= bin->baddr : toffset);
ret[ret_ctr].offset = Elf_(r_bin_elf_v2p) (bin, toffset);
ret[ret_ctr].size = tsize;
{
int rest = R_MIN (ELF_STRING_LENGTH,128)-1;
@ -1605,7 +1618,7 @@ if (
}
}
#endif
ret[ret_ctr].offset = (toffset >= bin->baddr ? toffset -= bin->baddr : toffset);
ret[ret_ctr].offset = Elf_(r_bin_elf_v2p) (bin, toffset);
if (section_text)
ret[ret_ctr].offset += section_text_offset;
ret[ret_ctr].size = tsize;
@ -1736,3 +1749,47 @@ struct Elf_(r_bin_elf_obj_t)* Elf_(r_bin_elf_new_buf)(struct r_buf_t *buf) {
return Elf_(r_bin_elf_free) (bin);
return bin;
}
static int is_in_pphdr (Elf_(Phdr) *p, ut64 addr) {
return addr >= p->p_offset && addr < p->p_offset + p->p_memsz;
}
static int is_in_vphdr (Elf_(Phdr) *p, ut64 addr) {
return addr >= p->p_vaddr && addr < p->p_vaddr + p->p_memsz;
}
/* converts a physical address to the virtual address, looking
* at the program headers in the binary bin */
ut64 Elf_(r_bin_elf_p2v) (struct Elf_(r_bin_elf_obj_t) *bin, ut64 paddr) {
int i;
if (!bin) return paddr;
for (i = 0; i < bin->ehdr.e_phnum; ++i) {
Elf_(Phdr) *p = &bin->phdr[i];
if (!p) break;
if (p->p_type == PT_LOAD && is_in_pphdr (p, paddr)) {
return p->p_vaddr + paddr - p->p_offset;
}
}
return paddr;
}
/* converts a virtual address to the relative physical address, looking
* at the program headers in the binary bin */
ut64 Elf_(r_bin_elf_v2p) (struct Elf_(r_bin_elf_obj_t) *bin, ut64 vaddr) {
int i;
if (!bin) return vaddr;
for (i = 0; i < bin->ehdr.e_phnum; ++i) {
Elf_(Phdr) *p = &bin->phdr[i];
if (!p) break;
if (p->p_type == PT_LOAD && is_in_vphdr (p, vaddr)) {
return p->p_offset + vaddr - p->p_vaddr;
}
}
return vaddr;
}

View File

@ -101,6 +101,8 @@ int Elf_(r_bin_elf_has_va)(struct Elf_(r_bin_elf_obj_t) *bin);
ut64 Elf_(r_bin_elf_get_section_addr)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name);
ut64 Elf_(r_bin_elf_get_section_offset)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name);
ut64 Elf_(r_bin_elf_get_baddr)(struct Elf_(r_bin_elf_obj_t) *bin);
ut64 Elf_(r_bin_elf_p2v)(struct Elf_(r_bin_elf_obj_t) *bin, ut64 paddr);
ut64 Elf_(r_bin_elf_v2p)(struct Elf_(r_bin_elf_obj_t) *bin, ut64 vaddr);
ut64 Elf_(r_bin_elf_get_boffset)(struct Elf_(r_bin_elf_obj_t) *bin);
ut64 Elf_(r_bin_elf_get_entry_offset)(struct Elf_(r_bin_elf_obj_t) *bin);
ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin);

View File

@ -92,7 +92,7 @@ static RBinAddr* binsym(RBinFile *arch, int sym) {
}
if (addr && (ret = R_NEW0 (RBinAddr))) {
ret->paddr = addr;
ret->vaddr = obj->baddr + addr;
ret->vaddr = Elf_(r_bin_elf_p2v) (obj, addr);
}
return ret;
}
@ -112,7 +112,7 @@ static RList* entries(RBinFile *arch) {
if (!(ptr = R_NEW0 (RBinAddr)))
return ret;
ptr->paddr = Elf_(r_bin_elf_get_entry_offset) (arch->o->bin_obj);
ptr->vaddr = obj->baddr + ptr->paddr;
ptr->vaddr = Elf_(r_bin_elf_p2v) (arch->o->bin_obj, ptr->paddr);
r_list_append (ret, ptr);
return ret;
}
@ -167,7 +167,6 @@ static RList* sections(RBinFile *arch) {
ut64 align = phdr[i].p_align;
if (!align) align = 0x1000;
memsz = (int)(size_t)R_PTR_ALIGN_NEXT ((size_t)memsz, (int)align);
//vaddr -= obj->baddr; // yeah
if (!(ptr = R_NEW0 (RBinSection)))
return ret;
sprintf (ptr->name, "phdr%d", n);
@ -221,52 +220,26 @@ static RList* sections(RBinFile *arch) {
static RBinInfo* info(RBinFile *arch);
static RList* symbols(RBinFile *arch) {
int i, bin_bits;
struct Elf_(r_bin_elf_obj_t) *bin;
struct r_bin_elf_symbol_t *symbol = NULL;
RBinSymbol *ptr = NULL;
RList *ret = NULL;
ut64 base = 0;
if (!arch || !arch->o || !arch->o->bin_obj)
return NULL;
bin = arch->o->bin_obj;
// has_va = Elf_(r_bin_elf_has_va) (bin);
// if (!has_va) {
if (arch && arch->o && arch->o->baddr==0LL) {
// find base address for non-linked object (.o) //
if (arch->o->sections) {
RBinSection *s;
RListIter *iter;
r_list_foreach (arch->o->sections, iter, s) {
if (s->srwx & R_BIN_SCN_EXECUTABLE) {
base = s->paddr;
break;
}
}
}
}
int i, bin_bits;
if (!(ret = r_list_new ()))
return NULL;
if (!arch || !arch->o || !arch->o->bin_obj) return NULL;
bin = arch->o->bin_obj;
ret = r_list_new ();
if (!ret) return NULL;
ret->free = free;
bin_bits = Elf_(r_bin_elf_get_bits) (arch->o->bin_obj);
if (!(symbol = Elf_(r_bin_elf_get_symbols) (arch->o->bin_obj, R_BIN_ELF_SYMBOLS)))
return ret;
for (i = 0; !symbol[i].last; i++) {
ut64 vaddr = r_bin_get_vaddr (NULL, //arch->o->bin_obj,
arch->o->baddr, symbol[i].offset,
symbol[i].offset+arch->o->baddr);
ut64 paddr = symbol[i].offset;
if (vaddr == UT64_MAX) {
ut64 ba = baddr (arch);
if (ba) {
vaddr = paddr + ba;
} else {
// no base address, probably an object file
vaddr = paddr + base;
}
}
ut64 vaddr = Elf_(r_bin_elf_p2v) (bin, paddr);
if (!(ptr = R_NEW0 (RBinSymbol)))
break;
strncpy (ptr->name, symbol[i].name, R_BIN_SIZEOF_STRINGS);
@ -299,17 +272,8 @@ static RList* symbols(RBinFile *arch) {
return ret;
for (i = 0; !symbol[i].last; i++) {
ut64 paddr = symbol[i].offset;
ut64 vaddr = r_bin_get_vaddr (NULL, baddr (arch), paddr,
symbol[i].offset+arch->o->baddr);
if (vaddr == UT64_MAX) {
ut64 ba = baddr (arch);
if (ba) {
vaddr = paddr + ba;
} else {
// no base address, probably an object file
vaddr = paddr + base;
}
}
ut64 vaddr = Elf_(r_bin_elf_p2v) (bin, paddr);
if (!symbol[i].size)
continue;
if (!(ptr = R_NEW0 (RBinSymbol)))
@ -755,15 +719,6 @@ static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data,
return buf;
}
static ut64 get_elf_vaddr (RBinFile *arch, ut64 ba, ut64 pa, ut64 va) {
//NOTE(aaSSfxxx): since RVA is vaddr - "official" image base, we just need to add imagebase to vaddr
// WHY? NO NEED TO HAVE PLUGIN SPECIFIC VADDR
struct Elf_(r_bin_elf_obj_t)* obj = arch->o->bin_obj;
return obj->baddr - obj->boffset + va - ba;
}
RBinPlugin r_bin_plugin_elf = {
.name = "elf",
.desc = "ELF format r_bin plugin",
@ -793,7 +748,7 @@ RBinPlugin r_bin_plugin_elf = {
.dbginfo = &r_bin_dbginfo_elf,
.create = &create,
.write = &r_bin_write_elf,
.get_vaddr = &get_elf_vaddr,
.get_vaddr = NULL,
};
#ifndef CORELIB

View File

@ -647,7 +647,8 @@ static int bin_entry (RCore *r, int mode, ut64 baddr, ut64 laddr, int va) {
r_cons_printf ("f entry%i 1 @ 0x%08"PFMT64x"\n", i, vaddr);
r_cons_printf ("s entry%i\n", i);
} else {
if (!baddr) {
/* XXX: just a temporary workaround */
if (!baddr && vaddr > paddr) {
baddr = vaddr - paddr;
}
r_cons_printf (

View File

@ -404,6 +404,7 @@ R_API int r_bin_file_ref_by_bind (RBinBind * binb);
R_API int r_bin_file_ref (RBin *bin, RBinFile * a);
R_API int r_bin_list(RBin *bin);
R_API RBinObject *r_bin_get_object(RBin *bin);
R_API ut64 r_binfile_get_baddr (RBinFile *binfile);
R_API ut64 r_bin_get_baddr(RBin *bin);
R_API void r_bin_set_baddr(RBin *bin, ut64 baddr);
R_API ut64 r_bin_get_boffset(RBin *bin);