mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 07:15:07 +08:00
GT-2845: updated Mach-O, DYLD, Prelink loaders to utilize FilesBytes.
This commit is contained in:
@@ -330,7 +330,7 @@ public class BinaryLoader extends AbstractProgramLoader {
|
|||||||
block.setWrite(isOverlay ? false : true);
|
block.setWrite(isOverlay ? false : true);
|
||||||
block.setExecute(isOverlay ? false : true);
|
block.setExecute(isOverlay ? false : true);
|
||||||
block.setSourceName("Binary Loader");
|
block.setSourceName("Binary Loader");
|
||||||
MemoryBlockUtil.adjustFragment(prog.getListing(), block.getStart(), blockName);
|
MemoryBlockUtils.adjustFragment(prog, block.getStart(), blockName);
|
||||||
}
|
}
|
||||||
catch (LockException | MemoryConflictException e) {
|
catch (LockException | MemoryConflictException e) {
|
||||||
Msg.error(this, "Unexpected exception creating memory block", e);
|
Msg.error(this, "Unexpected exception creating memory block", e);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package ghidra.app.util.opinion;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.app.util.MemoryBlockUtils;
|
||||||
import ghidra.app.util.Option;
|
import ghidra.app.util.Option;
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
@@ -44,8 +45,7 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
static final boolean PROCESS_SYMBOLS_OPTION_DEFAULT = true;
|
static final boolean PROCESS_SYMBOLS_OPTION_DEFAULT = true;
|
||||||
|
|
||||||
/** Loader option to create memory blocks for DYLIB sections */
|
/** Loader option to create memory blocks for DYLIB sections */
|
||||||
static final String CREATE_DYLIB_SECTIONS_OPTION_NAME =
|
static final String CREATE_DYLIB_SECTIONS_OPTION_NAME = "Create DYLIB section memory blocks";
|
||||||
"Create DYLIB section memory blocks (slow!)";
|
|
||||||
|
|
||||||
/** Default value for loader option to create memory blocks for DYLIB sections */
|
/** Default value for loader option to create memory blocks for DYLIB sections */
|
||||||
static final boolean CREATE_DYLIB_SECTIONS_OPTION_DEFAULT = false;
|
static final boolean CREATE_DYLIB_SECTIONS_OPTION_DEFAULT = false;
|
||||||
@@ -85,8 +85,9 @@ public class DyldCacheLoader extends AbstractLibrarySupportLoader {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DyldCacheProgramBuilder.buildProgram(program, provider, shouldProcessSymbols(options),
|
DyldCacheProgramBuilder.buildProgram(program, provider,
|
||||||
shouldCreateDylibSections(options), log, handler, monitor);
|
MemoryBlockUtils.createFileBytes(program, provider), shouldProcessSymbols(options),
|
||||||
|
shouldCreateDylibSections(options), log, monitor);
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+35
-43
@@ -19,13 +19,16 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.app.util.MemoryBlockUtils;
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
import ghidra.app.util.bin.format.macho.MachException;
|
import ghidra.app.util.bin.format.macho.MachException;
|
||||||
import ghidra.app.util.bin.format.macho.MachHeader;
|
import ghidra.app.util.bin.format.macho.MachHeader;
|
||||||
import ghidra.app.util.bin.format.macho.commands.NList;
|
import ghidra.app.util.bin.format.macho.commands.NList;
|
||||||
import ghidra.app.util.bin.format.macho.dyld.*;
|
import ghidra.app.util.bin.format.macho.dyld.*;
|
||||||
import ghidra.app.util.importer.*;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
import ghidra.app.util.importer.MessageLogContinuesFactory;
|
||||||
|
import ghidra.program.database.mem.FileBytes;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
@@ -47,17 +50,17 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
*
|
*
|
||||||
* @param program The {@link Program} to build up
|
* @param program The {@link Program} to build up
|
||||||
* @param provider The {@link ByteProvider} that contains the DYLD Cache bytes
|
* @param provider The {@link ByteProvider} that contains the DYLD Cache bytes
|
||||||
|
* @param fileBytes Where the Mach-O's bytes came from
|
||||||
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
||||||
* @param shouldCreateDylibSections True if memory blocks should be created for DYLIB sections;
|
* @param shouldCreateDylibSections True if memory blocks should be created for DYLIB sections;
|
||||||
* otherwise, false
|
* otherwise, false
|
||||||
* @param log The log
|
* @param log The log
|
||||||
* @param memoryConflictHandler How to handle memory conflicts that may occur
|
|
||||||
* @param monitor A cancelable task monitor
|
* @param monitor A cancelable task monitor
|
||||||
*/
|
*/
|
||||||
protected DyldCacheProgramBuilder(Program program, ByteProvider provider,
|
protected DyldCacheProgramBuilder(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
boolean shouldProcessSymbols, boolean shouldCreateDylibSections, MessageLog log,
|
boolean shouldProcessSymbols, boolean shouldCreateDylibSections, MessageLog log,
|
||||||
MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
super(program, provider, log, memoryConflictHandler, monitor);
|
super(program, provider, fileBytes, log, monitor);
|
||||||
this.shouldProcessSymbols = shouldProcessSymbols;
|
this.shouldProcessSymbols = shouldProcessSymbols;
|
||||||
this.shouldCreateDylibSections = shouldCreateDylibSections;
|
this.shouldCreateDylibSections = shouldCreateDylibSections;
|
||||||
}
|
}
|
||||||
@@ -67,20 +70,19 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
*
|
*
|
||||||
* @param program The {@link Program} to build up
|
* @param program The {@link Program} to build up
|
||||||
* @param provider The {@link ByteProvider} that contains the DYLD Cache's bytes
|
* @param provider The {@link ByteProvider} that contains the DYLD Cache's bytes
|
||||||
|
* @param fileBytes Where the Mach-O's bytes came from
|
||||||
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
* @param shouldProcessSymbols True if symbols should be processed; otherwise, false
|
||||||
* @param shouldCreateDylibSections True if memory blocks should be created for DYLIB sections;
|
* @param shouldCreateDylibSections True if memory blocks should be created for DYLIB sections;
|
||||||
* otherwise, false
|
* otherwise, false
|
||||||
* @param log The log
|
* @param log The log
|
||||||
* @param memoryConflictHandler How to handle memory conflicts that may occur
|
|
||||||
* @param monitor A cancelable task monitor
|
* @param monitor A cancelable task monitor
|
||||||
* @throws Exception if a problem occurs
|
* @throws Exception if a problem occurs
|
||||||
*/
|
*/
|
||||||
public static void buildProgram(Program program, ByteProvider provider,
|
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
boolean shouldProcessSymbols, boolean shouldCreateDylibSections, MessageLog log,
|
boolean shouldProcessSymbols, boolean shouldCreateDylibSections, MessageLog log,
|
||||||
MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor) throws Exception {
|
TaskMonitor monitor) throws Exception {
|
||||||
DyldCacheProgramBuilder dyldCacheProgramBuilder = new DyldCacheProgramBuilder(program,
|
DyldCacheProgramBuilder dyldCacheProgramBuilder = new DyldCacheProgramBuilder(program,
|
||||||
provider, shouldProcessSymbols, shouldCreateDylibSections, log, memoryConflictHandler,
|
provider, fileBytes, shouldProcessSymbols, shouldCreateDylibSections, log, monitor);
|
||||||
monitor);
|
|
||||||
dyldCacheProgramBuilder.build();
|
dyldCacheProgramBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,20 +95,12 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
dyldCacheHeader.parseFromFile(shouldProcessSymbols, log, monitor);
|
dyldCacheHeader.parseFromFile(shouldProcessSymbols, log, monitor);
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
|
|
||||||
try {
|
setDyldCacheImageBase();
|
||||||
setDyldCacheImageBase();
|
processDyldCacheMemoryBlocks();
|
||||||
processDyldCacheMemoryBlocks();
|
markupHeaders();
|
||||||
markupHeaders();
|
markupBranchIslands();
|
||||||
markupBranchIslands();
|
createSymbols();
|
||||||
createSymbols();
|
processDylibs();
|
||||||
processDylibs();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (mbu != null) {
|
|
||||||
mbu.dispose();
|
|
||||||
mbu = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,9 +129,9 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
for (DyldCacheMappingInfo mappingInfo : mappingInfos) {
|
for (DyldCacheMappingInfo mappingInfo : mappingInfos) {
|
||||||
long offset = mappingInfo.getFileOffset();
|
long offset = mappingInfo.getFileOffset();
|
||||||
long size = mappingInfo.getSize();
|
long size = mappingInfo.getSize();
|
||||||
mbu.createInitializedBlock("DYLD", space.getAddress(mappingInfo.getAddress()),
|
MemoryBlockUtils.createInitializedBlock(program, false, "DYLD",
|
||||||
provider.getInputStream(offset), size, "", "", mappingInfo.isRead(),
|
space.getAddress(mappingInfo.getAddress()), fileBytes, offset, size, "", "",
|
||||||
mappingInfo.isWrite(), mappingInfo.isExecute(), monitor);
|
mappingInfo.isRead(), mappingInfo.isWrite(), mappingInfo.isExecute(), log);
|
||||||
if (offset + size > endOfMappedOffset) {
|
if (offset + size > endOfMappedOffset) {
|
||||||
endOfMappedOffset = offset + size;
|
endOfMappedOffset = offset + size;
|
||||||
}
|
}
|
||||||
@@ -147,9 +141,10 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
|
|
||||||
if (endOfMappedOffset < provider.length()) {
|
if (endOfMappedOffset < provider.length()) {
|
||||||
monitor.setMessage("Processing DYLD unmapped memory block...");
|
monitor.setMessage("Processing DYLD unmapped memory block...");
|
||||||
mbu.createOverlayBlock("FILE", AddressSpace.OTHER_SPACE.getAddress(endOfMappedOffset),
|
MemoryBlockUtils.createInitializedBlock(program, true, "FILE",
|
||||||
provider.getInputStream(endOfMappedOffset), provider.length() - endOfMappedOffset,
|
AddressSpace.OTHER_SPACE.getAddress(endOfMappedOffset), fileBytes,
|
||||||
"Useful bytes that don't get mapped into memory", "", false, false, false, monitor);
|
endOfMappedOffset, provider.length() - endOfMappedOffset,
|
||||||
|
"Useful bytes that don't get mapped into memory", "", false, false, false, log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,10 +223,9 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
// easier
|
// easier
|
||||||
monitor.setMessage("Parsing DYLIB's...");
|
monitor.setMessage("Parsing DYLIB's...");
|
||||||
monitor.initialize(dyldCacheHeader.getImageInfos().size());
|
monitor.initialize(dyldCacheHeader.getImageInfos().size());
|
||||||
TreeSet<DyldCacheMachoInfo> dyldCacheMachoInfoSet =
|
List<DyldCacheMachoInfo> infoList = new ArrayList<>(dyldCacheHeader.getImageInfos().size());
|
||||||
new TreeSet<>((a, b) -> a.headerAddr.compareTo(b.headerAddr));
|
|
||||||
for (DyldCacheImageInfo dyldCacheImageInfo : dyldCacheHeader.getImageInfos()) {
|
for (DyldCacheImageInfo dyldCacheImageInfo : dyldCacheHeader.getImageInfos()) {
|
||||||
dyldCacheMachoInfoSet.add(new DyldCacheMachoInfo(provider,
|
infoList.add(new DyldCacheMachoInfo(provider,
|
||||||
dyldCacheImageInfo.getAddress() - dyldCacheHeader.getBaseAddress(),
|
dyldCacheImageInfo.getAddress() - dyldCacheHeader.getBaseAddress(),
|
||||||
space.getAddress(dyldCacheImageInfo.getAddress()), dyldCacheImageInfo.getPath()));
|
space.getAddress(dyldCacheImageInfo.getAddress()), dyldCacheImageInfo.getPath()));
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
@@ -240,8 +234,8 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
|
|
||||||
// Markup DyldCache Mach-O headers
|
// Markup DyldCache Mach-O headers
|
||||||
monitor.setMessage("Marking up DYLIB headers...");
|
monitor.setMessage("Marking up DYLIB headers...");
|
||||||
monitor.initialize(dyldCacheMachoInfoSet.size());
|
monitor.initialize(infoList.size());
|
||||||
for (DyldCacheMachoInfo info : dyldCacheMachoInfoSet) {
|
for (DyldCacheMachoInfo info : infoList) {
|
||||||
info.markupHeaders();
|
info.markupHeaders();
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
@@ -249,8 +243,8 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
|
|
||||||
// Add DyldCache Mach-O's to program tree
|
// Add DyldCache Mach-O's to program tree
|
||||||
monitor.setMessage("Adding DYLIB's to program tree...");
|
monitor.setMessage("Adding DYLIB's to program tree...");
|
||||||
monitor.initialize(dyldCacheMachoInfoSet.size());
|
monitor.initialize(infoList.size());
|
||||||
Iterator<DyldCacheMachoInfo> iter = dyldCacheMachoInfoSet.iterator();
|
Iterator<DyldCacheMachoInfo> iter = infoList.iterator();
|
||||||
if (iter.hasNext()) {
|
if (iter.hasNext()) {
|
||||||
DyldCacheMachoInfo curr = iter.next();
|
DyldCacheMachoInfo curr = iter.next();
|
||||||
do {
|
do {
|
||||||
@@ -263,13 +257,11 @@ public class DyldCacheProgramBuilder extends MachoProgramBuilder {
|
|||||||
while (iter.hasNext());
|
while (iter.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process DyldCache DYLIB memory blocks. Need to do it in descending (reverse) order or
|
// Process DyldCache DYLIB memory blocks.
|
||||||
// the memory block splitting will be way too slow.
|
|
||||||
monitor.setMessage("Processing DYLIB memory blocks...");
|
monitor.setMessage("Processing DYLIB memory blocks...");
|
||||||
monitor.initialize(dyldCacheMachoInfoSet.size());
|
monitor.initialize(infoList.size());
|
||||||
Iterator<DyldCacheMachoInfo> descendingIter = dyldCacheMachoInfoSet.descendingIterator();
|
for (DyldCacheMachoInfo info : infoList) {
|
||||||
while (descendingIter.hasNext()) {
|
info.processMemoryBlocks();
|
||||||
descendingIter.next().processMemoryBlocks();
|
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import generic.continues.RethrowContinuesFactory;
|
import generic.continues.RethrowContinuesFactory;
|
||||||
|
import ghidra.app.util.MemoryBlockUtils;
|
||||||
import ghidra.app.util.Option;
|
import ghidra.app.util.Option;
|
||||||
import ghidra.app.util.bin.*;
|
import ghidra.app.util.bin.*;
|
||||||
import ghidra.app.util.bin.format.macho.*;
|
import ghidra.app.util.bin.format.macho.*;
|
||||||
@@ -28,6 +29,7 @@ import ghidra.app.util.bin.format.ubi.*;
|
|||||||
import ghidra.app.util.importer.MemoryConflictHandler;
|
import ghidra.app.util.importer.MemoryConflictHandler;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.framework.model.DomainFolder;
|
import ghidra.framework.model.DomainFolder;
|
||||||
|
import ghidra.program.database.mem.FileBytes;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.LittleEndianDataConverter;
|
import ghidra.util.LittleEndianDataConverter;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@@ -81,15 +83,18 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
FileBytes fileBytes = MemoryBlockUtils.createFileBytes(program, provider);
|
||||||
|
|
||||||
// A Mach-O file may contain PRELINK information. If so, we use a special
|
// A Mach-O file may contain PRELINK information. If so, we use a special
|
||||||
// program builder that knows how to deal with it.
|
// program builder that knows how to deal with it.
|
||||||
List<PrelinkMap> prelinkList = MachoPrelinkUtils.parsePrelinkXml(provider, monitor);
|
List<PrelinkMap> prelinkList = MachoPrelinkUtils.parsePrelinkXml(provider, monitor);
|
||||||
if (!prelinkList.isEmpty()) {
|
if (!prelinkList.isEmpty()) {
|
||||||
MachoPrelinkProgramBuilder.buildProgram(program, provider, prelinkList, log, handler,
|
MachoPrelinkProgramBuilder.buildProgram(program, provider, fileBytes, prelinkList,
|
||||||
monitor);
|
log, monitor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MachoProgramBuilder.buildProgram(program, provider, log, handler, monitor);
|
MachoProgramBuilder.buildProgram(program, provider, fileBytes, log, handler,
|
||||||
|
monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
|||||||
+11
-10
@@ -25,7 +25,9 @@ import ghidra.app.util.bin.format.macho.MachHeader;
|
|||||||
import ghidra.app.util.bin.format.macho.Section;
|
import ghidra.app.util.bin.format.macho.Section;
|
||||||
import ghidra.app.util.bin.format.macho.commands.SegmentNames;
|
import ghidra.app.util.bin.format.macho.commands.SegmentNames;
|
||||||
import ghidra.app.util.bin.format.macho.prelink.PrelinkMap;
|
import ghidra.app.util.bin.format.macho.prelink.PrelinkMap;
|
||||||
import ghidra.app.util.importer.*;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
import ghidra.app.util.importer.MessageLogContinuesFactory;
|
||||||
|
import ghidra.program.database.mem.FileBytes;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataUtilities;
|
import ghidra.program.model.data.DataUtilities;
|
||||||
import ghidra.program.model.data.Pointer64DataType;
|
import ghidra.program.model.data.Pointer64DataType;
|
||||||
@@ -48,15 +50,15 @@ public class MachoPrelinkProgramBuilder extends MachoProgramBuilder {
|
|||||||
*
|
*
|
||||||
* @param program The {@link Program} to build up.
|
* @param program The {@link Program} to build up.
|
||||||
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
||||||
|
* @param fileBytes Where the Mach-O's bytes came from.
|
||||||
* @param prelinkList Parsed {@link PrelinkMap PRELINK} information.
|
* @param prelinkList Parsed {@link PrelinkMap PRELINK} information.
|
||||||
* @param log The log.
|
* @param log The log.
|
||||||
* @param memoryConflictHandler How to handle memory conflicts that may occur.
|
|
||||||
* @param monitor A cancelable task monitor.
|
* @param monitor A cancelable task monitor.
|
||||||
*/
|
*/
|
||||||
protected MachoPrelinkProgramBuilder(Program program, ByteProvider provider,
|
protected MachoPrelinkProgramBuilder(Program program, ByteProvider provider,
|
||||||
List<PrelinkMap> prelinkList, MessageLog log,
|
FileBytes fileBytes, List<PrelinkMap> prelinkList, MessageLog log,
|
||||||
MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
super(program, provider, log, memoryConflictHandler, monitor);
|
super(program, provider, fileBytes, log, monitor);
|
||||||
this.prelinkList = prelinkList;
|
this.prelinkList = prelinkList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +67,16 @@ public class MachoPrelinkProgramBuilder extends MachoProgramBuilder {
|
|||||||
*
|
*
|
||||||
* @param program The {@link Program} to build up.
|
* @param program The {@link Program} to build up.
|
||||||
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
||||||
|
* @param fileBytes Where the Mach-O's bytes came from.
|
||||||
* @param prelinkList Parsed {@link PrelinkMap PRELINK} information.
|
* @param prelinkList Parsed {@link PrelinkMap PRELINK} information.
|
||||||
* @param log The log.
|
* @param log The log.
|
||||||
* @param memoryConflictHandler How to handle memory conflicts that may occur.
|
|
||||||
* @param monitor A cancelable task monitor.
|
* @param monitor A cancelable task monitor.
|
||||||
* @throws Exception if a problem occurs.
|
* @throws Exception if a problem occurs.
|
||||||
*/
|
*/
|
||||||
public static void buildProgram(Program program, ByteProvider provider,
|
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
List<PrelinkMap> prelinkList, MessageLog log,
|
List<PrelinkMap> prelinkList, MessageLog log, TaskMonitor monitor) throws Exception {
|
||||||
MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor) throws Exception {
|
|
||||||
MachoPrelinkProgramBuilder machoPrelinkProgramBuilder = new MachoPrelinkProgramBuilder(
|
MachoPrelinkProgramBuilder machoPrelinkProgramBuilder = new MachoPrelinkProgramBuilder(
|
||||||
program, provider, prelinkList, log, memoryConflictHandler, monitor);
|
program, provider, fileBytes, prelinkList, log, monitor);
|
||||||
machoPrelinkProgramBuilder.build();
|
machoPrelinkProgramBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-54
@@ -19,7 +19,7 @@ import java.math.BigInteger;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.MemoryBlockUtil;
|
import ghidra.app.util.MemoryBlockUtils;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.app.util.bin.format.macho.*;
|
import ghidra.app.util.bin.format.macho.*;
|
||||||
@@ -30,6 +30,7 @@ import ghidra.app.util.bin.format.objectiveC.ObjectiveC1_Constants;
|
|||||||
import ghidra.app.util.importer.*;
|
import ghidra.app.util.importer.*;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.program.database.function.OverlappingFunctionException;
|
import ghidra.program.database.function.OverlappingFunctionException;
|
||||||
|
import ghidra.program.database.mem.FileBytes;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.Processor;
|
import ghidra.program.model.lang.Processor;
|
||||||
@@ -55,32 +56,32 @@ public class MachoProgramBuilder {
|
|||||||
|
|
||||||
protected Program program;
|
protected Program program;
|
||||||
protected ByteProvider provider;
|
protected ByteProvider provider;
|
||||||
|
protected FileBytes fileBytes;
|
||||||
protected MessageLog log;
|
protected MessageLog log;
|
||||||
protected TaskMonitor monitor;
|
protected TaskMonitor monitor;
|
||||||
protected Memory memory;
|
protected Memory memory;
|
||||||
protected Listing listing;
|
protected Listing listing;
|
||||||
protected AddressSpace space;
|
protected AddressSpace space;
|
||||||
protected MemoryBlockUtil mbu;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link MachoProgramBuilder} based on the given information.
|
* Creates a new {@link MachoProgramBuilder} based on the given information.
|
||||||
*
|
*
|
||||||
* @param program The {@link Program} to build up.
|
* @param program The {@link Program} to build up.
|
||||||
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
||||||
|
* @param fileBytes Where the Mach-O's bytes came from.
|
||||||
* @param log The log.
|
* @param log The log.
|
||||||
* @param memoryConflictHandler How to handle memory conflicts that may occur.
|
|
||||||
* @param monitor A cancelable task monitor.
|
* @param monitor A cancelable task monitor.
|
||||||
*/
|
*/
|
||||||
protected MachoProgramBuilder(Program program, ByteProvider provider, MessageLog log,
|
protected MachoProgramBuilder(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor) {
|
MessageLog log, TaskMonitor monitor) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
this.fileBytes = fileBytes;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
this.memory = program.getMemory();
|
this.memory = program.getMemory();
|
||||||
this.listing = program.getListing();
|
this.listing = program.getListing();
|
||||||
this.space = program.getAddressFactory().getDefaultAddressSpace();
|
this.space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
this.mbu = new MemoryBlockUtil(program, memoryConflictHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,15 +89,17 @@ public class MachoProgramBuilder {
|
|||||||
*
|
*
|
||||||
* @param program The {@link Program} to build up.
|
* @param program The {@link Program} to build up.
|
||||||
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
* @param provider The {@link ByteProvider} that contains the Mach-O's bytes.
|
||||||
|
* @param fileBytes Where the Mach-O's bytes came from.
|
||||||
* @param log The log.
|
* @param log The log.
|
||||||
* @param memoryConflictHandler How to handle memory conflicts that may occur.
|
* @param memoryConflictHandler How to handle memory conflicts that may occur.
|
||||||
* @param monitor A cancelable task monitor.
|
* @param monitor A cancelable task monitor.
|
||||||
* @throws Exception if a problem occurs.
|
* @throws Exception if a problem occurs.
|
||||||
*/
|
*/
|
||||||
public static void buildProgram(Program program, ByteProvider provider, MessageLog log,
|
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
|
||||||
MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor) throws Exception {
|
MessageLog log, MemoryConflictHandler memoryConflictHandler, TaskMonitor monitor)
|
||||||
|
throws Exception {
|
||||||
MachoProgramBuilder machoProgramBuilder =
|
MachoProgramBuilder machoProgramBuilder =
|
||||||
new MachoProgramBuilder(program, provider, log, memoryConflictHandler, monitor);
|
new MachoProgramBuilder(program, provider, fileBytes, log, monitor);
|
||||||
machoProgramBuilder.build();
|
machoProgramBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,33 +118,25 @@ public class MachoProgramBuilder {
|
|||||||
}
|
}
|
||||||
monitor.setCancelEnabled(true);
|
monitor.setCancelEnabled(true);
|
||||||
|
|
||||||
try {
|
setImageBase();
|
||||||
setImageBase();
|
processEntryPoint();
|
||||||
processEntryPoint();
|
processMemoryBlocks(machoHeader, provider.getName(), true, true);
|
||||||
processMemoryBlocks(machoHeader, provider.getName(), true, true);
|
processUnsupportedLoadCommands();
|
||||||
processUnsupportedLoadCommands();
|
processSymbolTables();
|
||||||
processSymbolTables();
|
processIndirectSymbols();
|
||||||
processIndirectSymbols();
|
setRelocatableProperty();
|
||||||
setRelocatableProperty();
|
processLibraries();
|
||||||
processLibraries();
|
processProgramDescription();
|
||||||
processProgramDescription();
|
renameObjMsgSendRtpSymbol();
|
||||||
renameObjMsgSendRtpSymbol();
|
processUndefinedSymbols();
|
||||||
processUndefinedSymbols();
|
processAbsoluteSymbols();
|
||||||
processAbsoluteSymbols();
|
processDyldInfo();
|
||||||
processDyldInfo();
|
markupHeaders(machoHeader, headerAddr);
|
||||||
markupHeaders(machoHeader, headerAddr);
|
markupSections();
|
||||||
markupSections();
|
processProgramVars();
|
||||||
processProgramVars();
|
loadSectionRelocations();
|
||||||
loadSectionRelocations();
|
loadExternalRelocations();
|
||||||
loadExternalRelocations();
|
loadLocalRelocations();
|
||||||
loadLocalRelocations();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (mbu != null) {
|
|
||||||
mbu.dispose();
|
|
||||||
mbu = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setImageBase() throws Exception {
|
private void setImageBase() throws Exception {
|
||||||
@@ -219,12 +214,8 @@ public class MachoProgramBuilder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create memory blocks for segments. Create them in reverse order so the splitting
|
// Create memory blocks for segments.
|
||||||
// is more efficient.
|
for (SegmentCommand segment : header.getAllSegments()) {
|
||||||
List<SegmentCommand> segments = header.getAllSegments();
|
|
||||||
segments.sort((SegmentCommand a, SegmentCommand b) -> Long.compare(b.getVMaddress(),
|
|
||||||
a.getVMaddress()));
|
|
||||||
for (SegmentCommand segment : segments) {
|
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -256,12 +247,9 @@ public class MachoProgramBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create memory blocks for sections. They will be in the segments we just created, so the
|
// Create memory blocks for sections. They will be in the segments we just created, so the
|
||||||
// segment blocks will be split and possibly replaced. Create them in reverse order so
|
// segment blocks will be split and possibly replaced.
|
||||||
// the splitting is more efficient.
|
|
||||||
if (processSections) {
|
if (processSections) {
|
||||||
List<Section> sections = header.getAllSections();
|
for (Section section : header.getAllSections()) {
|
||||||
sections.sort((Section a, Section b) -> Long.compare(b.getAddress(), a.getAddress()));
|
|
||||||
for (Section section : sections) {
|
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -331,12 +319,12 @@ public class MachoProgramBuilder {
|
|||||||
if (intersectingBlocks.isEmpty()) {
|
if (intersectingBlocks.isEmpty()) {
|
||||||
if (zeroFill) {
|
if (zeroFill) {
|
||||||
// Treat zero-fill blocks as uninitialized to save space
|
// Treat zero-fill blocks as uninitialized to save space
|
||||||
return mbu.createUninitializedBlock(false, name, start, dataLength, comment, source,
|
return MemoryBlockUtils.createUninitializedBlock(program, false, name, start,
|
||||||
r, w, x);
|
dataLength, comment, source, r, w, x, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mbu.createInitializedBlock(name, start, provider.getInputStream(dataOffset),
|
return MemoryBlockUtils.createInitializedBlock(program, false, name, start, fileBytes,
|
||||||
dataLength, comment, source, r, w, x, monitor);
|
dataOffset, dataLength, comment, source, r, w, x, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split the starting block (if necessary). Splitting is not necessary if the start of our
|
// Split the starting block (if necessary). Splitting is not necessary if the start of our
|
||||||
@@ -363,9 +351,7 @@ public class MachoProgramBuilder {
|
|||||||
for (MemoryBlock block : memory.getBlocks()) {
|
for (MemoryBlock block : memory.getBlocks()) {
|
||||||
if (range.intersects(block.getStart(), block.getEnd())) {
|
if (range.intersects(block.getStart(), block.getEnd())) {
|
||||||
block.setName(name);
|
block.setName(name);
|
||||||
block.setRead(r);
|
block.setPermissions(r, w, x);
|
||||||
block.setWrite(w);
|
|
||||||
block.setExecute(x);
|
|
||||||
block.setSourceName(source);
|
block.setSourceName(source);
|
||||||
block.setComment(comment);
|
block.setComment(comment);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-3
@@ -23,6 +23,7 @@ import org.apache.commons.collections4.BidiMap;
|
|||||||
import org.jdom.JDOMException;
|
import org.jdom.JDOMException;
|
||||||
|
|
||||||
import generic.continues.RethrowContinuesFactory;
|
import generic.continues.RethrowContinuesFactory;
|
||||||
|
import ghidra.app.util.MemoryBlockUtils;
|
||||||
import ghidra.app.util.bin.*;
|
import ghidra.app.util.bin.*;
|
||||||
import ghidra.app.util.bin.format.macho.*;
|
import ghidra.app.util.bin.format.macho.*;
|
||||||
import ghidra.app.util.bin.format.macho.commands.*;
|
import ghidra.app.util.bin.format.macho.commands.*;
|
||||||
@@ -37,6 +38,7 @@ import ghidra.formats.gfilesystem.factory.GFileSystemBaseFactory;
|
|||||||
import ghidra.framework.store.local.LocalFileSystem;
|
import ghidra.framework.store.local.LocalFileSystem;
|
||||||
import ghidra.macosx.MacosxLanguageHelper;
|
import ghidra.macosx.MacosxLanguageHelper;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
|
import ghidra.program.database.mem.FileBytes;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.lang.LanguageCompilerSpecPair;
|
import ghidra.program.model.lang.LanguageCompilerSpecPair;
|
||||||
import ghidra.program.model.lang.LanguageService;
|
import ghidra.program.model.lang.LanguageService;
|
||||||
@@ -185,9 +187,12 @@ public class PrelinkFileSystem extends GFileSystemBase implements GFileSystemPro
|
|||||||
int id = program.startTransaction(getName());
|
int id = program.startTransaction(getName());
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
MachoProgramBuilder.buildProgram(program,
|
FileBytes fileBytes = MemoryBlockUtils.createFileBytes(program, provider, offset,
|
||||||
new ByteProviderWrapper(provider, offset, provider.length() - offset),
|
provider.length() - offset);
|
||||||
new MessageLog(), MemoryConflictHandler.NEVER_OVERWRITE, monitor);
|
ByteProvider providerWrapper =
|
||||||
|
new ByteProviderWrapper(provider, offset, provider.length() - offset);
|
||||||
|
MachoProgramBuilder.buildProgram(program, providerWrapper, fileBytes, new MessageLog(),
|
||||||
|
MemoryConflictHandler.NEVER_OVERWRITE, monitor);
|
||||||
program.setExecutableFormat(MachoLoader.MACH_O_NAME);
|
program.setExecutableFormat(MachoLoader.MACH_O_NAME);
|
||||||
program.setExecutablePath(file.getPath());
|
program.setExecutablePath(file.getPath());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user