mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-07-05 01:08:38 +00:00
GP-3565: More Mach-O markup improvements
This commit is contained in:
parent
54d2bc2997
commit
05af5149ad
|
@ -63,13 +63,13 @@ public class DataInCodeCommand extends LinkEditDataCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, Address addr, String source,
|
||||
TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
if (addr == null || datasize == 0) {
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
Address addr = fileOffsetToAddress(program, header, dataoff, datasize);
|
||||
if (addr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.markup(program, header, addr, source, monitor, log);
|
||||
super.markup(program, header, source, monitor, log);
|
||||
|
||||
try {
|
||||
for (DataInCodeEntry entry : entries) {
|
||||
|
|
|
@ -64,14 +64,13 @@ public class DyldChainedFixupsCommand extends LinkEditDataCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, Address addr, String source,
|
||||
TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
|
||||
if (addr == null || datasize == 0) {
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
Address addr = fileOffsetToAddress(program, header, dataoff, datasize);
|
||||
if (addr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.markup(program, header, addr, source, monitor, log);
|
||||
super.markup(program, header, source, monitor, log);
|
||||
|
||||
try {
|
||||
DataUtilities.createData(program, addr, chainHeader.toDataType(), -1,
|
||||
|
|
|
@ -24,7 +24,9 @@ import ghidra.app.util.importer.MessageLog;
|
|||
import ghidra.program.flatapi.FlatProgramAPI;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.ProgramModule;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
|
@ -32,16 +34,16 @@ import ghidra.util.task.TaskMonitor;
|
|||
* Represents a dyld_info_command structure
|
||||
*/
|
||||
public class DyldInfoCommand extends LoadCommand {
|
||||
private int rebase_off;
|
||||
private int rebase_size;
|
||||
private int bind_off;
|
||||
private int bind_size;
|
||||
private int weak_bind_off;
|
||||
private int weak_bind_size;
|
||||
private int lazy_bind_off;
|
||||
private int lazy_bind_size;
|
||||
private int export_off;
|
||||
private int export_size;
|
||||
private int rebaseOff;
|
||||
private int rebaseSize;
|
||||
private int bindOff;
|
||||
private int bindSize;
|
||||
private int weakBindOff;
|
||||
private int weakBindSize;
|
||||
private int lazyBindOff;
|
||||
private int lazyBindSize;
|
||||
private int exportOff;
|
||||
private int exportSize;
|
||||
|
||||
private ExportTrie exportTrie;
|
||||
|
||||
|
@ -59,19 +61,19 @@ public class DyldInfoCommand extends LoadCommand {
|
|||
throws IOException {
|
||||
super(loadCommandReader);
|
||||
|
||||
rebase_off = loadCommandReader.readNextInt();
|
||||
rebase_size = loadCommandReader.readNextInt();
|
||||
bind_off = loadCommandReader.readNextInt();
|
||||
bind_size = loadCommandReader.readNextInt();
|
||||
weak_bind_off = loadCommandReader.readNextInt();
|
||||
weak_bind_size = loadCommandReader.readNextInt();
|
||||
lazy_bind_off = loadCommandReader.readNextInt();
|
||||
lazy_bind_size = loadCommandReader.readNextInt();
|
||||
export_off = loadCommandReader.readNextInt();
|
||||
export_size = loadCommandReader.readNextInt();
|
||||
rebaseOff = loadCommandReader.readNextInt();
|
||||
rebaseSize = loadCommandReader.readNextInt();
|
||||
bindOff = loadCommandReader.readNextInt();
|
||||
bindSize = loadCommandReader.readNextInt();
|
||||
weakBindOff = loadCommandReader.readNextInt();
|
||||
weakBindSize = loadCommandReader.readNextInt();
|
||||
lazyBindOff = loadCommandReader.readNextInt();
|
||||
lazyBindSize = loadCommandReader.readNextInt();
|
||||
exportOff = loadCommandReader.readNextInt();
|
||||
exportSize = loadCommandReader.readNextInt();
|
||||
|
||||
if (export_off > 0 && export_size > 0) {
|
||||
dataReader.setPointerIndex(header.getStartIndex() + export_off);
|
||||
if (exportOff > 0 && exportSize > 0) {
|
||||
dataReader.setPointerIndex(header.getStartIndex() + exportOff);
|
||||
exportTrie = new ExportTrie(dataReader);
|
||||
}
|
||||
else {
|
||||
|
@ -79,152 +81,181 @@ public class DyldInfoCommand extends LoadCommand {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The rebase info offset}
|
||||
*/
|
||||
public int getRebaseOffset() {
|
||||
return rebaseOff;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The rebase info size}
|
||||
*/
|
||||
public int getRebaseSize() {
|
||||
return rebaseSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The bind info offset}
|
||||
*/
|
||||
public int getBindOffset() {
|
||||
return bindOff;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The bind info size}
|
||||
*/
|
||||
public int getBindSize() {
|
||||
return bindSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The weak bind info offset}
|
||||
*/
|
||||
public int getWeakBindOffset() {
|
||||
return weakBindOff;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The weak bind info size}
|
||||
*/
|
||||
public int getWeakBindSize() {
|
||||
return weakBindSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The lazy bind info offset}
|
||||
*/
|
||||
public int getLazyBindOffset() {
|
||||
return lazyBindOff;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The lazy bind info size}
|
||||
*/
|
||||
public int getLazyBindSize() {
|
||||
return lazyBindSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The export info offset}
|
||||
*/
|
||||
public int getExportOffset() {
|
||||
return exportOff;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The export info size}
|
||||
*/
|
||||
public int getExportSize() {
|
||||
return exportSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return The export trie}
|
||||
*/
|
||||
public ExportTrie getExportTrie() {
|
||||
return exportTrie;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "dyld_info_command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(getCommandName(), 0);
|
||||
struct.add(DWORD, "cmd", null);
|
||||
struct.add(DWORD, "cmdsize", null);
|
||||
struct.add(DWORD, "rebase_off", "file offset to rebase info");
|
||||
struct.add(DWORD, "rebase_size", "size of rebase info");
|
||||
struct.add(DWORD, "bind_off", "file offset to binding info");
|
||||
struct.add(DWORD, "bind_size", "size of binding info");
|
||||
struct.add(DWORD, "weak_bind_off", "file offset to weak binding info");
|
||||
struct.add(DWORD, "weak_bind_size", "size of weak binding info");
|
||||
struct.add(DWORD, "lazy_bind_off", "file offset to lazy binding info");
|
||||
struct.add(DWORD, "lazy_bind_size", "size of lazy binding info");
|
||||
struct.add(DWORD, "export_off", "file offset to lazy binding info");
|
||||
struct.add(DWORD, "export_size", "size of lazy binding info");
|
||||
struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY));
|
||||
return struct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
markupRebaseInfo(program, header, source, monitor, log);
|
||||
markupBindInfo(program, header, source, monitor, log);
|
||||
markupWeakBindInfo(program, header, source, monitor, log);
|
||||
markupLazyBindInfo(program, header, source, monitor, log);
|
||||
markupExportInfo(program, header, source, monitor, log);
|
||||
|
||||
}
|
||||
|
||||
private void markupRebaseInfo(Program program, MachHeader header, String source,
|
||||
TaskMonitor monitor, MessageLog log) {
|
||||
markupPlateComment(program, fileOffsetToAddress(program, header, rebaseOff, rebaseSize),
|
||||
source, "rebase");
|
||||
}
|
||||
|
||||
private void markupBindInfo(Program program, MachHeader header, String source,
|
||||
TaskMonitor monitor, MessageLog log) {
|
||||
markupPlateComment(program, fileOffsetToAddress(program, header, bindOff, bindSize),
|
||||
source, "bind");
|
||||
}
|
||||
|
||||
private void markupWeakBindInfo(Program program, MachHeader header, String source,
|
||||
TaskMonitor monitor, MessageLog log) {
|
||||
markupPlateComment(program, fileOffsetToAddress(program, header, weakBindOff, weakBindSize),
|
||||
source, "weak bind");
|
||||
}
|
||||
|
||||
private void markupLazyBindInfo(Program program, MachHeader header, String source,
|
||||
TaskMonitor monitor, MessageLog log) {
|
||||
markupPlateComment(program, fileOffsetToAddress(program, header, lazyBindOff, lazyBindSize),
|
||||
source, "lazy bind");
|
||||
}
|
||||
|
||||
private void markupExportInfo(Program program, MachHeader header, String source,
|
||||
TaskMonitor monitor, MessageLog log) {
|
||||
markupPlateComment(program, fileOffsetToAddress(program, header, exportOff, exportSize),
|
||||
source, "export");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markupRawBinary(MachHeader header, FlatProgramAPI api, Address baseAddress,
|
||||
ProgramModule parentModule, TaskMonitor monitor, MessageLog log) {
|
||||
try {
|
||||
super.markupRawBinary(header, api, baseAddress, parentModule, monitor, log);
|
||||
|
||||
if (rebase_size > 0) {
|
||||
Address start = baseAddress.getNewAddress(rebase_off);
|
||||
if (rebaseSize > 0) {
|
||||
Address start = baseAddress.getNewAddress(rebaseOff);
|
||||
api.createFragment(parentModule, getCommandName() + "_REBASE", start,
|
||||
rebase_size);
|
||||
rebaseSize);
|
||||
}
|
||||
if (bind_size > 0) {
|
||||
Address start = baseAddress.getNewAddress(bind_off);
|
||||
api.createFragment(parentModule, getCommandName() + "_BIND", start, bind_size);
|
||||
if (bindSize > 0) {
|
||||
Address start = baseAddress.getNewAddress(bindOff);
|
||||
api.createFragment(parentModule, getCommandName() + "_BIND", start, bindSize);
|
||||
}
|
||||
if (weak_bind_size > 0) {
|
||||
Address start = baseAddress.getNewAddress(weak_bind_off);
|
||||
if (weakBindSize > 0) {
|
||||
Address start = baseAddress.getNewAddress(weakBindOff);
|
||||
api.createFragment(parentModule, getCommandName() + "_WEAK_BIND", start,
|
||||
weak_bind_size);
|
||||
weakBindSize);
|
||||
}
|
||||
if (lazy_bind_size > 0) {
|
||||
Address start = baseAddress.getNewAddress(lazy_bind_off);
|
||||
if (lazyBindSize > 0) {
|
||||
Address start = baseAddress.getNewAddress(lazyBindOff);
|
||||
api.createFragment(parentModule, getCommandName() + "_LAZY_BIND", start,
|
||||
lazy_bind_size);
|
||||
lazyBindSize);
|
||||
}
|
||||
if (export_size > 0) {
|
||||
Address start = baseAddress.getNewAddress(export_off);
|
||||
if (exportSize > 0) {
|
||||
Address start = baseAddress.getNewAddress(exportOff);
|
||||
api.createFragment(parentModule, getCommandName() + "_EXPORT", start,
|
||||
export_size);
|
||||
exportSize);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.appendMsg("Unable to create " + getCommandName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
StructureDataType struct = new StructureDataType(getCommandName(), 0);
|
||||
struct.add(DWORD, "cmd", null);
|
||||
struct.add(DWORD, "cmdsize", null);
|
||||
struct.add(DWORD, "rebase_off", null);
|
||||
struct.add(DWORD, "rebase_size", null);
|
||||
struct.add(DWORD, "bind_off", null);
|
||||
struct.add(DWORD, "bind_size", null);
|
||||
struct.add(DWORD, "weak_bind_off", null);
|
||||
struct.add(DWORD, "weak_bind_size", null);
|
||||
struct.add(DWORD, "lazy_bind_off", null);
|
||||
struct.add(DWORD, "lazy_bind_size", null);
|
||||
struct.add(DWORD, "export_off", null);
|
||||
struct.add(DWORD, "export_size", null);
|
||||
struct.setCategoryPath(new CategoryPath(MachConstants.DATA_TYPE_CATEGORY));
|
||||
return struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* file offset to rebase info
|
||||
* @return file offset to rebase info
|
||||
*/
|
||||
public int getRebaseOffset() {
|
||||
return rebase_off;
|
||||
}
|
||||
|
||||
/**
|
||||
* size of rebase info
|
||||
* @return size of rebase info
|
||||
*/
|
||||
public int getRebaseSize() {
|
||||
return rebase_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* file offset to binding info
|
||||
* @return file offset to binding info
|
||||
*/
|
||||
public int getBindOffset() {
|
||||
return bind_off;
|
||||
}
|
||||
|
||||
/**
|
||||
* size of binding info
|
||||
* @return size of binding info
|
||||
*/
|
||||
public int getBindSize() {
|
||||
return bind_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* file offset to weak binding info
|
||||
* @return file offset to weak binding info
|
||||
*/
|
||||
public int getWeakBindOffset() {
|
||||
return weak_bind_off;
|
||||
}
|
||||
|
||||
/**
|
||||
* size of weak binding info
|
||||
* @return size of weak binding info
|
||||
*/
|
||||
public int getWeakBindSize() {
|
||||
return weak_bind_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* file offset to lazy binding info
|
||||
* @return file offset to lazy binding info
|
||||
*/
|
||||
public int getLazyBindOffset() {
|
||||
return lazy_bind_off;
|
||||
}
|
||||
|
||||
/**
|
||||
* size of lazy binding infs
|
||||
* @return
|
||||
*/
|
||||
public int getLazyBindSize() {
|
||||
return lazy_bind_size;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getExportOffset() {
|
||||
return export_off;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getExportSize() {
|
||||
return export_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ExportTrie}
|
||||
*
|
||||
* @return The {@link ExportTrie}
|
||||
*/
|
||||
public ExportTrie getExportTrie() {
|
||||
return exportTrie;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,9 @@ public final class DyldInfoCommandConstants {
|
|||
public final static int BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0;
|
||||
public final static int BIND_OPCODE_THREADED = 0xD0;
|
||||
|
||||
public final static int BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB = 0x00;
|
||||
public final static int BIND_SUBOPCODE_THREADED_APPLY = 0x01;
|
||||
|
||||
/*
|
||||
* The following are used on the flags byte of a terminal node
|
||||
* in the export information.
|
||||
|
|
|
@ -24,7 +24,6 @@ import ghidra.app.util.bin.format.macho.*;
|
|||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.flatapi.FlatProgramAPI;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
@ -347,44 +346,32 @@ public class DynamicSymbolTableCommand extends LoadCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address getDataAddress(MachHeader header, AddressSpace space) {
|
||||
if (indirectsymoff != 0 && nindirectsyms != 0) {
|
||||
SegmentCommand segment = getContainingSegment(header, indirectsymoff);
|
||||
if (segment != null) {
|
||||
return space.getAddress(
|
||||
segment.getVMaddress() + (indirectsymoff - segment.getFileOffset()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
markupIndirectSymbolTable(program, header, source, monitor, log);
|
||||
|
||||
// TODO: Handle more than just the indirect symbol table
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, Address indirectSymbolTableAddr,
|
||||
String source, TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
// TODO: Handle more than just the indirect symbol table
|
||||
private void markupIndirectSymbolTable(Program program, MachHeader header, String source,
|
||||
TaskMonitor monitor, MessageLog log) {
|
||||
Address indirectSymbolTableAddr =
|
||||
fileOffsetToAddress(program, header, indirectsymoff, nindirectsyms);
|
||||
if (indirectSymbolTableAddr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
markupPlateComment(program, indirectSymbolTableAddr, source, "indirect");
|
||||
|
||||
Listing listing = program.getListing();
|
||||
ReferenceManager referenceManager = program.getReferenceManager();
|
||||
String name = LoadCommandTypes.getLoadCommandName(getCommandType()) + " (indirect)";
|
||||
if (source != null) {
|
||||
name += " - " + source;
|
||||
}
|
||||
SymbolTableCommand symbolTable = header.getFirstLoadCommand(SymbolTableCommand.class);
|
||||
Address symbolTableAddr = null;
|
||||
Address stringTableAddr = null;
|
||||
if (symbolTable != null) {
|
||||
symbolTableAddr =
|
||||
symbolTable.getDataAddress(header, indirectSymbolTableAddr.getAddressSpace());
|
||||
if (symbolTable.getStringTableOffset() != 0) {
|
||||
stringTableAddr = symbolTableAddr
|
||||
.add(symbolTable.getStringTableOffset() - symbolTable.getSymbolOffset());
|
||||
}
|
||||
}
|
||||
Address symbolTableAddr = fileOffsetToAddress(program, header,
|
||||
symbolTable.getSymbolOffset(), symbolTable.getNumberOfSymbols());
|
||||
Address stringTableAddr = fileOffsetToAddress(program, header,
|
||||
symbolTable.getStringTableOffset(), symbolTable.getStringTableSize());
|
||||
|
||||
ReferenceManager referenceManager = program.getReferenceManager();
|
||||
try {
|
||||
listing.setComment(indirectSymbolTableAddr, CodeUnit.PLATE_COMMENT, name);
|
||||
for (int i = 0; i < nindirectsyms; i++) {
|
||||
int nlistIndex = indirectSymbols[i];
|
||||
Address dataAddr = indirectSymbolTableAddr.add(i * DWORD.getLength());
|
||||
|
@ -408,6 +395,7 @@ public class DynamicSymbolTableCommand extends LoadCommand {
|
|||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
String name = LoadCommandTypes.getLoadCommandName(getCommandType()) + " (indirect)";
|
||||
log.appendMsg(DynamicSymbolTableCommand.class.getSimpleName(),
|
||||
"Failed to markup %s.".formatted(name));
|
||||
}
|
||||
|
|
|
@ -80,13 +80,13 @@ public class FunctionStartsCommand extends LinkEditDataCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, Address addr, String source,
|
||||
TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
if (addr == null || datasize == 0) {
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
Address addr = fileOffsetToAddress(program, header, dataoff, datasize);
|
||||
if (addr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.markup(program, header, addr, source, monitor, log);
|
||||
super.markup(program, header, source, monitor, log);
|
||||
|
||||
SegmentCommand textSegment = header.getSegment(SegmentNames.SEG_TEXT);
|
||||
if (textSegment == null) {
|
||||
|
|
|
@ -23,9 +23,9 @@ import ghidra.app.util.bin.format.macho.MachHeader;
|
|||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.flatapi.FlatProgramAPI;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.ProgramModule;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -73,28 +73,10 @@ public class LinkEditDataCommand extends LoadCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address getDataAddress(MachHeader header, AddressSpace space) {
|
||||
if (dataoff != 0 && datasize != 0) {
|
||||
SegmentCommand segment = getContainingSegment(header, dataoff);
|
||||
if (segment != null) {
|
||||
return space
|
||||
.getAddress(segment.getVMaddress() + (dataoff - segment.getFileOffset()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, Address addr, String source,
|
||||
TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
if (addr == null || datasize == 0) {
|
||||
return;
|
||||
}
|
||||
String name = LoadCommandTypes.getLoadCommandName(getCommandType());
|
||||
if (source != null) {
|
||||
name += " - " + source;
|
||||
}
|
||||
program.getListing().setComment(addr, CodeUnit.PLATE_COMMENT, name);
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
markupPlateComment(program, fileOffsetToAddress(program, header, dataoff, datasize), source,
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -105,35 +105,71 @@ public abstract class LoadCommand implements StructConverter {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Address} of this load command's "data"
|
||||
*
|
||||
* @param header The Mach-O header
|
||||
* @param space The {@link AddressSpace}
|
||||
* @return The {@link Address} of this load command's "data", or null if it has no data
|
||||
*/
|
||||
public Address getDataAddress(MachHeader header, AddressSpace space) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks up this {@link LoadCommand} data with data structures and comments. Assumes the
|
||||
* program was imported as a Mach-O.
|
||||
*
|
||||
* @param program The {@link Program} to mark up
|
||||
* @param header The Mach-O header
|
||||
* @param addr The {@link Address} of the start of load command data (could be null if no data)
|
||||
* @param source A name that represents where the header came from (could be null)
|
||||
* @param monitor A cancellable task monitor
|
||||
* @param log The log
|
||||
* @throws CancelledException if the user cancelled the operation
|
||||
*/
|
||||
public void markup(Program program, MachHeader header, Address addr, String source,
|
||||
TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
// Default is no markup
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a plate comment at the given {@link Address} based on this {@link LoadCommand}'s
|
||||
* name
|
||||
*
|
||||
* @param program The {@link Program} to mark up
|
||||
* @param address The {@link Address} to put the comment at
|
||||
* @param source An optional string representing the source of the {@link LoadCommand}. Could
|
||||
* be empty or null.
|
||||
* @param additionalDescription An optional string representing a sub-description of this
|
||||
* {@link LoadCommand}. Could be empty or null.
|
||||
*/
|
||||
protected void markupPlateComment(Program program, Address address, String source,
|
||||
String additionalDescription) {
|
||||
if (address == null) {
|
||||
return;
|
||||
}
|
||||
String comment = LoadCommandTypes.getLoadCommandName(getCommandType());
|
||||
if (additionalDescription != null && !additionalDescription.isBlank()) {
|
||||
comment += " (" + additionalDescription + ")";
|
||||
}
|
||||
if (source != null && !source.isBlank()) {
|
||||
comment += " - " + source;
|
||||
}
|
||||
program.getListing().setComment(address, CodeUnit.PLATE_COMMENT, comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given Mach-O file offset to an {@link Address}
|
||||
*
|
||||
* @param program The {@link Program}
|
||||
* @param header The Mach-O header
|
||||
* @param fileOffset The file offset of the data (0 indicates no data)
|
||||
* @param size The size (actual size not important, but 0 will cause null to be returned)
|
||||
* @return The converted {@link Address}, or null if there is no corresponding {@link Address}
|
||||
*/
|
||||
protected Address fileOffsetToAddress(Program program, MachHeader header, int fileOffset,
|
||||
int size) {
|
||||
if (fileOffset != 0 && size != 0) {
|
||||
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
|
||||
SegmentCommand segment = getContainingSegment(header, fileOffset);
|
||||
if (segment != null) {
|
||||
return space.getAddress(
|
||||
segment.getVMaddress() + (fileOffset - segment.getFileOffset()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link SegmentCommand segment} that contains the give file offset
|
||||
*
|
||||
|
@ -142,7 +178,7 @@ public abstract class LoadCommand implements StructConverter {
|
|||
* @return The {@link SegmentCommand segment} that contains the give file offset, or null if
|
||||
* one was not found
|
||||
*/
|
||||
protected SegmentCommand getContainingSegment(MachHeader header, long fileOffset) {
|
||||
private SegmentCommand getContainingSegment(MachHeader header, long fileOffset) {
|
||||
for (SegmentCommand segment : header.getAllSegments()) {
|
||||
if (fileOffset >= segment.getFileOffset() &&
|
||||
fileOffset < segment.getFileOffset() + segment.getFileSize()) {
|
||||
|
|
|
@ -26,7 +26,6 @@ import ghidra.app.util.bin.format.macho.MachHeader;
|
|||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.flatapi.FlatProgramAPI;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
@ -171,38 +170,20 @@ public class SymbolTableCommand extends LoadCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Address getDataAddress(MachHeader header, AddressSpace space) {
|
||||
if (symoff != 0 && nsyms != 0) {
|
||||
SegmentCommand segment = getContainingSegment(header, symoff);
|
||||
if (segment != null) {
|
||||
return space
|
||||
.getAddress(segment.getVMaddress() + (symoff - segment.getFileOffset()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void markup(Program program, MachHeader header, String source, TaskMonitor monitor,
|
||||
MessageLog log) throws CancelledException {
|
||||
|
||||
@Override
|
||||
public void markup(Program program, MachHeader header, Address symbolTableAddr,
|
||||
String source, TaskMonitor monitor, MessageLog log) throws CancelledException {
|
||||
Address symbolTableAddr = fileOffsetToAddress(program, header, symoff, nsyms);
|
||||
if (symbolTableAddr == null) {
|
||||
return;
|
||||
}
|
||||
Address stringTableAddr = stroff != 0 ? symbolTableAddr.add(stroff - symoff) : null;
|
||||
Address stringTableAddr = fileOffsetToAddress(program, header, stroff, strsize);
|
||||
|
||||
markupPlateComment(program, symbolTableAddr, source, "symbols");
|
||||
markupPlateComment(program, stringTableAddr, source, "strings");
|
||||
|
||||
Listing listing = program.getListing();
|
||||
ReferenceManager referenceManager = program.getReferenceManager();
|
||||
String symbolsName = LoadCommandTypes.getLoadCommandName(getCommandType()) + " (symbols)";
|
||||
String stringsName = LoadCommandTypes.getLoadCommandName(getCommandType()) + " (strings)";
|
||||
if (source != null) {
|
||||
symbolsName += " - " + source;
|
||||
stringsName += " - " + source;
|
||||
}
|
||||
try {
|
||||
listing.setComment(symbolTableAddr, CodeUnit.PLATE_COMMENT, symbolsName);
|
||||
if (stringTableAddr != null) {
|
||||
listing.setComment(stringTableAddr, CodeUnit.PLATE_COMMENT, stringsName);
|
||||
}
|
||||
for (int i = 0; i < nsyms; i++) {
|
||||
NList nlist = symbols.get(i);
|
||||
DataType dt = nlist.toDataType();
|
||||
|
@ -222,6 +203,8 @@ public class SymbolTableCommand extends LoadCommand {
|
|||
|
||||
}
|
||||
catch (Exception e) {
|
||||
String symbolsName =
|
||||
LoadCommandTypes.getLoadCommandName(getCommandType()) + " (symbols)";
|
||||
log.appendMsg(SymbolTableCommand.class.getSimpleName(),
|
||||
"Failed to markup %s.".formatted(symbolsName));
|
||||
}
|
||||
|
|
|
@ -1258,10 +1258,7 @@ public class MachoProgramBuilder {
|
|||
*/
|
||||
protected void markupLoadCommandData(MachHeader header, String source) throws Exception {
|
||||
for (LoadCommand cmd : header.getLoadCommands()) {
|
||||
Address dataAddr = cmd.getDataAddress(header, space);
|
||||
if (dataAddr != null) {
|
||||
cmd.markup(program, header, dataAddr, source, monitor, log);
|
||||
}
|
||||
cmd.markup(program, header, source, monitor, log);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user