Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Fix R_ARM_CALL relocs #22877

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions libr/bin/format/elf/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,9 @@ static ut64 get_import_addr_arm(ELFOBJ *eo, RBinElfReloc *rel) {
const ut64 pos = COMPUTE_PLTGOT_POSITION (rel, got_addr, 0x3);

switch (rel->type) {
case R_ARM_CALL:
// never reached
break;
case R_ARM_JUMP_SLOT:
plt_addr += pos * 12 + 20;
if (plt_addr & 1) {
Expand Down Expand Up @@ -5272,15 +5275,23 @@ static bool reloc_fill_local_address(ELFOBJ *eo) {
GotPltBounds ri = {0};
RBinElfSection *s;

ut64 di0 = UT64_MAX;
ut64 di1 = UT64_MAX;
// find got/plt section bounadries
r_vector_foreach (&eo->g_sections, s) {
if (!strcmp (s->name, ".got")) {
ri.got = true;
ri.got_min = s->offset;
ri.got_max = s->offset + s->size;
ri.got_va = s->rva;
}
if (!strcmp (s->name, ".plt")) {
#if 1
} else if (!strcmp (s->name, ".debug_info")) {
// di0 = s->rva;
// di1 = s->rva + s->size;
di0 = s->offset;
di1 = s->offset + s->size;
#endif
} else if (!strcmp (s->name, ".plt")) {
ri.plt_min = s->offset;
ri.plt_max = s->offset + s->size;
ri.plt_va = s->rva;
Expand All @@ -5291,7 +5302,9 @@ static bool reloc_fill_local_address(ELFOBJ *eo) {
}
}
if (!ri.got || !ri.plt) {
return false;
if (di0 == UT64_MAX) {
return false;
}
}
ut64 baddr = eo->user_baddr; // 0x10000;
if (baddr == UT64_MAX) {
Expand All @@ -5301,13 +5314,22 @@ static bool reloc_fill_local_address(ELFOBJ *eo) {
// resolve got and plt
r_vector_foreach (&eo->g_relocs, reloc) {
const ut64 raddr = reloc->offset;
if (!ri.got && !ri.plt) {
index++;
ut64 ra = baddr + di0 + (index * 4);
ra += 685182;
reloc->addend = 0; // index;
// reloc->rva = ra + baddr; // address to patch
reloc->laddr = ra;
continue;
}
if (raddr < ri.got_min || raddr >= ri.got_max) {
continue;
}
ut64 rvaddr = reloc->offset; // rva (eo, reloc->offset, reloc->rva);
ut64 pltptr = 0; // relocated buf tells the section to look at
#if R_BIN_ELF64
r_buf_read_at (eo->b, rvaddr, (ut8*)&pltptr, 8);
r_buf_read_at (eo->b, rvaddr, (ut8*)&pltptr, 8);
#else
ut32 n32 = 0;
r_buf_read_at (eo->b, rvaddr, (ut8*)&n32, 4);
Expand All @@ -5331,7 +5353,6 @@ static bool reloc_fill_local_address(ELFOBJ *eo) {
#else
index++;
#endif
// TODO: if (reloc->type == 22) { // on arm! // extra check of bounds
ut64 naddr = baddr + pltptr + (index * 12) + 0x20;
if (reloc->type == 1026) {
naddr = baddr + pltptr + (index * 16) + 64 - 16;
Expand All @@ -5342,6 +5363,10 @@ static bool reloc_fill_local_address(ELFOBJ *eo) {
} else {
R_LOG_DEBUG ("Cannot resolve reloc reference");
}
} else {
index++;
ut64 naddr = baddr + (index * 12) + 0x20;
reloc->laddr = naddr;
}
}
}
Expand Down
88 changes: 71 additions & 17 deletions libr/bin/p/bin_elf.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) {
r_return_val_if_fail (eo && rel, NULL);
ut64 B = eo->baddr;
ut64 P = rel->rva; // rva has taken baddr into account
ut64 G = got_addr;
RBinReloc *r = R_NEW0 (RBinReloc);
if (!r) {
return NULL;
Expand Down Expand Up @@ -509,8 +510,8 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) {
case R_386_GLOB_DAT: SET(32); break;
case R_386_JMP_SLOT: SET(32); break;
case R_386_RELATIVE: ADD(32, B); break;
case R_386_GOTOFF: ADD(32, -(st64)got_addr); break;
case R_386_GOTPC: ADD(32, got_addr - P); break;
case R_386_GOTOFF: ADD(32, -(st64)G); break;
case R_386_GOTPC: ADD(32, G- P); break;
case R_386_16: ADD(16, 0); break;
case R_386_PC16: ADD(16,-(st64)P); break;
case R_386_8: ADD(8, 0); break;
Expand All @@ -529,7 +530,7 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) {
case R_X86_64_NONE: break; // malloc then free. meh. then again, there's no real world use for _NONE.
case R_X86_64_64: ADD(64, 0); break;
case R_X86_64_PLT32: ADD(32,-(st64)P /* +L */); break;
case R_X86_64_GOT32: ADD(32, got_addr); break;
case R_X86_64_GOT32: ADD(32, G); break;
case R_X86_64_PC32: ADD(32,-(st64)P); break;
case R_X86_64_GLOB_DAT: r->vaddr -= rel->sto; SET(64); break;
case R_X86_64_JUMP_SLOT: r->vaddr -= rel->sto; SET(64); break;
Expand Down Expand Up @@ -563,9 +564,25 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) {
case R_ARM_JUMP_SLOT: ADD(32, 0); break;
case R_ARM_COPY: ADD(32, 0); break; // copy symbol at runtime
case R_ARM_RELATIVE: ADD(32, B); break;
case R_ARM_GOTOFF: ADD(32,-(st64)got_addr); break;
case R_ARM_GOTPC: ADD(32, got_addr - P); break;
case R_ARM_CALL: ADD(24, -(st64)P); break;
case R_ARM_GOTOFF: ADD(32,-(st64)G); break;
case R_ARM_GOTPC: ADD(32, G - P); break;
case R_ARM_CALL: // ADD(24, got_addr -P);
r->type = R_BIN_RELOC_24;
if (G == UT64_MAX) {
r->addend = B-P; // 171295;
eprintf( "jeje 0x%x 0x%x\n", P, got_addr);
} else {
eprintf( "joje 0x%x 0x%x\n", P, got_addr);
r->addend = got_addr -P;
}
// r->addend = 0x08004dad;
r->addend = 0x00004dad;
// rel->laddr += 685182;
rel->addend = r->addend + rel->laddr;
// rel->addend = 685182 /4; // 171295
r->additive = DT_RELA;
return r;
break;
case R_ARM_JUMP24: ADD(24, -(st64)P); break;
case R_ARM_THM_JUMP24: ADD(24, -(st64)P); break;
case R_ARM_PREL31: ADD(32, -(st64)P); break;
Expand Down Expand Up @@ -729,7 +746,13 @@ static RList* relocs(RBinFile *bf) {
if (got_addr == UT64_MAX && eo->ehdr.e_type == ET_REL) {
got_addr = Elf_(get_section_addr) (eo, ".got.r2");
}

#if 0
if (got_addr == UT64_MAX) {
// XXX
got_addr = Elf_(get_section_addr) (eo, ".debug_info");
// got_addr = 0x08001e60;
}
#endif
const RVector *relocs = Elf_(load_relocs) (eo);
if (!relocs) {
return ret;
Expand All @@ -744,9 +767,9 @@ static RList* relocs(RBinFile *bf) {
r_vector_foreach (relocs, reloc) {
RBinReloc *already_inserted = ht_up_find (reloc_ht, reloc->rva, NULL);
if (already_inserted) {
R_LOG_DEBUG ("Reloc already inserted at 0x%08"PFMT64x, reloc->rva);
continue;
}

RBinReloc *ptr = reloc_convert (eo, reloc, got_addr);
if (ptr && ptr->paddr != UT64_MAX) {
r_list_append (ret, ptr);
Expand Down Expand Up @@ -778,22 +801,53 @@ static void _patch_reloc(ELFOBJ *bo, ut16 e_machine, RIOBind *iob, RBinElfReloc
case EM_S390:
switch (rel->type) {
case R_390_GLOB_DAT: // globals
iob->overlay_write_at (iob->io, rel->rva, buf, 8);
break;
case R_390_RELATIVE:
case R_390_RELATIVE: // pic
iob->overlay_write_at (iob->io, rel->rva, buf, 8);
break;
}
break;
case EM_ARM:
if (!rel->sym && rel->mode == DT_REL) {
if (rel->type == R_ARM_CALL) {
eprintf ("one\n");
// read original bytes of the "bl" instruction
iob->read_at (iob->io, rel->rva, buf, 4);
V = r_read_ble32 (buf, bo->endian);
V = r_read_le32 (buf);

int delta = A;
// if (rel->rva == 0x08001ec8) {
eprintf ("DELTA = %llx\n",A);
// }
delta &= 0xfffff;
#if 0
if (rel->rva == 0x08001ec8) {
eprintf ("RAW DELTA 0x%llx -> %llx\n", P, delta);
eprintf ("V 0x%llx + %d\n", P , delta);
}
// delta = 685182 / 4;
#endif
#if 1
V+=delta;
V &= 0xffffff;
V |= (0xeb << 24);
#endif
// eprintf ("DELTA %x %x %x = %d\n", B ,P, L, delta);
// V += (1 << 24); // (rel->rva - (S/2) / 4);
r_write_le32 (buf, V);
if (rel->rva == 0x08001ec8) {
eprintf ("delta = %d\n", delta);
}
iob->overlay_write_at (iob->io, rel->rva, buf, 4);
// ignored
} else {
V = S + A;
if (!rel->sym && rel->mode == DT_REL) {
iob->read_at (iob->io, rel->rva, buf, 4);
V = r_read_ble32 (buf, bo->endian);
} else {
V = S + A;
}
r_write_le32 (buf, V);
iob->overlay_write_at (iob->io, rel->rva, buf, 4);
}
r_write_le32 (buf, V);
iob->overlay_write_at (iob->io, rel->rva, buf, 4);
break;
case EM_AARCH64:
V = S + A;
Expand Down Expand Up @@ -946,7 +1000,7 @@ static void _patch_reloc(ELFOBJ *bo, ut16 e_machine, RIOBind *iob, RBinElfReloc
V = B + A;
break;
default:
//eprintf ("relocation %d not handle at this time\n", rel->type);
R_LOG_WARN ("relocation %d not handle at this time", rel->type);
break;
}
switch (word) {
Expand Down
Loading