GP-3176 corrected ELF INIT/FINI array processing

This commit is contained in:
ghidra1
2023-03-09 16:14:14 -05:00
parent f56e922d43
commit dfac7f0109
@@ -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) {