GP-4737 - Improve ELF relocation handling of unresolved symbol

This commit is contained in:
ghidra1 2024-06-26 12:50:25 -04:00
parent 72d4a342a6
commit 036ef9d0db
20 changed files with 529 additions and 306 deletions

View File

@ -99,8 +99,8 @@ abstract public class AbstractElfRelocationHandler<T extends ElfRelocationType,
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // will never be null
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym); // may be null
long symbolValue = elfRelocationContext.getSymbolValue(sym);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
@ -122,12 +122,19 @@ abstract public class AbstractElfRelocationHandler<T extends ElfRelocationType,
/**
* Perform relocation fixup.
* <br>
* NOTE: This method will not be invoked if elfSymbol is null and
* {@link ElfRelocationContext#processRelocation(ElfRelocation, Address)} will report
* relocation failure.
* <br>
* NOTE: This method will not be invoked for {@code type} == 0/NONE and will be marked as
* skipped.
*
* @param elfRelocationContext relocation context
* @param relocation ELF relocation
* @param relocationType ELF relocation type enum value
* @param relocationAddress relocation target address (fixup location)
* @param elfSymbol relocation symbol (may be null)
* @param elfSymbol relocation symbol
* @param symbolAddr elfSymbol memory address (may be null)
* @param symbolValue unadjusted elfSymbol value (0 if no symbol)
* @param symbolName elfSymbol name (may be null)
@ -141,6 +148,39 @@ abstract public class AbstractElfRelocationHandler<T extends ElfRelocationType,
//
// Error and Warning markup methods
//
/**
* Check for unresolved relocation symbol. If symbol has not been resolved the associated
* symbol address will be null and the symbol value invalid.
* @param elfRelocationContext relocation context
* @param relocation ELF relocation
* @param relocationAddress relocation target address (fixup location)
* @return true if symbol was not resolved else false if symbol was resolved
*/
protected boolean handleUnresolvedSymbol(ElfRelocationContext<?> elfRelocationContext, ElfRelocation relocation,Address relocationAddress) {
int symbolIndex = relocation.getSymbolIndex();
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // will never be null
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym); // may be null
if (symbolIndex != 0 && symbolAddr == null) { // symbolValue will also be invalid
int typeId = relocation.getType();
T type = getRelocationType(typeId);
String symbolName = elfRelocationContext.getSymbolName(symbolIndex);
Program program = elfRelocationContext.getProgram();
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to resolve relocation symbol", elfRelocationContext.getLog());
return true;
}
return false;
}
// private String getRelocationTypeDetail(int typeId) {
// T relocationType = relocationTypesMap.get(typeId);

View File

