From 556710d26136527cd15a3d0ea6de7584d1a8f53e Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Fri, 3 Jul 2020 14:25:25 +0100 Subject: [PATCH] #1494: Fix incorrect handling of relocations for ARM BE8 binaries --- .../relocation/ARM_ElfRelocationHandler.java | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/Ghidra/Processors/ARM/src/main/java/ghidra/app/util/bin/format/elf/relocation/ARM_ElfRelocationHandler.java b/Ghidra/Processors/ARM/src/main/java/ghidra/app/util/bin/format/elf/relocation/ARM_ElfRelocationHandler.java index f245f7b77a..b2785c67da 100644 --- a/Ghidra/Processors/ARM/src/main/java/ghidra/app/util/bin/format/elf/relocation/ARM_ElfRelocationHandler.java +++ b/Ghidra/Processors/ARM/src/main/java/ghidra/app/util/bin/format/elf/relocation/ARM_ElfRelocationHandler.java @@ -41,7 +41,9 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { Program program = elfRelocationContext.getProgram(); Memory memory = program.getMemory(); - + + boolean instructionBigEndian = program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian(); + int type = relocation.getType(); if (type == ARM_ElfRelocationConstants.R_ARM_NONE) { return; @@ -62,8 +64,8 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { int newValue = 0; switch (type) { - case ARM_ElfRelocationConstants.R_ARM_PC24: { - int oldValue = memory.getInt(relocationAddress); + case ARM_ElfRelocationConstants.R_ARM_PC24: { // Target class: ARM Instruction + int oldValue = memory.getInt(relocationAddress, instructionBigEndian); newValue = (int) (symbolValue + addend); newValue -= (offset + 8); // PC relative, PC will be 8 bytes after inst start if (isThumb) { @@ -77,10 +79,10 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { else { newValue = (oldValue & 0xff000000) | ((newValue >> 2) & 0x00ffffff); } - memory.setInt(relocationAddress, newValue); + memory.setInt(relocationAddress, newValue, instructionBigEndian); break; } - case ARM_ElfRelocationConstants.R_ARM_ABS32: { + case ARM_ElfRelocationConstants.R_ARM_ABS32: { // Target class: Data int oldValue = memory.getInt(relocationAddress); newValue = (int) (symbolValue + addend + oldValue); if (isThumb) { @@ -89,7 +91,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { memory.setInt(relocationAddress, newValue); break; } - case ARM_ElfRelocationConstants.R_ARM_REL32: { + case ARM_ElfRelocationConstants.R_ARM_REL32: { // // Target class: Data newValue = (int) (symbolValue + addend); newValue -= (offset + 8); // PC relative, PC will be 8 bytes after inst start if (isThumb) { @@ -98,25 +100,25 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { memory.setInt(relocationAddress, newValue); break; } - case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G0: { - int oldValue = memory.getInt(relocationAddress); + case ARM_ElfRelocationConstants.R_ARM_LDR_PC_G0: { // Target class: ARM Instruction + int oldValue = memory.getInt(relocationAddress, instructionBigEndian); newValue = (int) (symbolValue + addend); newValue -= (offset + 8); // PC relative, PC will be 8 bytes after inst start newValue = (oldValue & 0xff7ff000) | ((~(newValue >> 31) & 1) << 23) | ((newValue >> 2) & 0xfff); - memory.setInt(relocationAddress, newValue); + memory.setInt(relocationAddress, newValue, instructionBigEndian); break; } - case ARM_ElfRelocationConstants.R_ARM_ABS16: { + case ARM_ElfRelocationConstants.R_ARM_ABS16: { // Target class: Data short sValue = (short) (symbolValue + addend); memory.setShort(relocationAddress, sValue); break; } - case ARM_ElfRelocationConstants.R_ARM_ABS12: { - int oldValue = memory.getInt(relocationAddress); + case ARM_ElfRelocationConstants.R_ARM_ABS12: { // Target class: ARM Instruction + int oldValue = memory.getInt(relocationAddress, instructionBigEndian); newValue = (int) (symbolValue + addend); newValue = (oldValue & 0xfffff000) | (newValue & 0x00000fff); - memory.setInt(relocationAddress, newValue); + memory.setInt(relocationAddress, newValue, instructionBigEndian); break; } /* @@ -124,7 +126,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { break; } */ - case ARM_ElfRelocationConstants.R_ARM_ABS_8: { + case ARM_ElfRelocationConstants.R_ARM_ABS_8: { // Target class: Data byte bValue = (byte) (symbolValue + addend); memory.setByte(relocationAddress, bValue); break; @@ -134,15 +136,15 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { break; } */ - case ARM_ElfRelocationConstants.R_ARM_THM_JUMP24: + case ARM_ElfRelocationConstants.R_ARM_THM_JUMP24: // // Target class: Thumb32 Instruction case ARM_ElfRelocationConstants.R_ARM_THM_CALL: { newValue = (int) (symbolValue + addend); // since it is adding in the oldvalue below, don't need to add in 4 for pc offset newValue -= (offset); - short oldValueH = memory.getShort(relocationAddress); - short oldValueL = memory.getShort(relocationAddress.add(2)); + short oldValueH = memory.getShort(relocationAddress, instructionBigEndian); + short oldValueL = memory.getShort(relocationAddress.add(2), instructionBigEndian); boolean isBLX = (oldValueL & 0x1000) == 0; int s = (oldValueH & (1 << 10)) >> 10; @@ -166,17 +168,17 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { newValueL &= 0xfffe; } - memory.setShort(relocationAddress, newValueH); - memory.setShort(relocationAddress.add(2), newValueL); + memory.setShort(relocationAddress, newValueH, instructionBigEndian); + memory.setShort(relocationAddress.add(2), newValueL, instructionBigEndian); break; } - case ARM_ElfRelocationConstants.R_ARM_THM_PC8: { - short oldValue = memory.getShort(relocationAddress); + case ARM_ElfRelocationConstants.R_ARM_THM_PC8: { // Target class: Thumb16 Instruction + short oldValue = memory.getShort(relocationAddress, instructionBigEndian); newValue = (int) (symbolValue + addend); newValue -= (offset + 4); // PC relative, PC will be 4 bytes past inst start newValue = newValue >> 1; short sValue = (short) ((oldValue & 0xff00) | (newValue & 0x00ff)); - memory.setShort(relocationAddress, sValue); + memory.setShort(relocationAddress, sValue, instructionBigEndian); break; } /* @@ -219,7 +221,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { break; } - case ARM_ElfRelocationConstants.R_ARM_JUMP_SLOT: { + case ARM_ElfRelocationConstants.R_ARM_JUMP_SLOT: { // Target class: Data // Corresponds to lazy dynamically linked external symbols within // GOT/PLT symbolValue corresponds to PLT entry for which we need to // create and external function location. Don't bother changing @@ -246,7 +248,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { break; } - case ARM_ElfRelocationConstants.R_ARM_RELATIVE: { + case ARM_ElfRelocationConstants.R_ARM_RELATIVE: { // Target class: Data if (elfRelocationContext.extractAddend()) { addend = memory.getInt(relocationAddress); } @@ -267,10 +269,10 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { } */ - case ARM_ElfRelocationConstants.R_ARM_JUMP24: + case ARM_ElfRelocationConstants.R_ARM_JUMP24: // Target class: ARM Instruction case ARM_ElfRelocationConstants.R_ARM_CALL: case ARM_ElfRelocationConstants.R_ARM_GOT_PLT32: - int oldValue = memory.getInt(relocationAddress); + int oldValue = memory.getInt(relocationAddress, instructionBigEndian); newValue = (int) (symbolValue + addend); newValue -= (offset + 8); // PC relative, PC will be 8 bytes past inst start @@ -284,7 +286,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler { else { newValue = (oldValue & 0xff000000) | ((newValue >> 2) & 0x00ffffff); } - memory.setInt(relocationAddress, newValue); + memory.setInt(relocationAddress, newValue, instructionBigEndian); break; /*