Merge remote-tracking branch 'origin/master' into debugger

This commit is contained in:
Dan 2021-05-14 10:34:05 -04:00
commit bdba9fa919
111 changed files with 1020 additions and 865 deletions

View file

@ -34,7 +34,7 @@ You may not need all of these, depending on which portions you are building or d
- https://adoptopenjdk.net/releases.html?variant=openjdk11&jvmVariant=hotspot
- Amazon Corretto
- https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html
* Gradle 5.0 or later - We use version 5.0, and tested with up to 6.8.3.
* Gradle 5.x or 6.x - We use version 5.0, and have tested with up to 6.8.3.
- https://gradle.org/next-steps/?version=5.0&format=bin
* A C/C++ compiler - We use GCC on Linux, Xcode (Clang) on macOS, and Visual Studio (2017 or later) on Windows.
- https://gcc.gnu.org/
@ -55,9 +55,6 @@ You may not need all of these, depending on which portions you are building or d
- https://github.com/pxb1988/dex2jar/releases
* AXMLPrinter2
- https://code.google.com/archive/p/android4me/downloads
* HFS Explorer. We use version 0.21.
- https://sourceforge.net/projects/catacombae/files/HFSExplorer/0.21/
- https://github.com/unsound/hfsexplorer/releases (newer versions)
* Yet Another Java Service Wrapper. We use version 12.12 - Only to build Ghidra package.
- https://sourceforge.net/projects/yajsw/files/yajsw/yajsw-stable-12.12/
* Eclipse PDE - Environment for developing the GhidraDev plugin.
@ -117,16 +114,12 @@ The Gradle task to be executed, in this case _init_, is unimportant. The point i
the `fetchDependencies.gradle` script. If it ran correctly you will have a new `~/git/ghidra/dependencies/`
directory populated with the following files:
* flatRepo/AXMLPrinter2.jar
* flatRepo/csframework.jar
* flatRepo/dex-ir-2.0.jar
* flatRepo/dex-reader-2.0.jar
* flatRepo/dex-reader-api-2.0.jar
* flatRepo/dex-tools-2.0.jar
* flatRepo/dex-translator-2.0.jar
* flatRepo/dex-writer-2.0.jar
* flatRepo/hfsx.jar
* flatRepo/hfsx_dmglib.jar
* flatRepo/iharder-base64.jar
* GhidraDev/cdt-8.6.0.zip
* GhidraDev/PyDev 6.3.1.zip
* GhidraServer/yajsw-stable-12.12.zip
@ -168,21 +161,6 @@ cd ~/git/ghidra/dependencies/flatRepo
curl -OL https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/android4me/AXMLPrinter2.jar
```
#### Get Dependencies for DMG:
Download `hfsexplorer-0_21-bin.zip` from www.catacombae.org.
Unpack the `lib` directory to `~/git/ghidra/dependencies/flatRepo`:
```bash
cd ~/Downloads # Or wherever
curl -OL https://sourceforge.net/projects/catacombae/files/HFSExplorer/0.21/hfsexplorer-0_21-bin.zip
mkdir hfsx
cd hfsx
unzip ../hfsexplorer-0_21-bin.zip
cd lib
cp csframework.jar hfsx_dmglib.jar hfsx.jar iharder-base64.jar ~/git/ghidra/dependencies/flatRepo/
```
#### Get Dependencies for GhidraServer
Building the GhidraServer requires "Yet another Java service wrapper" (yajsw) version 12.12.

View file

@ -41,6 +41,10 @@ sourceSets {
eclipse.classpath.plusConfigurations += [configurations.dmgCompile]
repositories {
flatDir name: "flat", dirs:["data/lib"]
}
dependencies {
dmgCompile ':csframework@jar'
dmgCompile ':hfsx@jar'

View file

@ -3,11 +3,11 @@
##MODULE IP: LGPL 2.1
##MODULE IP: Public Domain
Module.manifest||Public Domain||||END|
data/lib/catacombae_csframework.jar||LGPL 2.1||||END|
data/lib/catacombae_hfsx.jar||GPL 3||||END|
data/lib/catacombae_hfsx_dmglib.jar||GPL 3||||END|
data/lib/catacombae_iharder-base64.jar||GPL 3||||END|
data/lib/csframework.jar||LGPL 2.1||||END|
data/lib/hfsexplorer-0_21-src.zip||GPL 3||||END|
data/lib/hfsx.jar||GPL 3||||END|
data/lib/hfsx_dmglib.jar||GPL 3||||END|
data/lib/iharder-base64.jar||GPL 3||||END|
data/os/win32/llio_amd64.dll||GPL 3||||END|
data/os/win32/llio_i386.dll||GPL 3||||END|
data/os/win32/llio_ia64.dll||GPL 3||||END|

View file

@ -947,7 +947,7 @@ public class DataTypeMergeManager implements MergeResolver {
}
if (resolvedDt != null) {
return PointerDataType.getPointer(resolvedDt,
pointerDt.isDynamicallySized() ? -1 : pointerDt.getLength());
pointerDt.hasLanguageDependantLength() ? -1 : pointerDt.getLength());
}
}
return null;

View file

@ -456,7 +456,7 @@ public class DataTypeUtils {
if (dataType instanceof Pointer) {
Pointer pdt = (Pointer) dataType;
return new PointerDataType(copyToNamedBaseDataType(pdt.getDataType(), dtm),
pdt.isDynamicallySized() ? -1 : pdt.getLength(), dtm);
pdt.hasLanguageDependantLength() ? -1 : pdt.getLength(), dtm);
}
else if (dataType instanceof Array) {
Array adt = (Array) dataType;

View file

@ -40,11 +40,6 @@ public class StackPieceDataType extends DataTypeImpl {
return var.getDataType().getName() + ":" + pieceLen + " (piece)";
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -165,9 +165,4 @@ public abstract class AbstractLeb128DataType extends BuiltIn implements Dynamic
return false;
}
@Override
public boolean isDynamicallySized() {
return true;
}
}

View file

@ -44,11 +44,6 @@ public class DwarfEncodingModeDataType extends BuiltIn {
super(CategoryPath.ROOT, "dwfenc", dtm);
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -67,11 +67,6 @@ public class PcRelative31AddressDataType extends BuiltIn {
return name;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public int getLength() {
return 4;

View file

@ -84,8 +84,17 @@ public class FdeTable {
DataType encodedDt = decoder.getDataType(prog);
if (encodedDt.isDynamicallySized()) {
throw new ExceptionHandlerFrameException("Cannot build FDE structure with dynamically-encoded values");
if (encodedDt.getLength() <= 0) {
throw new ExceptionHandlerFrameException(
"Cannot build FDE structure with Dynamic or Void value type: " +
encodedDt.getClass().getName());
}
if (encodedDt.hasLanguageDependantLength()) {
// Should avoid using value types whose size fluctuates with Data Organization
throw new ExceptionHandlerFrameException(
"Cannot build FDE structure with dynamically-sized value type: " +
encodedDt.getClass().getName());
}
fdeTableEntry.deleteAll();

View file

@ -171,21 +171,48 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
!SystemUtilities.isEqual(fullDTCAt.getFieldName(), partDTC.getFieldName())) {
return false;
}
DataType partDT = partDTC.getDataType();
DataType fullDT = fullDTCAt.getDataType();
if (doRelaxedCompare(partDT, fullDT, visitedDataTypes) == RENAME_AND_ADD) {
if (!isMemberFieldPartiallyCompatible(fullDTCAt, partDTC, visitedDataTypes)) {
return false;
}
}
if ( part.getFlexibleArrayComponent() != null ) {
return full.getFlexibleArrayComponent() != null
&& doRelaxedCompare(part.getFlexibleArrayComponent().getDataType(),
full.getFlexibleArrayComponent().getDataType(), visitedDataTypes) != RENAME_AND_ADD;
return full.getFlexibleArrayComponent() != null &&
isMemberFieldPartiallyCompatible(full.getFlexibleArrayComponent(),
part.getFlexibleArrayComponent(), visitedDataTypes);
}
return true;
}
boolean isMemberFieldPartiallyCompatible(DataTypeComponent fullDTC, DataTypeComponent partDTC,
Set<Long> visitedDataTypes) {
DataType partDT = partDTC.getDataType();
DataType fullDT = fullDTC.getDataType();
ConflictResult dtCompResult = doRelaxedCompare(partDT, fullDT, visitedDataTypes);
switch (dtCompResult) {
case RENAME_AND_ADD:
// The data type of the field in the 'full' structure is completely
// different than the field in the 'part' structure, therefore
// the candidate 'part' structure is not a partial definition of the full struct
return false;
case REPLACE_EXISTING:
// Return true (meaning the field from the 'full' struct is the same or better
// than the field from the 'part' structure) if the components are size compatible.
// This is an intentionally fuzzy match to allow structures with fields
// that are generally the same at a binary level to match.
// For example, the same structure defined in 2 separate compile units with
// slightly different types for the field (due to different compiler options
// or versions or languages)
return fullDTC.getLength() >= partDTC.getLength();
case USE_EXISTING:
default:
// the data type of the field in the 'full' structure is the same as
// or a better version of the field in the 'part' structure.
return true;
}
}
private DataTypeComponent getBitfieldByOffsets(Structure full, DataTypeComponent partDTC) {
BitFieldDataType partBF = (BitFieldDataType) partDTC.getDataType();

View file

@ -140,14 +140,11 @@ public class DWARFDataTypeImporter {
if (result != null) {
return result;
}
// Query the dwarfDTM for plain Ghidra dataTypes that were previously
// registered in a different import session.
DataType alreadyImportedDT = dwarfDTM.getDataType(diea.getOffset(), null);
if (alreadyImportedDT != null &&
!(alreadyImportedDT instanceof Array &&
((Array) alreadyImportedDT).getNumElements() == 1)) {
// HACK: don't re-use previously imported single-element
// Ghidra array datatype because they may have actually been an empty array
// definition we need the special meta-data flag DWARFDataType.isEmptyArrayType
// which is only available in a freshly created DWARFDataType.
if (shouldReuseAlreadyImportedDT(alreadyImportedDT)) {
return new DWARFDataType(alreadyImportedDT, null, diea.getOffset());
}
@ -223,6 +220,28 @@ public class DWARFDataTypeImporter {
return result;
}
/**
* Returns true if the previously imported data type should be reused.
* <p>
* Don't re-use previously imported single-element
* Ghidra array datatypes because they may have actually been an empty array
* definition and we need the special meta-data flag DWARFDataType.isEmptyArrayType
* which is only available in a freshly created DWARFDataType.
* <p>
* Don't re-use empty structs (isNotYetDefined) to ensure that newer
* definitions of the same struct are given a chance to be resolved()
* into the DTM.
*
* @param alreadyImportedDT dataType to check
* @return boolean true if its okay to reuse the data type
*/
private boolean shouldReuseAlreadyImportedDT(DataType alreadyImportedDT) {
return alreadyImportedDT != null &&
!alreadyImportedDT.isNotYetDefined() &&
!(alreadyImportedDT instanceof Array &&
((Array) alreadyImportedDT).getNumElements() == 1);
}
/*
* when a clone()'d datatype is created, update the current mappings to
* point to the new instance instead of the old instance.
@ -1418,7 +1437,7 @@ public class DWARFDataTypeImporter {
for (int i = ptrChainTypes.size() - 1; i >= 0; i--) {
Pointer origPtr = ptrChainTypes.get(i);
result = new PointerDataType(result,
origPtr.isDynamicallySized() ? -1 : origPtr.getLength(), dataTypeManager);
origPtr.hasLanguageDependantLength() ? -1 : origPtr.getLength(), dataTypeManager);
}
return result;

View file

@ -34,11 +34,6 @@ class MSRichProductBuildNumberDataType extends DataTypeImpl {
this.compid = compid;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -34,11 +34,6 @@ class MSRichProductIDDataType extends DataTypeImpl {
this.compid = compid;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -34,7 +34,7 @@ class MSRichProductInfoDataType extends StructureDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}

View file

@ -128,7 +128,7 @@ public class PERichTableDataType extends DynamicDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}
@ -193,7 +193,7 @@ public class PERichTableDataType extends DynamicDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}
@ -259,7 +259,7 @@ public class PERichTableDataType extends DynamicDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}

View file

@ -34,11 +34,6 @@ class RichObjectCountDataType extends DataTypeImpl {
this.count = count;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -35,7 +35,7 @@ class RichTableRecordDataType extends StructureDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}

View file

@ -21,9 +21,9 @@ package ghidra.app.util.datatype.microsoft;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.ProcessorContext;
import ghidra.program.model.mem.MemBuffer;
import ghidra.util.*;
import ghidra.util.Conv;
import ghidra.util.DataConverter;
import ghidra.util.classfinder.ClassTranslator;
/**
@ -76,11 +76,6 @@ public class GuidDataType extends BuiltIn {
return SIZE;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public String getDescription() {
return NAME;
@ -130,8 +125,9 @@ public class GuidDataType extends BuiltIn {
retVal += Conv.toHexString((short) (data[1] >> 16)) + delim;
for (int i = 0; i < 4; i++) {
retVal += Conv.toHexString((byte) (data[2] >> i * 8));
if (i == 1)
if (i == 1) {
retVal += delim;
}
}
for (int i = 0; i < 4; i++) {
retVal += Conv.toHexString((byte) (data[3] >> i * 8));
@ -166,6 +162,7 @@ public class GuidDataType extends BuiltIn {
return NAME;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;

View file

@ -31,11 +31,6 @@ public class HTMLResourceDataType extends BuiltIn implements Dynamic {
super(null, "HTML-Resource", dtm);
}
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -36,6 +36,7 @@ public class ElfDataType extends FactoryStructureDataType {
super("ELF", dtm);
}
@Override
public String getMnemonic(Settings settings) {
return "ELF";
}
@ -44,13 +45,6 @@ public class ElfDataType extends FactoryStructureDataType {
public String getDescription() {
return "ELF Data Type";
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
public boolean isDynamicallySized() {
return true;
}
@Override
protected void populateDynamicStructure(MemBuffer buf, Structure struct) {

View file

@ -31,7 +31,6 @@ import ghidra.util.exception.DuplicateNameException;
* A datatype for creating portable executable data structures.
*/
public class PeDataType extends FactoryStructureDataType {
private final static long serialVersionUID = 1;
/**
* Constructs a new PE datatype.
@ -53,14 +52,6 @@ public class PeDataType extends FactoryStructureDataType {
public String getDescription() {
return "Windows Portable Executable Data Type";
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
protected void populateDynamicStructure(MemBuffer buf, Structure struct) {

View file

@ -165,11 +165,10 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
* @throws DWARFException
*/
@Test
@SuppressWarnings("unused")
public void testStructDanglingDecl() throws CancelledException, IOException, DWARFException {
// CU1
DebugInfoEntry declDIE = newDeclStruct("mystruct").create(cu);
newDeclStruct("mystruct").create(cu);
// CU2
DebugInfoEntry intDIE = addInt(cu2);
@ -188,11 +187,85 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
assertNull(structdt2);
}
/**
/*
* This test is more about the StructureDB implementation updating ordinals of
* components correctly when an embedded datatype changes size.
* <p>
* The initial version of struct2.guardfield will have an ordinal of 15 to account for
* all the invisible undefines that are between the first field and the guardfield at offset
* 16. When the data type for struct1 is overwritten with new information that
* changes it size, the undefines are no longer needed and the ordinal of guardfield should
* just be 1.
*/
@Test
public void testStructDeclThenGrow() throws CancelledException, IOException, DWARFException {
// CU1
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry struct1Decl = newDeclStruct("struct1").create(cu);
DebugInfoEntry struct2 = newStruct("struct2", 20).create(cu);
newMember(struct2, "struct1field", struct1Decl, 0).create(cu);
newMember(struct2, "guardfield", intDIE, 16).create(cu);
// CU2
DebugInfoEntry int2DIE = addInt(cu2);
DebugInfoEntry struct1Impl = newStruct("struct1", 16).create(cu2);
newMember(struct1Impl, "f1", int2DIE, 0).create(cu2);
newMember(struct1Impl, "f2", int2DIE, 4).create(cu2);
newMember(struct1Impl, "f3", int2DIE, 8).create(cu2);
newMember(struct1Impl, "f4", int2DIE, 12).create(cu2);
importAllDataTypes();
Structure struct2dt = (Structure)dataMgr.getDataType(rootCP, "struct2");
assertEquals(2, struct2dt.getNumComponents());
assertEquals(2, struct2dt.getNumDefinedComponents());
}
@Test
public void testStructDeclThatIsLaterDefined()
throws CancelledException, IOException, DWARFException {
// CU1
// struct structA; // fwd decl
// struct structB { structA struct1field; int guardfield; }
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry structADecl = newDeclStruct("structA").create(cu);
DebugInfoEntry structB = newStruct("structB", 20).create(cu);
newMember(structB, "structAfield", structADecl, 0).create(cu);
newMember(structB, "guardfield", intDIE, 16).create(cu);
// CU2
// struct structB { structA struct1field; int guardfield; }
// struct structA { int f1, f2, f3, f4; }
// Redefine structB with the same info, but to a fully
// specified structA instance instead of missing fwd decl.
// The order of the DIE records is important. The structure (structB)
// containing the problematic structA needs to be hit first so we can
// test that cached types are handled correctly.
DebugInfoEntry int2DIE = addInt(cu2);
DebugInfoEntry structB_cu2 = newStruct("structB", 20).create(cu2);
newMember(structB_cu2, "structAfield", getForwardOffset(cu2, 2), 0).create(cu2);
newMember(structB_cu2, "guardfield", int2DIE, 16).create(cu2);
DebugInfoEntry structA_cu2 = newStruct("structA", 16).create(cu2);
newMember(structA_cu2, "f1", int2DIE, 0).create(cu2);
newMember(structA_cu2, "f2", int2DIE, 4).create(cu2);
newMember(structA_cu2, "f3", int2DIE, 8).create(cu2);
newMember(structA_cu2, "f4", int2DIE, 12).create(cu2);
importAllDataTypes();
Structure structAdt = (Structure) dataMgr.getDataType(rootCP, "structA");
Structure structBdt = (Structure) dataMgr.getDataType(rootCP, "structB");
assertEquals(2, structBdt.getNumComponents());
assertEquals(4, structAdt.getNumComponents());
}
/*
* Test structure definition when the same structure is defined in two different CUs.
* @throws CancelledException
* @throws IOException
* @throws DWARFException
*/
@Test
public void testStructDup() throws CancelledException, IOException, DWARFException {
@ -648,6 +721,49 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
}
/*
* Test flex array where dims were specified with no value, relying on
* default.
*/
@Test
public void testStructFlexarray_noValue()
throws CancelledException, IOException, DWARFException {
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry arrayDIE = newArray(cu, intDIE, true, -1);
DebugInfoEntry structDIE = newStruct("mystruct", 100).create(cu);
newMember(structDIE, "f1", intDIE, 0).create(cu);
newMember(structDIE, "flexarray", arrayDIE, 100).create(cu);
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent());
}
/*
* Test flex array where dims were specified using a count=0 value instead of a
* upperbound=-1.
*/
@Test
public void testStructFlexarray_0count()
throws CancelledException, IOException, DWARFException {
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry arrayDIE = newArrayUsingCount(cu, intDIE, 0);
DebugInfoEntry structDIE = newStruct("mystruct", 100).create(cu);
newMember(structDIE, "f1", intDIE, 0).create(cu);
newMember(structDIE, "flexarray", arrayDIE, 100).create(cu);
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent());
}
@Test
public void testStructInteriorFlexarray()
throws CancelledException, IOException, DWARFException {
@ -691,7 +807,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
List<DataTypeComponent> bitfields = getBitFieldComponents(structdt);
Set<Integer> expectedBitfieldSizes = new HashSet<Integer>(Set.of(2, 3, 9));
Set<Integer> expectedBitfieldSizes = new HashSet<>(Set.of(2, 3, 9));
for (DataTypeComponent dtc : bitfields) {
BitFieldDataType bfdt = (BitFieldDataType) dtc.getDataType();
expectedBitfieldSizes.remove(bfdt.getBitSize());
@ -824,6 +940,9 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
// anon struct
}
/*
* Test array defintions that use upper_bound attribute
*/
@Test
public void testArray() throws CancelledException, IOException, DWARFException {
DebugInfoEntry intDIE = addInt(cu);
@ -833,8 +952,24 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
Array arr = (Array) dwarfDTM.getDataType(arrayDIE.getOffset(), null);
assertNotNull(arr);
assertEquals(11, arr.getNumElements());
}
/*
* Tests array definitions that use count attribute instead of upper_bounds
*/
@Test
public void testArrayWithCountAttr() throws CancelledException, IOException, DWARFException {
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry arrayDIE = newArrayUsingCount(cu, intDIE, 10);
importAllDataTypes();
Array arr = (Array) dwarfDTM.getDataType(arrayDIE.getOffset(), null);
assertNotNull(arr);
assertEquals(10, arr.getNumElements());
}
// not implemented yet
public void testSubr() {
// func ptrs

View file

@ -16,7 +16,7 @@
package ghidra.app.util.bin.format.dwarf4;
import static ghidra.app.util.bin.format.dwarf4.encoding.DWARFAttribute.*;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.io.IOException;
@ -264,9 +264,16 @@ public class DWARFTestBase extends AbstractGhidraHeadedIntegrationTest {
DebugInfoEntry dataType, int offset) {
assertTrue(
dataType == null || dataType.getCompilationUnit() == parentStruct.getCompilationUnit());
return newMember(parentStruct, fieldName, dataType.getOffset(), offset);
}
protected DIECreator newMember(DebugInfoEntry parentStruct, String fieldName,
long memberDIEOffset, int offset) {
DIECreator field =
new DIECreator(DWARFTag.DW_TAG_member).addString(DW_AT_name, fieldName).addRef(
DW_AT_type, dataType).setParent(parentStruct);
new DIECreator(DWARFTag.DW_TAG_member).addString(DW_AT_name, fieldName)
.addRef(
DW_AT_type, memberDIEOffset)
.setParent(parentStruct);
if (offset != -1) {
field.addInt(DW_AT_data_member_location, offset);
}
@ -285,11 +292,11 @@ public class DWARFTestBase extends AbstractGhidraHeadedIntegrationTest {
protected DebugInfoEntry newArray(MockDWARFCompilationUnit dcu, DebugInfoEntry baseTypeDIE,
boolean elideEmptyDimRangeValue, int... dimensions) {
DebugInfoEntry arrayType = new DIECreator(DWARFTag.DW_TAG_array_type) //
DebugInfoEntry arrayType = new DIECreator(DWARFTag.DW_TAG_array_type)
.addRef(DW_AT_type, baseTypeDIE).create(dcu);
for (int dimIndex = 0; dimIndex < dimensions.length; dimIndex++) {
int dim = dimensions[dimIndex];
DIECreator dimDIE = new DIECreator(DWARFTag.DW_TAG_subrange_type) //
DIECreator dimDIE = new DIECreator(DWARFTag.DW_TAG_subrange_type)
.setParent(arrayType);
if (dim != -1 || !elideEmptyDimRangeValue) {
dimDIE.addInt(DW_AT_upper_bound, dimensions[dimIndex]);
@ -299,6 +306,18 @@ public class DWARFTestBase extends AbstractGhidraHeadedIntegrationTest {
return arrayType;
}
protected DebugInfoEntry newArrayUsingCount(MockDWARFCompilationUnit dcu,
DebugInfoEntry baseTypeDIE, int count) {
DebugInfoEntry arrayType = new DIECreator(DWARFTag.DW_TAG_array_type)
.addRef(DW_AT_type, baseTypeDIE)
.create(dcu);
DIECreator dimDIE = new DIECreator(DWARFTag.DW_TAG_subrange_type)
.setParent(arrayType);
dimDIE.addInt(DW_AT_count, count);
dimDIE.create(dcu);
return arrayType;
}
protected Address addr(long l) {
return space.getAddress(l);
}

View file

@ -111,64 +111,64 @@
<BLOCKQUOTE>
<BLOCKQUOTE>
<UL>
<LI><A name="Compact_Hierarchical">
<LI><A name="Compact Hierarchical"/>
<B>Compact Hierarchical</B> is the <B>TidierTree Layout Algorithm</B>. It builds a tree
structure and attempts to reduce horizontal space.</LI>
<LI><A name="Hierarchical">
<B>Hierarchical</B> is a basic Tree algorithm. It prioritizes 'important' edges while
constructing the tree.</LI>
<LI><A name="Hierarchical"/>
<B>Hierarchical</B> is a basic Tree algorithm with the root(s) at the top.</LI>
<LI><A name="Compact Radial">
<LI><A name="Compact Radial"/>
<B>Compact Radial</B> is the <B>TidierTree Layout Algorithm</B> with the root(s) at the
center and child vertices radiating outwards.</LI>
<LI><B>Hierarchical MinCross</B> is the <B>Sugiyama Layout Algorithm</B>. It attempts to
route edges around vertices in order to reduce crossing.There are four layering
algorithms:</LI>
<LI><A name="Hierarchical MinCross"/>
<B>Hierarchical MinCross</B> is the <B>Sugiyama Layout Algorithm with optimizations</B>. It attempts to
route edges around vertices in order to reduce crossing. There are four layering
algorithms (below)</LI>
<LI style="list-style: none">
<LI><A name="Vertical Hierarchical MinCross"/>
<B>Vertical Hierarchical MinCross</B> is the <B>Sugiyama Layout Algorithm with optimizations</B>. It attempts to
route edges around vertices in order to reduce crossing. If there is a favored EdgeType, an attempt is made to
line up those favored edges so they are vertical in the presentation. There are four layering
algorithms:</LI>
<UL>
<LI><A name="Hierarchical_MinCross_Top_Down">
<B>Top Down</B> - biases the vertices to the top</LI>
<LI><B>Top Down</B> - Biases the vertices to the top. Sources on the top row.</LI>
<LI><A name="Hierarchical_MinCross_Longest_Path">
<B>Longest Path</B> - biases the vertices to the bottom</LI>
<LI><B>Longest Path</B> - Biases the vertices to the bottom. Sinks are on the bottom row.</LI>
<LI><A name="Hierarchical_MinCross_Network_Simplex">
<B>Network Simplex</B> - layers after finding an 'optimal tree'</LI>
<LI><B>Network Simplex</B> - Layers after finding an 'optimal tree' by not considering longer edges.</LI>
<LI><A name="Hierarchical_MinCross_Coffman_Graham">
<B>Coffman Graham</B> - biases the vertices using a scheduling algorithm to minimize
length</LI>
<LI><B>Coffman Graham</B> - Biases the vertices using a scheduling algorithm to minimize
length. Tends to balance the graph around the middle.</LI>
</UL>
</LI>
<LI><A name="Circle">
<B>Circle</B> will arrange vertices in a Circle. If there are not too many edges (less
than specified in the jungrapht.circle.reduceEdgeCrossingMaxEdges property with a default
of 200), it will attempt to reduce edge crossing by rearranging the vertices.</LI>
<LI><A name="Circle"/>
<B>Circle</B> will arrange vertices in a Circle. </LI>
<LI><A name="Force_Balanced">
<LI><A name="Force Balanced"/>
<B>Force Balanced</B> is a <B>Force Directed Layout Algorithm</B> using the the <B>Kamada
Kawai</B> approach. It attempts to balance the graph by considering vertices and edge
Kawai</B> algorithm. It attempts to balance the graph by considering vertices and edge
connections.</LI>
<LI><A name="Force_Directed">
<LI><A name="Force Directed"/>
<B>Force Directed</B> is a <B>Force Directed Layout Algorithm</B> using the
<B>Fructermann Reingold</B> approach. It pushes unconnected vertices apart and draws
connected vertices together.</LI>
<LI><A name="Radial">
<LI><A name="Radial"/>
<B>Radial</B> is a Tree structure with the root(s) at the center and child vertices
radiating outwards.</LI>
<LI><A name="Balloon">
<LI><A name="Balloon"/>
<B>Balloon</B> is a Tree structure with the root(s) at the centers of circles in a radial
pattern</LI>
<LI><A name="Gem__Graph_Embedder_">
<B>GEM</B> is a Force Directed layout with locally separated components</LI>
<LI><A name="GEM"/>
<B>GEM (Graph Embedder)</B> is a Force Directed layout with locally separated components</LI>
</UL>
</BLOCKQUOTE>
</BLOCKQUOTE>

View file

@ -51,7 +51,6 @@ import org.jungrapht.visualization.renderers.Renderer;
import org.jungrapht.visualization.renderers.Renderer.VertexLabel;
import org.jungrapht.visualization.renderers.Renderer.VertexLabel.Position;
import org.jungrapht.visualization.selection.MutableSelectedState;
import org.jungrapht.visualization.selection.VertexEndpointsSelectedEdgeSelectedState;
import org.jungrapht.visualization.transform.*;
import org.jungrapht.visualization.transform.shape.MagnifyImageLensSupport;
import org.jungrapht.visualization.transform.shape.MagnifyShapeTransformer;
@ -755,7 +754,17 @@ public class DefaultGraphDisplay implements GraphDisplay {
for (String layoutName : names) {
ActionState<String> state = new ActionState<>(layoutName,
DefaultDisplayGraphIcons.LAYOUT_ALGORITHM_ICON, layoutName);
state.setHelpLocation(new HelpLocation(ACTION_OWNER, layoutName));
// condense hierarchical action help to the top-level help description
String anchor = layoutName;
if (layoutName.contains(LayoutFunction.VERT_MIN_CROSS)) {
anchor = LayoutFunction.VERT_MIN_CROSS;
}
else if (layoutName.contains(LayoutFunction.MIN_CROSS)) {
anchor = LayoutFunction.MIN_CROSS;
}
state.setHelpLocation(new HelpLocation(ACTION_OWNER, anchor));
actionStates.add(state);
}
return actionStates;

View file

@ -41,18 +41,20 @@ class LayoutFunction
static final String CIRCLE = "Circle";
static final String TIDIER_TREE = "Compact Hierarchical";
static final String TIDIER_RADIAL_TREE = "Compact Radial";
static final String MIN_CROSS = "Hierarchical MinCross"; //not an alg, just a parent category
static final String MIN_CROSS_TOP_DOWN = "Hierarchical MinCross Top Down";
static final String MIN_CROSS_LONGEST_PATH = "Hierarchical MinCross Longest Path";
static final String MIN_CROSS_NETWORK_SIMPLEX = "Hierarchical MinCross Network Simplex";
static final String MIN_CROSS_COFFMAN_GRAHAM = "Hierarchical MinCross Coffman Graham";
static final String EXP_MIN_CROSS_TOP_DOWN = "Experimental Hierarchical MinCross Top Down";
static final String EXP_MIN_CROSS_LONGEST_PATH = "Experimental Hierarchical MinCross Longest Path";
static final String EXP_MIN_CROSS_NETWORK_SIMPLEX = "Experimental Hierarchical MinCross Network Simplex";
static final String EXP_MIN_CROSS_COFFMAN_GRAHAM = "Experimental Hierarchical MinCross Coffman Graham";
static final String VERT_MIN_CROSS = "Vertical Hierarchical MinCross"; //not an alg, just a parent category
static final String VERT_MIN_CROSS_TOP_DOWN = "Vertical Hierarchical MinCross Top Down";
static final String VERT_MIN_CROSS_LONGEST_PATH = "Vertical Hierarchical MinCross Longest Path";
static final String VERT_MIN_CROSS_NETWORK_SIMPLEX = "Vertical Hierarchical MinCross Network Simplex";
static final String VERT_MIN_CROSS_COFFMAN_GRAHAM = "Vertical Hierarchical MinCross Coffman Graham";
static final String TREE = "Hierarchical";
static final String RADIAL = "Radial";
static final String BALLOON = "Balloon";
static final String GEM = "Gem (Graph Embedder)";
static final String GEM = "GEM";
Predicate<AttributedEdge> favoredEdgePredicate;
Comparator<AttributedEdge> edgeTypeComparator;
@ -66,10 +68,10 @@ class LayoutFunction
return new String[] { TIDIER_TREE, TREE,
TIDIER_RADIAL_TREE, MIN_CROSS_TOP_DOWN, MIN_CROSS_LONGEST_PATH,
MIN_CROSS_NETWORK_SIMPLEX, MIN_CROSS_COFFMAN_GRAHAM, CIRCLE,
EXP_MIN_CROSS_TOP_DOWN,
EXP_MIN_CROSS_LONGEST_PATH,
EXP_MIN_CROSS_NETWORK_SIMPLEX,
EXP_MIN_CROSS_COFFMAN_GRAHAM,
VERT_MIN_CROSS_TOP_DOWN,
VERT_MIN_CROSS_LONGEST_PATH,
VERT_MIN_CROSS_NETWORK_SIMPLEX,
VERT_MIN_CROSS_COFFMAN_GRAHAM,
KAMADA_KAWAI, FRUCTERMAN_REINGOLD, RADIAL, BALLOON, GEM
};
}
@ -112,25 +114,25 @@ class LayoutFunction
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
.edgeComparator(edgeTypeComparator)
.layering(Layering.COFFMAN_GRAHAM);
case EXP_MIN_CROSS_TOP_DOWN:
case VERT_MIN_CROSS_TOP_DOWN:
return EiglspergerLayoutAlgorithm
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
.edgeComparator(edgeTypeComparator)
.favoredEdgePredicate(favoredEdgePredicate)
.layering(Layering.TOP_DOWN);
case EXP_MIN_CROSS_LONGEST_PATH:
case VERT_MIN_CROSS_LONGEST_PATH:
return EiglspergerLayoutAlgorithm
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
.edgeComparator(edgeTypeComparator)
.favoredEdgePredicate(favoredEdgePredicate)
.layering(Layering.LONGEST_PATH);
case EXP_MIN_CROSS_NETWORK_SIMPLEX:
case VERT_MIN_CROSS_NETWORK_SIMPLEX:
return EiglspergerLayoutAlgorithm
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
.edgeComparator(edgeTypeComparator)
.favoredEdgePredicate(favoredEdgePredicate)
.layering(Layering.NETWORK_SIMPLEX);
case EXP_MIN_CROSS_COFFMAN_GRAHAM:
case VERT_MIN_CROSS_COFFMAN_GRAHAM:
return EiglspergerLayoutAlgorithm
.<AttributedVertex, AttributedEdge> edgeAwareBuilder()
.edgeComparator(edgeTypeComparator)

View file

@ -27,12 +27,12 @@ import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.PeLoader;
import ghidra.app.util.pdb.PdbLocator;
import ghidra.app.util.pdb.PdbProgramAttributes;
import ghidra.app.util.pdb.pdbapplicator.*;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicator;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorOptions;
import ghidra.framework.Application;
import ghidra.framework.options.OptionType;
import ghidra.framework.options.Options;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.data.CharsetInfo;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
@ -92,105 +92,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
"If checked, specifically searching for PDB in PE-Header-Specified Location.";
private boolean includePeSpecifiedPdbPath = false;
//==============================================================================================
// Logging options
//==============================================================================================
// Perform logging of PDB information for debugging/development.
// NOTE: This logging mechanism is not intended to live the full life of this tool, but to
// aid in getting feedback from the field during its early development.
private static final String OPTION_NAME_PDB_READER_ANALYZER_LOGGING =
"[PDB Reader/Analyzer Debug Logging]";
private static final String OPTION_DESCRIPTION_PDB_READER_ANALYZER_LOGGING =
"If checked, logs information to the pdb.analyzer.log file for debug/development.";
private boolean pdbLogging = false;
//==============================================================================================
// PdbReader options
//==============================================================================================
// Sets the one-byte Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-specific Charset.
private static final String OPTION_NAME_ONE_BYTE_CHARSET_NAME = "PDB One-Byte Charset Name";
private static final String OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME =
"Charset used for processing of one-byte (or multi) encoded Strings: " +
PdbReaderOptions.getOneByteCharsetNames();
private String oneByteCharsetName = CharsetInfo.UTF8;
// Sets the wchar_t Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-program-specific Charset.
private static final String OPTION_NAME_WCHAR_CHARSET_NAME = "PDB Wchar_t Charset Name";
private static final String OPTION_DESCRIPTION_WCHAR_CHARSET_NAME =
"Charset used for processing of wchar_t encoded Strings: " +
PdbReaderOptions.getTwoByteCharsetNames();
private String wideCharCharsetName = CharsetInfo.UTF16;
//==============================================================================================
// PdbApplicator options
//==============================================================================================
// Applicator Restrictions.
private static final String OPTION_NAME_PROCESSING_RESTRICTIONS = "Processing Restrictions";
private static final String OPTION_DESCRIPTION_PROCESSING_RESTRICTIONS =
"Restrictions on applicator processing.";
private static PdbApplicatorRestrictions restrictions;
// Apply Code Block Comments.
private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
"Apply Code Scope Block Comments";
private static final String OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
"If checked, pre/post-comments will be applied when code scope blocks are specified.";
private boolean applyCodeScopeBlockComments;
// Apply Instruction Labels information.
private static final String OPTION_NAME_APPLY_INSTRUCTION_LABELS = "Apply Instruction Labels";
private static final String OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS =
"If checked, labels associated with instructions will be applied.";
private boolean applyInstructionLabels;
// Attempt to map address using existing mangled symbols.
private static final String OPTION_NAME_ADDRESS_REMAP = "Address Remap Using Existing Symbols";
private static final String OPTION_DESCRIPTION_ADDRESS_REMAP =
"If checked, attempts to remap address to those matching existing public symbols.";
private boolean remapAddressUsingExistingPublicMangledSymbols;
// Allow a mangled symbol to be demoted from being a primary symbol if another symbol and
// associated explicit data type will be laid down at the location. This option exists
// because we expect the PDB explicit data type will be more accurate than trying to
// have the demangler lay down the data type.
private static final String OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY =
"Allow demote mangled symbol from primary";
private static final String OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY =
"If checked, allows a mangled symbol to be demoted from primary if a possibly " +
"better data type can be laid down with a nonmangled symbol.";
private boolean allowDemotePrimaryMangledSymbol;
// Apply Function Variables
private static final String OPTION_NAME_APPLY_FUNCTION_VARIABLES = "Apply Function Variables";
private static final String OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES =
"If checked, attempts to apply function parameters and local variables for program functions.";
private boolean applyFunctionVariables;
// Sets the composite layout.
// Legacy
// - similar to existing DIA-based PDB Analyzer, only placing current composite direct
// members (none from parent classes.
// Warning: the remaining experimental layout choices may not be kept and are not guaranteed
// to result in data types that will be compatible with future Ghidra releases:
// Complex with Basic Fallback
// - Performs Complex layout, but if the current class has no parent classes, it will not
// encapsulate the current class's 'direct' members.
// Simple
// - Performs Complex layout, except in rare instances where , so in most cases is the same
// as 'Complex with Basic Fallback' layout.
// Complex
// - Puts all current class members and 'direct' parents' 'direct' components into an
// encapsulating 'direct' container
private static final String OPTION_NAME_COMPOSITE_LAYOUT = "Composite Layout Choice";
private static final String OPTION_DESCRIPTION_COMPOSITE_LAYOUT =
"Legacy layout like original PDB Analyzer. Warning: other choices have no compatibility" +
" guarantee with future Ghidra releases or minor PDB Analyzer changes";
private ObjectOrientedClassLayout compositeLayout;
//==============================================================================================
// Additional instance data
//==============================================================================================
@ -266,8 +167,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
return true;
}
setPdbLogging(log);
String pdbFilename;
if (doForceLoad) {
if (!confirmFile(forceLoadFile)) {
@ -365,48 +264,11 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
options.registerOption(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath, null,
OPTION_DESCRIPTION_INCLUDE_PE_PDB_PATH);
// PdbReaderOptions
getPdbReaderOptions();
options.registerOption(OPTION_NAME_PDB_READER_ANALYZER_LOGGING, pdbLogging, null,
OPTION_DESCRIPTION_PDB_READER_ANALYZER_LOGGING);
if (developerMode) {
options.registerOption(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName, null,
OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME);
options.registerOption(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName, null,
OPTION_DESCRIPTION_WCHAR_CHARSET_NAME);
}
pdbReaderOptions.registerOptions(options);
pdbApplicatorOptions.registerAnalyzerOptions(options);
// PdbApplicatorOptions
getPdbApplicatorOptions();
if (developerMode) {
options.registerOption(OPTION_NAME_PROCESSING_RESTRICTIONS, restrictions, null,
OPTION_DESCRIPTION_PROCESSING_RESTRICTIONS);
options.registerOption(OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS,
applyCodeScopeBlockComments, null,
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
options.registerOption(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels,
null, OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS);
// The remap capability is not completely implemented... do not turn on.
options.registerOption(OPTION_NAME_ADDRESS_REMAP,
remapAddressUsingExistingPublicMangledSymbols, null,
OPTION_DESCRIPTION_ADDRESS_REMAP);
options.registerOption(OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY,
allowDemotePrimaryMangledSymbol, null,
OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY);
// Function params and local implementation is not complete... do not turn on.
options.registerOption(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables,
null, OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES);
// Object-oriented composite layout is fairly far along, but its use will likely not
// be forward compatible with future Ghidra work in this area; i.e., it might leave
// the data type manager in a bad state for future revisions. While the current
// layout mechanism might work, I will likely change it to, instead, create a
// syntactic intermediate representation before creating the final layout. This will
// aid portability between tool chains and versions and yield a standard way of
// data-basing and presenting the information to a user.
options.registerOption(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout, null,
OPTION_DESCRIPTION_COMPOSITE_LAYOUT);
}
pdbReaderOptions.loadOptions(options);
pdbApplicatorOptions.loadAnalyzerOptions(options);
}
@Override
@ -426,33 +288,8 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
includePeSpecifiedPdbPath =
options.getBoolean(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath);
// PdbReaderOptions
pdbLogging = options.getBoolean(OPTION_NAME_PDB_READER_ANALYZER_LOGGING, pdbLogging);
if (developerMode) {
oneByteCharsetName =
options.getString(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName);
wideCharCharsetName =
options.getString(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName);
}
setPdbReaderOptions();
// PdbApplicatorOptions
if (developerMode) {
restrictions = options.getEnum(OPTION_NAME_PROCESSING_RESTRICTIONS, restrictions);
applyCodeScopeBlockComments = options.getBoolean(
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
applyInstructionLabels =
options.getBoolean(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels);
remapAddressUsingExistingPublicMangledSymbols = options.getBoolean(
OPTION_NAME_ADDRESS_REMAP, remapAddressUsingExistingPublicMangledSymbols);
allowDemotePrimaryMangledSymbol = options.getBoolean(
OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY, allowDemotePrimaryMangledSymbol);
applyFunctionVariables =
options.getBoolean(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables);
compositeLayout = options.getEnum(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout);
}
setPdbApplicatorOptions();
pdbReaderOptions.loadOptions(options);
pdbApplicatorOptions.loadAnalyzerOptions(options);
}
//==============================================================================================
@ -496,54 +333,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
return true;
}
private void setPdbLogging(MessageLog log) {
try {
PdbLog.setEnabled(pdbLogging);
}
catch (IOException e) {
// Probably could not open the file.
if (log != null) {
log.appendMsg(getName(), "IOException when trying to open PDB log file: ");
log.appendException(e);
}
}
}
private void getPdbReaderOptions() {
oneByteCharsetName = pdbReaderOptions.getOneByteCharsetName();
wideCharCharsetName = pdbReaderOptions.getTwoByteCharsetName();
}
private void setPdbReaderOptions() {
pdbReaderOptions.setOneByteCharsetForName(oneByteCharsetName);
pdbReaderOptions.setWideCharCharsetForName(wideCharCharsetName);
}
private void getPdbApplicatorOptions() {
applyCodeScopeBlockComments = PdbApplicatorOptions.DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
restrictions = PdbApplicatorOptions.DEFAULT_RESTRICTIONS;
applyInstructionLabels = PdbApplicatorOptions.DEFAULT_APPLY_INSTRUCTION_LABELS;
remapAddressUsingExistingPublicMangledSymbols =
PdbApplicatorOptions.DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
allowDemotePrimaryMangledSymbol =
PdbApplicatorOptions.DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS;
applyFunctionVariables = PdbApplicatorOptions.DEFAULT_APPLY_FUNCTION_VARIABLES;
compositeLayout = PdbApplicatorOptions.DEFAULT_CLASS_LAYOUT;
}
private void setPdbApplicatorOptions() {
pdbApplicatorOptions.setRestrictions(restrictions);
pdbApplicatorOptions.setApplyCodeScopeBlockComments(applyCodeScopeBlockComments);
pdbApplicatorOptions.setApplyInstructionLabels(applyInstructionLabels);
pdbApplicatorOptions.setRemapAddressUsingExistingPublicSymbols(
remapAddressUsingExistingPublicMangledSymbols);
pdbApplicatorOptions.setAllowDemotePrimaryMangledSymbols(allowDemotePrimaryMangledSymbol);
pdbApplicatorOptions.setApplyFunctionVariables(applyFunctionVariables);
pdbApplicatorOptions.setClassLayout(compositeLayout);
}
private boolean confirmDirectory(File path) {
return path.isDirectory();
}

View file

@ -30,11 +30,9 @@ import ghidra.util.Msg;
*/
public class PdbLog {
private static File logFile;
private static Writer nullWriter = new NullWriter();
private static Writer nullWriter;
private static Writer fileWriter;
private static Writer writer = nullWriter;
private static boolean enabled;
private static boolean enabled = false;
/**
* Enable or disable future messages to be output to the appropriate log resource. This
@ -47,15 +45,6 @@ public class PdbLog {
* @see #message(String, Supplier...)
*/
public static void setEnabled(boolean enable) throws IOException {
if (fileWriter == null) {
fileWriter = createFileWriter();
}
if (nullWriter == null) {
// Doing this here, even though statically assigned above, just in case dispose() was
// called prematurely.
nullWriter = new NullWriter();
}
writer = enable ? fileWriter : nullWriter;
enabled = enable;
}
@ -63,11 +52,11 @@ public class PdbLog {
* Outputs a message to the PDB log if messaging has been enable, else ignored. This method
* uses a format string and a variable arguments list of lambdas to allow for deferred
* processing of the message to output. Thus, when message output is disabled, the client
* does not endure as much cost in supplying a message string that is not used.
* does not endure as much cost in supplying a message string that is not used.
* @param format a {@link String} format list as would be used to a printf() function, but
* which must only specify {@code %s} {@link String} outputs.
* @param suppliers variable number of {@link Supplier}&lt;{@link String}&gt; arguments. The
* number must match the number of {@code %s} outputs in the format string.
* number must match the number of {@code %s} outputs in the format string.
* @see #setEnabled(boolean)
*/
// We know this is @SafeVarags (or SuppressWarnings("unchecked")) on potential
@ -85,6 +74,7 @@ public class PdbLog {
varArgs[i] = var;
}
try {
Writer writer = getWriter();
writer.append(String.format(format, varArgs));
writer.append("\n");
writer.flush();
@ -98,7 +88,7 @@ public class PdbLog {
* Outputs a message to the PDB log if messaging has been enable, else ignored. This method
* uses a {@link Supplier}&lt;{@link String}&gt; to allow for deferred processing of the message
* to output. Thus, when message output is disabled, the client does not endure as much cost
* in supplying a message string that is not used.
* in supplying a message string that is not used.
* @param supplier a {@link Supplier}&lt;{@link String}&gt; that supplies a {@link String}
* message to be output.
* @see #setEnabled(boolean)
@ -109,6 +99,7 @@ public class PdbLog {
}
try {
Writer writer = getWriter();
writer.append(supplier.get());
writer.append("\n");
writer.flush();
@ -125,6 +116,7 @@ public class PdbLog {
*/
public static void message(String message) {
try {
Writer writer = getWriter();
writer.append(message);
writer.append("\n");
writer.flush();
@ -187,22 +179,44 @@ public class PdbLog {
}
/**
* Creates a {@link FileWriter} for the log file to which we are planning to write, and
* deletes existing contents of the log file.
* Returns the {@link Writer} for logging.
* @return a {@link Writer} for for logging.
*/
private static Writer getWriter() throws IOException {
return enabled ? getFileWriter() : getNullWriter();
}
/**
* Returns the {@link FileWriter} for the log file. If the file is already open, it is
* returned. If not already open, it is opened and previous contents are deleted.
* @return a {@link FileWriter} for the log file.
*/
private static Writer createFileWriter() throws IOException {
/*
* Since we want this logging to be used sparingly and on a case-by-case basis, we
* delete the log at the start of each JVM session. New log writing always uses the
* same log file name with not date or process ID attributes.
*/
logFile = new File(Application.getUserSettingsDirectory(), "pdb.analyzer.log");
if (logFile.exists()) {
logFile.delete();
private static Writer getFileWriter() throws IOException {
if (fileWriter == null) {
/*
* Since we want this logging to be used sparingly and on a case-by-case basis, we
* delete the log contents upon initial opening. New log writing always uses the
* same log file name with not date or process ID attributes.
*/
File logFile = new File(Application.getUserSettingsDirectory(), "pdb.analyzer.log");
if (logFile.exists()) {
logFile.delete();
}
fileWriter = new FileWriter(logFile);
}
return new FileWriter(logFile);
return fileWriter;
}
/**
* Returns a {@link NullWriter} for the log file when chosen instead of a FileWriter. If
* one already exists, it is returned. Otherwise a new one is created.
* @return a {@link NullWriter} for the log file.
*/
private static Writer getNullWriter() {
if (nullWriter == null) {
nullWriter = new NullWriter();
}
return nullWriter;
}
private static void handleIOException(IOException exception) {
@ -215,7 +229,6 @@ public class PdbLog {
// squash
}
Msg.error(PdbLog.class, "IOException encountered; disabling writer", exception);
writer = nullWriter;
enabled = false;
}

View file

@ -15,10 +15,14 @@
*/
package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import ghidra.framework.options.Options;
import ghidra.program.model.data.CharsetInfo;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
/**
* Options used while reading a PDB ({@link AbstractPdb}) that control various aspects. These
@ -27,28 +31,103 @@ import ghidra.program.model.data.CharsetInfo;
*/
public class PdbReaderOptions extends Exception {
private static final String DEFAULT_ONE_BYTE_CHARSET_NAME = CharsetInfo.UTF8;
private static final String DEFAULT_TWO_BYTE_CHARSET_NAME = CharsetInfo.UTF16;
// Developer turn on/off options that are in still in development.
private static final boolean developerMode = false;
// Perform logging of PDB information for debugging/development.
// NOTE: This logging mechanism is not intended to live the full life of this tool, but to
// aid in getting feedback from the field during its early development.
private static final String OPTION_NAME_PDB_READER_APPLICATOR_LOGGING =
"[Dev] PDB Reader/Applicator Debug Logging";
private static final String OPTION_DESCRIPTION_PDB_READER_APPLICATOR_LOGGING =
"If checked, logs information to the pdb.analyzer.log file for debug/development.";
private static final boolean DEFAULT_PDB_READER_APPLICATOR_LOGGING = false;
private boolean pdbLogging;
// Sets the one-byte Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-specific Charset.
private static final String OPTION_NAME_ONE_BYTE_CHARSET_NAME = "PDB One-Byte Charset Name";
private static final String OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME =
"Charset used for processing of one-byte (or multi) encoded Strings: " +
PdbReaderOptions.getOneByteCharsetNames();
private static final String DEFAULT_ONE_BYTE_CHARSET_NAME = CharsetInfo.UTF8;
private String oneByteCharsetName;
// Sets the wchar_t Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-program-specific Charset.
private static final String OPTION_NAME_WCHAR_CHARSET_NAME = "PDB Wchar_t Charset Name";
private static final String OPTION_DESCRIPTION_WCHAR_CHARSET_NAME =
"Charset used for processing of wchar_t encoded Strings: " +
PdbReaderOptions.getTwoByteCharsetNames();
private static final String DEFAULT_TWO_BYTE_CHARSET_NAME = CharsetInfo.UTF16;
private String wideCharCharsetName;
//==============================================================================================
private static List<String> oneByteCharsetNames =
CharsetInfo.getInstance().getCharsetNamesWithCharSize(1);
private static List<String> twoByteCharsetNames =
CharsetInfo.getInstance().getCharsetNamesWithCharSize(2);
private String oneByteCharsetName;
private String twoByteCharsetName;
private Charset oneByteCharset;
private Charset twoByteCharset;
private Charset wideCharset;
/**
* Constructor.
*/
public PdbReaderOptions() {
setDefaults();
}
public void registerOptions(Options options) {
HelpLocation help = null;
options.registerOption(OPTION_NAME_PDB_READER_APPLICATOR_LOGGING, pdbLogging, null,
OPTION_DESCRIPTION_PDB_READER_APPLICATOR_LOGGING);
if (developerMode) {
options.registerOption(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName, help,
OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME);
options.registerOption(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName, help,
OPTION_DESCRIPTION_WCHAR_CHARSET_NAME);
}
}
public void loadOptions(Options options) {
pdbLogging = options.getBoolean(OPTION_NAME_PDB_READER_APPLICATOR_LOGGING, pdbLogging);
setPdbLogging();
if (developerMode) {
oneByteCharsetName =
options.getString(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName);
setOneByteCharsetForName(oneByteCharsetName);
wideCharCharsetName =
options.getString(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName);
setWideCharCharsetForName(wideCharCharsetName);
}
}
/**
* Set the options to their default values
*/
public void setDefaults() {
pdbLogging = DEFAULT_PDB_READER_APPLICATOR_LOGGING;
setPdbLogging();
oneByteCharsetName = DEFAULT_ONE_BYTE_CHARSET_NAME;
twoByteCharsetName = DEFAULT_TWO_BYTE_CHARSET_NAME;
wideCharCharsetName = DEFAULT_TWO_BYTE_CHARSET_NAME;
setOneByteCharsetForName(oneByteCharsetName);
setWideCharCharsetForName(twoByteCharsetName);
setWideCharCharsetForName(wideCharCharsetName);
}
private void setPdbLogging() {
try {
PdbLog.setEnabled(pdbLogging);
}
catch (IOException e) {
Msg.info(this, "Failure opening PDB log file: ", e);
}
}
/**
@ -90,8 +169,8 @@ public class PdbReaderOptions extends Exception {
if (!twoByteCharsetNames.contains(name)) {
throw new IllegalArgumentException("Unknown TwoByteCharset: " + name);
}
twoByteCharset = Charset.forName(name);
twoByteCharsetName = name;
wideCharset = Charset.forName(name);
wideCharCharsetName = name;
return this;
}
@ -108,7 +187,7 @@ public class PdbReaderOptions extends Exception {
* @return the name of the Charset.
*/
public String getTwoByteCharsetName() {
return twoByteCharsetName;
return wideCharCharsetName;
}
/**
@ -116,7 +195,7 @@ public class PdbReaderOptions extends Exception {
* @return the name of the Wchar Charset.
*/
public String getWideCharCharsetName() {
return twoByteCharsetName;
return wideCharCharsetName;
}
/**
@ -132,7 +211,7 @@ public class PdbReaderOptions extends Exception {
* @return the Charset.
*/
public Charset getTwoByteCharset() {
return twoByteCharset;
return wideCharset;
}
/**
@ -140,7 +219,6 @@ public class PdbReaderOptions extends Exception {
* @return the Wchar Charset.
*/
public Charset getWideCharCharset() {
return twoByteCharset;
return wideCharset;
}
}

View file

@ -340,7 +340,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
// TODO: Investigate. We should do this check for some classes somewhere. Should
// we do it here. Set breakpoint here to investigate.
}
classType.createLayout(applicator.getPdbApplicatorOptions().getClassLayout(),
classType.createLayout(applicator.getPdbApplicatorOptions().getCompositeLayout(),
applicator.getVbtManager(), applicator.getCancelOnlyWrappingMonitor());
}

View file

@ -192,19 +192,20 @@ public class PdbApplicator {
initializeApplyTo(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, monitorParam, logParam);
switch (applicatorOptions.getRestrictions()) {
switch (applicatorOptions.getProcessingControl()) {
case DATA_TYPES_ONLY:
processTypes();
break;
case PUBLIC_SYMBOLS_ONLY:
processPublicSymbols();
break;
case NONE:
case ALL:
processTypes();
processSymbols();
break;
default:
throw new PdbException("Invalid Restriction");
throw new PdbException("PDB: Invalid Application Control: " +
applicatorOptions.getProcessingControl());
}
if (program != null) {
@ -351,15 +352,16 @@ public class PdbApplicator {
if (programParam == null) {
if (dataTypeManagerParam == null) {
throw new PdbException(
"programParam and dataTypeManagerParam may not both be null.");
"PDB: programParam and dataTypeManagerParam may not both be null.");
}
if (imageBaseParam == null) {
throw new PdbException("programParam and imageBaseParam may not both be null.");
}
if (applicatorOptions.getRestrictions() != PdbApplicatorRestrictions.DATA_TYPES_ONLY) {
throw new PdbException(
"programParam may not be null for the chosen PdbApplicatorRestrictions: " +
applicatorOptions.getRestrictions());
"PDB: programParam and imageBaseParam may not both be null.");
}
if (applicatorOptions.getProcessingControl() != PdbApplicatorControl.DATA_TYPES_ONLY) {
throw new PdbException(
"PDB: programParam may not be null for the chosen Applicator Control: " +
applicatorOptions.getProcessingControl());
}
}
monitor = (monitorParam != null) ? monitorParam : TaskMonitor.DUMMY;
@ -641,7 +643,7 @@ public class PdbApplicator {
return sectionContribution.getModule();
}
}
throw new PdbException("Module not found for section/offset");
throw new PdbException("PDB: Module not found for section/offset");
}
//==============================================================================================

View file

@ -16,10 +16,12 @@
package ghidra.app.util.pdb.pdbapplicator;
/**
* PDB Applicator restrictions of actions performed. Used by {@link PdbApplicatorOptions}
* PDB Applicator control for actions performed. Used by {@link PdbApplicatorOptions}
*/
public enum PdbApplicatorRestrictions {
NONE("None"), DATA_TYPES_ONLY("Data Types Only"), PUBLIC_SYMBOLS_ONLY("Public Symbols Only");
public enum PdbApplicatorControl {
ALL("Process All"),
DATA_TYPES_ONLY("Data Types Only"),
PUBLIC_SYMBOLS_ONLY("Public Symbols Only");
private final String label;
@ -28,7 +30,7 @@ public enum PdbApplicatorRestrictions {
return label;
}
private PdbApplicatorRestrictions(String label) {
private PdbApplicatorControl(String label) {
this.label = label;
}

View file

@ -16,6 +16,8 @@
package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
import ghidra.framework.options.Options;
import ghidra.util.HelpLocation;
/**
* Options used while using a {@link PdbApplicator} to apply a PDB ({@link AbstractPdb}) to a
@ -24,54 +26,215 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
*/
public class PdbApplicatorOptions {
public static final boolean DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS = false;
public static final boolean DEFAULT_APPLY_INSTRUCTION_LABELS = false;
public static final PdbApplicatorRestrictions DEFAULT_RESTRICTIONS =
PdbApplicatorRestrictions.NONE;
public static final boolean DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS = false;
public static final boolean DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS = true;
// Developer turn on/off options that are in still in development.
private static final boolean developerMode = false;
// TODO: set the following to true if we come up with a reasonably good solution
public static final boolean DEFAULT_APPLY_FUNCTION_VARIABLES = false;
// Applicator Control.
private static final String OPTION_NAME_PROCESSING_CONTROL = "Control";
private static final String OPTION_DESCRIPTION_PROCESSING_CONTROL =
"Applicator processing control.";
private static final PdbApplicatorControl DEFAULT_CONTROL = PdbApplicatorControl.ALL;
private PdbApplicatorControl control;
public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
ObjectOrientedClassLayout.MEMBERS_ONLY;
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.BASIC_SIMPLE_COMPLEX;
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.SIMPLE_COMPLEX;
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.COMPLEX;
//==============================================================================================
// Apply Code Block Comments.
private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
"Apply Code Scope Block Comments";
private static final String OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
"If checked, pre/post-comments will be applied when code scope blocks are specified.";
private static final boolean DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS = false;
private boolean applyCodeScopeBlockComments;
// Apply Instruction Labels information.
// Mechanism to apply instruction labels is not yet implemented-> does nothing
private static final String OPTION_NAME_APPLY_INSTRUCTION_LABELS = "Apply Instruction Labels";
private static final String OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS =
"If checked, labels associated with instructions will be applied.";
private static final boolean DEFAULT_APPLY_INSTRUCTION_LABELS = false;
private boolean applyInstructionLabels;
private PdbApplicatorRestrictions restrictions;
private boolean remapAddressesUsingExistingPublicSymbols;
// Attempt to map address using existing mangled symbols.
private static final String OPTION_NAME_ADDRESS_REMAP = "Address Remap Using Existing Symbols";
private static final String OPTION_DESCRIPTION_ADDRESS_REMAP =
"If checked, attempts to remap address to those matching existing public symbols.";
private static final boolean DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS = false;
private boolean remapAddressUsingExistingPublicMangledSymbols;
// Allow a mangled symbol to be demoted from being a primary symbol if another symbol and
// associated explicit data type will be laid down at the location. This option exists
// because we expect the PDB explicit data type will be more accurate than trying to
// have the demangler lay down the data type.
private static final String OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY =
"Allow demote mangled symbol from primary";
private static final String OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY =
"If checked, allows a mangled symbol to be demoted from primary if a possibly " +
"better data type can be laid down with a nonmangled symbol.";
private static final boolean DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS = true;
private boolean allowDemotePrimaryMangledSymbols;
private boolean applyFunctionVariables; // investigation. might produce bad results.
// Apply Function Variables
// Investigation. might produce bad results.
private static final String OPTION_NAME_APPLY_FUNCTION_VARIABLES = "Apply Function Variables";
private static final String OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES =
"If checked, attempts to apply function parameters and local variables for program functions.";
// TODO: set the following to true if we come up with a reasonably good solution
private static final boolean DEFAULT_APPLY_FUNCTION_VARIABLES = false;
private boolean applyFunctionVariables;
private ObjectOrientedClassLayout classLayout;
// Sets the composite layout.
// Legacy
// - similar to existing DIA-based PDB Analyzer, only placing current composite direct
// members (none from parent classes.
// Warning: the remaining experimental layout choices may not be kept and are not guaranteed
// to result in data types that will be compatible with future Ghidra releases:
// Complex with Basic Fallback
// - Performs Complex layout, but if the current class has no parent classes, it will not
// encapsulate the current class's 'direct' members.
// Simple
// - Performs Complex layout, except in rare instances where , so in most cases is the same
// as 'Complex with Basic Fallback' layout.
// Complex
// - Puts all current class members and 'direct' parents' 'direct' components into an
// encapsulating 'direct' container
private static final String OPTION_NAME_COMPOSITE_LAYOUT = "Composite Layout Choice";
private static final String OPTION_DESCRIPTION_COMPOSITE_LAYOUT =
"Legacy layout like original PDB Analyzer. Warning: other choices have no compatibility" +
" guarantee with future Ghidra releases or minor PDB Analyzer changes";
private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
ObjectOrientedClassLayout.MEMBERS_ONLY;
private ObjectOrientedClassLayout compositeLayout;
// private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.BASIC_SIMPLE_COMPLEX;
//private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.SIMPLE_COMPLEX;
//private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.COMPLEX;
//==============================================================================================
/**
* Constructor
*/
public PdbApplicatorOptions() {
restoreDefaults();
setDefaults();
}
/**
* Set the options back to their default values
* Register the PdbApplicatorOptions for "Analysis."
* @param options the Options that will have PdbApplicator options registered in.
*/
public void restoreDefaults() {
public void registerAnalyzerOptions(Options options) {
registerOptions(options, false);
}
/**
* Load the PdbApplicatorOptions for used for "Analysis."
* @param options the Options that have PdbApplicator options registered in.
*/
public void loadAnalyzerOptions(Options options) {
loadOptions(options, false);
}
/**
* Register the PdbApplicatorOptions for "Load PDB."
* @param options the Options that will have PdbApplicator options registered in.
*/
public void registerLoaderOptions(Options options) {
registerOptions(options, true);
}
/**
* Load the PdbApplicatorOptions for used for "Load PDB."
* @param options the Options that have PdbApplicator options registered in.
*/
public void loadLoaderOptions(Options options) {
loadOptions(options, true);
}
private void registerOptions(Options options, boolean enableControl) {
HelpLocation help = null;
if (developerMode || enableControl) {
options.registerOption(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL, help,
OPTION_DESCRIPTION_PROCESSING_CONTROL);
}
// PdbApplicatorOptions
if (developerMode) {
options.registerOption(OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS,
applyCodeScopeBlockComments, help,
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
options.registerOption(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels,
help, OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS);
// The remap capability is not completely implemented... do not turn on.
options.registerOption(OPTION_NAME_ADDRESS_REMAP,
remapAddressUsingExistingPublicMangledSymbols, help,
OPTION_DESCRIPTION_ADDRESS_REMAP);
options.registerOption(OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY,
allowDemotePrimaryMangledSymbols, help,
OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY);
// Function params and local implementation is not complete... do not turn on.
options.registerOption(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables,
help, OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES);
// Object-oriented composite layout is fairly far along, but its use will likely not
// be forward compatible with future Ghidra work in this area; i.e., it might leave
// the data type manager in a bad state for future revisions. While the current
// layout mechanism might work, I will likely change it to, instead, create a
// syntactic intermediate representation before creating the final layout. This will
// aid portability between tool chains and versions and yield a standard way of
// data-basing and presenting the information to a user.
options.registerOption(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout, help,
OPTION_DESCRIPTION_COMPOSITE_LAYOUT);
}
}
private void loadOptions(Options options, boolean enableControl) {
if (developerMode || enableControl) {
control = options.getEnum(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL);
}
// PdbApplicatorOptions
if (developerMode) {
applyCodeScopeBlockComments = options.getBoolean(
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
applyInstructionLabels =
options.getBoolean(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels);
remapAddressUsingExistingPublicMangledSymbols = options.getBoolean(
OPTION_NAME_ADDRESS_REMAP, remapAddressUsingExistingPublicMangledSymbols);
allowDemotePrimaryMangledSymbols = options.getBoolean(
OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY, allowDemotePrimaryMangledSymbols);
applyFunctionVariables =
options.getBoolean(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables);
compositeLayout = options.getEnum(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout);
}
}
/**
* Set the options to their default values
*/
public void setDefaults() {
applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
restrictions = DEFAULT_RESTRICTIONS;
remapAddressesUsingExistingPublicSymbols = DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
control = DEFAULT_CONTROL;
remapAddressUsingExistingPublicMangledSymbols =
DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
allowDemotePrimaryMangledSymbols = DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS;
applyFunctionVariables = DEFAULT_APPLY_FUNCTION_VARIABLES;
classLayout = DEFAULT_CLASS_LAYOUT;
compositeLayout = DEFAULT_CLASS_LAYOUT;
}
/**
@ -107,19 +270,19 @@ public class PdbApplicatorOptions {
}
/**
* Set processing restrictions for PdbApplicator
* @param restrictions the restrictions
* Set processing control for PdbApplicator
* @param control the processing control
*/
public void setRestrictions(PdbApplicatorRestrictions restrictions) {
this.restrictions = restrictions;
public void setProcessingControl(PdbApplicatorControl control) {
this.control = control;
}
/**
* Returns the current restrictions on PdbApplicator processing
* @return the restrictions
* Returns the current processing control for the PdbApplicator
* @return the processing control
*/
public PdbApplicatorRestrictions getRestrictions() {
return restrictions;
public PdbApplicatorControl getProcessingControl() {
return control;
}
/**
@ -128,7 +291,7 @@ public class PdbApplicatorOptions {
* @param enable {@code true} to turn remapAddressesUsingExistingPublicSymbols on
*/
public void setRemapAddressUsingExistingPublicSymbols(boolean enable) {
this.remapAddressesUsingExistingPublicSymbols = enable;
this.remapAddressUsingExistingPublicMangledSymbols = enable;
}
/**
@ -136,7 +299,7 @@ public class PdbApplicatorOptions {
* @return {@code true} if remapAddressesUsingExistingPublicSymbols is "on."
*/
public boolean remapAddressUsingExistingPublicSymbols() {
return remapAddressesUsingExistingPublicSymbols;
return remapAddressUsingExistingPublicMangledSymbols;
}
/**
@ -179,16 +342,15 @@ public class PdbApplicatorOptions {
* Set the class layout.
* @param classLayout composite layout
*/
public void setClassLayout(ObjectOrientedClassLayout classLayout) {
this.classLayout = classLayout;
public void setCompositeLayout(ObjectOrientedClassLayout classLayout) {
this.compositeLayout = classLayout;
}
/**
* Returns the physical layout out classes.
* @return the class layout.
*/
public ObjectOrientedClassLayout getClassLayout() {
return classLayout;
public ObjectOrientedClassLayout getCompositeLayout() {
return compositeLayout;
}
}

View file

@ -24,7 +24,7 @@ import docking.DialogComponentProvider;
import docking.DockingWindowManager;
import docking.widgets.combobox.GComboBox;
import ghidra.app.util.bin.format.pdb.PdbParser;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorRestrictions;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
import ghidra.util.layout.PairLayout;
class AskPdbOptionsDialog extends DialogComponentProvider {
@ -32,12 +32,12 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
private boolean isCanceled;
private boolean useMsDiaParser;
private PdbApplicatorRestrictions restrictions = PdbApplicatorRestrictions.NONE;
private PdbApplicatorControl control = PdbApplicatorControl.ALL;
/**
* Popup PDB loader options
* @param parent parent component or null
* @param isPdbFile true if file to be loaded is a PDB file, false
* @param isPdbFile true if file to be loaded is a PDB file, false
* if MsDia XML file.
*/
AskPdbOptionsDialog(Component parent, boolean isPdbFile) {
@ -48,11 +48,11 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
JPanel optionsPanel = new JPanel(new PairLayout(10, 10));
final GComboBox<PdbApplicatorRestrictions> restrictionsCombo =
new GComboBox<>(PdbApplicatorRestrictions.values());
restrictionsCombo.setSelectedItem(PdbApplicatorRestrictions.NONE);
restrictionsCombo.addActionListener(e -> {
restrictions = (PdbApplicatorRestrictions) restrictionsCombo.getSelectedItem();
final GComboBox<PdbApplicatorControl> controlCombo =
new GComboBox<>(PdbApplicatorControl.values());
controlCombo.setSelectedItem(PdbApplicatorControl.ALL);
controlCombo.addActionListener(e -> {
control = (PdbApplicatorControl) controlCombo.getSelectedItem();
});
optionsPanel.add(new JLabel("PDB Parser:"));
@ -63,12 +63,12 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
final GComboBox<String> combo =
new GComboBox<>(new String[] { "PDB Universal", "PDB MSDIA" });
combo.setSelectedIndex(0);
restrictionsCombo.setEnabled(!useMsDiaParser);
controlCombo.setEnabled(!useMsDiaParser);
combo.addActionListener(e -> {
useMsDiaParser = (combo.getSelectedIndex() == 1);
restrictionsCombo.setEnabled(!useMsDiaParser);
controlCombo.setEnabled(!useMsDiaParser);
if (useMsDiaParser) {
restrictionsCombo.setSelectedItem(PdbApplicatorRestrictions.NONE);
controlCombo.setSelectedItem(PdbApplicatorControl.ALL);
}
});
optionsPanel.add(combo);
@ -85,8 +85,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
return; // no interaction currently required
}
optionsPanel.add(new JLabel("Restrictions:"));
optionsPanel.add(restrictionsCombo);
optionsPanel.add(new JLabel("Control:"));
optionsPanel.add(controlCombo);
panel.add(optionsPanel, BorderLayout.CENTER);
@ -101,7 +101,6 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
DockingWindowManager.showDialog(parent, AskPdbOptionsDialog.this);
}
@Override
protected void applyCallback() {
isCanceled = false;
@ -122,8 +121,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
return useMsDiaParser;
}
PdbApplicatorRestrictions getApplicatorRestrictions() {
return restrictions;
PdbApplicatorControl getApplicatorControl() {
return control;
}
}

View file

@ -44,15 +44,15 @@ class LoadPdbTask extends Task {
private DataTypeManagerService service;
private final Program program;
private final boolean useMsDiaParser;
private final PdbApplicatorRestrictions restrictions; // PDB Universal Parser only
private final PdbApplicatorControl control; // PDB Universal Parser only
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser,
PdbApplicatorRestrictions restrictions, DataTypeManagerService service) {
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, PdbApplicatorControl control,
DataTypeManagerService service) {
super("Load PDB", true, false, true, true);
this.program = program;
this.pdbFile = pdbFile;
this.useMsDiaParser = useMsDiaParser;
this.restrictions = restrictions;
this.control = control;
this.service = service;
}
@ -97,8 +97,8 @@ class LoadPdbTask extends Task {
};
try {
AutoAnalysisManager.getAnalysisManager(program)
.scheduleWorker(worker, null, true, wrappedMonitor);
AutoAnalysisManager.getAnalysisManager(program).scheduleWorker(worker, null, true,
wrappedMonitor);
if (log.hasMessages()) {
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
"There were warnings/errors loading the PDB file.", log.toString(),
@ -147,7 +147,7 @@ class LoadPdbTask extends Task {
return false;
}
// NOTE: OptionDialog will not display an empty line
// NOTE: OptionDialog will not display an empty line
private static final String BLANK_LINE = " \n";
private boolean parseWithNewParser(MessageLog log, TaskMonitor monitor)
@ -157,12 +157,12 @@ class LoadPdbTask extends Task {
PdbApplicatorOptions pdbApplicatorOptions = new PdbApplicatorOptions();
pdbApplicatorOptions.setRestrictions(restrictions);
pdbApplicatorOptions.setProcessingControl(control);
PdbProgramAttributes programAttributes = new PdbProgramAttributes(program);
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser
.parse(pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) {
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser.parse(
pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) {
PdbIdentifiers identifiers = pdb.getIdentifiers();
if (!PdbLocator.verifyPdbSignature(programAttributes, identifiers)) {

View file

@ -30,7 +30,7 @@ import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.services.DataTypeManagerService;
import ghidra.app.util.bin.format.pdb.PdbParser;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorRestrictions;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program;
@ -124,7 +124,7 @@ public class PdbPlugin extends Plugin {
}
boolean useMsDiaParser = optionsDialog.useMsDiaParser();
PdbApplicatorRestrictions restrictions = optionsDialog.getApplicatorRestrictions();
PdbApplicatorControl control = optionsDialog.getApplicatorControl();
tool.setStatusInfo("");
@ -139,7 +139,7 @@ public class PdbPlugin extends Plugin {
// dialog prompts. We want the task progress dialog to be showing before any
// prompts appear.
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, restrictions, service);
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, control, service);
TaskBuilder.withTask(task)
.setStatusTextAlignment(SwingConstants.LEADING)
.setLaunchDelay(0);

View file

@ -37,7 +37,7 @@ import ghidra.app.util.bin.format.pdb.PdbParser;
import ghidra.app.util.bin.format.pdb.PdbParser.PdbFileType;
import ghidra.app.util.pdb.PdbLocator;
import ghidra.app.util.pdb.PdbProgramAttributes;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorRestrictions;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
import ghidra.framework.Application;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
@ -808,7 +808,7 @@ public class PdbSymbolServerPlugin extends Plugin {
}
boolean useMsDiaParser = optionsDialog.useMsDiaParser();
PdbApplicatorRestrictions restrictions = optionsDialog.getApplicatorRestrictions();
PdbApplicatorControl control = optionsDialog.getApplicatorControl();
tool.setStatusInfo("");
@ -822,7 +822,7 @@ public class PdbSymbolServerPlugin extends Plugin {
TaskLauncher
.launch(
new LoadPdbTask(currentProgram, downloadedPdb, useMsDiaParser, restrictions,
new LoadPdbTask(currentProgram, downloadedPdb, useMsDiaParser, control,
service));
}
catch (Exception pe) {

View file

@ -111,8 +111,8 @@ class ArrayDB extends DataTypeDB implements Array {
}
@Override
public boolean isDynamicallySized() {
return getDataType().isDynamicallySized();
public boolean hasLanguageDependantLength() {
return getDataType().hasLanguageDependantLength();
}
@Override

View file

@ -189,10 +189,8 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
}
@Override
public boolean isDynamicallySized() {
return isPackingEnabled();
}
public abstract boolean hasLanguageDependantLength();
@Override
public Object getValue(MemBuffer buf, Settings settings, int length) {
return null;
@ -285,27 +283,33 @@ abstract class CompositeDB extends DataTypeDB implements CompositeInternal {
/**
* This method throws an exception if the indicated data type is not a valid
* data type for a component of this composite data type.
* data type for a component of this composite data type. If the DEFAULT
* datatype is specified when unsupported an Undefined1 will be returned
* in its place (e.g., packing enabled, Union).
*
* @param dataType the data type to be checked.
* @return datatype to be used for insert/add
* @throws IllegalArgumentException if the data type is invalid.
*/
protected void validateDataType(DataType dataType) {
if (isPackingEnabled() && dataType == DataType.DEFAULT) {
throw new IllegalArgumentException(
"The DEFAULT data type is not allowed in an aligned composite data type.");
protected DataType validateDataType(DataType dataType) {
if (dataType == DataType.DEFAULT) {
if (isPackingEnabled() || (this instanceof Union)) {
return Undefined1DataType.dataType;
}
return dataType;
}
if (dataType instanceof FactoryDataType) {
throw new IllegalArgumentException("The \"" + dataType.getName() +
"\" data type is not allowed in a composite data type.");
}
else if (dataType instanceof Dynamic) {
if (dataType instanceof Dynamic) {
Dynamic dynamicDataType = (Dynamic) dataType;
if (!dynamicDataType.canSpecifyLength()) {
throw new IllegalArgumentException("The \"" + dataType.getName() +
"\" data type is not allowed in a composite data type.");
}
}
else if (dataType instanceof FactoryDataType || dataType.getLength() <= 0) {
throw new IllegalArgumentException("The \"" + dataType.getName() +
"\" data type is not allowed in a composite data type.");
}
return dataType;
}
@Override

View file

@ -2314,7 +2314,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
else if (dt instanceof Pointer) {
Pointer ptr = (Pointer) dt;
int len = ptr.isDynamicallySized() ? -1 : ptr.getLength();
int len = ptr.hasLanguageDependantLength() ? -1 : ptr.getLength();
newDataType = createPointer(ptr.getDataType(), cat, (byte) len, handler);
}
else if (dt instanceof StructureInternal) {

View file

@ -155,7 +155,7 @@ class EnumDB extends DataTypeDB implements Enum {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}

View file

@ -87,7 +87,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false;
}

View file

@ -126,7 +126,7 @@ class PointerDB extends DataTypeDB implements Pointer {
return this;
}
// don't clone referenced data-type to avoid potential circular reference
return new PointerDataType(getDataType(), isDynamicallySized() ? -1 : getLength(), dtm);
return new PointerDataType(getDataType(), hasLanguageDependantLength() ? -1 : getLength(), dtm);
}
@Override
@ -148,7 +148,7 @@ class PointerDB extends DataTypeDB implements Pointer {
DataType dt = getDataType();
if (dt == null) {
displayName = PointerDataType.POINTER_NAME;
if (!isDynamicallySized()) {
if (!hasLanguageDependantLength()) {
displayName += Integer.toString(getLength() * 8);
}
}
@ -180,7 +180,7 @@ class PointerDB extends DataTypeDB implements Pointer {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
lock.acquire();
try {
checkIsValid();
@ -213,7 +213,7 @@ class PointerDB extends DataTypeDB implements Pointer {
try {
checkIsValid();
StringBuffer sbuf = new StringBuffer();
if (!isDynamicallySized()) {
if (!hasLanguageDependantLength()) {
sbuf.append(Integer.toString(getLength() * 8));
sbuf.append("-bit ");
}
@ -291,10 +291,10 @@ class PointerDB extends DataTypeDB implements Pointer {
Pointer p = (Pointer) dt;
DataType otherDataType = p.getDataType();
if (isDynamicallySized() != p.isDynamicallySized()) {
if (hasLanguageDependantLength() != p.hasLanguageDependantLength()) {
return false;
}
if (!isDynamicallySized() && (getLength() != p.getLength())) {
if (!hasLanguageDependantLength() && (getLength() != p.getLength())) {
return false;
}
@ -447,7 +447,7 @@ class PointerDB extends DataTypeDB implements Pointer {
@Override
public Pointer newPointer(DataType dataType) {
if (isDynamicallySized()) {
if (hasLanguageDependantLength()) {
return new PointerDataType(dataType, dataMgr);
}
return new PointerDataType(dataType, getLength(), dataMgr);

View file

@ -119,7 +119,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
checkDeleted();
if (validatePackAndNotify) {
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = resolve(dataType);
checkAncestry(dataType);
}
@ -178,12 +178,14 @@ class StructureDB extends CompositeDB implements StructureInternal {
checkDeleted();
if (validatePackAndNotify) {
validateDataType(dataType);
dataType = resolve(dataType);
if (isInvalidFlexArrayDataType(dataType)) {
throw new IllegalArgumentException(
"Unsupported flexType: " + dataType.getDisplayName());
}
validateDataType(dataType);
dataType = resolve(dataType);
checkAncestry(dataType);
}
@ -262,7 +264,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
if (ordinal == numComponents) {
return add(dataType, length, name, comment);
}
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = resolve(dataType);
checkAncestry(dataType);
@ -819,6 +821,11 @@ class StructureDB extends CompositeDB implements StructureInternal {
}
}
@Override
public boolean hasLanguageDependantLength() {
return isPackingEnabled();
}
@Override
public void clearComponent(int ordinal) {
lock.acquire();
@ -1047,7 +1054,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
lock.acquire();
try {
checkDeleted();
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = resolve(dataType);
checkAncestry(dataType);
@ -1121,7 +1128,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
throw new IndexOutOfBoundsException(ordinal);
}
validateDataType(dataType);
dataType = validateDataType(dataType);
DataTypeComponent origDtc = getComponent(ordinal);
if (origDtc.isBitFieldComponent()) {
@ -1182,7 +1189,7 @@ class StructureDB extends CompositeDB implements StructureInternal {
try {
checkDeleted();
validateDataType(dataType);
dataType = validateDataType(dataType);
DataTypeComponent origDtc = getComponentAt(offset);
if (origDtc.isBitFieldComponent()) {

View file

@ -61,8 +61,8 @@ class TypedefDB extends DataTypeDB implements TypeDef {
}
@Override
public boolean isDynamicallySized() {
return getDataType().isDynamicallySized();
public boolean hasLanguageDependantLength() {
return getDataType().hasLanguageDependantLength();
}
@Override

View file

@ -130,7 +130,7 @@ class UnionDB extends CompositeDB implements UnionInternal {
private DataTypeComponent doAdd(DataType dataType, int length, String name, String comment,
boolean validateAlignAndNotify) throws DataTypeDependencyException {
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = adjustBitField(dataType);
@ -178,7 +178,7 @@ class UnionDB extends CompositeDB implements UnionInternal {
lock.acquire();
try {
checkDeleted();
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = adjustBitField(dataType);
@ -471,6 +471,12 @@ class UnionDB extends CompositeDB implements UnionInternal {
}
}
@Override
public boolean hasLanguageDependantLength() {
// Assume any component may have a language-dependent length
return true;
}
@Override
protected void fixupComponents() {
boolean changed = false;

View file

@ -81,14 +81,6 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
return false;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -85,14 +85,6 @@ public class AUDataType extends BuiltIn implements Dynamic {
return false;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -91,11 +91,6 @@ public abstract class AbstractComplexDataType extends BuiltIn {
return "The data type for a complex number: a + bi";
}
@Override
public boolean isDynamicallySized() {
return false;
}
private static double toDouble(Object obj) {
if (obj instanceof Double) {
return (Double) obj;

View file

@ -232,7 +232,7 @@ public abstract class AbstractDataType implements DataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return false; // not applicable
}

View file

@ -47,14 +47,6 @@ public abstract class AbstractFloatDataType extends BuiltIn {
return name;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return false;
}
/**
*
* @see ghidra.program.model.data.DataType#getDescription()
@ -125,7 +117,7 @@ public abstract class AbstractFloatDataType extends BuiltIn {
@Override
public String getCTypeDeclaration(DataOrganization dataOrganization) {
return isDynamicallySized() ? null : name;
return hasLanguageDependantLength() ? null : name;
}
private static TreeMap<Integer, AbstractFloatDataType> floatTypes; // fixed-size float types

View file

@ -58,11 +58,6 @@ abstract class AbstractImageBaseOffsetDataType extends BuiltIn {
return getScalarDataType().getLength();
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
Address addr = (Address) getValue(buf, settings, length);

View file

@ -65,14 +65,6 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
this.signed = signed;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return false;
}
/**
* Return the Format settings definition included in the settings
* definition array

View file

@ -195,11 +195,6 @@ abstract public class AbstractStringDataType extends BuiltIn
StringDataInstance.DEFAULT_CHARSET_NAME);
}
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public int getLength() {
return -1;

View file

@ -78,14 +78,6 @@ public class AlignmentDataType extends BuiltIn implements Dynamic {
return new AlignmentDataType(dtm);
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public String getDescription() {
return "Consumes alignment/repeating bytes.";

View file

@ -88,8 +88,8 @@ public class ArrayDataType extends DataTypeImpl implements Array {
}
@Override
public boolean isDynamicallySized() {
return dataType.isDynamicallySized();
public boolean hasLanguageDependantLength() {
return dataType.hasLanguageDependantLength();
}
@Override

View file

@ -43,6 +43,7 @@ public class BadDataType extends BuiltIn implements Dynamic {
*
* @see ghidra.program.model.data.DataType#getMnemonic(Settings)
*/
@Override
public String getMnemonic(Settings settings) {
return getName();
}
@ -51,21 +52,16 @@ public class BadDataType extends BuiltIn implements Dynamic {
*
* @see ghidra.program.model.data.DataType#getLength()
*/
@Override
public int getLength() {
return -1;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
public boolean isDynamicallySized() {
return false;
}
/**
*
* @see ghidra.program.model.data.DataType#getDescription()
*/
@Override
public String getDescription() {
return "** Bad Data Type **";
}
@ -74,6 +70,7 @@ public class BadDataType extends BuiltIn implements Dynamic {
*
* @see ghidra.program.model.data.DataType#getValue(ghidra.program.model.mem.MemBuffer, ghidra.docking.settings.Settings, int)
*/
@Override
public Object getValue(MemBuffer buf, Settings settings, int length) {
return getDescription();
}
@ -87,10 +84,12 @@ public class BadDataType extends BuiltIn implements Dynamic {
*
* @see ghidra.program.model.data.DataType#getRepresentation(MemBuffer, Settings, int)
*/
@Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
return getDescription();
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;
@ -98,14 +97,17 @@ public class BadDataType extends BuiltIn implements Dynamic {
return new BadDataType(dtm);
}
@Override
public boolean canSpecifyLength() {
return true;
}
@Override
public int getLength(MemBuffer buf, int maxLength) {
return -1;
}
@Override
public DataType getReplacementBaseType() {
return null;
}

View file

@ -28,8 +28,6 @@ import ghidra.program.model.mem.MemoryAccessException;
*/
public class BooleanDataType extends AbstractIntegerDataType {
private final static long serialVersionUID = 1;
private static SettingsDefinition[] SETTINGS_DEFS = {};
public static final BooleanDataType dataType = new BooleanDataType();
@ -52,8 +50,9 @@ public class BooleanDataType extends AbstractIntegerDataType {
@Override
public String getDecompilerDisplayName(DecompilerLanguage language) {
if (language == DecompilerLanguage.JAVA_LANGUAGE)
if (language == DecompilerLanguage.JAVA_LANGUAGE) {
return "boolean";
}
return name;
}
@ -67,11 +66,6 @@ public class BooleanDataType extends AbstractIntegerDataType {
return 1; // TODO: Size should probably be based upon data organization
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public String getDescription() {
return "Boolean";

View file

@ -99,7 +99,7 @@ public class CharDataType extends AbstractIntegerDataType implements DataTypeWit
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -111,9 +111,7 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
}
@Override
public boolean isDynamicallySized() {
return true; // assume dynamically sized component datatype may be present
}
public abstract boolean hasLanguageDependantLength();
@Override
public boolean isPartOf(DataType dataTypeOfInterest) {
@ -142,23 +140,33 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
/**
* This method throws an exception if the indicated data type is not a valid
* data type for a component of this composite data type.
* data type for a component of this composite data type. If the DEFAULT
* datatype is specified when unsupported an Undefined1 will be returned
* in its place (e.g., packing enabled, Union).
*
* @param dataType the data type to be checked.
* @return datatype to be used for insert/add
* @throws IllegalArgumentException if the data type is invalid.
*/
protected void validateDataType(DataType dataType) {
if (dataType instanceof FactoryDataType) {
throw new IllegalArgumentException("The \"" + dataType.getName() +
"\" data type is not allowed in a composite data type.");
protected DataType validateDataType(DataType dataType) {
if (dataType == DataType.DEFAULT) {
if (isPackingEnabled() || (this instanceof Union)) {
return Undefined1DataType.dataType;
}
return dataType;
}
else if (dataType instanceof Dynamic) {
if (dataType instanceof Dynamic) {
Dynamic dynamicDataType = (Dynamic) dataType;
if (!dynamicDataType.canSpecifyLength()) {
throw new IllegalArgumentException("The \"" + dataType.getName() +
"\" data type is not allowed in a composite data type.");
}
}
else if (dataType instanceof FactoryDataType || dataType.getLength() <= 0) {
throw new IllegalArgumentException("The \"" + dataType.getName() +
"\" data type is not allowed in a composite data type.");
}
return dataType;
}
/**

View file

@ -38,10 +38,11 @@ public interface DataType {
static final long NO_LAST_CHANGE_TIME = 0L;
/**
* Indicates if this data-type is dynamically sized based upon DataOrganization.
* @return true if dynamically sized
* Indicates if the length of this data-type is determined based
* upon the {@link DataOrganization} obtained from the associated {@link DataTypeManager}.
* @return true length is language/compiler-specification dependent, else false
*/
public boolean isDynamicallySized();
public boolean hasLanguageDependantLength();
/**
* Indicates if type has not yet been defined.

View file

@ -54,14 +54,6 @@ public class DefaultDataType extends DataTypeImpl {
return 1;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return false;
}
/**
*
* @see ghidra.program.model.data.DataType#getDescription()

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -43,7 +42,7 @@ public class DoubleDataType extends AbstractFloatDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -50,14 +50,6 @@ public abstract class DynamicDataType extends BuiltIn implements Dynamic {
return false;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
/**
* Gets the number of component data types in this data type.
* @param buf a membuffer to be used by dataTypes that change depending on

View file

@ -73,11 +73,6 @@ public class EnumDataType extends GenericDataType implements Enum {
return ENUM_SETTINGS_DEFINITIONS;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public long getValue(String valueName) throws NoSuchElementException {
Long value = nameMap.get(valueName);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,7 +29,17 @@ public interface FactoryDataType extends BuiltInDataType {
* Returns the appropriate DataType which corresponds to the specified
* memory location.
* @param buf memory location
* @return fabricated datatype based upon memory data
*/
DataType getDataType(MemBuffer buf);
/**
* All implementations must return a length of -1.
* @return length of -1
*/
@Override
default int getLength() {
return -1;
}
}

View file

@ -24,7 +24,6 @@ import ghidra.util.exception.DuplicateNameException;
* a Structure and create a new Dynamic structure each time they are used.
*/
public abstract class FactoryStructureDataType extends BuiltIn implements FactoryDataType {
private final static long serialVersionUID = 1;
/**
* Constructs a new DynamicStructureDataType with the given name
@ -41,7 +40,7 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
* @see ghidra.program.model.data.DataType#getLength()
*/
@Override
public int getLength() {
public final int getLength() {
return -1;
}

View file

@ -67,14 +67,6 @@ public class FileTimeDataType extends BuiltIn {
return 8;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public String getMnemonic(Settings settings) {
return "FileTime";

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -43,7 +42,7 @@ public class FloatDataType extends AbstractFloatDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -97,11 +97,11 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
Parameter[] parameters = function.getParameters();
ArrayList<ParameterDefinition> paramList = new ArrayList<ParameterDefinition>();
for (int i = 0; i < parameters.length; i++) {
if (formalSignature && parameters[i].isAutoParameter()) {
for (Parameter parameter : parameters) {
if (formalSignature && parameter.isAutoParameter()) {
continue;
}
paramList.add(getParameterDefinition(parameters[i], formalSignature));
paramList.add(getParameterDefinition(parameter, formalSignature));
}
params = paramList.toArray(new ParameterDefinition[paramList.size()]);
@ -150,11 +150,6 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
}
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public void setReturnType(DataType type) {
returnType = ParameterDefinitionImpl.validateDataType(type, dataMgr, true);
@ -350,8 +345,7 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
return;
}
}
for (int i = 0; i < params.length; i++) {
ParameterDefinition param = params[i];
for (ParameterDefinition param : params) {
if (param.getDataType() == oldDt) {
try {
param.setDataType(newDt);
@ -391,9 +385,9 @@ public class FunctionDefinitionDataType extends GenericDataType implements Funct
if (returnType == dt) {
returnType = DataType.DEFAULT;
}
for (int i = 0; i < params.length; i++) {
if (params[i].getDataType() == dt) {
params[i].setDataType(DataType.DEFAULT);
for (ParameterDefinition param : params) {
if (param.getDataType() == dt) {
param.setDataType(DataType.DEFAULT);
}
}
}

View file

@ -66,14 +66,6 @@ public class GifDataType extends BuiltIn implements Dynamic, Resource {
return false;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -34,10 +34,10 @@ public class IntegerDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -80,14 +80,6 @@ public class JPEGDataType extends BuiltIn implements Dynamic, Resource {
return false;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -42,10 +42,10 @@ public class LongDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -48,7 +47,7 @@ public class LongDoubleDataType extends AbstractFloatDataType {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -42,10 +42,10 @@ public class LongLongDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -15,15 +15,15 @@
*/
package ghidra.program.model.data;
import ghidra.docking.settings.Settings;
import ghidra.program.model.mem.MemBuffer;
import ghidra.util.Msg;
import ghidra.util.classfinder.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import ghidra.docking.settings.Settings;
import ghidra.program.model.mem.MemBuffer;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassTranslator;
/**
* A datatype to interpret the Mac OS timestamp
* convention, which is based on the number of
@ -57,26 +57,23 @@ public class MacintoshTimeStampDataType extends BuiltIn {
super(null, "MacTime", dtm);
}
@Override
public String getDescription() {
return "The stamp follows the Macintosh time-measurement scheme "
+ "(that is, the number of seconds measured from January 1, 1904).";
}
@Override
public int getLength() {
return 4;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
public boolean isDynamicallySized() {
return false;
}
@Override
public String getMnemonic(Settings settings) {
return "MacTime";
}
@Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
if (macStartDate == null) {
return "unparsed date";
@ -93,10 +90,12 @@ public class MacintoshTimeStampDataType extends BuiltIn {
return "";
}
@Override
public Object getValue(MemBuffer buf, Settings settings, int length) {
return getRepresentation(buf, settings, length);
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;

View file

@ -85,14 +85,6 @@ public class MissingBuiltInDataType extends DataTypeImpl implements Dynamic {
return -1;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public boolean canSpecifyLength() {
return true;

View file

@ -79,7 +79,7 @@ public class ParameterDefinitionImpl implements ParameterDefinition {
dataType.getName());
}
dataType = dataType.clone(dtMgr != null ? dtMgr : dataType.getDataTypeManager());
if (!dataType.isDynamicallySized() && dataType.getLength() < 0) {
if (dataType.getLength() < 0) {
throw new IllegalArgumentException(kind +
" type must be specified with fixed-length data type: " + dataType.getName());
}
@ -94,7 +94,7 @@ public class ParameterDefinitionImpl implements ParameterDefinition {
"Parameter type may not specify the void datatype - empty parameter list should be used");
}
}
else if (!(dataType instanceof Composite) && dataType.getLength() == 0) {
else if (dataType.getLength() == 0) {
throw new IllegalArgumentException(kind +
" type must be specified with fixed-length data type: " + dataType.getName());
}

View file

@ -57,14 +57,6 @@ public class PngDataType extends BuiltIn implements Dynamic, Resource {
return -1;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public boolean canSpecifyLength() {
return false;

View file

@ -31,8 +31,6 @@ import ghidra.util.DataConverter;
*/
public class PointerDataType extends BuiltIn implements Pointer {
private final static long serialVersionUID = 1;
public final static PointerDataType dataType = new PointerDataType();
public final static int MAX_POINTER_SIZE_BYTES = 8;
@ -156,7 +154,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return length <= 0;
}
@ -460,10 +458,10 @@ public class PointerDataType extends BuiltIn implements Pointer {
Pointer p = (Pointer) dt;
DataType otherDataType = p.getDataType();
if (isDynamicallySized() != p.isDynamicallySized()) {
if (hasLanguageDependantLength() != p.hasLanguageDependantLength()) {
return false;
}
if (!isDynamicallySized() && (getLength() != p.getLength())) {
if (!hasLanguageDependantLength() && (getLength() != p.getLength())) {
return false;
}
if (referencedDataType == null) {

View file

@ -54,14 +54,6 @@ public class SegmentedCodePointerDataType extends BuiltIn {
return 4;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public String getDescription() {
return "Code address from 16 bit segment and 16 bit offset";
@ -98,8 +90,9 @@ public class SegmentedCodePointerDataType extends BuiltIn {
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
Object obj = getValue(buf, settings, length);
if (obj == null)
if (obj == null) {
return "??";
}
return obj.toString();
}

View file

@ -18,7 +18,6 @@ package ghidra.program.model.data;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.ProcessorContext;
import ghidra.program.model.mem.MemBuffer;
import ghidra.util.DataConverter;
import ghidra.util.classfinder.ClassTranslator;
@ -60,7 +59,7 @@ public class ShiftedAddressDataType extends BuiltIn {
}
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -42,10 +42,10 @@ public class ShortDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -203,6 +203,11 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
return structLength;
}
@Override
public boolean hasLanguageDependantLength() {
return isPackingEnabled();
}
@Override
public void delete(int ordinal) {
if (ordinal < 0 || ordinal >= numComponents) {
@ -373,16 +378,6 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
return super.getPreferredComponentLength(dataType, length);
}
@Override
protected void validateDataType(DataType dataType) {
// TODO: need tests - questionable if transitioning to/from no-packing works properly
if (isPackingEnabled() && dataType == DataType.DEFAULT) {
throw new IllegalArgumentException(
"The DEFAULT data type is not allowed in an aligned composite data type.");
}
super.validateDataType(dataType);
}
@Override
public final DataTypeComponentImpl insertAtOffset(int offset, DataType dataType, int length) {
return insertAtOffset(offset, dataType, length, null, null);
@ -410,7 +405,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
}
}
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = dataType.clone(dataMgr);
checkAncestry(dataType);
@ -487,13 +482,15 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
String componentName, String comment, boolean packAndNotify)
throws IllegalArgumentException {
validateDataType(dataType);
dataType = dataType.clone(dataMgr);
if (isFlexibleArray && isInvalidFlexArrayDataType(dataType)) {
throw new IllegalArgumentException(
"Unsupported flexType: " + dataType.getDisplayName());
}
dataType = validateDataType(dataType);
dataType = dataType.clone(dataMgr);
checkAncestry(dataType);
DataTypeComponentImpl dtc;
@ -566,7 +563,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index == numComponents) {
return add(dataType, length, componentName, comment);
}
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = dataType.clone(dataMgr);
checkAncestry(dataType);
@ -1311,7 +1308,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
throw new IndexOutOfBoundsException(index);
}
validateDataType(dataType);
dataType = validateDataType(dataType);
DataTypeComponentImpl origDtc = (DataTypeComponentImpl) getComponent(index);
if (origDtc.isBitFieldComponent()) {
@ -1354,7 +1351,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
"Offset " + offset + " is beyond end of structure (" + getLength() + ").");
}
validateDataType(dataType);
dataType = validateDataType(dataType);
DataTypeComponentImpl origDtc = (DataTypeComponentImpl) getComponentAt(offset);
if (origDtc.isBitFieldComponent()) {

View file

@ -104,8 +104,8 @@ public class TypedefDataType extends GenericDataType implements TypeDef {
}
@Override
public boolean isDynamicallySized() {
return dataType.isDynamicallySized();
public boolean hasLanguageDependantLength() {
return dataType.hasLanguageDependantLength();
}
@Override

View file

@ -39,14 +39,6 @@ public abstract class Undefined extends BuiltIn {
return undefinedTypes;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
@Override
public boolean isDynamicallySized() {
return false;
}
/**
* Get an Undefined data-type instance of the requested size
* @param size data type size, sizes greater than 8 will cause an Undefined1[size] (i.e., Array) to be returned.
@ -74,10 +66,12 @@ public abstract class Undefined extends BuiltIn {
* its various forms, else false.
*/
public static boolean isUndefined(DataType dataType) {
if (dataType instanceof DefaultDataType)
if (dataType instanceof DefaultDataType) {
return true;
if (dataType instanceof Undefined)
}
if (dataType instanceof Undefined) {
return true;
}
return isUndefinedArray(dataType);
}

View file

@ -170,7 +170,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
DataTypeComponent doAdd(DataType dataType, int length, String componentName, String comment)
throws IllegalArgumentException {
validateDataType(dataType);
dataType = validateDataType(dataType);
dataType = adjustBitField(dataType);
@ -190,7 +190,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
@Override
public DataTypeComponent insert(int ordinal, DataType dataType, int length,
String componentName, String comment) throws IllegalArgumentException {
validateDataType(dataType);
dataType = validateDataType(dataType);
int oldAlignment = getAlignment();
@ -248,6 +248,12 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
return unionLength;
}
@Override
public boolean hasLanguageDependantLength() {
// Assume any component may have a language-dependent length
return true;
}
@Override
public Union clone(DataTypeManager dtm) {
if (dataMgr == dtm) {

View file

@ -43,10 +43,10 @@ public class UnsignedIntegerDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -43,10 +43,10 @@ public class UnsignedLongDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -43,10 +43,10 @@ public class UnsignedLongLongDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -43,10 +43,10 @@ public class UnsignedShortDataType extends AbstractIntegerDataType {
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
* @see ghidra.program.model.data.DataType#hasLanguageDependantLength()
*/
@Override
public boolean isDynamicallySized() {
public boolean hasLanguageDependantLength() {
return true;
}

View file

@ -23,7 +23,6 @@ import ghidra.program.model.mem.MemBuffer;
* a function has no return value.
*/
public class VoidDataType extends BuiltIn {
private final static long serialVersionUID = 1;
/** A statically defined DefaultDataType used when an Undefined byte is needed.*/
public static VoidDataType dataType = new VoidDataType();
@ -40,6 +39,7 @@ public class VoidDataType extends BuiltIn {
*
* @see ghidra.program.model.data.DataType#getMnemonic(Settings)
*/
@Override
public String getMnemonic(Settings settings) {
return "void";
}
@ -48,21 +48,16 @@ public class VoidDataType extends BuiltIn {
*
* @see ghidra.program.model.data.DataType#getLength()
*/
@Override
public int getLength() {
return 0;
}
/**
* @see ghidra.program.model.data.DataType#isDynamicallySized()
*/
public boolean isDynamicallySized() {
return false;
}
/**
*
* @see ghidra.program.model.data.DataType#getDescription()
*/
@Override
public String getDescription() {
return "void datatype";
}
@ -71,6 +66,7 @@ public class VoidDataType extends BuiltIn {
*
* @see ghidra.program.model.data.DataType#getRepresentation(MemBuffer, Settings, int)
*/
@Override
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
return "";
}
@ -79,10 +75,12 @@ public class VoidDataType extends BuiltIn {
*
* @see ghidra.program.model.data.DataType#getValue(ghidra.program.model.mem.MemBuffer, ghidra.docking.settings.Settings, int)
*/
@Override
public Object getValue(MemBuffer buf, Settings settings, int length) {
return null;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {
return this;

View file

@ -78,11 +78,6 @@ public class WAVEDataType extends BuiltIn implements Dynamic {
return false;
}
@Override
public boolean isDynamicallySized() {
return true;
}
@Override
public DataType clone(DataTypeManager dtm) {
if (dtm == getDataTypeManager()) {

View file

@ -23,8 +23,6 @@ import ghidra.util.StringUtilities;
public class WideChar16DataType extends BuiltIn implements ArrayStringable, DataTypeWithCharset {
private final static long serialVersionUID = 1;
/** A statically defined WideCharDataType instance.*/
public final static WideChar16DataType dataType = new WideChar16DataType();
@ -41,11 +39,6 @@ public class WideChar16DataType extends BuiltIn implements ArrayStringable, Data
return 2;
}
@Override
public boolean isDynamicallySized() {
return false;
}
@Override
public String getDescription() {
return "Wide-Character (16-bit/UTF16)";

Some files were not shown because too many files have changed in this diff Show more