mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
#1494: Fix incorrect handling of relocations for ARM BE8 binaries
This commit is contained in:
parent
3fec48671c
commit
556710d261
1 changed files with 29 additions and 27 deletions
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue