mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/GP-5681_ryanmkurtz_macho' into
Ghidra_11.4 (Closes #8124)
This commit is contained in:
commit
c594e41f60
6 changed files with 70 additions and 29 deletions
|
@ -25,8 +25,9 @@ import ghidra.app.util.bin.format.macho.dyld.DyldChainedPtr.DyldChainType;
|
||||||
import ghidra.app.util.bin.format.macho.dyld.DyldFixup;
|
import ghidra.app.util.bin.format.macho.dyld.DyldFixup;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.app.util.opinion.MachoProgramBuilder;
|
import ghidra.app.util.opinion.MachoProgramBuilder;
|
||||||
|
import ghidra.app.util.opinion.MachoProgramUtils;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.model.reloc.Relocation.Status;
|
import ghidra.program.model.reloc.Relocation.Status;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -136,41 +137,79 @@ public class DyldChainedFixups {
|
||||||
public static List<Address> fixupChainedPointers(List<DyldFixup> fixups, Program program,
|
public static List<Address> fixupChainedPointers(List<DyldFixup> fixups, Program program,
|
||||||
Address imagebase, List<String> libraryPaths, MessageLog log, TaskMonitor monitor)
|
Address imagebase, List<String> libraryPaths, MessageLog log, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
List<Address> fixedAddrs = new ArrayList<>();
|
|
||||||
if (fixups.isEmpty()) {
|
if (fixups.isEmpty()) {
|
||||||
return fixedAddrs;
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
|
ExternalManager extMgr = program.getExternalManager();
|
||||||
|
|
||||||
|
// Figure out how much space in the EXTERNAL block we need, and make it
|
||||||
|
Address extAddr = null;
|
||||||
|
try {
|
||||||
|
long externalSize = fixups.stream()
|
||||||
|
.filter(e -> e.value() == null && e.symbol() != null && e.libOrdinal() != null)
|
||||||
|
.mapToLong(DyldFixup::size)
|
||||||
|
.sum();
|
||||||
|
if (externalSize > 0) {
|
||||||
|
extAddr = MachoProgramUtils.addExternalBlock(program, externalSize, log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
log.appendMsg(
|
||||||
|
"Failed to create space in EXTERNAL block for chained fixups: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Address> fixedAddrs = new ArrayList<>();
|
||||||
monitor.initialize(fixups.size(), "Fixing up chained pointers...");
|
monitor.initialize(fixups.size(), "Fixing up chained pointers...");
|
||||||
for (DyldFixup fixup : fixups) {
|
for (DyldFixup fixup : fixups) {
|
||||||
monitor.increment();
|
monitor.increment();
|
||||||
Status status = Status.UNSUPPORTED;
|
Status status = Status.UNSUPPORTED;
|
||||||
Address addr = imagebase.add(fixup.offset());
|
Address fixupAddr = imagebase.add(fixup.offset());
|
||||||
String symbol = fixup.symbol();
|
Long fixupValue = fixup.value();
|
||||||
|
String fixupSymbol = fixup.symbol();
|
||||||
long[] value = new long[] {};
|
long[] value = new long[] {};
|
||||||
try {
|
try {
|
||||||
if (fixup.value() != null) {
|
if (fixupValue == null && fixupSymbol != null && fixup.libOrdinal() != null &&
|
||||||
|
extAddr != null) {
|
||||||
|
try {
|
||||||
|
symbolTable.createLabel(extAddr, fixupSymbol, SourceType.IMPORTED);
|
||||||
|
fixupValue = extAddr.getOffset();
|
||||||
|
Function stubFunc = MachoProgramBuilder.createOneByteFunction(program,
|
||||||
|
fixupSymbol, extAddr);
|
||||||
|
if (stubFunc != null) {
|
||||||
|
ExternalLocation loc = extMgr.addExtLocation(Library.UNKNOWN,
|
||||||
|
fixupSymbol, null, SourceType.IMPORTED);
|
||||||
|
stubFunc.setThunkedFunction(loc.createFunction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
extAddr = extAddr.add(fixup.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fixupValue != null) {
|
||||||
if (fixup.size() == 8 || fixup.size() == 4) {
|
if (fixup.size() == 8 || fixup.size() == 4) {
|
||||||
if (fixup.size() == 8) {
|
if (fixup.size() == 8) {
|
||||||
memory.setLong(addr, fixup.value());
|
memory.setLong(fixupAddr, fixupValue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memory.setInt(addr, fixup.value().intValue());
|
memory.setInt(fixupAddr, fixupValue.intValue());
|
||||||
}
|
}
|
||||||
fixedAddrs.add(addr);
|
fixedAddrs.add(fixupAddr);
|
||||||
status = Status.APPLIED_OTHER;
|
status = Status.APPLIED;
|
||||||
}
|
}
|
||||||
value = new long[] { fixup.value() };
|
value = new long[] { fixupValue };
|
||||||
}
|
}
|
||||||
if (symbol != null && fixup.libOrdinal() != null) {
|
if (fixupSymbol != null && fixup.libOrdinal() != null) {
|
||||||
value = new long[] { fixup.libOrdinal() };
|
value = new long[] { fixup.libOrdinal() };
|
||||||
try {
|
try {
|
||||||
MachoProgramBuilder.fixupExternalLibrary(program, libraryPaths,
|
MachoProgramBuilder.fixupExternalLibrary(program, libraryPaths,
|
||||||
fixup.libOrdinal(), symbol);
|
fixup.libOrdinal(), fixupSymbol);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
log.appendMsg("WARNING: Problem fixing up symbol '%s' - %s"
|
log.appendMsg("WARNING: Problem fixing up symbol '%s' - %s"
|
||||||
.formatted(symbol, e.getMessage()));
|
.formatted(fixupSymbol, e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +218,7 @@ public class DyldChainedFixups {
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.getRelocationTable()
|
program.getRelocationTable()
|
||||||
.add(addr, status, RELOCATION_TYPE, value, fixup.size(), symbol);
|
.add(fixupAddr, status, RELOCATION_TYPE, value, fixup.size(), fixupSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.appendMsg("Fixed up " + fixedAddrs.size() + " chained pointers.");
|
log.appendMsg("Fixed up " + fixedAddrs.size() + " chained pointers.");
|
||||||
|
|
|
@ -146,7 +146,7 @@ public abstract class AbstractClassicProcessor {
|
||||||
status = Status.UNSUPPORTED;
|
status = Status.UNSUPPORTED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = Status.APPLIED_OTHER;
|
status = Status.APPLIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// put an entry in the relocation table, handled or not
|
// put an entry in the relocation table, handled or not
|
||||||
|
|
|
@ -150,7 +150,7 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
||||||
if (entryPoint != null) {
|
if (entryPoint != null) {
|
||||||
Address entryPointAddr = space.getAddress(entryPoint);
|
Address entryPointAddr = space.getAddress(entryPoint);
|
||||||
program.getSymbolTable().addExternalEntryPoint(entryPointAddr);
|
program.getSymbolTable().addExternalEntryPoint(entryPointAddr);
|
||||||
createOneByteFunction("entry", entryPointAddr);
|
createOneByteFunction(program, "entry", entryPointAddr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.appendMsg("Unable to determine entry point.");
|
log.appendMsg("Unable to determine entry point.");
|
||||||
|
|
|
@ -514,7 +514,7 @@ public class MachoProgramBuilder {
|
||||||
if (!realEntryFound) {
|
if (!realEntryFound) {
|
||||||
program.getSymbolTable().createLabel(addr, "entry", SourceType.IMPORTED);
|
program.getSymbolTable().createLabel(addr, "entry", SourceType.IMPORTED);
|
||||||
program.getSymbolTable().addExternalEntryPoint(addr);
|
program.getSymbolTable().addExternalEntryPoint(addr);
|
||||||
createOneByteFunction("entry", addr);
|
createOneByteFunction(program, "entry", addr);
|
||||||
realEntryFound = true;
|
realEntryFound = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -684,10 +684,11 @@ public class MachoProgramBuilder {
|
||||||
monitor.increment();
|
monitor.increment();
|
||||||
int symbolIndex = indirectSymbols.get(i);
|
int symbolIndex = indirectSymbols.get(i);
|
||||||
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
|
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
|
||||||
String name =
|
String name = null;
|
||||||
symbol != null ? SymbolUtilities.replaceInvalidChars(symbol.getString(), true)
|
if (symbol != null) {
|
||||||
: "STUB_" + startAddr;
|
name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true);
|
||||||
Function stubFunc = createOneByteFunction(name, startAddr);
|
}
|
||||||
|
Function stubFunc = createOneByteFunction(program, name, startAddr);
|
||||||
if (stubFunc != null && symbol != null) {
|
if (stubFunc != null && symbol != null) {
|
||||||
ExternalLocation loc = program.getExternalManager()
|
ExternalLocation loc = program.getExternalManager()
|
||||||
.addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
|
.addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
|
||||||
|
@ -965,8 +966,8 @@ public class MachoProgramBuilder {
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.getRelocationTable()
|
program.getRelocationTable()
|
||||||
.add(addr, success ? Status.APPLIED_OTHER : Status.FAILURE,
|
.add(addr, success ? Status.APPLIED : Status.FAILURE, binding.getType(),
|
||||||
binding.getType(), null, bytes.length, binding.getSymbolName());
|
null, bytes.length, binding.getSymbolName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1584,7 +1585,7 @@ public class MachoProgramBuilder {
|
||||||
}
|
}
|
||||||
Register tModeRegister = program.getLanguage().getRegister("TMode");
|
Register tModeRegister = program.getLanguage().getRegister("TMode");
|
||||||
program.getProgramContext().setValue(tModeRegister, address, address, BigInteger.ONE);
|
program.getProgramContext().setValue(tModeRegister, address, address, BigInteger.ONE);
|
||||||
createOneByteFunction(null, address);
|
createOneByteFunction(program, null, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processLazyPointerSection(AddressSetView set) {
|
private void processLazyPointerSection(AddressSetView set) {
|
||||||
|
@ -1638,13 +1639,14 @@ public class MachoProgramBuilder {
|
||||||
* create a one-byte function, so that when the code is analyzed,
|
* create a one-byte function, so that when the code is analyzed,
|
||||||
* it will be disassembled, and the function created with the correct body.
|
* it will be disassembled, and the function created with the correct body.
|
||||||
*
|
*
|
||||||
|
* @param program The {@link Program}
|
||||||
* @param name the name of the function
|
* @param name the name of the function
|
||||||
* @param address location to create the function
|
* @param address location to create the function
|
||||||
* @return If a function already existed at the given address, that function will be returned.
|
* @return If a function already existed at the given address, that function will be returned.
|
||||||
* Otherwise, the newly created function will be returned. If there was a problem creating
|
* Otherwise, the newly created function will be returned. If there was a problem creating
|
||||||
* the function, null will be returned.
|
* the function, null will be returned.
|
||||||
*/
|
*/
|
||||||
Function createOneByteFunction(String name, Address address) {
|
public static Function createOneByteFunction(Program program, String name, Address address) {
|
||||||
FunctionManager functionMgr = program.getFunctionManager();
|
FunctionManager functionMgr = program.getFunctionManager();
|
||||||
Function function = functionMgr.getFunctionAt(address);
|
Function function = functionMgr.getFunctionAt(address);
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
|
|
|
@ -64,9 +64,9 @@ public class MachoProgramUtils {
|
||||||
Address ret;
|
Address ret;
|
||||||
if (externalBlock != null) {
|
if (externalBlock != null) {
|
||||||
ret = externalBlock.getEnd().add(1);
|
ret = externalBlock.getEnd().add(1);
|
||||||
MemoryBlock newBlock = mem.createBlock(externalBlock, "REEXPORTS", ret, size);
|
MemoryBlock newBlock =
|
||||||
|
mem.createBlock(externalBlock, MemoryBlock.EXTERNAL_BLOCK_NAME, ret, size);
|
||||||
mem.join(externalBlock, newBlock);
|
mem.join(externalBlock, newBlock);
|
||||||
//joinedBlock.setName(MemoryBlock.EXTERNAL_BLOCK_NAME);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = MachoProgramUtils.getNextAvailableAddress(program);
|
ret = MachoProgramUtils.getNextAvailableAddress(program);
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class MachoExtractProgramBuilder extends MachoProgramBuilder {
|
||||||
// location to the newly exported function
|
// location to the newly exported function
|
||||||
Function func = funcManager.getFunctionAt(sym.getAddress());
|
Function func = funcManager.getFunctionAt(sym.getAddress());
|
||||||
if (func != null && func.getThunkedFunction(false) != null) {
|
if (func != null && func.getThunkedFunction(false) != null) {
|
||||||
func.setThunkedFunction(createOneByteFunction(name, exportAddr));
|
func.setThunkedFunction(createOneByteFunction(program, name, exportAddr));
|
||||||
|
|
||||||
// Remove the external location associated with the thunk function.
|
// Remove the external location associated with the thunk function.
|
||||||
// After the first delete, the external location becomes an external label, which
|
// After the first delete, the external location becomes an external label, which
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue