Skip to content

Commit

Permalink
WIP: Fix R_ARM_CALL relocs
Browse files Browse the repository at this point in the history
  • Loading branch information
radare committed May 3, 2024
1 parent 86299f1 commit 68dcba4
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 11 deletions.
3 changes: 3 additions & 0 deletions libr/bin/format/elf/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,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
71 changes: 60 additions & 11 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);
// eprintf ("CAL %llx\n", got_addr);
// eprintf ("CAL %llx\n", P);
// SET(24);
// P = address of bl instruction to patch
r->type = R_BIN_RELOC_24;
if (G == UT64_MAX) {
r->addend = B-P; // 171295;
eprintf( "jeje 0x%x 0x%x\n", P, B);
} else {
r->addend = got_addr -P;
}
rel->addend = r->addend;
// 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 @@ -786,14 +803,46 @@ static void _patch_reloc(ELFOBJ *bo, ut16 e_machine, RIOBind *iob, RBinElfReloc
}
break;
case EM_ARM:
if (!rel->sym && rel->mode == DT_REL) {
if (rel->type == R_ARM_CALL) {
// 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

0 comments on commit 68dcba4

Please sign in to comment.