mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-12 21:23:07 +00:00
GP-1029 Detect and mark unsupported EXTERNAL data relocation and correct MIPS compound relocation processing bug.
This commit is contained in:
parent
066b285446
commit
e89a8dcde3
|
@ -22,6 +22,7 @@ import ghidra.app.util.importer.MessageLog;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
|
||||
|
@ -69,6 +70,48 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
ElfRelocation relocation, Address relocationAddress)
|
||||
throws MemoryAccessException, NotFoundException;
|
||||
|
||||
/**
|
||||
* Determine if symbolAddr is contained within the EXTERNAL block. If so, relocationAddress will be marked
|
||||
* with a <code<Unsupported EXTERNAL Data Elf Relocation</code> error bookmark.
|
||||
* NOTE: This method should only be invoked when the symbol offset will be adjust with a non-zero
|
||||
* value (i.e., addend).
|
||||
* @param program
|
||||
* @param relocationAddress relocation address to be bookmarked if EXTERNAL block relocation
|
||||
* @param symbolAddr symbol address correspondng to relocation (may be null)
|
||||
* @param symbolName symbol name (may not be null if symbolAddr is not null)
|
||||
* @param adjustment relocation symbol offset adjustment/addend
|
||||
* @param log import log
|
||||
* @return true if symbolAddress contained within EXTERNAL block.
|
||||
*/
|
||||
public static boolean isUnsupportedExternalRelocation(Program program,
|
||||
Address relocationAddress, Address symbolAddr, String symbolName, long adjustment,
|
||||
MessageLog log) {
|
||||
|
||||
if (symbolAddr == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryBlock block = program.getMemory().getBlock(symbolAddr);
|
||||
if (block == null || !MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String sign = "+";
|
||||
if (adjustment < 0) {
|
||||
adjustment = -adjustment;
|
||||
sign = "-";
|
||||
}
|
||||
String adjStr = sign + "0x" + Long.toHexString(adjustment);
|
||||
|
||||
symbolName = symbolName == null ? "<no name>" : symbolName;
|
||||
log.appendMsg("Unsupported EXTERNAL Data Elf Relocation: at " + relocationAddress +
|
||||
" (External Location = " + symbolName + adjStr + ")");
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR, "EXTERNAL Relocation",
|
||||
"Unsupported EXTERNAL Data Elf Relocation: External Location = " + symbolName + adjStr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate error log entry and bookmark at relocationAddress indicating
|
||||
* an unhandled relocation.
|
||||
|
|
|
@ -64,12 +64,17 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
boolean isBigEndianInstructions =
|
||||
program.getLanguage().getLanguageDescription().getInstructionEndian().isBigEndian();
|
||||
|
||||
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
long symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
long newValue = 0;
|
||||
|
||||
switch (type) {
|
||||
// .xword: (S+A)
|
||||
case AARCH64_ElfRelocationConstants.R_AARCH64_ABS64: {
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
newValue = (symbolValue + addend);
|
||||
memory.setLong(relocationAddress, newValue);
|
||||
break;
|
||||
|
|
|
@ -59,6 +59,7 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
long offset = (int) relocationAddress.getOffset();
|
||||
|
||||
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
long symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
|
||||
int newValue = 0;
|
||||
|
@ -85,6 +86,10 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
if (elfRelocationContext.extractAddend()) {
|
||||
addend = memory.getInt(relocationAddress);
|
||||
}
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
newValue = (int) (symbolValue + addend);
|
||||
if (isThumb) {
|
||||
newValue |= 1;
|
||||
|
@ -354,8 +359,9 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
oldValue = (oldValue ^ 0x8000) - 0x8000;
|
||||
|
||||
oldValue += symbolValue;
|
||||
if (type == ARM_ElfRelocationConstants.R_ARM_MOVT_ABS)
|
||||
if (type == ARM_ElfRelocationConstants.R_ARM_MOVT_ABS) {
|
||||
oldValue >>= 16;
|
||||
}
|
||||
|
||||
newValue &= 0xfff0f000;
|
||||
newValue |= ((oldValue & 0xf000) << 4) |
|
||||
|
|
|
@ -121,8 +121,8 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
ElfSymbol elfSymbol = mipsRelocationContext.getSymbol(symbolIndex);
|
||||
|
||||
Address symbolAddr = mipsRelocationContext.getSymbolAddress(elfSymbol);
|
||||
long symbolValue = mipsRelocationContext.getSymbolValue(elfSymbol);
|
||||
|
||||
String symbolName = elfSymbol.getNameAsString();
|
||||
|
||||
long addend = 0;
|
||||
|
@ -152,7 +152,6 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
}
|
||||
}
|
||||
|
||||
mipsRelocationContext.useSavedAddend = saveValue;
|
||||
mipsRelocationContext.savedAddendHasError = false;
|
||||
mipsRelocationContext.savedAddend = 0;
|
||||
|
||||
|
@ -407,7 +406,13 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
symbolValue = mipsRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
}
|
||||
value = (int) symbolValue;
|
||||
value += mipsRelocationContext.extractAddend() ? oldValue : addend;
|
||||
int a = (int) (mipsRelocationContext.extractAddend() ? oldValue : addend);
|
||||
// NOTE: this may not detect correctly for all combound relocations
|
||||
if (a != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, a, log)) {
|
||||
a = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
value += a;
|
||||
|
||||
newValue = value;
|
||||
writeNewValue = true;
|
||||
|
@ -720,6 +725,8 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
}
|
||||
}
|
||||
|
||||
mipsRelocationContext.useSavedAddend = saveValue;
|
||||
|
||||
}
|
||||
|
||||
private boolean isMIPS16Reloc(int type) {
|
||||
|
|
|
@ -66,6 +66,8 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
long offset = relocationAddress.getOffset();
|
||||
|
||||
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
|
||||
String symbolName = sym.getNameAsString();
|
||||
Address symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
long symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
|
||||
int oldValue = memory.getInt(relocationAddress);
|
||||
|
@ -93,7 +95,7 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
Symbol tocBaseSym = SymbolUtilities.getLabelOrFunctionSymbol(program,
|
||||
PowerPC64_ElfExtension.TOC_BASE, err -> log.error("PPC_ELF", err));
|
||||
if (tocBaseSym == null) {
|
||||
markAsError(program, relocationAddress, type, sym.getNameAsString(),
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"TOC_BASE unknown", log);
|
||||
return;
|
||||
}
|
||||
|
@ -104,7 +106,7 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
switch (type) {
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_COPY:
|
||||
markAsWarning(program, relocationAddress, "R_PPC64_COPY", sym.getNameAsString(),
|
||||
markAsWarning(program, relocationAddress, "R_PPC64_COPY", symbolName,
|
||||
symbolIndex, "Runtime copy not supported", elfRelocationContext.getLog());
|
||||
break;
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR32:
|
||||
|
@ -220,6 +222,10 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
case PowerPC64_ElfRelocationConstants.R_PPC64_UADDR64:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR64:
|
||||
case PowerPC64_ElfRelocationConstants.R_PPC64_GLOB_DAT:
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
value64 = symbolValue + addend;
|
||||
memory.setLong(relocationAddress, value64);
|
||||
break;
|
||||
|
@ -227,7 +233,6 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
memory.setLong(relocationAddress, toc);
|
||||
break;
|
||||
default:
|
||||
String symbolName = sym.getNameAsString();
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
elfRelocationContext.getLog());
|
||||
break;
|
||||
|
|
|
@ -63,7 +63,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
int offset = (int) relocationAddress.getOffset();
|
||||
|
||||
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
|
||||
int symbolValue;
|
||||
|
||||
// if (sym.isLocal() && sym.getSectionHeaderIndex() != ElfSectionHeaderConstants.SHN_UNDEF) {
|
||||
//
|
||||
// // see glibc - sysdeps/powerpc/powerpc32/dl-machine.h elf_machine_rela
|
||||
|
@ -75,20 +75,26 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
// symbolValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
// }
|
||||
// else {
|
||||
symbolValue = (int) elfRelocationContext.getSymbolValue(sym);
|
||||
Address symbolAddr = (elfRelocationContext.getSymbolAddress(sym));
|
||||
int symbolValue = (int) elfRelocationContext.getSymbolValue(sym);
|
||||
// }
|
||||
String symbolName = sym.getNameAsString();
|
||||
|
||||
int oldValue = memory.getInt(relocationAddress);
|
||||
int newValue = 0;
|
||||
|
||||
switch (type) {
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_COPY:
|
||||
markAsWarning(program, relocationAddress, "R_PPC_COPY", sym.getNameAsString(),
|
||||
markAsWarning(program, relocationAddress, "R_PPC_COPY", symbolName,
|
||||
symbolIndex, "Runtime copy not supported", elfRelocationContext.getLog());
|
||||
break;
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR32:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_UADDR32:
|
||||
case PowerPC_ElfRelocationConstants.R_PPC_GLOB_DAT:
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
newValue = symbolValue + addend;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
|
@ -194,13 +200,11 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
// TODO: Handle this case if needed - hopefully the EXTERNAL block is
|
||||
// not too far away since a fabricated GOT would be in the same block
|
||||
// and we may only have room in the plt for two instructions.
|
||||
String symbolName = sym.getNameAsString();
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
elfRelocationContext.getLog());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
String symbolName = sym.getNameAsString();
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
elfRelocationContext.getLog());
|
||||
break;
|
||||
|
|
|
@ -51,6 +51,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
long base = elfRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||
ElfSymbol sym = null;
|
||||
long symbolValue = 0;
|
||||
Address symbolAddr = null;
|
||||
String symbolName = null;
|
||||
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
|
@ -59,6 +60,7 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
}
|
||||
|
||||
if (null != sym) {
|
||||
symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
symbolName = sym.getNameAsString();
|
||||
}
|
||||
|
@ -94,6 +96,10 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
case RISCV_ElfRelocationConstants.R_RISCV_64:
|
||||
// Runtime relocation word64 = S + A
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
value64 = symbolValue + addend;
|
||||
memory.setLong(relocationAddress, value64);
|
||||
break;
|
||||
|
|
|
@ -59,12 +59,15 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
ElfSymbol sym = null;
|
||||
long symbolValue = 0;
|
||||
Address symbolAddr = null;
|
||||
String symbolName = null;
|
||||
|
||||
if (symbolIndex != 0) {
|
||||
sym = elfRelocationContext.getSymbol(symbolIndex);
|
||||
}
|
||||
|
||||
if (sym != null) {
|
||||
symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
symbolName = sym.getNameAsString();
|
||||
}
|
||||
|
@ -79,6 +82,10 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
switch (type) {
|
||||
case X86_32_ElfRelocationConstants.R_386_32:
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
value = (int) (symbolValue + addend);
|
||||
memory.setInt(relocationAddress, value);
|
||||
break;
|
||||
|
|
|
@ -59,16 +59,17 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
ElfSymbol sym = null;
|
||||
long symbolValue = 0;
|
||||
long st_value = 0;
|
||||
Address symbolAddr = null;
|
||||
String symbolName = null;
|
||||
long symbolSize = 0;
|
||||
|
||||
if (symbolIndex != 0) {
|
||||
sym = elfRelocationContext.getSymbol(symbolIndex);
|
||||
}
|
||||
|
||||
if (sym != null) {
|
||||
symbolAddr = elfRelocationContext.getSymbolAddress(sym);
|
||||
symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
st_value = sym.getValue();
|
||||
symbolName = sym.getNameAsString();
|
||||
symbolSize = sym.getSize();
|
||||
}
|
||||
|
@ -86,6 +87,10 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
"Runtime copy not supported", elfRelocationContext.getLog());
|
||||
break;
|
||||
case X86_64_ElfRelocationConstants.R_X86_64_64:
|
||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
||||
}
|
||||
value = symbolValue + addend;
|
||||
memory.setLong(relocationAddress, value);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue