mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-03 00:44:52 +00:00
GP-3383 refactor struct mapping context classname
This commit is contained in:
parent
8766b0e9c7
commit
e98d0bbf37
|
@ -27,7 +27,7 @@ import ghidra.app.util.MemoryBlockUtils;
|
|||
import ghidra.app.util.bin.format.elf.info.ElfInfoItem.ItemWithAddress;
|
||||
import ghidra.app.util.bin.format.golang.*;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoModuledata;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiContext;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -72,9 +72,9 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
|||
throws CancelledException {
|
||||
monitor.setMessage("Golang symbol analyzer");
|
||||
|
||||
try (GoRttiContext programContext = GoRttiContext.getContextFor(program, log)) {
|
||||
try (GoRttiMapper programContext = GoRttiMapper.getMapperFor(program, log)) {
|
||||
if (programContext == null) {
|
||||
Msg.error(this, "Golang analyzer error: unable to get GoRttiContext");
|
||||
Msg.error(this, "Golang analyzer error: unable to get GoRttiMapper");
|
||||
return false;
|
||||
}
|
||||
programContext.discoverGoTypes(monitor);
|
||||
|
@ -121,7 +121,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
|||
analyzerOptions.createBootstrapDatatypeArchive);
|
||||
}
|
||||
|
||||
private void markupWellknownSymbols(GoRttiContext programContext) throws IOException {
|
||||
private void markupWellknownSymbols(GoRttiMapper programContext) throws IOException {
|
||||
Program program = programContext.getProgram();
|
||||
|
||||
Symbol g0 = SymbolUtilities.getUniqueSymbol(program, "runtime.g0");
|
||||
|
@ -225,7 +225,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
|||
return newMB.getStart();
|
||||
}
|
||||
|
||||
private void setupProgramContext(GoRttiContext programContext) throws IOException {
|
||||
private void setupProgramContext(GoRttiMapper programContext) throws IOException {
|
||||
Program program = programContext.getProgram();
|
||||
GoRegisterInfo goRegInfo = GoRegisterInfoManager.getInstance()
|
||||
.getRegisterInfoForLang(program.getLanguage(),
|
||||
|
@ -299,12 +299,12 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
private void createBootstrapGDT(GoRttiContext programContext, Program program,
|
||||
private void createBootstrapGDT(GoRttiMapper programContext, Program program,
|
||||
TaskMonitor monitor) throws IOException {
|
||||
GoVer goVer = programContext.getGolangVersion();
|
||||
String osName = GoRttiContext.getGolangOSString(program);
|
||||
String osName = GoRttiMapper.getGolangOSString(program);
|
||||
String gdtFilename =
|
||||
GoRttiContext.getGDTFilename(goVer, programContext.getPtrSize(), osName);
|
||||
GoRttiMapper.getGDTFilename(goVer, programContext.getPtrSize(), osName);
|
||||
gdtFilename =
|
||||
gdtFilename.replace(".gdt", "_%d.gdt".formatted(System.currentTimeMillis()));
|
||||
File gdt = new File(System.getProperty("user.home"), gdtFilename);
|
||||
|
|
|
@ -85,8 +85,7 @@ public class ElfNote implements ElfInfoItem {
|
|||
* @param program {@link Program}
|
||||
* @param sectionName name of the note section
|
||||
* @param readerFunc {@link NoteReaderFunc} that converts a generic note instance into a
|
||||
* specialized note.<br>
|
||||
* Example: <code>(note, programContext) -> new MyNote(....)</code>
|
||||
* specialized note.
|
||||
* @return new Note instance, or null if not present or error reading
|
||||
*/
|
||||
protected static <T extends ElfNote> T readFromProgramHelper(Program program,
|
||||
|
|
|
@ -33,7 +33,7 @@ import ghidra.util.exception.InvalidInputException;
|
|||
@StructureMapping(structureName = "runtime._func")
|
||||
public class GoFuncData implements StructureMarkup<GoFuncData> {
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoFuncData> context;
|
||||
|
|
|
@ -23,7 +23,7 @@ import ghidra.program.model.address.Address;
|
|||
@StructureMapping(structureName = "runtime.functab")
|
||||
public class GoFunctabEntry {
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoFunctabEntry> context;
|
||||
|
|
|
@ -22,7 +22,7 @@ import ghidra.app.util.bin.format.golang.structmapping.*;
|
|||
@StructureMapping(structureName = "runtime.iface")
|
||||
public class GoIface {
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoIface> context;
|
||||
|
|
|
@ -31,7 +31,7 @@ import ghidra.program.model.data.DataType;
|
|||
@StructureMapping(structureName = "runtime.itab")
|
||||
public class GoItab implements StructureMarkup<GoItab> {
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoItab> context;
|
||||
|
|
|
@ -43,7 +43,7 @@ import ghidra.util.task.TaskMonitor;
|
|||
public class GoModuledata implements StructureMarkup<GoModuledata> {
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoModuledata> structureContext;
|
||||
|
@ -156,7 +156,7 @@ public class GoModuledata implements StructureMarkup<GoModuledata> {
|
|||
|
||||
itablinks.markupArray("moduledata.itablinks", GoItab.class, true);
|
||||
|
||||
//cutab.markupArray("moduledata.cutab", programContext.getUint32DT(), false);
|
||||
//cutab.markupArray("moduledata.cutab", dataTypeMapper.getUint32DT(), false);
|
||||
markupStringTable(funcnametab.getArrayAddress(), funcnametab.getLen());
|
||||
markupStringTable(filetab.getArrayAddress(), filetab.getLen());
|
||||
|
||||
|
@ -233,11 +233,11 @@ public class GoModuledata implements StructureMarkup<GoModuledata> {
|
|||
/**
|
||||
* Returns an easily found first GoModuledata instance.
|
||||
*
|
||||
* @param context already initialized {@link GoRttiContext}
|
||||
* @param context already initialized {@link GoRttiMapper}
|
||||
* @return new GoModuledata instance, or null if not found
|
||||
* @throws IOException
|
||||
*/
|
||||
/* package */ static GoModuledata getFirstModuledata(GoRttiContext context)
|
||||
/* package */ static GoModuledata getFirstModuledata(GoRttiMapper context)
|
||||
throws IOException {
|
||||
Program program = context.getProgram();
|
||||
Symbol firstModuleDataSymbol =
|
||||
|
@ -251,7 +251,7 @@ public class GoModuledata implements StructureMarkup<GoModuledata> {
|
|||
/**
|
||||
* Searches memory for a likely GoModuledata
|
||||
*
|
||||
* @param context already initialized {@link GoRttiContext}
|
||||
* @param context already initialized {@link GoRttiMapper}
|
||||
* @param pclntabAddress address of an already found {@link GoPcHeader}
|
||||
* @param pclntab the {@link GoPcHeader}
|
||||
* @param range memory range to search. Will be different for different types of binaries
|
||||
|
@ -259,7 +259,7 @@ public class GoModuledata implements StructureMarkup<GoModuledata> {
|
|||
* @return new GoModuledata instance, or null if not found
|
||||
* @throws IOException
|
||||
*/
|
||||
/* package */ static GoModuledata findFirstModule(GoRttiContext context,
|
||||
/* package */ static GoModuledata findFirstModule(GoRttiMapper context,
|
||||
Address pclntabAddress, GoPcHeader pclntab, AddressRange range, TaskMonitor monitor)
|
||||
throws IOException {
|
||||
if (range == null) {
|
||||
|
|
|
@ -73,7 +73,7 @@ public class GoName implements StructureReader<GoName>, StructureMarkup<GoName>
|
|||
private StructureContext<GoName> context;
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@FieldOutput(dataTypeName = "byte")
|
||||
@EOLComment("flagsSet")
|
||||
|
|
|
@ -26,7 +26,8 @@ import ghidra.program.model.lang.Endian;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.SymbolUtilities;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
|
@ -84,13 +85,13 @@ public class GoPcHeader {
|
|||
* Searches (possibly slowly) for a pclntab structure in the specified memory range, which
|
||||
* is typically necessary in stripped PE binaries.
|
||||
*
|
||||
* @param programContext {@link GoRttiContext}
|
||||
* @param programContext {@link GoRttiMapper}
|
||||
* @param range memory range to search (typically .rdata or .noptrdata sections)
|
||||
* @param monitor {@link TaskMonitor} that will let the user cancel
|
||||
* @return {@link Address} of the found pclntab structure, or null if not found
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Address findPclntabAddress(GoRttiContext programContext, AddressRange range,
|
||||
public static Address findPclntabAddress(GoRttiMapper programContext, AddressRange range,
|
||||
TaskMonitor monitor) throws IOException {
|
||||
if (range == null) {
|
||||
return null;
|
||||
|
@ -141,7 +142,7 @@ public class GoPcHeader {
|
|||
}
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoPcHeader> context;
|
||||
|
|
|
@ -26,7 +26,7 @@ import ghidra.app.util.bin.BinaryReader;
|
|||
import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram;
|
||||
import ghidra.app.util.bin.format.golang.*;
|
||||
import ghidra.app.util.bin.format.golang.rtti.types.*;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.ProgramContext;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.DataTypeMapper;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.StructureMapping;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.app.util.opinion.ElfLoader;
|
||||
|
@ -45,15 +45,15 @@ import ghidra.util.task.TaskMonitor;
|
|||
import ghidra.util.task.UnknownProgressWrappingTaskMonitor;
|
||||
|
||||
/**
|
||||
* {@link ProgramContext} for golang binaries.
|
||||
* {@link DataTypeMapper} for golang binaries.
|
||||
* <p>
|
||||
* When bootstrapping golang binaries, the following steps are used:
|
||||
* <ul>
|
||||
* <li>Find the GoBuildInfo struct. This struct is the easiest to locate, even when the binary
|
||||
* is stripped. This gives us the go pointerSize (probably same as ghidra pointer size) and the
|
||||
* goVersion. This struct does not rely on StructureMapping, allowing its use before a
|
||||
* ProgramContext is created.
|
||||
* <li>Create ProgramContext
|
||||
* DataTypeMapper is created.
|
||||
* <li>Create DataTypeMapper
|
||||
* <li>Find the runtime.firstmoduledata structure.
|
||||
* <ul>
|
||||
* <li>If there are symbols, just use the symbol or named memory block.
|
||||
|
@ -70,18 +70,18 @@ import ghidra.util.task.UnknownProgressWrappingTaskMonitor;
|
|||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
public class GoRttiContext extends ProgramContext {
|
||||
public class GoRttiMapper extends DataTypeMapper {
|
||||
|
||||
/**
|
||||
* Returns a new {@link GoRttiContext} for the specified program, or null if the binary
|
||||
* Returns a new {@link GoRttiMapper} for the specified program, or null if the binary
|
||||
* is not a supported golang binary.
|
||||
*
|
||||
* @param program {@link Program}
|
||||
* @param log
|
||||
* @return new {@link GoRttiContext}, or null if not a golang binary
|
||||
* @return new {@link GoRttiMapper}, or null if not a golang binary
|
||||
* @throws IOException
|
||||
*/
|
||||
public static GoRttiContext getContextFor(Program program, MessageLog log) throws IOException {
|
||||
public static GoRttiMapper getMapperFor(Program program, MessageLog log) throws IOException {
|
||||
GoBuildInfo buildInfo = GoBuildInfo.fromProgram(program);
|
||||
GoVer goVer;
|
||||
if (buildInfo == null || (goVer = buildInfo.getVerEnum()) == GoVer.UNKNOWN) {
|
||||
|
@ -90,11 +90,11 @@ public class GoRttiContext extends ProgramContext {
|
|||
ResourceFile gdtFile =
|
||||
findGolangBootstrapGDT(goVer, buildInfo.getPointerSize(), getGolangOSString(program));
|
||||
if (gdtFile == null) {
|
||||
Msg.error(GoRttiContext.class, "Missing golang gdt archive for " + goVer);
|
||||
Msg.error(GoRttiMapper.class, "Missing golang gdt archive for " + goVer);
|
||||
}
|
||||
|
||||
try {
|
||||
return new GoRttiContext(program, buildInfo.getPointerSize(), buildInfo.getEndian(),
|
||||
return new GoRttiMapper(program, buildInfo.getPointerSize(), buildInfo.getEndian(),
|
||||
buildInfo.getVerEnum(), gdtFile);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
|
@ -185,7 +185,7 @@ public class GoRttiContext extends ProgramContext {
|
|||
private GoType mapGoType;
|
||||
private GoType chanGoType;
|
||||
|
||||
public GoRttiContext(Program program, int ptrSize, Endian endian, GoVer goVersion,
|
||||
public GoRttiMapper(Program program, int ptrSize, Endian endian, GoVer goVersion,
|
||||
ResourceFile archiveGDT) throws IOException {
|
||||
super(program, archiveGDT);
|
||||
|
|
@ -32,7 +32,7 @@ import ghidra.util.Msg;
|
|||
public class GoSlice {
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoSlice> context;
|
||||
|
@ -53,7 +53,7 @@ public class GoSlice {
|
|||
this.cap = cap;
|
||||
}
|
||||
|
||||
public GoSlice(long array, long len, long cap, GoRttiContext programContext) {
|
||||
public GoSlice(long array, long len, long cap, GoRttiMapper programContext) {
|
||||
this(array, len, cap);
|
||||
this.programContext = programContext;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class GoString {
|
|||
private long len;
|
||||
|
||||
public Address getStringAddr() {
|
||||
return context.getProgramContext().getDataAddress(str);
|
||||
return context.getDataTypeMapper().getDataAddress(str);
|
||||
}
|
||||
|
||||
public long getLength() {
|
||||
|
@ -44,7 +44,7 @@ public class GoString {
|
|||
}
|
||||
|
||||
public String getStringValue() throws IOException {
|
||||
BinaryReader reader = context.getProgramContext().getReader(str);
|
||||
BinaryReader reader = context.getDataTypeMapper().getReader(str);
|
||||
return reader.readNextUtf8String((int) len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public class GoVarlenString implements StructureReader<GoVarlenString> {
|
|||
|
||||
public DataType getValueDataType() {
|
||||
return new ArrayDataType(CharDataType.dataType, bytes.length, -1,
|
||||
context.getProgramContext().getDTM());
|
||||
context.getDataTypeMapper().getDTM());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Set;
|
|||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoName;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiContext;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||
|
||||
/**
|
||||
|
@ -43,7 +43,7 @@ public class GoBaseType {
|
|||
private StructureContext<GoBaseType> context;
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@FieldMapping(signedness = Signedness.Unsigned)
|
||||
private long size;
|
||||
|
|
|
@ -18,14 +18,14 @@ package ghidra.app.util.bin.format.golang.rtti.types;
|
|||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoName;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiContext;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||
|
||||
@StructureMapping(structureName = "runtime.imethod")
|
||||
public class GoIMethod implements StructureMarkup<GoIMethod> {
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoIMethod> context;
|
||||
|
|
|
@ -18,14 +18,14 @@ package ghidra.app.util.bin.format.golang.rtti.types;
|
|||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoName;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiContext;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
@StructureMapping(structureName = "runtime.method")
|
||||
public class GoMethod implements StructureMarkup<GoMethod> {
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoMethod> context;
|
||||
|
|
|
@ -35,7 +35,7 @@ import ghidra.util.Msg;
|
|||
public class GoPlainType extends GoType implements StructureReader<GoType> {
|
||||
@Override
|
||||
public void readStructure() throws IOException {
|
||||
this.typ = context.getProgramContext().readStructure(GoBaseType.class, context.getReader());
|
||||
this.typ = context.getDataTypeMapper().readStructure(GoBaseType.class, context.getReader());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,14 +18,14 @@ package ghidra.app.util.bin.format.golang.rtti.types;
|
|||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoName;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiContext;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||
|
||||
@StructureMapping(structureName = "runtime.structfield")
|
||||
public class GoStructField {
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoStructField> context;
|
||||
|
@ -45,7 +45,7 @@ public class GoStructField {
|
|||
@Markup
|
||||
public GoName getName() throws IOException {
|
||||
return name != 0
|
||||
? context.getProgramContext().readStructure(GoName.class, name)
|
||||
? context.getDataTypeMapper().readStructure(GoName.class, name)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Set;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiContext;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
|
||||
import ghidra.app.util.bin.format.golang.rtti.GoSlice;
|
||||
import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||
import ghidra.program.model.data.*;
|
||||
|
@ -38,7 +38,7 @@ public abstract class GoType implements StructureMarkup<GoType> {
|
|||
Map.entry(GoKind.Map, GoMapType.class),
|
||||
Map.entry(GoKind.Interface, GoInterfaceType.class));
|
||||
|
||||
public static Class<? extends GoType> getSpecializedTypeClass(GoRttiContext programContext,
|
||||
public static Class<? extends GoType> getSpecializedTypeClass(GoRttiMapper programContext,
|
||||
long offset) throws IOException {
|
||||
GoTypeDetector typeDetector = programContext.readStructure(GoTypeDetector.class, offset);
|
||||
Class<? extends GoType> result = specializedTypeClasses.get(typeDetector.getKind());
|
||||
|
@ -49,7 +49,7 @@ public abstract class GoType implements StructureMarkup<GoType> {
|
|||
}
|
||||
|
||||
@ContextField
|
||||
protected GoRttiContext programContext;
|
||||
protected GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
protected StructureContext<GoType> context;
|
||||
|
|
|
@ -27,7 +27,7 @@ import ghidra.util.Msg;
|
|||
public class GoUncommonType {
|
||||
|
||||
@ContextField
|
||||
private GoRttiContext programContext;
|
||||
private GoRttiMapper programContext;
|
||||
|
||||
@ContextField
|
||||
private StructureContext<GoUncommonType> context;
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.lang.annotation.Target;
|
|||
|
||||
/**
|
||||
* Indicates that the tagged field should be initialized with the value of the appropriate
|
||||
* context object, either {@link ProgramContext} or {@link StructureContext}.
|
||||
* context object, either {@link DataTypeMapper} or {@link StructureContext}.
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(FIELD)
|
||||
|
|
|
@ -38,19 +38,19 @@ import ghidra.util.task.TaskMonitor;
|
|||
* Information about {@link StructureMapping} classes and their metadata, as well as
|
||||
* accumulated information about structure instances that have been deserialized.
|
||||
* <p>
|
||||
* To use the full might and majesty of StructureMapping(tm), a ProgramContext must be created. It
|
||||
* To use the full might and majesty of StructureMapping(tm), a DataTypeMapper must be created. It
|
||||
* must be able to {@link #addArchiveSearchCategoryPath(CategoryPath...) find}
|
||||
* ({@link #addProgramSearchCategoryPath(CategoryPath...) more find}) the Ghidra structure data
|
||||
* types being used, and it must {@link #registerStructure(Class) know} about all classes that are
|
||||
* going to participate during deserialization and markup.
|
||||
* <p>
|
||||
* Structure mapped classes can receive a reference to the specific ProgramContext type that
|
||||
* created them by declaring a {@code ProgramContext} field, and tagging it with
|
||||
* Structure mapped classes can receive a reference to the specific DataTypeMapper type that
|
||||
* created them by declaring a {@code DataTypeMapper} field, and tagging it with
|
||||
* the @{@link ContextField} annotation:
|
||||
*
|
||||
* <pre>
|
||||
* class MyProgramContext extends ProgramContext {
|
||||
* public MyProgramContext() {
|
||||
* class MyDataTypeMapper extends DataTypeMapper {
|
||||
* public MyDataTypeMapper() {
|
||||
* ...
|
||||
* registerStructure(MyDataType.class);
|
||||
* }
|
||||
|
@ -61,7 +61,7 @@ import ghidra.util.task.TaskMonitor;
|
|||
* class MyDataType {
|
||||
*
|
||||
* @ContextField
|
||||
* private MyProgramContext myProgramContext;
|
||||
* private MyDataTypeMapper myDataTypeMapper;
|
||||
*
|
||||
* @ContextField
|
||||
* private StructureContext<MyDataType> context;
|
||||
|
@ -70,13 +70,13 @@ import ghidra.util.task.TaskMonitor;
|
|||
* private long someField;
|
||||
*
|
||||
* void bar() {
|
||||
* context.getProgramContext().getProgram(); // can only access methods defined on base ProgramContext type
|
||||
* myProgramContext.foo(); // same context as previous line, but typed correctly
|
||||
* context.getDataTypeMapper().getProgram(); // can only access methods defined on base DataTypeMapper type
|
||||
* myDataTypeMapper.foo(); // same context as previous line, but typed correctly
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class ProgramContext implements AutoCloseable {
|
||||
public class DataTypeMapper implements AutoCloseable {
|
||||
protected Program program;
|
||||
protected DataTypeManager programDTM;
|
||||
protected DataTypeManager archiveDTM;
|
||||
|
@ -92,7 +92,7 @@ public class ProgramContext implements AutoCloseable {
|
|||
* @param archiveGDT
|
||||
* @throws IOException
|
||||
*/
|
||||
protected ProgramContext(Program program, ResourceFile archiveGDT) throws IOException {
|
||||
protected DataTypeMapper(Program program, ResourceFile archiveGDT) throws IOException {
|
||||
this.program = program;
|
||||
this.programDTM = program.getDataTypeManager();
|
||||
this.archiveDTM = archiveGDT != null
|
||||
|
@ -126,12 +126,12 @@ public class ProgramContext implements AutoCloseable {
|
|||
return DataConverter.getInstance(program.getMemory().isBigEndian());
|
||||
}
|
||||
|
||||
public ProgramContext addProgramSearchCategoryPath(CategoryPath... paths) {
|
||||
public DataTypeMapper addProgramSearchCategoryPath(CategoryPath... paths) {
|
||||
programSearchCPs.addAll(Arrays.asList(paths));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProgramContext addArchiveSearchCategoryPath(CategoryPath... paths) {
|
||||
public DataTypeMapper addArchiveSearchCategoryPath(CategoryPath... paths) {
|
||||
archiveSearchCPs.addAll(Arrays.asList(paths));
|
||||
return this;
|
||||
}
|
||||
|
@ -401,6 +401,6 @@ public class ProgramContext implements AutoCloseable {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProgramContext { program: %s}".formatted(program.getName());
|
||||
return "DataTypeMapper { program: %s}".formatted(program.getName());
|
||||
}
|
||||
}
|
|
@ -38,8 +38,8 @@ public record FieldContext<T> (
|
|||
return structureContext.getStructureInstance();
|
||||
}
|
||||
|
||||
public ProgramContext getProgramContext() {
|
||||
return structureContext().getProgramContext();
|
||||
public DataTypeMapper getDataTypeMapper() {
|
||||
return structureContext().getDataTypeMapper();
|
||||
}
|
||||
|
||||
public void appendComment(int commentType, String prefix, String comment, String sep)
|
||||
|
|
|
@ -251,7 +251,7 @@ public class FieldMappingInfo<T> {
|
|||
|
||||
private Object readStructureMappedTypeFunc(FieldContext<T> context) throws IOException {
|
||||
return context.structureContext()
|
||||
.getProgramContext()
|
||||
.getDataTypeMapper()
|
||||
.readStructure(field.getType(), context.reader());
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ public class FieldMappingInfo<T> {
|
|||
// }
|
||||
|
||||
private void markupNestedStructure(FieldContext<T> fieldContext) throws IOException {
|
||||
fieldContext.getProgramContext().markup(fieldContext.getValue(Object.class), true);
|
||||
fieldContext.getDataTypeMapper().markup(fieldContext.getValue(Object.class), true);
|
||||
}
|
||||
|
||||
private FieldMarkupFunction<T> makeMarkupReferenceFunc(String getterName) {
|
||||
|
@ -317,7 +317,7 @@ public class FieldMappingInfo<T> {
|
|||
if (getterValue != null) {
|
||||
Address addr = getterValue instanceof Address getterAddr
|
||||
? getterAddr
|
||||
: fieldContext.getProgramContext().getExistingStructureAddress(getterValue);
|
||||
: fieldContext.getDataTypeMapper().getExistingStructureAddress(getterValue);
|
||||
if (addr != null) {
|
||||
fieldContext.addReference(addr);
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ public class FieldOutputInfo<T> {
|
|||
|
||||
private void dataTypeNameOutputFunc(StructureContext<T> context, Structure structure,
|
||||
FieldOutputInfo<T> foi) throws IOException {
|
||||
DataType dt = context.getProgramContext().getType(dataTypeName, DataType.class);
|
||||
DataType dt = context.getDataTypeMapper().getType(dataTypeName, DataType.class);
|
||||
if (dt == null) {
|
||||
throw new IOException(
|
||||
"Missing data type %s for field %s".formatted(dataTypeName, fmi.getFieldName()));
|
||||
|
@ -175,7 +175,7 @@ public class FieldOutputInfo<T> {
|
|||
private void primitiveOutputFunc(StructureContext<T> context, Structure structure,
|
||||
FieldOutputInfo<T> foi) throws IOException {
|
||||
DataType dt = ReflectionHelper.getPrimitiveOutputDataType(fmi.getField().getType(),
|
||||
fmi.getLength(), fmi.getSignedness(), context.getProgramContext());
|
||||
fmi.getLength(), fmi.getSignedness(), context.getDataTypeMapper());
|
||||
preAddField(structure);
|
||||
structure.add(dt, fmi.getFieldName(), null);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ public class FieldOutputInfo<T> {
|
|||
// only outputs array of primitive value
|
||||
Object fieldValue = foi.getValue(context.getStructureInstance(), Object.class);
|
||||
DataType dt = ReflectionHelper.getArrayOutputDataType(fieldValue, fmi.getField().getType(),
|
||||
fmi.getLength(), fmi.getSignedness(), context.getProgramContext());
|
||||
fmi.getLength(), fmi.getSignedness(), context.getDataTypeMapper());
|
||||
preAddField(structure);
|
||||
structure.add(dt, fmi.getFieldName(), null);
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ public class FieldOutputInfo<T> {
|
|||
}
|
||||
|
||||
StructureContext<?> nestedStructContext =
|
||||
context.getProgramContext().getExistingStructureContext(nestedStruct);
|
||||
context.getDataTypeMapper().getExistingStructureContext(nestedStruct);
|
||||
if (nestedStructContext == null) {
|
||||
throw new IOException(
|
||||
"Missing StructureContext for " + nestedStruct.getClass().getSimpleName());
|
||||
|
|
|
@ -95,24 +95,24 @@ public class ReflectionHelper {
|
|||
* @param fieldType
|
||||
* @param length
|
||||
* @param signedness
|
||||
* @param programContext
|
||||
* @param dataTypeMapper
|
||||
* @return
|
||||
*/
|
||||
public static DataType getArrayOutputDataType(Object array_value, Class<?> fieldType, int length,
|
||||
Signedness signedness, ProgramContext programContext) {
|
||||
Signedness signedness, DataTypeMapper dataTypeMapper) {
|
||||
int arrayLen = array_value != null ? Array.getLength(array_value) : 0;
|
||||
Class<?> elementType = fieldType.getComponentType();
|
||||
DataType elementDT =
|
||||
getPrimitiveOutputDataType(elementType, length, signedness, programContext);
|
||||
getPrimitiveOutputDataType(elementType, length, signedness, dataTypeMapper);
|
||||
|
||||
return new ArrayDataType(elementDT, arrayLen, -1, programContext.getDTM());
|
||||
return new ArrayDataType(elementDT, arrayLen, -1, dataTypeMapper.getDTM());
|
||||
}
|
||||
|
||||
public static DataType getPrimitiveOutputDataType(Class<?> fieldType, int length,
|
||||
Signedness signedness, ProgramContext programContext) {
|
||||
Signedness signedness, DataTypeMapper dataTypeMapper) {
|
||||
|
||||
boolean isChar = (fieldType == Character.class || fieldType == Character.TYPE);
|
||||
DataTypeManager dtm = programContext.getDTM();
|
||||
DataTypeManager dtm = dataTypeMapper.getDTM();
|
||||
|
||||
if (length == -1) {
|
||||
length = getPrimitiveSizeof(fieldType);
|
||||
|
@ -125,7 +125,7 @@ public class ReflectionHelper {
|
|||
if (isChar && length == 1) {
|
||||
defaultDtName = "char";
|
||||
}
|
||||
DataType dt = programContext.getType(defaultDtName, DataType.class);
|
||||
DataType dt = dataTypeMapper.getType(defaultDtName, DataType.class);
|
||||
if (dt == null && isChar) {
|
||||
dt = switch (length) {
|
||||
case 1 -> CharDataType.dataType;
|
||||
|
|
|
@ -46,16 +46,16 @@ import ghidra.program.model.listing.Program;
|
|||
* @param <T> a java class that has been tagged with a {@link StructureMapping} annotation.
|
||||
*/
|
||||
public class StructureContext<T> {
|
||||
protected final ProgramContext programContext;
|
||||
protected final DataTypeMapper dataTypeMapper;
|
||||
protected final StructureMappingInfo<T> mappingInfo;
|
||||
protected final BinaryReader reader;
|
||||
protected final long structureStart;
|
||||
protected T structureInstance;
|
||||
protected Structure structureDataType;
|
||||
|
||||
public StructureContext(ProgramContext programContext, StructureMappingInfo<T> mappingInfo,
|
||||
public StructureContext(DataTypeMapper dataTypeMapper, StructureMappingInfo<T> mappingInfo,
|
||||
BinaryReader reader) {
|
||||
this.programContext = programContext;
|
||||
this.dataTypeMapper = dataTypeMapper;
|
||||
this.mappingInfo = mappingInfo;
|
||||
this.reader = reader;
|
||||
this.structureStart = reader.getPointerIndex();
|
||||
|
@ -86,19 +86,19 @@ public class StructureContext<T> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the root {@link ProgramContext}, as a plain ProgramContext type. If
|
||||
* a more specific ProgramContext type is needed, either type-cast this value, or use
|
||||
* Returns a reference to the root {@link DataTypeMapper}, as a plain DataTypeMapper type. If
|
||||
* a more specific DataTypeMapper type is needed, either type-cast this value, or use
|
||||
* a {@link ContextField} tag on a field in your class that specifies the correct
|
||||
* ProgramContext type.
|
||||
* DataTypeMapper type.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ProgramContext getProgramContext() {
|
||||
return programContext;
|
||||
public DataTypeMapper getDataTypeMapper() {
|
||||
return dataTypeMapper;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return programContext.program;
|
||||
return dataTypeMapper.program;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,7 +107,7 @@ public class StructureContext<T> {
|
|||
* @return {@link Address}
|
||||
*/
|
||||
public Address getStructureAddress() {
|
||||
return programContext.getDataAddress(structureStart);
|
||||
return dataTypeMapper.getDataAddress(structureStart);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,7 +198,7 @@ public class StructureContext<T> {
|
|||
*/
|
||||
public void appendComment(int commentType, String prefix, String comment, String sep)
|
||||
throws IOException {
|
||||
DWARFUtil.appendComment(programContext.getProgram(), getStructureAddress(), commentType,
|
||||
DWARFUtil.appendComment(dataTypeMapper.getProgram(), getStructureAddress(), commentType,
|
||||
prefix, comment, sep);
|
||||
}
|
||||
|
||||
|
@ -219,14 +219,14 @@ public class StructureContext<T> {
|
|||
*/
|
||||
public void markupStructure(boolean nested) throws IOException {
|
||||
Address addr = getStructureAddress();
|
||||
if (!nested && !programContext.markedupStructs.add(addr)) {
|
||||
if (!nested && !dataTypeMapper.markedupStructs.add(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nested) {
|
||||
try {
|
||||
Structure structDT = getStructureDataType();
|
||||
programContext.markupAddress(addr, structDT);
|
||||
dataTypeMapper.markupAddress(addr, structDT);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IOException("Markup failed for structure %s at %s"
|
||||
|
@ -237,7 +237,7 @@ public class StructureContext<T> {
|
|||
if (structureInstance instanceof StructureMarkup<?> sm) {
|
||||
String structureLabel = sm.getStructureLabel();
|
||||
if (structureLabel != null) {
|
||||
programContext.labelAddress(addr, structureLabel);
|
||||
dataTypeMapper.labelAddress(addr, structureLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ public class StructureContext<T> {
|
|||
}
|
||||
if (structureInstance instanceof StructureMarkup<?> sm) {
|
||||
for (Object externalInstance : sm.getExternalInstancesToMarkup()) {
|
||||
programContext.markup(externalInstance, false);
|
||||
dataTypeMapper.markup(externalInstance, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import java.lang.annotation.*;
|
|||
* In either case, various annotations on fields and methods will control how this structure
|
||||
* will be marked up in the Ghidra program.
|
||||
* <p>
|
||||
* The tagged class must be {@link ProgramContext#registerStructure(Class) registered} with
|
||||
* The tagged class must be {@link DataTypeMapper#registerStructure(Class) registered} with
|
||||
* the program context to enable the suite of structure mapped classes to work together when
|
||||
* applied to a Ghidra binary.
|
||||
* <p>
|
||||
|
@ -44,8 +44,8 @@ import java.lang.annotation.*;
|
|||
* variable length fields found in the structure.
|
||||
* <p>
|
||||
* Structure mapped classes must have a {@link StructureContext} member variable that is tagged
|
||||
* with the {@link ContextField} annotation, and probably should have a {@link ProgramContext}
|
||||
* member variable (that corresponds to a more specific type of ProgramContext) that is also
|
||||
* with the {@link ContextField} annotation, and probably should have a {@link DataTypeMapper}
|
||||
* member variable (that corresponds to a more specific type of DataTypeMapper) that is also
|
||||
* tagged with the ContextField annotation.
|
||||
*
|
||||
*/
|
||||
|
@ -54,11 +54,11 @@ import java.lang.annotation.*;
|
|||
public @interface StructureMapping {
|
||||
/**
|
||||
* Specifies the name of a Ghidra structure that the tagged class represents. For fixed
|
||||
* length structures, the {@link ProgramContext} will search for this Ghidra data type
|
||||
* length structures, the {@link DataTypeMapper} will search for this Ghidra data type
|
||||
* in it's configured
|
||||
* {@link ProgramContext#addArchiveSearchCategoryPath(ghidra.program.model.data.CategoryPath...) archive}
|
||||
* {@link DataTypeMapper#addArchiveSearchCategoryPath(ghidra.program.model.data.CategoryPath...) archive}
|
||||
* and
|
||||
* {@link ProgramContext#addProgramSearchCategoryPath(ghidra.program.model.data.CategoryPath...) program}
|
||||
* {@link DataTypeMapper#addProgramSearchCategoryPath(ghidra.program.model.data.CategoryPath...) program}
|
||||
* search paths.
|
||||
*
|
||||
* @return
|
||||
|
|
|
@ -86,7 +86,7 @@ public class StructureMappingInfo<T> {
|
|||
markupFuncs.add(context -> {
|
||||
T obj = context.getStructureInstance();
|
||||
Object val = ReflectionHelper.callGetter(markupGetterMethod, obj);
|
||||
context.getProgramContext().markup(val, false);
|
||||
context.getDataTypeMapper().markup(val, false);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -158,10 +158,10 @@ public class StructureMappingInfo<T> {
|
|||
// used to create a structure that has variable length fields
|
||||
|
||||
Structure newStruct = new StructureDataType(
|
||||
context.getProgramContext().getDefaultVariableLengthStructCategoryPath(),
|
||||
context.getDataTypeMapper().getDefaultVariableLengthStructCategoryPath(),
|
||||
structureName,
|
||||
0,
|
||||
context.getProgramContext().getDTM());
|
||||
context.getDataTypeMapper().getDTM());
|
||||
|
||||
// TODO: set struct packing?
|
||||
|
||||
|
@ -200,14 +200,14 @@ public class StructureMappingInfo<T> {
|
|||
* @throws IOException
|
||||
*/
|
||||
public void assignContextFieldValues(StructureContext<T> context) throws IOException {
|
||||
Class<?> programContextType = context.getProgramContext().getClass();
|
||||
Class<?> dataTypeMapperType = context.getDataTypeMapper().getClass();
|
||||
Class<?> structureContextType = context.getClass();
|
||||
T obj = context.getStructureInstance();
|
||||
|
||||
for (Field f : contextFields) {
|
||||
Class<?> fieldType = f.getType();
|
||||
if (fieldType.isAssignableFrom(programContextType)) {
|
||||
ReflectionHelper.assignField(f, obj, context.getProgramContext());
|
||||
if (fieldType.isAssignableFrom(dataTypeMapperType)) {
|
||||
ReflectionHelper.assignField(f, obj, context.getDataTypeMapper());
|
||||
}
|
||||
else if (fieldType.isAssignableFrom(structureContextType)) {
|
||||
ReflectionHelper.assignField(f, obj, context);
|
||||
|
|
Loading…
Reference in a new issue