Skip to content

Commit

Permalink
librz/bin: use relocation types name defined by each format. (#4695)
Browse files Browse the repository at this point in the history
* Change ELF relocation type names to the naming used by SysV ABI
* Modified `bin_reloc_type_name` to return correct naming if possible,
  otherwise return the old ADD/SET naming.
* Add `print_name` field to `RzBinReloc`
* Fix ELF relocations tests
  • Loading branch information
Roeegg2 authored Nov 4, 2024
1 parent f1e5559 commit 8b90795
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 193 deletions.
219 changes: 113 additions & 106 deletions librz/bin/p/bin_elf.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1389,33 +1389,33 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
r->section_vaddr = section->rva;
}

#define SET(T) \
r->type = RZ_BIN_RELOC_##T; \
r->additive = 0; \
return r
#define ADD(T, A) \
r->type = RZ_BIN_RELOC_##T; \
r->addend += (A); \
r->additive = rel->mode == DT_RELA; \
#define SET(BIT_SIZE, RELOC_NAME) \
r->type = RZ_BIN_RELOC_##BIT_SIZE; \
r->print_name = (RELOC_NAME); \
return r
#define ADD(BIT_SIZE, ADDEND, RELOC_NAME) \
r->addend += (ADDEND); \
SET(BIT_SIZE, RELOC_NAME)