@ -50,20 +50,45 @@ public class AARCH64_ElfRelocationHandler
ElfRelocation relocation, AARCH64_ElfRelocationType type, Address relocationAddress,
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
boolean isBigEndianInstructions =
program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
boolean is64bit = true;
boolean overflowCheck = true; // *_NC type relocations specify "no overflow check"
long newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_AARCH64_P32_RELATIVE:
is64bit = false;
case R_AARCH64_RELATIVE:
if (elfRelocationContext.extractAddend()) {
addend = getValue(memory, relocationAddress, is64bit);
}
newValue = elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
byteLength = setValue(memory, relocationAddress, newValue, is64bit);
return new RelocationResult(Status.APPLIED, byteLength);
case R_AARCH64_P32_COPY:
case R_AARCH64_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
switch (type) {
// .xword: (S+A)
@ -324,19 +349,18 @@ public class AARCH64_ElfRelocationHandler
// GOT/PLT symbolValue corresponds to PLT entry for which we need to
// create and external function location. Don't bother changing
// GOT entry bytes if it refers to .plt block
Address symAddress = elfRelocationContext.getSymbolAddress(sym);
MemoryBlock block = memory.getBlock(symAddress);
MemoryBlock block = memory.getBlock(symbolAddr);
// TODO: jump slots are always in GOT - not sure why PLT check is done
boolean isPltSym = block != null && block.getName().startsWith(".plt");
boolean isExternalSym =
block != null && MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName());
if (!isPltSym) {
byteLength =
setValue(memory, relocationAddress, symAddress.getOffset(), is64bit);
byteLength = setValue(memory, relocationAddress, symbolValue, is64bit);
}
if ((isPltSym || isExternalSym) && !StringUtils.isBlank(symbolName)) {
Function extFunction = elfRelocationContext.getLoadHelper()
.createExternalFunctionLinkage(symbolName, symAddress, null);
.createExternalFunctionLinkage(symbolName, symbolAddr, null);
if (extFunction == null) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to create external function", elfRelocationContext.getLog());
@ -346,24 +370,6 @@ public class AARCH64_ElfRelocationHandler
break;
}
case R_AARCH64_P32_RELATIVE:
is64bit = false;
case R_AARCH64_RELATIVE: {
if (elfRelocationContext.extractAddend()) {
addend = getValue(memory, relocationAddress, is64bit);
}
newValue = elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
byteLength = setValue(memory, relocationAddress, newValue, is64bit);
break;
}
case R_AARCH64_P32_COPY:
case R_AARCH64_COPY: {
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
default: {
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View File

@ -62,7 +62,6 @@ public class ARM_ElfRelocationHandler
boolean instructionBigEndian =
program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian();
boolean isThumb = isThumb(sym);
long addend = relocation.getAddend(); // will be 0 for REL case
@ -71,6 +70,32 @@ public class ARM_ElfRelocationHandler
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_ARM_RELATIVE: // Target class: Data
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue =
(int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + (int) addend;
memory.setInt(relocationAddress, newValue);
return new RelocationResult(Status.APPLIED, byteLength);
case R_ARM_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
boolean isThumb = isThumb(sym);
switch (type) {
case R_ARM_PC24: { // Target class: ARM Instruction
int oldValue = memory.getInt(relocationAddress, instructionBigEndian);
@ -260,20 +285,19 @@ public class ARM_ElfRelocationHandler
case 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
// create an external function location. Don't bother changing
// GOT entry bytes if it refers to .plt block
Address symAddress = elfRelocationContext.getSymbolAddress(sym);
MemoryBlock block = memory.getBlock(symAddress);
MemoryBlock block = memory.getBlock(symbolAddr);
// TODO: jump slots are always in GOT - not sure why PLT check is done
boolean isPltSym = block != null && block.getName().startsWith(".plt");
boolean isExternalSym =
block != null && MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName());
if (!isPltSym) {
memory.setInt(relocationAddress, (int) symAddress.getOffset());
memory.setInt(relocationAddress, (int) symbolValue);
}
if (isPltSym || isExternalSym) {
Function extFunction = elfRelocationContext.getLoadHelper()
.createExternalFunctionLinkage(symbolName, symAddress, null);
.createExternalFunctionLinkage(symbolName, symbolAddr, null);
if (extFunction == null) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to create external function", elfRelocationContext.getLog());
@ -282,16 +306,7 @@ public class ARM_ElfRelocationHandler
}
break;
}
case R_ARM_RELATIVE: { // Target class: Data
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue =
(int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + (int) addend;
memory.setInt(relocationAddress, newValue);
break;
}
/*
case R_ARM_GOTOFF32: {
break;
@ -680,12 +695,6 @@ public class ARM_ElfRelocationHandler
}
*/
case R_ARM_COPY: {
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
}
default: {
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View File

@ -50,13 +50,20 @@ public class AVR32_ElfRelocationHandler
throws MemoryAccessException {
Program program = elfRelocationContext.getProgram();
int symbolIndex = relocation.getSymbolIndex();
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
Memory memory = program.getMemory();
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = (int) relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
int oldValue = memory.getInt(relocationAddress);
@ -64,8 +71,6 @@ public class AVR32_ElfRelocationHandler
int newValueShiftToAligntoUpper = 0;
switch (type) {
case R_AVR32_NONE:
return RelocationResult.SKIPPED;
case R_AVR32_32:
int newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
memory.setInt(relocationAddress, newValue);

View File

@ -43,27 +43,42 @@ public class AVR8_ElfRelocationHandler
ElfRelocation relocation, AVR8_ElfRelocationType type, Address relocationAddress,
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
switch (type) {
case R_AVR_DIFF8:
case R_AVR_DIFF16:
case R_AVR_DIFF32:
// nothing to do
return RelocationResult.SKIPPED;
default:
break;
}
// WARNING: symbolValue is not in bytes.
// It is an addressable word offset within the symbols address space
Program program = elfRelocationContext.getProgram();
int symbolIndex = relocation.getSymbolIndex();
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
Memory memory = program.getMemory();
long addend = relocation.getAddend(); // will be 0 for REL case
// WARNING: offset is in bytes be careful, word address potentially with byte indexes
long offset = relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
int oldValue = memory.getShort(relocationAddress);
int newValue = 0;
int byteLength = 2; // most relocations affect 2-bytes (change if different)
switch (type) {
case R_AVR_NONE:
return RelocationResult.SKIPPED;
case R_AVR_32:
newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
@ -300,12 +315,6 @@ public class AVR8_ElfRelocationHandler
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
break;
case R_AVR_DIFF8:
case R_AVR_DIFF16:
case R_AVR_DIFF32:
// nothing to do
break;
case R_AVR_LDS_STS_16:
newValue = (((int) symbolValue + (int) addend));

View File

@ -59,14 +59,59 @@ public class Loongarch_ElfRelocationHandler
long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int symbolIndex = relocation.getSymbolIndex();
long value64 = 0;
int value32 = 0;
short value16 = 0;
byte value8 = 0;
byte[] bytes24 = new byte[3];
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_LARCH_RELATIVE:
// Runtime fixup for load-address *(void **) PC = B + A
if (elf.is32Bit()) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
else {
value64 = base + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
}
return new RelocationResult(Status.APPLIED, byteLength);
case R_LARCH_IRELATIVE:
if (elf.is32Bit()) {
value32 =
(int) (addend + elfRelocationContext.getImageBaseWordAdjustmentOffset());
memory.setInt(relocationAddress, value32);
}
else {
byteLength = 8;
value64 = addend + elfRelocationContext.getImageBaseWordAdjustmentOffset();
memory.setLong(relocationAddress, value64);
}
return new RelocationResult(Status.APPLIED, byteLength);
case R_LARCH_COPY:
// Runtime memory copy in executable memcpy (PC, RtAddr, sizeof (sym))
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
byte[] bytes24 = new byte[3];
switch (type) {
case R_LARCH_32:
@ -96,25 +141,6 @@ public class Loongarch_ElfRelocationHandler
}
break;
case R_LARCH_RELATIVE:
// Runtime fixup for load-address *(void **) PC = B + A
if (elf.is32Bit()) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
else {
value64 = base + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
}
break;
case R_LARCH_COPY:
// Runtime memory copy in executable memcpy (PC, RtAddr, sizeof (sym))
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_LARCH_JUMP_SLOT:
// Runtime PLT supporting (implementation-defined)
if (elf.is32Bit()) {
@ -137,19 +163,7 @@ public class Loongarch_ElfRelocationHandler
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_LARCH_IRELATIVE:
if (elf.is32Bit()) {
value32 =
(int) (addend + elfRelocationContext.getImageBaseWordAdjustmentOffset());
memory.setInt(relocationAddress, value32);
}
else {
byteLength = 8;
value64 = addend + elfRelocationContext.getImageBaseWordAdjustmentOffset();
memory.setLong(relocationAddress, value64);
}
break;
// case R_LARCH_MARK_LA:
// case R_LARCH_MARK_PCREL:

View File

@ -62,6 +62,8 @@ public class MIPS_ElfRelocationHandler
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
// TODO: May need to add support for when symbol is not resolved, see handleUnresolvedSymbol
// Determine if result value should be saved as addend for next relocation
final boolean saveValue = elfRelocationContext.saveValueForNextReloc;
@ -633,20 +635,19 @@ public class MIPS_ElfRelocationHandler
case R_MICROMIPS_JALR:
boolean success = false;
Address symAddr = elfRelocationContext.getSymbolAddress(elfSymbol);
if (symAddr != null) {
MemoryBlock block = memory.getBlock(symAddr);
if (symbolAddr != null) {
MemoryBlock block = memory.getBlock(symbolAddr);
if (block != null) {
if (MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName())) {
success = elfRelocationContext.getLoadHelper()
.createExternalFunctionLinkage(symbolName, symAddr,
.createExternalFunctionLinkage(symbolName, symbolAddr,
null) != null;
if (success) {
// Inject appropriate JAL instruction
if (type == MIPS_ElfRelocationType.R_MICROMIPS_JALR) {
int offsetBits = (int) (symAddr.getOffset() >> 1) & 0x3ffffff;
int offsetBits = (int) (symbolValue >> 1) & 0x3ffffff;
// TODO: upper bits should really come from delay slot
int microJalrBits = 0xf4000000 | offsetBits;
memory.setShort(relocationAddress,
@ -655,7 +656,7 @@ public class MIPS_ElfRelocationHandler
(short) microJalrBits);
}
else {
int offsetBits = (int) (symAddr.getOffset() >> 2) & 0x3ffffff;
int offsetBits = (int) (symbolValue >> 2) & 0x3ffffff;
// TODO: upper bits should really come from delay slot
int jalrBits = 0x0c000000 | offsetBits;
memory.setInt(relocationAddress, jalrBits);

View File

@ -66,6 +66,11 @@ public class PIC30_ElfRelocationHandler
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();

View File

@ -62,15 +62,11 @@ public class PowerPC64_ElfRelocationHandler
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
long addend = relocation.getAddend();
long offset = relocationAddress.getOffset();
int symbolIndex = relocation.getSymbolIndex();
int oldValue = memory.getInt(relocationAddress);
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// IMPORTANT NOTE:
// Handling of Object modules (*.o) is currently problematic since relocations
@ -102,12 +98,40 @@ public class PowerPC64_ElfRelocationHandler
break;
default:
}
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_PPC64_RELATIVE:
long value64 = elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
memory.setLong(relocationAddress, value64);
return new RelocationResult(Status.APPLIED, 8);
case R_PPC64_TOC:
memory.setLong(relocationAddress, toc);
return new RelocationResult(Status.APPLIED, 8);
case R_PPC64_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
int oldValue = memory.getInt(relocationAddress);
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case R_PPC64_ADDR32:
newValue = (int) (symbolValue + addend);
memory.setInt(relocationAddress, newValue);
@ -179,11 +203,6 @@ public class PowerPC64_ElfRelocationHandler
newValue = (oldValue & ~PPC64_LOW24) | newValue;
memory.setInt(relocationAddress, newValue);
break;
case R_PPC64_RELATIVE:
long value64 = elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
break;
case R_PPC64_REL32:
newValue = (int) (symbolValue + addend - offset);
memory.setInt(relocationAddress, newValue);
@ -230,7 +249,7 @@ public class PowerPC64_ElfRelocationHandler
case R_PPC64_UADDR64:
case R_PPC64_ADDR64:
case R_PPC64_GLOB_DAT:
value64 = symbolValue + addend;
long value64 = symbolValue + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
if (symbolIndex != 0 && addend != 0 && !sym.isSection()) {
@ -239,10 +258,6 @@ public class PowerPC64_ElfRelocationHandler
applyComponentOffsetPointer(program, relocationAddress, addend);
}
break;
case R_PPC64_TOC:
memory.setLong(relocationAddress, toc);
byteLength = 8;
break;
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View File

@ -71,6 +71,33 @@ public class PowerPC_ElfRelocationHandler extends
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
int addend = (int) relocation.getAddend();
long relocbase = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_PPC_RELATIVE:
newValue = (int) relocbase + addend;
memory.setInt(relocationAddress, newValue);
return new RelocationResult(Status.APPLIED, byteLength);
case R_PPC_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
// if (sym.isLocal() && sym.getSectionHeaderIndex() != ElfSectionHeaderConstants.SHN_UNDEF) {
//
@ -83,18 +110,11 @@ public class PowerPC_ElfRelocationHandler extends
// symbolValue = elfRelocationContext.getImageBaseWordAdjustmentOffset();
// }
long relocbase = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int offset = (int) relocationAddress.getOffset();
int oldValue = memory.getInt(relocationAddress);
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
switch (type) {
case R_PPC_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_PPC_ADDR32:
case R_PPC_UADDR32:
case R_PPC_GLOB_DAT:
@ -162,10 +182,6 @@ public class PowerPC_ElfRelocationHandler extends
newValue = (oldValue & ~PPC_LOW24) | newValue;
memory.setInt(relocationAddress, newValue);
break;
case R_PPC_RELATIVE:
newValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
memory.setInt(relocationAddress, newValue);
break;
case R_PPC_REL32:
newValue = ((int) symbolValue + addend - offset);
memory.setInt(relocationAddress, newValue);
@ -216,8 +232,7 @@ public class PowerPC_ElfRelocationHandler extends
oldValue = memory.getInt(relocationAddress);
Address symAddr = elfRelocationContext.getSymbolAddress(sym);
MemoryBlock block = memory.getBlock(symAddr);
MemoryBlock block = memory.getBlock(symbolAddr);
Integer sdaBase = null;
Integer gprID = null;

View File

@ -154,7 +154,7 @@ public class RISCV_ElfRelocationHandler
long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
int symbolIndex = relocation.getSymbolIndex();
long value64 = 0;
int value32 = 0;
short value16 = 0;
@ -162,6 +162,67 @@ public class RISCV_ElfRelocationHandler
int target = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_RISCV_RELATIVE:
// Runtime relocation word32,64 = B + A
if (elf.is32Bit()) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
else {
value64 = base + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
}
return new RelocationResult(Status.APPLIED, byteLength);
case R_RISCV_PCREL_LO12_S:
// PC-relative reference %pcrel_lo(symbol) (S-Type)
// S-type immediates split the 12 bit value into separate 7 bit and 5 bit fields.
// Warning: untested!
target = getSymbolValueIndirect(elfRelocationContext, sym,
relocationAddress.getOffset() - relocation.getOffset());
if (target == 0) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to locate HI20 relocation", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
value32 = ((target & 0x000007f) << 25) | (target & 0x00000f80) |
(memory.getInt(relocationAddress) & 0x1fff07f);
memory.setInt(relocationAddress, value32);
return new RelocationResult(Status.APPLIED, byteLength);
case R_RISCV_PCREL_LO12_I:
// PC-relative reference %pcrel_lo(symbol) (I-Type), relative to the cited pc_rel_hi20
target = getSymbolValueIndirect(elfRelocationContext, sym,
relocationAddress.getOffset() - relocation.getOffset());
if (target == 0) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to locate HI20 relocation", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
value32 =
((target & 0x00000fff) << 20) | (memory.getInt(relocationAddress) & 0xfffff);
memory.setInt(relocationAddress, value32);
return new RelocationResult(Status.APPLIED, byteLength);
case R_RISCV_COPY:
// Runtime relocation must be in executable. not allowed in shared library
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
switch (type) {
case R_RISCV_32:
@ -191,25 +252,6 @@ public class RISCV_ElfRelocationHandler
}
break;
case R_RISCV_RELATIVE:
// Runtime relocation word32,64 = B + A
if (elf.is32Bit()) {
value32 = (int) (base + addend);
memory.setInt(relocationAddress, value32);
}
else {
value64 = base + addend;
memory.setLong(relocationAddress, value64);
byteLength = 8;
}
break;
case R_RISCV_COPY:
// Runtime relocation must be in executable. not allowed in shared library
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_RISCV_JUMP_SLOT:
// Runtime relocation word32,64 = S ;handled by PLT unless LD_BIND_NOW
if (elf.is32Bit()) {
@ -278,36 +320,6 @@ public class RISCV_ElfRelocationHandler
getHi20(target) | (memory.getInt(relocationAddress) & 0xfff));
break;
case R_RISCV_PCREL_LO12_I:
// PC-relative reference %pcrel_lo(symbol) (I-Type), relative to the cited pc_rel_hi20
target = getSymbolValueIndirect(elfRelocationContext, sym,
relocationAddress.getOffset() - relocation.getOffset());
if (target == 0) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to locate HI20 relocation", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
value32 =
((target & 0x00000fff) << 20) | (memory.getInt(relocationAddress) & 0xfffff);
memory.setInt(relocationAddress, value32);
break;
case R_RISCV_PCREL_LO12_S:
// PC-relative reference %pcrel_lo(symbol) (S-Type)
// S-type immediates split the 12 bit value into separate 7 bit and 5 bit fields.
// Warning: untested!
target = getSymbolValueIndirect(elfRelocationContext, sym,
relocationAddress.getOffset() - relocation.getOffset());
if (target == 0) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Failed to locate HI20 relocation", elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
value32 = ((target & 0x000007f) << 25) | (target & 0x00000f80) |
(memory.getInt(relocationAddress) & 0x1fff07f);
memory.setInt(relocationAddress, value32);
break;
case R_RISCV_HI20:
// Absolute address %hi(symbol) (U-Type)
value32 = (int) ((symbolValue + 0x800) & 0xfffff000) |

View File

@ -58,6 +58,28 @@ public class SPARC_ElfRelocationHandler
int oldValue = memory.getInt(relocationAddress);
int newValue = 0;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_SPARC_RELATIVE:
newValue = (int) elfRelocationContext.getElfHeader().getImageBase() + (int) addend;
memory.setInt(relocationAddress, newValue);
return new RelocationResult(Status.APPLIED, byteLength);
case R_SPARC_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
switch (type) {
case R_SPARC_DISP32:
@ -87,18 +109,10 @@ public class SPARC_ElfRelocationHandler
newValue = (int) symbolValue;
memory.setInt(relocationAddress, newValue);
break;
case R_SPARC_RELATIVE:
newValue = (int) elfRelocationContext.getElfHeader().getImageBase() + (int) addend;
memory.setInt(relocationAddress, newValue);
break;
case R_SPARC_UA32:
newValue = (int) symbolValue + (int) addend;
memory.setInt(relocationAddress, newValue);
break;
case R_SPARC_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View File

@ -54,6 +54,31 @@ public class SH_ElfRelocationHandler
int newValue = 0;
int oldValue;
int byteLength = 4; // most relocations affect 4-bytes (change if different)
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_SH_RELATIVE:
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue = (int) (elfRelocationContext.getImageBaseWordAdjustmentOffset()) + addend;
memory.setInt(relocationAddress, newValue);
return new RelocationResult(Status.APPLIED, byteLength);
case R_SH_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
switch (type) {
case R_SH_DIR32:
@ -123,19 +148,6 @@ public class SH_ElfRelocationHandler
byteLength = 2;
break;
case R_SH_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_SH_RELATIVE:
if (elfRelocationContext.extractAddend()) {
addend = memory.getInt(relocationAddress);
}
newValue = (int) (elfRelocationContext.getImageBaseWordAdjustmentOffset()) + addend;
memory.setInt(relocationAddress, newValue);
break;
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());

View File

@ -46,8 +46,14 @@ public class MSP430X_ElfRelocationHandler
ElfSymbol elfSymbol, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = relocationAddress.getOffset();

View File

@ -46,8 +46,14 @@ public class MSP430_ElfRelocationHandler
ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName)
throws MemoryAccessException {
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
Program program = elfRelocationContext.getProgram();
Memory memory = program.getMemory();
int symbolIndex = relocation.getSymbolIndex();
long addend = relocation.getAddend(); // will be 0 for REL case
long offset = relocationAddress.getOffset();

View File

@ -57,6 +57,24 @@ public class Xtensa_ElfRelocationHandler
int byteLength = -1;
int newValue;
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_XTENSA_RELATIVE:
newValue = ((int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend);
memory.setInt(relocationAddress, newValue);
byteLength = 4;
return new RelocationResult(Status.APPLIED, byteLength);
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
int diff_mask = 0;
boolean neg = false;
@ -71,12 +89,6 @@ public class Xtensa_ElfRelocationHandler
// case R_XTENSA_RTLD:
case R_XTENSA_RELATIVE:
newValue = ((int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend);
memory.setInt(relocationAddress, newValue);
byteLength = 4;
break;
case R_XTENSA_GLOB_DAT:
case R_XTENSA_JMP_SLOT:
case R_XTENSA_PLT:

View File

@ -54,6 +54,12 @@ public class eBPF_ElfRelocationHandler
}
int symbolIndex = relocation.getSymbolIndex();
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
long new_value = 0;
int byteLength = 8;

View File

@ -60,6 +60,33 @@ public class Tricore_ElfRelocationHandler
long rv = 0;
int byteLength = -1;
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_TRICORE_RELATIVE:
long base = program.getImageBase().getOffset();
rv = (int) (base + addend);
byteLength = relocate_word32(memory, relocationAddress, rv);
return new RelocationResult(Status.APPLIED, byteLength);
case R_TRICORE_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_TRICORE_BITPOS:
// This reads as a pseudo relocation, possibly do RelocationResult.PARTIAL instead?
return RelocationResult.SKIPPED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
/**
* Key S indicates the final value assigned to the symbol referenced in the
@ -274,21 +301,6 @@ public class Tricore_ElfRelocationHandler
memory.setInt(relocationAddress, (int) symbolValue);
break;
case R_TRICORE_RELATIVE:
long base = program.getImageBase().getOffset();
rv = (int) (base + addend);
byteLength = relocate_word32(memory, relocationAddress, rv);
break;
case R_TRICORE_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_TRICORE_BITPOS:
// This reads as a pseudo relocation, possibly do RelocationResult.PARTIAL instead?
return RelocationResult.SKIPPED;
/**
case R_TRICORE_SBREG_S2:
break;

View File

@ -62,6 +62,65 @@ public class X86_32_ElfRelocationHandler
int byteLength = 4; // most relocations affect 4-bytes (change if different)
int value;
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_386_RELATIVE:
long base = program.getImageBase().getOffset();
if (elfRelocationContext.getElfHeader().isPreLinked()) {
// adjust prelinked value that is already in memory
value = memory.getInt(relocationAddress) +
(int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
}
else {
value = (int) (base + addend);
}
memory.setInt(relocationAddress, value);
return new RelocationResult(Status.APPLIED, byteLength);
case R_386_IRELATIVE:
// NOTE: We don't support this since the code actually uses a function to
// compute the relocation value (i.e., indirect)
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Indirect computed relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_386_GOTPC:
// similar to R_386_PC32 but uses .got address instead of symbol address
try {
long dotgot = elfRelocationContext.getGOTValue();
value = (int) (dotgot + addend - offset);
memory.setInt(relocationAddress, value);
}
catch (NotFoundException e) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
e.getMessage(), elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
return new RelocationResult(Status.APPLIED, byteLength);
case R_386_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// Thread Local Symbol relocations (unimplemented concept)
case R_386_TLS_DTPMOD32:
case R_386_TLS_DTPOFF32:
case R_386_TLS_TPOFF32:
case R_386_TLS_TPOFF:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
switch (type) {
case R_386_32:
value = (int) (symbolValue + addend);
@ -102,54 +161,6 @@ public class X86_32_ElfRelocationHandler
return RelocationResult.FAILURE;
}
break;
case R_386_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// Thread Local Symbol relocations (unimplemented concept)
case R_386_TLS_DTPMOD32:
case R_386_TLS_DTPOFF32:
case R_386_TLS_TPOFF32:
case R_386_TLS_TPOFF:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// cases which do not use symbol value
case R_386_RELATIVE:
long base = program.getImageBase().getOffset();
if (elfRelocationContext.getElfHeader().isPreLinked()) {
// adjust prelinked value that is already in memory
value = memory.getInt(relocationAddress) +
(int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
}
else {
value = (int) (base + addend);
}
memory.setInt(relocationAddress, value);
break;
case R_386_IRELATIVE:
// NOTE: We don't support this since the code actually uses a function to
// compute the relocation value (i.e., indirect)
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
"Indirect computed relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_386_GOTPC:
// similar to R_386_PC32 but uses .got address instead of symbol address
try {
long dotgot = elfRelocationContext.getGOTValue();
value = (int) (dotgot + addend - offset);
memory.setInt(relocationAddress, value);
}
catch (NotFoundException e) {
markAsError(program, relocationAddress, type, symbolName, symbolIndex,
e.getMessage(), elfRelocationContext.getLog());
return RelocationResult.FAILURE;
}
break;
// TODO: Cases not yet examined
// case R_386_32PLT

View File

@ -66,12 +66,56 @@ public class X86_64_ElfRelocationHandler extends
int symbolIndex = relocation.getSymbolIndex();
int byteLength = 8; // most relocations affect 8-bytes (change if different)
long value;
// Handle relative relocations that do not require symbolAddr or symbolValue
switch (type) {
case R_X86_64_RELATIVE:
// word64 for LP64 and specifies word32 for ILP32,
// we assume LP64 only. We probably need a hybrid
// variant to handle the ILP32 case.
case R_X86_64_RELATIVE64:
// dl_machine.h
// value = (Elf64_64Addr) map->l_addr + reloc->r_addend
long imageBaseAdjustment = elfRelocationContext.getImageBaseWordAdjustmentOffset();
if (elfRelocationContext.getElfHeader().isPreLinked()) {
// adjust prelinked value that is already in memory
value = memory.getLong(relocationAddress) + imageBaseAdjustment;
}
else {
value = addend + imageBaseAdjustment;
}
memory.setLong(relocationAddress, value);
return new RelocationResult(Status.APPLIED, byteLength);
case R_X86_64_IRELATIVE:
value = addend + elfRelocationContext.getImageBaseWordAdjustmentOffset();
memory.setLong(relocationAddress, value);
return new RelocationResult(Status.APPLIED, byteLength);
// Thread Local Symbol relocations (unimplemented concept)
case R_X86_64_DTPMOD64:
case R_X86_64_DTPOFF64:
case R_X86_64_TPOFF64:
case R_X86_64_TLSDESC:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
case R_X86_64_COPY:
markAsUnsupportedCopy(program, relocationAddress, type, symbolName, symbolIndex,
sym.getSize(), elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
default:
break;
}
// Check for unresolved symbolAddr and symbolValue required by remaining relocation types handled below
if (handleUnresolvedSymbol(elfRelocationContext, relocation, relocationAddress)) {
return RelocationResult.FAILURE;
}
switch (type) {
case R_X86_64_64:
value = symbolValue + addend;
memory.setLong(relocationAddress, value);
@ -156,15 +200,6 @@ public class X86_64_ElfRelocationHandler extends
memory.setLong(relocationAddress, value);
break;
// Thread Local Symbol relocations (unimplemented concept)
case R_X86_64_DTPMOD64:
case R_X86_64_DTPOFF64:
case R_X86_64_TPOFF64:
case R_X86_64_TLSDESC:
markAsWarning(program, relocationAddress, type, symbolName, symbolIndex,
"Thread Local Symbol relocation not supported", elfRelocationContext.getLog());
return RelocationResult.UNSUPPORTED;
// cases which do not use symbol value
case R_X86_64_GOTPC32:
@ -258,28 +293,6 @@ public class X86_64_ElfRelocationHandler extends
value = symbolGotAddress.getOffset() + addend - offset;
memory.setLong(relocationAddress, value);
case R_X86_64_RELATIVE:
// word64 for LP64 and specifies word32 for ILP32,
// we assume LP64 only. We probably need a hybrid
// variant to handle the ILP32 case.
case R_X86_64_RELATIVE64:
// dl_machine.h
// value = (Elf64_64Addr) map->l_addr + reloc->r_addend
long imageBaseAdjustment = elfRelocationContext.getImageBaseWordAdjustmentOffset();
if (elfRelocationContext.getElfHeader().isPreLinked()) {
// adjust prelinked value that is already in memory
value = memory.getLong(relocationAddress) + imageBaseAdjustment;
}
else {
value = addend + imageBaseAdjustment;
}
memory.setLong(relocationAddress, value);
break;
case R_X86_64_IRELATIVE:
value = addend + elfRelocationContext.getImageBaseWordAdjustmentOffset();
memory.setLong(relocationAddress, value);
break;
// case ElfRelocationConstants.R_X86_64_TLSGD:
// case ElfRelocationConstants.R_X86_64_TLSLD:
// case ElfRelocationConstants.R_X86_64_DTPOFF32: