GP-302 corrected issue affected ELF PLTGOT bounds determination.

Corrected various pointer and data related issues
This commit is contained in:
ghidra1 2020-10-23 18:57:11 -04:00
parent 1c145dd781
commit 6107f29a95
6 changed files with 105 additions and 53 deletions

View file

@ -217,7 +217,7 @@ public class AddressTable {
* @param end end index (inclusive)
* @param createIndex don't create index if false
* @param autoLabel true if labels should be created on the table
* @return
* @return true if tablecreated else false
*/
public boolean makeTable(Program program, int start, int end, boolean createIndex,
boolean autoLabel) {
@ -236,13 +236,17 @@ public class AddressTable {
//TODO: Do I need to do something special for the 3 byte pointers or will it know
// how to make it automatically?
DataTypeManager dtm = program.getDataTypeManager();
if (shiftedAddr) {
adt = ShiftedAddressDataType.dataType;
}
else {
adt = new PointerDataType(DataType.DEFAULT, addrSize);
else if (addrSize == program.getDefaultPointerSize()) {
adt = new PointerDataType(DataType.DEFAULT, dtm);
}
adt = program.getDataTypeManager().resolve(adt, null);
else {
adt = new PointerDataType(DataType.DEFAULT, addrSize, dtm);
}
adt = dtm.resolve(adt, null);
Address newAddress = currentAddress;

View file

@ -122,20 +122,37 @@ public class ElfDefaultGotPltMarkup {
if (relocationTable == null) {
return;
}
ElfRelocation[] relocations = relocationTable.getRelocations();
int count = relocations.length;
// First few entries of GOT do not correspond to dynamic symbols.
// First relocation address must be used to calculate GOT end address
// based upon the total number of relocation entries.
long firstGotEntryOffset = relocations[0].getOffset() + imageBaseAdj;
// External dynamic symbol entries in the PLTGOT, if any, will be placed
// after any local symbol entries.
// While DT_PLTGOT identifies the start of the PLTGOT it does not
// specify its length. If there are dynamic non-local entries in the
// PLTGOT they should have relocation entries in the table identified
// by DT_JMPREL. It is important to note that this relocation table
// can include entries which affect other processor-specific PLTGOT
// tables (e.g., MIPS_PLTGOT) so we must attempt to isolate the
// entries which correspond to DT_PLTGOT.
// WARNING: This implementation makes a potentially bad assumption that
// the last relocation entry will identify the endof the PLTGOT if its
// offset is beyond the start of the PLTGOT. This assumption could
// easily be violated by a processor-specific PLTGOT which falls after
// the standard PLTGOT in memory and shares the same relocation table.
long pltgot = elf.adjustAddressForPrelink(
dynamicTable.getDynamicValue(ElfDynamicType.DT_PLTGOT)) + imageBaseAdj;
dynamicTable.getDynamicValue(ElfDynamicType.DT_PLTGOT));
ElfRelocation[] relocations = relocationTable.getRelocations();
long lastGotOffset = relocations[relocations.length - 1].getOffset();
if (lastGotOffset < pltgot) {
return;
}
Address gotStart = defaultSpace.getAddress(pltgot + imageBaseAdj);
Address gotEnd = defaultSpace.getAddress(lastGotOffset + imageBaseAdj);
Address gotStart = defaultSpace.getAddress(pltgot);
Address gotEnd = defaultSpace.getAddress(
firstGotEntryOffset + (count * defaultSpace.getPointerSize()) - 1);
processGOT(gotStart, gotEnd, monitor);
processDynamicPLT(gotStart, gotEnd, monitor);
}
@ -162,7 +179,7 @@ public class ElfDefaultGotPltMarkup {
try {
Address newImageBase = null;
while (gotStart.compareTo(gotEnd) < 0) {
while (gotStart.compareTo(gotEnd) <= 0) {
monitor.checkCanceled();
Data data = createPointer(gotStart, true);
@ -350,7 +367,7 @@ public class ElfDefaultGotPltMarkup {
return null;
}
int pointerSize = program.getDataTypeManager().getDataOrganization().getPointerSize();
Pointer pointer = PointerDataType.dataType;
Pointer pointer = PointerDataType.dataType.clone(program.getDataTypeManager());
if (elf.is32Bit() && pointerSize != 4) {
pointer = Pointer32DataType.dataType;
}
@ -364,20 +381,50 @@ public class ElfDefaultGotPltMarkup {
}
data = listing.createData(addr, pointer);
}
Address refAddr = (Address) data.getValue();
if (keepRefWhenValid) {
if (memory.contains(refAddr)) {
return data;
}
Symbol syms[] = program.getSymbolTable().getSymbols(refAddr);
if (syms != null && syms.length > 0 && syms[0].getSource() != SourceType.DEFAULT) {
return data;
}
if (keepRefWhenValid && isValidPointer(data)) {
setConstant(data);
}
else {
removeMemRefs(data);
}
removeMemRefs(data);
return data;
}
/**
* Set specified data as constant if contained within a writable block. It can be helpful
* to the decompiler results if constant pointers are marked as such (e.g., GOT entries)
* @param data program data
*/
public static void setConstant(Data data) {
Memory memory = data.getProgram().getMemory();
MemoryBlock block = memory.getBlock(data.getAddress());
if (!block.isWrite() || block.getName().startsWith(ElfSectionHeaderConstants.dot_got)) {
// .got blocks will be force to read-only by ElfDefaultGotPltMarkup
return;
}
data.setLong(MutabilitySettingsDefinition.MUTABILITY,
MutabilitySettingsDefinition.CONSTANT);
}
/**
* Determine if pointerData refers to a valid memory address or symbol
* @param pointerData pointer data
* @return true if pointer data refers to valid memory address or symbol
*/
public static boolean isValidPointer(Data pointerData) {
Program program = pointerData.getProgram();
Memory memory = program.getMemory();
Address refAddr = (Address) pointerData.getValue();
if (memory.contains(refAddr)) {
return true;
}
Symbol syms[] = program.getSymbolTable().getSymbols(refAddr);
if (syms != null && syms.length > 0 && syms[0].getSource() != SourceType.DEFAULT) {
return true;
}
return false;
}
private void removeMemRefs(Data data) {
if (data != null) {
Reference[] refs = data.getValueReferences();

View file

@ -125,12 +125,19 @@ public final class DataUtilities {
existingDataLen = data.getLength();
existingDT = data.getDataType();
if (data.isDefined() && newDataType.isEquivalent(existingDT)) {
return data;
}
// Check for external reference on pointer
Reference[] refs = refMgr.getReferencesFrom(addr);
for (Reference ref : refs) {
if (ref.getOperandIndex() == 0 && ref.isExternalReference()) {
extRef = ref;
break;
if (existingDT instanceof Pointer) {
// TODO: This can probably be eliminated
Reference[] refs = refMgr.getReferencesFrom(addr);
for (Reference ref : refs) {
if (ref.getOperandIndex() == 0 && ref.isExternalReference()) {
extRef = ref;
break;
}
}
}
}
@ -192,11 +199,11 @@ public final class DataUtilities {
private static void checkEnoughSpace(Program program, Address addr, int existingDataLen,
DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException {
Listing listing = program.getListing();
int newSize = dti.getLength();
if (newSize <= existingDataLen) {
listing.clearCodeUnits(addr, addr, false);
return;
}
// int newSize = dti.getLength();
// if (newSize <= existingDataLen) {
// listing.clearCodeUnits(addr, addr, false);
// return;
// }
try {
Address end = addr.addNoWrap(existingDataLen - 1);
Address newEnd = addr.addNoWrap(dti.getLength() - 1);

View file

@ -60,7 +60,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
* organization when resolved.
*/
public PointerDataType() {
this(null, -1, null);
this(DataType.DEFAULT, -1, null);
}
/**
@ -72,7 +72,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
* @param dtm data-type manager whose data organization should be used
*/
public PointerDataType(DataTypeManager dtm) {
this(null, -1, dtm);
this(DataType.DEFAULT, -1, dtm);
}
/**
@ -142,7 +142,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
}
@Override
public final DataType clone(DataTypeManager dtm) {
public final Pointer clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;
}

View file

@ -744,7 +744,9 @@ public class MIPS_ElfExtension extends ElfExtension {
Address gotEntryAddr =
adjustTableEntryIfNonZero(gotBaseAddress, i, imageShift, elfLoadHelper);
Data pointerData = elfLoadHelper.createData(gotEntryAddr, PointerDataType.dataType);
setConstant(pointerData);
if (ElfDefaultGotPltMarkup.isValidPointer(pointerData)) {
ElfDefaultGotPltMarkup.setConstant(pointerData);
}
}
// process global/external symbol got entries
@ -753,7 +755,7 @@ public class MIPS_ElfExtension extends ElfExtension {
Address gotEntryAddr = adjustTableEntryIfNonZero(gotBaseAddress, gotIndex++,
imageShift, elfLoadHelper);
Data pointerData = elfLoadHelper.createData(gotEntryAddr, PointerDataType.dataType);
setConstant(pointerData);
ElfDefaultGotPltMarkup.setConstant(pointerData);
if (elfSymbols[i].isFunction() && elfSymbols[i].getSectionHeaderIndex() == 0) {
// ensure that external function/thunk are created in absence of sections
Address refAddr = (Address) pointerData.getValue();
@ -811,7 +813,7 @@ public class MIPS_ElfExtension extends ElfExtension {
Address gotEntryAddr = adjustTableEntryIfNonZero(mipsPltgotBase, ++gotEntryIndex,
imageShift, elfLoadHelper);
Data pointerData = elfLoadHelper.createData(gotEntryAddr, PointerDataType.dataType);
setConstant(pointerData);
ElfDefaultGotPltMarkup.setConstant(pointerData);
}
}
catch (NotFoundException e) {
@ -822,17 +824,6 @@ public class MIPS_ElfExtension extends ElfExtension {
}
}
private void setConstant(Data pointerData) {
Memory memory = pointerData.getProgram().getMemory();
MemoryBlock block = memory.getBlock(pointerData.getAddress());
if (!block.isWrite() || block.getName().startsWith(ElfSectionHeaderConstants.dot_got)) {
// .got blocks will be force to read-only by ElfDefaultGotPltMarkup
return;
}
pointerData.setLong(MutabilitySettingsDefinition.MUTABILITY,
MutabilitySettingsDefinition.CONSTANT);
}
private Address adjustTableEntryIfNonZero(Address tableBaseAddr, int entryIndex,
long adjustment, ElfLoadHelper elfLoadHelper) throws MemoryAccessException {
boolean is64Bit = elfLoadHelper.getElfHeader().is64Bit();

View file

@ -368,6 +368,9 @@ public class PowerPC64_ElfExtension extends ElfExtension {
return null;
}
ElfDefaultGotPltMarkup.setConstant(refPtr);
ElfDefaultGotPltMarkup.setConstant(tocPtr);
Function function = program.getListing().getFunctionAt(refAddr);
if (function == null) {
// Check for potential pointer table (unsure a non-function would be referenced by OPD section)