mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-24 21:21:56 +00:00
Merge branch 'GP-252_ghidra1_ELF_DT_JMPREL_and_Externals' into Ghidra_9.2
This commit is contained in:
commit
63be47d026
@ -26,6 +26,7 @@ import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@ -61,8 +62,8 @@ public class ElfDefaultGotPltMarkup {
|
||||
}
|
||||
else {
|
||||
processGOTSections(monitor);
|
||||
processPLTSection(monitor);
|
||||
}
|
||||
processPLT(monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,10 +74,9 @@ public class ElfDefaultGotPltMarkup {
|
||||
private void processGOTSections(TaskMonitor monitor) throws CancelledException {
|
||||
// look for .got section blocks
|
||||
MemoryBlock[] blocks = memory.getBlocks();
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
for (MemoryBlock gotBlock : blocks) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
MemoryBlock gotBlock = blocks[i];
|
||||
if (!gotBlock.getName().startsWith(ElfSectionHeaderConstants.dot_got)) {
|
||||
continue;
|
||||
}
|
||||
@ -137,6 +137,7 @@ public class ElfDefaultGotPltMarkup {
|
||||
Address gotEnd = defaultSpace.getAddress(
|
||||
firstGotEntryOffset + (count * defaultSpace.getPointerSize()) - 1);
|
||||
processGOT(gotStart, gotEnd, monitor);
|
||||
processDynamicPLT(gotStart, gotEnd, monitor);
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
throw new AssertException(e);
|
||||
@ -198,7 +199,7 @@ public class ElfDefaultGotPltMarkup {
|
||||
}
|
||||
}
|
||||
|
||||
private void processPLT(TaskMonitor monitor) throws CancelledException {
|
||||
private void processPLTSection(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
// TODO: Handle case where PLT is non-executable pointer table
|
||||
|
||||
@ -227,16 +228,48 @@ public class ElfDefaultGotPltMarkup {
|
||||
processLinkageTable(ElfSectionHeaderConstants.dot_plt, minAddress, maxAddress, monitor);
|
||||
}
|
||||
|
||||
private void processDynamicPLT(Address gotStart, Address gotEnd, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
|
||||
Address pltStart = null;
|
||||
Address pltEnd = null;
|
||||
|
||||
for (Data gotPtr : listing.getDefinedData(new AddressSet(gotStart.next(), gotEnd), true)) {
|
||||
monitor.checkCanceled();
|
||||
if (!gotPtr.isPointer()) {
|
||||
Msg.error(this, "ELF PLTGOT contains non-pointer");
|
||||
return; // unexpected
|
||||
}
|
||||
Address ptr = (Address) gotPtr.getValue();
|
||||
if (ptr.getOffset() == 0) {
|
||||
continue;
|
||||
}
|
||||
MemoryBlock block = memory.getBlock(ptr);
|
||||
if (block == null || block.getName().equals(MemoryBlock.EXTERNAL_BLOCK_NAME)) {
|
||||
continue;
|
||||
}
|
||||
if (pltStart == null) {
|
||||
pltStart = ptr;
|
||||
}
|
||||
pltEnd = ptr;
|
||||
}
|
||||
|
||||
if (pltStart != null) {
|
||||
processLinkageTable("PLT", pltStart, pltEnd, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform disassembly and markup of specified external linkage table which
|
||||
* consists of thunks to external functions. If symbols are defined within the
|
||||
* linkage table, these will be transitioned to external functions.
|
||||
* @param pltName name of PLT section for log messages
|
||||
* @param minAddress minimum address of linkage table
|
||||
* @param maxAddress maximum address of linkage table
|
||||
* @param monitor task monitor
|
||||
* @throws CancelledException task cancelled
|
||||
*/
|
||||
public void processLinkageTable(String name, Address minAddress, Address maxAddress,
|
||||
public void processLinkageTable(String pltName, Address minAddress, Address maxAddress,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
// Disassemble section.
|
||||
@ -248,7 +281,7 @@ public class ElfDefaultGotPltMarkup {
|
||||
// This can be seen with ARM Android examples.
|
||||
int count = convertSymbolsToExternalFunctions(minAddress, maxAddress);
|
||||
if (count > 0) {
|
||||
log("Converted " + count + " " + name + " section symbols to external thunks");
|
||||
log("Converted " + count + " " + pltName + " section symbols to external thunks");
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,8 +381,8 @@ public class ElfDefaultGotPltMarkup {
|
||||
private void removeMemRefs(Data data) {
|
||||
if (data != null) {
|
||||
Reference[] refs = data.getValueReferences();
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
RemoveReferenceCmd cmd = new RemoveReferenceCmd(refs[i]);
|
||||
for (Reference ref : refs) {
|
||||
RemoveReferenceCmd cmd = new RemoveReferenceCmd(ref);
|
||||
cmd.applyTo(data.getProgram());
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +353,18 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_RELA,
|
||||
ElfDynamicType.DT_RELAENT, ElfDynamicType.DT_RELASZ, true);
|
||||
|
||||
if (dynamicTable.containsDynamicValue(ElfDynamicType.DT_PLTREL)) {
|
||||
try {
|
||||
boolean isRela = (dynamicTable
|
||||
.getDynamicValue(ElfDynamicType.DT_PLTREL) == ElfDynamicType.DT_RELA.value);
|
||||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_JMPREL,
|
||||
null, ElfDynamicType.DT_PLTRELSZ, isRela);
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
// ignore - skip (required dynamic table value is missing)
|
||||
}
|
||||
}
|
||||
|
||||
// Android versions
|
||||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_ANDROID_REL, null,
|
||||
ElfDynamicType.DT_ANDROID_RELSZ, false);
|
||||
|
@ -318,6 +318,19 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
||||
return struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the standard relocation size when one has notbeen specified
|
||||
* @param is64bit true if ELF 64-bit
|
||||
* @param hasAddend true if relocation has addend
|
||||
* @return size of relocation entry
|
||||
*/
|
||||
public static int getStandardRelocationEntrySize(boolean is64bit, boolean hasAddend) {
|
||||
if (is64bit) {
|
||||
return hasAddend ? 24 : 16;
|
||||
}
|
||||
return hasAddend ? 12 : 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.util.bin.ByteArrayConverter#toBytes(ghidra.util.DataConverter)
|
||||
*/
|
||||
|
@ -128,6 +128,9 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||
throws IOException {
|
||||
|
||||
List<ElfRelocation> relocations = new ArrayList<>();
|
||||
if (entrySize <= 0) {
|
||||
entrySize = ElfRelocation.getStandardRelocationEntrySize(elfHeader.is64Bit(), addendTypeReloc);
|
||||
}
|
||||
int nRelocs = (int) (length / entrySize);
|
||||
for (int relocationIndex = 0; relocationIndex < nRelocs; ++relocationIndex) {
|
||||
relocations.add(ElfRelocation.createElfRelocation(reader, elfHeader, relocationIndex,
|
||||
@ -258,8 +261,8 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||
public byte[] toBytes(DataConverter dc) {
|
||||
byte[] bytes = new byte[relocs.length * relocs[0].sizeof()];
|
||||
int index = 0;
|
||||
for (int i = 0; i < relocs.length; i++) {
|
||||
byte[] relocBytes = relocs[i].toBytes(dc);
|
||||
for (ElfRelocation reloc : relocs) {
|
||||
byte[] relocBytes = reloc.toBytes(dc);
|
||||
System.arraycopy(relocBytes, 0, bytes, index, relocBytes.length);
|
||||
index += relocBytes.length;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user