mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-3248: MachoLoader now creates thunks on stubs
This commit is contained in:
@@ -124,7 +124,7 @@ public class MachoProgramBuilder {
|
|||||||
processEntryPoint();
|
processEntryPoint();
|
||||||
boolean exportsFound = processExports(machoHeader);
|
boolean exportsFound = processExports(machoHeader);
|
||||||
processSymbolTables(machoHeader, !exportsFound);
|
processSymbolTables(machoHeader, !exportsFound);
|
||||||
processIndirectSymbols();
|
processStubs();
|
||||||
processUndefinedSymbols();
|
processUndefinedSymbols();
|
||||||
processAbsoluteSymbols();
|
processAbsoluteSymbols();
|
||||||
List<Address> chainedFixups = processChainedFixups(machoHeader);
|
List<Address> chainedFixups = processChainedFixups(machoHeader);
|
||||||
@@ -570,19 +570,8 @@ public class MachoProgramBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void processIndirectSymbols() throws Exception {
|
protected void processStubs() throws Exception {
|
||||||
// We only want to directly handle indirect symbols on incomplete dylibs that were extracted
|
monitor.setMessage("Processing stubs...");
|
||||||
// from a dyld_shared_cache. If the Mach-O is fully-formed and contains binding information
|
|
||||||
// (found in the DyldChainedFixupsCommand or DyldInfoCommand), thunk analysis properly
|
|
||||||
// associates indirect symbols with their "real" symbol and we shouldn't do anything here.
|
|
||||||
// We hope to one day include binding information in our extracted dylibs, at which point
|
|
||||||
// this method can fully go away.
|
|
||||||
if (machoHeader.getFirstLoadCommand(DyldChainedFixupsCommand.class) != null ||
|
|
||||||
machoHeader.getFirstLoadCommand(DyldInfoCommand.class) != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor.setMessage("Processing indirect symbols...");
|
|
||||||
|
|
||||||
SymbolTableCommand symbolTableCommand =
|
SymbolTableCommand symbolTableCommand =
|
||||||
machoHeader.getFirstLoadCommand(SymbolTableCommand.class);
|
machoHeader.getFirstLoadCommand(SymbolTableCommand.class);
|
||||||
@@ -598,24 +587,14 @@ public class MachoProgramBuilder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Integer> sectionTypes = List.of(SectionTypes.S_NON_LAZY_SYMBOL_POINTERS,
|
for (Section section : machoHeader.getAllSections()) {
|
||||||
SectionTypes.S_LAZY_SYMBOL_POINTERS, SectionTypes.S_SYMBOL_STUBS);
|
|
||||||
|
|
||||||
List<Section> sections = machoHeader.getAllSections()
|
|
||||||
.stream()
|
|
||||||
.filter(s -> sectionTypes.contains(s.getType()))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
for (Section section : sections) {
|
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (section.getSize() == 0) {
|
if (section.getSize() == 0 || section.getType() != SectionTypes.S_SYMBOL_STUBS) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Namespace namespace = createNamespace(section.getSectionName());
|
|
||||||
|
|
||||||
int indirectSymbolTableIndex = section.getReserved1();
|
int indirectSymbolTableIndex = section.getReserved1();
|
||||||
|
|
||||||
int symbolSize = machoHeader.getAddressSize();
|
int symbolSize = machoHeader.getAddressSize();
|
||||||
@@ -632,19 +611,19 @@ public class MachoProgramBuilder {
|
|||||||
}
|
}
|
||||||
int symbolIndex = indirectSymbols[i];
|
int symbolIndex = indirectSymbols[i];
|
||||||
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
|
NList symbol = symbolTableCommand.getSymbolAt(symbolIndex);
|
||||||
if (symbol != null) {
|
if (symbol == null) {
|
||||||
String name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true);
|
continue;
|
||||||
if (name != null && name.length() > 0) {
|
}
|
||||||
try {
|
String name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true);
|
||||||
program.getSymbolTable()
|
if (name != null && name.length() > 0) {
|
||||||
.createLabel(startAddr, name, namespace, SourceType.IMPORTED);
|
Function stubFunc = createOneByteFunction(name, startAddr);
|
||||||
}
|
if (stubFunc != null) {
|
||||||
catch (Exception e) {
|
ExternalLocation loc = program.getExternalManager()
|
||||||
log.appendMsg("Unable to create indirect symbol " + name);
|
.addExtLocation(Library.UNKNOWN, name, null, SourceType.IMPORTED);
|
||||||
log.appendException(e);
|
stubFunc.setThunkedFunction(loc.createFunction());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startAddr = startAddr.add(symbolSize);
|
startAddr = startAddr.add(symbolSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1511,14 +1490,19 @@ public class MachoProgramBuilder {
|
|||||||
*
|
*
|
||||||
* @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.
|
||||||
|
* Otherwise, the newly created function will be returned. If there was a problem creating
|
||||||
|
* the function, null will be returned.
|
||||||
*/
|
*/
|
||||||
void createOneByteFunction(String name, Address address) {
|
Function createOneByteFunction(String name, Address address) {
|
||||||
FunctionManager functionMgr = program.getFunctionManager();
|
FunctionManager functionMgr = program.getFunctionManager();
|
||||||
if (functionMgr.getFunctionAt(address) != null) {
|
Function function = functionMgr.getFunctionAt(address);
|
||||||
return;
|
if (function != null) {
|
||||||
|
return function;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
functionMgr.createFunction(name, address, new AddressSet(address), SourceType.IMPORTED);
|
return functionMgr.createFunction(name, address, new AddressSet(address),
|
||||||
|
SourceType.IMPORTED);
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -1526,6 +1510,7 @@ public class MachoProgramBuilder {
|
|||||||
catch (OverlappingFunctionException e) {
|
catch (OverlappingFunctionException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user