Merge remote-tracking branch 'origin/GP-5681_ryanmkurtz_macho' into

Ghidra_11.4 (Closes #8124)
This commit is contained in:
Ryan Kurtz 2025-05-20 17:19:49 -04:00
commit c594e41f60
6 changed files with 70 additions and 29 deletions

View file

@ -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.importer.MessageLog;
import ghidra.app.util.opinion.MachoProgramBuilder;
import ghidra.app.util.opinion.MachoProgramUtils;
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.reloc.Relocation.Status;
import ghidra.program.model.symbol.*;
@ -136,41 +137,79 @@ public class DyldChainedFixups {
public static List<Address> fixupChainedPointers(List<DyldFixup> fixups, Program program,
Address imagebase, List<String> libraryPaths, MessageLog log, TaskMonitor monitor)
throws CancelledException {
List<Address> fixedAddrs = new ArrayList<>();
if (fixups.isEmpty()) {
return fixedAddrs;
return List.of();
}
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...");
for (DyldFixup fixup : fixups) {
monitor.increment();
Status status = Status.UNSUPPORTED;
Address addr = imagebase.add(fixup.offset());
String symbol = fixup.symbol();
Address fixupAddr = imagebase.add(fixup.offset());
Long fixupValue = fixup.value();
String fixupSymbol = fixup.symbol();
long[] value = new long[] {};
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) {
memory.setLong(addr, fixup.value());
memory.setLong(fixupAddr, fixupValue);
}
else {
memory.setInt(addr, fixup.value().intValue());
memory.setInt(fixupAddr, fixupValue.intValue());
}
fixedAddrs.add(addr);
status = Status.APPLIED_OTHER;
fixedAddrs.add(fixupAddr);
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() };
try {
MachoProgramBuilder.fixupExternalLibrary(program, libraryPaths,
fixup.libOrdinal(), symbol);
fixup.libOrdinal(), fixupSymbol);
}
catch (Exception e) {
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 {
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.");

View file

@ -146,7 +146,7 @@ public abstract class AbstractClassicProcessor {
status = Status.UNSUPPORTED;
}
else {
status = Status.APPLIED_OTHER;
status = Status.APPLIED;
}
// put an entry in the relocation table, handled or not

View file

@ -150,7 +150,7 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
if (entryPoint != null) {
Address entryPointAddr = space.getAddress(entryPoint);
program.getSymbolTable().addExternalEntryPoint(entryPointAddr);
createOneByteFunction("entry", entryPointAddr);
createOneByteFunction(program, "entry", entryPointAddr);
}
else {
log.appendMsg("Unable to determine entry point.");

View file

@ -514,7 +514,7 @@ public class MachoProgramBuilder {
if (!realEntryFound) {
program.getSymbolTable().createLabel(addr, "entry", SourceType.IMPORTED);
program.getSymbolTable().addExternalEntryPoint(addr);
createOneByteFunction("entry", addr);
createOneByteFunction(program, "entry", addr);
realEntryFound = true;
}
else {
@ -684,10 +684,11 @@ public class MachoProgramBuilder {
monitor.increment();
int symbolIndex = indirectSymbols.get(i);
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
String name =
symbol != null ? SymbolUtilities.replaceInvalidChars(symbol.getString(), true)
: "STUB_" + startAddr;
Function stubFunc = createOneByteFunction(name, startAddr);
String name = null;
if (symbol != null) {
name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true);
}
Function stubFunc = createOneByteFunction(program, name, startAddr);
if (stubFunc != null && symbol != null) {
ExternalLocation loc = program.getExternalManager()
.addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
@ -965,8 +966,8 @@ public class MachoProgramBuilder {
}
finally {
program.getRelocationTable()
.add(addr, success ? Status.APPLIED_OTHER : Status.FAILURE,
binding.getType(), null, bytes.length, binding.getSymbolName());
.add(addr, success ? Status.APPLIED : Status.FAILURE, binding.getType(),
null, bytes.length, binding.getSymbolName());
}
}
}
@ -1584,7 +1585,7 @@ public class MachoProgramBuilder {
}
Register tModeRegister = program.getLanguage().getRegister("TMode");
program.getProgramContext().setValue(tModeRegister, address, address, BigInteger.ONE);
createOneByteFunction(null, address);
createOneByteFunction(program, null, address);
}
private void processLazyPointerSection(AddressSetView set) {
@ -1638,13 +1639,14 @@ public class MachoProgramBuilder {
* create a one-byte function, so that when the code is analyzed,
* 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 address location to create the function
* @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
* 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();
Function function = functionMgr.getFunctionAt(address);
if (function != null) {

View file

@ -64,9 +64,9 @@ public class MachoProgramUtils {
Address ret;
if (externalBlock != null) {
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);
//joinedBlock.setName(MemoryBlock.EXTERNAL_BLOCK_NAME);
}
else {
ret = MachoProgramUtils.getNextAvailableAddress(program);

View file

@ -113,7 +113,7 @@ public class MachoExtractProgramBuilder extends MachoProgramBuilder {
// location to the newly exported function
Function func = funcManager.getFunctionAt(sym.getAddress());
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.
// After the first delete, the external location becomes an external label, which