librz/bin/elf: fix and add new ARM32 relocations (#5455)

This commit is contained in:
well-mannered-goat 2026-01-03 17:52:37 +05:30 committed by GitHub
parent 2729fc1f1e
commit 5733f0509a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 931 additions and 210 deletions

View file

@ -139,6 +139,19 @@ static RzBinReloc *reloc_convert_ifunc(ELFOBJ *bin, RzBinElfReloc *rel, RzBinRel
return r;
}
// Custom function for arm specific relocations
static RzBinReloc *reloc_convert_add_t(ELFOBJ *bin, RzBinElfReloc *rel, RzBinRelocType type, bool T, const char *print_name) {
RzBinReloc *r = reloc_convert_new(bin, rel);
if (!r) {
return NULL;
}
r->addend = (r->addend | T);
r->type = type;
r->print_name = print_name;
return r;
}
#define UNSUPP_RELOC(NAME, V) \
RZ_LOG_WARN(NAME ": Unsupported conversion of ELF reloc %u (0x%x)\n", (ut32)V, (ut32)V); \
return reloc_convert_new(bin, rel)
@ -164,6 +177,14 @@ static RzBinReloc *reloc_convert_ifunc(ELFOBJ *bin, RzBinElfReloc *rel, RzBinRel
#define IFCN(BIT_SIZE, RELOC_NAME) \
return reloc_convert_ifunc(bin, rel, RZ_BIN_RELOC_##BIT_SIZE, RELOC_NAME)
/*
Custom add for arm specific relocations
We do A|T this would result the same as (S+A)|T
Then -P is added during patching
*/
#define ADD_T(BIT_SIZE, T, RELOC_NAME) \
return reloc_convert_add_t(bin, rel, RZ_BIN_RELOC_##BIT_SIZE, T, RELOC_NAME)
static RzBinReloc *reloc_convert_intel_80386(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
ut64 B = bin->baddr;
ut64 P = rel->vaddr;
@ -274,36 +295,44 @@ static RzBinReloc *reloc_convert_amd64(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT
static RzBinReloc *reloc_convert_arm(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT) {
ut64 B = bin->baddr;
ut64 P = rel->vaddr;
ut64 Pa = P & 0xfffffffc;
bool T = 0;
RzBinElfSymbol *symbol = Elf_(rz_bin_elf_get_symbol)(bin, rel->sym);
if (symbol && RZ_STR_EQ(symbol->type, RZ_BIN_TYPE_FUNC_STR)) {
// Check for LSB to know if symbol addresses thumb instruction
T = (symbol->vaddr & 1) ? 1 : 0;
}
switch (rel->type) {
case R_ARM_NONE:
return reloc_convert_set(bin, rel, 0, "R_ARM_NONE");
// case R_ARM_ABS32: ADD_T(32, 0, T, "R_ARM_ABS32");
case R_ARM_ABS32: ADD(32, 0, "R_ARM_ABS32");
case R_ARM_REL32: ADD(32, -P, "R_ARM_REL32");
case R_ARM_REL32: ADD_T(32, T, "R_ARM_REL32");
case R_ARM_ABS16: ADD(16, 0, "R_ARM_ABS16");
case R_ARM_ABS8: ADD(8, 0, "R_ARM_ABS8");
case R_ARM_SBREL32: ADD(32, -B, "R_ARM_SBREL32");
case R_ARM_GLOB_DAT: ADD(32, 0, "R_ARM_GLOB_DAT");
case R_ARM_JUMP_SLOT: ADD(32, 0, "R_ARM_JUMP_SLOT");
case R_ARM_SBREL32: ADD_T(32, T, "R_ARM_SBREL32");
case R_ARM_GLOB_DAT: ADD_T(32, T, "R_ARM_GLOB_DAT");
case R_ARM_JUMP_SLOT: ADD_T(32, T, "R_ARM_JUMP_SLOT");
case R_ARM_COPY: ADD(32, 0, "R_ARM_COPY"); // copy symbol at runtime
case R_ARM_RELATIVE: ADD(32, B, "R_ARM_RELATIVE");
case R_ARM_GOTOFF: ADD(32, -GOT, "R_ARM_GOTOFF");
case R_ARM_GOTPC: ADD(32, GOT - P, "R_ARM_GOTPC");
case R_ARM_CALL: ADD(24, -P, "R_ARM_CALL");
case R_ARM_JUMP24: ADD(24, -P, "R_ARM_JUMP24");
case R_ARM_THM_JUMP24: ADD(24, -P, "R_ARM_THM_JUMP24");
case R_ARM_THM_PC22: ADD(24, -P, "R_ARM_THM_PC22");
case R_ARM_PREL31: ADD(32, -P, "R_ARM_PREL31");
case R_ARM_MOVW_PREL_NC: ADD(16, -P, "R_ARM_MOVW_PREL_NC");
case R_ARM_GOTOFF32: ADD_T(32, T, "R_ARM_GOTOFF32");
case R_ARM_BASE_PREL: ADD(32, -P, "R_ARM_GOTPC");
case R_ARM_CALL: ADD_T(24, T, "R_ARM_CALL");
case R_ARM_JUMP24: ADD_T(24, T, "R_ARM_JUMP24");
case R_ARM_THM_JUMP24: ADD_T(24, T, "R_ARM_THM_JUMP24");
case R_ARM_THM_CALL: ADD_T(24, T, "R_ARM_THM_PC22");
case R_ARM_PREL31: ADD_T(32, T, "R_ARM_PREL31");
case R_ARM_MOVW_PREL_NC: ADD_T(16, T, "R_ARM_MOVW_PREL_NC");
case R_ARM_MOVT_PREL: ADD(32, -P, "R_ARM_MOVT_PREL");
case R_ARM_THM_MOVW_PREL_NC: ADD(16, -P, "R_ARM_THM_MOVW_PREL_NC");
case R_ARM_THM_MOVW_PREL_NC: ADD_T(16, T, "R_ARM_THM_MOVW_PREL_NC");
case R_ARM_REL32_NOI: ADD(32, -P, "R_ARM_REL32_NOI");
case R_ARM_ABS32_NOI: ADD(32, 0, "R_ARM_ABS32_NOI");
case R_ARM_ALU_PC_G0_NC: ADD(32, -P, "R_ARM_ALU_PC_G0_NC");
case R_ARM_ALU_PC_G0: ADD(32, -P, "R_ARM_ALU_PC_G0");
case R_ARM_ALU_PC_G1_NC: ADD(32, -P, "R_ARM_ALU_PC_G1_NC");
case R_ARM_ALU_PC_G1: ADD(32, -P, "R_ARM_ALU_PC_G1");
case R_ARM_ALU_PC_G2: ADD(32, -P, "R_ARM_ALU_PC_G2");
case R_ARM_ALU_PC_G0_NC: ADD_T(32, T, "R_ARM_ALU_PC_G0_NC");
case R_ARM_ALU_PC_G0: ADD_T(32, T, "R_ARM_ALU_PC_G0");
case R_ARM_ALU_PC_G1_NC: ADD_T(32, T, "R_ARM_ALU_PC_G1_NC");
case R_ARM_ALU_PC_G1: ADD_T(32, T, "R_ARM_ALU_PC_G1");
case R_ARM_ALU_PC_G2: ADD_T(32, T, "R_ARM_ALU_PC_G2");
case R_ARM_LDR_PC_G1: ADD(32, -P, "R_ARM_LDR_PC_G1");
case R_ARM_LDR_PC_G2: ADD(32, -P, "R_ARM_LDR_PC_G2");
case R_ARM_LDRS_PC_G0: ADD(32, -P, "R_ARM_LDRS_PC_G0");
@ -312,12 +341,12 @@ static RzBinReloc *reloc_convert_arm(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT)
case R_ARM_LDC_PC_G0: ADD(32, -P, "R_ARM_LDC_PC_G0");
case R_ARM_LDC_PC_G1: ADD(32, -P, "R_ARM_LDC_PC_G1");
case R_ARM_LDC_PC_G2: ADD(32, -P, "R_ARM_LDC_PC_G2");
case R_ARM_PC24: UNHANDL("R_ARM_PC24");
case R_ARM_PC13: UNHANDL("R_ARM_PC13");
case R_ARM_ABS12: UNHANDL("R_ARM_ABS12");
case R_ARM_THM_ABS5: UNHANDL("R_ARM_THM_ABS5");
case R_ARM_THM_PC8: UNHANDL("R_ARM_THM_PC8");
case R_ARM_AMP_VCALL9: UNHANDL("R_ARM_AMP_VCALL9");
case R_ARM_PC24: ADD_T(32, T, "R_ARM_PC24"); // Depracated
case R_ARM_LDR_PC_G0: ADD(32, -P, "R_ARM_LDR_PC_G0");
case R_ARM_ABS12: ADD(32, 0, "R_ARM_ABS12");
case R_ARM_THM_ABS5: ADD(16, 0, "R_ARM_THM_ABS5");
case R_ARM_THM_PC8: ADD(16, -Pa, "R_ARM_THM_PC8");
case R_ARM_BREL_ADJ: UNHANDL("R_ARM_BREL_ADJ");
case R_ARM_TLS_DESC: UNHANDL("R_ARM_TLS_DESC");
case R_ARM_THM_SWI8: UNHANDL("R_ARM_THM_SWI8");
case R_ARM_XPC25: UNHANDL("R_ARM_XPC25");
@ -325,82 +354,81 @@ static RzBinReloc *reloc_convert_arm(ELFOBJ *bin, RzBinElfReloc *rel, ut64 GOT)
case R_ARM_TLS_DTPMOD32: UNHANDL("R_ARM_TLS_DTPMOD32");
case R_ARM_TLS_DTPOFF32: UNHANDL("R_ARM_TLS_DTPOFF32");
case R_ARM_TLS_TPOFF32: UNHANDL("R_ARM_TLS_TPOFF32");
case R_ARM_GOT32: UNHANDL("R_ARM_GOT32");
case R_ARM_PLT32: UNHANDL("R_ARM_PLT32");
case R_ARM_BASE_ABS: UNHANDL("R_ARM_BASE_ABS");
case R_ARM_GOT_BREL: ADD(32, 0, "R_ARM_GOT_BREL");
case R_ARM_PLT32: ADD_T(32, T, "R_ARM_PLT32"); // Deprecated
case R_ARM_BASE_ABS: ADD(32, B, "R_ARM_BASE_ABS");
case R_ARM_ALU_PCREL_7_0: UNHANDL("R_ARM_ALU_PCREL_7_0");
case R_ARM_ALU_PCREL_15_8: UNHANDL("R_ARM_ALU_PCREL_15_8");
case R_ARM_ALU_PCREL_23_15: UNHANDL("R_ARM_ALU_PCREL_23_15");
case R_ARM_LDR_SBREL_11_0: UNHANDL("R_ARM_LDR_SBREL_11_0");
case R_ARM_ALU_SBREL_19_12: UNHANDL("R_ARM_ALU_SBREL_19_12");
case R_ARM_ALU_SBREL_27_20: UNHANDL("R_ARM_ALU_SBREL_27_20");
case R_ARM_TARGET1: UNHANDL("R_ARM_TARGET1");
case R_ARM_SBREL31: UNHANDL("R_ARM_SBREL31");
case R_ARM_LDR_SBREL_11_0_NC: ADD(32, -B, "R_ARM_LDR_SBREL_11_0"); // Deprecated
case R_ARM_ALU_SBREL_19_12_NC: ADD(32, -B, "R_ARM_ALU_SBREL_19_12"); // Deprecated
case R_ARM_ALU_SBREL_27_20_CK: ADD(32, -B, "R_ARM_ALU_SBREL_27_20"); // Deprecated
case R_ARM_TARGET1: UNHANDL("R_ARM_TARGET1"); // (S + A) | T or ((S + | A) | T) P
case R_ARM_SBREL31: ADD_T(32, T, "R_ARM_SBREL31");
case R_ARM_V4BX: UNHANDL("R_ARM_V4BX");
case R_ARM_TARGET2: UNHANDL("R_ARM_TARGET2");
case R_ARM_MOVW_ABS_NC: UNHANDL("R_ARM_MOVW_ABS_NC");
case R_ARM_MOVT_ABS: UNHANDL("R_ARM_MOVT_ABS");
case R_ARM_THM_MOVW_ABS_NC: UNHANDL("R_ARM_THM_MOVW_ABS_NC");
case R_ARM_THM_MOVT_ABS: UNHANDL("R_ARM_THM_MOVT_ABS");
case R_ARM_THM_MOVT_PREL: UNHANDL("R_ARM_THM_MOVT_PREL");
case R_ARM_THM_JUMP19: UNHANDL("R_ARM_THM_JUMP19");
case R_ARM_THM_JUMP6: UNHANDL("R_ARM_THM_JUMP6");
case R_ARM_THM_ALU_PREL_11_0: UNHANDL("R_ARM_THM_ALU_PREL_11_0");
case R_ARM_THM_PC12: UNHANDL("R_ARM_THM_PC12");
case R_ARM_ALU_SB_G0_NC: UNHANDL("R_ARM_ALU_SB_G0_NC");
case R_ARM_ALU_SB_G0: UNHANDL("R_ARM_ALU_SB_G0");
case R_ARM_ALU_SB_G1_NC: UNHANDL("R_ARM_ALU_SB_G1_NC");
case R_ARM_ALU_SB_G1: UNHANDL("R_ARM_ALU_SB_G1");
case R_ARM_ALU_SB_G2: UNHANDL("R_ARM_ALU_SB_G2");
case R_ARM_LDR_SB_G0: UNHANDL("R_ARM_LDR_SB_G0");
case R_ARM_LDR_SB_G1: UNHANDL("R_ARM_LDR_SB_G1");
case R_ARM_LDR_SB_G2: UNHANDL("R_ARM_LDR_SB_G2");
case R_ARM_LDRS_SB_G0: UNHANDL("R_ARM_LDRS_SB_G0");
case R_ARM_LDRS_SB_G1: UNHANDL("R_ARM_LDRS_SB_G1");
case R_ARM_LDRS_SB_G2: UNHANDL("R_ARM_LDRS_SB_G2");
case R_ARM_LDC_SB_G0: UNHANDL("R_ARM_LDC_SB_G0");
case R_ARM_LDC_SB_G1: UNHANDL("R_ARM_LDC_SB_G1");
case R_ARM_LDC_SB_G2: UNHANDL("R_ARM_LDC_SB_G2");
case R_ARM_MOVW_BREL_NC: UNHANDL("R_ARM_MOVW_BREL_NC");
case R_ARM_MOVT_BREL: UNHANDL("R_ARM_MOVT_BREL");
case R_ARM_MOVW_BREL: UNHANDL("R_ARM_MOVW_BREL");
case R_ARM_THM_MOVW_BREL_NC: UNHANDL("R_ARM_THM_MOVW_BREL_NC");
case R_ARM_THM_MOVT_BREL: UNHANDL("R_ARM_THM_MOVT_BREL");
case R_ARM_THM_MOVW_BREL: UNHANDL("R_ARM_THM_MOVW_BREL");
case R_ARM_MOVW_ABS_NC: ADD_T(32, T, "R_ARM_MOVW_ABS_NC");
case R_ARM_MOVT_ABS: ADD(32, 0, "R_ARM_MOVT_ABS");
case R_ARM_THM_MOVW_ABS_NC: ADD_T(32, T, "R_ARM_THM_MOVW_ABS_NC");
case R_ARM_THM_MOVT_ABS: ADD(32, 0, "R_ARM_THM_MOVT_ABS");
case R_ARM_THM_MOVT_PREL: ADD(32, -P, "R_ARM_THM_MOVT_PREL");
case R_ARM_THM_JUMP19: ADD_T(32, T, "R_ARM_THM_JUMP19");
case R_ARM_THM_JUMP6: ADD(16, -P, "R_ARM_THM_JUMP6");
case R_ARM_THM_ALU_PREL_11_0: ADD_T(32, T, "R_ARM_THM_ALU_PREL_11_0");
case R_ARM_THM_PC12: ADD(32, -Pa, "R_ARM_THM_PC12");
case R_ARM_ALU_SB_G0_NC: ADD_T(32, T, "R_ARM_ALU_SB_G0_NC");
case R_ARM_ALU_SB_G0: ADD_T(32, T, "R_ARM_ALU_SB_G0");
case R_ARM_ALU_SB_G1_NC: ADD_T(32, T, "R_ARM_ALU_SB_G1_NC");
case R_ARM_ALU_SB_G1: ADD_T(32, T, "R_ARM_ALU_SB_G1");
case R_ARM_ALU_SB_G2: ADD_T(32, T, "R_ARM_ALU_SB_G2");
case R_ARM_LDR_SB_G0: ADD(32, -B, "R_ARM_LDR_SB_G0");
case R_ARM_LDR_SB_G1: ADD(32, -B, "R_ARM_LDR_SB_G1");
case R_ARM_LDR_SB_G2: ADD(32, -B, "R_ARM_LDR_SB_G2");
case R_ARM_LDRS_SB_G0: ADD(32, -B, "R_ARM_LDRS_SB_G0");
case R_ARM_LDRS_SB_G1: ADD(32, -B, "R_ARM_LDRS_SB_G1");
case R_ARM_LDRS_SB_G2: ADD(32, -B, "R_ARM_LDRS_SB_G2");
case R_ARM_LDC_SB_G0: ADD(32, -B, "R_ARM_LDC_SB_G0");
case R_ARM_LDC_SB_G1: ADD(32, -B, "R_ARM_LDC_SB_G1");
case R_ARM_LDC_SB_G2: ADD(32, -B, "R_ARM_LDC_SB_G2");
case R_ARM_MOVW_BREL_NC: ADD_T(16, T, "R_ARM_MOVW_BREL_NC");
case R_ARM_MOVT_BREL: ADD(32, -B, "R_ARM_MOVT_BREL");
case R_ARM_MOVW_BREL: ADD_T(16, T, "R_ARM_MOVW_BREL");
case R_ARM_THM_MOVW_BREL_NC: ADD_T(16, T, "R_ARM_THM_MOVW_BREL_NC");
case R_ARM_THM_MOVT_BREL: ADD(32, -B, "R_ARM_THM_MOVT_BREL");
case R_ARM_THM_MOVW_BREL: ADD_T(16, T, "R_ARM_THM_MOVW_BREL");
case R_ARM_TLS_GOTDESC: UNHANDL("R_ARM_TLS_GOTDESC");
case R_ARM_TLS_CALL: UNHANDL("R_ARM_TLS_CALL");
case R_ARM_TLS_DESCSEQ: UNHANDL("R_ARM_TLS_DESCSEQ");
case R_ARM_THM_TLS_CALL: UNHANDL("R_ARM_THM_TLS_CALL");
case R_ARM_PLT32_ABS: UNHANDL("R_ARM_PLT32_ABS");
case R_ARM_GOT_ABS: UNHANDL("R_ARM_GOT_ABS");
case R_ARM_GOT_PREL: UNHANDL("R_ARM_GOT_PREL");
case R_ARM_GOT_BREL12: UNHANDL("R_ARM_GOT_BREL12");
case R_ARM_GOTOFF12: UNHANDL("R_ARM_GOTOFF12");
case R_ARM_GOT_ABS: ADD(32, 0, "R_ARM_GOT_ABS");
case R_ARM_GOT_PREL: ADD(32, -P, "R_ARM_GOT_PREL");
case R_ARM_GOT_BREL12: ADD(32, 0, "R_ARM_GOT_BREL12");
case R_ARM_GOTOFF12: ADD(32, -GOT, "R_ARM_GOTOFF12");
case R_ARM_GOTRELAX: UNHANDL("R_ARM_GOTRELAX");
case R_ARM_GNU_VTENTRY: UNHANDL("R_ARM_GNU_VTENTRY");
case R_ARM_GNU_VTINHERIT: UNHANDL("R_ARM_GNU_VTINHERIT");
case R_ARM_THM_PC11: UNHANDL("R_ARM_THM_PC11");
case R_ARM_THM_PC9: UNHANDL("R_ARM_THM_PC9");
case R_ARM_TLS_GD32: UNHANDL("R_ARM_TLS_GD32");
case R_ARM_TLS_LDM32: UNHANDL("R_ARM_TLS_LDM32");
case R_ARM_THM_JUMP11: ADD(16, -P, "R_ARM_THM_JUMP11");
case R_ARM_THM_JUMP8: ADD(16, -P, "R_ARM_THM_JUMP8");
case R_ARM_TLS_GD32: ADD(32, -P, "R_ARM_TLS_GD32");
case R_ARM_TLS_LDM32: ADD(32, -P, "R_ARM_TLS_LDM32");
case R_ARM_TLS_LDO32: UNHANDL("R_ARM_TLS_LDO32");
case R_ARM_TLS_IE32: UNHANDL("R_ARM_TLS_IE32");
case R_ARM_TLS_IE32: ADD(32, -P, "R_ARM_TLS_IE32");
case R_ARM_TLS_LE32: UNHANDL("R_ARM_TLS_LE32");
case R_ARM_TLS_LDO12: UNHANDL("R_ARM_TLS_LDO12");
case R_ARM_TLS_LE12: UNHANDL("R_ARM_TLS_LE12");
case R_ARM_TLS_IE12GP: UNHANDL("R_ARM_TLS_IE12GP");
case R_ARM_TLS_IE12GP: ADD(32, 0, "R_ARM_TLS_IE12GP");
case R_ARM_ME_TOO: UNHANDL("R_ARM_ME_TOO");
case R_ARM_THM_TLS_DESCSEQ: UNHANDL("R_ARM_THM_TLS_DESCSEQ");
case R_ARM_THM_TLS_DESCSEQ32: UNHANDL("R_ARM_THM_TLS_DESCSEQ32");
case R_ARM_THM_GOT_BREL12: UNHANDL("R_ARM_THM_GOT_BREL12");
case R_ARM_IRELATIVE: UNHANDL("R_ARM_IRELATIVE");
case R_ARM_RXPC25: UNHANDL("R_ARM_RXPC25");
case R_ARM_RSBREL32: UNHANDL("R_ARM_RSBREL32");
case R_ARM_THM_RPC22: UNHANDL("R_ARM_THM_RPC22");
case R_ARM_RREL32: UNHANDL("R_ARM_RREL32");
case R_ARM_RABS22: UNHANDL("R_ARM_RABS22");
case R_ARM_RPC24: UNHANDL("R_ARM_RPC24");
case R_ARM_RBASE: UNHANDL("R_ARM_RBASE");
case R_ARM_THM_GOT_BREL12: ADD(32, 0, "R_ARM_THM_GOT_BREL12");
case R_ARM_THM_ALU_ABS_G0_NC: ADD_T(16, T, "R_ARM_THM_ALU_ABS_G0_NC");
case R_ARM_THM_ALU_ABS_G1_NC: ADD(16, 0, "R_ARM_THM_ALU_ABS_G1_NC");
case R_ARM_THM_ALU_ABS_G2_NC: ADD(16, 0, "R_ARM_THM_ALU_ABS_G2_NC");
case R_ARM_THM_ALU_ABS_G3: ADD(16, 0, "R_ARM_THM_ALU_ABS_G3");
case R_ARM_THM_BF16: ADD_T(16, T, "R_ARM_THM_BF16");
case R_ARM_THM_BF12: ADD_T(16, T, "R_ARM_THM_BF12");
case R_ARM_THM_BF18: ADD_T(16, T, "R_ARM_THM_BF18");
// FIXME: Quite a few relocations missing here. It's incorrect to place them all under "reg relocations".
default: ADD(32, GOT, "ARM REG RELOC");

View file

@ -822,6 +822,61 @@ static void patch_reloc_mips(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_ad
}
}
// For arm group relocations related to ALU instructions
static ut32 convert_alu_group_mask(ut32 X, int n) {
ut32 residual = X;
ut32 encoded_g_n = 0;
for (int current_n = 0; current_n <= n; current_n++) {
int msb;
int shift;
if (residual == 0) {
shift = 0;
} else {
for (msb = 30; msb >= 0; msb -= 2) {
if (residual & (0x3 << msb)) {
break;
}
}
shift = ((msb - 6) < 0) ? 0 : (msb - 6);
}
ut32 g_n = residual & (0xFF << shift);
encoded_g_n = (g_n >> shift) | ((g_n <= 0xff ? 0 : (32 - shift) / 2) << 8);
residual &= ~g_n;
}
return encoded_g_n;
}
// For arm group relocations not related to ALU instructions
static ut32 convert_group_mask(ut32 X, int n) {
ut32 residual = X;
for (int current_n = 0; current_n <= n; current_n++) {
int msb;
int shift;
if (residual == 0) {
shift = 0;
} else {
for (msb = 30; msb >= 0; msb -= 2) {
if (residual & (0x3 << msb)) {
break;
}
}
shift = ((msb - 6) < 0) ? 0 : (msb - 6);
}
ut32 g_n = residual & (0xFF << shift);
residual &= ~g_n;
}
return residual;
}
/**
* \brief Patches the opcode at a given address depending on the relocation type.
*
@ -839,14 +894,15 @@ static void patch_reloc_arm(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_add
ut32 nbytes = 4;
ut8 buf[4] = { 0 };
ut64 val = 0;
ut16 offset = 0;
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
switch (rel->type) {
case R_ARM_NONE:
return;
case R_ARM_THM_JUMP24:
/* fall-thru */
case R_ARM_THM_PC22:
case R_ARM_THM_CALL:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
// I1 = NOT(J1 EOR S)
// I2 = NOT(J2 EOR S)
@ -864,16 +920,549 @@ static void patch_reloc_arm(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_add
(((~(val >> 11)) ^ (val >> 13)) & 0x0800) | // J2
((val >> 1) & 0x07ff), // imm11
big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_ABS32:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A;
rz_write_ble32(buf, val, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_REL32:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A - fs->P;
rz_write_ble32(buf, val, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_PC24:
/* fall through */
case R_ARM_PLT32:
/* fall through */
case R_ARM_CALL:
/* fall through */
case R_ARM_JUMP24:
val = fs->S + fs->A - fs->P;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x03FFFFFE, (val >> 2));
break;
case R_ARM_MOVW_PREL_NC:
val = fs->S + fs->A - fs->P;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x000F0FFF, val);
break;
case R_ARM_THM_MOVW_PREL_NC:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = imm4:i:imm3:imm8
val = fs->S + fs->A - fs->P;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBF0) |
((val & 0xF000) >> 12) | // imm4
((val & 0x0800) >> 1); // i
keephw2 = (keephw2 & 0x8F00) |
((val & 0x0700) << 4) | // imm3
((val & 0x00FF)); // imm8
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_JUMP19:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = S:J1:J2:imm6:imm11:0
val = fs->S + fs->A - fs->P;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBC0) |
((val >> 10) & 0x0400) | // S
((val >> 12) & 0x003F); // imm6
keephw2 = (keephw2 & 0xD000) |
(((val >> 19) & 1) << 13) | // J1
(((val >> 18) & 1) << 11) | // J2
((val >> 1) & 0x07FF); // imm11
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_ALU_PREL_11_0:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = i:imm3:imm8
val = fs->S + fs->A - (fs->P & 0xFFFFFFFC); // S+A-Pa
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBFF) |
((val >> 1) & 0x0400); // i
keephw2 = (keephw2 & 0x8F00) |
((val << 4) & 0x7000) | // imm3
(val & 0x00FF); // imm8
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_ABS16:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A;
rz_write_ble16(buf, (val & 0xFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_ABS12:
val = fs->S + fs->A;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, val);
break;
case R_ARM_THM_ABS5:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = ((fs->S + fs->A) & 0x7C) >> 2;
keephw1 = rz_read_ble16(buf, big_endian);
keephw1 = (keephw1 & 0xF83F) |
(val << 6);
rz_write_ble16(buf, keephw1, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_ABS8:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A;
rz_write_ble8(buf, (val & 0xFF));
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_SBREL32:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A - fs->B;
rz_write_ble32(buf, (val & 0xFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_PC8:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A - (fs->P & 0xFFFFFFFC);
val = (val & 0x3FC) >> 2;
keephw1 = rz_read_ble16(buf, big_endian);
keephw1 = (keephw1 & 0xFF00) | val;
rz_write_ble16(buf, keephw1, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_GOTOFF32:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A - fs->GOT;
rz_write_ble32(buf, (val & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_BASE_PREL:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
if (fs->S == 0) { // NUll symbol
val = fs->GOT + fs->A;
} else {
val = fs->B + fs->A;
}
rz_write_ble32(buf, (val & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_GOT_BREL:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->G + fs->A;
rz_write_ble32(buf, (val & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_BASE_ABS:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
rz_write_ble32(buf, (fs->A & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_PREL31:
val = (fs->S + fs->A - fs->P) >> 1;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x7FFFFFFF, val);
break;
case R_ARM_MOVW_ABS_NC:
// val = imm4:imm12
val = (fs->S + fs->A) & 0xFFFF;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x000F0FFF, val);
break;
case R_ARM_MOVT_ABS:
/* fall through */
case R_ARM_MOVT_PREL:
// val = imm4:imm12
val = (fs->S + fs->A) >> 16;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x000F0FFF, val);
break;
case R_ARM_THM_MOVW_ABS_NC:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = imm4:i:imm3:imm8
val = (fs->S + fs->A) & 0xFFFF;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBF0) |
((val >> 1) & 0x0400) | // i
((val >> 12) & 0x000F); // imm4
keephw2 = (keephw2 & 0x8F00) |
((val << 4) & 0x7000) | // imm3
(val & 0x00FF); // imm8
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_MOVT_ABS:
/* fall through */
case R_ARM_THM_MOVT_PREL:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = imm4:i:imm3:imm8
val = (fs->S + fs->A) >> 16;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBF0) |
((val >> 1) & 0x0400) | // i
((val >> 12) & 0x000F); // imm4
keephw2 = (keephw2 & 0x8F00) |
((val << 4) & 0x7000) | // imm3
(val & 0x00FF); // imm8
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_JUMP6:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = i:imm5
val = ((fs->S + fs->A) & 0x7E) >> 1;
keephw1 = rz_read_ble16(buf, big_endian);
keephw1 = (keephw1 & 0xFD07) |
((val << 4) & 0x0200) | // i
((val << 3) & 0x00F8); // imm5
rz_write_ble16(buf, keephw1, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_PC12:
// val = imm12
val = (fs->S + fs->A) & 0xFFF;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, val);
break;
case R_ARM_ABS32_NOI:
/* fall through */
case R_ARM_REL32_NOI:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A;
rz_write_ble32(buf, (val & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_MOVW_BREL:
/* fall through */
case R_ARM_MOVW_BREL_NC:
// val = imm4:imm12
val = (fs->S + fs->A - fs->B) & 0xFFFF;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x000F0FFF, val);
break;
case R_ARM_MOVT_BREL:
val = (fs->S + fs->A) >> 16;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x000F0FFF, val);
break;
case R_ARM_THM_MOVW_BREL:
/* fall through */
case R_ARM_THM_MOVW_BREL_NC:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = imm4:i:imm3:imm8
val = (fs->S + fs->A - fs->B) & 0xFFFF;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBF0) |
((val >> 1) & 0x0400) | // i
((val >> 12) & 0x000F); // imm4
keephw2 = (keephw2 & 0x8F00) |
((val << 4) & 0x7000) | // imm3
(val & 0x00FF); // imm8
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_MOVT_BREL:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = imm4:i:imm3:imm8
val = (fs->S + fs->A) >> 16;
keephw1 = rz_read_ble16(&buf[0], big_endian);
keephw2 = rz_read_ble16(&buf[2], big_endian);
keephw1 = (keephw1 & 0xFBF0) |
((val >> 1) & 0x0400) | // i
((val >> 12) & 0x000F); // imm4
keephw2 = (keephw2 & 0x8F00) |
((val << 4) & 0x7000) | // imm3
(val & 0x00FF); // imm8
rz_write_ble16(&buf[0], keephw1, big_endian);
rz_write_ble16(&buf[2], keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_GOT_PREL:
/* fall through */
case R_ARM_GOT_ABS:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->G + fs->GOT + fs->A;
rz_write_ble32(buf, (val & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_GOT_BREL12:
/* fall through */
case R_ARM_TLS_IE12GP:
/* fall through */
case R_ARM_GOT_BREL12:
// val = imm12
val = (fs->G + fs->A) & 0xFFF; // G(S) + A - GOT_ORG
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, val);
break;
case R_ARM_GOTOFF12:
// val = imm12
val = (fs->S + fs->A) & 0xFFF;
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, val);
break;
case R_ARM_THM_JUMP11:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val = imm11
val = ((fs->S + fs->A) & 0xFFE) >> 1;
keephw1 = rz_read_ble16(buf, big_endian);
keephw1 = (keephw1 & 0xF800) | val;
rz_write_ble16(buf, keephw1, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_THM_JUMP8:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
// val - imm8
val = ((fs->S + fs->A) & 0x1FE) >> 1;
keephw1 = rz_read_ble16(buf, big_endian);
keephw1 = (keephw1 & 0xFF00) | val;
rz_write_ble16(buf, keephw1, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_TLS_GD32:
/* fall through */
case R_ARM_TLS_LDM32:
/* fall through */
case R_ARM_TLS_IE32:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->G + fs->GOT + fs->A;
rz_write_ble32(buf, (val & 0xFFFFFFFF), big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
case R_ARM_ALU_PC_G0:
/* fall through */
case R_ARM_ALU_PC_G0_NC:
val = fs->S + fs->A - fs->P;
offset = convert_alu_group_mask(val, 0);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_ALU_PC_G1:
/* fall through */
case R_ARM_ALU_PC_G1_NC:
val = fs->S + fs->A - fs->P;
offset = convert_alu_group_mask(val, 1);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_ALU_PC_G2:
val = fs->S + fs->A - fs->P;
offset = convert_alu_group_mask(val, 2);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_LDR_SB_G0:
/* fall through */
case R_ARM_LDR_PC_G0:
val = fs->S + fs->A;
offset = convert_group_mask(val, 0);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_LDR_SB_G1:
/* fall through */
case R_ARM_LDR_PC_G1:
val = fs->S + fs->A;
offset = convert_group_mask(val, 1);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_LDR_SB_G2:
/* fall through */
case R_ARM_LDR_PC_G2:
val = fs->S + fs->A;
offset = convert_group_mask(val, 2);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_LDRS_SB_G0:
/* fall through */
case R_ARM_LDRS_PC_G0:
val = fs->S + fs->A;
offset = convert_group_mask(val, 0);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x0F0F, offset);
break;
case R_ARM_LDRS_SB_G1:
/* fall through */
case R_ARM_LDRS_PC_G1:
val = fs->S + fs->A;
offset = convert_group_mask(val, 1);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x0F0F, offset);
break;
case R_ARM_LDRS_SB_G2:
/* fall through */
case R_ARM_LDRS_PC_G2:
val = fs->S + fs->A;
offset = convert_group_mask(val, 2);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0x0F0F, offset);
break;
case R_ARM_LDC_SB_G0:
/* fall through */
case R_ARM_LDC_PC_G0:
val = fs->S + fs->A;
offset = convert_group_mask(val, 0);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFF, offset);
break;
case R_ARM_LDC_SB_G1:
/* fall through */
case R_ARM_LDC_PC_G1:
val = fs->S + fs->A;
offset = convert_group_mask(val, 1);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFF, offset);
break;
case R_ARM_LDC_SB_G2:
/* fall through */
case R_ARM_LDC_PC_G2:
val = fs->S + fs->A;
offset = convert_group_mask(val, 2);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFF, offset);
break;
case R_ARM_ALU_SB_G0:
/* fall through */
case R_ARM_ALU_SB_G0_NC:
val = fs->S + fs->A - fs->B;
offset = convert_alu_group_mask(val, 0);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_ALU_SB_G1:
/* fall through */
case R_ARM_ALU_SB_G1_NC:
val = fs->S + fs->A - fs->B;
offset = convert_alu_group_mask(val, 1);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
case R_ARM_ALU_SB_G2:
val = fs->S + fs->A - fs->B;
offset = convert_alu_group_mask(val, 2);
patch_val_over_mask_32(buf_patched, big_endian, patch_addr, 0xFFF, offset);
break;
/*
The following relocations are for Branch Future instructions in Armv8.1-M Mainline.
Check the docs: https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst#56114armv81-m-mainline-branch-future-relocations
*/
case R_ARM_THM_BF16:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = (fs->S + fs->A - fs->P) & 0x0001FFFE;
keephw1 = rz_read_ble16(buf, big_endian);
keephw2 = rz_read_ble16(buf + 2, big_endian);
// insn[10:1] = (val >> 2) & 0x3FF
// insn[11] = (val >> 1) & 0x1
// insn[20:16] = val >> 12
keephw1 = (keephw1 & 0xF800) | ((val >> 2) & 0x3FF) | (((val >> 1) & 0x1) << 11);
keephw2 = (keephw2 & 0xFFE0) | ((val >> 12) & 0x1F);
rz_write_ble16(buf, keephw1, big_endian);
rz_write_ble16(buf + 2, keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, 4);
break;
case R_ARM_THM_BF12:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A - fs->P;
val = val & 0x00001FFE;
keephw1 = rz_read_ble16(buf, big_endian);
keephw2 = rz_read_ble16(buf + 2, big_endian);
// insn[10:1] = (val >> 2) & 0x3FF
// insn[11] = (val >> 1) & 0x1
// insn[16] = val >> 12
keephw1 = (keephw1 & 0xF800) | ((val >> 2) & 0x3FF) | (((val >> 1) & 0x1) << 11);
keephw2 = (keephw2 & 0xFFFE) | ((val >> 12) & 0x1);
rz_write_ble16(buf, keephw1, big_endian);
rz_write_ble16(buf + 2, keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, 4);
break;
case R_ARM_THM_BF18:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A - fs->P;
val = val & 0x0007FFFE;
keephw1 = rz_read_ble16(buf, big_endian);
keephw2 = rz_read_ble16(buf + 2, big_endian);
// insn[10:1] = (val >> 2) & 0x3FF
// insn[11] = (val >> 1) & 0x1
// insn[22:16] = val >> 12
keephw1 = (keephw1 & 0xF800) | ((val >> 2) & 0x3FF) | (((val >> 1) & 0x1) << 11);
keephw2 = (keephw2 & 0xFF80) | ((val >> 12) & 0x7F);
rz_write_ble16(buf, keephw1, big_endian);
rz_write_ble16(buf + 2, keephw2, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, 4);
break;
default:
rz_buf_read_at(buf_patched, patch_addr, buf, 4);
val = fs->S + fs->A;
if (!rel->sym && rel->mode == DT_REL) {
val += rz_read_ble32(buf, big_endian);
}
rz_write_ble32(buf, val, big_endian);
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
break;
}
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
}
/**

View file

@ -3028,133 +3028,139 @@ enum {
#define STO_AARCH64_VARIANT_PCS 0x80
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
#define R_ARM_PC24 1 /* Deprecated PC relative 26 bit branch. */
#define R_ARM_ABS32 2 /* Direct 32 bit */
#define R_ARM_REL32 3 /* PC relative 32 bit */
#define R_ARM_PC13 4
#define R_ARM_ABS16 5 /* Direct 16 bit */
#define R_ARM_ABS12 6 /* Direct 12 bit */
#define R_ARM_THM_ABS5 7 /* Direct & 0x7C (LDR, STR). */
#define R_ARM_ABS8 8 /* Direct 8 bit */
#define R_ARM_SBREL32 9
#define R_ARM_THM_PC22 10 /* PC relative 24 bit (Thumb32 BL). */
#define R_ARM_THM_PC8 11 /* PC relative & 0x3FC (Thumb16 LDR, ADD, ADR). */
#define R_ARM_AMP_VCALL9 12
#define R_ARM_SWI24 13 /* Obsolete static relocation. */
#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */
#define R_ARM_THM_SWI8 14 /* Reserved. */
#define R_ARM_XPC25 15 /* Reserved. */
#define R_ARM_THM_XPC22 16 /* Reserved. */
#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
#define R_ARM_COPY 20 /* Copy symbol at runtime */
#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
#define R_ARM_RELATIVE 23 /* Adjust by program base */
#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
#define R_ARM_GOT32 26 /* 32 bit GOT entry */
#define R_ARM_PLT32 27 /* Deprecated, 32 bit PLT address. */
#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */
#define R_ARM_JUMP24 29 /* PC relative 24 bit (B, BL<cond>). */
#define R_ARM_THM_JUMP24 30 /* PC relative 24 bit (Thumb32 B.W). */
#define R_ARM_BASE_ABS 31 /* Adjust by program base. */
#define R_ARM_ALU_PCREL_7_0 32 /* Obsolete. */
#define R_ARM_ALU_PCREL_15_8 33 /* Obsolete. */
#define R_ARM_ALU_PCREL_23_15 34 /* Obsolete. */
#define R_ARM_LDR_SBREL_11_0 35 /* Deprecated, prog. base relative. */
#define R_ARM_ALU_SBREL_19_12 36 /* Deprecated, prog. base relative. */
#define R_ARM_ALU_SBREL_27_20 37 /* Deprecated, prog. base relative. */
#define R_ARM_TARGET1 38
#define R_ARM_SBREL31 39 /* Program base relative. */
#define R_ARM_V4BX 40
#define R_ARM_TARGET2 41
#define R_ARM_PREL31 42 /* 32 bit PC relative. */
#define R_ARM_MOVW_ABS_NC 43 /* Direct 16-bit (MOVW). */
#define R_ARM_MOVT_ABS 44 /* Direct high 16-bit (MOVT). */
#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */
#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */
#define R_ARM_THM_MOVW_ABS_NC 47 /* Direct 16 bit (Thumb32 MOVW). */
#define R_ARM_THM_MOVT_ABS 48 /* Direct high 16 bit (Thumb32 MOVT). */
#define R_ARM_THM_MOVW_PREL_NC 49 /* PC relative 16 bit (Thumb32 MOVW). */
#define R_ARM_THM_MOVT_PREL 50 /* PC relative high 16 bit (Thumb32 MOVT). */
#define R_ARM_THM_JUMP19 51 /* PC relative 20 bit (Thumb32 B<cond>.W). */
#define R_ARM_THM_JUMP6 52 /* PC relative X & 0x7E (Thumb16 CBZ, CBNZ). */
#define R_ARM_THM_ALU_PREL_11_0 53 /* PC relative 12 bit (Thumb32 ADR.W). */
#define R_ARM_THM_PC12 54 /* PC relative 12 bit (Thumb32 LDR{D,SB,H,SH}). */
#define R_ARM_ABS32_NOI 55 /* Direct 32-bit. */
#define R_ARM_REL32_NOI 56 /* PC relative 32-bit. */
#define R_ARM_ALU_PC_G0_NC 57 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G0 58 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G1_NC 59 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G1 60 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G2 61 /* PC relative (ADD, SUB). */
#define R_ARM_LDR_PC_G1 62 /* PC relative (LDR,STR,LDRB,STRB). */
#define R_ARM_LDR_PC_G2 63 /* PC relative (LDR,STR,LDRB,STRB). */
#define R_ARM_LDRS_PC_G0 64 /* PC relative (STR{D,H}, LDR{D,SB,H,SH}). */
#define R_ARM_LDRS_PC_G1 65 /* PC relative (STR{D,H}, LDR{D,SB,H,SH}). */
#define R_ARM_LDRS_PC_G2 66 /* PC relative (STR{D,H}, LDR{D,SB,H,SH}). */
#define R_ARM_LDC_PC_G0 67 /* PC relative (LDC, STC). */
#define R_ARM_LDC_PC_G1 68 /* PC relative (LDC, STC). */
#define R_ARM_LDC_PC_G2 69 /* PC relative (LDC, STC). */
#define R_ARM_ALU_SB_G0_NC 70 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G0 71 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G1_NC 72 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G1 73 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G2 74 /* Program base relative (ADD,SUB). */
#define R_ARM_LDR_SB_G0 75 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDR_SB_G1 76 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDR_SB_G2 77 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDRS_SB_G0 78 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDRS_SB_G1 79 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDRS_SB_G2 80 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDC_SB_G0 81 /* Program base relative (LDC,STC). */
#define R_ARM_LDC_SB_G1 82 /* Program base relative (LDC,STC). */
#define R_ARM_LDC_SB_G2 83 /* Program base relative (LDC,STC). */
#define R_ARM_MOVW_BREL_NC 84 /* Program base relative 16 bit (MOVW). */
#define R_ARM_MOVT_BREL 85 /* Program base relative high 16 bit (MOVT). */
#define R_ARM_MOVW_BREL 86 /* Program base relative 16 bit (MOVW). */
#define R_ARM_THM_MOVW_BREL_NC 87 /* Program base relative 16 bit (Thumb32 MOVW). */
#define R_ARM_THM_MOVT_BREL 88 /* Program base relative high 16 bit (Thumb32 MOVT). */
#define R_ARM_THM_MOVW_BREL 89 /* Program base relative 16 bit (Thumb32 MOVW). */
#define R_ARM_TLS_GOTDESC 90
#define R_ARM_TLS_CALL 91
#define R_ARM_TLS_DESCSEQ 92 /* TLS relaxation. */
#define R_ARM_THM_TLS_CALL 93
#define R_ARM_PLT32_ABS 94
#define R_ARM_GOT_ABS 95 /* GOT entry. */
#define R_ARM_GOT_PREL 96 /* PC relative GOT entry. */
#define R_ARM_GOT_BREL12 97 /* GOT entry relative to GOT origin (LDR). */
#define R_ARM_GOTOFF12 98 /* 12 bit, GOT entry relative to GOT origin (LDR, STR). */
#define R_ARM_GOTRELAX 99
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_THM_PC11 102 /* PC relative & 0xFFE (Thumb16 B). */
#define R_ARM_THM_PC9 103 /* PC relative & 0x1FE (Thumb16 B/B<cond>). */
#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic thread local data */
#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic thread local data */
#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS block */
#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of static TLS block offset */
#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static TLS block */
#define R_ARM_TLS_LDO12 109 /* 12 bit relative to TLS block (LDR, STR). */
#define R_ARM_TLS_LE12 110 /* 12 bit relative to static TLS block (LDR, STR). */
#define R_ARM_TLS_IE12GP 111 /* 12 bit GOT entry relative to GOT origin (LDR). */
#define R_ARM_ME_TOO 128 /* Obsolete. */
#define R_ARM_THM_TLS_DESCSEQ 129
#define R_ARM_THM_TLS_DESCSEQ16 129
#define R_ARM_THM_TLS_DESCSEQ32 130
#define R_ARM_THM_GOT_BREL12 131 /* GOT entry relative to GOT origin, 12 bit (Thumb32 LDR). */
#define R_ARM_IRELATIVE 160
#define R_ARM_RXPC25 249
#define R_ARM_RSBREL32 250
#define R_ARM_THM_RPC22 251
#define R_ARM_RREL32 252
#define R_ARM_RABS22 253
#define R_ARM_RPC24 254
#define R_ARM_RBASE 255
/* Source: https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst#relocation */
#define R_ARM_NONE 0 /* No reloc */
#define R_ARM_PC24 1 /* Deprecated PC relative 26 bit branch. */
#define R_ARM_ABS32 2 /* Direct 32 bit */
#define R_ARM_REL32 3 /* PC relative 32 bit */
#define R_ARM_LDR_PC_G0 4
#define R_ARM_ABS16 5 /* Direct 16 bit */
#define R_ARM_ABS12 6 /* Direct 12 bit */
#define R_ARM_THM_ABS5 7 /* Direct & 0x7C (LDR, STR). */
#define R_ARM_ABS8 8 /* Direct 8 bit */
#define R_ARM_SBREL32 9
#define R_ARM_THM_CALL 10 /* PC relative 24 bit (Thumb32 BL). */
#define R_ARM_THM_PC8 11 /* PC relative & 0x3FC (Thumb16 LDR, ADD, ADR). */
#define R_ARM_BREL_ADJ 12
#define R_ARM_SWI24 13 /* Obsolete static relocation. */
#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */
#define R_ARM_THM_SWI8 14 /* Reserved. */
#define R_ARM_XPC25 15 /* Reserved. */
#define R_ARM_THM_XPC22 16 /* Reserved. */
#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
#define R_ARM_COPY 20 /* Copy symbol at runtime */
#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
#define R_ARM_RELATIVE 23 /* Adjust by program base */
#define R_ARM_GOTOFF32 24 /* 32 bit offset to GOT */
#define R_ARM_BASE_PREL 25 /* 32 bit PC relative offset to GOT */
#define R_ARM_GOT_BREL 26 /* 32 bit GOT entry */
#define R_ARM_PLT32 27 /* Deprecated, 32 bit PLT address. */
#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */
#define R_ARM_JUMP24 29 /* PC relative 24 bit (B, BL<cond>). */
#define R_ARM_THM_JUMP24 30 /* PC relative 24 bit (Thumb32 B.W). */
#define R_ARM_BASE_ABS 31 /* Adjust by program base. */
#define R_ARM_ALU_PCREL_7_0 32 /* Obsolete. */
#define R_ARM_ALU_PCREL_15_8 33 /* Obsolete. */
#define R_ARM_ALU_PCREL_23_15 34 /* Obsolete. */
#define R_ARM_LDR_SBREL_11_0_NC 35 /* Deprecated, prog. base relative. */
#define R_ARM_ALU_SBREL_19_12_NC 36 /* Deprecated, prog. base relative. */
#define R_ARM_ALU_SBREL_27_20_CK 37 /* Deprecated, prog. base relative. */
#define R_ARM_TARGET1 38
#define R_ARM_SBREL31 39 /* Program base relative. */
#define R_ARM_V4BX 40
#define R_ARM_TARGET2 41
#define R_ARM_PREL31 42 /* 32 bit PC relative. */
#define R_ARM_MOVW_ABS_NC 43 /* Direct 16-bit (MOVW). */
#define R_ARM_MOVT_ABS 44 /* Direct high 16-bit (MOVT). */
#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */
#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */
#define R_ARM_THM_MOVW_ABS_NC 47 /* Direct 16 bit (Thumb32 MOVW). */
#define R_ARM_THM_MOVT_ABS 48 /* Direct high 16 bit (Thumb32 MOVT). */
#define R_ARM_THM_MOVW_PREL_NC 49 /* PC relative 16 bit (Thumb32 MOVW). */
#define R_ARM_THM_MOVT_PREL 50 /* PC relative high 16 bit (Thumb32 MOVT). */
#define R_ARM_THM_JUMP19 51 /* PC relative 20 bit (Thumb32 B<cond>.W). */
#define R_ARM_THM_JUMP6 52 /* PC relative X & 0x7E (Thumb16 CBZ, CBNZ). */
#define R_ARM_THM_ALU_PREL_11_0 53 /* PC relative 12 bit (Thumb32 ADR.W). */
#define R_ARM_THM_PC12 54 /* PC relative 12 bit (Thumb32 LDR{D,SB,H,SH}). */
#define R_ARM_ABS32_NOI 55 /* Direct 32-bit. */
#define R_ARM_REL32_NOI 56 /* PC relative 32-bit. */
#define R_ARM_ALU_PC_G0_NC 57 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G0 58 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G1_NC 59 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G1 60 /* PC relative (ADD, SUB). */
#define R_ARM_ALU_PC_G2 61 /* PC relative (ADD, SUB). */
#define R_ARM_LDR_PC_G1 62 /* PC relative (LDR,STR,LDRB,STRB). */
#define R_ARM_LDR_PC_G2 63 /* PC relative (LDR,STR,LDRB,STRB). */
#define R_ARM_LDRS_PC_G0 64 /* PC relative (STR{D,H}, LDR{D,SB,H,SH}). */
#define R_ARM_LDRS_PC_G1 65 /* PC relative (STR{D,H}, LDR{D,SB,H,SH}). */
#define R_ARM_LDRS_PC_G2 66 /* PC relative (STR{D,H}, LDR{D,SB,H,SH}). */
#define R_ARM_LDC_PC_G0 67 /* PC relative (LDC, STC). */
#define R_ARM_LDC_PC_G1 68 /* PC relative (LDC, STC). */
#define R_ARM_LDC_PC_G2 69 /* PC relative (LDC, STC). */
#define R_ARM_ALU_SB_G0_NC 70 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G0 71 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G1_NC 72 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G1 73 /* Program base relative (ADD,SUB). */
#define R_ARM_ALU_SB_G2 74 /* Program base relative (ADD,SUB). */
#define R_ARM_LDR_SB_G0 75 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDR_SB_G1 76 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDR_SB_G2 77 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDRS_SB_G0 78 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDRS_SB_G1 79 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDRS_SB_G2 80 /* Program base relative (LDR, STR, LDRB, STRB). */
#define R_ARM_LDC_SB_G0 81 /* Program base relative (LDC,STC). */
#define R_ARM_LDC_SB_G1 82 /* Program base relative (LDC,STC). */
#define R_ARM_LDC_SB_G2 83 /* Program base relative (LDC,STC). */
#define R_ARM_MOVW_BREL_NC 84 /* Program base relative 16 bit (MOVW). */
#define R_ARM_MOVT_BREL 85 /* Program base relative high 16 bit (MOVT). */
#define R_ARM_MOVW_BREL 86 /* Program base relative 16 bit (MOVW). */
#define R_ARM_THM_MOVW_BREL_NC 87 /* Program base relative 16 bit (Thumb32 MOVW). */
#define R_ARM_THM_MOVT_BREL 88 /* Program base relative high 16 bit (Thumb32 MOVT). */
#define R_ARM_THM_MOVW_BREL 89 /* Program base relative 16 bit (Thumb32 MOVW). */
#define R_ARM_TLS_GOTDESC 90
#define R_ARM_TLS_CALL 91
#define R_ARM_TLS_DESCSEQ 92 /* TLS relaxation. */
#define R_ARM_THM_TLS_CALL 93
#define R_ARM_PLT32_ABS 94
#define R_ARM_GOT_ABS 95 /* GOT entry. */
#define R_ARM_GOT_PREL 96 /* PC relative GOT entry. */
#define R_ARM_GOT_BREL12 97 /* GOT entry relative to GOT origin (LDR). */
#define R_ARM_GOTOFF12 98 /* 12 bit, GOT entry relative to GOT origin (LDR, STR). */
#define R_ARM_GOTRELAX 99
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
#define R_ARM_THM_JUMP11 102 /* PC relative & 0xFFE (Thumb16 B). */
#define R_ARM_THM_JUMP8 103 /* PC relative & 0x1FE (Thumb16 B/B<cond>). */
#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic thread local data */
#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic thread local data */
#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS block */
#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of static TLS block offset */
#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static TLS block */
#define R_ARM_TLS_LDO12 109 /* 12 bit relative to TLS block (LDR, STR). */
#define R_ARM_TLS_LE12 110 /* 12 bit relative to static TLS block (LDR, STR). */
#define R_ARM_TLS_IE12GP 111 /* 12 bit GOT entry relative to GOT origin (LDR). */
#define R_ARM_ME_TOO 128 /* Obsolete. */
#define R_ARM_THM_TLS_DESCSEQ 129
#define R_ARM_THM_TLS_DESCSEQ16 129
#define R_ARM_THM_TLS_DESCSEQ32 130
#define R_ARM_THM_GOT_BREL12 131 /* GOT entry relative to GOT origin, 12 bit (Thumb32 LDR). */
#define R_ARM_THM_ALU_ABS_G0_NC 132
#define R_ARM_THM_ALU_ABS_G1_NC 133
#define R_ARM_THM_ALU_ABS_G2_NC 134
#define R_ARM_THM_ALU_ABS_G3 135
#define R_ARM_THM_BF16 136
#define R_ARM_THM_BF12 137
#define R_ARM_THM_BF18 138
/*
ARM32 relocations:
139-159 Reserved for Future Allocation
160 Reserved for future functionality
161-176 Private relocations
177-255 Reserved for future allocations
*/
/* Keep this the last entry. */
#define R_ARM_NUM 256

View file

@ -229,3 +229,101 @@ ldr x0, [x0, 0x8c8]
bl reloc.target.fputs
EOF
RUN
NAME=arm R_ARM_PREL31 relocation
FILE=bins/elf/arm-reloc-prel31.o
CMDS=<<EOF
ir~R_ARM_PREL31?
pf w @ 0x08000038
pd 1 @ 0x08000038
EOF
EXPECT=<<EOF
1
0x08000038 = 0x0090
;-- section..data:
;-- foo:
;-- .data:
;-- reloc_slot:
0x08000038 .dword 0x00000090 ; RELOC 32 foo ; [02] -rw- section size 4 named .data
EOF
RUN
NAME=arm call/jump relocations
FILE=bins/elf/arm-reloc-call.o
CMDS=<<EOF
ir
pd 1 @ 0x08000038
pd 1 @ 0x0800003c
pd 1 @ 0x08000040
EOF
EXPECT=<<EOF
vaddr paddr target type name
---------------------------------------------------
0x08000038 0x00000038 0x08000034 R_ARM_CALL foo
0x0800003c 0x0000003c 0x08000034 R_ARM_JUMP24 foo
0x08000040 0x00000040 0x08000034 R_ARM_CALL foo
;-- foo:
;-- arm:
0x08000038 bl loc.arm ; RELOC 24 foo @ 0x08000034
;-- foo:
0x0800003c bl reloc.foo.800003c ; RELOC 24 foo @ 0x08000034
;-- foo:
0x08000040 blx foo ; RELOC 24 foo @ 0x08000034
EOF
RUN
NAME=arm alu group relocations
FILE=bins/elf/arm-reloc-alu-group.o
CMDS=<<EOF
ir
pd 2 @ 0x08000038
EOF
EXPECT=<<EOF
vaddr paddr target type name
------------------------------------------------------
0x08000038 0x00000038 0x08000034 R_ARM_ALU_PC_G0 foo
0x0800003c 0x0000003c 0x08000034 R_ARM_ALU_PC_G1 foo
;-- foo:
;-- test:
0x08000038 add r0, pc, -0x1000000 ; RELOC 32 foo @ 0x08000034
;-- foo:
0x0800003c add r0, r0, 0xff0000 ; RELOC 32 foo @ 0x08000034
EOF
RUN
NAME=arm dynamic R_ARM_JUMP_SLOT relocation
FILE=bins/elf/arm-reloc-jump-slot.so
CMDS=<<EOF
ir
pf w @ 0x000011c4
pd 1 @ 0x000011c4
EOF
EXPECT=<<EOF
vaddr paddr target type name
-------------------------------------------------------------
0x000011c4 0x000001c4 0x000011d0 R_ARM_JUMP_SLOT target_func
0x000011c4 = 0x11d0
;-- target_func:
0x000011c4 .dword 0x000011d0 ; reloc.target.target_func; RELOC 32 target_func
EOF
RUN
NAME=thumb32 R_ARM_THM_JUMP24 relocation
FILE=bins/elf/arm-reloc-thm-jump24.o
CMDS=<<EOF
ir
pd 1 @ 0x08000034
pf w @ 0x08000034
EOF
EXPECT=<<EOF
vaddr paddr target type name
-------------------------------------------------------
0x08000034 0x00000034 0x0800012c R_ARM_THM_JUMP24 foo
;-- section..text:
;-- foo:
;-- .text:
;-- _start:
,=< 0x08000034 b.w foo ; RELOC 24 foo ; [01] -r-x section size 4 named .text
0x08000034 = 0xf000
EOF
RUN