mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-29 03:06:57 +08:00
GP-3176 corrected ELF INIT/FINI array processing
This commit is contained in:
@@ -15,12 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.util.opinion;
|
package ghidra.app.util.opinion;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.file.AccessMode;
|
import java.nio.file.AccessMode;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
|
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -170,11 +169,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
|
|
||||||
elf.getLoadAdapter().processElf(this, monitor);
|
elf.getLoadAdapter().processElf(this, monitor);
|
||||||
|
|
||||||
processEntryPoints(monitor);
|
|
||||||
|
|
||||||
monitor.setIndeterminate(false);
|
monitor.setIndeterminate(false);
|
||||||
|
|
||||||
processRelocations(monitor);
|
processRelocations(monitor);
|
||||||
|
processEntryPoints(monitor);
|
||||||
processImports(monitor);
|
processImports(monitor);
|
||||||
|
|
||||||
monitor.setIndeterminate(true);
|
monitor.setIndeterminate(true);
|
||||||
@@ -680,18 +678,20 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
|
|
||||||
// process dynamic entry points
|
// process dynamic entry points
|
||||||
createDynamicEntryPoints(ElfDynamicType.DT_INIT, null, "_INIT_", monitor);
|
createDynamicEntryPoints(ElfDynamicType.DT_INIT, null, "_INIT_", monitor);
|
||||||
|
createDynamicEntryPoints(ElfDynamicType.DT_FINI, null, "_FINI_", monitor);
|
||||||
|
|
||||||
createDynamicEntryPoints(ElfDynamicType.DT_INIT_ARRAY, ElfDynamicType.DT_INIT_ARRAYSZ,
|
createDynamicEntryPoints(ElfDynamicType.DT_INIT_ARRAY, ElfDynamicType.DT_INIT_ARRAYSZ,
|
||||||
"_INIT_", monitor);
|
"_INIT_", monitor);
|
||||||
createDynamicEntryPoints(ElfDynamicType.DT_PREINIT_ARRAY, ElfDynamicType.DT_PREINIT_ARRAYSZ,
|
createDynamicEntryPoints(ElfDynamicType.DT_PREINIT_ARRAY, ElfDynamicType.DT_PREINIT_ARRAYSZ,
|
||||||
"_PREINIT_", monitor);
|
"_PREINIT_", monitor);
|
||||||
createDynamicEntryPoints(ElfDynamicType.DT_FINI, null, "_FINI_", monitor);
|
|
||||||
createDynamicEntryPoints(ElfDynamicType.DT_FINI_ARRAY, ElfDynamicType.DT_FINI_ARRAYSZ,
|
createDynamicEntryPoints(ElfDynamicType.DT_FINI_ARRAY, ElfDynamicType.DT_FINI_ARRAYSZ,
|
||||||
"_FINI_", monitor);
|
"_FINI_", monitor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDynamicEntryPoints(ElfDynamicType dynamicEntryType,
|
private void createDynamicEntryPoints(ElfDynamicType dynamicEntryType,
|
||||||
ElfDynamicType entryArraySizeType, String baseName, TaskMonitor monitor) {
|
ElfDynamicType entryArraySizeType, String baseName, TaskMonitor monitor)
|
||||||
|
throws CancelledException {
|
||||||
|
|
||||||
ElfDynamicTable dynamicTable = elf.getDynamicTable();
|
ElfDynamicTable dynamicTable = elf.getDynamicTable();
|
||||||
if (dynamicTable == null) {
|
if (dynamicTable == null) {
|
||||||
@@ -701,7 +701,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
try {
|
try {
|
||||||
long entryAddrOffset =
|
long entryAddrOffset =
|
||||||
elf.adjustAddressForPrelink(dynamicTable.getDynamicValue(dynamicEntryType));
|
elf.adjustAddressForPrelink(dynamicTable.getDynamicValue(dynamicEntryType));
|
||||||
|
|
||||||
if (entryArraySizeType == null) {
|
if (entryArraySizeType == null) {
|
||||||
// single entry addr case
|
// single entry addr case
|
||||||
createEntryFunction("_" + dynamicEntryType.name, entryAddrOffset, monitor);
|
createEntryFunction("_" + dynamicEntryType.name, entryAddrOffset, monitor);
|
||||||
@@ -709,30 +708,48 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// entryAddrOffset points to array of entry addresses
|
// entryAddrOffset points to array of entry addresses
|
||||||
DataType dt = elf.is32Bit() ? DWordDataType.dataType : QWordDataType.dataType;
|
|
||||||
Address entryArrayAddr = getDefaultAddress(entryAddrOffset);
|
Address entryArrayAddr = getDefaultAddress(entryAddrOffset);
|
||||||
|
|
||||||
|
DataType dt = elf.is32Bit() ? DWordDataType.dataType : QWordDataType.dataType;
|
||||||
|
if (program.getRelocationTable().hasRelocation(entryArrayAddr) ||
|
||||||
|
(getImageBaseWordAdjustmentOffset() == 0 && elf.adjustAddressForPrelink(0) == 0)) {
|
||||||
|
// apply pointers if relocations applied to array entries or no scalar adjustment
|
||||||
|
dt = new PointerDataType(program.getDataTypeManager());
|
||||||
|
}
|
||||||
|
|
||||||
long arraySize = dynamicTable.getDynamicValue(entryArraySizeType);
|
long arraySize = dynamicTable.getDynamicValue(entryArraySizeType);
|
||||||
long elementCount = arraySize / dt.getLength();
|
long elementCount = arraySize / dt.getLength();
|
||||||
|
|
||||||
|
monitor.setMessage("Processing " + baseName + " array...");
|
||||||
|
monitor.initialize(elementCount);
|
||||||
for (int i = 0; i < elementCount; i++) {
|
for (int i = 0; i < elementCount; i++) {
|
||||||
|
|
||||||
|
monitor.checkCanceled();
|
||||||
|
monitor.incrementProgress(1);
|
||||||
|
|
||||||
Address addr = entryArrayAddr.add(i * dt.getLength());
|
Address addr = entryArrayAddr.add(i * dt.getLength());
|
||||||
Data data = createData(addr, dt);
|
Data data = createData(addr, dt);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Scalar value = (Scalar) data.getValue();
|
|
||||||
if (value != null) {
|
Object value = data.getValue();
|
||||||
if (i != 0 && value.getValue() == 0) {
|
Address funcAddr;
|
||||||
|
if (value instanceof Address) {
|
||||||
|
funcAddr = (Address) value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Scalar s = (Scalar) value;
|
||||||
|
long funcAddrOffset = s.getValue();
|
||||||
|
if (funcAddrOffset == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long funcAddrOffset = elf.adjustAddressForPrelink(value.getValue());
|
funcAddrOffset = elf.adjustAddressForPrelink(funcAddrOffset);
|
||||||
Address funcAddr = createEntryFunction(baseName + i, funcAddrOffset, monitor);
|
funcAddr = getDefaultAddress(funcAddrOffset);
|
||||||
if (funcAddr != null) {
|
data.addOperandReference(0, funcAddr, RefType.DATA, SourceType.ANALYSIS);
|
||||||
data.addOperandReference(0, funcAddr, RefType.DATA, SourceType.ANALYSIS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
createEntryFunction(baseName + i, funcAddr, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (NotFoundException e) {
|
catch (NotFoundException e) {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -741,23 +758,35 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an entry point function.
|
* Attempt to create an entry point function.
|
||||||
* Note: entries in the dynamic table appear to have any pre-link adjustment already applied.
|
* Note: entries in the dynamic table appear to have any pre-link adjustment already applied.
|
||||||
* @param name
|
* @param name function name
|
||||||
* @param entryAddr function address (adjusted for pre-linking).
|
* @param entryAddr function address offset (must already be adjusted for pre-linking).
|
||||||
* @param monitor
|
* Any required image-base adjustment will be applied before converting to an Address.
|
||||||
* @return function address
|
* @param monitor task monitor
|
||||||
|
* @return address which corresponds to entryAddr
|
||||||
*/
|
*/
|
||||||
private Address createEntryFunction(String name, long entryAddr, TaskMonitor monitor) {
|
private Address createEntryFunction(String name, long entryAddr, TaskMonitor monitor) {
|
||||||
|
|
||||||
entryAddr += getImageBaseWordAdjustmentOffset(); // word offset
|
entryAddr += getImageBaseWordAdjustmentOffset(); // word offset
|
||||||
|
|
||||||
Address entryAddress = getDefaultAddressSpace().getTruncatedAddress(entryAddr, true);
|
Address entryAddress = getDefaultAddressSpace().getTruncatedAddress(entryAddr, true);
|
||||||
|
createEntryFunction(name, entryAddress, monitor);
|
||||||
|
return entryAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to create an entry point function.
|
||||||
|
* Note: entries in the dynamic table appear to have any pre-link adjustment already applied.
|
||||||
|
* @param name function name
|
||||||
|
* @param entryAddress function Address
|
||||||
|
* @param monitor task monitor
|
||||||
|
*/
|
||||||
|
private void createEntryFunction(String name, Address entryAddress, TaskMonitor monitor) {
|
||||||
|
|
||||||
// TODO: Entry may refer to a pointer - make sure we have execute permission
|
// TODO: Entry may refer to a pointer - make sure we have execute permission
|
||||||
|
|
||||||
MemoryBlock block = memory.getBlock(entryAddress);
|
MemoryBlock block = memory.getBlock(entryAddress);
|
||||||
if (block == null || !block.isExecute()) {
|
if (block == null || !block.isExecute()) {
|
||||||
return entryAddress;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
entryAddress = elf.getLoadAdapter().creatingFunction(this, entryAddress);
|
entryAddress = elf.getLoadAdapter().creatingFunction(this, entryAddress);
|
||||||
@@ -765,7 +794,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
Function function = program.getFunctionManager().getFunctionAt(entryAddress);
|
Function function = program.getFunctionManager().getFunctionAt(entryAddress);
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
program.getSymbolTable().addExternalEntryPoint(entryAddress);
|
program.getSymbolTable().addExternalEntryPoint(entryAddress);
|
||||||
return entryAddress; // symbol-based function already created
|
return; // symbol-based function already created
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -774,8 +803,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
log("Could not create symbol at entry point: " + getMessage(e));
|
log("Could not create symbol at entry point: " + getMessage(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
return entryAddress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getMessage(Exception e) {
|
private String getMessage(Exception e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user