switch (bin->ehdr.e_machine) {
case EM_386:
// TODO: We're missing a lot of architectures!
switch (rel->type) {
case RZ_386_NONE: break; // malloc then free. meh. then again, there's no real world use for _NONE.
case RZ_386_32: ADD(32, 0);
case RZ_386_PC32: ADD(32, -P);
case RZ_386_GLOB_DAT: SET(32);
case RZ_386_JMP_SLOT: SET(32);
case RZ_386_RELATIVE: ADD(32, B);
case RZ_386_GOTOFF: ADD(32, -GOT);
case RZ_386_GOTPC: ADD(32, GOT - P);
case RZ_386_16: ADD(16, 0);
case RZ_386_PC16: ADD(16, -P);
case RZ_386_8: ADD(8, 0);
case RZ_386_PC8: ADD(8, -P);
case RZ_386_COPY: ADD(32, 0); // copy symbol at runtime
case RZ_386_IRELATIVE: r->is_ifunc = true; SET(32);
case RZ_386_32: ADD(32, 0, "R_386_32");
case RZ_386_PC32: ADD(32, -P, "R_386_PC32");
case RZ_386_GLOB_DAT: SET(32, "R_386_GLOB_DAT");
case RZ_386_JMP_SLOT: SET(32, "R_386_JMP_SLOT");
case RZ_386_RELATIVE: ADD(32, B, "R_386_RELATIVE");
case RZ_386_GOTOFF: ADD(32, -GOT, "R_386_GOTOFF");
case RZ_386_GOTPC: ADD(32, GOT - P, "R_386_GOTPC");
case RZ_386_16: ADD(16, 0, "R_386_16");
case RZ_386_PC16: ADD(16, -P, "R_386_PC16");
case RZ_386_8: ADD(8, 0, "R_386_8");
case RZ_386_PC8: ADD(8, -P, "R_386_PC8");
case RZ_386_COPY: ADD(32, 0, "R_386_COPY"); // copy symbol at runtime
case RZ_386_IRELATIVE: r->is_ifunc = true; SET(32, "R_386_IRELATIVE");
// FIXME: Quite a few relocatons missing here.
default:
RZ_LOG_WARN("unimplemented ELF/X86_32 reloc type %d\n", rel->type);
break;
Expand All @@ -1424,22 +1424,23 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case EM_X86_64:
switch (rel->type) {
case RZ_X86_64_NONE: break; // malloc then free. meh. then again, there's no real world use for _NONE.
case RZ_X86_64_64: ADD(64, 0);
case RZ_X86_64_PLT32: ADD(32, -P /* +L */);
case RZ_X86_64_GOT32: ADD(32, GOT);
case RZ_X86_64_PC32: ADD(32, -P);
case RZ_X86_64_GLOB_DAT: r->vaddr -= rel->sto; SET(64);
case RZ_X86_64_JUMP_SLOT: r->vaddr -= rel->sto; SET(64);
case RZ_X86_64_RELATIVE: ADD(64, B);
case RZ_X86_64_32: ADD(32, 0);
case RZ_X86_64_32S: ADD(32, 0);
case RZ_X86_64_16: ADD(16, 0);
case RZ_X86_64_PC16: ADD(16, -P);
case RZ_X86_64_8: ADD(8, 0);
case RZ_X86_64_PC8: ADD(8, -P);
case RZ_X86_64_GOTPCREL: ADD(64, GOT - P);
case RZ_X86_64_COPY: ADD(64, 0); // copy symbol at runtime
case RZ_X86_64_IRELATIVE: r->is_ifunc = true; SET(64);
case RZ_X86_64_64: ADD(64, 0, "R_X86_64_64");
case RZ_X86_64_PLT32: ADD(32, -P /* +L */, "R_X86_64_PLT32");
case RZ_X86_64_GOT32: ADD(32, GOT, "R_X86_64_GOT32");
case RZ_X86_64_PC32: ADD(32, -P, "R_X86_64_PC32");
case RZ_X86_64_GLOB_DAT: r->vaddr -= rel->sto; SET(64, "R_X86_64_GLOB_DAT");
case RZ_X86_64_JUMP_SLOT: r->vaddr -= rel->sto; SET(64, "R_X86_64_JUMP_SLOT");
case RZ_X86_64_RELATIVE: ADD(64, B, "R_X86_64_RELATIVE");
case RZ_X86_64_32: ADD(32, 0, "R_X86_64_32");
case RZ_X86_64_32S: ADD(32, 0, "R_X86_64_32S");
case RZ_X86_64_16: ADD(16, 0, "R_X86_64_16");
case RZ_X86_64_PC16: ADD(16, -P, "R_X86_64_PC16");
case RZ_X86_64_8: ADD(8, 0, "R_X86_64_8");
case RZ_X86_64_PC8: ADD(8, -P, "R_X86_64_PC8");
case RZ_X86_64_GOTPCREL: ADD(64, GOT - P, "R_X86_64_GOTPCREL");
case RZ_X86_64_COPY: ADD(64, 0, "R_X86_64_COPY"); // copy symbol at runtime
case RZ_X86_64_IRELATIVE: r->is_ifunc = true; SET(64, "R_X86_64_IRELATIVE");
// FIXME: Quite a few relocatons missing here.
default:
RZ_LOG_WARN("unimplemented ELF/X86_64 reloc type %d\n", rel->type);
break;
Expand All @@ -1448,73 +1449,76 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case EM_ARM:
switch (rel->type) {
case RZ_ARM_NONE: break;
case RZ_ARM_ABS32: ADD(32, 0);
case RZ_ARM_REL32: ADD(32, -P);
case RZ_ARM_ABS16: ADD(16, 0);
case RZ_ARM_ABS8: ADD(8, 0);
case RZ_ARM_SBREL32: ADD(32, -B);
case RZ_ARM_GLOB_DAT: ADD(32, 0);
case RZ_ARM_JUMP_SLOT: ADD(32, 0);
case RZ_ARM_COPY: ADD(32, 0); // copy symbol at runtime
case RZ_ARM_RELATIVE: ADD(32, B);
case RZ_ARM_GOTOFF: ADD(32, -GOT);
case RZ_ARM_GOTPC: ADD(32, GOT - P);
case RZ_ARM_CALL: ADD(24, -P);
case RZ_ARM_JUMP24: ADD(24, -P);
case RZ_ARM_THM_JUMP24: ADD(24, -P);
case RZ_ARM_THM_PC22: ADD(24, -P);
case RZ_ARM_PREL31: ADD(32, -P);
case RZ_ARM_MOVW_PREL_NC: ADD(16, -P);
case RZ_ARM_MOVT_PREL: ADD(32, -P);
case RZ_ARM_THM_MOVW_PREL_NC: ADD(16, -P);
case RZ_ARM_REL32_NOI: ADD(32, -P);
case RZ_ARM_ABS32_NOI: ADD(32, 0);
case RZ_ARM_ALU_PC_G0_NC: ADD(32, -P);
case RZ_ARM_ALU_PC_G0: ADD(32, -P);
case RZ_ARM_ALU_PC_G1_NC: ADD(32, -P);
case RZ_ARM_ALU_PC_G1: ADD(32, -P);
case RZ_ARM_ALU_PC_G2: ADD(32, -P);
case RZ_ARM_LDR_PC_G1: ADD(32, -P);
case RZ_ARM_LDR_PC_G2: ADD(32, -P);
case RZ_ARM_LDRS_PC_G0: ADD(32, -P);
case RZ_ARM_LDRS_PC_G1: ADD(32, -P);
case RZ_ARM_LDRS_PC_G2: ADD(32, -P);
case RZ_ARM_LDC_PC_G0: ADD(32, -P);
case RZ_ARM_LDC_PC_G1: ADD(32, -P);
case RZ_ARM_LDC_PC_G2: ADD(32, -P);
default: ADD(32, GOT); break; // reg relocations
case RZ_ARM_ABS32: ADD(32, 0, "R_ARM_ABS32");
case RZ_ARM_REL32: ADD(32, -P, "R_ARM_REL32");
case RZ_ARM_ABS16: ADD(16, 0, "R_ARM_ABS16");
case RZ_ARM_ABS8: ADD(8, 0, "R_ARM_ABS8");
case RZ_ARM_SBREL32: ADD(32, -B, "R_ARM_SBREL32");
case RZ_ARM_GLOB_DAT: ADD(32, 0, "R_ARM_GLOB_DAT");
case RZ_ARM_JUMP_SLOT: ADD(32, 0, "R_ARM_JUMP_SLOT");
case RZ_ARM_COPY: ADD(32, 0, "R_ARM_COPY"); // copy symbol at runtime
case RZ_ARM_RELATIVE: ADD(32, B, "R_ARM_RELATIVE");
case RZ_ARM_GOTOFF: ADD(32, -GOT, "R_ARM_GOTOFF");
case RZ_ARM_GOTPC: ADD(32, GOT - P, "R_ARM_GOTPC");
case RZ_ARM_CALL: ADD(24, -P, "R_ARM_CALL");
case RZ_ARM_JUMP24: ADD(24, -P, "R_ARM_JUMP24");
case RZ_ARM_THM_JUMP24: ADD(24, -P, "R_ARM_THM_JUMP24");
case RZ_ARM_THM_PC22: ADD(24, -P, "R_ARM_THM_PC22");
case RZ_ARM_PREL31: ADD(32, -P, "R_ARM_PREL31");
case RZ_ARM_MOVW_PREL_NC: ADD(16, -P, "R_ARM_MOVW_PREL_NC");
case RZ_ARM_MOVT_PREL: ADD(32, -P, "R_ARM_MOVT_PREL");
case RZ_ARM_THM_MOVW_PREL_NC: ADD(16, -P, "R_ARM_THM_MOVW_PREL_NC");
case RZ_ARM_REL32_NOI: ADD(32, -P, "R_ARM_REL32_NOI");
case RZ_ARM_ABS32_NOI: ADD(32, 0, "R_ARM_ABS32_NOI");
case RZ_ARM_ALU_PC_G0_NC: ADD(32, -P, "R_ARM_ALU_PC_G0_NC");
case RZ_ARM_ALU_PC_G0: ADD(32, -P, "R_ARM_ALU_PC_G0");
case RZ_ARM_ALU_PC_G1_NC: ADD(32, -P, "R_ARM_ALU_PC_G1_NC");
case RZ_ARM_ALU_PC_G1: ADD(32, -P, "R_ARM_ALU_PC_G1");
case RZ_ARM_ALU_PC_G2: ADD(32, -P, "R_ARM_ALU_PC_G2");
case RZ_ARM_LDR_PC_G1: ADD(32, -P, "R_ARM_LDR_PC_G1");
case RZ_ARM_LDR_PC_G2: ADD(32, -P, "R_ARM_LDR_PC_G2");
case RZ_ARM_LDRS_PC_G0: ADD(32, -P, "R_ARM_LDRS_PC_G0");
case RZ_ARM_LDRS_PC_G1: ADD(32, -P, "R_ARM_LDRS_PC_G1");
case RZ_ARM_LDRS_PC_G2: ADD(32, -P, "R_ARM_LDRS_PC_G2");
case RZ_ARM_LDC_PC_G0: ADD(32, -P, "R_ARM_LDC_PC_G0");
case RZ_ARM_LDC_PC_G1: ADD(32, -P, "R_ARM_LDC_PC_G1");
case RZ_ARM_LDC_PC_G2: ADD(32, -P, "R_ARM_LDC_PC_G2");
// FIXME: Quite a few relocatons missing here. It's incorrect to place them all under "reg relocations".
default: ADD(32, GOT, "ARM REG RELOC"); break;
}
break;
case EM_RISCV:
switch (rel->type) {
case RZ_RISCV_NONE: break;
case RZ_RISCV_JUMP_SLOT: ADD(64, 0);
case RZ_RISCV_RELATIVE: ADD(64, B);
default: ADD(64, GOT); break; // reg relocations
case RZ_RISCV_JUMP_SLOT: ADD(64, 0, "R_RISCV_JUMP_SLOT");
case RZ_RISCV_RELATIVE: ADD(64, B, "R_RISCV_RELATIVE");
// FIXME: Quite a few relocatons missing here. It's incorrect to place them all under "reg relocations".
default: ADD(64, GOT, "RISC-V REG RELOC"); break; // reg relocations
}
break;
case EM_AARCH64:
switch (rel->type) {
case RZ_AARCH64_NONE: break;
case RZ_AARCH64_ABS64: ADD(64, 0);
case RZ_AARCH64_ABS32: ADD(32, 0);
case RZ_AARCH64_ABS16: ADD(16, 0);
case RZ_AARCH64_PREL64: ADD(64, 0);
case RZ_AARCH64_PREL32: ADD(32, 0);
case RZ_AARCH64_PREL16: ADD(16, 0);
case RZ_AARCH64_GLOB_DAT: SET(64);
case RZ_AARCH64_JUMP_SLOT: SET(64);
case RZ_AARCH64_RELATIVE: ADD(64, B);
case RZ_AARCH64_LDST8_ABS_LO12_NC: ADD(16, 0);
case RZ_AARCH64_ADD_ABS_LO12_NC: ADD(16, 0);
case RZ_AARCH64_JUMP26: ADD(32, 0);
case RZ_AARCH64_CALL26: ADD(32, 0);
case RZ_AARCH64_LDST64_ABS_LO12_NC: ADD(32, 0);
case RZ_AARCH64_LD64_GOT_LO12_NC: ADD(32, 0);
case RZ_AARCH64_ABS64: ADD(64, 0, "R_AARCH64_ABS64");
case RZ_AARCH64_ABS32: ADD(32, 0, "R_AARCH64_ABS32");
case RZ_AARCH64_ABS16: ADD(16, 0, "R_AARCH64_ABS16");
case RZ_AARCH64_PREL64: ADD(64, 0, "R_AARCH64_PREL64");
case RZ_AARCH64_PREL32: ADD(32, 0, "R_AARCH64_PREL32");
case RZ_AARCH64_PREL16: ADD(16, 0, "R_AARCH64_PREL16");
case RZ_AARCH64_GLOB_DAT: SET(64, "R_AARCH64_GLOB_DAT");
case RZ_AARCH64_JUMP_SLOT: SET(64, "R_AARCH64_JUMP_SLOT");
case RZ_AARCH64_RELATIVE: ADD(64, B, "R_AARCH64_RELATIVE");
case RZ_AARCH64_LDST8_ABS_LO12_NC: ADD(16, 0, "R_AARCH64_LDST8_ABS_LO12_NC");
case RZ_AARCH64_ADD_ABS_LO12_NC: ADD(16, 0, "R_AARCH64_ADD_ABS_LO12_NC");
case RZ_AARCH64_JUMP26: ADD(32, 0, "R_AARCH64_JUMP26");
case RZ_AARCH64_CALL26: ADD(32, 0, "R_AARCH64_CALL26");
case RZ_AARCH64_LDST64_ABS_LO12_NC: ADD(32, 0, "R_AARCH64_LDST64_ABS_LO12_NC");
case RZ_AARCH64_LD64_GOT_LO12_NC: ADD(32, 0, "R_AARCH64_LD64_GOT_LO12_NC");
// Page-relative relocations
case RZ_AARCH64_ADR_GOT_PAGE: ADD(32, 0);
case RZ_AARCH64_ADR_PREL_PG_HI21: ADD(32, 0);
case RZ_AARCH64_ADR_PREL_PG_HI21_NC: ADD(32, 0);
case RZ_AARCH64_ADR_GOT_PAGE: ADD(32, 0, "R_AARCH64_ADR_GOT_PAGE");
case RZ_AARCH64_ADR_PREL_PG_HI21: ADD(32, 0, "R_AARCH64_ADR_PREL_PG_HI21");
case RZ_AARCH64_ADR_PREL_PG_HI21_NC: ADD(32, 0, "R_AARCH64_ADR_PREL_PG_HI21_NC");
// FIXME: Quite a few relocations missing here
default:
RZ_LOG_WARN("unimplemented ELF/AARCH64 reloc type %d\n", rel->type);
break;
Expand All @@ -1523,16 +1527,17 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case EM_PPC:
switch (rel->type) {
case RZ_PPC_NONE: break;
case RZ_PPC_GLOB_DAT: ADD(32, 0);
case RZ_PPC_JMP_SLOT: ADD(32, 0);
case RZ_PPC_COPY: ADD(32, 0); // copy symbol at runtime
case RZ_PPC_REL24: ADD(24, -P);
case RZ_PPC_REL14: ADD(16, -P);
case RZ_PPC_REL32: ADD(32, -P);
case RZ_PPC_RELATIVE: ADD(32, -P);
case RZ_PPC_PLT32: ADD(32, -P);
case RZ_PPC_ADDR16: ADD(16, 0);
case RZ_PPC_ADDR32: ADD(32, 0);
case RZ_PPC_GLOB_DAT: ADD(32, 0, "R_PPC_GLOB_DAT");
case RZ_PPC_JMP_SLOT: ADD(32, 0, "R_PPC_JMP_SLOT");
case RZ_PPC_COPY: ADD(32, 0, "R_PPC_COPY"); // copy symbol at runtime
case RZ_PPC_REL24: ADD(24, -P, "R_PPC_REL24");
case RZ_PPC_REL14: ADD(16, -P, "R_PPC_REL14");
case RZ_PPC_REL32: ADD(32, -P, "R_PPC_REL32");
case RZ_PPC_RELATIVE: ADD(32, -P, "R_PPC_RELATIVE");
case RZ_PPC_PLT32: ADD(32, -P, "R_PPC_PLT32");
case RZ_PPC_ADDR16: ADD(16, 0, "R_PPC_ADDR16");
case RZ_PPC_ADDR32: ADD(32, 0, "R_PPC_ADDR32");
// FIXME: Quite a few relocatons missing here.
default:
RZ_LOG_WARN("unimplemented ELF/PPC reloc type %d\n", rel->type);
break;
Expand All @@ -1541,13 +1546,15 @@ static RzBinReloc *reloc_convert(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
case EM_RX:
switch (rel->type) {
case R_RX_NONE: break;
case R_RX_DIR24S_PCREL: ADD(24, -P);
case R_RX_DIR32: SET(32);
case R_RX_DIR24S_PCREL: ADD(24, -P, "RX_DIR24S_PCREL");
case R_RX_DIR32: SET(32, "RX_DIR32");
// FIXME: Quite a few relocatons missing here.
default:
RZ_LOG_WARN("unimplemented ELF/RX reloc type %d\n", rel->type);
break;
}
default: break;
default:
break;
}

#undef SET
Expand Down
3 changes: 3 additions & 0 deletions librz/core/cbin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1854,6 +1854,9 @@ RZ_API void rz_core_bin_print_source_line_info(RzCore *core, const RzBinSourceLi
}

static const char *bin_reloc_type_name(RzBinReloc *reloc) {
if (RZ_STR_ISNOTEMPTY(reloc->print_name)) {
return reloc->print_name;
}
#define CASE(T) \
case RZ_BIN_RELOC_##T: return reloc->additive ? "ADD_" #T : "SET_" #T
switch (reloc->type) {
Expand Down
1 change: 1 addition & 0 deletions librz/include/rz_bin.h
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ typedef struct rz_bin_reloc_t {
ut64 section_vaddr; ///< the subsection address
ut32 visibility;
bool additive;
const char *print_name; ///< Name of the relocation type. NULL if none is specified. Not setting this field is deprecated.
/* is_ifunc: indirect function, `addend` points to a resolver function
* that returns the actual relocation value, e.g. chooses
* an optimized version depending on the CPU.
Expand Down
20 changes: 10 additions & 10 deletions test/db/analysis/rx
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ CMDS=<<EOF
ir
EOF
EXPECT=<<EOF
vaddr paddr target type name
-----------------------------------------------------------------
0x08000042 0x00000042 0x080000a8 SET_32 _static_bar.1425
0x08000059 0x00000059 0x00000004 SET_32 _local_gint
0x08000063 0x00000063 0x00000004 SET_32 _local_gint
0x08000070 0x00000070 0x08000300 SET_32 _extern_int
0x08000079 0x00000079 0x080000a8 SET_32 _local_static_gint
0x08000086 0x00000086 0x08000304 ADD_24 _extern_foo - 0x08000086
0x0800008a 0x0000008a 0x0800003c ADD_24 _top_foo - 0x0800008a
0x0800008e 0x0000008e 0x08000098 ADD_24 _bottom_foo - 0x0800008e
vaddr paddr target type name
--------------------------------------------------------------------------
0x08000042 0x00000042 0x080000a8 RX_DIR32 _static_bar.1425
0x08000059 0x00000059 0x00000004 RX_DIR32 _local_gint
0x08000063 0x00000063 0x00000004 RX_DIR32 _local_gint
0x08000070 0x00000070 0x08000300 RX_DIR32 _extern_int
0x08000079 0x00000079 0x080000a8 RX_DIR32 _local_static_gint
0x08000086 0x00000086 0x08000304 RX_DIR24S_PCREL _extern_foo - 0x08000086
0x0800008a 0x0000008a 0x0800003c RX_DIR24S_PCREL _top_foo - 0x0800008a
0x0800008e 0x0000008e 0x08000098 RX_DIR24S_PCREL _bottom_foo - 0x0800008e
EOF
RUN

Expand Down
Loading

0 comments on commit 8b90795

Please sign in to comment.