mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
a821b44c76
4 changed files with 147 additions and 43 deletions
|
@ -16,6 +16,7 @@
|
|||
package ghidra.app.util.bin.format.elf;
|
||||
|
||||
import ghidra.app.cmd.refs.RemoveReferenceCmd;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.disassemble.Disassembler;
|
||||
import ghidra.program.disassemble.DisassemblerMessageListener;
|
||||
import ghidra.program.model.address.*;
|
||||
|
@ -25,7 +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.exception.CancelledException;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
|
@ -54,21 +55,24 @@ public class ElfDefaultGotPltMarkup {
|
|||
elfLoadHelper.log(msg);
|
||||
}
|
||||
|
||||
private void log(Throwable t) {
|
||||
elfLoadHelper.log(t);
|
||||
}
|
||||
|
||||
public void process(TaskMonitor monitor) throws CancelledException {
|
||||
processGOT(monitor);
|
||||
if (elf.e_shnum() == 0) {
|
||||
processDynamicPLTGOT(monitor);
|
||||
}
|
||||
else {
|
||||
processGOTSections(monitor);
|
||||
}
|
||||
processPLT(monitor);
|
||||
}
|
||||
|
||||
private void processGOT(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
/**
|
||||
* Process all GOT sections based upon blocks whose names begin with .got
|
||||
* @param monitor task monitor
|
||||
* @throws CancelledException thrown if task cancelled
|
||||
*/
|
||||
private void processGOTSections(TaskMonitor monitor) throws CancelledException {
|
||||
// look for .got section blocks
|
||||
MemoryBlock[] blocks = memory.getBlocks();
|
||||
|
||||
boolean imageBaseAlreadySet = elf.isPreLinked();
|
||||
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
|
@ -76,19 +80,94 @@ public class ElfDefaultGotPltMarkup {
|
|||
if (!gotBlock.getName().startsWith(ElfSectionHeaderConstants.dot_got)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Assume the .got section is read_only. This is not true, but it helps with analysis
|
||||
// This should be relocation setup.
|
||||
gotBlock.setWrite(false);
|
||||
|
||||
processGOT(gotBlock.getStart(), gotBlock.getEnd(), monitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process GOT table specified by Dynamic Program Header (DT_PLTGOT).
|
||||
* Entry count determined by corresponding relocation table identified by
|
||||
* the dynamic table entry DT_JMPREL.
|
||||
* @param monitor task monitor
|
||||
* @throws CancelledException thrown if task cancelled
|
||||
*/
|
||||
private void processDynamicPLTGOT(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
ElfDynamicTable dynamicTable = elf.getDynamicTable();
|
||||
if (dynamicTable == null || !dynamicTable.containsDynamicValue(ElfDynamicType.DT_PLTGOT) ||
|
||||
!dynamicTable.containsDynamicValue(ElfDynamicType.DT_JMPREL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: there may be other relocation table affecting the GOT
|
||||
// corresponding to DT_PLTGOT
|
||||
|
||||
AddressSpace defaultSpace = program.getAddressFactory().getDefaultAddressSpace();
|
||||
long imageBaseAdj = elfLoadHelper.getImageBaseWordAdjustmentOffset();
|
||||
|
||||
try {
|
||||
long relocTableAddr =
|
||||
elf.adjustAddressForPrelink(dynamicTable.getDynamicValue(ElfDynamicType.DT_JMPREL));
|
||||
|
||||
ElfProgramHeader relocTableLoadHeader =
|
||||
elf.getProgramLoadHeaderContaining(relocTableAddr);
|
||||
if (relocTableLoadHeader == null || relocTableLoadHeader.getOffset() < 0) {
|
||||
return;
|
||||
}
|
||||
long relocTableOffset = relocTableLoadHeader.getOffset(relocTableAddr);
|
||||
ElfRelocationTable relocationTable = elf.getRelocationTableAtOffset(relocTableOffset);
|
||||
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;
|
||||
|
||||
long pltgot = elf.adjustAddressForPrelink(
|
||||
dynamicTable.getDynamicValue(ElfDynamicType.DT_PLTGOT)) + imageBaseAdj;
|
||||
|
||||
Address gotStart = defaultSpace.getAddress(pltgot);
|
||||
Address gotEnd = defaultSpace.getAddress(
|
||||
firstGotEntryOffset + (count * defaultSpace.getPointerSize()) - 1);
|
||||
processGOT(gotStart, gotEnd, monitor);
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
log("Failed to process GOT: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark-up all GOT entries as pointers within the memory range gotStart to
|
||||
* gotEnd.
|
||||
* @param gotStart address for start of GOT
|
||||
* @param gotEnd address for end of GOT
|
||||
* @param monitor task monitor
|
||||
* @throws CancelledException thrown if task cancelled
|
||||
*/
|
||||
private void processGOT(Address gotStart, Address gotEnd, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
|
||||
boolean imageBaseAlreadySet = elf.isPreLinked();
|
||||
|
||||
try {
|
||||
Address newImageBase = null;
|
||||
Address addr = gotBlock.getStart();
|
||||
try {
|
||||
while (addr.compareTo(gotBlock.getEnd()) < 0) {
|
||||
while (gotStart.compareTo(gotEnd) < 0) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
Data data = createPointer(addr, true);
|
||||
Data data = createPointer(gotStart, true);
|
||||
|
||||
try {
|
||||
addr = data.getMaxAddress().add(1);
|
||||
gotStart = data.getMaxAddress().add(1);
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
break; // no more room
|
||||
|
@ -108,9 +187,14 @@ public class ElfDefaultGotPltMarkup {
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log(e);
|
||||
catch (CodeUnitInsertionException e) {
|
||||
log("Failed to process GOT: " + e.getMessage());
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
log("Failed to adjust image base: " + e.getMessage());
|
||||
}
|
||||
catch (LockException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +310,7 @@ public class ElfDefaultGotPltMarkup {
|
|||
}
|
||||
|
||||
private Data createPointer(Address addr, boolean keepRefWhenValid)
|
||||
throws CodeUnitInsertionException, DataTypeConflictException {
|
||||
throws CodeUnitInsertionException {
|
||||
|
||||
MemoryBlock block = memory.getBlock(addr);
|
||||
if (block == null || !block.isInitialized()) {
|
||||
|
|
|
@ -1595,13 +1595,24 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the relocation table associated to the specified section header.
|
||||
* Or, null if one does not exist.
|
||||
* Returns the relocation table associated to the specified section header,
|
||||
* or null if one does not exist.
|
||||
* @param relocSection section header corresponding to relocation table
|
||||
* @return the relocation table associated to the specified section header
|
||||
*/
|
||||
public ElfRelocationTable getRelocationTable(ElfSectionHeader relocSection) {
|
||||
return getRelocationTableAtOffset(relocSection.getOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relocation table located at the specified fileOffset,
|
||||
* or null if one does not exist.
|
||||
* @param fileOffset file offset corresponding to start of relocation table
|
||||
* @return the relocation table located at the specified fileOffset or null
|
||||
*/
|
||||
public ElfRelocationTable getRelocationTableAtOffset(long fileOffset) {
|
||||
for (int i = 0; i < relocationTables.length; i++) {
|
||||
if (relocationTables[i].getFileOffset() == relocSection.getOffset()) {
|
||||
if (relocationTables[i].getFileOffset() == fileOffset) {
|
||||
return relocationTables[i];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -343,7 +343,8 @@ public class ElfProgramHeader
|
|||
// TODO: unsure if we will encounter this situation
|
||||
throw new UnsupportedOperationException("unsupported use of filtered load segment");
|
||||
}
|
||||
long addressableUnitSize = p_filesz / p_memsz; // FIXME: verify unit size computation approach !
|
||||
// TODO: additional validation of this approach is needed
|
||||
long addressableUnitSize = p_filesz / getAdjustedLoadSize();
|
||||
return (addressableUnitSize * (virtualAddress - getVirtualAddress())) + p_offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -236,6 +236,14 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
|||
return relocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of relocation entries contained within this table
|
||||
* @return relocation entry count
|
||||
*/
|
||||
public int getRelocationCount() {
|
||||
return relocs.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated symbol table.
|
||||
* A relocation object contains a symbol index.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue