GP-1029 Detect and mark unsupported EXTERNAL data relocation and correct MIPS compound relocation processing bug.

This commit is contained in:
ghidra1 2021-06-09 18:26:05 -04:00
parent 066b285446
commit e89a8dcde3
9 changed files with 102 additions and 14 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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) |

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;