diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/chained/DyldChainedFixups.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/chained/DyldChainedFixups.java
index b43ec8a59f..7a4c7cfecc 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/chained/DyldChainedFixups.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/chained/DyldChainedFixups.java
@@ -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
fixupChainedPointers(List fixups, Program program,
Address imagebase, List libraryPaths, MessageLog log, TaskMonitor monitor)
throws CancelledException {
- List 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 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.");
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java
index 4f80607718..c63e36072e 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java
@@ -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
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DyldCacheProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DyldCacheProgramBuilder.java
index 784c560e7b..bcb6e6cd03 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DyldCacheProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DyldCacheProgramBuilder.java
@@ -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.");
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
index 509aa8cf91..368ad63abf 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
@@ -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) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramUtils.java
index 1a918f9e7a..51c26309c5 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramUtils.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramUtils.java
@@ -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);
diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/app/util/opinion/MachoExtractProgramBuilder.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/app/util/opinion/MachoExtractProgramBuilder.java
index 84b3a25769..5cf3aa02c5 100644
--- a/Ghidra/Features/FileFormats/src/main/java/ghidra/app/util/opinion/MachoExtractProgramBuilder.java
+++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/app/util/opinion/MachoExtractProgramBuilder.java
@@ -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