mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-302 corrected issue affected ELF PLTGOT bounds determination.
Corrected various pointer and data related issues
This commit is contained in:
parent
1c145dd781
commit
6107f29a95
6 changed files with 105 additions and 53 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue