Merge remote-tracking branch 'origin/GP-3279_ghizard_20230401_PDB_struct_union_conflicts_due_to_members_of_same_datatype_name_but_different_type--SQUASHED'

This commit is contained in:
Ryan Kurtz
2023-04-13 12:35:05 -04:00
3 changed files with 146 additions and 74 deletions
@@ -26,14 +26,14 @@ import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
/**
* <code>CompositeMember</code> provides the ability to process PDB data-type records and
* incrementally build-up composite structure and union data-types from a flattened offset-based
* list of members which may include embedded anonymous composite members. Composite members
* <code>CompositeMember</code> provides the ability to process PDB data-type records and
* incrementally build-up composite structure and union data-types from a flattened offset-based
* list of members which may include embedded anonymous composite members. Composite members
* correspond to either hard predefined data-types, or structure/union containers whose members
* are added and refined incrementally.
* are added and refined incrementally.
* <p>
* Container members are characterized by a null data-type name, zero length, and will be
* identified as either a structure or union.
* Container members are characterized by a null data-type name, zero length, and will be
* identified as either a structure or union.
*/
public class DefaultCompositeMember extends CompositeMember {
@@ -143,7 +143,7 @@ public class DefaultCompositeMember extends CompositeMember {
* @param componentOffset member offset within parent
* @param baseDataType bitfield base datatype
* @param bitSize bitfield size in bits
* @param bitOffsetWithinBaseType offset of bitfield within base type
* @param bitOffsetWithinBaseType offset of bitfield within base type
* @throws InvalidDataTypeException invalid baseDataType for bitfield
*/
private DefaultCompositeMember(int componentOffset, DataType baseDataType, int bitSize,
@@ -220,7 +220,7 @@ public class DefaultCompositeMember extends CompositeMember {
parent.memberNameChanged(oldMemberName, memberName);
}
catch (InvalidNameException | DuplicateNameException e) {
// exceptions are unexpected
// exceptions are unexpected
throw new AssertException(e);
}
}
@@ -309,7 +309,7 @@ public class DefaultCompositeMember extends CompositeMember {
}
/**
* Align container composite data type if possible.
* Align container composite data type if possible.
* @param preferredSize preferred size of composite if known, else <= 0 if unknown
*/
private void alignComposite(int preferredSize) {
@@ -335,11 +335,19 @@ public class DefaultCompositeMember extends CompositeMember {
composite.setToDefaultPacking();
}
else {
pack = 1;
copy.setExplicitPackingValue(pack);
copy.setToMachineAligned();
alignOK = isGoodAlignment(copy, preferredSize);
if (alignOK) {
composite.setExplicitPackingValue(pack);
composite.setToDefaultPacking();
composite.setToMachineAligned();
}
else {
pack = 1;
copy.setExplicitPackingValue(pack);
alignOK = isGoodAlignment(copy, preferredSize);
if (alignOK) {
composite.setExplicitPackingValue(pack);
}
}
}
if (!alignOK && errorConsumer != null && !isClass) { // don't complain about Class structs which always fail
@@ -503,7 +511,7 @@ public class DefaultCompositeMember extends CompositeMember {
* false if unable to resolve member's data-type or other error occurred.
* NOTE: there may be complex hierarchies not yet handled.
* @throws CancelledException if operation cancelled
* @throws DataTypeDependencyException if child's datatype can not be resolved.
* @throws DataTypeDependencyException if child's datatype can not be resolved.
* It may be possible to skip and continue with next child.
*/
private boolean addMember(PdbMember child, TaskMonitor monitor)
@@ -813,7 +821,7 @@ public class DefaultCompositeMember extends CompositeMember {
private boolean addStructureMember(DefaultCompositeMember member) {
try {
// check for conflict within structure container deferred
// check for conflict within structure container deferred
int conflictOffset = structureMemberRangeMap.getValue(member.memberOffset);
if (conflictOffset < 0) {
@@ -1086,10 +1094,10 @@ public class DefaultCompositeMember extends CompositeMember {
/**
* This method facilitates the removal and collection of all siblings of this
* member from its parent container. Only those siblings whose offset is greater
* than this member's offset will be included. The use of this method is necessary when
* a member sequence has been added to a structure container and it is later decided to
* push this member and its siblings into a new sub-composite. Before they can be
* member from its parent container. Only those siblings whose offset is greater
* than this member's offset will be included. The use of this method is necessary when
* a member sequence has been added to a structure container and it is later decided to
* push this member and its siblings into a new sub-composite. Before they can be
* added to the new container they must be removed from their current container
* using this method.
* @return list of sibling structure members removed from parent
@@ -1145,8 +1153,8 @@ public class DefaultCompositeMember extends CompositeMember {
}
/**
* Buildup an empty composite by applying datatype composite members.
* Only those children with a kind of "Member" will be processed.
* Buildup an empty composite by applying datatype composite members.
* Only those children with a kind of "Member" will be processed.
* @param composite empty composite to which members will be added
* @param isClass true if composite corresponds to a Class structure, else false
* @param preferredCompositeSize preferred size of composite, <= 0 indicates unknown
@@ -1195,8 +1203,8 @@ public class DefaultCompositeMember extends CompositeMember {
private static enum MemberType {
//@formatter:off
STRUCTURE,
UNION,
STRUCTURE,
UNION,
MEMBER;
//@formatter:on
@@ -97,22 +97,59 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
return;
}
dataType = createEmptyComposite((AbstractCompositeMsType) msType);
String mangledName = ((AbstractCompositeMsType) msType).getMangledName();
classType = new CppCompositeType((Composite) dataType, mangledName);
classType.setName(getName());
classType.setSize(DefaultPdbApplicator.bigIntegerToInt(applicator, getSize()));
if (msType instanceof AbstractClassMsType) {
classType.setClass();
}
else if (msType instanceof AbstractStructureMsType) {
classType.setStruct();
}
else if (msType instanceof AbstractUnionMsType) {
classType.setUnion();
}
classType.setFinal(isFinal());
SymbolPath sp = getFixedSymbolPath();
CategoryPath categoryPath = applicator.getCategory(sp.getParent());
ComboType c = getOrCreateComposite(applicator, this, (AbstractCompositeMsType) msType,
categoryPath, sp);
dataType = c.dt();
classType = c.ct();
}
private record ComboType(DataType dt, CppCompositeType ct) {
}
// DefaultPdbApplicator is passed in for bigIntegerToInt...
// TODO: find a better way... maybe eventually eliminate PdbMsgLog
private static ComboType getOrCreateComposite(DefaultPdbApplicator myApplicator,
AbstractComplexTypeApplier myCompositeApplier, AbstractCompositeMsType compositeMsType,
CategoryPath categoryPath, SymbolPath fixedSymbolPath) {
Composite myComposite;
CppCompositeType myClassType;
String mangledName = compositeMsType.getMangledName();
if (compositeMsType instanceof AbstractClassMsType) {
myApplicator.predefineClass(fixedSymbolPath);
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), 0,
myApplicator.getDataTypeManager());
myClassType = new CppCompositeType(myComposite, mangledName);
myClassType.setClass();
}
else if (compositeMsType instanceof AbstractStructureMsType) {
myComposite = new StructureDataType(categoryPath, fixedSymbolPath.getName(), 0,
myApplicator.getDataTypeManager());
myClassType = new CppCompositeType(myComposite, mangledName);
myClassType.setStruct();
}
else if (compositeMsType instanceof AbstractUnionMsType) {
myComposite = new UnionDataType(categoryPath, fixedSymbolPath.getName(),
myApplicator.getDataTypeManager());
myClassType = new CppCompositeType(myComposite, mangledName);
myClassType.setUnion();
}
else { // InterfaceMsType
String message = "Unsupported datatype (" + compositeMsType.getClass().getSimpleName() +
"): " + fixedSymbolPath.getPath();
myApplicator.appendLogMsg(message);
return null;
}
myClassType.setName(myCompositeApplier.getMsType().getName());
myClassType.setSize(
DefaultPdbApplicator.bigIntegerToInt(myApplicator, myCompositeApplier.getSize()));
myClassType.setFinal(compositeMsType.getMsProperty().isSealed());
return new ComboType(myComposite, myClassType);
}
@Override
@@ -146,11 +183,18 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
// TODO: Dome some output comparisons with and without the !isNested()
// test which is intended to ignore nested anonymous composites.
if (!isForwardReference() && !isNested()) {
if (!isForwardReference() && !isNested() && !isUnnamed()) {
super.resolve();
}
}
private boolean isUnnamed() {
if (msType instanceof AbstractClassMsType) {
return false;
}
return "__unnamed".equals(((AbstractComplexMsType) msType).getName());
}
private void applyOrDeferForDependencies() throws PdbException, CancelledException {
AbstractCompositeMsType type = (AbstractCompositeMsType) msType;
MsProperty property = type.getMsProperty();
@@ -202,7 +246,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
applicator.addApplierDependency(this, memberTypeApplierIterated);
}
}
if (!isDeferred()) {
if (!isDeferred() || isUnnamed()) {
applyInternal();
}
}
@@ -260,7 +304,11 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
if (isApplied()) {
return;
}
Composite composite = (Composite) dataType;
applyInternal((Composite) dataType);
setApplied();
}
private void applyInternal(Composite composite) throws CancelledException, PdbException {
AbstractCompositeMsType type = (AbstractCompositeMsType) msType;
@@ -272,13 +320,16 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
"Unexpected base classes for union type: " + type.getName());
}
}
if (isUnnamed()) {
applyCpp = false;
}
if (applyCpp) {
applyCpp(composite, type);
}
else {
applyBasic(composite, type);
}
setApplied();
}
//==============================================================================================
@@ -384,6 +435,35 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
return dataType;
}
/**
* Returns a datatype or a newly minted datatype if it is an unnamed datatype. In the latter
* case, the type is put into an internal category of the parent and the name is given
* a suffix based on the ordinal within the parent
* @param categoryPath the CategoryPath
* @param ordinal the ordinal
* @return the Datatype
* @throws CancelledException upon user cancellation
* @throws PdbException upon error
*/
DataType getDataType(CategoryPath categoryPath, int ordinal)
throws CancelledException, PdbException {
if (!isUnnamed()) {
return getDataType();
}
return mintNestedUnnamedDataType(categoryPath, ordinal);
}
private DataType mintNestedUnnamedDataType(CategoryPath categoryPath, int ordinal)
throws CancelledException, PdbException {
SymbolPath sp = getFixedSymbolPath();
SymbolPath modifiedSymbolPath =
new SymbolPath(sp.getParent(), sp.getName() + "_" + ordinal);
ComboType c = getOrCreateComposite(applicator, this, (AbstractCompositeMsType) msType,
categoryPath, modifiedSymbolPath);
applyInternal((Composite) c.dt());
return c.dt();
}
@Override
DataType getCycleBreakType() {
if (isForwardReference() && definitionApplier != null && definitionApplier.isApplied()) {
@@ -416,34 +496,6 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
}
private Composite createEmptyComposite(AbstractCompositeMsType type) {
SymbolPath fixedPath = getFixedSymbolPath();
CategoryPath categoryPath = applicator.getCategory(fixedPath.getParent());
Composite composite;
if (type instanceof AbstractClassMsType) {
applicator.predefineClass(fixedPath);
composite = new StructureDataType(categoryPath, fixedPath.getName(), 0,
applicator.getDataTypeManager());
}
else if (type instanceof AbstractStructureMsType) {
composite = new StructureDataType(categoryPath, fixedPath.getName(), 0,
applicator.getDataTypeManager());
}
else if (type instanceof AbstractUnionMsType) {
composite = new UnionDataType(categoryPath, fixedPath.getName(),
applicator.getDataTypeManager());
}
else { // InterfaceMsType
String message = "Unsupported datatype (" + type.getClass().getSimpleName() + "): " +
fixedPath.getPath();
applicator.appendLogMsg(message);
return null;
}
return composite;
}
private boolean hasBaseClasses() {
AbstractCompositeMsType defType;
if (definitionApplier == null) {
@@ -644,7 +696,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
return new CppCompositeType.ClassFieldAttributes(myAccess, myProperty);
}
private void addMembers(Composite composite, FieldListTypeApplier fieldListApplier) {
private void addMembers(Composite composite, FieldListTypeApplier fieldListApplier)
throws CancelledException, PdbException {
AbstractCompositeMsType type = (AbstractCompositeMsType) msType;
@@ -660,6 +713,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
memberAttributes.getAccess(); // TODO: do something with this and other attributes
MsTypeApplier fieldApplier = memberTypeApplier.getFieldTypeApplier();
DataType fieldDataType = null;
if (fieldApplier instanceof CompositeTypeApplier) {
CompositeTypeApplier defApplier =
((CompositeTypeApplier) fieldApplier).getDefinitionApplier(
@@ -667,8 +721,12 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
if (defApplier != null) {
fieldApplier = defApplier;
}
fieldDataType = ((CompositeTypeApplier) fieldApplier).getDataType(
ClassTypeUtils.getInternalsCategoryPath(this), members.size());
}
if (fieldDataType == null) {
fieldDataType = fieldApplier.getDataType();
}
DataType fieldDataType = fieldApplier.getDataType();
boolean isFlexibleArray;
if (fieldApplier instanceof ArrayTypeApplier) {
isFlexibleArray = ((ArrayTypeApplier) fieldApplier).isFlexibleArray();
@@ -676,7 +734,13 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
else {
isFlexibleArray = false;
}
if (fieldDataType == null) {
if (fieldApplier instanceof CompositeTypeApplier &&
((CompositeTypeApplier) fieldApplier).isUnnamed()) {
DefaultPdbUniversalMember member = new DefaultPdbUniversalMember(applicator,
memberName, fieldDataType, offset);
members.add(member);
}
else if (fieldDataType == null) {
if (fieldApplier instanceof PrimitiveTypeApplier &&
((PrimitiveTypeApplier) fieldApplier).isNoType()) {
DefaultPdbUniversalMember member = new DefaultPdbUniversalMember(applicator,
@@ -101,7 +101,7 @@ public class DefaultPdbUniversalMember extends PdbMember {
DataType dt = getDataTypeInternal();
if (dt instanceof PdbBitField) {
PdbBitField bfDt = (PdbBitField) dataType;
PdbBitField bfDt = (PdbBitField) dt;
builder.append(", type=");
builder.append(bfDt.getBaseDataType().getName());
builder.append(", offset=");
@@ -113,7 +113,7 @@ public class DefaultPdbUniversalMember extends PdbMember {
}
else {
builder.append(", type=");
builder.append(dataType.getName());
builder.append(dt.getName());
builder.append(", offset=");
builder.append(getOffset());
}