diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/ApplyDataTypes.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/ApplyDataTypes.java index f108377c72..1e8687cf36 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/ApplyDataTypes.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/ApplyDataTypes.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -121,9 +121,9 @@ public class ApplyDataTypes { Composite composite = (Composite) cachedDataType; PdbUtil.clearComponents(composite); - if (!DefaultCompositeMember.applyDataTypeMembers(composite, compositeDefinition.isClass, - compositeDefinition.length, getNormalMembersOnly(compositeDefinition), - msg -> Msg.warn(this, msg), monitor)) { + if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, + compositeDefinition.isClass, compositeDefinition.length, + getNormalMembersOnly(compositeDefinition), msg -> Msg.warn(this, msg), monitor)) { PdbUtil.clearComponents(composite); } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/BitFieldGroupCompositeMember.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/BitFieldGroupCompositeMember.java index 608a6aebae..13fa5318c6 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/BitFieldGroupCompositeMember.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/BitFieldGroupCompositeMember.java @@ -22,9 +22,9 @@ import ghidra.program.model.data.BitFieldDataType; import ghidra.program.model.data.DataType; /** - * BitFieldGroupCompositeMember provides the ability to collect related + * BitFieldGroupCompositeMember provides the ability to collect related * {@link DefaultCompositeMember} members within a group during the composite reconstruction - * process. + * process. */ public class BitFieldGroupCompositeMember extends CompositeMember { @@ -128,7 +128,7 @@ public class BitFieldGroupCompositeMember extends CompositeMember { } @Override - void finalizeDataType(int preferredSize) { + void finalizeDataType(int preferredSize, boolean packingDisabled) { return; // nothing to do } @@ -149,8 +149,8 @@ public class BitFieldGroupCompositeMember extends CompositeMember { /** * Add a new member to the end of this bit-field group. The caller should ensure that the - * specified member is a suitable addition to this group (must be single bit field whose - * member offset and length match this group's). + * specified member is a suitable addition to this group (must be single bit field whose + * member offset and length match this group's). * @param member bit-field member (must have data type of BitFieldDataType). * @throws IllegalArgumentException if specified member is not suitable for this group. */ diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/CompositeMember.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/CompositeMember.java index 310d30295b..206201c158 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/CompositeMember.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/CompositeMember.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,12 +25,14 @@ abstract class CompositeMember { /** * Due to the dynamic restructuring of data type containers, this method should be invoked - * on the root container prior to adding or applying the associated data type to the program. - * This method will appropriately rename and categorize associated anonymous structures and + * on the root container prior to adding or applying the associated data type to the program. + * This method will appropriately rename and categorize associated anonymous structures and * unions to reflect the final organization and check if internal alignment should be enabled. * @param preferredSize preferred size of composite if known, else <= 0 if unknown + * @param packingDisabled {@code true} to disable any attempted use of packing on this + * composite or any of its generated composite dependencies */ - abstract void finalizeDataType(int preferredSize); + abstract void finalizeDataType(int preferredSize, boolean packingDisabled); /** * Determine if this member is a container @@ -58,7 +60,7 @@ abstract class CompositeMember { /** * Determine if this member is a bit-field member not yet contained within a group. - * If true is returned this instance is ensured to be a {@link DefaultCompositeMember} instance + * If true is returned this instance is ensured to be a {@link DefaultCompositeMember} instance * whose data type is {@link BitFieldDataType}. * @return true if bit-field member not yet contained within a group */ @@ -96,16 +98,17 @@ abstract class CompositeMember { abstract void setParent(DefaultCompositeMember parent); /** - * Add specified member to this member. If this member is not a composite - * it will trigger the creation - * @param member - * @return + * Add specified member to this member. If this member is not a composite + * it will trigger the creation + * @param member the member to be added + * @return {@code true} if the specified member was successfully added to this member */ abstract boolean addMember(DefaultCompositeMember member); /** * Instructs this member to add itself to the specified structure * @param structure composite structure + * @return {@code true} if this member was successfully added to the specified structure */ abstract boolean addToStructure(DefaultCompositeMember structure); } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/DefaultCompositeMember.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/DefaultCompositeMember.java index 4950646256..6307836a97 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/DefaultCompositeMember.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/DefaultCompositeMember.java @@ -64,7 +64,7 @@ public class DefaultCompositeMember extends CompositeMember { private TreeMap structureMemberOffsetMap; private RangeMap structureMemberRangeMap; private int largestPrimitiveSize; - private boolean hasPadding = false; + private boolean hasStructurePadding = false; // Union container data private List unionMemberList; @@ -250,7 +250,7 @@ public class DefaultCompositeMember extends CompositeMember { } @Override - void finalizeDataType(int preferredSize) { + void finalizeDataType(int preferredSize, boolean packingDisabled) { if (!isContainer()) { return; } @@ -258,7 +258,7 @@ public class DefaultCompositeMember extends CompositeMember { updateContainerNameAndCategoryPath("s"); CompositeMember lastMember = null; for (CompositeMember member : structureMemberOffsetMap.values()) { - member.finalizeDataType(0); + member.finalizeDataType(0, packingDisabled); lastMember = member; } transformLastMemberIntoFlexArray(lastMember); @@ -269,10 +269,10 @@ public class DefaultCompositeMember extends CompositeMember { else if (isUnionContainer()) { updateContainerNameAndCategoryPath("u"); for (CompositeMember member : unionMemberList) { - member.finalizeDataType(0); + member.finalizeDataType(0, packingDisabled); } } - alignComposite(preferredSize); + alignComposite(preferredSize, packingDisabled); } /** @@ -318,8 +318,10 @@ public class DefaultCompositeMember extends CompositeMember { /** * Align container composite data type if possible. * @param preferredSize preferred size of composite if known, else <= 0 if unknown + * @param packingDisabled {@code true} to disable any attempted use of packing on this + * composite or any of its generated composite dependencies */ - private void alignComposite(int preferredSize) { + private void alignComposite(int preferredSize, boolean packingDisabled) { Composite composite = (Composite) memberDataType; @@ -333,6 +335,20 @@ public class DefaultCompositeMember extends CompositeMember { return; } + // Try to get unions to get to the preferred size by adding a padding member + if (composite instanceof Union && preferredSize > composite.getAlignedLength()) { + ArrayDataType padding = new ArrayDataType(CharDataType.dataType, preferredSize); + composite.add(padding, PADDING_COMPONENT_NAME, ""); + } + + if (packingDisabled) { + if (composite instanceof Structure) { + removeAllPadding(composite); // includes bit-field padding + } + setComputedAlignment(composite); + return; + } + Composite copy = (Composite) composite.copy(dataTypeManager); int pack = 0; @@ -341,18 +357,18 @@ public class DefaultCompositeMember extends CompositeMember { boolean alignOK = isGoodAlignment(copy, preferredSize); if (alignOK) { composite.setToDefaultPacking(); - if (hasPadding) { + if (hasStructurePadding) { removeUnnecessaryPadding(composite); } } - else { + else if (composite instanceof Structure) { if (preferredSize > 0 && copy.getLength() != preferredSize) { copy.setToMachineAligned(); // will only impact structure length alignOK = isGoodAlignment(copy, preferredSize); if (alignOK) { composite.setToDefaultPacking(); composite.setToMachineAligned(); - if (hasPadding) { + if (hasStructurePadding) { removeUnnecessaryPadding(composite); } } @@ -362,7 +378,7 @@ public class DefaultCompositeMember extends CompositeMember { } if (!alignOK) { removeAllPadding(composite); // includes bit-field padding - if (!hasPadding) { + if (!hasStructurePadding) { pack = 1; copy.setExplicitPackingValue(pack); alignOK = isGoodAlignment(copy, preferredSize); @@ -372,13 +388,46 @@ public class DefaultCompositeMember extends CompositeMember { } } } - if (!alignOK && errorConsumer != null && !isClass) { // don't complain about Class structs which always fail + // Unions fall through to here + if (!alignOK) { + setComputedAlignment(composite); + } + // Don't complain about Class structs which always fail... this might always be true + // for the MSDIA analyzer, but we hope classes will align better with PDB Universal in + // the future + if (!alignOK && errorConsumer != null && !isClass) { String anonymousStr = parent != null ? " anonymous " : ""; errorConsumer.accept("PDB " + anonymousStr + memberType + " reconstruction failed to align " + composite.getPathName()); } } + /** + * Computes and sets the alignment of the composite. Will not set an alignment if the + * calculation does not make sense + * @param composite the composite to affect + */ + private void setComputedAlignment(Composite composite) { + // Only need to compute alignment from immediate child components, as those components + // would have already seen this method in their calculations. + // If any component of the composite is not at an offset that is a multiple of that + // comonent's alignment, then abort setting the composite alignment + int compositeAlignment = 1; + for (DataTypeComponent dtc : composite.getDefinedComponents()) { + DataType dt = dtc.getDataType(); + int offset = dtc.getOffset(); + int alignment = dt.getAlignment(); + if (offset % alignment != 0) { + return; + } + compositeAlignment = Integer.max(compositeAlignment, alignment); + } + if (composite.getLength() % compositeAlignment != 0) { + return; + } + composite.align(compositeAlignment); + } + private void removeUnnecessaryPadding(Composite packedComposite) { if (!packedComposite.isPackingEnabled()) { throw new IllegalArgumentException("composite must have packing enabled"); @@ -507,7 +556,7 @@ public class DefaultCompositeMember extends CompositeMember { structureMemberRangeMap = new RangeMap(-1); // allow padding size to use pointer-size and smaller by default largestPrimitiveSize = memberDataType.getDataOrganization().getPointerSize(); - hasPadding = false; + hasStructurePadding = false; unionMemberList = null; } else { @@ -750,8 +799,8 @@ public class DefaultCompositeMember extends CompositeMember { /** * Insert minimal padding into structure prior to the addition of a component such that packing * will allow component to be placed at intended offset. - * @param nextComponentOffset - * @param dt + * @param nextComponentOffset + * @param dt */ private void insertMinimalStructurePadding(int nextComponentOffset, DataType dt) { @@ -786,7 +835,7 @@ public class DefaultCompositeMember extends CompositeMember { int paddingOffset = DataOrganizationImpl.getAlignedOffset(paddingDt.getAlignment(), structLen); struct.insertAtOffset(paddingOffset, paddingDt, -1, PADDING_COMPONENT_NAME, null); - hasPadding = true; + hasStructurePadding = true; structLen = struct.getLength(); fillSpace = nextComponentOffset - structLen; @@ -1296,6 +1345,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. * @param composite empty composite to which members will be added + * @param packingDisabled {@code true} to disable any attempted use of packing on this + * composite or any of its generated composite dependencies * @param isClass true if composite corresponds to a Class structure, else false * @param preferredCompositeSize preferred size of composite, <= 0 indicates unknown * @param members list of composite members @@ -1304,9 +1355,10 @@ public class DefaultCompositeMember extends CompositeMember { * @return true if members successfully added to composite * @throws CancelledException if monitor is cancelled */ - public static boolean applyDataTypeMembers(Composite composite, boolean isClass, - int preferredCompositeSize, List members, - Consumer errorConsumer, TaskMonitor monitor) throws CancelledException { + public static boolean applyDataTypeMembers(Composite composite, boolean packingDisabled, + boolean isClass, int preferredCompositeSize, + List members, Consumer errorConsumer, TaskMonitor monitor) + throws CancelledException { Composite editComposite = composite; @@ -1332,7 +1384,7 @@ public class DefaultCompositeMember extends CompositeMember { } } - rootMember.finalizeDataType(preferredCompositeSize); + rootMember.finalizeDataType(preferredCompositeSize, packingDisabled); return true; } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java index 301a583e89..ce3e0fb3b5 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java @@ -163,7 +163,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier { addVftPtrs(composite, classType, lists.vftPtrs(), type, myMembers); addMembers(composite, classType, lists.nonstaticMembers(), type, myMembers); - if (!DefaultCompositeMember.applyDataTypeMembers(composite, isClass, size, myMembers, + if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, isClass, size, myMembers, msg -> reconstructionWarn(msg, hasHiddenComponents(lists)), applicator.getCancelOnlyWrappingMonitor())) { clearComponents(composite); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeType.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeType.java index 5b3eec0ece..47be665a92 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeType.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeType.java @@ -686,7 +686,7 @@ public class CppCompositeType { addLayoutPdbMembers(directClassPdbMembers, layoutMembers); insertVirtualFunctionTablePointers(directClassPdbMembers); - if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, 0, + if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, false, 0, directClassPdbMembers, msg -> Msg.warn(this, msg), monitor)) { clearComponents(directDataType); } @@ -706,7 +706,8 @@ public class CppCompositeType { directDataType = new StructureDataType(cn.getParent(), cn.getName(), 0, composite.getDataTypeManager()); if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, - size, directClassPdbMembers, msg -> Msg.warn(this, msg), monitor)) { + false, size, directClassPdbMembers, msg -> Msg.warn(this, msg), + monitor)) { clearComponents(directDataType); } directClassLength = getCompositeLength(directDataType); @@ -735,7 +736,7 @@ public class CppCompositeType { throw new PdbException("Unhandled layout mode"); } - if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, size, memberData, + if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, false, size, memberData, msg -> Msg.warn(this, msg), monitor)) { clearComponents(composite); } @@ -826,7 +827,7 @@ public class CppCompositeType { addLayoutPdbMembers(directClassPdbMembers, layoutMembers); insertVirtualFunctionTablePointers(directClassPdbMembers); - if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, 0, + if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, false, 0, directClassPdbMembers, msg -> Msg.warn(this, msg), monitor)) { clearComponents(directDataType); } @@ -846,7 +847,8 @@ public class CppCompositeType { directDataType = new StructureDataType(cn.getParent(), cn.getName(), 0, composite.getDataTypeManager()); if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, - size, directClassPdbMembers, msg -> Msg.warn(this, msg), monitor)) { + false, size, directClassPdbMembers, msg -> Msg.warn(this, msg), + monitor)) { clearComponents(directDataType); } directClassLength = getCompositeLength(directDataType); @@ -875,7 +877,7 @@ public class CppCompositeType { throw new PdbException("Unhandled layout mode"); } - if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, size, memberData, + if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, false, size, memberData, msg -> Msg.warn(this, msg), monitor)) { clearComponents(composite); } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java index 0446724034..08a6f2d242 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java @@ -545,7 +545,7 @@ public class PdbResearch { members.add(member); size += extra.getLength(); } - if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, size, members, + if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, false, size, members, msg -> reconstructionWarn(msg), monitor)) { ((Structure) composite).deleteAll(); } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/VtShapeTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/VtShapeTypeApplier.java index 817ae84cb5..7315c5a4c0 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/VtShapeTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/VtShapeTypeApplier.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -127,7 +127,7 @@ public class VtShapeTypeApplier extends MsDataTypeApplier { members.add(member); } // offset has the total size at this point - if (!DefaultCompositeMember.applyDataTypeMembers(shape, false, offset, members, + if (!DefaultCompositeMember.applyDataTypeMembers(shape, false, false, offset, members, msg -> Msg.warn(this, msg), applicator.getCancelOnlyWrappingMonitor())) { CompositeTypeApplier.clearComponents(shape); } diff --git a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/CompositeMemberTest.java b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/CompositeMemberTest.java index 8ca817fab5..853c854d07 100644 --- a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/CompositeMemberTest.java +++ b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/CompositeMemberTest.java @@ -107,12 +107,12 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest public void testUnionWithStructureOfBitFieldsWithPadding() throws Exception { /** - + - + union TestUnion { struct { int :32; @@ -122,7 +122,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest }; short fieldSHORT; }; - + */ UnionDataType union = new UnionDataType(CategoryPath.ROOT, "testUnion", dataMgr); @@ -135,26 +135,26 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest ); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(union, false, 8, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(union, false, false, 8, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/testUnion\n" + - "pack()\n" + - "Union testUnion {\n" + - " 0 testUnion_s_0 8 _s_0 \"\"\n" + - " 0 short 2 fieldSHORT \"\"\n" + - "}\n" + - "Length: 8 Alignment: 4\n" + - "/testUnion/testUnion_s_0\n" + - "pack()\n" + - "Structure testUnion_s_0 {\n" + - " 0 int 4 _padding_ \"\"\n" + - " 4 int:11(0) 2 _padding_ \"\"\n" + - " 5 int:1(3) 1 field1 \"\"\n" + - " 5 int:4(4) 1 field2 \"\"\n" + - "}\n" + + "/testUnion\n" + + "pack()\n" + + "Union testUnion {\n" + + " 0 testUnion_s_0 8 _s_0 \"\"\n" + + " 0 short 2 fieldSHORT \"\"\n" + + "}\n" + + "Length: 8 Alignment: 4\n" + + "/testUnion/testUnion_s_0\n" + + "pack()\n" + + "Structure testUnion_s_0 {\n" + + " 0 int 4 _padding_ \"\"\n" + + " 4 int:11(0) 2 _padding_ \"\"\n" + + " 5 int:1(3) 1 field1 \"\"\n" + + " 5 int:4(4) 1 field2 \"\"\n" + + "}\n" + "Length: 8 Alignment: 4", union, true); //@formatter:on } @@ -174,21 +174,21 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "ushort", 8)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 12, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 12, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack()\n" + - "Structure struct {\n" + - " 0 uchar 1 a \"\"\n" + - " 1 uchar:4(0) 1 b \"\"\n" + - " 1 uchar:4(4) 1 c \"\"\n" + - " 2 uchar:4(0) 1 d \"\"\n" + - " 4 uint:4(0) 1 e \"\"\n" + - " 8 ushort 2 f \"\"\n" + - "}\n" + + "/struct\n" + + "pack()\n" + + "Structure struct {\n" + + " 0 uchar 1 a \"\"\n" + + " 1 uchar:4(0) 1 b \"\"\n" + + " 1 uchar:4(4) 1 c \"\"\n" + + " 2 uchar:4(0) 1 d \"\"\n" + + " 4 uint:4(0) 1 e \"\"\n" + + " 8 ushort 2 f \"\"\n" + + "}\n" + "Length: 12 Alignment: 4", struct); //@formatter:on } @@ -209,21 +209,21 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "ushort", 7)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 9, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 9, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack(1)\n" + - "Structure struct {\n" + - " 0 uchar 1 a \"\"\n" + - " 1 uchar:4(0) 1 b \"\"\n" + - " 1 uchar:4(4) 1 c \"\"\n" + - " 2 uchar:4(0) 1 d \"\"\n" + - " 3 uint:4(0) 1 e \"\"\n" + - " 7 ushort 2 f \"\"\n" + - "}\n" + + "/struct\n" + + "pack(1)\n" + + "Structure struct {\n" + + " 0 uchar 1 a \"\"\n" + + " 1 uchar:4(0) 1 b \"\"\n" + + " 1 uchar:4(4) 1 c \"\"\n" + + " 2 uchar:4(0) 1 d \"\"\n" + + " 3 uint:4(0) 1 e \"\"\n" + + " 7 ushort 2 f \"\"\n" + + "}\n" + "Length: 9 Alignment: 1", struct, true); //@formatter:on } @@ -242,19 +242,19 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "ushort", 7)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 9, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 9, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack(disabled)\n" + - "Structure struct {\n" + - " 0 uchar 1 a \"\"\n" + - " 1 uchar:4(0) 1 b \"\"\n" + - " 3 uint:4(0) 1 e \"\"\n" + - " 7 ushort 2 f \"\"\n" + - "}\n" + + "/struct\n" + + "pack(disabled)\n" + + "Structure struct {\n" + + " 0 uchar 1 a \"\"\n" + + " 1 uchar:4(0) 1 b \"\"\n" + + " 3 uint:4(0) 1 e \"\"\n" + + " 7 ushort 2 f \"\"\n" + + "}\n" + "Length: 9 Alignment: 1", struct, true); //@formatter:on } @@ -275,24 +275,60 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "ushort", 8)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 12, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 12, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack()\n" + - "Structure struct {\n" + - " 0 uchar 1 a \"\"\n" + - " 1 uchar:2(0) 1 _padding_ \"\"\n" + - " 1 uchar:2(2) 1 b \"\"\n" + - " 1 uchar:1(4) 1 c1 \"\"\n" + - " 1 uchar:1(5) 1 _padding_ \"\"\n" + - " 1 uchar:1(6) 1 c2 \"\"\n" + - " 2 uchar:7(0) 1 d \"\"\n" + - " 4 uint:4(0) 1 e \"\"\n" + - " 8 ushort 2 f \"\"\n" + - "}\n" + + "/struct\n" + + "pack()\n" + + "Structure struct {\n" + + " 0 uchar 1 a \"\"\n" + + " 1 uchar:2(0) 1 _padding_ \"\"\n" + + " 1 uchar:2(2) 1 b \"\"\n" + + " 1 uchar:1(4) 1 c1 \"\"\n" + + " 1 uchar:1(5) 1 _padding_ \"\"\n" + + " 1 uchar:1(6) 1 c2 \"\"\n" + + " 2 uchar:7(0) 1 d \"\"\n" + + " 4 uint:4(0) 1 e \"\"\n" + + " 8 ushort 2 f \"\"\n" + + "}\n" + + "Length: 12 Alignment: 4", struct, true); + //@formatter:on + } + + @Test + public void testSimpleStructureWithFillerBitFieldsPackingDisabled() throws Exception { + + StructureDataType struct = new StructureDataType("struct", 0, dataMgr); + + //@formatter:off + List members = + CollectionUtils.asList(new MyPdbMember("a", "uchar", 0), + new MyPdbMember("b:0x2:0x2", "uchar", 1), + new MyPdbMember("c1:0x1:0x4", "uchar", 1), + new MyPdbMember("c2:0x1:0x6", "uchar", 1), + new MyPdbMember("d:0x7:0x0", "uchar", 2), + new MyPdbMember("e:0x4:0x0", "uint", 4), + new MyPdbMember("f", "ushort", 8)); + //@formatter:on + + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, true, false, 12, members, + this, TaskMonitor.DUMMY)); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, + "/struct\n" + + "aligned(4) pack(disabled)\n" + + "Structure struct {\n" + + " 0 uchar 1 a \"\"\n" + + " 1 uchar:2(2) 1 b \"\"\n" + + " 1 uchar:1(4) 1 c1 \"\"\n" + + " 1 uchar:1(6) 1 c2 \"\"\n" + + " 2 uchar:7(0) 1 d \"\"\n" + + " 4 uint:4(0) 1 e \"\"\n" + + " 8 ushort 2 f \"\"\n" + + "}\n" + "Length: 12 Alignment: 4", struct, true); //@formatter:on } @@ -301,7 +337,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest public void testUnionedStructuresWithFillerBitFields() throws Exception { /*** Structure Source *** - + struct BitFieldUnionAlternatingPadded_s { union { struct { @@ -322,7 +358,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest }; }; }; - + */ StructureDataType struct = new StructureDataType("struct", 0, dataMgr); @@ -338,44 +374,44 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("a5:0x1:0x5", "char", 0)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 1, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 1, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack()\n" + - "Structure struct {\n" + - " 0 struct_u_0 1 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/struct/struct_u_0\n" + - "pack()\n" + - "Union struct_u_0 {\n" + - " 0 struct_u_0_s_0 1 _s_0 \"\"\n" + - " 0 struct_u_0_s_1 1 _s_1 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/struct/struct_u_0/struct_u_0_s_0\n" + - "pack()\n" + - "Structure struct_u_0_s_0 {\n" + - " 0 char:1(0) 1 a0 \"\"\n" + - " 0 char:1(1) 1 _padding_ \"\"\n" + - " 0 char:1(2) 1 a2 \"\"\n" + - " 0 char:1(3) 1 _padding_ \"\"\n" + - " 0 char:1(4) 1 a4 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/struct/struct_u_0/struct_u_0_s_1\n" + - "pack()\n" + - "Structure struct_u_0_s_1 {\n" + - " 0 char:1(0) 1 _padding_ \"\"\n" + - " 0 char:1(1) 1 a1 \"\"\n" + - " 0 char:1(2) 1 _padding_ \"\"\n" + - " 0 char:1(3) 1 a3 \"\"\n" + - " 0 char:1(4) 1 _padding_ \"\"\n" + - " 0 char:1(5) 1 a5 \"\"\n" + - "}\n" + + "/struct\n" + + "pack()\n" + + "Structure struct {\n" + + " 0 struct_u_0 1 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/struct/struct_u_0\n" + + "pack()\n" + + "Union struct_u_0 {\n" + + " 0 struct_u_0_s_0 1 _s_0 \"\"\n" + + " 0 struct_u_0_s_1 1 _s_1 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/struct/struct_u_0/struct_u_0_s_0\n" + + "pack()\n" + + "Structure struct_u_0_s_0 {\n" + + " 0 char:1(0) 1 a0 \"\"\n" + + " 0 char:1(1) 1 _padding_ \"\"\n" + + " 0 char:1(2) 1 a2 \"\"\n" + + " 0 char:1(3) 1 _padding_ \"\"\n" + + " 0 char:1(4) 1 a4 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/struct/struct_u_0/struct_u_0_s_1\n" + + "pack()\n" + + "Structure struct_u_0_s_1 {\n" + + " 0 char:1(0) 1 _padding_ \"\"\n" + + " 0 char:1(1) 1 a1 \"\"\n" + + " 0 char:1(2) 1 _padding_ \"\"\n" + + " 0 char:1(3) 1 a3 \"\"\n" + + " 0 char:1(4) 1 _padding_ \"\"\n" + + " 0 char:1(5) 1 a5 \"\"\n" + + "}\n" + "Length: 1 Alignment: 1", struct, true); //@formatter:on } @@ -394,40 +430,40 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("b:0x4:0x0", "uchar", 0), new MyPdbMember("c:0x4:0x4", "uchar", 0), new MyPdbMember("d:0x4:0x0", "uchar", 0), - new MyPdbMember("e:0x4:0x4", "uchar", 0), + new MyPdbMember("e:0x4:0x4", "uchar", 0), new MyPdbMember("f", "ushort", 0)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(union, false, 2, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(union, false, false, 2, members, + this, TaskMonitor.DUMMY)); // NOTE: handling of bit-fields within union is rather ambiguous within // PDB data //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/union\n" + - "pack()\n" + - "Union union {\n" + - " 0 uchar 1 a \"\"\n" + - " 0 union_s_1 1 _s_1 \"\"\n" + - " 0 union_s_2 1 _s_2 \"\"\n" + - " 0 ushort 2 f \"\"\n" + - "}\n" + - "Length: 2 Alignment: 2\n" + - "/union/union_s_1\n" + - "pack()\n" + - "Structure union_s_1 {\n" + - " 0 uchar:4(0) 1 b \"\"\n" + - " 0 uchar:4(4) 1 c \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/union/union_s_2\n" + - "pack()\n" + - "Structure union_s_2 {\n" + - " 0 uchar:4(0) 1 d \"\"\n" + - " 0 uchar:4(4) 1 e \"\"\n" + - "}\n" + + "/union\n" + + "pack()\n" + + "Union union {\n" + + " 0 uchar 1 a \"\"\n" + + " 0 union_s_1 1 _s_1 \"\"\n" + + " 0 union_s_2 1 _s_2 \"\"\n" + + " 0 ushort 2 f \"\"\n" + + "}\n" + + "Length: 2 Alignment: 2\n" + + "/union/union_s_1\n" + + "pack()\n" + + "Structure union_s_1 {\n" + + " 0 uchar:4(0) 1 b \"\"\n" + + " 0 uchar:4(4) 1 c \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/union/union_s_2\n" + + "pack()\n" + + "Structure union_s_2 {\n" + + " 0 uchar:4(0) 1 d \"\"\n" + + " 0 uchar:4(4) 1 e \"\"\n" + + "}\n" + "Length: 1 Alignment: 1", union, true); //@formatter:on } @@ -444,17 +480,17 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("e", "char[0]", 1)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 1, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 1, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack()\n" + - "Structure struct {\n" + - " 0 char 1 a \"\"\n" + - " 1 char[0] 0 e \"\"\n" + - "}\n" + + "/struct\n" + + "pack()\n" + + "Structure struct {\n" + + " 0 char 1 a \"\"\n" + + " 1 char[0] 0 e \"\"\n" + + "}\n" + "Length: 1 Alignment: 1", struct, true); //@formatter:on } @@ -475,33 +511,34 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "char[0]", 8)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 16, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 16, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/union\n" + - "pack()\n" + - "Union union {\n" + - " 0 union_s_0 12 _s_0 \"\"\n" + - " 0 union_s_1 8 _s_1 \"\"\n" + - "}\n" + - "Length: 16 Alignment: 8\n" + - "/union/union_s_0\n" + - "pack()\n" + - "Structure union_s_0 {\n" + - " 0 int 4 a \"\"\n" + - " 4 int 4 b \"\"\n" + - " 8 int 4 c \"\"\n" + - " 12 char[0] 0 d \"\"\n" + - "}\n" + - "Length: 12 Alignment: 4\n" + - "/union/union_s_1\n" + - "pack()\n" + - "Structure union_s_1 {\n" + - " 0 longlong 8 e \"\"\n" + - " 8 char[0] 0 f \"\"\n" + - "}\n" + + "/union\n" + + "pack()\n" + + "Union union {\n" + + " 0 union_s_0 12 _s_0 \"\"\n" + + " 0 union_s_1 8 _s_1 \"\"\n" + + " 0 char[16] 16 _padding_ \"\"\n" + + "}\n" + + "Length: 16 Alignment: 8\n" + + "/union/union_s_0\n" + + "pack()\n" + + "Structure union_s_0 {\n" + + " 0 int 4 a \"\"\n" + + " 4 int 4 b \"\"\n" + + " 8 int 4 c \"\"\n" + + " 12 char[0] 0 d \"\"\n" + + "}\n" + + "Length: 12 Alignment: 4\n" + + "/union/union_s_1\n" + + "pack()\n" + + "Structure union_s_1 {\n" + + " 0 longlong 8 e \"\"\n" + + " 8 char[0] 0 f \"\"\n" + + "}\n" + "Length: 8 Alignment: 8\n", struct, true); //@formatter:on } @@ -521,32 +558,32 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "char[0]", 0)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 12, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 12, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/union\n" + - "pack()\n" + - "Union union {\n" + - " 0 union_s_0 12 _s_0 \"\"\n" + - " 0 union_s_1 0 _s_1 \"\"\n" + - "}\n" + - "Length: 12 Alignment: 4\n" + - "/union/union_s_0\n" + - "pack()\n" + - "Structure union_s_0 {\n" + - " 0 int 4 a \"\"\n" + - " 4 int 4 b \"\"\n" + - " 8 int 4 c \"\"\n" + - " 12 char[0] 0 d \"\"\n" + - "}\n" + - "Length: 12 Alignment: 4\n" + - "/union/union_s_1\n" + - "pack()\n" + - "Structure union_s_1 {\n" + - " 0 char[0] 0 f \"\"\n" + - "}\n" + + "/union\n" + + "pack()\n" + + "Union union {\n" + + " 0 union_s_0 12 _s_0 \"\"\n" + + " 0 union_s_1 0 _s_1 \"\"\n" + + "}\n" + + "Length: 12 Alignment: 4\n" + + "/union/union_s_0\n" + + "pack()\n" + + "Structure union_s_0 {\n" + + " 0 int 4 a \"\"\n" + + " 4 int 4 b \"\"\n" + + " 8 int 4 c \"\"\n" + + " 12 char[0] 0 d \"\"\n" + + "}\n" + + "Length: 12 Alignment: 4\n" + + "/union/union_s_1\n" + + "pack()\n" + + "Structure union_s_1 {\n" + + " 0 char[0] 0 f \"\"\n" + + "}\n" + "Length: 0 Alignment: 1\n", struct, true); //@formatter:on } @@ -565,31 +602,31 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("c", "char", 1)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 1, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 2, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/union\n" + - "pack(disabled)\n" + - "Union union {\n" + - " 0 union_s_0 1 _s_0 \"\"\n" + - " 0 union_s_1 2 _s_1 \"\"\n" + - "}\n" + - "Length: 2 Alignment: 1\n" + - "/union/union_s_0\n" + - "pack()\n" + - "Structure union_s_0 {\n" + - " 0 char 1 a \"\"\n" + - " 1 char[0] 0 flex \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/union/union_s_1\n" + - "pack()\n" + - "Structure union_s_1 {\n" + - " 0 char 1 b \"\"\n" + - " 1 char 1 c \"\"\n" + - "}\n" + + "/union\n" + + "pack()\n" + + "Union union {\n" + + " 0 union_s_0 1 _s_0 \"\"\n" + + " 0 union_s_1 2 _s_1 \"\"\n" + + "}\n" + + "Length: 2 Alignment: 1\n" + + "/union/union_s_0\n" + + "pack()\n" + + "Structure union_s_0 {\n" + + " 0 char 1 a \"\"\n" + + " 1 char[0] 0 flex \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/union/union_s_1\n" + + "pack()\n" + + "Structure union_s_1 {\n" + + " 0 char 1 b \"\"\n" + + " 1 char 1 c \"\"\n" + + "}\n" + "Length: 2 Alignment: 1", struct, true); //@formatter:on } @@ -622,57 +659,57 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("b", "longlong", 8)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 16, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 16, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/struct\n" + - "pack()\n" + - "Structure struct {\n" + - " 0 struct_u_0 1 \"\"\n" + - " 8 struct_u_8 8 \"\"\n" + - "}\n" + - "Length: 16 Alignment: 8\n" + - "/struct/struct_u_0\n" + - "pack()\n" + - "Union struct_u_0 {\n" + - " 0 struct_u_0_s_0 1 _s_0 \"\"\n" + - " 0 struct_u_0_s_1 1 _s_1 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/struct/struct_u_0/struct_u_0_s_0\n" + - "pack()\n" + - "Structure struct_u_0_s_0 {\n" + - " 0 char:1(0) 1 s0 \"\"\n" + - " 0 char:1(1) 1 s1 \"\"\n" + - " 0 char:1(2) 1 s2 \"\"\n" + - " 0 char:1(3) 1 s3 \"\"\n" + - " 0 char:1(4) 1 s4 \"\"\n" + - " 0 char:1(5) 1 s5 \"\"\n" + - " 0 char:1(6) 1 s6 \"\"\n" + - " 0 char:1(7) 1 s7 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/struct/struct_u_0/struct_u_0_s_1\n" + - "pack()\n" + - "Structure struct_u_0_s_1 {\n" + - " 0 uchar:1(0) 1 u0 \"\"\n" + - " 0 uchar:1(1) 1 u1 \"\"\n" + - " 0 uchar:1(2) 1 u2 \"\"\n" + - " 0 uchar:1(3) 1 u3 \"\"\n" + - " 0 uchar:1(4) 1 u4 \"\"\n" + - " 0 uchar:1(5) 1 u5 \"\"\n" + - " 0 uchar:1(6) 1 u6 \"\"\n" + - " 0 uchar:1(7) 1 u7 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/struct/struct_u_8\n" + - "pack()\n" + - "Union struct_u_8 {\n" + - " 0 ulong 4 a \"\"\n" + - " 0 longlong 8 b \"\"\n" + - "}\n" + + "/struct\n" + + "pack()\n" + + "Structure struct {\n" + + " 0 struct_u_0 1 \"\"\n" + + " 8 struct_u_8 8 \"\"\n" + + "}\n" + + "Length: 16 Alignment: 8\n" + + "/struct/struct_u_0\n" + + "pack()\n" + + "Union struct_u_0 {\n" + + " 0 struct_u_0_s_0 1 _s_0 \"\"\n" + + " 0 struct_u_0_s_1 1 _s_1 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/struct/struct_u_0/struct_u_0_s_0\n" + + "pack()\n" + + "Structure struct_u_0_s_0 {\n" + + " 0 char:1(0) 1 s0 \"\"\n" + + " 0 char:1(1) 1 s1 \"\"\n" + + " 0 char:1(2) 1 s2 \"\"\n" + + " 0 char:1(3) 1 s3 \"\"\n" + + " 0 char:1(4) 1 s4 \"\"\n" + + " 0 char:1(5) 1 s5 \"\"\n" + + " 0 char:1(6) 1 s6 \"\"\n" + + " 0 char:1(7) 1 s7 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/struct/struct_u_0/struct_u_0_s_1\n" + + "pack()\n" + + "Structure struct_u_0_s_1 {\n" + + " 0 uchar:1(0) 1 u0 \"\"\n" + + " 0 uchar:1(1) 1 u1 \"\"\n" + + " 0 uchar:1(2) 1 u2 \"\"\n" + + " 0 uchar:1(3) 1 u3 \"\"\n" + + " 0 uchar:1(4) 1 u4 \"\"\n" + + " 0 uchar:1(5) 1 u5 \"\"\n" + + " 0 uchar:1(6) 1 u6 \"\"\n" + + " 0 uchar:1(7) 1 u7 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/struct/struct_u_8\n" + + "pack()\n" + + "Union struct_u_8 {\n" + + " 0 ulong 4 a \"\"\n" + + " 0 longlong 8 b \"\"\n" + + "}\n" + "Length: 8 Alignment: 8\n", struct, true); //@formatter:on } @@ -703,42 +740,43 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("u5:0x1:0x5", "uchar", 1), new MyPdbMember("u6:0x1:0x6", "uchar", 1), new MyPdbMember("u7:0x1:0x7", "uchar", 1)); - + //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 12, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 12, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/union\n" + - "pack(disabled)\n" + - "Union union {\n" + - " 0 ulong 4 a \"\"\n" + - " 0 longlong 8 b \"\"\n" + - " 0 union_s_2 2 _s_2 \"\"\n" + - "}\n" + - "Length: 8 Alignment: 1\n" + - "/union/union_s_2\n" + - "pack()\n" + - "Structure union_s_2 {\n" + - " 0 char:1(0) 1 s0 \"\"\n" + - " 0 char:1(1) 1 s1 \"\"\n" + - " 0 char:1(2) 1 s2 \"\"\n" + - " 0 char:1(3) 1 s3 \"\"\n" + - " 0 char:1(4) 1 s4 \"\"\n" + - " 0 char:1(5) 1 s5 \"\"\n" + - " 0 char:1(6) 1 s6 \"\"\n" + - " 0 char:1(7) 1 s7 \"\"\n" + - " 1 uchar:1(0) 1 u0 \"\"\n" + - " 1 uchar:1(1) 1 u1 \"\"\n" + - " 1 uchar:1(2) 1 u2 \"\"\n" + - " 1 uchar:1(3) 1 u3 \"\"\n" + - " 1 uchar:1(4) 1 u4 \"\"\n" + - " 1 uchar:1(5) 1 u5 \"\"\n" + - " 1 uchar:1(6) 1 u6 \"\"\n" + - " 1 uchar:1(7) 1 u7 \"\"\n" + - "}\n" + + "/union\n" + + "pack(disabled)\n" + + "Union union {\n" + + " 0 ulong 4 a \"\"\n" + + " 0 longlong 8 b \"\"\n" + + " 0 union_s_2 2 _s_2 \"\"\n" + + " 0 char[12] 12 _padding_ \"\"\n" + + "}\n" + + "Length: 12 Alignment: 1\n" + + "/union/union_s_2\n" + + "pack()\n" + + "Structure union_s_2 {\n" + + " 0 char:1(0) 1 s0 \"\"\n" + + " 0 char:1(1) 1 s1 \"\"\n" + + " 0 char:1(2) 1 s2 \"\"\n" + + " 0 char:1(3) 1 s3 \"\"\n" + + " 0 char:1(4) 1 s4 \"\"\n" + + " 0 char:1(5) 1 s5 \"\"\n" + + " 0 char:1(6) 1 s6 \"\"\n" + + " 0 char:1(7) 1 s7 \"\"\n" + + " 1 uchar:1(0) 1 u0 \"\"\n" + + " 1 uchar:1(1) 1 u1 \"\"\n" + + " 1 uchar:1(2) 1 u2 \"\"\n" + + " 1 uchar:1(3) 1 u3 \"\"\n" + + " 1 uchar:1(4) 1 u4 \"\"\n" + + " 1 uchar:1(5) 1 u5 \"\"\n" + + " 1 uchar:1(6) 1 u6 \"\"\n" + + " 1 uchar:1(7) 1 u7 \"\"\n" + + "}\n" + "Length: 2 Alignment: 1", struct, true); //@formatter:on } @@ -816,156 +854,156 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("buf", "char[0]", 0x2c)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 0x38, members, this, - TaskMonitor.DUMMY)); + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, false, 0x38, members, + this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, - "/MoreComplicated_s\n" + - "pack()\n" + - "Structure MoreComplicated_s {\n" + - " 0 MoreComplicated_s_u_0 1 \"\"\n" + - " 8 MoreComplicated_s_u_8 8 \"\"\n" + - " 16 MoreComplicated_s_u_16 16 \"\"\n" + - " 32 char[10] 10 beef \"\"\n" + - " 44 MoreComplicated_s_u_44 12 \"\"\n" + - "}\n" + - "Length: 56 Alignment: 8\n" + - "/MoreComplicated_s/MoreComplicated_s_u_0\n" + - "pack()\n" + - "Union MoreComplicated_s_u_0 {\n" + - " 0 MoreComplicated_s_u_0_s_0 1 _s_0 \"\"\n" + - " 0 MoreComplicated_s_u_0_s_1 1 _s_1 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/MoreComplicated_s/MoreComplicated_s_u_0/MoreComplicated_s_u_0_s_0\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_0_s_0 {\n" + - " 0 char:1(0) 1 s0 \"\"\n" + - " 0 char:1(1) 1 s1 \"\"\n" + - " 0 char:1(2) 1 s2 \"\"\n" + - " 0 char:1(3) 1 s3 \"\"\n" + - " 0 char:1(4) 1 s4 \"\"\n" + - " 0 char:1(5) 1 s5 \"\"\n" + - " 0 char:1(6) 1 s6 \"\"\n" + - " 0 char:1(7) 1 s7 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/MoreComplicated_s/MoreComplicated_s_u_0/MoreComplicated_s_u_0_s_1\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_0_s_1 {\n" + - " 0 uchar:1(0) 1 u0 \"\"\n" + - " 0 uchar:1(1) 1 u1 \"\"\n" + - " 0 uchar:1(2) 1 u2 \"\"\n" + - " 0 uchar:1(3) 1 u3 \"\"\n" + - " 0 uchar:1(4) 1 u4 \"\"\n" + - " 0 uchar:1(5) 1 u5 \"\"\n" + - " 0 uchar:1(6) 1 u6 \"\"\n" + - " 0 uchar:1(7) 1 u7 \"\"\n" + - "}\n" + - "Length: 1 Alignment: 1\n" + - "/MoreComplicated_s/MoreComplicated_s_u_16\n" + - "pack()\n" + - "Union MoreComplicated_s_u_16 {\n" + - " 0 MoreComplicated_s_u_16_s_0 16 _s_0 \"\"\n" + - " 0 MoreComplicated_s_u_16_s_1 16 _s_1 \"\"\n" + - "}\n" + - "Length: 16 Alignment: 8\n" + - "/MoreComplicated_s/MoreComplicated_s_u_16/MoreComplicated_s_u_16_s_0\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_16_s_0 {\n" + - " 0 double 8 da \"\"\n" + - " 8 char[8] 8 ca \"\"\n" + - "}\n" + - "Length: 16 Alignment: 8\n" + - "/MoreComplicated_s/MoreComplicated_s_u_16/MoreComplicated_s_u_16_s_1\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_16_s_1 {\n" + - " 0 char[8] 8 cb \"\"\n" + - " 8 double 8 db \"\"\n" + - "}\n" + - "Length: 16 Alignment: 8\n" + - "/MoreComplicated_s/MoreComplicated_s_u_44\n" + - "pack()\n" + - "Union MoreComplicated_s_u_44 {\n" + - " 0 MoreComplicated_s_u_44_s_0 12 _s_0 \"\"\n" + - " 0 MoreComplicated_s_u_44_s_1 0 _s_1 \"\"\n" + - "}\n" + - "Length: 12 Alignment: 4\n" + - "/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_0\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_44_s_0 {\n" + - " 0 int 4 fromAddress \"\"\n" + - " 4 int 4 toAddress \"\"\n" + - " 8 int 4 seqNum \"\"\n" + - " 12 char[0] 0 data \"\"\n" + - "}\n" + - "Length: 12 Alignment: 4\n" + - "/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_1\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_44_s_1 {\n" + - " 0 char[0] 0 buf \"\"\n" + - "}\n" + - "Length: 0 Alignment: 1\n" + - "/MoreComplicated_s/MoreComplicated_s_u_8\n" + - "pack()\n" + - "Union MoreComplicated_s_u_8 {\n" + - " 0 ulong 4 val \"\"\n" + - " 0 double 8 d \"\"\n" + - " 0 MoreComplicated_s_u_8_s_2 8 _s_2 \"\"\n" + - " 0 MoreComplicated_s_u_8_s_3 8 _s_3 \"\"\n" + - " 0 MoreComplicated_s_u_8_s_4 8 _s_4 \"\"\n" + - "}\n" + - "Length: 8 Alignment: 8\n" + - "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_2\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_8_s_2 {\n" + - " 0 ulong:4(0) 1 n0 \"\"\n" + - " 0 ulong:4(4) 1 n1 \"\"\n" + - " 1 ulong:4(0) 1 n2 \"\"\n" + - " 1 ulong:4(4) 1 n3 \"\"\n" + - " 2 ulong:4(0) 1 n4 \"\"\n" + - " 2 ulong:4(4) 1 n5 \"\"\n" + - " 3 ulong:4(0) 1 n6 \"\"\n" + - " 3 ulong:4(4) 1 n7 \"\"\n" + - " 4 ulong:4(0) 1 n8 \"\"\n" + - " 4 ulong:4(4) 1 n9 \"\"\n" + - " 5 ulong:4(0) 1 n10 \"\"\n" + - " 5 ulong:4(4) 1 n11 \"\"\n" + - " 6 ulong:4(0) 1 n12 \"\"\n" + - " 6 ulong:4(4) 1 n13 \"\"\n" + - " 7 ulong:4(0) 1 n14 \"\"\n" + - " 7 ulong:4(4) 1 n15 \"\"\n" + - "}\n" + - "Length: 8 Alignment: 4\n" + - "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_3\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_8_s_3 {\n" + - " 0 ulong:1(0) 1 x1 \"\"\n" + - " 0 ulong:2(1) 1 x2 \"\"\n" + - " 0 ulong:3(3) 1 x3 \"\"\n" + - " 0 ulong:4(6) 2 x4 \"\"\n" + - " 1 ulong:5(2) 1 x5 \"\"\n" + - " 1 ulong:6(7) 2 x6 \"\"\n" + - " 2 ulong:7(5) 2 x7 \"\"\n" + - " 4 ulong:8(0) 1 x8 \"\"\n" + - " 5 ulong:9(0) 2 x9 \"\"\n" + - " 6 ulong:10(1) 2 x10 \"\"\n" + - "}\n" + - "Length: 8 Alignment: 4\n" + - "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_4\n" + - "pack()\n" + - "Structure MoreComplicated_s_u_8_s_4 {\n" + - " 0 uchar:1(0) 1 y1 \"\"\n" + - " 0 uchar:2(1) 1 y2 \"\"\n" + - " 0 uchar:3(3) 1 y3 \"\"\n" + - " 1 uchar:4(0) 1 y4 \"\"\n" + - " 2 uchar:5(0) 1 y5 \"\"\n" + - " 3 uchar:6(0) 1 y6 \"\"\n" + - " 4 uchar:7(0) 1 y7 \"\"\n" + - " 5 uchar:8(0) 1 y8 \"\"\n" + - " 6 ushort:9(0) 2 y9 \"\"\n" + - "}\n" + + "/MoreComplicated_s\n" + + "pack()\n" + + "Structure MoreComplicated_s {\n" + + " 0 MoreComplicated_s_u_0 1 \"\"\n" + + " 8 MoreComplicated_s_u_8 8 \"\"\n" + + " 16 MoreComplicated_s_u_16 16 \"\"\n" + + " 32 char[10] 10 beef \"\"\n" + + " 44 MoreComplicated_s_u_44 12 \"\"\n" + + "}\n" + + "Length: 56 Alignment: 8\n" + + "/MoreComplicated_s/MoreComplicated_s_u_0\n" + + "pack()\n" + + "Union MoreComplicated_s_u_0 {\n" + + " 0 MoreComplicated_s_u_0_s_0 1 _s_0 \"\"\n" + + " 0 MoreComplicated_s_u_0_s_1 1 _s_1 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/MoreComplicated_s/MoreComplicated_s_u_0/MoreComplicated_s_u_0_s_0\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_0_s_0 {\n" + + " 0 char:1(0) 1 s0 \"\"\n" + + " 0 char:1(1) 1 s1 \"\"\n" + + " 0 char:1(2) 1 s2 \"\"\n" + + " 0 char:1(3) 1 s3 \"\"\n" + + " 0 char:1(4) 1 s4 \"\"\n" + + " 0 char:1(5) 1 s5 \"\"\n" + + " 0 char:1(6) 1 s6 \"\"\n" + + " 0 char:1(7) 1 s7 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/MoreComplicated_s/MoreComplicated_s_u_0/MoreComplicated_s_u_0_s_1\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_0_s_1 {\n" + + " 0 uchar:1(0) 1 u0 \"\"\n" + + " 0 uchar:1(1) 1 u1 \"\"\n" + + " 0 uchar:1(2) 1 u2 \"\"\n" + + " 0 uchar:1(3) 1 u3 \"\"\n" + + " 0 uchar:1(4) 1 u4 \"\"\n" + + " 0 uchar:1(5) 1 u5 \"\"\n" + + " 0 uchar:1(6) 1 u6 \"\"\n" + + " 0 uchar:1(7) 1 u7 \"\"\n" + + "}\n" + + "Length: 1 Alignment: 1\n" + + "/MoreComplicated_s/MoreComplicated_s_u_16\n" + + "pack()\n" + + "Union MoreComplicated_s_u_16 {\n" + + " 0 MoreComplicated_s_u_16_s_0 16 _s_0 \"\"\n" + + " 0 MoreComplicated_s_u_16_s_1 16 _s_1 \"\"\n" + + "}\n" + + "Length: 16 Alignment: 8\n" + + "/MoreComplicated_s/MoreComplicated_s_u_16/MoreComplicated_s_u_16_s_0\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_16_s_0 {\n" + + " 0 double 8 da \"\"\n" + + " 8 char[8] 8 ca \"\"\n" + + "}\n" + + "Length: 16 Alignment: 8\n" + + "/MoreComplicated_s/MoreComplicated_s_u_16/MoreComplicated_s_u_16_s_1\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_16_s_1 {\n" + + " 0 char[8] 8 cb \"\"\n" + + " 8 double 8 db \"\"\n" + + "}\n" + + "Length: 16 Alignment: 8\n" + + "/MoreComplicated_s/MoreComplicated_s_u_44\n" + + "pack()\n" + + "Union MoreComplicated_s_u_44 {\n" + + " 0 MoreComplicated_s_u_44_s_0 12 _s_0 \"\"\n" + + " 0 MoreComplicated_s_u_44_s_1 0 _s_1 \"\"\n" + + "}\n" + + "Length: 12 Alignment: 4\n" + + "/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_0\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_44_s_0 {\n" + + " 0 int 4 fromAddress \"\"\n" + + " 4 int 4 toAddress \"\"\n" + + " 8 int 4 seqNum \"\"\n" + + " 12 char[0] 0 data \"\"\n" + + "}\n" + + "Length: 12 Alignment: 4\n" + + "/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_1\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_44_s_1 {\n" + + " 0 char[0] 0 buf \"\"\n" + + "}\n" + + "Length: 0 Alignment: 1\n" + + "/MoreComplicated_s/MoreComplicated_s_u_8\n" + + "pack()\n" + + "Union MoreComplicated_s_u_8 {\n" + + " 0 ulong 4 val \"\"\n" + + " 0 double 8 d \"\"\n" + + " 0 MoreComplicated_s_u_8_s_2 8 _s_2 \"\"\n" + + " 0 MoreComplicated_s_u_8_s_3 8 _s_3 \"\"\n" + + " 0 MoreComplicated_s_u_8_s_4 8 _s_4 \"\"\n" + + "}\n" + + "Length: 8 Alignment: 8\n" + + "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_2\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_8_s_2 {\n" + + " 0 ulong:4(0) 1 n0 \"\"\n" + + " 0 ulong:4(4) 1 n1 \"\"\n" + + " 1 ulong:4(0) 1 n2 \"\"\n" + + " 1 ulong:4(4) 1 n3 \"\"\n" + + " 2 ulong:4(0) 1 n4 \"\"\n" + + " 2 ulong:4(4) 1 n5 \"\"\n" + + " 3 ulong:4(0) 1 n6 \"\"\n" + + " 3 ulong:4(4) 1 n7 \"\"\n" + + " 4 ulong:4(0) 1 n8 \"\"\n" + + " 4 ulong:4(4) 1 n9 \"\"\n" + + " 5 ulong:4(0) 1 n10 \"\"\n" + + " 5 ulong:4(4) 1 n11 \"\"\n" + + " 6 ulong:4(0) 1 n12 \"\"\n" + + " 6 ulong:4(4) 1 n13 \"\"\n" + + " 7 ulong:4(0) 1 n14 \"\"\n" + + " 7 ulong:4(4) 1 n15 \"\"\n" + + "}\n" + + "Length: 8 Alignment: 4\n" + + "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_3\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_8_s_3 {\n" + + " 0 ulong:1(0) 1 x1 \"\"\n" + + " 0 ulong:2(1) 1 x2 \"\"\n" + + " 0 ulong:3(3) 1 x3 \"\"\n" + + " 0 ulong:4(6) 2 x4 \"\"\n" + + " 1 ulong:5(2) 1 x5 \"\"\n" + + " 1 ulong:6(7) 2 x6 \"\"\n" + + " 2 ulong:7(5) 2 x7 \"\"\n" + + " 4 ulong:8(0) 1 x8 \"\"\n" + + " 5 ulong:9(0) 2 x9 \"\"\n" + + " 6 ulong:10(1) 2 x10 \"\"\n" + + "}\n" + + "Length: 8 Alignment: 4\n" + + "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_4\n" + + "pack()\n" + + "Structure MoreComplicated_s_u_8_s_4 {\n" + + " 0 uchar:1(0) 1 y1 \"\"\n" + + " 0 uchar:2(1) 1 y2 \"\"\n" + + " 0 uchar:3(3) 1 y3 \"\"\n" + + " 1 uchar:4(0) 1 y4 \"\"\n" + + " 2 uchar:5(0) 1 y5 \"\"\n" + + " 3 uchar:6(0) 1 y6 \"\"\n" + + " 4 uchar:7(0) 1 y7 \"\"\n" + + " 5 uchar:8(0) 1 y8 \"\"\n" + + " 6 ushort:9(0) 2 y9 \"\"\n" + + "}\n" + "Length: 8 Alignment: 2", struct, true); //@formatter:on } diff --git a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/ConflictHandler2Test.java b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/ConflictHandler2Test.java index 7ef045bd68..e0aab0e4a1 100644 --- a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/ConflictHandler2Test.java +++ b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/ConflictHandler2Test.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,8 +33,8 @@ import ghidra.util.task.TaskMonitor; /** * Tests for the {@link DataTypeConflictHandler conflict handler} stuff. - * - * + * + * */ public class ConflictHandler2Test extends AbstractGhidraHeadedIntegrationTest { private ProgramDB program; @@ -136,7 +136,7 @@ public class ConflictHandler2Test extends AbstractGhidraHeadedIntegrationTest { size += extra.getLength(); } try { - if (!DefaultCompositeMember.applyDataTypeMembers(composite, false, size, members, + if (DefaultCompositeMember.applyDataTypeMembers(composite, false, false, size, members, msg -> Msg.warn(ConflictHandler2Test.class, msg), monitor)) { ((Structure) composite).deleteAll(); }