#1494: Fix incorrect handling of relocations for ARM BE8 binaries

This commit is contained in:
WorksButNotTested 2020-07-03 14:25:25 +01:00 committed by ghidra1
parent 3fec48671c
commit 556710d261

View file

@ -42,6 +42,8 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
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;
/*