mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/Ghidra_12.0'
This commit is contained in:
commit
7231c8b1e8
18 changed files with 136 additions and 511 deletions
|
@ -134,8 +134,8 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
|
||||||
|
|
||||||
// Truncate, then check that against existing code units.
|
// Truncate, then check that against existing code units.
|
||||||
long endSnap = computeTruncatedMax(lifespan, null, createdRange);
|
long endSnap = computeTruncatedMax(lifespan, null, createdRange);
|
||||||
TraceAddressSnapRange tasr = new ImmutableTraceAddressSnapRange(createdRange,
|
TraceAddressSnapRange tasr =
|
||||||
Lifespan.span(startSnap, endSnap));
|
new ImmutableTraceAddressSnapRange(createdRange, Lifespan.span(startSnap, endSnap));
|
||||||
if (!space.undefinedData.coversRange(tasr)) {
|
if (!space.undefinedData.coversRange(tasr)) {
|
||||||
// TODO: Figure out the conflicting unit?
|
// TODO: Figure out the conflicting unit?
|
||||||
throw new CodeUnitInsertionException("Code units cannot overlap");
|
throw new CodeUnitInsertionException("Code units cannot overlap");
|
||||||
|
@ -170,26 +170,4 @@ public class DBTraceDefinedDataView extends AbstractBaseDBTraceDefinedUnitsView<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void unitRemoved(DBTraceData unit) {
|
|
||||||
super.unitRemoved(unit);
|
|
||||||
DataType dataType = unit.getBaseDataType();
|
|
||||||
if (dataType instanceof Composite || dataType instanceof Array ||
|
|
||||||
dataType instanceof Dynamic) {
|
|
||||||
space.trace.setChanged(new TraceChangeRecord<>(TraceEvents.COMPOSITE_DATA_REMOVED,
|
|
||||||
space.space, unit.getBounds(), unit, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void unitSpanChanged(Lifespan oldSpan, DBTraceData unit) {
|
|
||||||
super.unitSpanChanged(oldSpan, unit);
|
|
||||||
DataType dataType = unit.getBaseDataType();
|
|
||||||
if (dataType instanceof Composite || dataType instanceof Array ||
|
|
||||||
dataType instanceof Dynamic) {
|
|
||||||
space.trace.setChanged(
|
|
||||||
new TraceChangeRecord<>(TraceEvents.COMPOSITE_DATA_LIFESPAN_CHANGED,
|
|
||||||
space.space, unit, oldSpan, unit.getLifespan()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ import java.util.*;
|
||||||
|
|
||||||
import org.apache.commons.collections4.IteratorUtils;
|
import org.apache.commons.collections4.IteratorUtils;
|
||||||
|
|
||||||
import generic.util.MergeSortingIterator;
|
|
||||||
import generic.util.FlattenedIterator;
|
import generic.util.FlattenedIterator;
|
||||||
|
import generic.util.MergeSortingIterator;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.database.code.InstructionDB;
|
import ghidra.program.database.code.InstructionDB;
|
||||||
import ghidra.program.database.function.OverlappingFunctionException;
|
import ghidra.program.database.function.OverlappingFunctionException;
|
||||||
|
@ -688,24 +688,6 @@ public abstract class AbstractDBTraceProgramViewListing implements TraceProgramV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(boolean forward) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(Address start, boolean forward) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<String> getUserDefinedProperties() {
|
public Iterator<String> getUserDefinedProperties() {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
|
@ -115,10 +115,6 @@ public class DBTraceProgramView implements TraceProgramView {
|
||||||
listenFor(TraceEvents.PRE_COMMENT_CHANGED, this::commentPreChanged);
|
listenFor(TraceEvents.PRE_COMMENT_CHANGED, this::commentPreChanged);
|
||||||
listenFor(TraceEvents.REPEATABLE_COMMENT_CHANGED, this::commentRepeatableChanged);
|
listenFor(TraceEvents.REPEATABLE_COMMENT_CHANGED, this::commentRepeatableChanged);
|
||||||
|
|
||||||
listenFor(TraceEvents.COMPOSITE_DATA_ADDED, this::compositeDataAdded);
|
|
||||||
listenFor(TraceEvents.COMPOSITE_DATA_LIFESPAN_CHANGED, this::compositeLifespanChanged);
|
|
||||||
listenFor(TraceEvents.COMPOSITE_DATA_REMOVED, this::compositeDataRemoved);
|
|
||||||
|
|
||||||
listenFor(TraceEvents.DATA_TYPE_ADDED, this::dataTypeAdded);
|
listenFor(TraceEvents.DATA_TYPE_ADDED, this::dataTypeAdded);
|
||||||
listenFor(TraceEvents.DATA_TYPE_CHANGED, this::dataTypeChanged);
|
listenFor(TraceEvents.DATA_TYPE_CHANGED, this::dataTypeChanged);
|
||||||
listenFor(TraceEvents.DATA_TYPE_REPLACED, this::dataTypeReplaced);
|
listenFor(TraceEvents.DATA_TYPE_REPLACED, this::dataTypeReplaced);
|
||||||
|
@ -322,8 +318,7 @@ public class DBTraceProgramView implements TraceProgramView {
|
||||||
range.getX2(), null, null, null));
|
range.getX2(), null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void codeDataTypeSettingsChanged(AddressSpace space,
|
private void codeDataTypeSettingsChanged(AddressSpace space, TraceAddressSnapRange range) {
|
||||||
TraceAddressSnapRange range) {
|
|
||||||
DomainObjectEventQueues queues = isVisible(space, range);
|
DomainObjectEventQueues queues = isVisible(space, range);
|
||||||
if (queues == null) {
|
if (queues == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -369,45 +364,6 @@ public class DBTraceProgramView implements TraceProgramView {
|
||||||
commentChanged(CommentType.REPEATABLE, space, range, oldValue, newValue);
|
commentChanged(CommentType.REPEATABLE, space, range, oldValue, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compositeDataAdded(AddressSpace space, TraceAddressSnapRange range,
|
|
||||||
TraceData oldIsNull, TraceData added) {
|
|
||||||
DomainObjectEventQueues queues = isCodeVisible(space, added);
|
|
||||||
if (queues == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
queues.fireEvent(new ProgramChangeRecord(ProgramEvent.COMPOSITE_ADDED,
|
|
||||||
added.getMinAddress(), added.getMaxAddress(), null, null, added));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void compositeLifespanChanged(AddressSpace space, TraceData data, Lifespan oldSpan,
|
|
||||||
Lifespan newSpan) {
|
|
||||||
DomainObjectEventQueues queues = getEventQueues(space);
|
|
||||||
if (queues == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean inOld = isCodeVisible(data, oldSpan);
|
|
||||||
boolean inNew = isCodeVisible(data, newSpan);
|
|
||||||
if (inOld && !inNew) {
|
|
||||||
queues.fireEvent(new ProgramChangeRecord(ProgramEvent.COMPOSITE_REMOVED,
|
|
||||||
data.getMinAddress(), data.getMaxAddress(), null, data, null));
|
|
||||||
}
|
|
||||||
if (!inOld && inNew) {
|
|
||||||
queues.fireEvent(new ProgramChangeRecord(ProgramEvent.COMPOSITE_ADDED,
|
|
||||||
data.getMinAddress(), data.getMaxAddress(), null, null, data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void compositeDataRemoved(AddressSpace space, TraceAddressSnapRange range,
|
|
||||||
TraceData removed, TraceData newIsNull) {
|
|
||||||
DomainObjectEventQueues queues = isCodeVisible(space, removed);
|
|
||||||
if (queues == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: ProgramDB doesn't send this.... Should I?
|
|
||||||
queues.fireEvent(new ProgramChangeRecord(ProgramEvent.COMPOSITE_REMOVED,
|
|
||||||
removed.getMinAddress(), removed.getMaxAddress(), null, removed, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dataTypeAdded(long id, DataType oldIsNull, DataType added) {
|
private void dataTypeAdded(long id, DataType oldIsNull, DataType added) {
|
||||||
fireEventAllViews(new ProgramChangeRecord(ProgramEvent.DATA_TYPE_ADDED, null, null,
|
fireEventAllViews(new ProgramChangeRecord(ProgramEvent.DATA_TYPE_ADDED, null, null,
|
||||||
null, oldIsNull, added));
|
null, oldIsNull, added));
|
||||||
|
@ -452,8 +408,8 @@ public class DBTraceProgramView implements TraceProgramView {
|
||||||
instruction.getMinAddress(), instruction.getMinAddress(), null, null, null));
|
instruction.getMinAddress(), instruction.getMinAddress(), null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void instructionFallThroughChanged(AddressSpace space,
|
private void instructionFallThroughChanged(AddressSpace space, TraceInstruction instruction,
|
||||||
TraceInstruction instruction, boolean oldFallThrough, boolean newFallThrough) {
|
boolean oldFallThrough, boolean newFallThrough) {
|
||||||
DomainObjectEventQueues queues = isCodeVisible(space, instruction);
|
DomainObjectEventQueues queues = isCodeVisible(space, instruction);
|
||||||
if (queues == null) {
|
if (queues == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1460,8 +1416,7 @@ public class DBTraceProgramView implements TraceProgramView {
|
||||||
return eventQueues;
|
return eventQueues;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DomainObjectEventQueues isVisible(AddressSpace space,
|
protected DomainObjectEventQueues isVisible(AddressSpace space, TraceAddressSnapRange range) {
|
||||||
TraceAddressSnapRange range) {
|
|
||||||
return viewport.containsAnyUpper(range.getLifespan()) ? getEventQueues(space) : null;
|
return viewport.containsAnyUpper(range.getLifespan()) ? getEventQueues(space) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,8 @@ import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.xml.*;
|
import ghidra.xml.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager to hold byte information from the <bytechunk> tags inside the Decompiler Debug's XML.
|
* Manager to hold byte information from the {@code <bytechunk>} tags inside the Decompiler Debug's
|
||||||
|
* XML.
|
||||||
*/
|
*/
|
||||||
public class DecompileDebugByteManager {
|
public class DecompileDebugByteManager {
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ public class DecompileDebugByteManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the <bytechunk> tag - has the memory offset and the raw bytes
|
* Parse the {@code <bytechunk>} tag - has the memory offset and the raw bytes
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log Xml
|
* @param log Xml
|
||||||
|
@ -66,7 +67,7 @@ public class DecompileDebugByteManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle parsing and creating bytechunks & pulling out the byte string as a byte array.
|
* Handle parsing and creating bytechunks and pulling out the byte string as a byte array.
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
|
|
|
@ -34,7 +34,7 @@ import ghidra.xml.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for parsing and storing data type objects from the XML - identified by
|
* Manager for parsing and storing data type objects from the XML - identified by
|
||||||
* the <coretypes> and <typegrp> tags.
|
* the {@code <coretypes>} and {@code <typegrp>} tags.
|
||||||
*
|
*
|
||||||
* NOTE: In the typegrp subtree, ID is often on a different line from the element's name and
|
* NOTE: In the typegrp subtree, ID is often on a different line from the element's name and
|
||||||
* metatype, so we need a way to reference this for use in the map -- String idHolder var
|
* metatype, so we need a way to reference this for use in the map -- String idHolder var
|
||||||
|
@ -62,13 +62,15 @@ public class DecompileDebugDataTypeManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse Data Type tag, handling types:
|
* Parse Data Type tag, handling types:
|
||||||
* <type>
|
* <ul>
|
||||||
* <typeref>
|
* <li>{@code <type>}</li>
|
||||||
* <def>
|
* <li>{@code <typeref>}</li>
|
||||||
* <void>
|
* <li>{@code <def>}</li>
|
||||||
|
* <li>{@code <void>}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
*
|
|
||||||
* @return retrieved DataType
|
* @return retrieved DataType
|
||||||
*/
|
*/
|
||||||
public DataType parseDataTypeTag(XmlPullParser parser, XmlMessageLog log) {
|
public DataType parseDataTypeTag(XmlPullParser parser, XmlMessageLog log) {
|
||||||
|
@ -98,7 +100,7 @@ public class DecompileDebugDataTypeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the <type> tag
|
* Parse the {@code <type>} tag
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
|
@ -138,7 +140,7 @@ public class DecompileDebugDataTypeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TypeDefs (<def> tags) are new definitions of types - basically, a re-naming.
|
* TypeDefs ({@cod <def>} tags) are new definitions of types - basically, a re-naming.
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
|
@ -197,7 +199,7 @@ public class DecompileDebugDataTypeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse & create union types
|
* Parse and create union types
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,6 +30,8 @@ import org.xml.sax.*;
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.app.util.opinion.DecompileDebugXmlLoader.DecompileDebugProgramInfo;
|
import ghidra.app.util.opinion.DecompileDebugXmlLoader.DecompileDebugProgramInfo;
|
||||||
|
import ghidra.formats.gfilesystem.FSRL;
|
||||||
|
import ghidra.formats.gfilesystem.FileSystemService;
|
||||||
import ghidra.framework.store.LockException;
|
import ghidra.framework.store.LockException;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressOverflowException;
|
import ghidra.program.model.address.AddressOverflowException;
|
||||||
|
@ -65,7 +67,7 @@ public class DecompileDebugFormatManager {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Constructs a new program Decompiler Debug XML manager using the provided ByteProvider.
|
* Constructs a new program Decompiler Debug XML manager using the provided ByteProvider.
|
||||||
* <p>
|
* <p>
|
||||||
* If {@link ByteProvider} has a {@link FSRL} and it is a simple local filepath,
|
* If {@link ByteProvider} has a {@link FSRL} and it is a simple local filepath,
|
||||||
|
@ -73,8 +75,8 @@ public class DecompileDebugFormatManager {
|
||||||
* {@link ByteProvider}'s File property which is probably located in the
|
* {@link ByteProvider}'s File property which is probably located in the
|
||||||
* {@link FileSystemService} filecache directory, which will break the ability
|
* {@link FileSystemService} filecache directory, which will break the ability
|
||||||
* to find the *.bytes file associated with this .xml file.
|
* to find the *.bytes file associated with this .xml file.
|
||||||
* <p>
|
*
|
||||||
* @param provider
|
* @param provider The provider
|
||||||
*/
|
*/
|
||||||
public DecompileDebugFormatManager(ByteProvider provider) {
|
public DecompileDebugFormatManager(ByteProvider provider) {
|
||||||
this.file = (provider.getFSRL() != null && provider.getFSRL().getNestingDepth() == 1)
|
this.file = (provider.getFSRL() != null && provider.getFSRL().getNestingDepth() == 1)
|
||||||
|
@ -82,10 +84,12 @@ public class DecompileDebugFormatManager {
|
||||||
: provider.getFile();
|
: provider.getFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Initial parsing of the XML file to obtain the binary image info with load specs.
|
* Initial parsing of the XML file to obtain the binary image info with load specs.
|
||||||
*
|
*
|
||||||
* @return DecompileDebugProgramInfo binary image / load spec details
|
* @return DecompileDebugProgramInfo binary image / load spec details
|
||||||
|
* @throws SAXException If there was a problem parsing the XML
|
||||||
|
* @throws IOException If there was an IO-related error
|
||||||
*/
|
*/
|
||||||
public DecompileDebugProgramInfo getProgramInfo() throws SAXException, IOException {
|
public DecompileDebugProgramInfo getProgramInfo() throws SAXException, IOException {
|
||||||
XmlPullParser parser =
|
XmlPullParser parser =
|
||||||
|
@ -118,22 +122,26 @@ public class DecompileDebugFormatManager {
|
||||||
* Perform the parsing from the underlying decompile debug XML file and populates the program fields.
|
* Perform the parsing from the underlying decompile debug XML file and populates the program fields.
|
||||||
* See @DecompileDebug.java for reference on the generation of the XML file.
|
* See @DecompileDebug.java for reference on the generation of the XML file.
|
||||||
* Tags currently supported/expected:
|
* Tags currently supported/expected:
|
||||||
* - <binaryimage>
|
* <ul>
|
||||||
* - <coretypes>
|
* <li>{@code <binaryimage>}</li>
|
||||||
* - <typegrp>
|
* <li>{@code <coretypes>}</li>
|
||||||
* - <save_state>
|
* <li>{@code <typegrp>}</li>
|
||||||
* - <db>
|
* <li>{@code <save_state>}</li>
|
||||||
* - <commentdb>
|
* <li>{@code <db>}</li>
|
||||||
* - <stringmanage>
|
* <li>{@code <commentdb>}</li>
|
||||||
|
* <li>{@code <stringmanage>}</li>
|
||||||
|
*</ul>
|
||||||
*
|
*
|
||||||
* NOTE: the following subtree tags are not yet supported:
|
* NOTE: the following subtree tags are not yet supported:
|
||||||
* - <context_points>
|
* <ul>
|
||||||
* - <optionslist>
|
* <li>{@code <context_points>}</li>
|
||||||
|
* <li>{@code <optionslist>}</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param prog created program
|
* @param prog created program
|
||||||
* @param monitor task monitor
|
* @param monitor task monitor
|
||||||
* @param programName name of program
|
* @param programName name of program
|
||||||
*@return MessageLog
|
* @return MessageLog
|
||||||
* @throws LoadException If there is a parsing issue with the XML file.
|
* @throws LoadException If there is a parsing issue with the XML file.
|
||||||
*/
|
*/
|
||||||
public MessageLog read(Program prog, TaskMonitor monitor, String programName)
|
public MessageLog read(Program prog, TaskMonitor monitor, String programName)
|
||||||
|
@ -234,8 +242,10 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse elements in the <db> subtree. Elements we currently handle include:
|
* Parse elements in the {@code <db>} subtree. Elements we currently handle include:
|
||||||
* - <scope>
|
* <ul>
|
||||||
|
* <li>{@code <scope>}</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param monitor TaskMonitor
|
* @param monitor TaskMonitor
|
||||||
|
@ -292,12 +302,12 @@ public class DecompileDebugFormatManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse element subtrees within the scope tag.
|
* Parse element subtrees within the scope tag.
|
||||||
*
|
* <p>
|
||||||
* NOTE: The scope tag must be parsed prior to a call to this message with the value
|
* NOTE: The scope tag must be parsed prior to a call to this message with the value
|
||||||
* of the namespace object sent as the first parameter.
|
* of the namespace object sent as the first parameter.
|
||||||
*
|
* <p>
|
||||||
* NOTE: it is expected that the wrapper <symbollist> tag is being used around the collection of
|
* NOTE: it is expected that the wrapper {@code <symbollist>} tag is being used around the
|
||||||
* <mapsymp> tags.
|
* collection of {@code <mapsymp>} tags.
|
||||||
*
|
*
|
||||||
* @param namespace Namespace
|
* @param namespace Namespace
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
|
@ -355,7 +365,8 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the <binaryimage> tag and subtree which includes the <bytechunk> tag(s).
|
* Handle the {@code <binaryimage>} tag and subtree which includes the {@code <bytechunk>}
|
||||||
|
* tag(s).
|
||||||
*
|
*
|
||||||
* @param parser XmlPullparser
|
* @param parser XmlPullparser
|
||||||
* @param monitor TaskMonitor
|
* @param monitor TaskMonitor
|
||||||
|
@ -382,7 +393,7 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle generation of labels from the <labelsym> tag
|
* Handle generation of labels from the {@code <labelsym>} tag
|
||||||
* @param prog program
|
* @param prog program
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
|
@ -415,9 +426,9 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse <symbol> tag under the <mapsym> tag -- meaning, they are outside of a function,
|
* Parse {@code <symbol>} tag under the {@code <mapsym>} tag -- meaning, they are outside of a
|
||||||
* most likely these are data references.
|
* function, most likely these are data references.
|
||||||
*
|
* <p>
|
||||||
* NOTE: We are currently not pulling the bytes for referenced functions or data, as a result
|
* NOTE: We are currently not pulling the bytes for referenced functions or data, as a result
|
||||||
* we need to generate an initialized memory block for data references to avoid errors
|
* we need to generate an initialized memory block for data references to avoid errors
|
||||||
* in the Listing pane.
|
* in the Listing pane.
|
||||||
|
@ -500,10 +511,11 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse comments from the <commentdb> tag and add to listing via setupComments method.
|
* Parse comments from the {@code <commentdb>} tag and add to listing via setupComments method.
|
||||||
*
|
* <p>
|
||||||
* Note: <commentdb> has two <addr> tags. The first is the function address, and the second
|
* Note: {@code <commentdb>} has two {@code <addr>} tags. The first is the function address,
|
||||||
* is the (CodeUnit) address where the comment should be placed. Discard the first address.
|
* and the second is the {@link CodeUnit} address where the comment should be placed. Discard
|
||||||
|
* the first address.
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param prog Program
|
* @param prog Program
|
||||||
|
@ -550,14 +562,15 @@ public class DecompileDebugFormatManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See @DecompileCallback.java for the encoding of the comments by @DecompileDebug.java.
|
* See @DecompileCallback.java for the encoding of the comments by @DecompileDebug.java.
|
||||||
* The method <encodeCommentsType> encodes the comment types found in @CodeUnit.java
|
* The method {@code <encodeCommentsType>} encodes the comment types found in @CodeUnit.java
|
||||||
* in 4 alternative labels:
|
* in 4 alternative labels:
|
||||||
* CodeUnit.EOL_COMMENT = "user1"
|
* <ul>
|
||||||
* CodeUnit.PRE_COMMENT = "user2"
|
* <li>{@code CodeUnit.EOL_COMMENT = "user1"}</li>
|
||||||
* CodeUnit.POST_COMMENT = "user3"
|
* <li>{@code CodeUnit.PRE_COMMENT = "user2"}</li>
|
||||||
* CodeUnit.PLATE_COMMENT = "header"
|
* <li>{@code CodeUnit.POST_COMMENT = "user3"}</li>
|
||||||
*
|
* <li>{@code CodeUnit.PLATE_COMMENT = "header"}</li>
|
||||||
* In order to generate comments using @CodeUnit.java, we will need to re-encode the user<1-3>
|
* </ul>
|
||||||
|
* In order to generate comments using @CodeUnit.java, we will need to re-encode the user[1-3]
|
||||||
* and header type labels from the DecompileDebug XML back into the CodeUnit constant values of:
|
* and header type labels from the DecompileDebug XML back into the CodeUnit constant values of:
|
||||||
* 0-3 (respectively).
|
* 0-3 (respectively).
|
||||||
*
|
*
|
||||||
|
@ -566,29 +579,17 @@ public class DecompileDebugFormatManager {
|
||||||
* @return CodeUnit comment type (0-3)
|
* @return CodeUnit comment type (0-3)
|
||||||
*/
|
*/
|
||||||
private CommentType decodeCommentType(String typeName) {
|
private CommentType decodeCommentType(String typeName) {
|
||||||
CommentType commentType;
|
return switch (typeName) {
|
||||||
switch (typeName) {
|
case "user1" -> CommentType.EOL;
|
||||||
case "user1":
|
case "user2" -> CommentType.PRE;
|
||||||
commentType = CommentType.EOL;
|
case "user3" -> CommentType.POST;
|
||||||
break;
|
case "header" -> CommentType.PLATE;
|
||||||
case "user2":
|
default -> CommentType.valueOf("");
|
||||||
commentType = CommentType.PRE;
|
};
|
||||||
break;
|
|
||||||
case "user3":
|
|
||||||
commentType = CommentType.POST;
|
|
||||||
break;
|
|
||||||
case "header":
|
|
||||||
commentType = CommentType.PLATE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
commentType = CommentType.valueOf("");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return commentType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loop through the <type> tags in the <coretypes> subtree
|
* Loop through the {@code <type>} tags in the {@code <coretypes>} subtree
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param prog built program
|
* @param prog built program
|
||||||
|
@ -605,7 +606,7 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the <stringmanage> subtree
|
* Parse the {@code <stringmanage>} subtree
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param monitor TaskMonitor
|
* @param monitor TaskMonitor
|
||||||
|
@ -620,7 +621,7 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the <string> tag and insert into the program
|
* Parse the {@code <string>} tag and insert into the program
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param monitor TaskMonitor
|
* @param monitor TaskMonitor
|
||||||
|
@ -650,7 +651,7 @@ public class DecompileDebugFormatManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the parsing of the context pointset inside of the <contextpointset> subtree
|
* Handle the parsing of the context pointset inside of the {@code <contextpointset>} subtree
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param monitor TaskMonitor
|
* @param monitor TaskMonitor
|
||||||
|
|
|
@ -63,14 +63,14 @@ public class DecompileDebugFunctionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup functions from within the <symbollist> tag.
|
* Setup functions from within the {@code <symbollist>} tag.
|
||||||
* Functions referenced by the central function are loaded the same except we do not
|
* Functions referenced by the central function are loaded the same except we do not
|
||||||
* (currently) have the memory/program context for them. Thus, they will show up in the Listing
|
* (currently) have the memory/program context for them. Thus, they will show up in the Listing
|
||||||
* with a red "X".
|
* with a red "X".
|
||||||
* NOTE: This is the expected functionality.
|
* NOTE: This is the expected functionality.
|
||||||
*
|
*
|
||||||
* @param parser XmlPullParser
|
* @param parser XmlPullParser
|
||||||
* @param scopeMap Map<String, Namespace> used for getting parent namespace
|
* @param scopeMap {@code Map<String, Namespace>} used for getting parent namespace
|
||||||
* @param log XmlMessageLog
|
* @param log XmlMessageLog
|
||||||
*/
|
*/
|
||||||
public void parseFunctionSignature(XmlPullParser parser, Map<Long, Namespace> scopeMap,
|
public void parseFunctionSignature(XmlPullParser parser, Map<Long, Namespace> scopeMap,
|
||||||
|
|
|
@ -36,7 +36,8 @@ import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.LanguageID;
|
import ghidra.program.model.lang.LanguageID;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.Data;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
import ghidra.util.exception.RollbackException;
|
import ghidra.util.exception.RollbackException;
|
||||||
|
@ -44,7 +45,9 @@ import ghidra.util.exception.RollbackException;
|
||||||
@Category(NightlyCategory.class)
|
@Category(NightlyCategory.class)
|
||||||
public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private static final String COMPOSITE_DATA_ADDRESS = "00400050";
|
private static final int ARRAY_ELEMENT_COUNT = 6;
|
||||||
|
private static final String ARRAY_DATA_ADDRESS = "00400050";
|
||||||
|
|
||||||
private static final String DATA_STRING_ADDRESS = "0041fee4";
|
private static final String DATA_STRING_ADDRESS = "0041fee4";
|
||||||
private static final String BYTE_SCALAR_ADDRESS = "00421eb0";
|
private static final String BYTE_SCALAR_ADDRESS = "00421eb0";
|
||||||
private static final String CHAR_SCALAR_ADDRESS = "00421ed0";
|
private static final String CHAR_SCALAR_ADDRESS = "00421ed0";
|
||||||
|
@ -98,7 +101,7 @@ public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
int txId = program.startTransaction("Test");
|
int txId = program.startTransaction("Test");
|
||||||
try {
|
try {
|
||||||
createCompositeDataType();
|
createArrayDataType();
|
||||||
createByteDataType();
|
createByteDataType();
|
||||||
createCharDataType();
|
createCharDataType();
|
||||||
createDWordDataType();
|
createDWordDataType();
|
||||||
|
@ -212,9 +215,9 @@ public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCompositeDataInTable() throws Exception {
|
public void testArrayDataInTable() throws Exception {
|
||||||
searchProgramAndDisplayResults(program, null, minScalarVal, maxScalarVal);
|
searchProgramAndDisplayResults(program, null, minScalarVal, maxScalarVal);
|
||||||
assertScalarsFromCompositeDataInTable();
|
assertScalarsFromArrayDataInTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -417,25 +420,18 @@ public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(0, data.size());
|
assertEquals(0, data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertScalarsFromCompositeDataInTable() {
|
private void assertScalarsFromArrayDataInTable() {
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
|
||||||
DataIterator compositeData = listing.getCompositeData(true);
|
|
||||||
Data composite = compositeData.next();
|
|
||||||
assertTrue("Expected array; found: " + composite, composite.getDataType() instanceof Array);
|
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
List<ScalarRowObject> data = getTableData();
|
List<ScalarRowObject> data = getTableData();
|
||||||
List<Address> addresses =
|
List<Address> addresses = data.stream().map(rowObject -> rowObject.getAddress()).toList();
|
||||||
data.stream()
|
|
||||||
.map(rowObject -> rowObject.getAddress())
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
;
|
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
int n = composite.getNumComponents();
|
Address arrayAddr = program.getAddressFactory().getAddress(ARRAY_DATA_ADDRESS);
|
||||||
for (int i = 0; i < n; i++) {
|
Data arrayData = program.getListing().getDefinedDataAt(arrayAddr);
|
||||||
Data child = composite.getComponent(i);
|
assertNotNull(arrayData);
|
||||||
|
assertEquals("byte[6]", arrayData.getDataType().getName());
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_ELEMENT_COUNT; i++) {
|
||||||
|
Data child = arrayData.getComponent(i);
|
||||||
Address a = child.getAddress();
|
Address a = child.getAddress();
|
||||||
assertTrue(addresses.contains(a));
|
assertTrue(addresses.contains(a));
|
||||||
}
|
}
|
||||||
|
@ -497,18 +493,12 @@ public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
tableAddress.add(rowObject.getAddress());
|
tableAddress.add(rowObject.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
DataIterator compositeData = p.getListing().getCompositeData(true);
|
Address structAddr = p.getAddressFactory().getAddress(NESTED_STRUCTURE_DATA_ADDRESS);
|
||||||
|
Data compositeData = p.getListing().getDefinedDataAt(structAddr);
|
||||||
|
assertEquals("NESTED_STRUCTURE", compositeData.getDataType().getName());
|
||||||
|
|
||||||
while (compositeData.hasNext()) {
|
assertTrue("Table not created correctly: could not find address " + structAddr +
|
||||||
|
"in scalar table.", tableAddress.contains(structAddr));
|
||||||
Data structureData = compositeData.next();
|
|
||||||
Address address = structureData.getComponent(0).getAddress();
|
|
||||||
|
|
||||||
if (!tableAddress.contains(address)) {
|
|
||||||
fail("Table not created correctly: could not find address " + address +
|
|
||||||
"in scalar table.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFilterValues(int min, int max) {
|
private void setFilterValues(int min, int max) {
|
||||||
|
@ -555,15 +545,14 @@ public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
"A_virt2@401120", 16);
|
"A_virt2@401120", 16);
|
||||||
createFunction(builder, "00401130", "55 8b ec 51 89 4d fc b8 08 00 00 00 8b e5 5d c3",
|
createFunction(builder, "00401130", "55 8b ec 51 89 4d fc b8 08 00 00 00 8b e5 5d c3",
|
||||||
"B_virt2@401130", 16);
|
"B_virt2@401130", 16);
|
||||||
createFunction(builder, "00401140", "48 83 ec cc",
|
createFunction(builder, "00401140", "48 83 ec cc", "C_virt2@401140", 4);
|
||||||
"C_virt2@401140", 4);
|
|
||||||
createFunction(builder, "00401150", "55 8b ec 51 89 4d fc b8 cc 00 00 00 8b e5 5d c3",
|
createFunction(builder, "00401150", "55 8b ec 51 89 4d fc b8 cc 00 00 00 8b e5 5d c3",
|
||||||
"C_virt2@401150", 16);
|
"C_virt2@401150", 16);
|
||||||
|
|
||||||
createBytes(builder, COMPOSITE_DATA_ADDRESS,
|
createBytes(builder, ARRAY_DATA_ADDRESS,
|
||||||
"0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 69 73 20 70 " +
|
"0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 69 73 20 70 72 6f 67 72 61 6d 20 63 " +
|
||||||
"72 6f 67 72 61 6d 20 63 61 6e 6e 6f 74 20 62 65 20 72 75 6e " +
|
"61 6e 6e 6f 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 6d 6f 64 65 2e 0d " +
|
||||||
"20 69 6e 20 44 4f 53 20 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 " + "00 00 00 00");
|
"0d 0a 24 00 00 00 00 00 00 00");
|
||||||
createBytes(builder, BYTE_SCALAR_ADDRESS, "c4");
|
createBytes(builder, BYTE_SCALAR_ADDRESS, "c4");
|
||||||
createBytes(builder, CHAR_SCALAR_ADDRESS, "28");
|
createBytes(builder, CHAR_SCALAR_ADDRESS, "28");
|
||||||
createBytes(builder, DWORD_SCALAR_ADDRESS, "08 34 23 cd");
|
createBytes(builder, DWORD_SCALAR_ADDRESS, "08 34 23 cd");
|
||||||
|
@ -686,9 +675,9 @@ public class ScalarSearchTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createCompositeDataType() throws Exception {
|
private void createArrayDataType() throws Exception {
|
||||||
ArrayDataType arrayDataType = new ArrayDataType(new ByteDataType(), 6, 2);
|
ArrayDataType arrayDataType = new ArrayDataType(new ByteDataType(), 6, 2);
|
||||||
createData(addr(Long.parseLong(COMPOSITE_DATA_ADDRESS, 16)), arrayDataType);
|
createData(addr(Long.parseLong(ARRAY_DATA_ADDRESS, 16)), arrayDataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createByteDataType() throws Exception {
|
private void createByteDataType() throws Exception {
|
||||||
|
|
|
@ -1239,169 +1239,6 @@ public class CodeUnitIteratorTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
dtm.close();
|
dtm.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetCompositeData() throws Exception {
|
|
||||||
startTransaction();
|
|
||||||
mem.createInitializedBlock("test", addr(0), 1000, (byte) 0, TaskMonitor.DUMMY, false);
|
|
||||||
|
|
||||||
Structure struct = new StructureDataType("struct_1", 100);
|
|
||||||
Structure struct2 = new StructureDataType("struct_2", 0);
|
|
||||||
Structure struct3 = new StructureDataType("struct_3", 0);
|
|
||||||
DataTypeManager dtm = new StandAloneDataTypeManager("dummyDTM");
|
|
||||||
int id = dtm.startTransaction("");
|
|
||||||
|
|
||||||
struct = (Structure) dtm.resolve(struct, null);
|
|
||||||
struct2 = (Structure) dtm.resolve(struct2, null);
|
|
||||||
struct3 = (Structure) dtm.resolve(struct3, null);
|
|
||||||
|
|
||||||
struct2.add(new ByteDataType());
|
|
||||||
struct2.add(new StringDataType(), 20);
|
|
||||||
struct2.add(new QWordDataType());
|
|
||||||
struct3.add(struct2);
|
|
||||||
|
|
||||||
struct.replace(0, struct2, struct2.getLength());
|
|
||||||
struct.replace(1, new StringDataType(), 10);
|
|
||||||
|
|
||||||
listing.createData(addr(0), struct, 0);
|
|
||||||
|
|
||||||
listing.createData(addr(300), struct2, 0);
|
|
||||||
|
|
||||||
listing.createData(addr(250), struct3, 0);
|
|
||||||
endTransaction();
|
|
||||||
|
|
||||||
DataIterator iter = listing.getCompositeData(true);
|
|
||||||
assertTrue(iter.hasNext());
|
|
||||||
Data d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(0), d.getMinAddress());
|
|
||||||
assertEquals(addr(99), d.getMaxAddress());
|
|
||||||
|
|
||||||
d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(250), d.getMinAddress());
|
|
||||||
assertEquals("struct_3", d.getDataType().getName());
|
|
||||||
|
|
||||||
d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(300), d.getMinAddress());
|
|
||||||
assertEquals(3, d.getNumComponents());
|
|
||||||
|
|
||||||
assertTrue(!iter.hasNext());
|
|
||||||
d = iter.next();
|
|
||||||
assertNull(d);
|
|
||||||
dtm.endTransaction(id, true);
|
|
||||||
dtm.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetCompositeDataStartingAt() throws Exception {
|
|
||||||
startTransaction();
|
|
||||||
mem.createInitializedBlock("test", addr(0), 1000, (byte) 0, TaskMonitor.DUMMY, false);
|
|
||||||
|
|
||||||
Structure struct = new StructureDataType("struct_1", 100);
|
|
||||||
Structure struct2 = new StructureDataType("struct_2", 0);
|
|
||||||
Structure struct3 = new StructureDataType("struct_3", 0);
|
|
||||||
DataTypeManager dtm = new StandAloneDataTypeManager("dummyDTM");
|
|
||||||
int id = dtm.startTransaction("");
|
|
||||||
struct = (Structure) dtm.resolve(struct, null);
|
|
||||||
struct2 = (Structure) dtm.resolve(struct2, null);
|
|
||||||
struct3 = (Structure) dtm.resolve(struct3, null);
|
|
||||||
|
|
||||||
struct2.add(new ByteDataType());
|
|
||||||
struct2.add(new StringDataType(), 20);
|
|
||||||
struct2.add(new QWordDataType());
|
|
||||||
struct3.add(struct2);
|
|
||||||
|
|
||||||
struct.replace(0, struct2, struct2.getLength());
|
|
||||||
struct.replace(1, new StringDataType(), 10);
|
|
||||||
|
|
||||||
listing.createData(addr(0), struct, 0);
|
|
||||||
|
|
||||||
listing.createData(addr(300), struct2, 0);
|
|
||||||
|
|
||||||
listing.createData(addr(250), struct3, 0);
|
|
||||||
|
|
||||||
Union union = new UnionDataType("union_1");
|
|
||||||
union.add(struct3);
|
|
||||||
union.add(struct2);
|
|
||||||
|
|
||||||
listing.createData(addr(600), union, 0);
|
|
||||||
endTransaction();
|
|
||||||
|
|
||||||
DataIterator iter = listing.getCompositeData(addr(275), true);
|
|
||||||
assertTrue(iter.hasNext());
|
|
||||||
|
|
||||||
Data d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(300), d.getMinAddress());
|
|
||||||
|
|
||||||
d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(600), d.getMinAddress());
|
|
||||||
|
|
||||||
assertTrue(!iter.hasNext());
|
|
||||||
assertNull(iter.next());
|
|
||||||
dtm.endTransaction(id, true);
|
|
||||||
dtm.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetCompositeDataInSet() throws Exception {
|
|
||||||
startTransaction();
|
|
||||||
mem.createInitializedBlock("test", addr(0), 1000, (byte) 0, TaskMonitor.DUMMY, false);
|
|
||||||
|
|
||||||
Structure struct = new StructureDataType("struct_1", 100);
|
|
||||||
Structure struct2 = new StructureDataType("struct_2", 0);
|
|
||||||
Structure struct3 = new StructureDataType("struct_3", 0);
|
|
||||||
DataTypeManager dtm = new StandAloneDataTypeManager("dummyDTM");
|
|
||||||
int id = dtm.startTransaction("");
|
|
||||||
struct = (Structure) dtm.resolve(struct, null);
|
|
||||||
struct2 = (Structure) dtm.resolve(struct2, null);
|
|
||||||
struct3 = (Structure) dtm.resolve(struct3, null);
|
|
||||||
|
|
||||||
struct2.add(new ByteDataType());
|
|
||||||
struct2.add(new StringDataType(), 20);
|
|
||||||
struct2.add(new QWordDataType());
|
|
||||||
struct3.add(struct2);
|
|
||||||
|
|
||||||
struct.replace(0, struct2, struct2.getLength());
|
|
||||||
struct.replace(1, new StringDataType(), 10);
|
|
||||||
|
|
||||||
listing.createData(addr(0), struct, 0);
|
|
||||||
|
|
||||||
listing.createData(addr(300), struct2, 0);
|
|
||||||
|
|
||||||
listing.createData(addr(450), struct3, 0);
|
|
||||||
|
|
||||||
Union union = new UnionDataType("union_1");
|
|
||||||
union.add(struct3);
|
|
||||||
union.add(struct2);
|
|
||||||
|
|
||||||
listing.createData(addr(800), union, 0);
|
|
||||||
endTransaction();
|
|
||||||
|
|
||||||
AddressSet set = new AddressSet();
|
|
||||||
set.addRange(addr(5), addr(10));
|
|
||||||
set.addRange(addr(100), addr(200));
|
|
||||||
set.addRange(addr(300), addr(320));
|
|
||||||
set.addRange(addr(400), addr(500));
|
|
||||||
|
|
||||||
DataIterator iter = listing.getCompositeData(set, true);
|
|
||||||
Data d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(300), d.getMinAddress());
|
|
||||||
d = iter.next();
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals(addr(450), d.getMinAddress());
|
|
||||||
|
|
||||||
d = iter.next();
|
|
||||||
assertNull(d);
|
|
||||||
dtm.endTransaction(id, true);
|
|
||||||
dtm.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetDefinedDataIterator() throws Exception {
|
public void testGetDefinedDataIterator() throws Exception {
|
||||||
startTransaction();
|
startTransaction();
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Objects;
|
||||||
import ghidra.pcode.emu.jit.analysis.JitType.*;
|
import ghidra.pcode.emu.jit.analysis.JitType.*;
|
||||||
import ghidra.pcode.emu.jit.op.JitCopyOp;
|
import ghidra.pcode.emu.jit.op.JitCopyOp;
|
||||||
import ghidra.pcode.emu.jit.op.JitPhiOp;
|
import ghidra.pcode.emu.jit.op.JitPhiOp;
|
||||||
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior/requirement for an operand's type.
|
* The behavior/requirement for an operand's type.
|
||||||
|
@ -177,6 +178,9 @@ public enum JitTypeBehavior {
|
||||||
if (cls == void.class) {
|
if (cls == void.class) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (cls == Varnode.class) {
|
||||||
|
return ANY;
|
||||||
|
}
|
||||||
if (cls.isPrimitive()) {
|
if (cls.isPrimitive()) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ public abstract class DataTreeNode extends GTreeSlowLoadingNode implements Cutta
|
||||||
public abstract ProjectData getProjectData();
|
public abstract ProjectData getProjectData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns domain folder/file pathname within project
|
* {@return domain folder/file pathname within project}
|
||||||
*/
|
*/
|
||||||
public abstract String getPathname();
|
public abstract String getPathname();
|
||||||
|
|
||||||
|
|
|
@ -235,22 +235,6 @@ class ListingDB implements Listing {
|
||||||
return codeMgr.getFirstUndefinedDataBefore(addr, monitor);
|
return codeMgr.getFirstUndefinedDataBefore(addr, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(boolean forward) {
|
|
||||||
return codeMgr.getCompositeData(forward ? program.getMinAddress() : program.getMaxAddress(),
|
|
||||||
forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(Address start, boolean forward) {
|
|
||||||
return codeMgr.getCompositeData(start, forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) {
|
|
||||||
return codeMgr.getCompositeData(addrSet, forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<String> getUserDefinedProperties() {
|
public Iterator<String> getUserDefinedProperties() {
|
||||||
return codeMgr.getUserDefinedProperties();
|
return codeMgr.getUserDefinedProperties();
|
||||||
|
|
|
@ -115,8 +115,9 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* Multiple blocks are permitted within a single overlay space.
|
* Multiple blocks are permitted within a single overlay space.
|
||||||
* 13-Dec-2024 - version 29 Added source file manager.
|
* 13-Dec-2024 - version 29 Added source file manager.
|
||||||
* 3-Jun-2025 - version 30 Symbol Table schema V4 with external symbol data indexing
|
* 3-Jun-2025 - version 30 Symbol Table schema V4 with external symbol data indexing
|
||||||
|
* 15-Sep-2025 - version 31 Code Mananger dropped Composites property map use
|
||||||
*/
|
*/
|
||||||
static final int DB_VERSION = 30;
|
static final int DB_VERSION = 31;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UPGRADE_REQUIRED_BFORE_VERSION should be changed to DB_VERSION anytime the
|
* UPGRADE_REQUIRED_BFORE_VERSION should be changed to DB_VERSION anytime the
|
||||||
|
|
|
@ -64,7 +64,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
private ProgramContext contextMgr;
|
private ProgramContext contextMgr;
|
||||||
private ReferenceManager refManager;
|
private ReferenceManager refManager;
|
||||||
private PropertyMapManager propertyMapMgr;
|
private PropertyMapManager propertyMapMgr;
|
||||||
private VoidPropertyMapDB compositeMgr;
|
|
||||||
private IntPropertyMapDB lengthMgr;
|
private IntPropertyMapDB lengthMgr;
|
||||||
|
|
||||||
private boolean contextLockingEnabled = false;
|
private boolean contextLockingEnabled = false;
|
||||||
|
@ -97,8 +96,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
|
|
||||||
cache = new DBObjectCache<>(1000);
|
cache = new DBObjectCache<>(1000);
|
||||||
protoMgr = new PrototypeManager(handle, addrMap, openMode, monitor);
|
protoMgr = new PrototypeManager(handle, addrMap, openMode, monitor);
|
||||||
compositeMgr =
|
|
||||||
new VoidPropertyMapDB(dbHandle, openMode, this, null, addrMap, "Composites", monitor);
|
|
||||||
lengthMgr =
|
lengthMgr =
|
||||||
new IntPropertyMapDB(dbHandle, openMode, this, null, addrMap, "Lengths", monitor);
|
new IntPropertyMapDB(dbHandle, openMode, this, null, addrMap, "Lengths", monitor);
|
||||||
|
|
||||||
|
@ -131,6 +128,15 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeOldCompositeMap() throws IOException {
|
||||||
|
// Remove old Composites Void property map associated with tracking composite
|
||||||
|
// placement in memory. This tracking mechanism was never used.
|
||||||
|
String oldTableName = "Property Map - Composites";
|
||||||
|
if (dbHandle.getTable(oldTableName) != null) {
|
||||||
|
dbHandle.deleteTable(oldTableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert old fall-through overrides into References.
|
* Convert old fall-through overrides into References.
|
||||||
*/
|
*/
|
||||||
|
@ -235,6 +241,7 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
if (openMode == OpenMode.UPGRADE) {
|
if (openMode == OpenMode.UPGRADE) {
|
||||||
upgradeOldFallThroughMaps(monitor);
|
upgradeOldFallThroughMaps(monitor);
|
||||||
|
removeOldCompositeMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,7 +758,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
compositeMgr.removeRange(start, end);
|
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
instAdapter.deleteRecords(start, end);
|
instAdapter.deleteRecords(start, end);
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
|
@ -2061,12 +2067,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
data = getDataDB(record);
|
data = getDataDB(record);
|
||||||
baseDt = data.getBaseDataType();
|
baseDt = data.getBaseDataType();
|
||||||
|
|
||||||
if (dataType instanceof Composite || dataType instanceof Array ||
|
|
||||||
dataType instanceof Dynamic) {
|
|
||||||
compositeMgr.add(addr);
|
|
||||||
program.setChanged(ProgramEvent.COMPOSITE_ADDED, addr, endAddr, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fire event
|
// fire event
|
||||||
program.setChanged(ProgramEvent.CODE_ADDED, addr, endAddr, null, data);
|
program.setChanged(ProgramEvent.CODE_ADDED, addr, endAddr, null, data);
|
||||||
|
|
||||||
|
@ -2399,43 +2399,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a composite data iterator beginning at the specified start address.
|
|
||||||
*
|
|
||||||
* @param start the address to begin iterator
|
|
||||||
* @param forward true means get iterator in forward direction
|
|
||||||
* @return the composite data iterator
|
|
||||||
*/
|
|
||||||
public DataIterator getCompositeData(Address start, boolean forward) {
|
|
||||||
try {
|
|
||||||
return new DataKeyIterator(this, addrMap,
|
|
||||||
compositeMgr.getAddressKeyIterator(start, forward));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
program.dbError(e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a composite data iterator limited to the addresses in the specified address set.
|
|
||||||
*
|
|
||||||
* @param addrSet the address set to limit the iterator
|
|
||||||
* @param forward determines if the iterator will go from the lowest address to the highest or
|
|
||||||
* the other way around.
|
|
||||||
* @return DataIterator the composite data iterator
|
|
||||||
*/
|
|
||||||
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) {
|
|
||||||
try {
|
|
||||||
return new DataKeyIterator(this, addrMap,
|
|
||||||
compositeMgr.getAddressKeyIterator(addrSet, forward));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
program.dbError(e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator over all codeUnits in the program from the given start address to either
|
* Returns an iterator over all codeUnits in the program from the given start address to either
|
||||||
* the end address or the start address, depending if the iterator is forward or not.
|
* the end address or the start address, depending if the iterator is forward or not.
|
||||||
|
@ -2856,7 +2819,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
try {
|
try {
|
||||||
Address endAddr = startAddr.add(length - 1);
|
Address endAddr = startAddr.add(length - 1);
|
||||||
|
|
||||||
compositeMgr.moveRange(startAddr, endAddr, newStartAddr);
|
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
|
|
||||||
lengthMgr.moveRange(startAddr, endAddr, newStartAddr);
|
lengthMgr.moveRange(startAddr, endAddr, newStartAddr);
|
||||||
|
@ -3205,7 +3167,6 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
try {
|
try {
|
||||||
cache.invalidate();
|
cache.invalidate();
|
||||||
lengthMgr.invalidate();
|
lengthMgr.invalidate();
|
||||||
compositeMgr.invalidate();
|
|
||||||
protoMgr.clearCache();
|
protoMgr.clearCache();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -3227,12 +3188,7 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
*/
|
*/
|
||||||
public void memoryChanged(Address addr, Address end) {
|
public void memoryChanged(Address addr, Address end) {
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
// CodeUnit cu = getCodeUnitContaining(addr);
|
|
||||||
// if (cu != null) {
|
|
||||||
// addr = cu.getMinAddress();
|
|
||||||
// }
|
|
||||||
try {
|
try {
|
||||||
// cache.invalidate(addrMap.getKey(addr), addrMap.getKey(end));
|
|
||||||
cache.invalidate();
|
cache.invalidate();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|
|
@ -604,39 +604,6 @@ public interface Listing {
|
||||||
*/
|
*/
|
||||||
public CodeUnit getDefinedCodeUnitBefore(Address addr);
|
public CodeUnit getDefinedCodeUnitBefore(Address addr);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an iterator over all the composite data objects (Arrays, Structures,
|
|
||||||
* and Union) in the program.
|
|
||||||
*
|
|
||||||
* @param forward true means get iterator that starts at the minimum address
|
|
||||||
* and iterates forward. Otherwise it starts at the maximum
|
|
||||||
* address and iterates backwards.
|
|
||||||
* @return an iterator over all the composite data objects.
|
|
||||||
*/
|
|
||||||
public DataIterator getCompositeData(boolean forward);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an iterator over all the composite data objects (Arrays, Structures,
|
|
||||||
* and Union) in the program at or after the given Address.
|
|
||||||
*
|
|
||||||
* @param start start of the iterator
|
|
||||||
* @param forward true means get iterator in forward direction
|
|
||||||
* @return an iterator over all the composite data objects starting with the
|
|
||||||
* given address.
|
|
||||||
*/
|
|
||||||
public DataIterator getCompositeData(Address start, boolean forward);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an iterator over all the composite data objects (Arrays, Structures,
|
|
||||||
* and Union) within the specified address set in the program.
|
|
||||||
*
|
|
||||||
* @param addrSet the address set
|
|
||||||
* @param forward true means get iterator in forward direction
|
|
||||||
* @return an iterator over all the composite data objects in the given
|
|
||||||
* address set.
|
|
||||||
*/
|
|
||||||
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator over all user defined property names.
|
* Returns an iterator over all user defined property names.
|
||||||
*
|
*
|
||||||
|
|
|
@ -267,21 +267,6 @@ public class StubListing implements Listing {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(boolean forward) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(Address start, boolean forward) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<String> getUserDefinedProperties() {
|
public Iterator<String> getUserDefinedProperties() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -199,20 +199,6 @@ public interface ChangeManager {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static final ProgramEvent DOCR_CODE_MOVED = FRAGMENT_CHANGED;
|
public static final ProgramEvent DOCR_CODE_MOVED = FRAGMENT_CHANGED;
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure was added.
|
|
||||||
* @deprecated Event type numeric constants have been changed to enums. Use the enum directly.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final ProgramEvent DOCR_COMPOSITE_ADDED = COMPOSITE_ADDED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure was removed.
|
|
||||||
* @deprecated Event type numeric constants have been changed to enums. Use the enum directly.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final ProgramEvent DOCR_COMPOSITE_REMOVED = COMPOSITE_REMOVED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data was replaced.
|
* Data was replaced.
|
||||||
* @deprecated Event type numeric constants have been changed to enums. Use the enum directly.
|
* @deprecated Event type numeric constants have been changed to enums. Use the enum directly.
|
||||||
|
|
|
@ -37,9 +37,6 @@ public enum ProgramEvent implements EventType {
|
||||||
CODE_REMOVED, // instructions or data cleared at an address
|
CODE_REMOVED, // instructions or data cleared at an address
|
||||||
CODE_REPLACED, // the instruction or data type at an address was changed
|
CODE_REPLACED, // the instruction or data type at an address was changed
|
||||||
|
|
||||||
COMPOSITE_ADDED, // a non-primitive data type was added
|
|
||||||
COMPOSITE_REMOVED, // a non-primitive data type was removed
|
|
||||||
|
|
||||||
CODE_UNIT_PROPERTY_CHANGED, // a property map value changed
|
CODE_UNIT_PROPERTY_CHANGED, // a property map value changed
|
||||||
CODE_UNIT_PROPERTY_ALL_REMOVED, // a property map was removed
|
CODE_UNIT_PROPERTY_ALL_REMOVED, // a property map was removed
|
||||||
CODE_UNIT_PROPERTY_RANGE_REMOVED, // a ranges of values was removed
|
CODE_UNIT_PROPERTY_RANGE_REMOVED, // a ranges of values was removed
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue