diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html index 21f8caaf81..0bd9779ae0 100644 --- a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html +++ b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html @@ -344,7 +344,7 @@ -

Note:While packing of bitfields within aligned +

Note:While packing of bitfields within packed structures is controlled by the compiler specification (e.g., data organization), bit-packing order is currently fixed based upon endianess. Little-endian packs starting with bit-0 (lsb) while big-endian packs starting with bit-7 (msb).

@@ -401,9 +414,10 @@ Insert Undefined Byte
-

Undefined Bytes can only be inserted into a structure that is not aligned. A single - Undefined byte is inserted before the current selection by clicking the Insert Undefined Byte button.

+

Within a non-packed structure undefined components are inserted before the current selection by clicking the Insert Undefined Byte button. Within a packed structure an undefined1 datatype component + is inserted in a similar fashion, although in packed structures it is more appropriate to use a properly sized datatype (e.g., modify datatype + on inserted component).

Move @@ -442,9 +456,9 @@
  • A single copy of the component is created immediately following the selected one.
  • -

    If the structure is not aligned, then there must be enough Undefined bytes following the - component to accommodate the duplicate. In an unaligned structure, Undefined bytes get - replaced by the new copy of the component.

    +

    If the structure is not packed (i.e., pack disabled), then there must be enough undefined components following the + component to accommodate the duplicate. In such a such a structure, undefined bytes get + consumed by the new copy of the component.

    button.
  • The number of duplicates - dialog appears. In an unaligned structure, you can only indicate as many duplicates as will - fit in place of Undefined bytes.
  • + dialog appears. In a non-packed structure, you can only indicate as many duplicates as will + fit in place of undefined bytes. @@ -502,10 +516,10 @@ Clear Component(s)

    -

    Clearing a component changes it into Undefined byte components that take up the same - amount of space as the component being cleared. Components can be cleared in unaligned - structures, but not in unions or aligned structures. This is because the resulting Undefined - bytes are not valid components in a union or aligned structure.

    +

    Clearing a component changes it into an undefined components that take up the same + amount of space as the component being cleared. Components can only be cleared in non-packed + structures (i.e., pack disabled), but not in unions or packed structures. This is because the resulting undefined + components are not valid in a union or packed structure.

    To clear components in a structure:

    @@ -514,7 +528,7 @@
  • Press the Clear Component(s) button.
  • -
  • Each selected component is replaced by Undefined Bytes. The number of Undefined Bytes +
  • Each selected component is replaced by undefined components. The number of undefined components will be equal to the length of the component being cleared.
  • @@ -542,8 +556,8 @@
      -
    1. Specify the number of elements. For an unaligned structure, the maximum size of the - array is limited by the number of Undefined bytes following the selected component.
    2. +
    3. Specify the number of elements. For a non-packed structure (i.e., pack disabled), the maximum size of the + array is limited by the number of undefined components following the selected component.
    4. Press the OK button.
    5. @@ -568,7 +582,7 @@ the data type of the array. The array's dimension is determined by how many of that data type will fit in the space that was occupied by the selection. The size of the array will be the array that can fit in the selected number of bytes. Any left over (unused) bytes at - the end of the selection will become Undefined bytes. + the end of the selection will become undefined components.
    @@ -621,12 +635,12 @@

    -

    Bitfield Actions (unaligned structures)

    +

    Bitfield Actions (Non-Packed Structures)

    -

    The following bitfield actions are available when modifying unaligned structures only and are available +

    The following bitfield actions are available when modifying non-packed structures only (i.e., pack disabled) and are available via the popup menu based upon a selected component or table row. When working with unions and - aligned structures, bitfields may only be specified via datatype text entry specification within the + packed structures, bitfields may only be specified via datatype text entry specification within the table view (e.g., char:1).

    Add Bitfield

    @@ -671,10 +685,10 @@

    Name - The field name associated with this component in the structure or union. When specified, the field names must be unique for the components in a structure or - union. This field is editable, except on components that are Undefined bytes.

    + union. This field is editable, except on undefined components.

    Comment - A comment associated with this component. This field is editable, - except on components that are Undefined bytes.

    + except on undefined components.

    To rearrange the order of the component @@ -687,8 +701,7 @@

    Editing Component Fields

    The DataType, Name and Comment fields are editable. However, the - Name and Comment are not editable when the component's DataType is an - Undefined byte.

    + Name and Comment are not editable on undefined components.

    To place an editable field into edit mode:

    @@ -792,28 +805,29 @@

    Effect of Changing a Component's Size

    -

    An unaligned union's size will always be the size of its largest component. If you +

    A non-packed union's size will always be the size of its largest component. If you change a data type for a component and the component size changes, the union size will - change if necessary. An aligned union is padded to make its size a multiple of the union's + change if necessary. A packed union is padded to make its size a multiple of the union's alignment.

    How a structure is affected by changing a component's data type depends on whether the - structure size is aligned or unaligned.

    + structure size is packed or non-packed.

    -

    Unaligned - If the structure is unaligned, then the new component must - be less than or equal to the original component's size plus any Undefined byte components - that immediately follow it in the structure. In an unaligned structure, decreasing the - component size will create Undefined byte components following it to maintain the - structure size. Increasing the component size replaces Undefined bytes immediately - following the component. The last component of a structure can be always be changed which +

    Non-Packed - If the structure has pack disabled, then the new component must + be less than or equal to the original component's size plus any undefined components + that immediately follow it in the structure. Decreasing the + component size will create undefined components following it to maintain the + structure size and placement of other components. Increasing the component size replaces + undefined components immediately + following the component. The last component of a structure can always be changed which can cause the structure to grow larger.

    -

    Aligned - If the structure is aligned, the component can change size, - which affects the structure's overall size and the alignment of individual components - that follow it.

    +

    Packed - If the structure is packed, a component can change size or alignment, + which can affect the placement of subsequent components within a structure and/or the + overall size and alignment of both structures and unions.

    @@ -859,7 +873,7 @@
    -

    Union or Aligned Structure
    +

    Union or Packed Structure

    The first data type in a cycle group can be added to the end of a structure as a new @@ -897,13 +911,13 @@ cycle group. The data type can then be cycled to any other data type in the group.

    -

    Unaligned Structure

    +

    Non-Packed Structure

    -

    Cycling is implemented similar to how it is implemented in an aligned structure. The +

    Cycling is implemented similar to how it is implemented in a packed structure. The only exception is that the user can only cycle to data types that will fit within the data - boundary of the current component. If Undefined bytes follow the selected component, the - Undefined bytes can be replaced by cycling the data type to a larger sized data type. - Likewise, cycling to a smaller data type will add Undefined bytes after the component being + boundary of the current component. If undefined components follow the selected component, the + component can be replaced by cycling the data type to a larger sized data type. + Likewise, cycling to a smaller data type will add undefined components after the component being cycled. However, the last component is not restricted to a particular size.

    @@ -957,8 +971,8 @@

    Adding a Data Type

    -

    A data type can be added as a component by replacing Undefined bytes. When editing an - unaligned structure, there must be enough Undefined bytes for the data type to replace. A +

    A data type can be added as a component by replacing undefined components. When editing a + non-packed structure, there must be enough undefined components for the new data type. A data type can also be added to the end of a structure or union.

    @@ -997,7 +1011,7 @@

    Inserting a Data Type

    -

    In an aligned structure or a union, a data type can be inserted as a new component.

    +

    In a packed structure or a union, a data type can be inserted as a new component.

    Drag and Drop

    @@ -1025,9 +1039,9 @@

    Replacing a Data Type

    -

    A component can have its data type replaced with a different data type. If an unaligned - structure is being edited then Undefined bytes are created or consumed as necessary to - maintain the position of other components within the structure. For unions and aligned +

    A component can have its data type replaced with a different data type. If a non-packed + structure is being edited then undefined components are created or consumed as necessary to + maintain the position of other components within the structure. For unions and packed structures, the data type simply changes for the component and the overall size is adjusted accordingly.

    @@ -1041,22 +1055,22 @@ component in the editor. If the mouse pointer is a 'circle with a slash' then the data type cannot be dropped to replace the component. This is probably because the data type being dropped - won't fit in the structure in place of the original component. If editing a union or an - aligned structure the data type should always fit and the drop is allowed. If editing an - unaligned structure, the component is replaced only if the new component will fit. (see + won't fit in the structure in place of the original component. If editing a union or + packed structure the data type will always fit and the drop is allowed (provided the datatype is allowed). If editing a + non-packed structure, the component is replaced only if the new component will fit. (see Effect of Changing a Component's Size)

    Contiguous Selection of Multiple Components

    Drag a data type to a block of selected components. - Whether the structure is aligned or unaligned doesn't matter when dropping a data type on + Whether the structure is packed or non-packed doesn't matter when dropping a data type on a block of selected components. This is because the new component (s) will occupy the same space as the currently selected components.
    In a union, all selected components will be replaced with a single component containing the data type dropped.
    In a structure, as many components of the dropped data type as will fit in the - selection are created to replace the selection. In an unaligned structure any left over - bytes in the selection will become Undefined bytes.

    + selection are created to replace the selection. In a non-packed structure any left over + bytes in the selection will become undefined components.

    For information about drag and drop with pointers, see Drag and Drop Basics.

    @@ -1085,9 +1099,9 @@ In a union, all selected components will be replaced with a single component containing the favorite data type.
    In a structure
    , only favorites that will fit in place of the selection will be - enabled. Just like with drag and drop, whether the structure is aligned or unaligned + enabled. Just like with drag and drop, whether the structure is packed or non-packed doesn't matter. The selection becomes as many of the data type as will fit and left over - bytes become Undefined bytes for an unaligned structure.

    + bytes become undefined components for a non-packed structure.

    For information about Pointers as a Favorite, see Favorites Basics.

    @@ -1248,14 +1262,14 @@

    -

    Bitfield Editor (unaligned structures only)

    +

    Bitfield Editor (Non-Packed Structures only)

    The Bitfield Editor is used by the Structure Editor when adding or modifying bitfield components - within unaligned structures to facilitate precise placement at the bit level. The Bitfield Editor - is not supported for unions and aligned structures since automated packing is performed (i.e., + within non-packed structures to facilitate precise placement at the bit level. The Bitfield Editor + is not supported for unions and packed structures since automated packing is performed (i.e., bitfields are specified via datatype text entry within the structure/union table view). - While editing an unaligned structure, the Structure Editor popup menu actions Add Bitfield + While editing a non-packed structure, the Structure Editor popup menu actions Add Bitfield and Edit Bitfield are used to launch the Bitfield Editor.

    The Bitfield Editor includes a visual depiction of the storage allocation bytes and associated diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditor.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditor.png index 5b5902d897..194fbb1ffd 100644 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditor.png and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditor.png differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.png deleted file mode 100644 index 8c44523204..0000000000 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.png and /dev/null differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorPacked.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorPacked.png new file mode 100644 index 0000000000..ddaf0e6785 Binary files /dev/null and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorPacked.png differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorWithFlexArray.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorWithFlexArray.png index 8bed9e4d6e..3ab2ea0a87 100644 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorWithFlexArray.png and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorWithFlexArray.png differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditor.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditor.png index af474fae50..02c3152875 100644 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditor.png and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditor.png differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditorAligned.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditorAligned.png deleted file mode 100644 index 2562fb7eb2..0000000000 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditorAligned.png and /dev/null differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditorPacked.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditorPacked.png new file mode 100644 index 0000000000..7fc56dced9 Binary files /dev/null and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/UnionEditorPacked.png differ diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_description.htm b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_description.htm index a877246ee1..01daa93f42 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_description.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_description.htm @@ -487,14 +487,13 @@ Archive action.

    -

    Aligning All Data Types In a Program or Archive

    +

    Pack All Data Types In a Program or Archive

    -

    Right-click on the program or data type archive where data types are to be aligned, - and select the Align All... action. A confirmation dialog will appear to - make sure you want to align all the structures and unions in the program or data type - archive. If you continue, all structures and unions that are unaligned will be changed to - aligned data types with no minimum alignment (the default) and no packing.

    +

    Right-click on the program or data type archive where structures and unions are to be packed, + and select the Pack All... action. A confirmation dialog will appear to + make sure you want to pack all composites in the program or data type + archive. If you continue, all non-packed composites will have default packing enabled.

    Updating an Archive From a Source @@ -926,15 +925,14 @@

    - +

    Committing Changes To Source Archive

    diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/data/CreateArrayInStructureCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/data/CreateArrayInStructureCmd.java index df6c6e079d..db26d3d1dc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/data/CreateArrayInStructureCmd.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/data/CreateArrayInStructureCmd.java @@ -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. @@ -103,7 +102,7 @@ public class CreateArrayInStructureCmd implements Command { try { ArrayDataType adt = new ArrayDataType(dataType, numElements, dataType.getLength()); clearStruct(struct, compData.getParentOffset(), length); - if (struct.isInternallyAligned()) { + if (struct.isPackingEnabled()) { struct.insert(index, adt, adt.getLength()); } else { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java index 3fdbd5ab11..8eedd74e53 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java @@ -1164,7 +1164,7 @@ public class DataTypeMergeManager implements MergeResolver { updateAlignment(sourceDt, destStruct); DataTypeManager sourceDTM = sourceDt.getDataTypeManager(); - boolean aligned = sourceDt.isInternallyAligned(); + boolean aligned = sourceDt.isPackingEnabled(); // Add each of the defined components back in. DataTypeComponent[] comps = sourceDt.getDefinedComponents(); @@ -1480,17 +1480,25 @@ public class DataTypeMergeManager implements MergeResolver { private void updateAlignment(Composite sourceDt, Composite destinationDt) { if (sourceDt.isDefaultAligned()) { - destinationDt.setToDefaultAlignment(); + destinationDt.setToDefaultAligned(); } else if (sourceDt.isMachineAligned()) { - destinationDt.setToMachineAlignment(); + destinationDt.setToMachineAligned(); } else { - destinationDt.setMinimumAlignment(sourceDt.getMinimumAlignment()); + destinationDt.setExplicitMinimumAlignment(sourceDt.getExplicitMinimumAlignment()); + } + if (sourceDt.isPackingEnabled()) { + if (sourceDt.hasExplicitPackingValue()) { + destinationDt.setExplicitPackingValue(sourceDt.getExplicitPackingValue()); + } + else { + destinationDt.setToDefaultPacking(); + } + } + else { + destinationDt.setPackingEnabled(false); } - destinationDt.setPackingValue(sourceDt.getPackingValue()); - boolean aligned = sourceDt.isInternallyAligned(); - destinationDt.setInternallyAligned(aligned); } private void updateComposite(long sourceDtID, Composite sourceDt, Composite destDt, @@ -1860,11 +1868,15 @@ public class DataTypeMergeManager implements MergeResolver { private boolean compositeDataTypeWasChanged(Composite c1, Composite c2) { DataTypeManager dtm1 = c1.getDataTypeManager(); DataTypeManager dtm2 = c2.getDataTypeManager(); - if (c1.isInternallyAligned() != c2.isInternallyAligned() || - c1.isDefaultAligned() != c2.isDefaultAligned() || - c1.isMachineAligned() != c2.isMachineAligned() || - c1.getMinimumAlignment() != c2.getMinimumAlignment() || - c1.getPackingValue() != c2.getPackingValue()) { + + PackingType packingType = c1.getPackingType(); + AlignmentType alignmentType = c1.getAlignmentType(); + + if ((packingType != c2.getPackingType()) || (alignmentType != c2.getAlignmentType()) || + (packingType == PackingType.EXPLICIT && + c1.getExplicitPackingValue() != c2.getExplicitPackingValue()) || + (alignmentType == AlignmentType.EXPLICIT && + c1.getExplicitMinimumAlignment() != c2.getExplicitMinimumAlignment())) { return true; } @@ -1877,7 +1889,7 @@ public class DataTypeMergeManager implements MergeResolver { boolean checkOffsets = false; if (c1 instanceof Structure) { - if (!((Structure) c1).isInternallyAligned()) { + if (!((Structure) c1).isPackingEnabled()) { if (c1.getNumComponents() != c2.getNumComponents()) { return true; } @@ -2444,13 +2456,13 @@ public class DataTypeMergeManager implements MergeResolver { } /** - * Process fixup for unaligned structure component + * Process fixup for non-packed structure component * @param info fixup info * @param struct result structure * @param dt component datatype * @return false if component not found, else true */ - private boolean fixUpUnalignedStructureComponent(FixUpInfo info, Structure struct, + private boolean fixUpNonPackedStructureComponent(FixUpInfo info, Structure struct, DataType dt) { int offset = info.index; DataTypeComponent dtc = struct.getComponentAt(offset); @@ -2533,7 +2545,7 @@ public class DataTypeMergeManager implements MergeResolver { boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE); if (compDt != null) { - if (struct.isInternallyAligned() || isFlexArrayFixup) { + if (struct.isPackingEnabled() || isFlexArrayFixup) { if (!fixUpAlignedStructureComponent(info, struct, compDt)) { String msg = isFlexArrayFixup ? "flex-array component" : ("component " + info.index); @@ -2544,7 +2556,7 @@ public class DataTypeMergeManager implements MergeResolver { return true; } - if (!fixUpUnalignedStructureComponent(info, struct, compDt)) { + if (!fixUpNonPackedStructureComponent(info, struct, compDt)) { Msg.warn(this, "Structure Merge: Couldn't get component at offset " + info.index + " in " + struct.getPathName()); return false; @@ -2556,7 +2568,7 @@ public class DataTypeMergeManager implements MergeResolver { else if (isFlexArrayFixup) { struct.clearFlexibleArrayComponent(); } - else if (struct.isInternallyAligned()) { + else if (struct.isPackingEnabled()) { int ordinal = info.index; int numComponents = struct.getNumComponents(); if (ordinal >= 0 && ordinal < numComponents) { @@ -2595,7 +2607,7 @@ public class DataTypeMergeManager implements MergeResolver { * @return the number of contiguous undefined bytes or 0. */ private int getNumUndefinedBytes(Structure struct, int ordinal) { - if (struct.isInternallyAligned()) { + if (struct.isPackingEnabled()) { return 0; } int numComponents = struct.getNumComponents(); @@ -3276,7 +3288,7 @@ public class DataTypeMergeManager implements MergeResolver { private static int getComponentFixupIndex(DataTypeComponent dtc) { Composite composite = (Composite) dtc.getParent(); - if (composite.isInternallyAligned() || (composite instanceof Union)) { + if (composite.isPackingEnabled() || (composite instanceof Union)) { return dtc.getOrdinal(); } return dtc.getOffset(); @@ -3301,7 +3313,7 @@ public class DataTypeMergeManager implements MergeResolver { * or components were resolved. * @param id id of data type needed to be fixed up * @param compID id of either component or base type - * @param index offset into unaligned structure, or ordinal into union or aligned + * @param index offset into non-packed structure, or ordinal into union or packed * structure; or parameter/return ordinal; for other data types index is not used (specify -1). * For structure trailing flex-array specify {@link Integer#MAX_VALUE}. * @param resolvedDataTypes hashtable used for resolving the data type @@ -3333,7 +3345,7 @@ public class DataTypeMergeManager implements MergeResolver { } /** - * Find unaligned structure bitfield component at or after specified component + * Find non-packed structure bitfield component at or after specified component * which matches this info's bitfield data. * @param struct structure * @param dtc structure component contained within struct @@ -3412,7 +3424,7 @@ public class DataTypeMergeManager implements MergeResolver { /** * - * @param index offset into unaligned structure, or ordinal into union or aligned + * @param index offset into non-packed structure, or ordinal into union or packed * structure; for other data types, offset is not used (specify -1) * @param resolvedDataTypes hashtable used for resolving the data type */ @@ -3466,7 +3478,7 @@ public class DataTypeMergeManager implements MergeResolver { } private void cleanUpStructure(int[] indexArray, Structure dt) { - boolean aligned = dt.isInternallyAligned(); + boolean aligned = dt.isPackingEnabled(); Arrays.sort(indexArray); for (int i = indexArray.length - 1; i >= 0; i--) { if (aligned) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java index f0ff3dee2b..ab746965c9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypePanel.java @@ -149,28 +149,8 @@ class DataTypePanel extends JPanel { } private void formatAlignment(Composite composite) { - StringBuffer alignmentBuffer = new StringBuffer(); - if (!composite.isInternallyAligned()) { - alignmentBuffer.append("Unaligned"); - } - else if (composite.isDefaultAligned()) { - alignmentBuffer.append("Aligned"); - } - else if (composite.isMachineAligned()) { - alignmentBuffer.append("Machine aligned"); - } - else { - long alignment = composite.getMinimumAlignment(); - alignmentBuffer.append("align(" + alignment + ")"); - } - if (composite.isInternallyAligned()) { - long packingValue = composite.getPackingValue(); - if (packingValue != Composite.NOT_PACKING) { - alignmentBuffer.append(" pack(" + packingValue + ")"); - } - } - - insertString(alignmentBuffer.toString() + "\n\n", sourceAttrSet); + String str = CompositeDataTypeImpl.getAlignmentAndPackingString(composite); + insertString(str + "\n\n", sourceAttrSet); } private void insertAlignment(Composite composite) { @@ -202,7 +182,7 @@ class DataTypePanel extends JPanel { buffer.append("[0]"); } else if (dt instanceof BitFieldDataType && - !((Composite) dtc.getParent()).isInternallyAligned()) { + !((Composite) dtc.getParent()).isPackingEnabled()) { BitFieldDataType bfDt = (BitFieldDataType) dt; buffer.append("("); buffer.append(Integer.toString(bfDt.getBitOffset())); @@ -255,24 +235,24 @@ class DataTypePanel extends JPanel { DataTypeComponent[] components = comp.getDefinedComponents(); DataTypeComponent flexDtc = null; if (comp instanceof Structure) { - showComponentOffset = !comp.isInternallyAligned(); + showComponentOffset = !comp.isPackingEnabled(); flexDtc = ((Structure) comp).getFlexibleArrayComponent(); } int offsetLength = showComponentOffset ? Integer.toHexString(comp.getLength()).length() : 0; int maxDtNameLength = 10; int maxFieldNameLength = 1; - for (int i = 0; i < components.length; i++) { - maxDtNameLength = max(getDataTypeName(components[i]), maxDtNameLength); - maxFieldNameLength = max(components[i].getFieldName(), maxFieldNameLength); + for (DataTypeComponent component : components) { + maxDtNameLength = max(getDataTypeName(component), maxDtNameLength); + maxFieldNameLength = max(component.getFieldName(), maxFieldNameLength); } if (flexDtc != null) { maxDtNameLength = max(getDataTypeName(flexDtc), maxDtNameLength); maxFieldNameLength = max(flexDtc.getFieldName(), maxFieldNameLength); } - for (int i = 0; i < components.length; i++) { - renderComponent(components[i], maxDtNameLength, maxFieldNameLength, offsetLength); + for (DataTypeComponent component : components) { + renderComponent(component, maxDtNameLength, maxFieldNameLength, offsetLength); } if (flexDtc != null) { renderComponent(flexDtc, maxDtNameLength, maxFieldNameLength, offsetLength); @@ -293,9 +273,9 @@ class DataTypePanel extends JPanel { String[] names = enuum.getNames(); int maxLength = 0; - for (int i = 0; i < names.length; i++) { - if (names[i].length() > maxLength) { - maxLength = names[i].length(); + for (String name : names) { + if (name.length() > maxLength) { + maxLength = name.length(); } } long[] values = enuum.getValues(); @@ -336,8 +316,8 @@ class DataTypePanel extends JPanel { return; } int maxLength = 0; - for (int i = 0; i < vars.length; i++) { - String typeName = vars[i].getDataType().getDisplayName(); + for (ParameterDefinition var : vars) { + String typeName = var.getDataType().getDisplayName(); if (typeName.length() > maxLength) { maxLength = typeName.length(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/AddBitFieldAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/AddBitFieldAction.java index 442bd8fe62..c6188c5ed9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/AddBitFieldAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/AddBitFieldAction.java @@ -69,8 +69,8 @@ public class AddBitFieldAction extends CompositeEditorTableAction { public void adjustEnablement() { boolean enabled = true; CompEditorModel editorModel = (CompEditorModel) model; - // Union do not support unaligned placement of bitfields - if (!(editorModel.viewComposite instanceof Structure) || editorModel.isAligned() || + // Union do not support non-packed placement of bitfields + if (!(editorModel.viewComposite instanceof Structure) || editorModel.isPackingEnabled() || editorModel.getNumSelectedRows() != 1 || editorModel.isFlexibleArraySelection()) { enabled = false; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java index 47036afab9..adf37c72ae 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java @@ -38,7 +38,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider { private Composite composite; private CompositeChangeListener listener; - private BitFieldEditorPanel bitFieldEditorPanel; // for unaligned use case + private BitFieldEditorPanel bitFieldEditorPanel; // for non-packed use case BitFieldEditorDialog(Composite composite, DataTypeManagerService dtmService, int editOrdinal, boolean showOffsetsInHex, CompositeChangeListener listener) { @@ -290,11 +290,11 @@ public class BitFieldEditorDialog extends DialogComponentProvider { } private static String getCompositeType(Composite composite) { - // currently supports unaligned case only! - if (composite.isInternallyAligned()) { - throw new IllegalArgumentException("Aligned use not supported"); + // currently supports non-packed case only! + if (composite.isPackingEnabled()) { + throw new IllegalArgumentException("Packed use not supported"); } - String alignmentMode = composite.isInternallyAligned() ? "Aligned" : "Unaligned"; + String alignmentMode = composite.isPackingEnabled() ? "Packed" : "Non-Packed"; String type = (composite instanceof Union) ? "Union" : "Structure"; return alignmentMode + " " + type; } @@ -309,7 +309,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider { baseDataType = ((BitFieldDataType) dtc.getDataType()).getBaseDataType(); } } - else if (!composite.isNotYetDefined()) { + else if (!composite.isZeroLength()) { offset = composite.getLength(); } @@ -346,7 +346,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider { // Assume a reasonable alignment in identifying aligned offset int alignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization, - Composite.NOT_PACKING, bitfieldDt.getBaseDataType(), bitfieldDt.getBaseTypeSize()); + CompositeInternal.NO_PACKING, bitfieldDtc); int adjustedOffset = offset - (offset % alignment); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java index c438f2344b..a70cec5916 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorPanel.java @@ -41,7 +41,7 @@ import resources.ResourceManager; /** * BitFieldEditorPanel provides the ability to add or modify bitfields - * within unaligned structures. + * within non-packed structures. */ public class BitFieldEditorPanel extends JPanel { @@ -81,9 +81,9 @@ public class BitFieldEditorPanel extends JPanel { super(); this.composite = composite; - if (composite.isInternallyAligned()) { + if (composite.isPackingEnabled()) { // A different bitfield editor should be used for aligned composites - throw new IllegalArgumentException("composite must be unaligned"); + throw new IllegalArgumentException("composite must be non-packed"); } setLayout(new VerticalLayout(5)); @@ -169,7 +169,7 @@ public class BitFieldEditorPanel extends JPanel { int offset = placementComponent.getAllocationOffset(); decrementButton.setEnabled(offset > 0); - int length = composite.isNotYetDefined() ? 0 : composite.getLength(); + int length = composite.isZeroLength() ? 0 : composite.getLength(); incrementButton.setEnabled(offset < length); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java index 882c9ff970..18d028a304 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldPlacementComponent.java @@ -157,7 +157,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable { } allocationByteOffset = 0; allocationByteSize = 1; - if (!editUseEnabled) { + if (!editUseEnabled && composite != null) { allocationByteSize = composite.getLength(); } init(null); @@ -456,7 +456,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable { composite.delete(editOrdinal); int sizeChange = initialLength - composite.getLength(); - if (!composite.isInternallyAligned() && editOrdinal < composite.getNumComponents()) { + if (!composite.isPackingEnabled() && editOrdinal < composite.getNumComponents()) { // deletions cause shift which is bad - pad with defaults for (int i = 0; i < sizeChange; i++) { composite.insert(editOrdinal, DataType.DEFAULT); @@ -851,7 +851,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable { BitFieldDataType bitfield = (BitFieldDataType) component.getDataType(); int storageSize = 8 * bitfield.getStorageSize(); rightBit = leftAdj + storageSize - bitfield.getBitOffset() - 1; - // Use effective bit-size since unaligned uses are only concerned with actual + // Use effective bit-size since non-packed uses are only concerned with actual // bits stored (NOTE: this may cause a transition from declared to effective // bit-size when editing a bitfield where the these bit-sizes differ). int bitSize = bitfield.getBitSize(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java index ea8d0360ba..392e0ba492 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java @@ -21,7 +21,6 @@ import docking.widgets.OptionDialog; import docking.widgets.fieldpanel.support.*; import ghidra.program.database.data.DataTypeUtilities; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; import ghidra.program.model.lang.InsufficientBytesException; import ghidra.util.*; import ghidra.util.exception.*; @@ -232,7 +231,7 @@ public abstract class CompEditorModel extends CompositeEditorModel { int numComps = getNumComponents(); // Make sure we don't have a selection with rows outside the table. - // This can happen due to switching between aligned and unaligned. + // This can happen due to switching between packed and non-packed. FieldSelection allRows = new FieldSelection(); allRows.addRange(0, numComps + 1); selection.intersect(allRows); @@ -346,30 +345,31 @@ public abstract class CompEditorModel extends CompositeEditorModel { * and does not perform any edit notification. * * @param rows array with each row (component) index to delete - * @param monitor the task monitor * @throws CancelledException if cancelled */ - private void delete(int[] rows, TaskMonitor monitor) throws CancelledException { + private void delete(int[] rows) throws CancelledException { int n = rows.length; - monitor.initialize(n); - - int[] selectedRows = getSelectedRows(); Arrays.sort(rows); + + Set rowSet = new HashSet<>(); + for (int i = n - 1; i >= 0; i--) { - monitor.checkCanceled(); - monitor.setMessage("Deleting " + (n - i + 1) + " of " + n); int rowIndex = rows[i]; int componentOrdinal = convertRowToOrdinal(rowIndex); - doDelete(componentOrdinal); - monitor.incrementProgress(1); + if (componentOrdinal < row) { + row--; + } + rowSet.add(componentOrdinal); } + viewComposite.delete(rowSet); + // Not sure if this is the right behavior. Assuming the deleted rows were selected, // restore the selection to be the first row that was deleted so that the UI leaves the // user's selection close to where it was. - if (selectedRows.length > 0) { - setSelection(new int[] { selectedRows[0] }); + if (rows.length > 0) { + setSelection(new int[] { rows[0] }); } notifyCompositeChanged(); @@ -409,14 +409,13 @@ public abstract class CompEditorModel extends CompositeEditorModel { } final int entries = endRowIndex - startRowIndex + 1; - int[] ordinals = new int[entries]; + Set ordinals = new HashSet<>(); monitor.initialize(entries); - int i = 0; - for (int rowIndex = endRowIndex; rowIndex >= startRowIndex; rowIndex--, i++) { + for (int rowIndex = endRowIndex; rowIndex >= startRowIndex; rowIndex--) { monitor.checkCanceled(); int componentOrdinal = convertRowToOrdinal(rowIndex); - ordinals[i] = componentOrdinal; + ordinals.add(componentOrdinal); if (componentOrdinal < row) { row--; } @@ -432,7 +431,7 @@ public abstract class CompEditorModel extends CompositeEditorModel { } @Override - public void deleteSelectedComponents(TaskMonitor monitor) throws UsrException { + public void deleteSelectedComponents() throws UsrException { if (!isDeleteAllowed()) { throw new UsrException("Deleting is not allowed."); } @@ -443,7 +442,7 @@ public abstract class CompEditorModel extends CompositeEditorModel { int[] selectedComponents = getSelectedComponentRows(); int firstRowIndex = !selection.isEmpty() ? selectedComponents[0] : getRowCount(); try { - delete(selectedComponents, monitor); + delete(selectedComponents); } finally { componentEdited(); @@ -1531,7 +1530,7 @@ public abstract class CompEditorModel extends CompositeEditorModel { } DataType dt = getComponent(rowIndex).getDataType(); int maxDups = Integer.MAX_VALUE; - // If editModel is showing undefined bytes (unaligned) + // If editModel is showing undefined bytes (non-packed) // then constrain by number of undefined bytes that follow. if (isShowingUndefinedBytes() && (dt != DataType.DEFAULT)) { int numBytes = getNumUndefinedBytesAt(rowIndex + 1); @@ -1609,23 +1608,6 @@ public abstract class CompEditorModel extends CompositeEditorModel { return rowIndex; } - public boolean isAligned() { - return viewComposite.isInternallyAligned(); - } - - public void setAligned(boolean aligned) { - boolean currentViewIsAligned = viewComposite.isInternallyAligned(); - if (currentViewIsAligned == aligned) { - return; - } - viewComposite.setInternallyAligned(aligned); - notifyCompositeChanged(); - } - - public int getPackingValue() { - return viewComposite.getPackingValue(); - } - protected boolean isSizeEditable() { return false; } @@ -1644,69 +1626,102 @@ public abstract class CompEditorModel extends CompositeEditorModel { hadChanges = false; return hadChanges; } - hadChanges = !(viewComposite.isInternallyAligned() == oldComposite.isInternallyAligned() && - viewComposite.getPackingValue() == oldComposite.getPackingValue() && - viewComposite.isDefaultAligned() == oldComposite.isDefaultAligned() && - viewComposite.isMachineAligned() == oldComposite.isMachineAligned() && - viewComposite.getMinimumAlignment() == oldComposite.getMinimumAlignment()); + + PackingType packingType = getPackingType(); + AlignmentType alignmentType = getAlignmentType(); + + hadChanges = (packingType != oldComposite.getPackingType()) || + (alignmentType != oldComposite.getAlignmentType()) || + (packingType == PackingType.EXPLICIT && + getExplicitPackingValue() != oldComposite.getExplicitPackingValue()) || + (alignmentType == AlignmentType.EXPLICIT && + getExplicitMinimumAlignment() != oldComposite.getExplicitMinimumAlignment()); return hadChanges; } /** - * Return the external (minimum) alignment type for the structure or union being viewed + * Return the (minimum) alignment type for the structure or union being viewed * @return the alignment type */ - public AlignmentType getMinimumAlignmentType() { - if (viewComposite.isDefaultAligned()) { - return AlignmentType.DEFAULT_ALIGNED; - } - if (viewComposite.isMachineAligned()) { - return AlignmentType.MACHINE_ALIGNED; - } - return AlignmentType.ALIGNED_BY_VALUE; + public AlignmentType getAlignmentType() { + return viewComposite.getAlignmentType(); } - /** - * Return the external (minimum) alignment value for the structure or union being viewed. - * @return the alignment - */ - public int getMinimumAlignment() { - if (viewComposite != null) { - return viewComposite.getMinimumAlignment(); - } - return 0; + public int getExplicitMinimumAlignment() { + return viewComposite.getExplicitMinimumAlignment(); } - public void setAlignmentType(AlignmentType alignmentType) { - if (alignmentType == AlignmentType.DEFAULT_ALIGNED) { - viewComposite.setToDefaultAlignment(); + public void setAlignmentType(AlignmentType alignmentType, int explicitValue) { + AlignmentType currentAlignType = getAlignmentType(); + if (alignmentType == AlignmentType.DEFAULT) { + if (currentAlignType == AlignmentType.DEFAULT) { + return; + } + viewComposite.setToDefaultAligned(); } - else if (alignmentType == AlignmentType.MACHINE_ALIGNED) { - viewComposite.setToMachineAlignment(); + else if (alignmentType == AlignmentType.MACHINE) { + if (currentAlignType == AlignmentType.MACHINE) { + return; + } + viewComposite.setToMachineAligned(); } else { - int alignment = viewComposite.getMinimumAlignment(); - if (alignment == 0) { - alignment = viewDTM.getDataOrganization().getAlignment(viewComposite, getLength()); + if (currentAlignType == AlignmentType.EXPLICIT && + explicitValue == viewComposite.getExplicitMinimumAlignment()) { + return; } - viewComposite.setMinimumAlignment(alignment); // Causes the type to change, but not the value. + viewComposite.setExplicitMinimumAlignment(explicitValue); + } + if (fixSelection()) { + selectionChanged(); } notifyCompositeChanged(); } - public abstract void setAlignment(int alignmentValue) throws InvalidInputException; + public boolean isPackingEnabled() { + return viewComposite.isPackingEnabled(); + } - public void setPackingValue(int packingValue) { - int currentViewPackingValue = viewComposite.getPackingValue(); - if (currentViewPackingValue == packingValue) { - return; + public PackingType getPackingType() { + return viewComposite.getPackingType(); + } + + public int getExplicitPackingValue() { + return viewComposite.getExplicitPackingValue(); + } + + public void setPackingType(PackingType packingType, int explicitValue) { + PackingType currentPacktype = getPackingType(); + if (packingType == PackingType.DISABLED) { + if (currentPacktype == PackingType.DISABLED) { + return; + } + viewComposite.setPackingEnabled(false); + } + else if (packingType == PackingType.DEFAULT) { + if (currentPacktype == PackingType.DEFAULT) { + return; + } + viewComposite.setToDefaultPacking(); + } + else { + if (currentPacktype == PackingType.EXPLICIT && + explicitValue == viewComposite.getExplicitPackingValue()) { + return; + } + viewComposite.setExplicitPackingValue(explicitValue); + } + if (fixSelection()) { + selectionChanged(); } - viewComposite.setPackingValue(packingValue); notifyCompositeChanged(); } public int getActualAlignment() { - return viewDTM.getDataOrganization().getAlignment(viewComposite, getLength()); + return viewComposite.getAlignment(); +// return viewDTM.getDataOrganization().getAlignment(viewComposite, getLength()); } + + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java index 6e0f4c1ca7..e16c706737 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorPanel.java @@ -21,23 +21,21 @@ import java.awt.dnd.DropTargetDragEvent; import java.awt.event.*; import javax.swing.*; +import javax.swing.border.TitledBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.Document; import docking.widgets.OptionDialog; import docking.widgets.button.GRadioButton; -import docking.widgets.checkbox.GCheckBox; import docking.widgets.fieldpanel.support.FieldSelection; import docking.widgets.label.GDLabel; import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitAttributes; import ghidra.program.model.data.*; import ghidra.program.model.data.Composite; -import ghidra.program.model.data.Composite.AlignmentType; import ghidra.util.HelpLocation; import ghidra.util.InvalidNameException; import ghidra.util.exception.DuplicateNameException; -import ghidra.util.exception.InvalidInputException; import ghidra.util.layout.PairLayout; import ghidra.util.layout.VerticalLayout; @@ -47,37 +45,35 @@ import ghidra.util.layout.VerticalLayout; */ public class CompEditorPanel extends CompositeEditorPanel { - private final static String NO_PACKING_STRING = ""; protected final static Insets LEFT_INSETS = new Insets(2, 3, 1, 0); protected final static Insets VERTICAL_INSETS = new Insets(2, 0, 1, 0); // GUI components for displaying composite data type information. - protected GridBagLayout gridBagLayout; - protected JPanel infoPanel; - protected JLabel nameLabel; + private GridBagLayout gridBagLayout; + private JPanel infoPanel; + private JLabel nameLabel; protected JTextField nameTextField; - protected JLabel descriptionLabel; - protected JTextField descriptionTextField; - protected JLabel categoryLabel; - protected JTextField categoryStatusTextField; - protected JLabel sizeLabel; - protected JTextField sizeStatusTextField; + private JLabel descriptionLabel; + private JTextField descriptionTextField; + private JLabel categoryLabel; + private JTextField categoryStatusTextField; + private JLabel sizeLabel; + private JTextField sizeTextField; - protected JCheckBox internalAlignmentCheckBox; + private JPanel alignPanel; + private JRadioButton defaultAlignButton; + private JRadioButton machineAlignButton; + private JRadioButton explicitAlignButton; + private JTextField explicitAlignTextField; - protected JPanel minimumAlignmentPanel; - protected JRadioButton defaultMinAlignButton; - protected JRadioButton machineMinAlignButton; - protected JRadioButton byValueMinAlignButton; - protected JTextField minAlignValueTextField; + private JPanel packingPanel; + private JCheckBox packingEnablementButton; + private JRadioButton defaultPackingButton; + private JRadioButton explicitPackingButton; + private JTextField explicitPackingTextField; - protected JPanel packingPanel; - protected JRadioButton noPackingButton; - protected JRadioButton byValuePackingButton; - protected JTextField packingValueTextField; - - protected JLabel actualAlignmentLabel; - protected JTextField actualAlignmentValueTextField; + private JLabel actualAlignmentLabel; + private JTextField actualAlignmentValueTextField; private BitFieldPlacementComponent bitViewComponent; @@ -100,7 +96,6 @@ public class CompEditorPanel extends CompositeEditorPanel { */ public CompEditorPanel(CompEditorModel model, CompositeEditorProvider provider) { super(model, provider); - setInternallyAligned(model.viewComposite.isInternallyAligned()); } @Override @@ -111,6 +106,8 @@ public class CompEditorPanel extends CompositeEditorPanel { @Override public void componentDataChanged() { + refreshGUIPackingValue(); + refreshGUIMinimumAlignmentValue(); refreshGUIActualAlignmentValue(); setCompositeSize(model.getLength()); } @@ -135,25 +132,7 @@ public class CompEditorPanel extends CompositeEditorPanel { if (c != null) { setCategoryName(c.toString()); } - setInternallyAligned(((CompEditorModel) model).isAligned()); - refreshGUIMinimumAlignmentType(); - refreshGUIMinimumAlignmentValue(); - refreshGUIActualAlignmentValue(); - setCompositeSize(model.getLength()); - refreshGUIPackingValue(); - } - - private void refreshGUIMinimumAlignmentType() { - AlignmentType minimumAlignmentType = ((CompEditorModel) model).getMinimumAlignmentType(); - if (minimumAlignmentType == AlignmentType.DEFAULT_ALIGNED) { - defaultMinAlignButton.setSelected(true); - } - else if (minimumAlignmentType == AlignmentType.MACHINE_ALIGNED) { - machineMinAlignButton.setSelected(true); - } - else { - byValueMinAlignButton.setSelected(true); - } + componentDataChanged(); } @Override @@ -267,7 +246,6 @@ public class CompEditorPanel extends CompositeEditorPanel { setupCategory(); setupSize(); setupActualAlignment(); - setupInternallyAligned(); setupMinimumAlignment(); setupPacking(); @@ -363,56 +341,16 @@ public class CompEditorPanel extends CompositeEditorPanel { infoPanel.add(categoryStatusTextField, gridBagConstraints); } - private void setupInternallyAligned() { - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - - internalAlignmentCheckBox = new GCheckBox("Align"); - gridBagConstraints.anchor = GridBagConstraints.LINE_END; - gridBagConstraints.fill = GridBagConstraints.NONE; - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 3; - internalAlignmentCheckBox.setSelected(model.viewComposite.isInternallyAligned()); - internalAlignmentCheckBox.setToolTipText( - "Whether or not the internal components of this structure are aligned."); - internalAlignmentCheckBox.setEnabled(true); - if (helpManager != null) { - helpManager.registerHelp(internalAlignmentCheckBox, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "InternallyAligned")); - } - internalAlignmentCheckBox.setName("Internally Aligned"); - - internalAlignmentCheckBox.addItemListener(e -> adjustInternalAlignment()); - infoPanel.add(internalAlignmentCheckBox, gridBagConstraints); - } - - protected void adjustInternalAlignment() { - boolean aligned = internalAlignmentCheckBox.isSelected(); - ((CompEditorModel) model).setAligned(aligned); - if (aligned) { - showMinimumAlignment(); - } - else { - hideMinimumAlignment(); - } - packingValueTextField.setEditable(aligned); - if (aligned) { - showPacking(); - } - else { - hidePacking(); - } - } - @Override public Dimension getPreferredSize() { // make sure our preferred size accounts for that of our components that the user // may choose to show Dimension preferredSize = super.getPreferredSize(); - if (minimumAlignmentPanel.isShowing()) { + if (alignPanel.isShowing()) { return preferredSize; } - Dimension alignmentPanelPreferredSize = minimumAlignmentPanel.getPreferredSize(); + Dimension alignmentPanelPreferredSize = alignPanel.getPreferredSize(); preferredSize.width += alignmentPanelPreferredSize.width; Dimension packingPanelPreferredSize = packingPanel.getPreferredSize(); @@ -422,34 +360,50 @@ public class CompEditorPanel extends CompositeEditorPanel { } private void setupMinimumAlignment() { - defaultMinAlignButton = new GRadioButton("none "); - machineMinAlignButton = new GRadioButton("machine "); - byValueMinAlignButton = new GRadioButton(); - minAlignValueTextField = new JTextField(); - setupDefaultMinAlignButton(); - setupMachineMinAlignButton(); - setupByValueMinAlignButton(); - ButtonGroup minAlignGroup = new ButtonGroup(); - minAlignGroup.add(defaultMinAlignButton); - minAlignGroup.add(machineMinAlignButton); - minAlignGroup.add(byValueMinAlignButton); - refreshGUIMinimumAlignmentType(); - minimumAlignmentPanel = new JPanel(new GridBagLayout()); - minimumAlignmentPanel.setBorder(BorderFactory.createTitledBorder("align( minimum )")); + DataOrganization dataOrganization = + ((CompEditorModel) model).viewComposite.getDataOrganization(); + int machineAlignment = dataOrganization.getMachineAlignment(); + + defaultAlignButton = new GRadioButton("default "); + explicitAlignButton = new GRadioButton(); + explicitAlignTextField = new JTextField(); + machineAlignButton = new GRadioButton("machine: " + machineAlignment); + setupDefaultMinAlignButton(); + setupExplicitAlignButton(); + setupMachineMinAlignButton(); + ButtonGroup minAlignGroup = new ButtonGroup(); + minAlignGroup.add(defaultAlignButton); + minAlignGroup.add(explicitAlignButton); + minAlignGroup.add(machineAlignButton); + + alignPanel = new JPanel(new GridBagLayout()); + TitledBorder border = BorderFactory.createTitledBorder("align (minimum)"); +// border.setTitlePosition(TitledBorder.ABOVE_TOP); + alignPanel.setBorder(border); if (helpManager != null) { - helpManager.registerHelp(minimumAlignmentPanel, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "AlignMinimum")); + helpManager.registerHelp(alignPanel, + new HelpLocation(provider.getHelpTopic(), provider.getHelpName() + "_" + "Align")); } - String alignmentToolTip = "" + "The minimum alignment to be used when
    " + - "aligning this data type inside another data type.

    " + - "Align this data type
    " + - "... in the default way based only on its components with no minimum,
    " + - "... to a multiple of the machine alignment,
    " + - "... to a multiple of the specified value in the text field." + ""; - minimumAlignmentPanel.setToolTipText(alignmentToolTip); + String alignmentToolTip = + "The align control allows the overall minimum alignment of this
    " + + "data type to be specified. The actual computed alignment
    " + + "may be any multiple of this value. (<F1> for help)"; + alignPanel.setToolTipText(alignmentToolTip); addMinimumAlignmentComponents(); + + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.fill = GridBagConstraints.NONE; + gridBagConstraints.weightx = 0; + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 4; + infoPanel.add(alignPanel, gridBagConstraints); + infoPanel.invalidate(); + + refreshGUIActualAlignmentValue(); } private void addMinimumAlignmentComponents() { @@ -460,121 +414,143 @@ public class CompEditorPanel extends CompositeEditorPanel { gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 2; - minimumAlignmentPanel.add(defaultMinAlignButton, gridBagConstraints); + alignPanel.add(defaultAlignButton, gridBagConstraints); gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.fill = GridBagConstraints.NONE; gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - minimumAlignmentPanel.add(machineMinAlignButton, gridBagConstraints); + gridBagConstraints.gridwidth = 1; + alignPanel.add(explicitAlignButton, gridBagConstraints); + + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 1; + alignPanel.add(explicitAlignTextField, gridBagConstraints); gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.fill = GridBagConstraints.NONE; gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 1; - minimumAlignmentPanel.add(byValueMinAlignButton, gridBagConstraints); - - gridBagConstraints.anchor = GridBagConstraints.WEST; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 1; - minimumAlignmentPanel.add(minAlignValueTextField, gridBagConstraints); + gridBagConstraints.gridwidth = 2; + alignPanel.add(machineAlignButton, gridBagConstraints); } private void setupDefaultMinAlignButton() { - defaultMinAlignButton.setName("Default Minimum Alignment"); + defaultAlignButton.setName("Default Alignment"); String alignmentToolTip = - "" + "Sets this data type to have no minimum alignment
    " + - "when aligning this data type inside another data type.
    " + - "Align this data type based only on its components." + ""; - defaultMinAlignButton.setToolTipText(alignmentToolTip); + "Sets this data type to use default alignment.
    " + + "If packing is disabled, the default will be 1 byte. If packing
    " + + "is enabled, the alignment is computed based upon the pack
    " + + "setting and the alignment of each component data type."; + + defaultAlignButton.addActionListener(e -> { + ((CompEditorModel) model).setAlignmentType(AlignmentType.DEFAULT, -1); + }); + + defaultAlignButton.setToolTipText(alignmentToolTip); if (helpManager != null) { - helpManager.registerHelp(defaultMinAlignButton, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "AlignMinimum")); + helpManager.registerHelp(defaultAlignButton, new HelpLocation( + provider.getHelpTopic(), provider.getHelpName() + "_" + "Align")); } } private void setupMachineMinAlignButton() { - machineMinAlignButton.setName("Machine Minimum Alignment"); - String alignmentToolTip = "" + "Sets this data type to have a minimum alignment
    " + - "that is a multiple of the machine alignment
    " + - "when aligning this data type inside another data type." + ""; - machineMinAlignButton.setToolTipText(alignmentToolTip); + machineAlignButton.setName("Machine Alignment"); + String alignmentToolTip = + "Sets this data type to use the machine alignment
    " + + "as specified by the compiler specification. If packing is
    " + + "enabled, the computed alignment of this composite should be
    " + + "the machine alignment value."; + machineAlignButton.setToolTipText(alignmentToolTip); + + machineAlignButton.addActionListener(e -> { + ((CompEditorModel) model).setAlignmentType(AlignmentType.MACHINE, -1); + }); + if (helpManager != null) { - helpManager.registerHelp(machineMinAlignButton, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "AlignMinimum")); + helpManager.registerHelp(machineAlignButton, new HelpLocation( + provider.getHelpTopic(), provider.getHelpName() + "_" + "Align")); } } - private void setupByValueMinAlignButton() { - byValueMinAlignButton.setName("By Value Minimum Alignment"); - String alignmentToolTip = "" + "Sets this data type to have a minimum alignment
    " + - "that is a multiple of the specified value
    " + - "when aligning this data type inside another data type." + ""; - byValueMinAlignButton.setToolTipText(alignmentToolTip); + private void setupExplicitAlignButton() { + explicitAlignButton.setName("Explicit Alignment"); + String alignmentToolTip = + "Sets this data type to use the explicit alignment value
    " + + "specified. If packing is enabled, the computed alignment of
    " + + "this composite may be any multiple of this value."; + explicitAlignButton.setToolTipText(alignmentToolTip); + + explicitAlignButton.addActionListener(e -> { + chooseExplicitAlign(); + }); + if (helpManager != null) { - helpManager.registerHelp(byValueMinAlignButton, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "AlignMinimum")); + helpManager.registerHelp(explicitAlignButton, new HelpLocation( + provider.getHelpTopic(), provider.getHelpName() + "_" + "Align")); } - minAlignValueTextField.setName("Minimum Alignment Value"); - minAlignValueTextField.setEditable(true); - minAlignValueTextField.setToolTipText(alignmentToolTip); + explicitAlignTextField.setName("Explicit Alignment Value"); + explicitAlignTextField.setEditable(true); + explicitAlignTextField.addActionListener(e -> adjustExplicitMinimumAlignmentValue()); + + explicitAlignTextField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + if (explicitAlignButton.isSelected()) { + return; + } + explicitAlignButton.setSelected(true); + chooseExplicitAlign(); + } + + @Override + public void focusLost(FocusEvent e) { + adjustExplicitMinimumAlignmentValue(); + } + }); + + explicitAlignTextField.setToolTipText(alignmentToolTip); if (helpManager != null) { - helpManager.registerHelp(minAlignValueTextField, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "AlignMinimum")); + helpManager.registerHelp(explicitAlignTextField, new HelpLocation( + provider.getHelpTopic(), provider.getHelpName() + "_" + "Align")); } refreshGUIMinimumAlignmentValue(); // Display the initial value. } - private void showMinimumAlignment() { - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; - gridBagConstraints.fill = GridBagConstraints.NONE; - gridBagConstraints.weightx = 0; - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridheight = 4; - infoPanel.add(minimumAlignmentPanel, gridBagConstraints); - infoPanel.invalidate(); - validate(); - } - - private void hideMinimumAlignment() { - infoPanel.remove(minimumAlignmentPanel); - infoPanel.invalidate(); - validate(); - } - - protected void adjustMinimumAlignmentValue() { - String value = minAlignValueTextField.getText(); + private void adjustExplicitMinimumAlignmentValue() { + setStatus(null); + String value = explicitAlignTextField.getText(); try { - int minAlignment = Integer.decode(value); + int minAlignment = Integer.decode(value.trim()); try { - ((CompEditorModel) model).setAlignment(minAlignment); + ((CompEditorModel) model).setAlignmentType(AlignmentType.EXPLICIT, minAlignment); adjustCompositeInfo(); } - catch (InvalidInputException e1) { + catch (IllegalArgumentException e1) { refreshGUIMinimumAlignmentValue(); - String message = "\"" + value + "\" is not a valid minimum alignment value."; + String message = "\"" + value + "\" is not a valid alignment value."; setStatus(message); } } catch (NumberFormatException e1) { refreshGUIMinimumAlignmentValue(); - String message = "\"" + value + "\" is not a valid minimum alignment value."; + String message = "\"" + value + "\" is not a valid alignment value."; setStatus(message); } } private void setupActualAlignment() { GridBagConstraints gridBagConstraints = new GridBagConstraints(); - String actualAlignmentToolTip = "" + "The actual alignment to be used when
    " + - "aligning this data type inside another data type." + ""; + String actualAlignmentToolTip = + "The actual alignment to be used for this data type.
    " + + "A combination of the pack and alignment settings made to this datatype
    " + + "combined with alignments of the individual components are used to
    " + + "to compute the actual alignment of this datatype."; JPanel actualAlignmentPanel = new JPanel(new BorderLayout()); actualAlignmentLabel = new GDLabel("Alignment:"); @@ -588,7 +564,7 @@ public class CompEditorPanel extends CompositeEditorPanel { infoPanel.add(actualAlignmentPanel, gridBagConstraints); actualAlignmentValueTextField = new JTextField(8); - actualAlignmentValueTextField.setText("" + ((CompEditorModel) model).getMinimumAlignment()); + actualAlignmentValueTextField.setText("" + ((CompEditorModel) model).getActualAlignment()); actualAlignmentValueTextField.setToolTipText(actualAlignmentToolTip); actualAlignmentValueTextField.setEditable(false); if (helpManager != null) { @@ -604,36 +580,55 @@ public class CompEditorPanel extends CompositeEditorPanel { gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 3; infoPanel.add(actualAlignmentValueTextField, gridBagConstraints); + actualAlignmentValueTextField.setBackground(new Color(getBackground().getRGB())); } private void setupPacking() { - noPackingButton = new GRadioButton("none "); - byValuePackingButton = new GRadioButton(); - packingValueTextField = new JTextField(); - setupNoPackingButton(); - setupByValuePackingButton(); + + packingPanel = new JPanel(new VerticalLayout(0)); + + packingEnablementButton = new JCheckBox("pack"); + packingEnablementButton.setEnabled(true); + packingEnablementButton.setFont(UIManager.getFont("TitledBorder.font")); + packingEnablementButton.setForeground(UIManager.getColor("TitledBorder.titleColor")); + packingPanel.add(packingEnablementButton); + + JPanel innerPanel = new JPanel(new GridBagLayout()); + innerPanel.setBorder(UIManager.getBorder("TitledBorder.border")); + packingPanel.add(innerPanel); + + defaultPackingButton = new GRadioButton("default "); + explicitPackingButton = new GRadioButton(); + explicitPackingTextField = new JTextField(); + + setupDefaultPackingButton(); + setupExplicitPackingButton(); + setupPackingEnablementButton(); ButtonGroup packingGroup = new ButtonGroup(); - packingGroup.add(noPackingButton); - packingGroup.add(byValuePackingButton); + packingGroup.add(defaultPackingButton); + packingGroup.add(explicitPackingButton); - packingPanel = new JPanel(new GridBagLayout()); - packingPanel.setBorder(BorderFactory.createTitledBorder("pack( maximum )")); if (helpManager != null) { helpManager.registerHelp(packingPanel, new HelpLocation(provider.getHelpTopic(), - provider.getHelpName() + "_" + "PackMaximum")); + provider.getHelpName() + "_" + "Pack")); } - String packingToolTipText = - "\"none\" indicates components are not being packed.
    " + - "Otherwise, the value indicates the maximum alignment to use when packing any component.
    " + - "Note: An individual data type's alignment may override this value."; - packingPanel.setToolTipText(packingToolTipText); - addPackingComponents(); + addPackingComponents(innerPanel); + + GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.fill = GridBagConstraints.NONE; + gridBagConstraints.weightx = 0; + gridBagConstraints.gridx = 7; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 4; + infoPanel.add(packingPanel, gridBagConstraints); + refreshGUIPackingValue(); } - private void addPackingComponents() { + private void addPackingComponents(JPanel gridPanel) { GridBagConstraints gridBagConstraints = new GridBagConstraints(); gridBagConstraints.anchor = GridBagConstraints.WEST; @@ -641,67 +636,87 @@ public class CompEditorPanel extends CompositeEditorPanel { gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 2; - packingPanel.add(noPackingButton, gridBagConstraints); + gridPanel.add(defaultPackingButton, gridBagConstraints); gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.fill = GridBagConstraints.NONE; gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 1; - packingPanel.add(byValuePackingButton, gridBagConstraints); + gridPanel.add(explicitPackingButton, gridBagConstraints); gridBagConstraints.anchor = GridBagConstraints.WEST; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 1; - packingPanel.add(packingValueTextField, gridBagConstraints); + gridPanel.add(explicitPackingTextField, gridBagConstraints); + + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.fill = GridBagConstraints.NONE; + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; +// gridPanel.add(disabledPackingButton, gridBagConstraints); } - private void setupNoPackingButton() { - noPackingButton.setName("No Packing"); + private void setupPackingEnablementButton() { + packingEnablementButton.setName("Packing Enablement"); String packingToolTipText = - "\"none\" indicates components are not being packed.
    " + - "Otherwise, the value indicates the maximum alignment to use when packing any component.
    " + - "Note: An individual data type's alignment may override this value."; - - noPackingButton.addActionListener(e -> { - ((CompEditorModel) model).setPackingValue(Composite.NOT_PACKING); + "Enable packing when details of all components are known (including sizing and alignment).
    " + + "Disable packing when Reverse Engineering composite. (<F1> for help)"; + packingEnablementButton.addActionListener(e -> { + ((CompEditorModel) model).setPackingType( + packingEnablementButton.isSelected() ? PackingType.DEFAULT : PackingType.DISABLED, + -1); }); - noPackingButton.setToolTipText(packingToolTipText); + packingEnablementButton.setToolTipText(packingToolTipText); if (helpManager != null) { - helpManager.registerHelp(noPackingButton, new HelpLocation(provider.getHelpTopic(), - provider.getHelpName() + "_" + "PackMaximum")); + helpManager.registerHelp(packingEnablementButton, + new HelpLocation(provider.getHelpTopic(), provider.getHelpName() + "_" + "Pack")); } } - private void setupByValuePackingButton() { - byValuePackingButton.setName("By Value Packing"); + private void setupDefaultPackingButton() { + defaultPackingButton.setName("Default Packing"); String packingToolTipText = - "\"none\" indicates components are not being packed.
    " + - "Otherwise, the value indicates the maximum alignment to use when packing any component.
    " + - "Note: An individual data type's alignment may override this value."; + "Indicates default compiler packing rules should be applied."; - byValuePackingButton.addActionListener(e -> chooseByValuePacking()); - byValuePackingButton.setToolTipText(packingToolTipText); + defaultPackingButton.addActionListener(e -> { + ((CompEditorModel) model).setPackingType(PackingType.DEFAULT, -1); + }); + + defaultPackingButton.setToolTipText(packingToolTipText); if (helpManager != null) { - helpManager.registerHelp(byValuePackingButton, new HelpLocation(provider.getHelpTopic(), - provider.getHelpName() + "_" + "PackMaximum")); + helpManager.registerHelp(defaultPackingButton, new HelpLocation(provider.getHelpTopic(), + provider.getHelpName() + "_" + "Pack")); + } + } + + private void setupExplicitPackingButton() { + explicitPackingButton.setName("Explicit Packing"); + String packingToolTipText = + "Indicates an explicit pack size should be applied."; + + explicitPackingButton.addActionListener(e -> chooseByValuePacking()); + explicitPackingButton.setToolTipText(packingToolTipText); + if (helpManager != null) { + helpManager.registerHelp(explicitPackingButton, new HelpLocation(provider.getHelpTopic(), + provider.getHelpName() + "_" + "Pack")); } - packingValueTextField.setName("Packing Value"); - packingValueTextField.setEditable(true); + explicitPackingTextField.setName("Packing Value"); + explicitPackingTextField.setEditable(true); + explicitPackingTextField.addActionListener(e -> adjustPackingValue()); - packingValueTextField.addActionListener(e -> adjustPackingValue()); - - packingValueTextField.addFocusListener(new FocusListener() { + explicitPackingTextField.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { - if (byValuePackingButton.isSelected()) { + if (explicitPackingButton.isSelected()) { return; } - byValuePackingButton.setSelected(true); + explicitPackingButton.setSelected(true); chooseByValuePacking(); } @@ -711,31 +726,25 @@ public class CompEditorPanel extends CompositeEditorPanel { } }); - packingValueTextField.setToolTipText(packingToolTipText); + explicitPackingTextField.setToolTipText(packingToolTipText); if (helpManager != null) { - helpManager.registerHelp(packingValueTextField, new HelpLocation( - provider.getHelpTopic(), provider.getHelpName() + "_" + "PackMaximum")); + helpManager.registerHelp(explicitPackingTextField, new HelpLocation( + provider.getHelpTopic(), provider.getHelpName() + "_" + "Pack")); } } - protected void chooseByValuePacking() { - ((CompEditorModel) model).setPackingValue(1); - packingValueTextField.selectAll(); - packingValueTextField.requestFocus(); + private void chooseByValuePacking() { + ((CompEditorModel) model).setPackingType(PackingType.EXPLICIT, 1); + explicitPackingTextField.selectAll(); + explicitPackingTextField.requestFocus(); } - protected void adjustPackingValue() { - if (!packingValueTextField.isShowing()) { - return; - } - String value = packingValueTextField.getText(); + private void adjustPackingValue() { + setStatus(null); + String value = explicitPackingTextField.getText(); try { - int packingAlignment = 0; - if (!value.toLowerCase().equals(NO_PACKING_STRING)) { - packingAlignment = Integer.decode(value); - } - - ((CompEditorModel) model).setPackingValue(packingAlignment); + int explicitPacking = Integer.decode(value.trim()); + ((CompEditorModel) model).setPackingType(PackingType.EXPLICIT, explicitPacking); adjustCompositeInfo(); } catch (NumberFormatException e1) { @@ -744,47 +753,31 @@ public class CompEditorPanel extends CompositeEditorPanel { } } - private void showPacking() { - GridBagConstraints gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; - gridBagConstraints.fill = GridBagConstraints.NONE; - gridBagConstraints.weightx = 0; - gridBagConstraints.gridx = 7; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridheight = 4; - infoPanel.add(packingPanel, gridBagConstraints); - infoPanel.invalidate(); - validate(); - } - - private void hidePacking() { - infoPanel.remove(packingPanel); - infoPanel.invalidate(); - validate(); - } - /** * Sets the currently displayed structure packing value (maximum component alignment) */ public void refreshGUIPackingValue() { - int packingValue = ((CompEditorModel) model).getPackingValue(); - boolean isPacking = (packingValue != Composite.NOT_PACKING); - if (isPacking) { - byValuePackingButton.setSelected(true); + PackingType packingType = ((CompEditorModel) model).getPackingType(); + String packingString = ""; + + boolean packingEnabled = packingType != PackingType.DISABLED; + packingEnablementButton.setSelected(packingEnabled); + + defaultPackingButton.setEnabled(packingEnabled); + explicitPackingButton.setEnabled(packingEnabled); + explicitPackingTextField.setEnabled(packingEnabled); + + if (packingType == PackingType.DEFAULT) { + defaultPackingButton.setSelected(true); } - else { - noPackingButton.setSelected(true); - } - String packingString; - if (isPacking) { + else if (packingType == PackingType.EXPLICIT) { + int packValue = ((CompEditorModel) model).getExplicitPackingValue(); packingString = - model.showHexNumbers ? CompositeViewerModel.getHexString(packingValue, true) - : Integer.toString(packingValue); + model.showHexNumbers ? CompositeViewerModel.getHexString(packValue, true) + : Integer.toString(packValue); + explicitPackingButton.setSelected(true); } - else { - packingString = NO_PACKING_STRING; - } - packingValueTextField.setText(packingString); + explicitPackingTextField.setText(packingString); } protected void setupSize() { @@ -798,18 +791,18 @@ public class CompEditorPanel extends CompositeEditorPanel { gridBagConstraints.gridy = 3; infoPanel.add(sizeLabel, gridBagConstraints); - sizeStatusTextField = new JTextField(10); - sizeStatusTextField.setName("Total Length"); - sizeStatusTextField.setEditable(false); - sizeStatusTextField.setToolTipText("The current size in bytes."); + sizeTextField = new JTextField(10); + sizeTextField.setName("Total Length"); + sizeTextField.setToolTipText("The current size in bytes."); + setSizeEditable(false); gridBagConstraints.ipadx = 60; gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; - infoPanel.add(sizeStatusTextField, gridBagConstraints); + infoPanel.add(sizeTextField, gridBagConstraints); - sizeStatusTextField.addActionListener(e -> updatedStructureSize()); - sizeStatusTextField.addFocusListener(new FocusListener() { + sizeTextField.addActionListener(e -> updatedStructureSize()); + sizeTextField.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { // don't care @@ -817,7 +810,7 @@ public class CompEditorPanel extends CompositeEditorPanel { @Override public void focusLost(FocusEvent e) { - if (sizeStatusTextField.isEditable()) { + if (sizeTextField.isEditable()) { updatedStructureSize(); } } @@ -825,7 +818,15 @@ public class CompEditorPanel extends CompositeEditorPanel { } protected void setSizeEditable(boolean editable) { - sizeStatusTextField.setEditable(editable); + sizeTextField.setEditable(editable); + if (editable) { + // editable - use same background as category field + sizeTextField.setBackground(categoryStatusTextField.getBackground()); + } + else { + // not editable - use same background as panel + sizeTextField.setBackground(new Color(getBackground().getRGB())); + } } private void updatedStructureSize() { @@ -833,7 +834,7 @@ public class CompEditorPanel extends CompositeEditorPanel { if (updatingSize) { return; } - if (!sizeStatusTextField.isShowing()) { + if (!sizeTextField.isShowing()) { return; } @@ -841,7 +842,7 @@ public class CompEditorPanel extends CompositeEditorPanel { return; } - String valueStr = sizeStatusTextField.getText(); + String valueStr = sizeTextField.getText(); Integer value; try { updatingSize = true; @@ -866,6 +867,7 @@ public class CompEditorPanel extends CompositeEditorPanel { } } ((StructureEditorModel) model).setStructureSize(structureSize); + model.setStatus(null); } } catch (NumberFormatException e1) { @@ -931,37 +933,14 @@ public class CompEditorPanel extends CompositeEditorPanel { else if (source == descriptionTextField) { updatedDescription(); } - else if (source == defaultMinAlignButton) { - chooseDefaultMinAlign(); - } - else if (source == machineMinAlignButton) { - chooseMachineMinAlign(); - } - else if (source == byValueMinAlignButton) { - chooseByValueMinAlign(); - } - else if (source == minAlignValueTextField) { - updatedMinAlignValue(); - } }; nameTextField.addActionListener(fieldActionListener); descriptionTextField.addActionListener(fieldActionListener); - defaultMinAlignButton.addActionListener(fieldActionListener); - machineMinAlignButton.addActionListener(fieldActionListener); - byValueMinAlignButton.addActionListener(fieldActionListener); - minAlignValueTextField.addActionListener(fieldActionListener); fieldFocusListener = new FocusListener() { @Override public void focusGained(FocusEvent e) { - Object source = e.getSource(); - if (source == minAlignValueTextField) { - if (byValueMinAlignButton.isSelected()) { - return; - } - byValueMinAlignButton.setSelected(true); - chooseByValueMinAlign(); - } + // ignore } @Override @@ -973,33 +952,24 @@ public class CompEditorPanel extends CompositeEditorPanel { else if (source == descriptionTextField) { updatedDescription(); } - else if (source == minAlignValueTextField) { - updatedMinAlignValue(); - } } }; nameTextField.addFocusListener(fieldFocusListener); descriptionTextField.addFocusListener(fieldFocusListener); - minAlignValueTextField.addFocusListener(fieldFocusListener); - } - protected void chooseDefaultMinAlign() { - ((CompEditorModel) model).setAlignmentType(AlignmentType.DEFAULT_ALIGNED); - } - - protected void chooseMachineMinAlign() { - ((CompEditorModel) model).setAlignmentType(AlignmentType.MACHINE_ALIGNED); - } - - protected void chooseByValueMinAlign() { - ((CompEditorModel) model).setAlignmentType(AlignmentType.ALIGNED_BY_VALUE); - minAlignValueTextField.selectAll(); - minAlignValueTextField.requestFocus(); - } - - protected void updatedMinAlignValue() { - adjustMinimumAlignmentValue(); + private void chooseExplicitAlign() { + if (((CompEditorModel) model).getAlignmentType() != AlignmentType.EXPLICIT) { + Composite viewComposite = ((CompEditorModel) model).viewComposite; + int defaultValue = 1; + if (viewComposite.isPackingEnabled()) { + defaultValue = viewComposite.getDataOrganization().getMachineAlignment(); + } + ((CompEditorModel) model).setAlignmentType(AlignmentType.EXPLICIT, + defaultValue); + } + explicitAlignTextField.selectAll(); + explicitAlignTextField.requestFocus(); } private void removeFieldListeners() { @@ -1011,14 +981,14 @@ public class CompEditorPanel extends CompositeEditorPanel { descriptionTextField.removeActionListener(fieldActionListener); descriptionTextField.removeFocusListener(fieldFocusListener); - defaultMinAlignButton.addActionListener(fieldActionListener); + defaultAlignButton.addActionListener(fieldActionListener); - machineMinAlignButton.addActionListener(fieldActionListener); + machineAlignButton.addActionListener(fieldActionListener); - byValueMinAlignButton.addActionListener(fieldActionListener); + explicitAlignButton.addActionListener(fieldActionListener); - minAlignValueTextField.addActionListener(fieldActionListener); - minAlignValueTextField.removeFocusListener(fieldFocusListener); + explicitAlignTextField.addActionListener(fieldActionListener); + explicitAlignTextField.removeFocusListener(fieldFocusListener); } /** @@ -1139,56 +1109,31 @@ public class CompEditorPanel extends CompositeEditorPanel { descriptionTextField.setText(description); } - /** - * Checks the GUI to determine if this composite is internally aligned - * @return true if interanlly aligned - */ - public boolean isInternallyAlignedInGui() { - return internalAlignmentCheckBox.isSelected(); - } - - /** - * Sets the currently displayed structure minimum alignment type - * - * @param aligned true if aligned - */ - public void setInternallyAligned(boolean aligned) { - boolean alignedInGui = internalAlignmentCheckBox.isSelected(); - if (alignedInGui != aligned) { - internalAlignmentCheckBox.setSelected(aligned); - } - adjustInternalAlignment(); - } - - /** - * Updates the GUI display of the minimum alignment value. - */ public void refreshGUIMinimumAlignmentValue() { - int minimumAlignment = ((CompEditorModel) model).getMinimumAlignment(); - String value = minAlignValueTextField.getText(); - boolean emptyValue = (value.length() == 0); - boolean notByValue = ((CompEditorModel) model).viewComposite.isDefaultAligned() || - ((CompEditorModel) model).viewComposite.isMachineAligned(); - if (notByValue) { - if (!emptyValue) { - minAlignValueTextField.setText(""); - } - return; // No value displayed since default or machine. - } - // Change the display to the correct value. - String minimumAlignmentStr = - model.showHexNumbers ? CompositeViewerModel.getHexString(minimumAlignment, true) - : Integer.toString(minimumAlignment); - minAlignValueTextField.setText(minimumAlignmentStr); + AlignmentType alignmentType = ((CompEditorModel) model).getAlignmentType(); + String minimumAlignmentStr = ""; + if (alignmentType == AlignmentType.DEFAULT) { + defaultAlignButton.setSelected(true); + } + else if (alignmentType == AlignmentType.MACHINE) { + machineAlignButton.setSelected(true); + } + else { + explicitAlignButton.setSelected(true); + int minimumAlignment = ((CompEditorModel) model).getExplicitMinimumAlignment(); + minimumAlignmentStr = + model.showHexNumbers ? CompositeViewerModel.getHexString(minimumAlignment, true) + : Integer.toString(minimumAlignment); + } + explicitAlignTextField.setText(minimumAlignmentStr); } /** * Updates the GUI display of the actual alignment value. */ public void refreshGUIActualAlignmentValue() { - int actualAlignment = ((CompEditorModel) model).viewDTM.getDataOrganization().getAlignment( - ((CompEditorModel) model).viewComposite, ((CompEditorModel) model).getLength()); + int actualAlignment = ((CompEditorModel) model).getActualAlignment(); String alignmentStr = model.showHexNumbers ? CompositeViewerModel.getHexString(actualAlignment, true) : Integer.toString(actualAlignment); @@ -1200,7 +1145,7 @@ public class CompEditorPanel extends CompositeEditorPanel { * @return the size */ public int getCompositeSize() { - return Integer.decode(sizeStatusTextField.getText()); + return Integer.decode(sizeTextField.getText()); } /** @@ -1210,12 +1155,12 @@ public class CompEditorPanel extends CompositeEditorPanel { */ public void setCompositeSize(int size) { boolean sizeIsEditable = ((CompEditorModel) model).isSizeEditable(); - if (sizeStatusTextField.isEditable() != sizeIsEditable) { - sizeStatusTextField.setEditable(sizeIsEditable); + if (sizeTextField.isEditable() != sizeIsEditable) { + setSizeEditable(sizeIsEditable); } String sizeStr = model.showHexNumbers ? CompositeViewerModel.getHexString(size, true) : Integer.toString(size); - sizeStatusTextField.setText(sizeStr); + sizeTextField.setText(sizeStr); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorModel.java index 334ce10939..f925f51541 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorModel.java @@ -35,7 +35,6 @@ import ghidra.program.model.data.*; import ghidra.program.model.data.Enum; import ghidra.util.*; import ghidra.util.exception.*; -import ghidra.util.task.TaskMonitor; /** * Model for editing a composite data type. Specific composite data type editors @@ -546,7 +545,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen } @Override - public void deleteSelectedComponents(TaskMonitor monitor) throws UsrException { + public void deleteSelectedComponents() throws UsrException { if (!isDeleteAllowed()) { throw new UsrException("Deleting is not allowed."); } @@ -610,8 +609,8 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen private boolean hasCompPathNameChanges(Composite currentViewComposite, Composite oldComposite) { // Check component data type pathnames. - DataTypeComponent[] comps = currentViewComposite.getComponents(); - DataTypeComponent[] oldComps = oldComposite.getComponents(); + DataTypeComponent[] comps = currentViewComposite.getDefinedComponents(); + DataTypeComponent[] oldComps = oldComposite.getDefinedComponents(); if (comps.length != oldComps.length) { return true; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java index d7f748cd5f..4cbf429fc0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java @@ -153,7 +153,7 @@ public abstract class CompositeEditorPanel extends JPanel private boolean launchBitFieldEditor(int modelColumn, int editingRow) { if (model.viewComposite instanceof Structure && - !model.viewComposite.isInternallyAligned() && + !model.viewComposite.isPackingEnabled() && model.getDataTypeColumn() == modelColumn && editingRow < model.getNumComponents()) { // check if we are attempting to edit a bitfield DataTypeComponent dtComponent = model.getComponent(editingRow); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeViewerModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeViewerModel.java index f475d58d4f..8e966a9f24 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeViewerModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeViewerModel.java @@ -363,7 +363,7 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager * @return this size */ public int getLength() { - if (viewComposite != null && !viewComposite.isNotYetDefined()) { + if (viewComposite != null && !viewComposite.isZeroLength()) { return viewComposite.getLength(); } return 0; @@ -1386,8 +1386,7 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager protected void selectionChanged() { updatingSelection(() -> { - for (int i = 0; i < modelListeners.size(); i++) { - CompositeViewerModelListener listener = modelListeners.get(i); + for (CompositeViewerModelListener listener : modelListeners) { listener.selectionChanged(); } }); @@ -1411,8 +1410,7 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager */ protected void notify(List listeners, Consumer method) { swing(() -> { - for (int i = 0; i < listeners.size(); i++) { - T listener = listeners.get(i); + for (T listener : listeners) { method.accept(listener); } }); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java index 95252ee9fa..cd236c29df 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/DeleteAction.java @@ -52,7 +52,7 @@ public class DeleteAction extends CompositeEditorTableAction { private void doDelete(TaskMonitor monitor) { try { - model.deleteSelectedComponents(monitor); + model.deleteSelectedComponents(); } catch (CancelledException e) { // user cancelled diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditBitFieldAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditBitFieldAction.java index 6b3c7125b7..605b6530e6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditBitFieldAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditBitFieldAction.java @@ -48,7 +48,7 @@ public class EditBitFieldAction extends CompositeEditorTableAction { private DataTypeComponent getUnalignedBitFieldComponent() { CompEditorModel editorModel = (CompEditorModel) model; if ((editorModel.viewComposite instanceof Structure) && - !editorModel.viewComposite.isInternallyAligned() && + !editorModel.viewComposite.isPackingEnabled() && editorModel.getNumSelectedRows() == 1) { int rowIndex = model.getSelectedRows()[0]; if (rowIndex < model.getNumComponents()) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditorModel.java index ce3456616a..e915024ec2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/EditorModel.java @@ -322,8 +322,7 @@ public interface EditorModel { public void cycleDataType(CycleGroup cycleGroup); /** - * - * @param parent + * Create array component * @throws UsrException */ public void createArray() throws UsrException; @@ -331,10 +330,9 @@ public interface EditorModel { /** * Delete the selected components. * - * @param monitor the task monitor * @throws UsrException if the data type isn't allowed to be deleted. */ - public void deleteSelectedComponents(TaskMonitor monitor) throws UsrException; + public void deleteSelectedComponents() throws UsrException; /** * Creates multiple duplicates of the indicated component. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java index 8915ea41eb..72a8e6e557 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/InsertUndefinedAction.java @@ -58,7 +58,7 @@ public class InsertUndefinedAction extends CompositeEditorTableAction { int index = model.getMinIndexSelected(); if (index >= 0) { DataType undefinedDt = - model.viewComposite.isInternallyAligned() ? Undefined1DataType.dataType + model.viewComposite.isPackingEnabled() ? Undefined1DataType.dataType : DataType.DEFAULT; DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(undefinedDt, -1); model.insert(index, dti.getDataType(), dti.getLength()); @@ -77,7 +77,7 @@ public class InsertUndefinedAction extends CompositeEditorTableAction { if (model.viewComposite instanceof Structure) { boolean isContiguousSelection = model.getSelection().getNumRanges() == 1; DataType undefinedDt = - model.viewComposite.isInternallyAligned() ? Undefined1DataType.dataType + model.viewComposite.isPackingEnabled() ? Undefined1DataType.dataType : DataType.DEFAULT; enabled = isContiguousSelection && model.isInsertAllowed(model.getMinIndexSelected(), undefinedDt); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorModel.java index 34e188ba43..f5436d210d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/StructureEditorModel.java @@ -25,7 +25,6 @@ import docking.widgets.dialogs.InputDialogListener; import docking.widgets.fieldpanel.support.FieldRange; import docking.widgets.fieldpanel.support.FieldSelection; import ghidra.docking.settings.SettingsImpl; -import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.data.*; import ghidra.program.model.lang.InsufficientBytesException; import ghidra.util.Msg; @@ -201,17 +200,7 @@ class StructureEditorModel extends CompEditorModel { @Override public int getNumComponents() { - if (viewComposite == null) { - return 0; - } - if (isShowingUndefinedBytes()) { - if (viewComposite.isNotYetDefined()) { - return 0; - } - return viewComposite.getNumComponents(); - } - DataTypeComponent[] definedComponents = ((Structure) viewComposite).getDefinedComponents(); - return definedComponents.length; + return viewComposite == null ? 0 : viewComposite.getNumComponents(); } @Override @@ -252,14 +241,14 @@ class StructureEditorModel extends CompEditorModel { @Override protected boolean isSizeEditable() { - return !isAligned(); + return !isPackingEnabled(); } void setStructureSize(int size) { if (viewComposite == null) { return; } - int currentLength = viewComposite.isNotYetDefined() ? 0 : viewComposite.getLength(); + int currentLength = viewComposite.isZeroLength() ? 0 : viewComposite.getLength(); if (currentLength == size) { return; } @@ -449,8 +438,8 @@ class StructureEditorModel extends CompEditorModel { DataTypeComponent comp = deleteComponentAndResidual(startIndex - 1); try { - if (!isAligned() && comp.isBitFieldComponent()) { - // insert residual undefined bytes before inserting unaligned bitfield + if (!isPackingEnabled() && comp.isBitFieldComponent()) { + // insert residual undefined bytes before inserting non-packed bitfield int lenChange = len - getLength(); insert(endIndex, DataType.DEFAULT, 1, lenChange, TaskMonitor.DUMMY); } @@ -485,8 +474,8 @@ class StructureEditorModel extends CompEditorModel { DataTypeComponent comp = deleteComponentAndResidual(endIndex + 1); try { - if (!isAligned() && comp.isBitFieldComponent()) { - // insert residual undefined bytes before inserting unaligned bitfield + if (!isPackingEnabled() && comp.isBitFieldComponent()) { + // insert residual undefined bytes before inserting non-packed bitfield int lenChange = len - getLength(); insert(startIndex, DataType.DEFAULT, 1, lenChange, TaskMonitor.DUMMY); } @@ -507,7 +496,7 @@ class StructureEditorModel extends CompEditorModel { DataTypeComponent comp = getComponent(index); deleteComponent(index); - if (isAligned() || !comp.isBitFieldComponent() || index >= getNumComponents()) { + if (isPackingEnabled() || !comp.isBitFieldComponent() || index >= getNumComponents()) { return comp; } @@ -627,7 +616,7 @@ class StructureEditorModel extends CompEditorModel { } @Override - public void deleteSelectedComponents(TaskMonitor monitor) throws UsrException { + public void deleteSelectedComponents() throws UsrException { if (!isDeleteAllowed()) { throw new UsrException("Deleting is not allowed."); } @@ -646,7 +635,7 @@ class StructureEditorModel extends CompEditorModel { selectionChanged(); return; } - super.deleteSelectedComponents(monitor); + super.deleteSelectedComponents(); } @Override @@ -660,14 +649,14 @@ class StructureEditorModel extends CompEditorModel { int rowIndex = getRow(); DataTypeComponent comp = getComponent(rowIndex); DataType dt = comp.getDataType(); - if (viewComposite.isInternallyAligned()) { + if (viewComposite.isPackingEnabled()) { return true; } if (dt.equals(DataType.DEFAULT)) { return true; // Insert an undefined and push everything down. } if (comp.isBitFieldComponent()) { - return false; // unable to place unaligned bitfield in a reasonable fashion + return false; // unable to place non-packed bitfield in a reasonable fashion } // Can always duplicate at the end. if (isAtEnd(rowIndex) || onlyUndefinedsUntilEnd(rowIndex + 1)) { @@ -956,7 +945,7 @@ class StructureEditorModel extends CompEditorModel { dtc.getComment()); } else { - if (isAligned() || !(dataType instanceof BitFieldDataType)) { + if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) { dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name, comment); } @@ -1174,41 +1163,9 @@ class StructureEditorModel extends CompEditorModel { } } - @Override - public void setAligned(boolean aligned) { - boolean currentViewIsAligned = viewComposite.isInternallyAligned(); - if (currentViewIsAligned == aligned) { - return; - } - viewComposite.setInternallyAligned(aligned); - if (fixSelection()) { - selectionChanged(); - } - notifyCompositeChanged(); - } - - public void adjustAlignment(PluginTool tool, int minAlignment) { - int currentViewAlignment = viewComposite.getMinimumAlignment(); - if (currentViewAlignment == minAlignment) { - return; - } - viewComposite.setMinimumAlignment(minAlignment); - notifyCompositeChanged(); - } - - @Override - public void setAlignment(int minAlignment) throws InvalidInputException { - int currentViewAlignment = viewComposite.getMinimumAlignment(); - if (currentViewAlignment == minAlignment) { - return; - } - viewComposite.setMinimumAlignment(minAlignment); - notifyCompositeChanged(); - } - @Override public boolean isShowingUndefinedBytes() { - return !viewComposite.isInternallyAligned(); + return !viewComposite.isPackingEnabled(); } public void createInternalStructure(TaskMonitor monitor) @@ -1259,7 +1216,7 @@ class StructureEditorModel extends CompEditorModel { final StructureDataType structureDataType = new StructureDataType(originalCategoryPath, uniqueName, length, originalDTM); -// if (isAligned()) { +// if (isPackingEnabled()) { // structureDataType.setPackingValue(getPackingValue()); // } @@ -1281,7 +1238,7 @@ class StructureEditorModel extends CompEditorModel { length += compLength; - if (!structureDataType.isInternallyAligned() && component.isBitFieldComponent()) { + if (!structureDataType.isPackingEnabled() && component.isBitFieldComponent()) { BitFieldDataType bitfield = (BitFieldDataType) dt; structureDataType.insertBitFieldAt(component.getOffset() - firstDtc.getOffset(), compLength, bitfield.getBitOffset(), bitfield.getBaseDataType(), @@ -1296,8 +1253,8 @@ class StructureEditorModel extends CompEditorModel { lastDtc = component; } DataType addedDataType = createDataTypeInOriginalDTM(structureDataType); - if (viewComposite.isInternallyAligned()) { - deleteSelectedComponents(monitor); + if (viewComposite.isPackingEnabled()) { + deleteSelectedComponents(); insert(minRow, addedDataType, addedDataType.getLength()); } else { @@ -1434,7 +1391,7 @@ class StructureEditorModel extends CompEditorModel { DataTypeComponent dtc = struct.getComponent(i); DataType dt = dtc.getDataType(); int compLength = dtc.getLength(); - if (!isAligned()) { + if (!isPackingEnabled()) { if (dtc.isBitFieldComponent()) { BitFieldDataType bitfield = (BitFieldDataType) dt; viewStruct.insertBitFieldAt(currentOffset + dtc.getOffset(), compLength, diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorModel.java index 93366c7c03..3e5a8420e1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/UnionEditorModel.java @@ -40,7 +40,8 @@ import docking.widgets.fieldpanel.support.FieldSelection; import ghidra.program.model.data.*; import ghidra.program.model.lang.InsufficientBytesException; -import ghidra.util.exception.*; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.UsrException; import ghidra.util.task.TaskMonitor; class UnionEditorModel extends CompEditorModel { @@ -502,16 +503,6 @@ class UnionEditorModel extends CompEditorModel { } } - @Override - public void setAlignment(int minAlignment) throws InvalidInputException { - long currentViewAlignment = viewComposite.getMinimumAlignment(); - if (currentViewAlignment == minAlignment) { - return; - } - viewComposite.setMinimumAlignment(minAlignment); - notifyCompositeChanged(); - } - /** * Returns the number of undefined bytes that are available in the structure * beginning at the specified row index. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSynchronizer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSynchronizer.java index 7971464994..30bf283847 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSynchronizer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSynchronizer.java @@ -494,7 +494,6 @@ public class DataTypeSynchronizer { dataType.setLastChangeTimeInSourceArchive(0); // Set timestamp so user must re-sync. fixedSync = true; - dataTypeManager.dataTypeChanged(dataType); } } if (fixedSync) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index 8919c69140..d526bbb203 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -152,10 +152,11 @@ public class DataTypesProvider extends ComponentProviderAdapter { addLocalAction(new DeleteArchiveAction(plugin)); addLocalAction(new RenameAction(plugin)); addLocalAction(new EditAction(plugin)); - addLocalAction(new AlignDataTypeAction(plugin)); + // NOTE: it make very little sense to blindly enable packing +// addLocalAction(new PackDataTypeAction(plugin)); // addLocalAction( new PackDataTypeAction( plugin )); // addLocalAction( new PackSizeDataTypeAction( plugin )); - addLocalAction(new AlignAllDataTypesAction(plugin)); +// addLocalAction(new PackAllDataTypesAction(plugin)); // addLocalAction( new DefineDataTypeAlignmentAction( plugin )); addLocalAction(new CreateEnumFromSelectionAction(plugin)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/AlignDataTypeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/Pack1DataTypeAction.java similarity index 51% rename from Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/AlignDataTypeAction.java rename to Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/Pack1DataTypeAction.java index 88578c0dcd..def536c39c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/AlignDataTypeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/Pack1DataTypeAction.java @@ -25,97 +25,62 @@ import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.tree.DataTypeNode; import ghidra.app.plugin.core.datamgr.tree.DataTypeTreeNode; import ghidra.program.model.data.*; -import ghidra.util.HelpLocation; import ghidra.util.Msg; -public class AlignDataTypeAction extends DockingAction { +public class Pack1DataTypeAction extends DockingAction { + private DataTypeManagerPlugin plugin; - public AlignDataTypeAction(DataTypeManagerPlugin plugin) { - super("Align Data Type", plugin.getName()); - setPopupMenuData(new MenuData(new String[] { "Align" }, "Edit")); - setHelpLocation(new HelpLocation(plugin.getName(), getName())); - } - - @Override - public boolean isAddToPopup(ActionContext context) { - DataTypeNode node = getSelectedDataTypeNode(context); - if (node == null) { - return false; - } - DataType dataType = node.getDataType(); - if (dataType instanceof BuiltInDataType || dataType instanceof Pointer || - dataType instanceof MissingBuiltInDataType) { - return false; - } - if (!node.isModifiable()) { - return false; - } - return true; + public Pack1DataTypeAction(DataTypeManagerPlugin plugin) { + super("Pack1 Data Type", plugin.getName()); + this.plugin = plugin; + setPopupMenuData(new MenuData(new String[] { "Pack (1)" }, "Edit")); } @Override public boolean isEnabledForContext(ActionContext context) { - DataTypeNode node = getSelectedDataTypeNode(context); - if (node == null) { - return false; - } - DataType dataType = node.getDataType(); - if (dataType instanceof Composite) { - return !((Composite) dataType).isInternallyAligned(); - } - return false; - } - - private DataTypeNode getSelectedDataTypeNode(ActionContext context) { Object contextObject = context.getContextObject(); if (!(contextObject instanceof GTree)) { - return null; + return false; } GTree gTree = (GTree) contextObject; TreePath[] selectionPaths = gTree.getSelectionPaths(); if (selectionPaths.length != 1) { - return null; + return false; } DataTypeTreeNode node = (DataTypeTreeNode) selectionPaths[0].getLastPathComponent(); if (!(node instanceof DataTypeNode)) { - return null; + return false; } - return (DataTypeNode) node; + setEnabled(node.isModifiable()); + return true; } @Override public void actionPerformed(ActionContext context) { GTree gTree = (GTree) context.getContextObject(); TreePath[] selectionPaths = gTree.getSelectionPaths(); - for (TreePath treePath : selectionPaths) { - final DataTypeNode dataTypeNode = (DataTypeNode) treePath.getLastPathComponent(); - DataType dataType = dataTypeNode.getDataType(); - DataTypeManager dataTypeManager = dataType.getDataTypeManager(); - DataOrganization dataOrganization = dataTypeManager.getDataOrganization(); - alignDataType(dataType, dataOrganization); + if (selectionPaths.length != 1) { + Msg.error(this, "Pack is only allowed on an individual data type."); + return; } - } - - private void alignDataType(DataType dataType, DataOrganization dataOrganization) { + TreePath treePath = selectionPaths[0]; + final DataTypeNode dataTypeNode = (DataTypeNode) treePath.getLastPathComponent(); + DataType dataType = dataTypeNode.getDataType(); DataTypeManager dataTypeManager = dataType.getDataTypeManager(); if (dataTypeManager == null) { - Msg.error(this, "Can't align data type " + dataType.getName() + - " without a data type manager."); - return; - } - if (!(dataType instanceof Structure)) { - Msg.error(this, "Can't align data type " + dataType.getName() + - ". It's not a structure."); + Msg.error(this, + "Can't pack data type " + dataType.getName() + " without a data type manager."); return; } + int transactionID = -1; boolean commit = false; try { // start a transaction - transactionID = dataTypeManager.startTransaction("align " + dataType.getName()); - ((Structure) dataType).setInternallyAligned(true); + transactionID = dataTypeManager.startTransaction("pack of " + dataType.getName()); + packDataType(dataType); commit = true; } finally { @@ -124,4 +89,13 @@ public class AlignDataTypeAction extends DockingAction { } } + private void packDataType(DataType dataType) { + if (!(dataType instanceof Composite)) { + Msg.error(this, + "Can't pack data type " + dataType.getName() + ". It's not a composite."); + return; + } + ((Composite) dataType).pack(1); + } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/AlignAllDataTypesAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackAllDataTypesAction.java similarity index 72% rename from Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/AlignAllDataTypesAction.java rename to Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackAllDataTypesAction.java index 8abbd3163f..de63eb7293 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/AlignAllDataTypesAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackAllDataTypesAction.java @@ -29,19 +29,18 @@ import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.archive.Archive; import ghidra.app.plugin.core.datamgr.tree.*; import ghidra.program.model.data.*; -import ghidra.util.HelpLocation; import ghidra.util.Msg; -public class AlignAllDataTypesAction extends DockingAction { +public class PackAllDataTypesAction extends DockingAction { private DataTypeManagerPlugin plugin; - public AlignAllDataTypesAction(DataTypeManagerPlugin plugin) { - super("Align All Data Types", plugin.getName()); + public PackAllDataTypesAction(DataTypeManagerPlugin plugin) { + super("Pack All Composites", plugin.getName()); this.plugin = plugin; - setPopupMenuData(new MenuData(new String[] { "Align All..." }, "Edit")); - setHelpLocation(new HelpLocation(plugin.getName(), getName())); + setPopupMenuData(new MenuData(new String[] { "Pack All..." }, "Edit")); +// setHelpLocation(new HelpLocation(plugin.getName(), getName())); } @Override @@ -85,27 +84,27 @@ public class AlignAllDataTypesAction extends DockingAction { int result = OptionDialog.showOptionDialog( plugin.getTool().getToolFrame(), - "Align Data Types", - "Are you sure you want to align all of the data types in " + + "Pack All Composites", + "Are you sure you want to enable packing of all non-packed composites in " + dataTypeManager.getName() + - "?\nBoth structures and unions that are currently unaligned will become aligned.\n" + - "This could cause component offsets to change and datatype sizes to change.\n" + + "?\nAll structures and unions that are not currently packed will default packing enabled.\n" + + "This could cause component offsets to change as well as size and alignment of these data types to change.\n" + "Do you want to continue?", "Continue", OptionDialog.WARNING_MESSAGE); if (result == OptionDialog.CANCEL_OPTION) { return; } - alignDataTypes(dataTypeManager, dataOrganization); + packDataTypes(dataTypeManager, dataOrganization); } else { - Msg.showWarn(this, gTree, "Alignment Not Allowed", - "The archive must be modifiable to align data types."); + Msg.showWarn(this, gTree, "Modification Not Allowed", + "The archive must be modifiable to pack data types."); } } } - private void alignDataTypes(DataTypeManager dataTypeManager, DataOrganization dataOrganization) { + private void packDataTypes(DataTypeManager dataTypeManager, DataOrganization dataOrganization) { if (dataTypeManager == null) { - Msg.error(this, "Can't align data types without a data type manager."); + Msg.error(this, "Can't pack data types without a data type manager."); return; } int transactionID = -1; @@ -113,9 +112,8 @@ public class AlignAllDataTypesAction extends DockingAction { try { // start a transaction transactionID = - dataTypeManager.startTransaction("Align all data types in " + - dataTypeManager.getName()); - alignEachStructure(dataTypeManager, dataOrganization); + dataTypeManager.startTransaction("Pack Composite Types"); + packEachStructure(dataTypeManager, dataOrganization); commit = true; } finally { @@ -124,12 +122,14 @@ public class AlignAllDataTypesAction extends DockingAction { } } - private void alignEachStructure(DataTypeManager dataTypeManager, + private void packEachStructure(DataTypeManager dataTypeManager, DataOrganization dataOrganization) { Iterator allComposites = dataTypeManager.getAllComposites(); while (allComposites.hasNext()) { Composite composite = allComposites.next(); - composite.setInternallyAligned(true); + if (!composite.isPackingEnabled()) { + composite.setPackingEnabled(true); + } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackDataTypeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackDataTypeAction.java index 9c08a29697..ec93f82c93 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackDataTypeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackDataTypeAction.java @@ -26,81 +26,101 @@ import ghidra.app.plugin.core.datamgr.tree.DataTypeNode; import ghidra.app.plugin.core.datamgr.tree.DataTypeTreeNode; import ghidra.program.model.data.*; import ghidra.util.Msg; -import ghidra.util.exception.InvalidInputException; public class PackDataTypeAction extends DockingAction { - private DataTypeManagerPlugin plugin; public PackDataTypeAction(DataTypeManagerPlugin plugin) { super("Pack Data Type", plugin.getName()); - this.plugin = plugin; - setPopupMenuData(new MenuData(new String[] { "Pack" }, "Edit")); + setPopupMenuData(new MenuData(new String[] { "Pack (default)" }, "Edit")); +// setHelpLocation(new HelpLocation(plugin.getName(), getName())); + } + + @Override + public boolean isAddToPopup(ActionContext context) { + DataTypeNode node = getSelectedDataTypeNode(context); + if (node == null) { + return false; + } + DataType dataType = node.getDataType(); + if (dataType instanceof BuiltInDataType || dataType instanceof Pointer || + dataType instanceof MissingBuiltInDataType) { + return false; + } + if (!node.isModifiable()) { + return false; + } + return true; } @Override public boolean isEnabledForContext(ActionContext context) { + DataTypeNode node = getSelectedDataTypeNode(context); + if (node == null) { + return false; + } + DataType dataType = node.getDataType(); + if (dataType instanceof Composite) { + return !((Composite) dataType).isPackingEnabled(); + } + return false; + } + + private DataTypeNode getSelectedDataTypeNode(ActionContext context) { Object contextObject = context.getContextObject(); if (!(contextObject instanceof GTree)) { - return false; + return null; } GTree gTree = (GTree) contextObject; TreePath[] selectionPaths = gTree.getSelectionPaths(); if (selectionPaths.length != 1) { - return false; + return null; } DataTypeTreeNode node = (DataTypeTreeNode) selectionPaths[0].getLastPathComponent(); if (!(node instanceof DataTypeNode)) { - return false; + return null; } - setEnabled(node.isModifiable()); - return true; + return (DataTypeNode) node; } @Override public void actionPerformed(ActionContext context) { GTree gTree = (GTree) context.getContextObject(); TreePath[] selectionPaths = gTree.getSelectionPaths(); - if (selectionPaths.length != 1) { - Msg.error(this, "Pack is only allowed on an individual data type."); - return; + for (TreePath treePath : selectionPaths) { + final DataTypeNode dataTypeNode = (DataTypeNode) treePath.getLastPathComponent(); + DataType dataType = dataTypeNode.getDataType(); + DataTypeManager dataTypeManager = dataType.getDataTypeManager(); + DataOrganization dataOrganization = dataTypeManager.getDataOrganization(); + alignDataType(dataType, dataOrganization); } - TreePath treePath = selectionPaths[0]; - final DataTypeNode dataTypeNode = (DataTypeNode) treePath.getLastPathComponent(); - DataType dataType = dataTypeNode.getDataType(); + } + + private void alignDataType(DataType dataType, DataOrganization dataOrganization) { DataTypeManager dataTypeManager = dataType.getDataTypeManager(); if (dataTypeManager == null) { - Msg.error(this, - "Can't pack data type " + dataType.getName() + " without a data type manager."); + Msg.error(this, "Can't align data type " + dataType.getName() + + " without a data type manager."); + return; + } + if (!(dataType instanceof Structure)) { + Msg.error(this, "Can't align data type " + dataType.getName() + + ". It's not a structure."); return; } - int transactionID = -1; boolean commit = false; try { // start a transaction - transactionID = dataTypeManager.startTransaction("pack of " + dataType.getName()); - packDataType(dataType); + transactionID = dataTypeManager.startTransaction("align " + dataType.getName()); + ((Structure) dataType).setPackingEnabled(true); commit = true; } - catch (InvalidInputException iie) { - // TODO Auto-generated catch block - iie.printStackTrace(); - } finally { // commit the changes dataTypeManager.endTransaction(transactionID, commit); } } - private void packDataType(DataType dataType) throws InvalidInputException { - if (!(dataType instanceof Structure)) { - Msg.error(this, - "Can't pack data type " + dataType.getName() + ". It's not a structure."); - return; - } - ((Structure) dataType).pack(1); - } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackSizeDataTypeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackSizeDataTypeAction.java index 78a0a0c99a..ee538ddb98 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackSizeDataTypeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/PackSizeDataTypeAction.java @@ -27,7 +27,6 @@ import ghidra.app.plugin.core.datamgr.tree.DataTypeNode; import ghidra.app.plugin.core.datamgr.tree.DataTypeTreeNode; import ghidra.program.model.data.*; import ghidra.util.Msg; -import ghidra.util.exception.InvalidInputException; public class PackSizeDataTypeAction extends DockingAction { @@ -73,7 +72,8 @@ public class PackSizeDataTypeAction extends DockingAction { return; } - NumberInputDialog numberInputDialog = new NumberInputDialog("pack alignment", 0, 0, 16); + NumberInputDialog numberInputDialog = + new NumberInputDialog("explicit pack value", 0, 0, 16); if (!numberInputDialog.show()) { return; } @@ -88,9 +88,8 @@ public class PackSizeDataTypeAction extends DockingAction { packDataType(dataType, packSize); commit = true; } - catch (InvalidInputException iie) { - // TODO Auto-generated catch block - iie.printStackTrace(); + catch (IllegalArgumentException iie) { + Msg.showError(this, null, "Invalid Pack Value", iie.getMessage()); } finally { // commit the changes @@ -98,13 +97,13 @@ public class PackSizeDataTypeAction extends DockingAction { } } - private void packDataType(DataType dataType, int packSize) throws InvalidInputException { - if (!(dataType instanceof Structure)) { + private void packDataType(DataType dataType, int packSize) throws IllegalArgumentException { + if (!(dataType instanceof Composite)) { Msg.error(this, - "Can't pack data type " + dataType.getName() + ". It's not a structure."); + "Can't pack data type " + dataType.getName() + ". It's not a composite."); return; } - ((Structure) dataType).pack(packSize); + ((Composite) dataType).pack(packSize); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/DataTypeEditorManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/DataTypeEditorManager.java index e52ef5cd58..308657c440 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/DataTypeEditorManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/editor/DataTypeEditorManager.java @@ -463,25 +463,25 @@ public class DataTypeEditorManager return editorOptionMgr.showUnionNumbersInHex(); } - public void createNewStructure(Category category, boolean isInternallyAligned) { + public void createNewStructure(Category category, boolean isPacked) { String newName = getUniqueName(category, "struct"); DataTypeManager dataTypeManager = category.getDataTypeManager(); SourceArchive sourceArchive = dataTypeManager.getLocalSourceArchive(); StructureDataType structureDataType = new StructureDataType(category.getCategoryPath(), newName, 0, dataTypeManager); structureDataType.setSourceArchive(sourceArchive); - structureDataType.setInternallyAligned(isInternallyAligned); + structureDataType.setPackingEnabled(isPacked); edit(structureDataType); } - public void createNewUnion(Category category, boolean isInternallyAligned) { + public void createNewUnion(Category category, boolean isPacked) { String newName = getUniqueName(category, "union"); DataTypeManager dataTypeManager = category.getDataTypeManager(); SourceArchive sourceArchive = dataTypeManager.getLocalSourceArchive(); UnionDataType unionDataType = new UnionDataType(category.getCategoryPath(), newName, dataTypeManager); unionDataType.setSourceArchive(sourceArchive); - unionDataType.setInternallyAligned(isInternallyAligned); + unionDataType.setPackingEnabled(isPacked); edit(unionDataType); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java index 2c51239153..a9f2a5df0f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPlugin.java @@ -101,7 +101,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin { model = new DTPPTableModel(); table = new DTPPTable(model); component = new DTPPScrollPane(table); - dataTypeManager = new LayeredDataTypeManager(); + dataTypeManager = new LayeredDataTypeManager(activeProgram); addDataType(new ByteDataType()); addDataType(new WordDataType()); @@ -177,27 +177,29 @@ public class DataTypePreviewPlugin extends ProgramPlugin { private void updateModel() { + LayeredDataTypeManager newDtm = new LayeredDataTypeManager(activeProgram); + + int transactionId = newDtm.startTransaction("add datatypes"); + try { + Iterator allDataTypes = dataTypeManager.getAllDataTypes(); + while (allDataTypes.hasNext()) { + newDtm.resolve(allDataTypes.next(), null); + } + } + finally { + newDtm.endTransaction(transactionId, true); + } + // NOTE: data types do not respond to switching the data organization object // since this is cached internal to the data type at time of construction. // We must purge old datatypes and have them re-instantiated by the // datatype manager List dtPaths = getModelDataTypePaths(); model.removeAll(); - dataTypeManager.invalidate(); - int transactionId = dataTypeManager.startTransaction("realign"); - try { - Iterator allComposites = dataTypeManager.getAllComposites(); - while (allComposites.hasNext()) { - Composite composite = allComposites.next(); - if (composite.isInternallyAligned()) { - composite.realign(); - } - } - } - finally { - dataTypeManager.endTransaction(transactionId, true); - } + LayeredDataTypeManager oldDtm = dataTypeManager; + dataTypeManager = newDtm; + oldDtm.close(); for (DataTypePath dtPath : dtPaths) { DataType dataType = dataTypeManager.getDataType(dtPath); @@ -538,14 +540,11 @@ public class DataTypePreviewPlugin extends ProgramPlugin { } private void add(Composite c, DataTypeComponentPreview parent) { - DataTypeComponent[] comps = c.getComponents(); + DataTypeComponent[] comps = c.getDefinedComponents(); for (DataTypeComponent element : comps) { DataTypeComponentPreview preview = new DataTypeComponentPreview(c, element); preview.setParent(parent); DataType dataType = element.getDataType(); - if (dataType == DataType.DEFAULT) { - continue; - } if (dataType instanceof Composite) { add((Composite) element.getDataType(), preview); } @@ -714,21 +713,22 @@ public class DataTypePreviewPlugin extends ProgramPlugin { private class LayeredDataTypeManager extends StandAloneDataTypeManager { - public LayeredDataTypeManager() { + DataOrganization layeredDataOrganization1; + + public LayeredDataTypeManager(Program program) { super("DataTypePreviewer"); + this.layeredDataOrganization1 = + program != null ? program.getDataTypeManager().getDataOrganization() : null; } @Override public DataOrganization getDataOrganization() { - if (currentProgram != null) { - return currentProgram.getDataTypeManager().getDataOrganization(); + if (layeredDataOrganization1 == null) { + return super.getDataOrganization(); } - return super.getDataOrganization(); - } - - void invalidate() { - invalidateCache(); + return layeredDataOrganization1; } } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/BiDirectionDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/BiDirectionDataType.java index 171bf11bb0..54e5b525c3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/BiDirectionDataType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/BiDirectionDataType.java @@ -15,8 +15,9 @@ */ package ghidra.app.plugin.core.stackeditor; -import java.util.Collections; -import java.util.Comparator; +import java.util.*; + +import javax.help.UnsupportedOperationException; import ghidra.program.model.data.*; import ghidra.util.exception.AssertException; @@ -54,6 +55,49 @@ public abstract class BiDirectionDataType extends StructureDataType this.splitOffset = splitOffset; } + @Override + public int getAlignment() { + throw new UnsupportedOperationException( + "BiDirectionDataType.getAlignment() not implemented."); + } + + @Override + public boolean repack(boolean notify) { + throw new AssertException(); + } + + @Override + public void setToDefaultAligned() { + // ignore + } + + @Override + public void setToMachineAligned() { + // ignore + } + + @Override + public void setPackingEnabled(boolean aligned) { + // ignore + } + + @Override + public void setExplicitPackingValue(int packingValue) { + // ignore + } + + @Override + public void setExplicitMinimumAlignment(int minimumAlignment) { + // ignore + } + + @Override + public DataTypeComponent setFlexibleArrayComponent(DataType flexType, String name, + String comment) { + throw new UnsupportedOperationException( + "BiDirectionDataType.setFlexibleArrayComponent() not implemented."); + } + protected DataTypeComponent getDefinedComponentAt(int offset) { if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) { return null; @@ -108,20 +152,15 @@ public abstract class BiDirectionDataType extends StructureDataType return positiveLength; } - @Override - public int getLength() { - return structLength; - } - @Override public void delete(int index) { if (index < 0 || index >= numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + throw new IndexOutOfBoundsException(index); } DataTypeComponent comp = getComponent(index); int offset = comp.getOffset(); int length = comp.getLength(); - int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator); + int idx = Collections.binarySearch(components, index, ordinalComparator); if (idx >= 0) { DataTypeComponent dtc = components.remove(idx); dtc.getDataType().removeParent(this); @@ -137,7 +176,7 @@ public abstract class BiDirectionDataType extends StructureDataType } @Override - public void delete(int[] ordinals) { + public void delete(Set ordinals) { for (int ordinal : ordinals) { delete(ordinal); } @@ -173,6 +212,7 @@ public abstract class BiDirectionDataType extends StructureDataType } } structLength += deltaLength; +// nonpackedAlignedStructLength = -1; } /* @@ -198,7 +238,7 @@ public abstract class BiDirectionDataType extends StructureDataType protected DataTypeComponent getDefinedComponent(int ordinal) { if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); if (idx >= 0) { @@ -210,7 +250,7 @@ public abstract class BiDirectionDataType extends StructureDataType @Override public DataTypeComponent getComponent(int ordinal) { if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); if (idx >= 0) { @@ -255,12 +295,14 @@ public abstract class BiDirectionDataType extends StructureDataType numComponents += deltaLength; positiveLength += deltaLength; structLength += deltaLength; +// nonpackedAlignedStructLength = -1; } if (nextOffset < splitOffset - negativeLength) { int deltaLength = splitOffset - nextOffset - negativeLength; numComponents += deltaLength; negativeLength += deltaLength; structLength += deltaLength; +// nonpackedAlignedStructLength = -1; } checkAncestry(dataType); dataType = dataType.clone(getDataTypeManager()); @@ -319,6 +361,7 @@ public abstract class BiDirectionDataType extends StructureDataType numComponents++; positiveLength += length; structLength += length; +// nonpackedAlignedStructLength = -1; notifySizeChanged(); return dtc; } @@ -341,6 +384,7 @@ public abstract class BiDirectionDataType extends StructureDataType numComponents++; negativeLength += length; structLength += length; +// nonpackedAlignedStructLength = -1; notifySizeChanged(); return dtc; } @@ -367,39 +411,14 @@ public abstract class BiDirectionDataType extends StructureDataType } numComponents += absAmount; structLength += absAmount; +// nonpackedAlignedStructLength = -1; notifySizeChanged(); } @Override public DataTypeComponent insert(int index, DataType dataType, int length, String newName, String comment) { - throw new AssertException("BiDirectionDataType.insert() not implemented."); -// if (index < 0 || index > numComponents) { -// throw new ArrayIndexOutOfBoundsException(index); -// } -// if (index == numComponents) { -// return add(dataType, length, newName, comment); -// } -// validateDataType(dataType); -// -// dataType = resolve(dataType); -// checkAncestry(dataType); -// -// int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator); -// if (idx < 0) { -// idx = -idx -1; -// } -// if (dataType == DataType.DEFAULT) { -// shiftOffsets(idx, 1, 1); -// return getComponent(index); -// } -// int offset = ((DataTypeComponent)getComponent(index)).getOffset(); -// DataTypeComponent dtc = new DataTypeComponentImpl(dataType,this, length,index, -// offset, newName, comment); -// shiftOffsets(idx, 1, dtc.getLength()); -// components.add(idx, dtc); -// sizeChanged(); -// return dtc; + throw new UnsupportedOperationException("BiDirectionDataType.insert() not implemented."); } protected void insertAtOffset(int offset, int numBytes) { @@ -441,6 +460,7 @@ public abstract class BiDirectionDataType extends StructureDataType } numComponents += numBytes; structLength += numBytes; +// nonpackedAlignedStructLength = -1; notifySizeChanged(); } @@ -479,7 +499,7 @@ public abstract class BiDirectionDataType extends StructureDataType if ((splitOffset != biDir.getSplitOffset()) || (negativeLength != biDir.getNegativeLength()) || (positiveLength != biDir.getPositiveLength()) || - (structLength != biDir.getLength())) { + (getLength() != biDir.getLength())) { return false; } DataTypeComponent[] myComps = getDefinedComponents(); @@ -499,72 +519,13 @@ public abstract class BiDirectionDataType extends StructureDataType @Override public void dataTypeSizeChanged(DataType dt) { - throw new AssertException("BiDirectionDataType.dataTypeSizeChanged() not implemented."); -// int n = components.size(); -// boolean didChange = false; -// for(int i=0;i dtcLen) { -// int consumed = consumeBytesAfter(i, dtLen-dtcLen); -// if (consumed > 0) { -// shiftOffsets(i+1, 0-consumed, 0); -// didChange = true; -// } -// } -// } -// } -// if (didChange & dtMgr != null) { -// dtMgr.dataTypeChanged(this); -// } + // ignore } - /** - * - * @param index the index of the defined component that is consuming the bytes. - * @param numBytes the number of undefined bytes to consume - * @return the number of bytes actually consumed - */ -// private int consumeBytesAfter(int index, int numBytes) { -// throw new AssertException("BiDirectionDataType.consumeBytesAfter() not implemented."); -// DataTypeComponentImpl thisDtc = (DataTypeComponentImpl)components.get(index); -// int thisLen = thisDtc.getLength(); -// int nextOffset = thisDtc.getOffset()+thisLen; -// int available = structLength-nextOffset; -// if (index+1 < components.size()) { -// DataTypeComponent nextDtc = (DataTypeComponent)components.get(index+1); -// available = nextDtc.getOffset() - nextOffset; -// } -// else { -// available = structLength-nextOffset; -// } -// if (numBytes <= available) { -// thisDtc.setLength(thisLen + numBytes); -// return numBytes; -// } -// else { -// thisDtc.setLength(thisLen + available); -// return available; -// } -// } - -// private boolean hasRoom(int index, int offset, int length) { -// if (offset+length > this.positiveLength) { -// return false; -// } -// if (index+1 < components.size()) { -// DataTypeComponent nextDtc = (DataTypeComponent)components.get(index+1); -// return offset+length <= nextDtc.getOffset(); -// } -// return true; -// } + @Override + public void dataTypeAlignmentChanged(DataType dt) { + // ignore + } @Override public abstract BiDirectionDataType clone(DataTypeManager dtm); @@ -572,7 +533,7 @@ public abstract class BiDirectionDataType extends StructureDataType @Override public void clearComponent(int index) { if (index < 0 || index >= numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + throw new IndexOutOfBoundsException(index); } int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator); if (idx >= 0) { @@ -589,81 +550,20 @@ public abstract class BiDirectionDataType extends StructureDataType } public void replaceWith(Structure struct) { - throw new AssertException("BiDirectionDataType.replaceWith() not implemented."); -// int oldLength = structLength; -// doReplaceWith(struct); -// if (oldLength != structLength) { -// sizeChanged(); -// } -// else if (dtMgr != null) { -// dtMgr.dataTypeChanged(this); -// } + throw new UnsupportedOperationException( + "BiDirectionDataType.replaceWith() not implemented."); } -// private void doReplaceWith(Structure struct) { -// throw new AssertException("BiDirectionDataType.doReplaceWith() not implemented."); -// components.clear(); -// structLength = struct.getLength(); -// numComponents = structLength; -// -// DataTypeComponent[] components = struct.getDefinedComponents(); -// for(int i=0;i=0;i--) { -// DataTypeComponentImpl dtc = (DataTypeComponentImpl)components.get(i); -// if (dtc.getDataType() == dt) { -// components.remove(i); -// shiftOffsets(i, dtc.getLength()-1, 0); -// didChange = true; -// } -// } -// if (didChange && dtMgr != null) { -// dtMgr.dataTypeChanged(this); -// } - + throw new UnsupportedOperationException( + "BiDirectionDataType.dataTypeDeleted() not implemented."); } @Override public void dataTypeReplaced(DataType oldDt, DataType newDt) { - throw new AssertException("BiDirectionDataType.dataTypeReplaced() not implemented."); -// int n = components.size(); -// boolean didChange = false; -// for(int i=0;i dtcLen) { -// int consumed = consumeBytesAfter(i, dtLen-dtcLen); -// if (consumed > 0) { -// shiftOffsets(i+1, 0-consumed, 0); -// didChange = true; -// } -// } -// } -// } -// if (didChange & dtMgr != null) { -// dtMgr.dataTypeChanged(this); -// } + throw new UnsupportedOperationException( + "BiDirectionDataType.dataTypeReplaced() not implemented."); } @Override @@ -682,9 +582,9 @@ public abstract class BiDirectionDataType extends StructureDataType @Override public DataTypeComponent replace(int index, DataType dataType, int length, String newName, - String comment) throws ArrayIndexOutOfBoundsException, IllegalArgumentException { + String comment) throws IndexOutOfBoundsException, IllegalArgumentException { if (index < 0 || index >= numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + throw new IndexOutOfBoundsException(index); } validateDataType(dataType); checkAncestry(dataType); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/StackFrameDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/StackFrameDataType.java index 6b102cfcdf..3b9eec09e1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/StackFrameDataType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/stackeditor/StackFrameDataType.java @@ -68,8 +68,7 @@ public class StackFrameDataType extends BiDirectionDataType { this.returnAddressOffset = stackDt.returnAddressOffset; this.stack = stackDt.stack; this.defaultSettings = stackDt.defaultSettings; - for (int i = 0; i < stackDt.components.size(); i++) { - DataTypeComponent dtc = stackDt.components.get(i); + for (DataTypeComponentImpl dtc : stackDt.components) { replaceAtOffset(dtc.getOffset(), dtc.getDataType(), dtc.getLength(), dtc.getFieldName(), dtc.getComment()); } @@ -216,7 +215,7 @@ public class StackFrameDataType extends BiDirectionDataType { * @see ghidra.program.model.listing.StackFrame#getFrameSize() */ public int getFrameSize() { - return structLength; + return getLength(); } /* (non-Javadoc) @@ -261,8 +260,9 @@ public class StackFrameDataType extends BiDirectionDataType { } private boolean adjustStackFrameSize(int newSize, int oldSize, boolean isNegative) { - if (newSize < 0) + if (newSize < 0) { return false; + } int delta = newSize - oldSize; if (delta == 0) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeConflictHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeConflictHandler.java index b3e783f8d8..753a78ecf4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeConflictHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFDataTypeConflictHandler.java @@ -82,8 +82,7 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler { * @return true if empty or default and false otherwise */ private boolean isCompositeDefault(Composite composite) { - return composite.isNotYetDefined() - || ((composite instanceof Structure) && ((Structure) composite).getNumDefinedComponents() == 0); + return composite.isNotYetDefined() || (composite.getNumDefinedComponents() == 0); } private boolean isCompositePart(Composite full, Composite part, Set visitedDataTypes) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/MSDataTypeUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/MSDataTypeUtils.java index c125ccbfb6..7b56c34661 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/MSDataTypeUtils.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/MSDataTypeUtils.java @@ -85,8 +85,10 @@ public class MSDataTypeUtils { CategoryPath categoryPath, String structureName, int packValue) { StructureDataType struct = new StructureDataType(categoryPath, structureName, 0, dataTypeManager); - struct.setInternallyAligned(true); - struct.setPackingValue(packValue); + struct.setPackingEnabled(true); + if (packValue > 0) { + struct.setExplicitPackingValue(packValue); + } return struct; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/CompositeDataTypeHTMLRepresentation.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/CompositeDataTypeHTMLRepresentation.java index 5ae0045eba..b0edc058d9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/CompositeDataTypeHTMLRepresentation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/CompositeDataTypeHTMLRepresentation.java @@ -15,7 +15,7 @@ */ package ghidra.app.util.html; -import static ghidra.util.HTMLUtilities.friendlyEncodeHTML; +import static ghidra.util.HTMLUtilities.*; import java.awt.Color; import java.util.*; @@ -77,7 +77,7 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat } protected List buildWarnings(Composite comp) { - if (!comp.isNotYetDefined()) { + if (!comp.isZeroLength()) { return Collections.emptyList(); } List list = new ArrayList<>(); @@ -87,7 +87,7 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat @Override protected TextLine buildFooterText(DataType dataType) { - if (dataType.isNotYetDefined()) { + if (dataType.isZeroLength()) { return new TextLine("0"); } return super.buildFooterText(dataType); @@ -95,44 +95,24 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat protected List buildAlignmentText(Composite dataType) { List list = new ArrayList<>(); - if (!dataType.isInternallyAligned()) { - list.add(new TextLine("unaligned")); + String alignStr = CompositeDataTypeImpl.getMinAlignmentString(dataType); + if (alignStr != null && alignStr.length() != 0) { + list.add(new TextLine(alignStr)); } - else if (dataType.isDefaultAligned()) { - list.add(new TextLine("align()")); - } - else if (dataType.isMachineAligned()) { - list.add(new TextLine("align(machine)")); - } - else { - long alignment = dataType.getMinimumAlignment(); - list.add(new TextLine("align(" + alignment + ")")); - } - TextLine packingText = buildPackingText(dataType); - if (packingText != null) { - list.add(packingText); + String packStr = CompositeDataTypeImpl.getPackingString(dataType); + if (packStr != null && packStr.length() != 0) { + list.add(new TextLine(packStr)); } return list; } - protected TextLine buildPackingText(Composite dataType) { - if (!dataType.isInternallyAligned()) { - return null; - } - long packingValue = dataType.getPackingValue(); - if (packingValue == Composite.NOT_PACKING) { - return null; - } - return new TextLine(" pack(" + packingValue + ")"); - } - protected TextLine buildAlignmentValueText(Composite composite) { return new TextLine("" + composite.getAlignment()); } private List buildContent(Composite comp) { List list = new ArrayList<>(); - if (comp.isNotYetDefined()) { + if (comp.isZeroLength()) { return list; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java index 45232d0c92..da591abaf1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java @@ -70,7 +70,7 @@ public class TypeDefDataTypeHTMLRepresentation extends HTMLDataTypeRepresentatio protected List buildWarnings() { DataType baseType = typeDef.getBaseDataType(); - if (!(baseType instanceof Composite) || !baseType.isNotYetDefined()) { + if (!(baseType instanceof Composite) || !baseType.isZeroLength()) { return Collections.emptyList(); } List list = new ArrayList<>(); @@ -81,7 +81,7 @@ public class TypeDefDataTypeHTMLRepresentation extends HTMLDataTypeRepresentatio @Override protected TextLine buildFooterText(DataType dataType) { - if (dataType.isNotYetDefined()) { + if (dataType.isZeroLength()) { return new TextLine("0"); } return super.buildFooterText(dataType); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BytesFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BytesFieldFactory.java index 54736f7baa..7792221b03 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BytesFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BytesFieldFactory.java @@ -292,7 +292,7 @@ public class BytesFieldFactory extends FieldFactory { return null; // e.g., union } Structure struct = (Structure) baseDataType; - if (!struct.isInternallyAligned()) { + if (!struct.isPackingEnabled()) { return null; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java index 6e158a6c16..f541e4bf45 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java @@ -623,7 +623,7 @@ public class DataTypesXmlMgr { XmlAttributes attrs = new XmlAttributes(); attrs.addAttribute("NAME", struct.getDisplayName()); attrs.addAttribute("NAMESPACE", struct.getCategoryPath().getPath()); - attrs.addAttribute("SIZE", struct.isNotYetDefined() ? 0 : struct.getLength(), true); + attrs.addAttribute("SIZE", struct.isZeroLength() ? 0 : struct.getLength(), true); writer.startElement("STRUCTURE", attrs); writeRegularComment(writer, struct.getDescription()); DataTypeComponent[] members = struct.getComponents(); @@ -637,7 +637,7 @@ public class DataTypesXmlMgr { XmlAttributes attrs = new XmlAttributes(); attrs.addAttribute("NAME", union.getDisplayName()); attrs.addAttribute("NAMESPACE", union.getCategoryPath().getPath()); - attrs.addAttribute("SIZE", union.isNotYetDefined() ? 0 : union.getLength(), true); + attrs.addAttribute("SIZE", union.isZeroLength() ? 0 : union.getLength(), true); writer.startElement("UNION", attrs); writeRegularComment(writer, union.getDescription()); DataTypeComponent[] members = union.getComponents(); @@ -649,7 +649,7 @@ public class DataTypesXmlMgr { private void writerMember(XmlWriter writer, DataTypeComponent member) { XmlAttributes attrs = new XmlAttributes(); - // TODO: how should we output bitfields (aligned/unaligned) and flex array + // TODO: how should we output bitfields (packed/non-packed) and flex array attrs.addAttribute("OFFSET", member.getOffset(), true); attrs.addAttribute("DATATYPE", member.getDataType().getDisplayName()); attrs.addAttribute("DATATYPE_NAMESPACE", member.getDataType().getCategoryPath().getPath()); diff --git a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj index d11b7a3c90..dd583c69e0 100644 --- a/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj +++ b/Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj @@ -1675,17 +1675,25 @@ Composite StructOrUnion() : {Composite comp;} ( ( DeclSpec() )* { comp = new StructureDataType(ANONYMOUS_STRUCT_PREFIX + cnt++, 0); - // Always set the packing, because by default structures should be aligned - // setting 0 turns off packing, but sets structures to be aligned - comp.setPackingValue(this.packSize); + // Always set the packing, because by default structures should be aligned + if (packSize > 0) { + comp.setExplicitPackingValue(packSize); + } + else { + comp.setPackingEnabled(true); // ensure default packing enabled + } } | ( DeclSpec() )* { comp = new UnionDataType(ANONYMOUS_UNION_PREFIX + cnt++); // Always set the packing, because by default structures should be aligned - // setting 0 turns off packing, but sets structures to be aligned. - comp.setPackingValue(this.packSize); + if (packSize > 0) { + comp.setExplicitPackingValue(packSize); + } + else { + comp.setPackingEnabled(true); // ensure default packing enabled + } } ) { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java index 78ea69269c..d97a996841 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java @@ -604,7 +604,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { executeMerge(); - chooseOption(DataTypeMergeManager.OPTION_MY);// choose My Bar + chooseOption(DataTypeMergeManager.OPTION_MY);// choose My Bar // TODO: I see no reason for a conflict ! setErrorsExpected(true); @@ -2201,7 +2201,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); //@formatter:off assertEquals("/Category1/Category2/CoolUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union CoolUnion {\n" + " 0 qword 8 null \"\"\n" + " 0 byte:4(4) 1 BF1 \"my bf1\"\n" + diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge4Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge4Test.java index 3241043768..5c63251269 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge4Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge4Test.java @@ -27,7 +27,7 @@ import ghidra.program.database.ProgramModifierListener; import ghidra.program.model.data.*; import ghidra.util.InvalidNameException; import ghidra.util.exception.DuplicateNameException; -import ghidra.util.task.TaskMonitorAdapter; +import ghidra.util.task.TaskMonitor; /** * More data type merge tests. @@ -502,7 +502,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { int transactionID = program.startTransaction("test"); Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo"); try { - dtm.remove(foo, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(foo, TaskMonitor.DUMMY); commit = true; } finally { @@ -709,7 +709,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { // delete Bar from Foo fs.delete(3); // add Foo to Bar - dtm.remove(bs, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bs, TaskMonitor.DUMMY); // Add s1, s2, s3 Structure s1 = new StructureDataType(new CategoryPath("/MISC"), "S1", 0); @@ -809,7 +809,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { // delete Bar from Foo foo.delete(3); // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); // Add s1, s2, s3 Structure s1 = new StructureDataType(new CategoryPath("/MISC"), "S1", 0); @@ -920,7 +920,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { // delete Bar from Foo fs.delete(3); // remove Bar from the data type manager - dtm.remove(bs, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bs, TaskMonitor.DUMMY); // Add s1, s2, s3 Structure s1 = new StructureDataType(new CategoryPath("/MISC"), "S1", 0); @@ -1034,7 +1034,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure fs = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo"); try { // delete Foo from the data type manager - dtm.remove(fs, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(fs, TaskMonitor.DUMMY); commit = true; } finally { @@ -1051,7 +1051,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // delete Foo from the data type manager - dtm.remove(foo, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(foo, TaskMonitor.DUMMY); // Add s1, s2, s3 Structure s1 = new StructureDataType(new CategoryPath("/MISC"), "S1", 0); @@ -1129,7 +1129,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure fs = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo"); try { // delete Foo from the data type manager - dtm.remove(fs, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(fs, TaskMonitor.DUMMY); commit = true; } finally { @@ -1146,7 +1146,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // delete Foo from the data type manager - dtm.remove(foo, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(foo, TaskMonitor.DUMMY); // Add s1, s2, s3 Structure s1 = new StructureDataType(new CategoryPath("/MISC"), "S1", 0); @@ -1318,7 +1318,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { @@ -1441,7 +1441,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { @@ -1555,7 +1555,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { @@ -1643,7 +1643,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { @@ -1750,7 +1750,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { @@ -1844,7 +1844,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { @@ -1943,7 +1943,7 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest { Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); try { // remove Bar from the data type manager - dtm.remove(bar, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(bar, TaskMonitor.DUMMY); commit = true; } finally { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge6Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge6Test.java index 5182291665..88636dc157 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge6Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge6Test.java @@ -21,7 +21,7 @@ import org.junit.Test; import ghidra.program.database.*; import ghidra.program.model.data.*; -import ghidra.util.task.TaskMonitorAdapter; +import ghidra.util.task.TaskMonitor; /** * Data type merge tests for aligned data types. @@ -31,9 +31,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructureMachineAlignedVsValue() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -45,7 +43,8 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - s.setInternallyAligned(true); + s.setToDefaultPacking(); + // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); @@ -60,9 +59,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -72,7 +68,8 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setToMachineAlignment(); + s.setToMachineAligned(); + // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); @@ -87,9 +84,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -99,7 +93,8 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setMinimumAlignment(4); + s.setExplicitMinimumAlignment(4); + // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); @@ -129,11 +124,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3")); Structure s = (Structure) c.getDataType("IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(false, s.isDefaultAligned()); - assertEquals(true, s.isMachineAligned()); - assertEquals(8, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isMachineAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -155,11 +148,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3")); Structure s = (Structure) c.getDataType("IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(false, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(4, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.hasExplicitMinimumAlignment()); + assertEquals(4, s.getExplicitMinimumAlignment()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -181,11 +173,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3")); Structure s = (Structure) c.getDataType("IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -197,9 +187,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructurePack1VsPack2() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -211,7 +199,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - s.setInternallyAligned(true); + s.setToDefaultPacking(); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -220,7 +208,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(8, s.getComponent(3).getOffset()); assertEquals(16, s.getLength()); assertEquals(4, s.getAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + commit = true; } finally { @@ -228,9 +216,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -240,7 +225,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setPackingValue(1); + s.pack(1); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -249,7 +234,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(7, s.getComponent(3).getOffset()); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - assertEquals(1, s.getPackingValue()); + commit = true; } finally { @@ -257,9 +242,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -269,7 +251,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setPackingValue(2); + s.pack(2); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -278,7 +260,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(8, s.getComponent(3).getOffset()); assertEquals(16, s.getLength()); assertEquals(2, s.getAlignment()); - assertEquals(2, s.getPackingValue()); + commit = true; } finally { @@ -302,11 +284,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(1, s.getPackingValue()); + assertTrue(s.hasExplicitPackingValue()); + assertEquals(1, s.getExplicitPackingValue()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); assertEquals(3, s.getComponent(2).getOffset()); @@ -329,11 +310,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(2, s.getPackingValue()); + assertTrue(s.hasExplicitPackingValue()); + assertEquals(2, s.getExplicitPackingValue()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -355,11 +335,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3")); Structure s = (Structure) c.getDataType("IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -371,9 +349,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructureMinAlignVsPack() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -385,7 +361,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - s.setInternallyAligned(true); + s.setToDefaultPacking(); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -394,7 +370,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(8, s.getComponent(3).getOffset()); assertEquals(16, s.getLength()); assertEquals(4, s.getAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + commit = true; } finally { @@ -402,9 +378,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -414,7 +387,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setToMachineAlignment(); + s.setToMachineAligned(); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -430,9 +403,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -442,7 +412,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setPackingValue(1); + s.pack(1); assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); @@ -450,7 +420,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(7, s.getComponent(3).getOffset()); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - assertEquals(1, s.getPackingValue()); + commit = true; } finally { @@ -474,11 +444,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(false, s.isDefaultAligned()); - assertEquals(true, s.isMachineAligned()); - assertEquals(8, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isMachineAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -501,11 +469,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(1, s.getPackingValue()); + assertTrue(s.hasExplicitPackingValue()); + assertEquals(1, s.getExplicitPackingValue()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); assertEquals(3, s.getComponent(2).getOffset()); @@ -517,9 +484,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructureAddVsAlign() throws Exception { mtf.initialize("notepad", new ProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ + @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -534,6 +499,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { s.add(new IntegerDataType()); // Offsets change to 0,2,4,8. + assertFalse(s.isPackingEnabled()); assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); assertEquals(3, s.getComponent(2).getOffset()); @@ -541,7 +507,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(15, s.getComponent(4).getOffset()); assertEquals(19, s.getLength()); assertEquals(1, s.getAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); commit = true; } finally { @@ -549,9 +514,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -563,7 +525,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - s.setInternallyAligned(true); + s.setToDefaultPacking(); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -572,7 +534,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(8, s.getComponent(3).getOffset()); assertEquals(16, s.getLength()); assertEquals(4, s.getAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + commit = true; } finally { @@ -596,11 +558,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(false, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertFalse(s.isPackingEnabled()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); assertEquals(3, s.getComponent(2).getOffset()); @@ -624,11 +584,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -640,9 +598,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructureFieldNameVsPack() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -654,7 +610,8 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - s.setInternallyAligned(true); + s.setToDefaultPacking(); + // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); @@ -669,9 +626,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -685,6 +639,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(4, s.getAlignment()); s.getComponent(1).setFieldName("MyComponentOne"); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals("MyComponentOne", s.getComponent(1).getFieldName()); @@ -692,7 +649,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(8, s.getComponent(3).getOffset()); assertEquals(16, s.getLength()); assertEquals(4, s.getAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + commit = true; } finally { @@ -700,9 +657,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -714,7 +668,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(16, s.getLength()); assertEquals(4, s.getAlignment()); - s.setPackingValue(1); + s.pack(1); assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); @@ -722,7 +676,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(7, s.getComponent(3).getOffset()); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - assertEquals(1, s.getPackingValue()); + commit = true; } finally { @@ -746,11 +700,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + assertTrue(s.hasDefaultPacking()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(2, s.getComponent(1).getOffset()); assertEquals(4, s.getComponent(2).getOffset()); @@ -773,11 +725,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(1, s.getPackingValue()); + assertTrue(s.hasExplicitPackingValue()); + assertEquals(1, s.getExplicitPackingValue()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); assertEquals(3, s.getComponent(2).getOffset()); @@ -789,9 +740,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructureRemoveVsPack() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -803,7 +752,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - s.setInternallyAligned(true); + s.setToDefaultPacking(); // Offsets change to 0,2,4,8. assertEquals(0, s.getComponent(0).getOffset()); @@ -812,7 +761,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(8, s.getComponent(3).getOffset()); assertEquals(16, s.getLength()); assertEquals(4, s.getAlignment()); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + commit = true; } finally { @@ -820,9 +769,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -832,7 +778,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR); + dtm.remove(s, TaskMonitor.DUMMY); // Offsets change to 0,2,4,8. Structure intStruct = (Structure) dtm.getDataType( @@ -845,9 +791,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -857,7 +800,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setPackingValue(1); + s.pack(1); assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); @@ -865,7 +808,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(7, s.getComponent(3).getOffset()); assertEquals(15, s.getLength()); assertEquals(1, s.getAlignment()); - assertEquals(1, s.getPackingValue()); + commit = true; } finally { @@ -906,11 +849,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure s = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, s.isInternallyAligned()); - assertEquals(true, s.isDefaultAligned()); - assertEquals(false, s.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, s.getMinimumAlignment()); - assertEquals(1, s.getPackingValue()); + assertTrue(s.hasExplicitPackingValue()); + assertEquals(1, s.getExplicitPackingValue()); + assertTrue(s.isDefaultAligned()); + assertEquals(0, s.getComponent(0).getOffset()); assertEquals(1, s.getComponent(1).getOffset()); assertEquals(3, s.getComponent(2).getOffset()); @@ -922,9 +864,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { private void setupStructureInUnionAndViceVersa() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -934,11 +874,11 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Structure s = (Structure) dtm.getDataType( new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - s.setInternallyAligned(true); + s.setPackingEnabled(true); Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); - union.setInternallyAligned(true); + union.setPackingEnabled(true); commit = true; } @@ -947,9 +887,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -975,9 +912,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -1019,11 +953,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Structure intStruct = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2/Category3"), "IntStruct"); - assertEquals(true, intStruct.isInternallyAligned()); - assertEquals(true, intStruct.isDefaultAligned()); - assertEquals(false, intStruct.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, intStruct.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, intStruct.getPackingValue()); + assertTrue(intStruct.hasDefaultPacking()); + assertTrue(intStruct.isDefaultAligned()); + assertEquals(5, intStruct.getNumComponents()); assertEquals(0, intStruct.getComponent(0).getOffset()); assertEquals(2, intStruct.getComponent(1).getOffset()); @@ -1036,11 +968,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { Union coolUnion = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); - assertEquals(true, coolUnion.isInternallyAligned()); - assertEquals(true, coolUnion.isDefaultAligned()); - assertEquals(false, coolUnion.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, coolUnion.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, coolUnion.getPackingValue()); + assertTrue(coolUnion.hasDefaultPacking()); + assertTrue(coolUnion.isDefaultAligned()); + assertEquals(6, coolUnion.getNumComponents()); assertEquals("qword", coolUnion.getComponent(0).getDataType().getDisplayName()); assertEquals("word", coolUnion.getComponent(1).getDataType().getDisplayName()); @@ -1061,9 +991,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { public void setupUnionMachineAlignedVsValue() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -1075,7 +1003,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { "CoolUnion"); assertEquals(96, union.getLength()); assertEquals(1, union.getAlignment()); - union.setInternallyAligned(true); + union.setPackingEnabled(true); assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); @@ -1091,9 +1019,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -1103,7 +1028,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); - union.setToMachineAlignment(); + union.setToMachineAligned(); assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); @@ -1119,9 +1044,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -1131,7 +1053,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); - union.setMinimumAlignment(4); + union.setExplicitMinimumAlignment(4); assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); @@ -1162,11 +1084,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); - assertEquals(true, union.isInternallyAligned()); - assertEquals(false, union.isDefaultAligned()); - assertEquals(true, union.isMachineAligned()); - assertEquals(8, union.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, union.getPackingValue()); + assertTrue(union.hasDefaultPacking()); + assertTrue(union.isMachineAligned()); + assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); assertEquals(4, union.getComponent(2).getLength()); @@ -1189,11 +1109,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); - assertEquals(true, union.isInternallyAligned()); - assertEquals(false, union.isDefaultAligned()); - assertEquals(false, union.isMachineAligned()); - assertEquals(4, union.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, union.getPackingValue()); + assertTrue(union.hasDefaultPacking()); + assertTrue(union.hasExplicitMinimumAlignment()); + assertEquals(4, union.getExplicitMinimumAlignment()); + assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); assertEquals(4, union.getComponent(2).getLength()); @@ -1216,11 +1135,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); - assertEquals(true, union.isInternallyAligned()); - assertEquals(true, union.isDefaultAligned()); - assertEquals(false, union.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, union.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, union.getPackingValue()); + assertTrue(union.hasDefaultPacking()); + assertTrue(union.isDefaultAligned()); + assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); assertEquals(4, union.getComponent(2).getLength()); @@ -1233,9 +1150,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { public void setupUnionPack1VsPack2() throws Exception { mtf.initialize("notepad", new OriginalProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.OriginalProgramModifierListener#modifyOriginal(ghidra.program.database.ProgramDB) - */ + @Override public void modifyOriginal(ProgramDB program) throws Exception { boolean commit = false; @@ -1247,7 +1162,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { "CoolUnion"); assertEquals(96, union.getLength()); assertEquals(1, union.getAlignment()); - union.setInternallyAligned(true); + union.setPackingEnabled(true); assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); @@ -1263,9 +1178,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -1275,7 +1187,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); - union.setPackingValue(1); + union.pack(1); assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); @@ -1291,9 +1203,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { } } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -1303,7 +1212,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { try { Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); - union.setPackingValue(2); + union.pack(2); assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); @@ -1334,11 +1243,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); - assertEquals(true, union.isInternallyAligned()); - assertEquals(true, union.isDefaultAligned()); - assertEquals(false, union.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, union.getMinimumAlignment()); - assertEquals(1, union.getPackingValue()); + assertTrue(union.hasExplicitPackingValue()); + assertEquals(1, union.getExplicitPackingValue()); + assertTrue(union.isDefaultAligned()); + assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); assertEquals(4, union.getComponent(2).getLength()); @@ -1361,11 +1269,10 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); - assertEquals(true, union.isInternallyAligned()); - assertEquals(true, union.isDefaultAligned()); - assertEquals(false, union.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, union.getMinimumAlignment()); - assertEquals(2, union.getPackingValue()); + assertTrue(union.hasExplicitPackingValue()); + assertEquals(2, union.getExplicitPackingValue()); + assertTrue(union.isDefaultAligned()); + assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); assertEquals(4, union.getComponent(2).getLength()); @@ -1388,11 +1295,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); - assertEquals(true, union.isInternallyAligned()); - assertEquals(true, union.isDefaultAligned()); - assertEquals(false, union.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, union.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, union.getPackingValue()); + assertTrue(union.hasDefaultPacking()); + assertTrue(union.isDefaultAligned()); + assertEquals(8, union.getComponent(0).getLength()); assertEquals(2, union.getComponent(1).getLength()); assertEquals(4, union.getComponent(2).getLength()); @@ -1416,9 +1321,7 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { struct2.add(new StringDataType(), 4); mtf.initialize("notepad", new ProgramModifierListener() { - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB) - */ + @Override public void modifyLatest(ProgramDB program) throws Exception { boolean commit = false; @@ -1444,12 +1347,9 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertTrue(new PointerDataType(new FloatDataType()).isEquivalent( s.getComponent(0).getDataType())); assertTrue(new FloatDataType().isEquivalent(s.getComponent(1).getDataType())); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); + } - /* (non-Javadoc) - * @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB) - */ @Override public void modifyPrivate(ProgramDB program) throws Exception { boolean commit = false; @@ -1474,7 +1374,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(4, s.getComponent(1).getLength()); assertTrue(new CharDataType().isEquivalent(s.getComponent(0).getDataType())); assertTrue(new StringDataType().isEquivalent(s.getComponent(1).getDataType())); - assertEquals(Composite.NOT_PACKING, s.getPackingValue()); } }); @@ -1495,7 +1394,6 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertTrue(new PointerDataType(new FloatDataType()).isEquivalent( s1.getComponent(0).getDataType())); assertTrue(new FloatDataType().isEquivalent(s1.getComponent(1).getDataType())); - assertEquals(Composite.NOT_PACKING, s1.getPackingValue()); Structure s2 = (Structure) dtm.getDataType(new CategoryPath("/Category1"), "ABCStructure.conflict"); @@ -1508,6 +1406,5 @@ public class DataTypeMerge6Test extends AbstractDataTypeMergeTest { assertEquals(4, s2.getComponent(1).getLength()); assertTrue(new CharDataType().isEquivalent(s2.getComponent(0).getDataType())); assertTrue(new StringDataType().isEquivalent(s2.getComponent(1).getDataType())); - assertEquals(Composite.NOT_PACKING, s2.getPackingValue()); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMergeFixupTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMergeFixupTest.java index a646d4d8cb..04ab41dc12 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMergeFixupTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMergeFixupTest.java @@ -60,7 +60,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { Structure inner = new StructureDataType("inner", 0); inner.add(new ByteDataType()); inner.add(new WordDataType()); - inner.setInternallyAligned(true); + inner.setPackingEnabled(true); try { Category rootCategory = dtm.getCategory(rootPath); @@ -103,7 +103,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { Structure outer = new StructureDataType("outer", 0); outer.add(new ByteDataType()); outer.add(inner); - outer.setInternallyAligned(true); + outer.setPackingEnabled(true); int transactionID = program.startTransaction("create outer struct, modify inner"); try { @@ -134,14 +134,14 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { waitForCompletion(); DataTypeManager dtm = resultProgram.getDataTypeManager(); - Structure inner = (Structure) dtm.getDataType(rootPath, "inner"); + StructureInternal inner = (StructureInternal) dtm.getDataType(rootPath, "inner"); assertNull(inner); - Structure outer = (Structure) dtm.getDataType(rootPath, "outer"); + StructureInternal outer = (StructureInternal) dtm.getDataType(rootPath, "outer"); assertNotNull(outer); - assertEquals(true, outer.isInternallyAligned()); + assertEquals(true, outer.isPackingEnabled()); assertEquals(true, outer.isDefaultAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, outer.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, outer.getPackingValue()); + assertEquals(CompositeInternal.DEFAULT_ALIGNMENT, outer.getStoredMinimumAlignment()); + assertEquals(CompositeInternal.DEFAULT_PACKING, outer.getStoredPackingValue()); assertEquals(1, outer.getNumComponents()); assertTrue(new ByteDataType().isEquivalent(outer.getComponent(0).getDataType())); assertEquals(1, outer.getLength()); @@ -162,24 +162,24 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { waitForCompletion(); DataTypeManager dtm = resultProgram.getDataTypeManager(); - Structure inner = (Structure) dtm.getDataType(rootPath, "inner"); + StructureInternal inner = (StructureInternal) dtm.getDataType(rootPath, "inner"); assertNotNull(inner); - assertEquals(true, inner.isInternallyAligned()); + assertEquals(true, inner.isPackingEnabled()); assertEquals(true, inner.isDefaultAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, inner.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, inner.getPackingValue()); + assertEquals(CompositeInternal.DEFAULT_ALIGNMENT, inner.getStoredMinimumAlignment()); + assertEquals(CompositeInternal.DEFAULT_PACKING, inner.getStoredPackingValue()); assertEquals(2, inner.getNumComponents()); assertTrue(new CharDataType().isEquivalent(inner.getComponent(0).getDataType())); assertTrue(new WordDataType().isEquivalent(inner.getComponent(1).getDataType())); assertEquals(4, inner.getLength()); assertEquals(2, inner.getAlignment()); - Structure outer = (Structure) dtm.getDataType(rootPath, "outer"); + StructureInternal outer = (StructureInternal) dtm.getDataType(rootPath, "outer"); assertNotNull(outer); - assertEquals(true, outer.isInternallyAligned()); + assertEquals(true, outer.isPackingEnabled()); assertEquals(true, outer.isDefaultAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, outer.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, outer.getPackingValue()); + assertEquals(CompositeInternal.DEFAULT_ALIGNMENT, outer.getStoredMinimumAlignment()); + assertEquals(CompositeInternal.DEFAULT_PACKING, outer.getStoredPackingValue()); assertEquals(2, outer.getNumComponents()); assertTrue(new ByteDataType().isEquivalent(outer.getComponent(0).getDataType())); assertEquals(inner, outer.getComponent(1).getDataType()); @@ -220,7 +220,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { Structure inner = new StructureDataType("inner", 0); inner.add(new ByteDataType()); inner.add(new WordDataType()); - inner.setInternallyAligned(true); + inner.setPackingEnabled(true); try { Category rootCategory = dtm.getCategory(rootPath); @@ -263,7 +263,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { Structure outer = new StructureDataType("outer", 0); outer.add(new ByteDataType()); outer.add(inner); - outer.setInternallyAligned(true); + outer.setPackingEnabled(true); int transactionID = program.startTransaction("create outer struct, don't modify inner"); @@ -283,14 +283,14 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { waitForCompletion(); DataTypeManager dtm = resultProgram.getDataTypeManager(); - Structure inner = (Structure) dtm.getDataType(rootPath, "inner"); + StructureInternal inner = (StructureInternal) dtm.getDataType(rootPath, "inner"); assertNull(inner); - Structure outer = (Structure) dtm.getDataType(rootPath, "outer"); + StructureInternal outer = (StructureInternal) dtm.getDataType(rootPath, "outer"); assertNotNull(outer); - assertEquals(true, outer.isInternallyAligned()); + assertEquals(true, outer.isPackingEnabled()); assertEquals(true, outer.isDefaultAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, outer.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, outer.getPackingValue()); + assertEquals(CompositeInternal.DEFAULT_ALIGNMENT, outer.getStoredMinimumAlignment()); + assertEquals(CompositeInternal.DEFAULT_PACKING, outer.getStoredPackingValue()); assertEquals(1, outer.getNumComponents()); assertTrue(new ByteDataType().isEquivalent(outer.getComponent(0).getDataType())); assertEquals(1, outer.getLength()); @@ -335,7 +335,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { Structure inner = new StructureDataType("inner", 0); inner.add(new ByteDataType()); inner.add(new WordDataType()); - inner.setInternallyAligned(true); + inner.setPackingEnabled(true); try { Category rootCategory = dtm.getCategory(rootPath); @@ -378,7 +378,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { Structure other = new StructureDataType("other", 0); other.add(new ByteDataType()); other.add(new PointerDataType(new VoidDataType())); - other.setInternallyAligned(true); + other.setPackingEnabled(true); Structure outer = new StructureDataType("outer", 0); outer.add(new ByteDataType()); @@ -386,7 +386,7 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { outer.add(new FloatDataType()); outer.add(other); outer.add(new ByteDataType()); - outer.setInternallyAligned(true); + outer.setPackingEnabled(true); int transactionID = program.startTransaction( "create outer struct with other structure after inner"); @@ -407,15 +407,15 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { DataTypeManager dtm = resultProgram.getDataTypeManager(); - Structure inner = (Structure) dtm.getDataType(rootPath, "inner"); + StructureInternal inner = (StructureInternal) dtm.getDataType(rootPath, "inner"); assertNull(inner); - Structure other = (Structure) dtm.getDataType(rootPath, "other"); + StructureInternal other = (StructureInternal) dtm.getDataType(rootPath, "other"); assertNotNull(other); - assertEquals(true, other.isInternallyAligned()); + assertEquals(true, other.isPackingEnabled()); assertEquals(true, other.isDefaultAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, other.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, other.getPackingValue()); + assertEquals(CompositeInternal.DEFAULT_ALIGNMENT, other.getStoredMinimumAlignment()); + assertEquals(CompositeInternal.DEFAULT_PACKING, other.getStoredPackingValue()); assertEquals(2, other.getNumComponents()); assertTrue(new ByteDataType().isEquivalent(other.getComponent(0).getDataType())); assertTrue(new PointerDataType(new VoidDataType()).isEquivalent( @@ -423,12 +423,12 @@ public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest { assertEquals(8, other.getLength()); assertEquals(4, other.getAlignment()); - Structure outer = (Structure) dtm.getDataType(rootPath, "outer"); + StructureInternal outer = (StructureInternal) dtm.getDataType(rootPath, "outer"); assertNotNull(outer); - assertEquals(true, outer.isInternallyAligned()); + assertEquals(true, outer.isPackingEnabled()); assertEquals(true, outer.isDefaultAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, outer.getMinimumAlignment()); - assertEquals(Composite.NOT_PACKING, outer.getPackingValue()); + assertEquals(CompositeInternal.DEFAULT_ALIGNMENT, outer.getStoredMinimumAlignment()); + assertEquals(CompositeInternal.DEFAULT_PACKING, outer.getStoredPackingValue()); assertEquals(4, outer.getNumComponents()); assertTrue(new ByteDataType().isEquivalent(outer.getComponent(0).getDataType())); assertTrue(new FloatDataType().isEquivalent(outer.getComponent(1).getDataType())); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java index 8a64ddfddd..fd0791da01 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java @@ -90,12 +90,12 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest struct.add(CharDataType.dataType); struct.add(IntegerDataType.dataType); struct.add(CharDataType.dataType); - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); builder.applyDataType("0x1001100", struct); builder.setBytes("0x1001200", "01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"); struct = new StructureDataType("struct2", 12); - struct.setInternallyAligned(false); + struct.setPackingEnabled(false); struct.insertAtOffset(0, CharDataType.dataType, -1); struct.insertAtOffset(4, IntegerDataType.dataType, -1); struct.insertAtOffset(8, CharDataType.dataType, -1); @@ -486,7 +486,7 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest showTool(tool); loadProgram(); - // turn alignment bytes option on but it has no impact on displayed bytes for unaligned structure + // turn alignment bytes option on but it has no impact on displayed bytes for non-packed structure Options options = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS); options.setBoolean("Bytes Field.Display Structure Alignment Bytes", true); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractEditorTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractEditorTest.java index a8f1c39ea0..8223a73e07 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractEditorTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractEditorTest.java @@ -47,7 +47,6 @@ import ghidra.framework.plugintool.util.PluginException; import ghidra.program.database.ProgramBuilder; import ghidra.program.model.data.*; import ghidra.program.model.data.Composite; -import ghidra.program.model.data.Composite.AlignmentType; import ghidra.program.model.data.Enum; import ghidra.program.model.listing.Program; import ghidra.test.AbstractGhidraHeadedIntegrationTest; @@ -213,8 +212,7 @@ public abstract class AbstractEditorTest extends AbstractGhidraHeadedIntegration } protected CycleGroupAction getCycleGroup(DataType dt) { - for (int cycleIndex = 0; cycleIndex < cycles.size(); cycleIndex++) { - CycleGroupAction action = cycles.get(cycleIndex); + for (CycleGroupAction action : cycles) { CycleGroup group = action.getCycleGroup(); DataType[] types = group.getDataTypes(); for (DataType type : types) { @@ -227,8 +225,7 @@ public abstract class AbstractEditorTest extends AbstractGhidraHeadedIntegration } protected FavoritesAction getFavorite(String name) { - for (int favIndex = 0; favIndex < favorites.size(); favIndex++) { - FavoritesAction action = favorites.get(favIndex); + for (FavoritesAction action : favorites) { if (action.getDataType().getDisplayName().equals(name)) { return action; } @@ -332,13 +329,17 @@ public abstract class AbstractEditorTest extends AbstractGhidraHeadedIntegration } protected void invoke(final DockingActionIf action) { + invoke(action, true); + } + + protected void invoke(final DockingActionIf action, boolean wait) { assertNotNull(action); boolean isEnabled = runSwing(() -> action.isEnabled()); if (!isEnabled) { Msg.debug(this, "Calling actionPerformed() on a disabled action: " + action.getName(), ReflectionUtilities.createJavaFilteredThrowable()); } - runSwing(() -> action.actionPerformed(new ActionContext()), false); + runSwing(() -> action.actionPerformed(new ActionContext()), wait); waitForSwing(); } @@ -811,20 +812,30 @@ public abstract class AbstractEditorTest extends AbstractGhidraHeadedIntegration actionEnablement); } - protected void assertIsInternallyAligned(boolean aligned) { - assertEquals(aligned, ((CompEditorModel) model).isAligned()); + protected void assertIsPackingEnabled(boolean aligned) { + assertEquals(aligned, ((CompEditorModel) model).isPackingEnabled()); } - protected void assertPackingValue(int value) { - assertEquals(value, ((CompEditorModel) model).getPackingValue()); + protected void assertDefaultPacked() { + assertEquals(PackingType.DEFAULT, ((CompEditorModel) model).getPackingType()); } - protected void assertMinimumAlignmentType(AlignmentType alignmentType) { - assertEquals(alignmentType, ((CompEditorModel) model).getMinimumAlignmentType()); + protected void assertPacked(int pack) { + assertEquals(PackingType.EXPLICIT, ((CompEditorModel) model).getPackingType()); + assertEquals(pack, ((CompEditorModel) model).getExplicitPackingValue()); } - protected void assertMinimumAlignmentValue(int value) { - assertEquals(value, ((CompEditorModel) model).getMinimumAlignment()); + protected void assertIsDefaultAligned() { + assertEquals(AlignmentType.DEFAULT, ((CompEditorModel) model).getAlignmentType()); + } + + protected void assertIsMachineAligned() { + assertEquals(AlignmentType.MACHINE, ((CompEditorModel) model).getAlignmentType()); + } + + protected void assertExplicitAlignment(int alignment) { + assertEquals(AlignmentType.EXPLICIT, ((CompEditorModel) model).getAlignmentType()); + assertEquals(alignment, ((CompEditorModel) model).getExplicitMinimumAlignment()); } protected void assertActualAlignment(int value) { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorLockedActionsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorLockedActionsTest.java index c342ae7fc6..582ef0a782 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorLockedActionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorLockedActionsTest.java @@ -28,7 +28,7 @@ public abstract class AbstractStructureEditorLockedActionsTest extends AbstractS try { DataTypeManager dataTypeManager = cat.getDataTypeManager(); if (dt.getDataTypeManager() != dataTypeManager) { - dt = (Structure) dt.clone(dataTypeManager); + dt = dt.clone(dataTypeManager); } CategoryPath categoryPath = cat.getCategoryPath(); if (!dt.getCategoryPath().equals(categoryPath)) { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorTest.java index fb3236d068..7f321ef597 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/AbstractStructureEditorTest.java @@ -60,7 +60,7 @@ public abstract class AbstractStructureEditorTest extends AbstractEditorTest { try { DataTypeManager dataTypeManager = cat.getDataTypeManager(); if (dt.getDataTypeManager() != dataTypeManager) { - dt = (Structure) dt.clone(dataTypeManager); + dt = dt.clone(dataTypeManager); } CategoryPath categoryPath = cat.getCategoryPath(); if (!dt.getCategoryPath().equals(categoryPath)) { @@ -81,6 +81,7 @@ public abstract class AbstractStructureEditorTest extends AbstractEditorTest { installProvider(new StructureEditorProvider(plugin, structDt, showInHex)); model = provider.getModel(); }); + waitForSwing(); getActions(); structureModel = (StructureEditorModel) model; } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorAlignmentTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorAlignmentTest.java index e1fa6feff2..b81a6df05c 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorAlignmentTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorAlignmentTest.java @@ -23,7 +23,6 @@ import javax.swing.JTextField; import org.junit.Test; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Library; import ghidra.program.model.symbol.ExternalLocation; @@ -32,7 +31,7 @@ import ghidra.program.model.symbol.SourceType; public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { @Test - public void testUnalignedStructure() { + public void testNonPackedStructure() { init(emptyStructure, pgmRootCat, false); assertTrue(structureModel.hasChanges());// initial unsaved empty structure @@ -44,10 +43,8 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { structureModel.getOriginalCategoryPath().getPath()); assertEquals(0, structureModel.getNumComponents());// no components assertEquals(1, structureModel.getRowCount());// blank row - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertLength(0); assertActualAlignment(1); assertEquals(0, structureModel.getNumSelectedComponentRows()); @@ -102,7 +99,9 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { assertLength(10); assertActualAlignment(1); - pressButtonByName(getPanel(), "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); assertEquals(3, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -115,7 +114,7 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { @Test public void testEnablementDefaultAlignedStructure() throws Exception { - emptyStructure.setInternallyAligned(true); + emptyStructure.setPackingEnabled(true); init(emptyStructure, pgmRootCat, false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); @@ -159,8 +158,12 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { waitForSwing(); - pressButtonByName(getPanel(), "Internally Aligned"); - pressButtonByName(getPanel(), "Machine Minimum Alignment"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); + + pressButtonByName(getPanel(), "Machine Alignment"); + assertIsMachineAligned(); assertEquals(3, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -184,19 +187,24 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { waitForSwing(); - pressButtonByName(editorPanel, "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); + JTextField minAlignField = - (JTextField) getInstanceField("minAlignValueTextField", editorPanel); + (JTextField) getInstanceField("explicitAlignTextField", editorPanel); assertNotNull(minAlignField); - JRadioButton byValueMinAlignButton = - (JRadioButton) getInstanceField("byValueMinAlignButton", editorPanel); - assertNotNull(byValueMinAlignButton); - pressButton(byValueMinAlignButton); - assertEquals("4", minAlignField.getText()); + JRadioButton explicitAlignButton = + (JRadioButton) getInstanceField("explicitAlignButton", editorPanel); + assertNotNull(explicitAlignButton); + pressButton(explicitAlignButton); + assertEquals("8", minAlignField.getText()); // toy.cspec machine alignment is default value assertEquals(false, structureModel.viewComposite.isDefaultAligned()); assertEquals(false, structureModel.viewComposite.isMachineAligned()); - assertEquals(4, structureModel.getMinimumAlignment()); + assertEquals(8, structureModel.getExplicitMinimumAlignment()); + + assertActualAlignment(8); assertEquals(3, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -204,7 +212,7 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); assertLength(16); - assertActualAlignment(4); + assertActualAlignment(8); } @Test @@ -232,10 +240,10 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { checkByValueAlignedStructure(16, 16, 16); } - public void checkByValueAlignedStructure(int value, int alignment, int length) + public void checkByValueAlignedStructure(int minAlignment, int alignment, int length) throws Exception { - emptyStructure.setInternallyAligned(true); - emptyStructure.setMinimumAlignment(value); + emptyStructure.setPackingEnabled(true); + emptyStructure.setExplicitMinimumAlignment(minAlignment); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyStructure.add(new ByteDataType()); @@ -245,19 +253,20 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { init(emptyStructure, pgmRootCat, false); CompEditorPanel editorPanel = (CompEditorPanel) getPanel(); - JRadioButton byValueMinAlignButton = - (JRadioButton) getInstanceField("byValueMinAlignButton", editorPanel); - assertNotNull(byValueMinAlignButton); - assertEquals(true, byValueMinAlignButton.isSelected()); + JRadioButton explicitAlignButton = + (JRadioButton) getInstanceField("explicitAlignButton", editorPanel); + assertNotNull(explicitAlignButton); + assertEquals(true, explicitAlignButton.isSelected()); JTextField minAlignField = - (JTextField) getInstanceField("minAlignValueTextField", editorPanel); + (JTextField) getInstanceField("explicitAlignTextField", editorPanel); assertNotNull(minAlignField); - assertEquals("" + value, minAlignField.getText()); + assertEquals("" + minAlignment, minAlignField.getText()); assertEquals(false, structureModel.viewComposite.isDefaultAligned()); assertEquals(false, structureModel.viewComposite.isMachineAligned()); - assertEquals(value, structureModel.getMinimumAlignment()); + + assertExplicitAlignment(minAlignment); assertEquals(3, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -270,9 +279,9 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { @Test public void testDefaultAlignedPacked1Structure() throws Exception { - int value = 1; - emptyStructure.setInternallyAligned(true); - emptyStructure.setPackingValue(value); + int pack = 1; + emptyStructure.setPackingEnabled(true); + emptyStructure.pack(pack); init(emptyStructure, pgmRootCat, false); CompEditorPanel editorPanel = (CompEditorPanel) getPanel(); @@ -283,17 +292,18 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { addDataType(arrayDt); JRadioButton byValuePackingButton = - (JRadioButton) findComponentByName(editorPanel, "By Value Packing"); + (JRadioButton) findComponentByName(editorPanel, "Explicit Packing"); assertNotNull(byValuePackingButton); JTextField packingValueField = (JTextField) findComponentByName(editorPanel, "Packing Value"); assertNotNull(packingValueField); assertEquals(true, byValuePackingButton.isSelected()); - assertEquals("" + value, packingValueField.getText()); + assertEquals(Integer.toString(pack), packingValueField.getText()); assertEquals(true, structureModel.viewComposite.isDefaultAligned()); assertEquals(false, structureModel.viewComposite.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, structureModel.getMinimumAlignment()); + + assertIsDefaultAligned(); assertEquals(3, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -306,7 +316,6 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { @Test public void testAlignedEditToFunctionDefinitionDataType() throws Exception { - int value = 1; startTransaction("addExternal"); ExternalLocation extLoc = program.getExternalManager().addExtFunction(Library.UNKNOWN, @@ -321,8 +330,8 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { boolean commit = false; txId = program.startTransaction("Modify Program"); try { - simpleStructure.setInternallyAligned(true); - simpleStructure.setPackingValue(value); + simpleStructure.setPackingEnabled(true); + simpleStructure.pack(1); programDTM = program.getListing().getDataTypeManager(); functionDefinition = @@ -358,7 +367,7 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { } @Test - public void testSelectionOnGoFromUnalignedToAlignedStructure() throws Exception { + public void testSelectionOnGoFromNonPackedToDefaultPackedStructure() throws Exception { init(emptyStructure, pgmRootCat, false); CompEditorPanel editorPanel = (CompEditorPanel) getPanel(); @@ -372,10 +381,8 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { structureModel.getOriginalCategoryPath().getPath()); assertEquals(0, structureModel.getNumComponents());// no components assertEquals(1, structureModel.getRowCount());// blank row - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertLength(0); assertActualAlignment(1); assertEquals(0, structureModel.getNumSelectedComponentRows()); @@ -388,7 +395,9 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { checkSelection(new int[] { 3 }); - pressButtonByName(editorPanel, "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); assertEquals(0, structureModel.getNumComponents()); assertEquals(1, structureModel.getRowCount()); @@ -397,368 +406,383 @@ public class StructureEditorAlignmentTest extends AbstractStructureEditorTest { checkSelection(new int[] { 0 }); } -// public void testTurnOffAlignmentInStructure() throws Exception { -// emptyStructure.setInternallyAligned(true); -// emptyStructure.setMinimumAlignment(8); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// JRadioButton byValueButton = (JRadioButton)findComponentByName(getPanel(), "By Value Minimum Alignment"); -// assertEquals(true, byValueButton.isSelected()); -// JTextField minAlignField = (JTextField)findComponentByName(getPanel(), "Minimum Alignment Value"); -// assertEquals("8", minAlignField.getText()); -// -// assertEquals(false, structureModel.viewComposite.isDefaultAligned()); -// assertEquals(false, structureModel.viewComposite.isMachineAligned()); -// assertEquals(8, structureModel.getMinimumAlignment()); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(8); -// assertEquals(true, structureModel.isAligned()); -// -// pressButtonByName(getPanel(), "Internally Aligned"); -// -// assertEquals(false, structureModel.isAligned()); -// assertEquals(true, structureModel.viewComposite.isDefaultAligned()); -// assertEquals(false, structureModel.viewComposite.isMachineAligned()); -// assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, structureModel.getMinimumAlignment()); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// } -// -// public void testInsertUnaligned1() throws Exception { -// emptyStructure.setInternallyAligned(false); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// -// DataType asciiDt = model.getOriginalDataTypeManager().findDataType("/char"); -// assertNotNull(asciiDt); -// insertAtPoint(asciiDt,0,0); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "ch", asciiDt, "", ""); -// checkRow(1, 1, "db", new ByteDataType(), "", ""); -// checkRow(2, 4, "float", new FloatDataType(), "", ""); -// checkRow(3, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// } -// -// public void testInsertUnaligned2() throws Exception { -// emptyStructure.setInternallyAligned(false); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// -// DataType asciiDt = model.getOriginalDataTypeManager().findDataType("/char"); -// assertNotNull(asciiDt); -// insertAtPoint(asciiDt,2,3); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 1, "ch", asciiDt, "", ""); -// checkRow(3, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// } -// -// public void testInsertUnaligned3() throws Exception { -// emptyStructure.setInternallyAligned(false); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// -// DataType doubleDt = model.getOriginalDataTypeManager().findDataType("/double"); -// assertNotNull(doubleDt); -// insertAtPoint(doubleDt,3,3); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// checkRow(3, 8, "double", doubleDt, "", ""); -// assertLength(8); -// assertActualAlignment(1); -// } -// -// public void testReplaceUnaligned1() throws Exception { -// emptyStructure.setInternallyAligned(false); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// -// DataType asciiDt = model.getOriginalDataTypeManager().findDataType("/char"); -// assertNotNull(asciiDt); -// addAtPoint(asciiDt,2,3); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 1, "ch", asciiDt, "", ""); -// assertLength(4); -// assertActualAlignment(1); -// } -// -// public void testReplaceUnaligned2() throws Exception { -// emptyStructure.setInternallyAligned(false); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(5); -// assertActualAlignment(1); -// -// DataType doubleDt = model.getOriginalDataTypeManager().findDataType("/double"); -// assertNotNull(doubleDt); -// addAtPoint(doubleDt,3,3); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// checkRow(3, 8, "double", doubleDt, "", ""); -// assertLength(8); -// assertActualAlignment(1); -// } -// -// public void testInsertAligned1() throws Exception { -// emptyStructure.setInternallyAligned(true); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// -// DataType asciiDt = model.getOriginalDataTypeManager().findDataType("/char"); -// assertNotNull(asciiDt); -// insertAtPoint(asciiDt,0,0); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "ch", asciiDt, "", ""); -// checkRow(1, 1, "db", new ByteDataType(), "", ""); -// checkRow(2, 4, "float", new FloatDataType(), "", ""); -// checkRow(3, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// } -// -// public void testInsertAligned2() throws Exception { -// emptyStructure.setInternallyAligned(true); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// -// DataType asciiDt = model.getOriginalDataTypeManager().findDataType("/char"); -// assertNotNull(asciiDt); -// insertAtPoint(asciiDt,2,3); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 1, "ch", asciiDt, "", ""); -// checkRow(3, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// } -// -// public void testInsertAligned3() throws Exception { -// emptyStructure.setInternallyAligned(true); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// -// DataType doubleDt = model.getOriginalDataTypeManager().findDataType("/double"); -// assertNotNull(doubleDt); -// insertAtPoint(doubleDt,3,3); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// checkRow(3, 8, "double", doubleDt, "", ""); -// assertLength(8); -// assertActualAlignment(8); -// } -// -// public void testReplaceAligned1() throws Exception { -// emptyStructure.setInternallyAligned(true); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// -// DataType asciiDt = model.getOriginalDataTypeManager().findDataType("/char"); -// assertNotNull(asciiDt); -// addAtPoint(asciiDt,2,3); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 1, "ch", asciiDt, "", ""); -// assertLength(4); -// assertActualAlignment(4); -// } -// -// public void testReplaceAligned2() throws Exception { -// emptyStructure.setInternallyAligned(true); -// -// DataType arrayDt = new ArrayDataType(new AsciiDataType(), 5, 1); -// emptyStructure.add(new ByteDataType()); -// emptyStructure.add(new FloatDataType()); -// emptyStructure.add(arrayDt); -// -// init(emptyStructure, pgmRootCat, false); -// -// assertEquals(3, structureModel.getNumComponents()); -// assertEquals(4, structureModel.getRowCount()); -// checkRow(0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, "char[5]", arrayDt, "", ""); -// assertLength(8); -// assertActualAlignment(4); -// -// DataType doubleDt = model.getOriginalDataTypeManager().findDataType("/double"); -// assertNotNull(doubleDt); -// addAtPoint(doubleDt,3,3); -// -// assertEquals(4, structureModel.getNumComponents()); -// assertEquals(5, structureModel.getRowCount()); -// checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); -// checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); -// checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); -// checkRow(3, 10, 8, "double", doubleDt, "", ""); -// assertLength(18); -// assertActualAlignment(8); -// } + @Test + public void testTurnOffAlignmentInStructure() throws Exception { + emptyStructure.setPackingEnabled(true); + emptyStructure.setExplicitMinimumAlignment(8); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + CompEditorPanel editorPanel = (CompEditorPanel) getPanel(); + + JRadioButton byValueButton = + (JRadioButton) findComponentByName(getPanel(), "Explicit Alignment"); + assertEquals(true, byValueButton.isSelected()); + JTextField minAlignField = + (JTextField) findComponentByName(getPanel(), "Explicit Alignment Value"); + assertEquals("8", minAlignField.getText()); + + assertEquals(false, structureModel.viewComposite.isDefaultAligned()); + assertEquals(false, structureModel.viewComposite.isMachineAligned()); + assertEquals(8, structureModel.getExplicitMinimumAlignment()); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(8); + assertEquals(true, structureModel.isPackingEnabled()); + + pressButtonByName(editorPanel, "Packing Enablement"); // toggle -> disable packing + + assertEquals(false, structureModel.isPackingEnabled()); + assertEquals(true, structureModel.viewComposite.isDefaultAligned()); + assertEquals(false, structureModel.viewComposite.isMachineAligned()); + assertEquals(false, structureModel.viewComposite.hasExplicitMinimumAlignment()); + + assertEquals(9, structureModel.getNumComponents()); + assertEquals(10, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(4, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(5, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(1); + } + + @Test + public void testInsertUnaligned1() throws Exception { + emptyStructure.setPackingEnabled(false); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + assertLength(10); + assertActualAlignment(1); + + DataType asciiDt = model.getOriginalDataTypeManager().getDataType("/char"); + assertNotNull(asciiDt); + insertAtPoint(asciiDt, 0, 0); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "char", asciiDt, "", ""); + checkRow(1, 1, 1, "db", new ByteDataType(), "", ""); + checkRow(2, 2, 4, "float", new FloatDataType(), "", ""); + checkRow(3, 6, 5, "char[5]", arrayDt, "", ""); + assertLength(11); + assertActualAlignment(1); + } + + @Test + public void testInsertUnaligned2() throws Exception { + emptyStructure.setPackingEnabled(false); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + assertLength(10); + assertActualAlignment(1); + + DataType asciiDt = model.getOriginalDataTypeManager().getDataType("/char"); + assertNotNull(asciiDt); + insertAtPoint(asciiDt, 2, 3); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 1, "char", asciiDt, "", ""); + checkRow(3, 6, 5, "char[5]", arrayDt, "", ""); + assertLength(11); + assertActualAlignment(1); + } + + @Test + public void testInsertUnaligned3() throws Exception { + emptyStructure.setPackingEnabled(false); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + assertLength(10); + assertActualAlignment(1); + + DataType doubleDt = model.getOriginalDataTypeManager().getDataType("/double"); + assertNotNull(doubleDt); + insertAtPoint(doubleDt, 3, 3); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + checkRow(3, 10, 8, "double", doubleDt, "", ""); + assertLength(18); + assertActualAlignment(1); + } + + @Test + public void testReplaceUnaligned1() throws Exception { + emptyStructure.setPackingEnabled(false); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + assertLength(10); + assertActualAlignment(1); + + DataType asciiDt = model.getOriginalDataTypeManager().getDataType("/char"); + assertNotNull(asciiDt); + addAtPoint(asciiDt, 2, 3); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 1, "char", asciiDt, "", ""); + assertLength(6); + assertActualAlignment(1); + } + + @Test + public void testReplaceUnaligned2() throws Exception { + emptyStructure.setPackingEnabled(false); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + assertLength(10); + assertActualAlignment(1); + + DataType doubleDt = model.getOriginalDataTypeManager().getDataType("/double"); + assertNotNull(doubleDt); + addAtPoint(doubleDt, 3, 3); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 1, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 5, 5, "char[5]", arrayDt, "", ""); + checkRow(3, 10, 8, "double", doubleDt, "", ""); + assertLength(18); + assertActualAlignment(1); + } + + @Test + public void testInsertAligned1() throws Exception { + emptyStructure.setPackingEnabled(true); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + + DataType asciiDt = model.getOriginalDataTypeManager().getDataType("/char"); + assertNotNull(asciiDt); + insertAtPoint(asciiDt, 0, 0); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "char", asciiDt, "", ""); + checkRow(1, 1, 1, "db", new ByteDataType(), "", ""); + checkRow(2, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(3, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + } + + @Test + public void testInsertAligned2() throws Exception { + emptyStructure.setPackingEnabled(true); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + + DataType asciiDt = model.getOriginalDataTypeManager().getDataType("/char"); + assertNotNull(asciiDt); + insertAtPoint(asciiDt, 2, 3); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 1, "char", asciiDt, "", ""); + checkRow(3, 9, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + } + + @Test + public void testInsertAligned3() throws Exception { + emptyStructure.setPackingEnabled(true); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + + DataType doubleDt = model.getOriginalDataTypeManager().getDataType("/double"); + assertNotNull(doubleDt); + insertAtPoint(doubleDt, 3, 3); + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + checkRow(3, 16, 8, "double", doubleDt, "", ""); // alignment is 4 + assertLength(24); + assertActualAlignment(4); + } + + @Test + public void testReplaceAligned1() throws Exception { + emptyStructure.setPackingEnabled(true); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + + DataType asciiDt = model.getOriginalDataTypeManager().getDataType("/char"); + assertNotNull(asciiDt); + addAtPoint(asciiDt, 2, 3); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 1, "char", asciiDt, "", ""); + assertLength(12); + assertActualAlignment(4); + } + + @Test + public void testReplaceAligned2() throws Exception { + emptyStructure.setPackingEnabled(true); + + DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); + emptyStructure.add(new ByteDataType()); + emptyStructure.add(new FloatDataType()); + emptyStructure.add(arrayDt); + + init(emptyStructure, pgmRootCat, false); + + assertEquals(3, structureModel.getNumComponents()); + assertEquals(4, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + assertLength(16); + assertActualAlignment(4); + + DataType doubleDt = model.getOriginalDataTypeManager().getDataType("/double"); + assertNotNull(doubleDt); + addAtPoint(doubleDt, 3, 3); // same as insert on last row + + assertEquals(4, structureModel.getNumComponents()); + assertEquals(5, structureModel.getRowCount()); + checkRow(0, 0, 1, "db", new ByteDataType(), "", ""); + checkRow(1, 4, 4, "float", new FloatDataType(), "", ""); + checkRow(2, 8, 5, "char[5]", arrayDt, "", ""); + checkRow(3, 16, 8, "double", doubleDt, "", ""); + assertLength(24); + assertActualAlignment(4); + } //////////////////////////// diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorFlexAlignmentTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorFlexAlignmentTest.java index c17a597edd..24005deab7 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorFlexAlignmentTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorFlexAlignmentTest.java @@ -23,10 +23,15 @@ import javax.swing.JTextField; import org.junit.Test; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTest { + // NOTE: The trailing flexable array may be assigned an incorrect offset + // when packing is enabled and the minimum alignment is specified. In such cases, + // the flex array may be less than the overall structure length. Currently, it is + // assumed the trailing flex array will have an offset equal to the overall + // structure length. + @Test public void testUnalignedStructure() { init(emptyStructure, pgmRootCat, false); @@ -40,10 +45,8 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes structureModel.getOriginalCategoryPath().getPath()); assertEquals(0, structureModel.getNumComponents());// no components assertEquals(1, structureModel.getRowCount());// blank row - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertLength(0); assertActualAlignment(1); assertEquals(0, structureModel.getNumSelectedComponentRows()); @@ -83,7 +86,9 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes assertLength(2); assertActualAlignment(1); - pressButtonByName(getPanel(), "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); assertEquals(2, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -105,8 +110,12 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes waitForSwing(); - pressButtonByName(getPanel(), "Internally Aligned"); - pressButtonByName(getPanel(), "Machine Minimum Alignment"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); + + pressButtonByName(getPanel(), "Machine Alignment"); + assertIsMachineAligned(); assertEquals(2, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -130,19 +139,22 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes waitForSwing(); - pressButtonByName(editorPanel, "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); + JTextField minAlignField = - (JTextField) getInstanceField("minAlignValueTextField", editorPanel); + (JTextField) getInstanceField("explicitAlignTextField", editorPanel); assertNotNull(minAlignField); - JRadioButton byValueMinAlignButton = - (JRadioButton) getInstanceField("byValueMinAlignButton", editorPanel); - assertNotNull(byValueMinAlignButton); - pressButton(byValueMinAlignButton); - assertEquals("4", minAlignField.getText()); + JRadioButton explicitAlignButton = + (JRadioButton) getInstanceField("explicitAlignButton", editorPanel); + assertNotNull(explicitAlignButton); + pressButton(explicitAlignButton); + assertEquals("8", minAlignField.getText()); // toy.cspec machine alignment is default value assertEquals(false, structureModel.viewComposite.isDefaultAligned()); assertEquals(false, structureModel.viewComposite.isMachineAligned()); - assertEquals(4, structureModel.getMinimumAlignment()); + assertEquals(8, structureModel.getExplicitMinimumAlignment()); assertEquals(2, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -151,9 +163,9 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes checkRow(0, 0, 1, "db", ByteDataType.dataType, "", ""); checkRow(1, 1, 1, "char", CharDataType.dataType, "", ""); checkBlankRow(2); - checkRow(3, 4, 0, "ddw[0]", DWordDataType.dataType, "", ""); - assertLength(4); - assertActualAlignment(4); + checkRow(3, 8, 0, "ddw[0]", DWordDataType.dataType, "", ""); + assertLength(8); + assertActualAlignment(8); } @Test @@ -183,8 +195,8 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes public void checkByValueAlignedStructure(int value, int alignment, int length) throws Exception { - emptyStructure.setInternallyAligned(true); - emptyStructure.setMinimumAlignment(value); + emptyStructure.setPackingEnabled(true); + emptyStructure.setExplicitMinimumAlignment(value); emptyStructure.add(ByteDataType.dataType); emptyStructure.add(CharDataType.dataType); @@ -193,19 +205,19 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes init(emptyStructure, pgmRootCat, false); CompEditorPanel editorPanel = (CompEditorPanel) getPanel(); - JRadioButton byValueMinAlignButton = - (JRadioButton) getInstanceField("byValueMinAlignButton", editorPanel); - assertNotNull(byValueMinAlignButton); - assertEquals(true, byValueMinAlignButton.isSelected()); + JRadioButton explicitAlignButton = + (JRadioButton) getInstanceField("explicitAlignButton", editorPanel); + assertNotNull(explicitAlignButton); + assertEquals(true, explicitAlignButton.isSelected()); JTextField minAlignField = - (JTextField) getInstanceField("minAlignValueTextField", editorPanel); + (JTextField) getInstanceField("explicitAlignTextField", editorPanel); assertNotNull(minAlignField); assertEquals("" + value, minAlignField.getText()); assertEquals(false, structureModel.viewComposite.isDefaultAligned()); assertEquals(false, structureModel.viewComposite.isMachineAligned()); - assertEquals(value, structureModel.getMinimumAlignment()); + assertEquals(value, structureModel.getExplicitMinimumAlignment()); assertEquals(2, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); @@ -220,8 +232,8 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes @Test public void testDefaultAlignedPacked1Structure() throws Exception { int value = 1; - emptyStructure.setInternallyAligned(true); - emptyStructure.setPackingValue(value); + emptyStructure.setPackingEnabled(true); + emptyStructure.setExplicitPackingValue(value); init(emptyStructure, pgmRootCat, false); CompEditorPanel editorPanel = (CompEditorPanel) getPanel(); @@ -231,17 +243,17 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes addFlexDataType(DWordDataType.dataType, null, null); JRadioButton byValuePackingButton = - (JRadioButton) findComponentByName(editorPanel, "By Value Packing"); + (JRadioButton) findComponentByName(editorPanel, "Explicit Packing"); assertNotNull(byValuePackingButton); JTextField packingValueField = (JTextField) findComponentByName(editorPanel, "Packing Value"); assertNotNull(packingValueField); assertEquals(true, byValuePackingButton.isSelected()); - assertEquals("" + value, packingValueField.getText()); + assertEquals(Integer.toString(value), packingValueField.getText()); assertEquals(true, structureModel.viewComposite.isDefaultAligned()); assertEquals(false, structureModel.viewComposite.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, structureModel.getMinimumAlignment()); + assertEquals(false, structureModel.viewComposite.hasExplicitMinimumAlignment()); assertEquals(2, structureModel.getNumComponents()); assertEquals(4, structureModel.getRowCount()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions2Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions2Test.java index 4ecc69eae1..f9398846bc 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions2Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions2Test.java @@ -243,7 +243,7 @@ public class StructureEditorLockedActions2Test extends AbstractStructureEditorLo DataType dt2 = getDataType(2); DataType dt7 = getDataType(7); - invoke(duplicateMultipleAction); + invoke(duplicateMultipleAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); badInput(dialog, 3); @@ -270,7 +270,7 @@ public class StructureEditorLockedActions2Test extends AbstractStructureEditorLo boolean commit = false; txId = program.startTransaction("Modify Program"); try { - simpleStructure.setInternallyAligned(true); + simpleStructure.setPackingEnabled(true); commit = true; } finally { @@ -288,7 +288,7 @@ public class StructureEditorLockedActions2Test extends AbstractStructureEditorLo DataType originalDt4 = getDataType(4); // Make selected components into internal structure. - invoke(createInternalStructureAction); + invoke(createInternalStructureAction, false); // Specify name for structure. JDialog inputDialog = waitForJDialog("Specify the Structure's Name"); @@ -331,7 +331,7 @@ public class StructureEditorLockedActions2Test extends AbstractStructureEditorLo DataType originalDt4 = getDataType(4); // Make selected components into internal structure. - invoke(createInternalStructureAction); + invoke(createInternalStructureAction, false); // Specify name for structure. JDialog inputDialog = waitForJDialog("Specify the Structure's Name"); @@ -365,7 +365,7 @@ public class StructureEditorLockedActions2Test extends AbstractStructureEditorLo DataType originalDt4 = getDataType(4); // Make selected components into internal structure. - invoke(createInternalStructureAction); + invoke(createInternalStructureAction, false); // Specify name for structure. JDialog inputDialog = waitForJDialog("Specify the Structure's Name"); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions3Test.java index 804272686b..8ae4c1ac90 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions3Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions3Test.java @@ -47,7 +47,7 @@ public class StructureEditorLockedActions3Test extends AbstractStructureEditorLo DataType originalDt4 = getDataType(4); // Make selected components into internal structure. - invoke(createInternalStructureAction); + invoke(createInternalStructureAction, false); // Specify name for structure. InputDialog inputDialog = waitForDialogComponent(InputDialog.class); @@ -173,7 +173,7 @@ public class StructureEditorLockedActions3Test extends AbstractStructureEditorLo assertEquals(29, getModel().getLength()); assertEquals(8, getModel().getNumComponents()); setSelection(new int[] { 4 }); - invoke(fav); + invoke(fav, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 8); @@ -213,7 +213,7 @@ public class StructureEditorLockedActions3Test extends AbstractStructureEditorLo // setSelection(new int[] {1}); // DataType dt1 = getDataType(1); // assertTrue(getDataType(1).isEquivalent(new WordDataType())); - // invoke(pointerAction); + // invoke(pointerAction, false); // dialog = (NumberInputDialog)env.waitForDialogComponent(NumberInputDialog.class, 1000); // assertNotNull(dialog); // cancelInput(dialog, 2); @@ -259,7 +259,7 @@ public class StructureEditorLockedActions3Test extends AbstractStructureEditorLo // DataType dt1 = getDataType(1); // assertTrue(getDataType(1).isEquivalent(new StringDataType())); // assertEquals(5, getModel().getComponent(1).getLength()); - // invoke(pointerAction); + // invoke(pointerAction, false); // dialog = (NumberInputDialog)env.waitForDialogComponent(NumberInputDialog.class, 1000); // assertNotNull(dialog); // okInput(dialog, 8); @@ -299,7 +299,7 @@ public class StructureEditorLockedActions3Test extends AbstractStructureEditorLo // // setSelection(new int[] {10}); // DataType dt10 = getDataType(10); - // invoke(pointerAction); + // invoke(pointerAction, false); // dialog = (NumberInputDialog)env.waitForDialogComponent(NumberInputDialog.class, 1000); // assertNotNull(dialog); // okInput(dialog, 2); @@ -321,7 +321,7 @@ public class StructureEditorLockedActions3Test extends AbstractStructureEditorLo // // setSelection(new int[] {15}); // DataType dt15 = getDataType(15); - // invoke(pointerAction); + // invoke(pointerAction, false); // dialog = (NumberInputDialog)env.waitForDialogComponent(NumberInputDialog.class, 1000); // assertNotNull(dialog); // okInput(dialog, 4); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions4Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions4Test.java index 2b1ceeb8ff..6893ef3200 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions4Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedActions4Test.java @@ -36,7 +36,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo DataType dt8 = getDataType(8); // Make array of 7 bytes - invoke(arrayAction); + invoke(arrayAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); assertEquals("Enter Number", dialog.getTitle()); @@ -65,7 +65,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo checkSelection(new int[] { 1 }); // Make array of 5 quadwords - invoke(arrayAction); + invoke(arrayAction, false); waitForPostedSwingRunnables(); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); @@ -109,7 +109,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo assertEquals(getLength(16), dt16Len); assertEquals(getDataType(16), dt16); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); badInput(dialog, 20); @@ -126,7 +126,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo assertEquals(getLength(2), dt16Len); assertEquals(getDataType(2), dt16); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 10); @@ -180,7 +180,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo assertEquals(getLength(8), dt8Len); assertEquals(getDataType(8), dt8); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 7); @@ -194,7 +194,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo assertEquals(getLength(2), dt8Len); assertEquals(getDataType(2), dt8); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 6); @@ -241,7 +241,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo assertEquals(1, getLength(1)); assertEquals(getDataType(1), dt1); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); badInput(dialog, 7); @@ -255,7 +255,7 @@ public class StructureEditorLockedActions4Test extends AbstractStructureEditorLo assertEquals(1, getLength(1)); assertEquals(getDataType(1), dt1); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); badInput(dialog, 10); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedCellEditTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedCellEditTest.java index 6faa392580..030538916b 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedCellEditTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorLockedCellEditTest.java @@ -523,7 +523,7 @@ public class StructureEditorLockedCellEditTest extends AbstractStructureEditorTe public void testEditDataTypeNotSelf() throws Exception { Structure testStruct = new StructureDataType("testStruct", 20); - testStruct.setInternallyAligned(false); + testStruct.setPackingEnabled(false); DataTypeManager dtm = program.getDataTypeManager(); txId = program.startTransaction("Add testStruct"); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions1Test.java index c9020aa290..92c8f8205f 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions1Test.java @@ -46,7 +46,7 @@ public class StructureEditorUnlockedActions1Test assertEquals(getDataType(3), DataType.DEFAULT); assertEquals(getDataType(4), dt3); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); @@ -60,7 +60,7 @@ public class StructureEditorUnlockedActions1Test assertEquals(getDataType(3), dt3); setSelection(new int[] { 2 }); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions2Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions2Test.java index ea4dd50efe..482eb80345 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions2Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions2Test.java @@ -165,7 +165,7 @@ public class StructureEditorUnlockedActions2Test assertEquals(getDataType(3), DataType.DEFAULT); assertEquals(getDataType(4), dt3); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); @@ -179,7 +179,7 @@ public class StructureEditorUnlockedActions2Test assertEquals(getDataType(3), dt3); setSelection(new int[] { 2 }); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions3Test.java index c91b9d021d..82fa2c4e00 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions3Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions3Test.java @@ -44,7 +44,7 @@ public class StructureEditorUnlockedActions3Test DataType dt2 = getDataType(2);// word DataType dt7 = getDataType(7);// SimpleUnion - invoke(duplicateMultipleAction); + invoke(duplicateMultipleAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); @@ -73,7 +73,7 @@ public class StructureEditorUnlockedActions3Test DataType dt0 = getDataType(0); DataType dt1 = getDataType(1); - invoke(duplicateMultipleAction); + invoke(duplicateMultipleAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions4Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions4Test.java index 0eee6ce58e..ab011f5bf1 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions4Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions4Test.java @@ -26,7 +26,6 @@ import org.junit.Test; import docking.widgets.dialogs.NumberInputDialog; import ghidra.program.model.data.*; import ghidra.util.exception.UsrException; -import ghidra.util.task.TaskMonitor; public class StructureEditorUnlockedActions4Test extends AbstractStructureEditorUnlockedActionsTest { @@ -56,7 +55,7 @@ public class StructureEditorUnlockedActions4Test invoke(applyAction); assertTrue(complexStructure.isEquivalent(model.viewComposite)); assertEquals(1, complexStructure.getLength()); - assertTrue(complexStructure.isNotYetDefined()); + assertTrue(complexStructure.isZeroLength()); } @Test @@ -74,7 +73,7 @@ public class StructureEditorUnlockedActions4Test assertEquals(2, model.getComponent(5).getLength()); // Make array of 3 pointers - invoke(arrayAction); + invoke(arrayAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 3); @@ -222,7 +221,7 @@ public class StructureEditorUnlockedActions4Test runSwing(() -> { try { model.clearSelectedComponents(); - model.deleteSelectedComponents(TaskMonitor.DUMMY); + model.deleteSelectedComponents(); } catch (UsrException e) { failWithException("Unexpected error", e); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions5Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions5Test.java index de327790b1..0ca919016d 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions5Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions5Test.java @@ -87,6 +87,7 @@ public class StructureEditorUnlockedActions5Test invoke(applyAction); assertTrue(simpleStructure.isEquivalent(model.viewComposite)); assertTrue(simpleStructure.isNotYetDefined()); + assertTrue(simpleStructure.isZeroLength()); assertTrue(viewCopy.isEquivalent(model.viewComposite)); // Is now allowed // assertEquals( @@ -132,7 +133,7 @@ public class StructureEditorUnlockedActions5Test assertTrue(dt2 instanceof WordDataType); // Cancel the array dialog - invoke(arrayAction); + invoke(arrayAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); cancelInput(dialog); @@ -163,7 +164,7 @@ public class StructureEditorUnlockedActions5Test assertEquals(getDataType(3), DataType.DEFAULT); assertEquals(getDataType(4), dt3); - invoke(action); + invoke(action, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); cancelInput(dialog); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions6Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions6Test.java index 7f9609cdc4..61989d7a89 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions6Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedActions6Test.java @@ -43,7 +43,7 @@ public class StructureEditorUnlockedActions6Test assertTrue(dt15 instanceof Array); // Make array of 2 arrays - invoke(arrayAction); + invoke(arrayAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); @@ -70,7 +70,7 @@ public class StructureEditorUnlockedActions6Test assertEquals("dword", dt3.getDisplayName()); // Make array of 5 quadwords - invoke(arrayAction); + invoke(arrayAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 5); @@ -88,6 +88,7 @@ public class StructureEditorUnlockedActions6Test init(emptyStructure, pgmRootCat); int originalLength = 0; assertTrue(emptyStructure.isNotYetDefined()); + assertTrue(emptyStructure.isZeroLength()); int newLength = 5; assertEquals(originalLength, model.getLength()); @@ -151,7 +152,7 @@ public class StructureEditorUnlockedActions6Test assertEquals(0, model.getLength()); assertEquals(0, model.getNumComponents()); - invoke(fav); + invoke(fav, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 7); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedEnablementTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedEnablementTest.java index 54556b06c6..f1d07eaf13 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedEnablementTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/StructureEditorUnlockedEnablementTest.java @@ -15,8 +15,7 @@ */ package ghidra.app.plugin.core.compositeeditor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import org.junit.Assert; import org.junit.Test; @@ -32,7 +31,7 @@ public class StructureEditorUnlockedEnablementTest extends AbstractStructureEdit try { DataTypeManager dataTypeManager = cat.getDataTypeManager(); if (dt.getDataTypeManager() != dataTypeManager) { - dt = (Structure) dt.clone(dataTypeManager); + dt = dt.clone(dataTypeManager); } CategoryPath categoryPath = cat.getCategoryPath(); if (!dt.getCategoryPath().equals(categoryPath)) { @@ -336,7 +335,7 @@ public class StructureEditorUnlockedEnablementTest extends AbstractStructureEdit assertEquals("word", getDataType(3).getDisplayName()); assertTrue(!editBitFieldAction.isEnabled()); - structureModel.setAligned(true); + structureModel.setPackingType(PackingType.DEFAULT, 0); // Edit Bitfield action not enabled for Aligned mode setSelection(new int[] { 1 }); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions1Test.java index f8b6ae5cb2..867c4e1e5b 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions1Test.java @@ -26,8 +26,6 @@ import org.junit.Test; import docking.widgets.dialogs.NumberInputDialog; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; -import ghidra.util.task.TaskMonitor; public class UnionEditorActions1Test extends AbstractUnionEditorTest { @@ -44,10 +42,8 @@ public class UnionEditorActions1Test extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(emptyUnion.getName(), model.getCompositeName()); @@ -83,10 +79,8 @@ public class UnionEditorActions1Test extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { model.getNumComponents() }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(8); assertEquals(simpleUnion.getName(), model.getCompositeName()); @@ -283,8 +277,8 @@ public class UnionEditorActions1Test extends AbstractUnionEditorTest { assertEquals(0, model.getLength()); assertEquals(0, model.getNumComponents()); - invoke(fav); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(fav, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 7); dialog = null; @@ -377,8 +371,8 @@ public class UnionEditorActions1Test extends AbstractUnionEditorTest { assertTrue(getDataType(2).isEquivalent(new CharDataType())); assertEquals(getDataType(3), dt3); - invoke(action); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(action, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); cancelInput(dialog); dialog = null; @@ -668,7 +662,7 @@ public class UnionEditorActions1Test extends AbstractUnionEditorTest { DataType dt3 = getDataType(3); // Cancel the array dialog - invoke(arrayAction); + invoke(arrayAction, false); dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); cancelInput(dialog); @@ -766,7 +760,7 @@ public class UnionEditorActions1Test extends AbstractUnionEditorTest { init(complexUnion, pgmTestCat, false); setSelection(new int[] { 3, 4 }); - model.deleteSelectedComponents(TaskMonitor.DUMMY); + model.deleteSelectedComponents(); DataType viewCopy = model.viewComposite.clone(null); assertFalse(complexUnion.isEquivalent(model.viewComposite)); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions2Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions2Test.java index c18010746e..0b14238243 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions2Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions2Test.java @@ -46,8 +46,8 @@ public class UnionEditorActions2Test extends AbstractUnionEditorTest { assertTrue(getDataType(2).isEquivalent(new CharDataType())); assertEquals(getDataType(3), dt3); - invoke(action); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(action, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 7); dialog = null; @@ -59,8 +59,8 @@ public class UnionEditorActions2Test extends AbstractUnionEditorTest { assertTrue(getDataType(2).isEquivalent(new StringDataType())); assertEquals(getDataType(3), dt3); - invoke(action); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(action, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 10); dialog = null; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions3Test.java index 3f4f14deb5..a7ac6f9a88 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions3Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions3Test.java @@ -35,8 +35,8 @@ public class UnionEditorActions3Test extends AbstractUnionEditorTest { DataType dt11 = getDataType(11); // Make array of 2 arrays - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); dialog = null; @@ -58,8 +58,8 @@ public class UnionEditorActions3Test extends AbstractUnionEditorTest { DataType dt3 = getDataType(3); // Make array of 5 quadwords - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 5); dialog = null; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions4Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions4Test.java index a00d4bf516..5af5f6707d 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions4Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorActions4Test.java @@ -36,8 +36,8 @@ public class UnionEditorActions4Test extends AbstractUnionEditorTest { assertEquals(2, model.getComponent(4).getLength()); // Make array of 3 pointers - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 3); dialog = null; @@ -59,8 +59,8 @@ public class UnionEditorActions4Test extends AbstractUnionEditorTest { DataType dt2 = getDataType(2); DataType dt3 = getDataType(3); - invoke(duplicateMultipleAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(duplicateMultipleAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 5); dialog = null; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorAlignmentTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorAlignmentTest.java index 3e99c43f12..db815aad5f 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorAlignmentTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorAlignmentTest.java @@ -23,7 +23,6 @@ import javax.swing.JTextField; import org.junit.Test; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @@ -40,10 +39,8 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { unionModel.getOriginalCategoryPath().getPath()); assertEquals(0, unionModel.getNumComponents());// no components assertEquals(1, unionModel.getRowCount());// blank row - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertLength(0); assertActualAlignment(1); assertEquals(0, unionModel.getNumSelectedComponentRows()); @@ -88,7 +85,9 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { addDataType(new FloatDataType()); addDataType(arrayDt); - pressButtonByName(getPanel(), "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); assertEquals(true, unionModel.viewComposite.isDefaultAligned()); assertEquals(3, unionModel.getNumComponents()); @@ -102,7 +101,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testEnablementDefaultAlignedUnion() throws Exception { - emptyUnion.setInternallyAligned(true); + emptyUnion.setPackingEnabled(true); init(emptyUnion, pgmRootCat, false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); @@ -112,16 +111,16 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { // Check enablement. CompositeEditorTableAction[] pActions = provider.getActions(); - for (int i = 0; i < pActions.length; i++) { - if ((pActions[i] instanceof FavoritesAction) || - (pActions[i] instanceof CycleGroupAction) || - (pActions[i] instanceof EditFieldAction) || - (pActions[i] instanceof PointerAction) || - (pActions[i] instanceof HexNumbersAction) || (pActions[i] instanceof ApplyAction)) { - checkEnablement(pActions[i], true); + for (CompositeEditorTableAction pAction : pActions) { + if ((pAction instanceof FavoritesAction) || + (pAction instanceof CycleGroupAction) || + (pAction instanceof EditFieldAction) || + (pAction instanceof PointerAction) || + (pAction instanceof HexNumbersAction) || (pAction instanceof ApplyAction)) { + checkEnablement(pAction, true); } else { - checkEnablement(pActions[i], false); + checkEnablement(pAction, false); } } @@ -144,8 +143,11 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { addDataType(new FloatDataType()); addDataType(arrayDt); - pressButtonByName(getPanel(), "Internally Aligned"); - pressButtonByName(getPanel(), "Machine Minimum Alignment"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); + + pressButtonByName(getPanel(), "Machine Alignment"); assertEquals(true, unionModel.viewComposite.isMachineAligned()); assertEquals(3, unionModel.getNumComponents()); @@ -166,16 +168,19 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { addDataType(new FloatDataType()); addDataType(arrayDt); - pressButtonByName(getPanel(), "Internally Aligned"); - pressButtonByName(getPanel(), "By Value Minimum Alignment"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> enable packing + assertIsPackingEnabled(true); + assertDefaultPacked(); + + pressButtonByName(getPanel(), "Explicit Alignment"); JTextField minAlignField = - (JTextField) findComponentByName(getPanel(), "Minimum Alignment Value"); - assertEquals("4", minAlignField.getText()); + (JTextField) findComponentByName(getPanel(), "Explicit Alignment Value"); + assertEquals("8", minAlignField.getText()); // toy.cspec machine alignment is default value assertEquals(false, unionModel.viewComposite.isDefaultAligned()); assertEquals(false, unionModel.viewComposite.isMachineAligned()); - assertEquals(4, unionModel.getMinimumAlignment()); + assertEquals(8, unionModel.getExplicitMinimumAlignment()); assertEquals(3, unionModel.getNumComponents()); assertEquals(4, unionModel.getRowCount()); @@ -183,7 +188,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { checkRow(1, 4, "float", new FloatDataType(), "", ""); checkRow(2, 5, "char[5]", arrayDt, "", ""); assertLength(8); - assertActualAlignment(4); + assertActualAlignment(8); } @Test @@ -211,9 +216,9 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { checkByValueAlignedUnion(16, 16, 16); } - public void checkByValueAlignedUnion(int value, int alignment, int length) throws Exception { - emptyUnion.setInternallyAligned(true); - emptyUnion.setMinimumAlignment(value); + public void checkByValueAlignedUnion(int minAlignment, int alignment, int length) throws Exception { + emptyUnion.setPackingEnabled(true); + emptyUnion.setExplicitMinimumAlignment(minAlignment); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -223,15 +228,15 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { init(emptyUnion, pgmRootCat, false); JRadioButton byValueButton = - (JRadioButton) findComponentByName(getPanel(), "By Value Minimum Alignment"); + (JRadioButton) findComponentByName(getPanel(), "Explicit Alignment"); assertEquals(true, byValueButton.isSelected()); JTextField minAlignField = - (JTextField) findComponentByName(getPanel(), "Minimum Alignment Value"); - assertEquals("" + value, minAlignField.getText()); + (JTextField) findComponentByName(getPanel(), "Explicit Alignment Value"); + assertEquals("" + minAlignment, minAlignField.getText()); assertEquals(false, unionModel.viewComposite.isDefaultAligned()); assertEquals(false, unionModel.viewComposite.isMachineAligned()); - assertEquals(value, unionModel.getMinimumAlignment()); + assertEquals(minAlignment, unionModel.getExplicitMinimumAlignment()); assertEquals(3, unionModel.getNumComponents()); assertEquals(4, unionModel.getRowCount()); @@ -244,8 +249,8 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testTurnOffAlignmentInUnion() throws Exception { - emptyUnion.setInternallyAligned(true); - emptyUnion.setMinimumAlignment(8); + emptyUnion.setPackingEnabled(true); + emptyUnion.setExplicitMinimumAlignment(8); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -255,15 +260,15 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { init(emptyUnion, pgmRootCat, false); JRadioButton byValueButton = - (JRadioButton) findComponentByName(getPanel(), "By Value Minimum Alignment"); + (JRadioButton) findComponentByName(getPanel(), "Explicit Alignment"); assertEquals(true, byValueButton.isSelected()); JTextField minAlignField = - (JTextField) findComponentByName(getPanel(), "Minimum Alignment Value"); + (JTextField) findComponentByName(getPanel(), "Explicit Alignment Value"); assertEquals("8", minAlignField.getText()); assertEquals(false, unionModel.viewComposite.isDefaultAligned()); assertEquals(false, unionModel.viewComposite.isMachineAligned()); - assertEquals(8, unionModel.getMinimumAlignment()); + assertEquals(8, unionModel.getExplicitMinimumAlignment()); assertEquals(3, unionModel.getNumComponents()); assertEquals(4, unionModel.getRowCount()); @@ -272,14 +277,14 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { checkRow(2, 5, "char[5]", arrayDt, "", ""); assertLength(8); assertActualAlignment(8); - assertEquals(true, unionModel.isAligned()); + assertEquals(true, unionModel.isPackingEnabled()); - pressButtonByName(getPanel(), "Internally Aligned"); + pressButtonByName(getPanel(), "Packing Enablement"); // toggle -> disable packing - assertEquals(false, unionModel.isAligned()); + assertEquals(false, unionModel.isPackingEnabled()); assertEquals(true, unionModel.viewComposite.isDefaultAligned()); assertEquals(false, unionModel.viewComposite.isMachineAligned()); - assertEquals(Composite.DEFAULT_ALIGNMENT_VALUE, unionModel.getMinimumAlignment()); + assertEquals(false, unionModel.viewComposite.hasExplicitMinimumAlignment()); assertEquals(3, unionModel.getNumComponents()); assertEquals(4, unionModel.getRowCount()); @@ -292,7 +297,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testInsertUnaligned1() throws Exception { - emptyUnion.setInternallyAligned(false); + emptyUnion.setPackingEnabled(false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -325,7 +330,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testInsertUnaligned2() throws Exception { - emptyUnion.setInternallyAligned(false); + emptyUnion.setPackingEnabled(false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -358,7 +363,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testInsertUnaligned3() throws Exception { - emptyUnion.setInternallyAligned(false); + emptyUnion.setPackingEnabled(false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -391,7 +396,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testReplaceUnaligned1() throws Exception { - emptyUnion.setInternallyAligned(false); + emptyUnion.setPackingEnabled(false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -423,7 +428,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testReplaceUnaligned2() throws Exception { - emptyUnion.setInternallyAligned(false); + emptyUnion.setPackingEnabled(false); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -456,7 +461,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testInsertAligned1() throws Exception { - emptyUnion.setInternallyAligned(true); + emptyUnion.setPackingEnabled(true); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -489,7 +494,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testInsertAligned2() throws Exception { - emptyUnion.setInternallyAligned(true); + emptyUnion.setPackingEnabled(true); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -522,7 +527,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testInsertAligned3() throws Exception { - emptyUnion.setInternallyAligned(true); + emptyUnion.setPackingEnabled(true); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -555,7 +560,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testReplaceAligned1() throws Exception { - emptyUnion.setInternallyAligned(true); + emptyUnion.setPackingEnabled(true); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); @@ -587,7 +592,7 @@ public class UnionEditorAlignmentTest extends AbstractUnionEditorTest { @Test public void testReplaceAligned2() throws Exception { - emptyUnion.setInternallyAligned(true); + emptyUnion.setPackingEnabled(true); DataType arrayDt = new ArrayDataType(new CharDataType(), 5, 1); emptyUnion.add(new ByteDataType()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorDnDTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorDnDTest.java index 39ae852454..450e8b9245 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorDnDTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorDnDTest.java @@ -63,7 +63,7 @@ public class UnionEditorDnDTest extends AbstractUnionEditorTest { assertNotNull(dt4); addAtPoint(dt4, 3, 0); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 25); dialog = null; @@ -106,7 +106,7 @@ public class UnionEditorDnDTest extends AbstractUnionEditorTest { DataType dt4 = model.getOriginalDataTypeManager().getDataType("/string"); assertNotNull(dt4); insertAtPoint(dt4, 0, 0); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 25); dialog = null; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorNotifiedTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorNotifiedTest.java index 006ea5d25e..56759dde85 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorNotifiedTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/UnionEditorNotifiedTest.java @@ -25,11 +25,9 @@ import org.junit.Assert; import org.junit.Test; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskMonitor; -import ghidra.util.task.TaskMonitorAdapter; public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { @@ -40,7 +38,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { try { DataTypeManager dataTypeManager = cat.getDataTypeManager(); if (dt.getDataTypeManager() != dataTypeManager) { - dt = (Union) dt.clone(dataTypeManager); + dt = dt.clone(dataTypeManager); } CategoryPath categoryPath = cat.getCategoryPath(); if (!dt.getCategoryPath().equals(categoryPath)) { @@ -61,10 +59,8 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { installProvider(new UnionEditorProvider(plugin, unionDt, showInHex)); model = provider.getModel(); }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); startTransaction("Modify Program"); } @@ -86,7 +82,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { init(complexUnion, pgmTestCat, false); assertEquals("/aa/bb", getDataType(20).getCategoryPath().getPath()); - pgmTestCat.moveCategory(pgmBbCat, TaskMonitorAdapter.DUMMY_MONITOR); + pgmTestCat.moveCategory(pgmBbCat, TaskMonitor.DUMMY); waitForSwing(); assertEquals("/testCat/bb", getDataType(20).getCategoryPath().getPath()); } @@ -101,7 +97,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { init(simpleUnion, pgmBbCat, false); assertEquals(pgmBbCat.getCategoryPathName(), model.getOriginalCategoryPath().getPath()); - pgmTestCat.moveCategory(pgmBbCat, TaskMonitorAdapter.DUMMY_MONITOR); + pgmTestCat.moveCategory(pgmBbCat, TaskMonitor.DUMMY); waitForSwing(); assertTrue(model.getOriginalCategoryPath().getPath().startsWith( pgmTestCat.getCategoryPathName())); @@ -142,9 +138,9 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { DataType dt18 = getDataType(18).clone(programDTM); DataType dt20 = getDataType(20).clone(programDTM); SwingUtilities.invokeLater(() -> { - programDTM.remove(complexUnion, TaskMonitorAdapter.DUMMY_MONITOR); + programDTM.remove(complexUnion, TaskMonitor.DUMMY); programDTM.getCategory(pgmRootCat.getCategoryPath()).removeCategory("Temp", - TaskMonitorAdapter.DUMMY_MONITOR); + TaskMonitor.DUMMY); }); waitForSwing(); @@ -250,7 +246,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { DataType origCopy = complexUnion.clone(null); // Verify the Reload Union Editor? dialog is displayed. - dialog = env.waitForWindow("Reload Union Editor?", 1000); + dialog = waitForWindow("Reload Union Editor?"); assertNotNull(dialog); pressButtonByText(dialog, "Yes"); dialog.dispose(); @@ -287,7 +283,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { waitForSwing(); // Verify the Reload Union Editor? dialog is displayed. - dialog = env.waitForWindow("Reload Union Editor?", 1000); + dialog = waitForWindow("Reload Union Editor?"); assertNotNull(dialog); pressButtonByText(dialog, "No"); dialog.dispose(); @@ -374,7 +370,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { assertEquals(21, model.getNumComponents()); SwingUtilities.invokeLater(() -> complexUnion.getDataTypeManager().remove( - simpleStructure, TaskMonitorAdapter.DUMMY_MONITOR)); + simpleStructure, TaskMonitor.DUMMY)); waitForSwing(); assertEquals(15, model.getNumComponents()); } @@ -400,7 +396,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest { assertTrue(simpleUnion.isEquivalent(getDataType(0))); SwingUtilities.invokeLater(() -> simpleUnion.getDataTypeManager().remove(simpleUnion, - TaskMonitorAdapter.DUMMY_MONITOR)); + TaskMonitor.DUMMY)); waitForSwing(); assertEquals(0, model.getNumComponents()); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeStructureTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeStructureTest.java index de6c7ccd4e..63dc787c74 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeStructureTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeStructureTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.*; import org.junit.Test; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; public class ZeroSizeStructureTest extends AbstractStructureEditorTest { @@ -39,10 +38,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(emptyStructure.getName(), model.getCompositeName()); @@ -55,12 +52,10 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { DataType dt = pgmRootCat.getDataType(emptyStructure.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(emptyStructure.getName(), model.getCompositeName()); @@ -76,7 +71,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { DataType dt = pgmBbCat.getDataType(simpleStructure.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(8, model.getNumComponents()); assertEquals(9, model.getRowCount()); @@ -87,10 +82,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 8 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(29); assertEquals(simpleStructure.getName(), model.getCompositeName()); @@ -110,10 +103,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(simpleStructure.getName(), model.getCompositeName()); @@ -125,16 +116,14 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { invoke(applyAction); assertTrue(simpleStructure.isEquivalent(model.viewComposite)); - assertTrue(simpleStructure.isNotYetDefined()); + assertTrue(simpleStructure.isZeroLength()); dt = pgmBbCat.getDataType(simpleStructure.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(simpleStructure.getName(), model.getCompositeName()); @@ -179,7 +168,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { DataType dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -190,10 +179,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -213,10 +200,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -229,12 +214,10 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -280,7 +263,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { DataType dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -291,10 +274,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -314,10 +295,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -330,15 +309,13 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(innerStructure.isEquivalent(model.viewComposite)); - assertTrue(innerStructure.isNotYetDefined()); + assertTrue(innerStructure.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -373,13 +350,13 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { } assertNotNull(innerStructure); assertNotNull(innerTypedef); - assertTrue(!innerTypedef.isNotYetDefined()); + assertTrue(!innerTypedef.isZeroLength()); init(innerStructure, pgmTestCat, false); DataType dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -390,10 +367,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -413,10 +388,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -429,15 +402,13 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(innerStructure.isEquivalent(model.viewComposite)); - assertTrue(innerStructure.isNotYetDefined()); + assertTrue(innerStructure.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -446,7 +417,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(false, applyAction.isEnabled()); // assertStatus("/testCat/innerStructure is contained in /testCat/innerStructureTypedef and can't be changed to a zero size data type."); - assertTrue(innerTypedef.isNotYetDefined()); + assertTrue(innerTypedef.isZeroLength()); assertEquals(1, innerTypedef.getLength()); } @@ -481,7 +452,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { DataType dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -492,10 +463,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(2); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -515,10 +484,8 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); @@ -531,15 +498,13 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest { dt = pgmTestCat.getDataType(innerStructure.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(innerStructure.isEquivalent(model.viewComposite)); - assertTrue(innerStructure.isNotYetDefined()); + assertTrue(innerStructure.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerStructure.getName(), model.getCompositeName()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeUnionTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeUnionTest.java index 15c8e66b58..9e749ea549 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeUnionTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/compositeeditor/ZeroSizeUnionTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.*; import org.junit.Test; import ghidra.program.model.data.*; -import ghidra.program.model.data.Composite.AlignmentType; public class ZeroSizeUnionTest extends AbstractUnionEditorTest { @@ -39,10 +38,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(emptyUnion.getName(), model.getCompositeName()); @@ -55,12 +52,10 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { DataType dt = pgmRootCat.getDataType(emptyUnion.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(emptyUnion.getName(), model.getCompositeName()); @@ -76,7 +71,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { DataType dt = pgmBbCat.getDataType(simpleUnion.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(7, model.getNumComponents()); assertEquals(8, model.getRowCount()); @@ -87,10 +82,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 7 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(8); assertEquals(simpleUnion.getName(), model.getCompositeName()); @@ -110,10 +103,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(simpleUnion.getName(), model.getCompositeName()); @@ -125,18 +116,16 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { invoke(applyAction); assertTrue(simpleUnion.isEquivalent(model.viewComposite)); - assertTrue(simpleUnion.isNotYetDefined()); + assertTrue(simpleUnion.isZeroLength()); dt = pgmBbCat.getDataType(simpleUnion.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(simpleUnion.isEquivalent(model.viewComposite)); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(simpleUnion.getName(), model.getCompositeName()); @@ -179,7 +168,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { DataType dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -190,10 +179,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -213,10 +200,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -229,12 +214,10 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -278,7 +261,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { DataType dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -289,10 +272,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -312,10 +293,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -328,15 +307,13 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(innerUnion.isEquivalent(model.viewComposite)); - assertTrue(innerUnion.isNotYetDefined()); + assertTrue(innerUnion.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -374,7 +351,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { DataType dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -385,10 +362,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -408,10 +383,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -424,15 +397,13 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(innerUnion.isEquivalent(model.viewComposite)); - assertTrue(innerUnion.isNotYetDefined()); + assertTrue(innerUnion.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -470,7 +441,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { DataType dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertFalse(dt.isNotYetDefined()); + assertFalse(dt.isZeroLength()); assertEquals(1, model.getNumComponents()); assertEquals(2, model.getRowCount()); @@ -481,10 +452,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 1 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(1); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -504,10 +473,8 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { assertEquals(0, model.getNumSelectedComponentRows()); assertEquals(1, model.getNumSelectedRows()); checkSelection(new int[] { 0 }); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); @@ -520,15 +487,13 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest { dt = pgmTestCat.getDataType(innerUnion.getName()); assertNotNull(dt); - assertTrue(dt.isNotYetDefined()); + assertTrue(dt.isZeroLength()); assertTrue(innerUnion.isEquivalent(model.viewComposite)); - assertTrue(innerUnion.isNotYetDefined()); + assertTrue(innerUnion.isZeroLength()); - assertIsInternallyAligned(false); - assertPackingValue(Composite.NOT_PACKING); - assertMinimumAlignmentType(AlignmentType.DEFAULT_ALIGNED); - assertMinimumAlignmentValue(Composite.DEFAULT_ALIGNMENT_VALUE); + assertIsPackingEnabled(false); + assertIsDefaultAligned(); assertActualAlignment(1); assertLength(0); assertEquals(innerUnion.getName(), model.getCompositeName()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/editor/EnumEditor1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/editor/EnumEditor1Test.java index 34e4002087..2a2dbce884 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/editor/EnumEditor1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/editor/EnumEditor1Test.java @@ -774,14 +774,14 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest { enumm.add("One", 1); Structure structX = new StructureDataType("StructX", 0); - structX.setInternallyAligned(true); + structX.setPackingEnabled(true); structX.add(new ByteDataType()); structX.add(enumm); structX.add(new ByteDataType()); category.addDataType(structX, DataTypeConflictHandler.DEFAULT_HANDLER); Structure structY = new StructureDataType("StructY", 0); - structY.setInternallyAligned(false); + structY.setPackingEnabled(false); structY.add(new ByteDataType()); structY.add(enumm); category.addDataType(structY, DataTypeConflictHandler.DEFAULT_HANDLER); @@ -815,7 +815,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(intValue, 4); Structure structX = (Structure) category.getDataType("StructX"); - assertTrue(structX.isInternallyAligned()); + assertTrue(structX.isPackingEnabled()); assertEquals(3, structX.getNumComponents()); assertEquals(1, structX.getComponent(0).getLength()); assertEquals(4, structX.getComponent(1).getLength()); @@ -823,7 +823,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(12, structX.getLength()); Structure structY = (Structure) category.getDataType("StructY"); - assertFalse(structY.isInternallyAligned()); + assertFalse(structY.isPackingEnabled()); assertEquals(2, structY.getNumComponents()); assertEquals(1, structY.getComponent(0).getLength()); assertEquals(4, structY.getComponent(1).getLength()); @@ -846,14 +846,14 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest { enumm.setDescription("ABCD"); Structure structX = new StructureDataType("StructX", 0); - structX.setInternallyAligned(true); + structX.setPackingEnabled(true); structX.add(new ByteDataType()); structX.add(enumm); structX.add(new ByteDataType()); category.addDataType(structX, DataTypeConflictHandler.DEFAULT_HANDLER); Structure structY = new StructureDataType("StructY", 0); - structY.setInternallyAligned(false); + structY.setPackingEnabled(false); structY.add(new ByteDataType()); structY.add(enumm); category.addDataType(structY, DataTypeConflictHandler.DEFAULT_HANDLER); @@ -926,7 +926,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(1, value1); Structure structX = (Structure) category.getDataType("StructX"); - assertTrue(structX.isInternallyAligned()); + assertTrue(structX.isPackingEnabled()); assertEquals(3, structX.getNumComponents()); assertEquals(1, structX.getComponent(0).getLength()); assertEquals(4, structX.getComponent(1).getLength()); @@ -934,7 +934,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(12, structX.getLength()); Structure structY = (Structure) category.getDataType("StructY"); - assertFalse(structY.isInternallyAligned()); + assertFalse(structY.isPackingEnabled()); assertEquals(2, structY.getNumComponents()); assertEquals(1, structY.getComponent(0).getLength()); assertEquals(4, structY.getComponent(1).getLength()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPluginTest.java index 5637560c5b..575f6e7370 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datapreview/DataTypePreviewPluginTest.java @@ -180,7 +180,7 @@ public class DataTypePreviewPluginTest extends AbstractGhidraHeadedIntegrationTe plugin.addDataType(ShortDataType.dataType); Structure struct = new StructureDataType("test", 0); - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); struct.add(IntegerDataType.dataType, "intField", ""); struct.add(LongDataType.dataType, "longField", ""); struct.add(ShortDataType.dataType, "shortField", ""); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorEnablementTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorEnablementTest.java index b8131ace29..de41b808dd 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorEnablementTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorEnablementTest.java @@ -15,8 +15,7 @@ */ package ghidra.app.plugin.core.stackeditor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import org.junit.Test; @@ -26,10 +25,6 @@ import ghidra.program.model.data.Pointer; public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { - /** - * Constructor for StackEditorLockedActionsTest. - * @param name the testcase name. - */ public PositiveStackEditorEnablementTest() { super(true); } @@ -52,13 +47,13 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { assertEquals(stackModel.getTypeName(), "Stack"); // Check enablement. - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -83,13 +78,13 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { assertEquals(stackModel.getTypeName(), "Stack"); // Check enablement. - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } @@ -97,9 +92,9 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement. int numBytes = getModel().getMaxReplaceLength(0); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); @@ -108,17 +103,17 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { if (offset < 0 && offset > paramOffset) { enabled = false; } - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof PointerAction) || - (actions[i] instanceof HexNumbersAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof PointerAction) || + (action instanceof HexNumbersAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -143,49 +138,49 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { setSelection(new int[] { 19 });// undefined (no variable here). int numBytes = getModel().getMaxReplaceLength(19); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } setSelection(new int[] { 14 });// pointer numBytes = getModel().getMaxReplaceLength(14); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = (len <= numBytes) // && !(favDt instanceof TerminatedStringDataType) // && !(favDt instanceof TerminatedUnicodeDataType) ; - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof ArrayAction) || (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof ArrayAction) || (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -197,24 +192,24 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on first component selected. model.setSelection(new int[] { 0 }); int numBytes = getModel().getMaxReplaceLength(0); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof ArrayAction) || - (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof ArrayAction) || + (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -226,23 +221,23 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on central component selected. model.setSelection(new int[] { 1 }); int numBytes = getModel().getMaxReplaceLength(1); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof ArrayAction) || (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof ArrayAction) || (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -254,24 +249,24 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on last component selected. model.setSelection(new int[] { model.getNumComponents() - 1 }); int numBytes = getModel().getMaxReplaceLength(model.getNumComponents() - 1); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof ArrayAction) || - (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof ArrayAction) || + (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -282,14 +277,14 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on a contiguous multi-component selection. model.setSelection(new int[] { 2, 3, 4 }); - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || (actions[i] instanceof PointerAction) || - (actions[i] instanceof ClearAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || (action instanceof PointerAction) || + (action instanceof ClearAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -300,13 +295,13 @@ public class PositiveStackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on a non-contiguous multi-component selection. model.setSelection(new int[] { 2, 3, 6, 7 }); - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || (actions[i] instanceof ClearAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || (action instanceof ClearAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorProviderTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorProviderTest.java index 8ce546bf2b..fa3c5166a0 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorProviderTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/PositiveStackEditorProviderTest.java @@ -15,8 +15,7 @@ */ package ghidra.app.plugin.core.stackeditor; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import javax.swing.JTextField; @@ -29,10 +28,6 @@ import ghidra.program.model.data.Pointer; public class PositiveStackEditorProviderTest extends AbstractStackEditorTest { - /** - * Constructor for UnionEditorProviderTest. - * @param name the testcase name. - */ public PositiveStackEditorProviderTest() { super(true); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions1Test.java index 075274f84c..c3aca87f3c 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions1Test.java @@ -24,10 +24,7 @@ import docking.widgets.dialogs.NumberInputDialog; import ghidra.program.model.data.*; public class StackEditorActions1Test extends AbstractStackEditorTest { - /** - * Constructor for StackEditorActionsTest. - * @param name the testcase name. - */ + public StackEditorActions1Test() { super(false); } @@ -54,15 +51,15 @@ public class StackEditorActions1Test extends AbstractStackEditorTest { // Make array of 2 arrays assertEquals("", model.getStatus()); - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 3); assertEquals("", model.getStatus()); dialog = null; waitUntilDialogProviderGone(NumberInputDialog.class, 2000); - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); okInput(dialog, 2); dialog = null; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions2Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions2Test.java index c3f6da101d..7915c5bd48 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions2Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions2Test.java @@ -30,10 +30,7 @@ import ghidra.program.model.listing.StackFrame; import ghidra.program.model.listing.Variable; public class StackEditorActions2Test extends AbstractStackEditorTest { - /** - * Constructor for StackEditorActionsTest. - * @param name the testcase name. - */ + public StackEditorActions2Test() { super(false); } @@ -365,12 +362,12 @@ public class StackEditorActions2Test extends AbstractStackEditorTest { assertEquals(1, model.getComponent(1).getLength()); assertEquals("", model.getStatus()); - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); assertEquals("Enter Number", dialog.getTitle()); badInput(dialog, 5); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); assertEquals("Enter Number", dialog.getTitle()); okInput(dialog, 4); @@ -395,13 +392,13 @@ public class StackEditorActions2Test extends AbstractStackEditorTest { checkSelection(new int[] { 0 }); assertEquals("", model.getStatus()); - invoke(arrayAction); + invoke(arrayAction, false); waitForSwing(); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 2000); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); assertEquals("Enter Number", dialog.getTitle()); badInput(dialog, 2); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 2000); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); assertEquals("Value must be between 1 and 1", dialog.getStatusText()); assertEquals("Enter Number", dialog.getTitle()); @@ -428,8 +425,8 @@ public class StackEditorActions2Test extends AbstractStackEditorTest { // Cancel the array dialog assertEquals("", model.getStatus()); - invoke(arrayAction); - dialog = env.waitForDialogComponent(NumberInputDialog.class, 1000); + invoke(arrayAction, false); + dialog = waitForDialogComponent(NumberInputDialog.class); assertNotNull(dialog); cancelInput(dialog); assertEquals("", model.getStatus()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions4Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions4Test.java index a695cb8d14..a6eca4f12f 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions4Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorActions4Test.java @@ -31,10 +31,7 @@ import ghidra.app.plugin.core.compositeeditor.FavoritesAction; import ghidra.program.model.data.*; public class StackEditorActions4Test extends AbstractStackEditorTest { - /** - * Constructor for StackEditorActionsTest. - * @param name the testcase name. - */ + public StackEditorActions4Test() { super(false); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorCellEditTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorCellEditTest.java index 49f5a2a2c5..986e78b74b 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorCellEditTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorCellEditTest.java @@ -32,10 +32,6 @@ import ghidra.program.model.listing.Variable; public class StackEditorCellEditTest extends AbstractStackEditorTest { - /** - * Constructor for UnionEditorCellEditTest. - * @param name the testcase name. - */ public StackEditorCellEditTest() { super(false); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorDnDTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorDnDTest.java index 24a2796233..2631a85525 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorDnDTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorDnDTest.java @@ -24,10 +24,6 @@ import ghidra.program.model.data.*; public class StackEditorDnDTest extends AbstractStackEditorTest { - /** - * Constructor for StackEditorDnDTest. - * @param name the testcase name. - */ public StackEditorDnDTest() { super(false); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorEnablementTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorEnablementTest.java index 773cec909b..ea93174bab 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorEnablementTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/stackeditor/StackEditorEnablementTest.java @@ -25,10 +25,6 @@ import ghidra.program.model.data.Pointer; public class StackEditorEnablementTest extends AbstractStackEditorTest { - /** - * Constructor for StackEditorLockedActionsTest. - * @param name the testcase name. - */ public StackEditorEnablementTest() { super(false); } @@ -51,13 +47,13 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { assertEquals(stackModel.getTypeName(), "Stack"); // Check enablement. - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -82,13 +78,13 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { assertEquals(stackModel.getTypeName(), "Stack"); // Check enablement. - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } @@ -96,23 +92,23 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement. int numBytes = getModel().getMaxReplaceLength(0); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof PointerAction) || - (actions[i] instanceof HexNumbersAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof PointerAction) || + (action instanceof HexNumbersAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -137,45 +133,45 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { setSelection(new int[] { 19 });// Move to a float int numBytes = getModel().getMaxReplaceLength(19); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof ArrayAction) || - (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof ArrayAction) || + (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } setSelection(new int[] { 5 });// Move to a pointer numBytes = getModel().getMaxReplaceLength(5); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); - checkEnablement(actions[i], true); + checkEnablement(action, true); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof ArrayAction) || (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof ArrayAction) || (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -187,24 +183,24 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on first component selected. runSwing(() -> model.setSelection(new int[] { 0 })); int numBytes = getModel().getMaxReplaceLength(0); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof ArrayAction) || - (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof ArrayAction) || + (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -217,23 +213,23 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { runSwing(() -> model.setSelection(new int[] { 1 })); int numBytes = getModel().getMaxReplaceLength(1); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof ArrayAction) || (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof ArrayAction) || (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -245,24 +241,24 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on last component selected. runSwing(() -> model.setSelection(new int[] { model.getNumComponents() - 1 })); int numBytes = getModel().getMaxReplaceLength(model.getNumComponents() - 1); - for (int i = 0; i < actions.length; i++) { - if (actions[i] instanceof FavoritesAction) { - FavoritesAction fav = (FavoritesAction) actions[i]; + for (CompositeEditorTableAction action : actions) { + if (action instanceof FavoritesAction) { + FavoritesAction fav = (FavoritesAction) action; DataType favDt = fav.getDataType(); int len = favDt.getLength(); boolean enabled = ((len <= numBytes) && ((favDt instanceof Pointer) || (len > 0))); - checkEnablement(actions[i], enabled); + checkEnablement(action, enabled); } - else if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || - (actions[i] instanceof ShowComponentPathAction) || - (actions[i] instanceof EditFieldAction) || (actions[i] instanceof ClearAction) || - (actions[i] instanceof DeleteAction) || (actions[i] instanceof ArrayAction) || - (actions[i] instanceof PointerAction)) { - checkEnablement(actions[i], true); + else if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || + (action instanceof ShowComponentPathAction) || + (action instanceof EditFieldAction) || (action instanceof ClearAction) || + (action instanceof DeleteAction) || (action instanceof ArrayAction) || + (action instanceof PointerAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -273,14 +269,14 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on a contiguous multi-component selection. runSwing(() -> model.setSelection(new int[] { 2, 3, 4 })); - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || (actions[i] instanceof PointerAction) || - (actions[i] instanceof ClearAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || (action instanceof PointerAction) || + (action instanceof ClearAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } @@ -291,13 +287,13 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest { // Check enablement on a non-contiguous multi-component selection. runSwing(() -> model.setSelection(new int[] { 2, 3, 6, 7 })); - for (int i = 0; i < actions.length; i++) { - if ((actions[i] instanceof CycleGroupAction) || - (actions[i] instanceof HexNumbersAction) || (actions[i] instanceof ClearAction)) { - checkEnablement(actions[i], true); + for (CompositeEditorTableAction action : actions) { + if ((action instanceof CycleGroupAction) || + (action instanceof HexNumbersAction) || (action instanceof ClearAction)) { + checkEnablement(action, true); } else { - checkEnablement(actions[i], false); + checkEnablement(action, false); } } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/parser/FunctionSignatureParserTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/parser/FunctionSignatureParserTest.java index 159f2c3801..719a79b6b3 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/parser/FunctionSignatureParserTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/parser/FunctionSignatureParserTest.java @@ -43,7 +43,7 @@ public class FunctionSignatureParserTest extends AbstractGhidraHeadedIntegration public void setUp() throws Exception { ProgramBuilder builder = new ToyProgramBuilder("test", false); StructureDataType s = new StructureDataType("StructA", 0); - s.setInternallyAligned(true); + s.setPackingEnabled(true); s.add(IntegerDataType.dataType); builder.addDataType(s); program = builder.getProgram(); @@ -241,7 +241,7 @@ public class FunctionSignatureParserTest extends AbstractGhidraHeadedIntegration int txId = program.startTransaction("Add Struct"); try { StructureDataType s = new StructureDataType(new CategoryPath("/Test"), "StructA", 0); - s.setInternallyAligned(true); + s.setPackingEnabled(true); s.add(ByteDataType.dataType); program.getDataTypeManager().addDataType(s, null); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/BitFieldListingDisplayTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/BitFieldListingDisplayTest.java index 1886a7178e..3637f7be2f 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/BitFieldListingDisplayTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/BitFieldListingDisplayTest.java @@ -51,7 +51,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT TaskMonitor.DUMMY, false); struct = createStructure("Test", 0); - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); struct.addBitField(IntegerDataType.dataType, 3, "bf1", "Nuts"); struct.addBitField(IntegerDataType.dataType, 24, "bf2", null); struct.addBitField(IntegerDataType.dataType, 4, "bf3", null); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/ConflictHandlerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/ConflictHandlerTest.java index 0e94570a97..45bd5f52af 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/ConflictHandlerTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/ConflictHandlerTest.java @@ -398,118 +398,118 @@ public class ConflictHandlerTest extends AbstractGhidraHeadedIntegrationTest { /** * Tests the * {@link DataTypeConflictHandler#REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER RESORAAH} - * conflict handler to be sure that, if all else is the same, the aligned version is chosen - * over the unaligned version. + * conflict handler to be sure that, if all else is the same, the packed version is chosen + * over the non-packed version. *

    - * Success is the aligned version is chosen over the unaligned version. + * Success is the packed version is chosen over the non-packed version. */ @Test - public void testChooseNewAlignedOverExistingUnalignedWhenAllElseIsEqualForEmptyStructures() { - // Unaligned exists first. - Structure empty1Unaligned = new StructureDataType(root, "empty1", 0, dataMgr); - Composite empty1AlignedToAdd = (Composite) empty1Unaligned.copy(dataMgr); - empty1AlignedToAdd.setInternallyAligned(true); + public void testChooseNewPackedOverExistingNonPackedWhenAllElseIsEqualForEmptyStructures() { + // NonPacked exists first. + Structure empty1NonPacked = new StructureDataType(root, "empty1", 0, dataMgr); + Composite empty1PackedToAdd = (Composite) empty1NonPacked.copy(dataMgr); + empty1PackedToAdd.setPackingEnabled(true); - String empty1UnalignedString = empty1Unaligned.toString(); - String empty1AlignedToAddString = empty1AlignedToAdd.toString(); + String empty1NonPackedString = empty1NonPacked.toString(); + String empty1PackedToAddString = empty1PackedToAdd.toString(); - Structure empty1AddResult = (Structure) dataMgr.addDataType(empty1AlignedToAdd, + Structure empty1AddResult = (Structure) dataMgr.addDataType(empty1PackedToAdd, DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER); String empty1AddResultString = empty1AddResult.toString(); - assertEquals(empty1AlignedToAddString, empty1AddResultString); - assertNotEquals(empty1UnalignedString, empty1AddResultString); + assertEquals(empty1PackedToAddString, empty1AddResultString); + assertNotEquals(empty1NonPackedString, empty1AddResultString); } /** * Tests the * {@link DataTypeConflictHandler#REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER RESORAAH} - * conflict handler to be sure that, if all else is the same, the aligned version is chosen - * over the unaligned version. + * conflict handler to be sure that, if all else is the same, the packed version is chosen + * over the non-packed version. *

    - * Success is the aligned version is chosen over the unaligned version. + * Success is the packed version is chosen over the non-packed version. */ @Test - public void testChooseNewAlignedOverExistingUnalignedWhenAllElseIsEqualForNonEmptyStructures() { - // Unaligned exists first. - StructureDataType struct1Unaligned = createPopulated(dataMgr); - Composite struct1AlignedToAdd = (Composite) struct1Unaligned.copy(dataMgr); - struct1AlignedToAdd.setInternallyAligned(true); + public void testChooseNewPackedOverExistingNonPackedWhenAllElseIsEqualForNonEmptyStructures() { + // NonPacked exists first. + StructureDataType struct1NonPacked = createPopulated(dataMgr); + Composite struct1PackedToAdd = (Composite) struct1NonPacked.copy(dataMgr); + struct1PackedToAdd.setPackingEnabled(true); - String struct1UnalignedString = struct1Unaligned.toString(); - String struct1AlignedToAddString = struct1AlignedToAdd.toString(); + String struct1NonPackedString = struct1NonPacked.toString(); + String struct1PackedToAddString = struct1PackedToAdd.toString(); - Structure struct1AddResult = (Structure) dataMgr.addDataType(struct1AlignedToAdd, + Structure struct1AddResult = (Structure) dataMgr.addDataType(struct1PackedToAdd, DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER); String struct1AddResultString = struct1AddResult.toString(); - assertEquals(struct1AlignedToAddString, struct1AddResultString); - assertNotEquals(struct1UnalignedString, struct1AddResultString); + assertEquals(struct1PackedToAddString, struct1AddResultString); + assertNotEquals(struct1NonPackedString, struct1AddResultString); } /** * Tests the * {@link DataTypeConflictHandler#REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER RESORAAH} - * conflict handler to be sure that, if all else is the same, the new unaligned version is - * chosen over the existing unaligned version. + * conflict handler to be sure that, if all else is the same, the new non-packed version is + * chosen over the existing non-packed version. *

    - * Success is the new unaligned version is chosen over the existing aligned version. + * Success is the new non-packed version is chosen over the existing packed version. */ // TODO: consider whether we want to change the logic of the conflict handler to favor - // aligned over unaligned. + // packed over non-packed. @Test - public void testChooseNewUnalignedOverExistingAlignedWhenAllElseIsEqualForEmptyStructures() { + public void testChooseNewNonPackedOverExistingPackedWhenAllElseIsEqualForEmptyStructures() { - // Aligned exists first. - Structure empty2Aligned = new StructureDataType(root, "empty2", 0, dataMgr); - Composite empty2UnalignedToAdd = (Composite) empty2Aligned.copy(dataMgr); - // aligning only after making unaligned copy. - empty2Aligned.setInternallyAligned(true); + // Packed exists first. + Structure empty2Packed = new StructureDataType(root, "empty2", 0, dataMgr); + Composite empty2NonPackedToAdd = (Composite) empty2Packed.copy(dataMgr); + // aligning only after making non-packed copy. + empty2Packed.setPackingEnabled(true); - String empty2AlignedString = empty2Aligned.toString(); - String empty2UnalignedToAddString = empty2UnalignedToAdd.toString(); + String empty2PackedString = empty2Packed.toString(); + String empty2NonPackedToAddString = empty2NonPackedToAdd.toString(); - Structure empty2AddResult = (Structure) dataMgr.addDataType(empty2UnalignedToAdd, + Structure empty2AddResult = (Structure) dataMgr.addDataType(empty2NonPackedToAdd, DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER); String empty2AddResultString = empty2AddResult.toString(); - assertEquals(empty2UnalignedToAddString, empty2AddResultString); - assertNotEquals(empty2AlignedString, empty2AddResultString); + assertEquals(empty2NonPackedToAddString, empty2AddResultString); + assertNotEquals(empty2PackedString, empty2AddResultString); } /** * Tests the * {@link DataTypeConflictHandler#REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER RESORAAH} - * conflict handler to be sure that, if all else is the same, the new unaligned version is - * chosen over the existing aligned version. + * conflict handler to be sure that, if all else is the same, the new non-packed version is + * chosen over the existing packed version. *

    - * Success is the new unaligned version is chosen over the existing aligned version. + * Success is the new non-packed version is chosen over the existing packed version. */ // TODO: consider whether we want to change the logic of the conflict handler to favor - // aligned over unaligned. + // packed over non-packed. @Test - public void testChooseNewUnalignedOverExistingAlignedWhenAllElseIsEqualForNonEmptyStructures() { + public void testChooseNewNonPackedOverExistingPackedWhenAllElseIsEqualForNonEmptyStructures() { - // Aligned exists first. - StructureDataType struct2Aligned = createPopulated(dataMgr); - Composite struct2UnalignedToAdd = (Composite) struct2Aligned.copy(dataMgr); - // aligning only after making unaligned copy. - struct2Aligned.setInternallyAligned(true); + // Packed exists first. + StructureDataType struct2Packed = createPopulated(dataMgr); + Composite struct2NonPackedToAdd = (Composite) struct2Packed.copy(dataMgr); + // aligning only after making non-packed copy. + struct2Packed.setPackingEnabled(true); - String struct2AlignedString = struct2Aligned.toString(); - String struct2UnalignedToAddString = struct2UnalignedToAdd.toString(); + String struct2PackedString = struct2Packed.toString(); + String struct2NonPackedToAddString = struct2NonPackedToAdd.toString(); - Structure struct2AddResult = (Structure) dataMgr.addDataType(struct2UnalignedToAdd, + Structure struct2AddResult = (Structure) dataMgr.addDataType(struct2NonPackedToAdd, DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER); String struct2AddResultString = struct2AddResult.toString(); - assertEquals(struct2UnalignedToAddString, struct2AddResultString); - assertNotEquals(struct2AlignedString, struct2AddResultString); + assertEquals(struct2NonPackedToAddString, struct2AddResultString); + assertNotEquals(struct2PackedString, struct2AddResultString); } /** * Tests the * {@link DataTypeConflictHandler#REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER RESORAAH} - * conflict handler to be sure that, if all else is the same, the aligned version is chosen - * over the unaligned version. + * conflict handler to be sure that, if all else is the same, the packed version is chosen + * over the non-packed version. *

    - * Success is the aligned version is chosen over the unaligned version. + * Success is the packed version is chosen over the non-packed version. */ @Test public void testResolveDataTypeNonStructConflict() throws Exception { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/model/data/DataTypeTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/model/data/DataTypeTest.java index 6ad3dd3e85..565b13b6e2 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/model/data/DataTypeTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/model/data/DataTypeTest.java @@ -61,7 +61,7 @@ public class DataTypeTest extends AbstractGhidraHeadedIntegrationTest { Structure structA = new StructureDataType("structA", 0); structA.setCategoryPath(new CategoryPath("/catA")); - structA.setInternallyAligned(true); + structA.setPackingEnabled(true); Pointer p = new PointerDataType(structA); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/util/data/DataTypeParserTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/util/data/DataTypeParserTest.java index baa1c1446e..3a3c02f0ff 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/util/data/DataTypeParserTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/util/data/DataTypeParserTest.java @@ -39,7 +39,7 @@ public class DataTypeParserTest extends AbstractEditorTest { try { DataTypeManager dataTypeManager = cat.getDataTypeManager(); if (dt.getDataTypeManager() != dataTypeManager) { - dt = (Union) dt.clone(dataTypeManager); + dt = dt.clone(dataTypeManager); } CategoryPath categoryPath = cat.getCategoryPath(); if (!dt.getCategoryPath().equals(categoryPath)) { diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/StructureDataTypeTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/StructureDataTypeTest.java index f764e7ece4..a1098f72f1 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/StructureDataTypeTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/StructureDataTypeTest.java @@ -20,6 +20,7 @@ package ghidra.program.database.data; import static org.junit.Assert.*; +import org.apache.commons.compress.utils.Sets; import org.junit.*; import generic.test.AbstractGTest; @@ -45,7 +46,7 @@ public class StructureDataTypeTest extends AbstractGTest { // transition default little-endian structure to big-endian DataTypeManager beDtm = new MyBigEndianDataTypeManager(); - struct = (Structure) struct.clone(beDtm); + struct = struct.clone(beDtm); } private Structure createStructure(String name, int length) { @@ -420,7 +421,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -438,7 +439,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -461,7 +462,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -481,7 +482,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -506,7 +507,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -525,7 +526,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -545,7 +546,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -573,7 +574,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -607,7 +608,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -626,7 +627,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -646,7 +647,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -665,7 +666,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -693,7 +694,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -894,6 +895,79 @@ public class StructureDataTypeTest extends AbstractGTest { assertEquals(7, comps[3].getOrdinal()); } + @Test + public void testDeleteMany() { + + struct.growStructure(20); + struct.insertAtOffset(12, WordDataType.dataType, -1, "A", null); + struct.insertAtOffset(16, WordDataType.dataType, -1, "B", null); + + assertEquals(32, struct.getLength()); + assertEquals(26, struct.getNumComponents()); + assertEquals(6, struct.getNumDefinedComponents()); + + struct.delete(Sets.newHashSet(1, 4, 5)); + + assertEquals(28, struct.getLength()); + assertEquals(23, struct.getNumComponents()); + assertEquals(5, struct.getNumDefinedComponents()); + + DataTypeComponent[] comps = struct.getDefinedComponents(); + assertEquals(WordDataType.class, comps[3].getDataType().getClass()); + assertEquals(5, comps[3].getOrdinal()); + assertEquals(8, comps[3].getOffset()); + } + + @Test + public void testDeleteManyBF() throws InvalidDataTypeException { + + struct.insertBitFieldAt(2, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment"); + struct.insertBitFieldAt(2, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment"); + struct.insertBitFieldAt(2, 4, 6, IntegerDataType.dataType, 15, "bf3", "bf3Comment"); + struct.insertBitFieldAt(2, 4, 21, IntegerDataType.dataType, 11, "bf4", "bf4Comment"); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + + " 2 int:3(3) 1 bf2 \"bf2Comment\"\n" + + " 2 int:15(6) 3 bf3 \"bf3Comment\"\n" + + " 4 int:11(5) 2 bf4 \"bf4Comment\"\n" + + " 6 word 2 null \"Comment2\"\n" + + " 8 dword 4 field3 \"\"\n" + + " 12 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 13 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(Sets.newHashSet(1, 2, 3, 4, 5, 6)); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + +// " 2 undefined 1 null \"\"\n" + +// " 3 undefined 1 null \"\"\n" + +// " 4 undefined 1 null \"\"\n" + + " 5 dword 4 field3 \"\"\n" + + " 9 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 10 Actual Alignment = 1", struct); + //@formatter:on + + assertEquals(10, struct.getLength()); + assertEquals(7, struct.getNumComponents()); + assertEquals(3, struct.getNumDefinedComponents()); + DataTypeComponent[] comps = struct.getDefinedComponents(); + assertEquals(DWordDataType.class, comps[1].getDataType().getClass()); + assertEquals(5, comps[1].getOffset()); + } + @Test public void testDelete() { struct.delete(1); @@ -904,6 +978,144 @@ public class StructureDataTypeTest extends AbstractGTest { assertEquals(1, comps[1].getOffset()); } + @Test + public void testDeleteBF() throws InvalidDataTypeException { + + struct.insertBitFieldAt(2, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment"); + struct.insertBitFieldAt(2, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment"); + struct.insertBitFieldAt(2, 4, 6, IntegerDataType.dataType, 15, "bf3", "bf3Comment"); + struct.insertBitFieldAt(2, 4, 21, IntegerDataType.dataType, 11, "bf4", "bf4Comment"); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + + " 2 int:3(3) 1 bf2 \"bf2Comment\"\n" + + " 2 int:15(6) 3 bf3 \"bf3Comment\"\n" + + " 4 int:11(5) 2 bf4 \"bf4Comment\"\n" + + " 6 word 2 null \"Comment2\"\n" + + " 8 dword 4 field3 \"\"\n" + + " 12 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 13 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(6); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + + " 2 int:3(3) 1 bf2 \"bf2Comment\"\n" + + " 2 int:15(6) 3 bf3 \"bf3Comment\"\n" + + " 4 int:11(5) 2 bf4 \"bf4Comment\"\n" + + " 6 dword 4 field3 \"\"\n" + + " 10 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(3); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + + " 2 int:15(6) 3 bf3 \"bf3Comment\"\n" + + " 4 int:11(5) 2 bf4 \"bf4Comment\"\n" + + " 6 dword 4 field3 \"\"\n" + + " 10 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(3); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + +// " 3 undefined 1 null \"\"\n" + + " 4 int:11(5) 2 bf4 \"bf4Comment\"\n" + + " 6 dword 4 field3 \"\"\n" + + " 10 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(4); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + +// " 3 undefined 1 null \"\"\n" + +// " 4 undefined 1 null \"\"\n" + +// " 5 undefined 1 null \"\"\n" + + " 6 dword 4 field3 \"\"\n" + + " 10 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(2); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + +// " 2 undefined 1 null \"\"\n" + +// " 3 undefined 1 null \"\"\n" + +// " 4 undefined 1 null \"\"\n" + +// " 5 undefined 1 null \"\"\n" + + " 6 dword 4 field3 \"\"\n" + + " 10 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(2); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + + "pack(disabled)\n" + + "Structure TestStruct {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + +// " 2 undefined 1 null \"\"\n" + +// " 3 undefined 1 null \"\"\n" + +// " 4 undefined 1 null \"\"\n" + + " 5 dword 4 field3 \"\"\n" + + " 9 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 10 Actual Alignment = 1", struct); + //@formatter:on + + assertEquals(10, struct.getLength()); + assertEquals(7, struct.getNumComponents()); + assertEquals(3, struct.getNumDefinedComponents()); + DataTypeComponent[] comps = struct.getDefinedComponents(); + assertEquals(DWordDataType.class, comps[1].getDataType().getClass()); + assertEquals(5, comps[1].getOffset()); + } + @Test public void testDeleteAtOffset() { struct.deleteAtOffset(2); @@ -936,15 +1148,51 @@ public class StructureDataTypeTest extends AbstractGTest { @Test public void testDeleteAll() { + struct.setPackingEnabled(true); // enable packing for struct + assertEquals(12, struct.getLength()); + Structure s = new StructureDataType("test1", 0); s.add(new ByteDataType()); s.add(new FloatDataType()); + assertEquals(1, s.getAlignment()); + assertEquals(5, s.getLength()); struct.add(s); + assertEquals(16, struct.getLength()); + s.deleteAll(); assertEquals(1, s.getLength()); assertTrue(s.isNotYetDefined()); + assertTrue(s.isZeroLength()); assertEquals(0, s.getNumComponents()); + + assertEquals(12, struct.getLength()); + + } + + @Test + public void testAlignmentAndPacking() { + + struct.setPackingEnabled(true); // enable packing for struct + assertEquals(12, struct.getLength()); + + Structure s = new StructureDataType("test1", 0); + s.add(new ByteDataType()); + s.add(new FloatDataType()); + assertEquals(1, s.getAlignment()); + assertEquals(5, s.getLength()); + + struct.add(s); + assertEquals(16, struct.getLength()); + + s.setExplicitMinimumAlignment(8); // does not force packing (s length unaffected) + + assertEquals(5, s.getLength()); + assertFalse(s.isNotYetDefined()); + assertFalse(s.isZeroLength()); + assertEquals(2, s.getNumComponents()); + + assertEquals(24, struct.getLength()); } @Test @@ -1129,9 +1377,9 @@ public class StructureDataTypeTest extends AbstractGTest { @Test public void testReplaceWith2() throws InvalidDataTypeException { - // NOTE: unaligned bitfields should remain unchanged when + // NOTE: pack(disabled) bitfields should remain unchanged when // transitioning endianess even though it makes little sense. - // Unaligned structures are not intended to be portable! + // pack(disabled) structures are not intended to be portable! TypeDef td = new TypedefDataType("Foo", IntegerDataType.dataType); @@ -1144,7 +1392,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure TestStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -1169,7 +1417,7 @@ public class StructureDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/bigStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure bigStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/UnionDataTypeTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/UnionDataTypeTest.java index e98836e83d..1ab193bacc 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/UnionDataTypeTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/database/data/UnionDataTypeTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.*; import org.junit.*; +import com.google.common.collect.Sets; + import generic.test.AbstractGTest; import ghidra.program.model.data.*; @@ -152,7 +154,7 @@ public class UnionDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 short 2 null \"\"\n" + " 0 int:2(0) 1 bf1 \"bf1Comment\"\n" + @@ -170,11 +172,11 @@ public class UnionDataTypeTest extends AbstractGTest { } union.insertBitField(0, IntegerDataType.dataType, 2, "bf1", "bf1Comment"); union.insert(0, ShortDataType.dataType); - union.setInternallyAligned(true); + union.setPackingEnabled(true); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Aligned\n" + + "pack()\n" + "Union TestUnion {\n" + " 0 short 2 null \"\"\n" + " 0 int:2(0) 1 bf1 \"bf1Comment\"\n" + @@ -191,7 +193,7 @@ public class UnionDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -214,7 +216,7 @@ public class UnionDataTypeTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -261,6 +263,42 @@ public class UnionDataTypeTest extends AbstractGTest { assertEquals(2, union.getLength()); } + @Test + public void testDeleteMany() throws Exception { + Structure struct = createStructure("struct_1", 0); + struct.add(new ByteDataType()); + struct.add(new StringDataType(), 10); + union.add(struct); + assertEquals(11, union.getLength()); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + + "pack(disabled)\n" + + "Union TestUnion {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + + " 0 word 2 null \"Comment2\"\n" + + " 0 dword 4 field3 \"\"\n" + + " 0 byte 1 field4 \"Comment4\"\n" + + " 0 struct_1 11 null \"\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", union); + //@formatter:on + + union.delete(Sets.newHashSet(2, 4)); + + assertEquals(2, union.getLength()); + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + + "pack(disabled)\n" + + "Union TestUnion {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + + " 0 word 2 null \"Comment2\"\n" + + " 0 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 2 Actual Alignment = 1", union); + //@formatter:on + } + @Test public void testIsPartOf() { Structure struct = createStructure("struct_1", 0); diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/AbstractCompositeImplBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/AbstractCompositeImplBitFieldTest.java index 136221cc0a..ee17f1ce98 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/AbstractCompositeImplBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/AbstractCompositeImplBitFieldTest.java @@ -15,7 +15,7 @@ */ package ghidra.program.model.data; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.io.FileNotFoundException; import java.io.InputStream; @@ -36,7 +36,7 @@ public abstract class AbstractCompositeImplBitFieldTest extends AbstractGTest { DataTypeManager dataMgr = getDataTypeManager(); if (dataMgr.getDataTypeCount(false) != 0) { - Msg.info(this, "Using previously parsed data types"); +// Msg.info(this, "Using previously parsed data types"); return; // already have types } diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCStructureImplBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCStructureImplBitFieldTest.java index cb22ff12be..399932725b 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCStructureImplBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCStructureImplBitFieldTest.java @@ -40,7 +40,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("A1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A1\n" + - "Aligned\n" + + "pack()\n" + "Structure A1 {\n" + " 0 char[5] 5 a \"\"\n" + " 8 int:3(0) 1 b \"\"\n" + @@ -57,7 +57,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("A2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A2\n" + - "Aligned\n" + + "pack()\n" + "Structure A2 {\n" + " 0 oddStruct 5 a \"\"\n" + " 8 int:3(0) 1 b \"\"\n" + @@ -74,7 +74,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("A3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A3\n" + - "Aligned\n" + + "pack()\n" + "Structure A3 {\n" + " 0 char[5] 5 a \"\"\n" + " 8 int:3(0) 1 b \"\"\n" + @@ -97,7 +97,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1\n" + - "Aligned\n" + + "pack()\n" + "Structure B1 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -113,7 +113,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B1flex"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" + - "Aligned\n" + + "pack()\n" + "Structure B1flex {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -130,7 +130,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2\n" + - "Aligned\n" + + "pack()\n" + "Structure B2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -146,7 +146,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3\n" + - "Aligned\n" + + "pack()\n" + "Structure B3 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -163,7 +163,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1\n" + - "Aligned\n" + + "pack()\n" + "Structure Z1 {\n" + " 0 char 1 a \"\"\n" + " 2 int:0(0) 1 \"\"\n" + @@ -180,7 +180,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2\n" + - "Aligned\n" + + "pack()\n" + "Structure Z2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -197,7 +197,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3\n" + - "Aligned\n" + + "pack()\n" + "Structure Z3 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -214,7 +214,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4\n" + - "Aligned\n" + + "pack()\n" + "Structure Z4 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -231,7 +231,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z5"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5\n" + - "Aligned\n" + + "pack()\n" + "Structure Z5 {\n" + " 0 char 1 a \"\"\n" + " 8 int:0(0) 1 \"\"\n" + @@ -248,7 +248,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z6"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z6\n" + - "Aligned\n" + + "pack()\n" + "Structure Z6 {\n" + " 0 char 1 a \"\"\n" + " 8 int:0(0) 1 \"\"\n" + @@ -268,7 +268,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B1p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -284,7 +284,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B2p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -300,7 +300,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B3p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B3p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -316,7 +316,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z1p1 {\n" + " 0 char 1 a \"\"\n" + " 1 int:0(0) 1 \"\"\n" + @@ -333,7 +333,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z2p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -350,7 +350,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z3p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z3p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -367,7 +367,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z3p1T"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p1T\n" + - "Aligned\n" + + "pack()\n" + "Structure Z3p1T {\n" + " 0 char 1 a \"\"\n" + " 1 Z3p1 7 z3p1 \"\"\n" + @@ -381,7 +381,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z4p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z4p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -398,7 +398,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B1p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -414,7 +414,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B2p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -430,7 +430,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B3p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -446,7 +446,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("B4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B4p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -463,7 +463,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z1p2 {\n" + " 0 char 1 a \"\"\n" + " 2 int:0(0) 1 \"\"\n" + @@ -480,7 +480,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z1p2x"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p2x\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z1p2x {\n" + " 0 char 1 a \"\"\n" + " 2 int:0(0) 1 \"\"\n" + @@ -515,7 +515,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z2p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -532,7 +532,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z3p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -549,7 +549,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z4p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:6(0) 1 b \"\"\n" + @@ -566,7 +566,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z5p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z5p2 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:12(0) 2 b \"\"\n" + @@ -583,7 +583,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x1p2 {\n" + " 0 char 1 a \"\"\n" + "}\n" + @@ -596,7 +596,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x2p2 {\n" + " 0 char 1 a \"\"\n" + " 2 int:27(0) 4 b \"\"\n" + @@ -610,7 +610,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x3p2 {\n" + " 0 char 1 a \"\"\n" + " 2 short:0(0) 1 \"\"\n" + @@ -625,7 +625,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x4p2 {\n" + " 0 char 1 a \"\"\n" + " 2 int:27(0) 4 b \"\"\n" + @@ -640,7 +640,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("Z5p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure Z5p4 {\n" + " 0 char 1 a \"\"\n" + " 2 ushort:12(0) 2 b \"\"\n" + @@ -657,7 +657,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x1p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x1p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x1p4 {\n" + " 0 char 1 a \"\"\n" + "}\n" + @@ -670,7 +670,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x2p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x2p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x2p4 {\n" + " 0 char 1 a \"\"\n" + " 4 int:27(0) 4 b \"\"\n" + @@ -684,7 +684,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x3p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x3p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x3p4 {\n" + " 0 char 1 a \"\"\n" + " 4 short:0(0) 1 \"\"\n" + @@ -699,7 +699,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("x4p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x4p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x4p4 {\n" + " 0 char 1 a \"\"\n" + " 4 int:27(0) 4 b \"\"\n" + @@ -714,7 +714,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("T1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/T1\n" + - "Aligned\n" + + "pack()\n" + "Structure T1 {\n" + " 0 charTypedef 1 a \"\"\n" + " 4 myEnum:3(0) 1 b \"\"\n" + @@ -730,7 +730,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("T2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/T2\n" + - "Aligned\n" + + "pack()\n" + "Structure T2 {\n" + " 0 charTypedef 1 a \"\"\n" + " 4 intTypedef:17(0) 3 b \"\"\n" + @@ -746,7 +746,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("S1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1\n" + - "Aligned\n" + + "pack()\n" + "Structure S1 {\n" + " 0 B1 12 b1 \"\"\n" + " 12 B2 8 b2 \"\"\n" + @@ -763,7 +763,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("S1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure S1p1 {\n" + " 0 B1 12 b1 \"\"\n" + " 12 B2 8 b2 \"\"\n" + @@ -780,7 +780,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("S2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure S2p1 {\n" + " 0 B1p1 9 b1p1 \"\"\n" + " 9 B2p1 7 b2p1 \"\"\n" + @@ -797,7 +797,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("S1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure S1p2 {\n" + " 0 B1 12 b1 \"\"\n" + " 12 B2 8 b2 \"\"\n" + @@ -814,7 +814,7 @@ public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitField Structure struct = getStructure("S2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure S2p2 {\n" + " 0 B1p2 10 b1p2 \"\"\n" + " 10 B2p2 8 b2p2 \"\"\n" + diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCUnionImplBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCUnionImplBitFieldTest.java index 951d422b0f..43d07140ed 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCUnionImplBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/MSVCUnionImplBitFieldTest.java @@ -38,7 +38,7 @@ public class MSVCUnionImplBitFieldTest extends AbstractCompositeImplBitFieldTest Union struct = getUnion("U1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1\n" + - "Aligned\n" + + "pack()\n" + "Union U1 {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 int:2(0) 1 b \"\"\n" + @@ -52,7 +52,7 @@ public class MSVCUnionImplBitFieldTest extends AbstractCompositeImplBitFieldTest Union struct = getUnion("U1z"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" + - "Aligned\n" + + "pack()\n" + "Union U1z {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 longlong:0(0) 1 \"\"\n" + @@ -67,7 +67,7 @@ public class MSVCUnionImplBitFieldTest extends AbstractCompositeImplBitFieldTest Union struct = getUnion("U1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Union U1p1 {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 int:2(0) 1 b \"\"\n" + @@ -81,7 +81,7 @@ public class MSVCUnionImplBitFieldTest extends AbstractCompositeImplBitFieldTest Union struct = getUnion("U1p1z"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Union U1p1z {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 longlong:0(0) 1 \"\"\n" + @@ -96,7 +96,7 @@ public class MSVCUnionImplBitFieldTest extends AbstractCompositeImplBitFieldTest Union struct = getUnion("U1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Union U1p2 {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 int:2(0) 1 b \"\"\n" + diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplBigEndianBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplBigEndianBitFieldTest.java index 17b4f28478..038288dc39 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplBigEndianBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplBigEndianBitFieldTest.java @@ -42,7 +42,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("A1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A1\n" + - "Aligned\n" + + "pack()\n" + "Structure A1 {\n" + " 0 char[5] 5 a \"\"\n" + " 5 int:3(5) 1 b \"\"\n" + @@ -59,7 +59,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("A2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A2\n" + - "Aligned\n" + + "pack()\n" + "Structure A2 {\n" + " 0 oddStruct 5 a \"\"\n" + " 5 int:3(5) 1 b \"\"\n" + @@ -76,7 +76,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("A3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A3\n" + - "Aligned\n" + + "pack()\n" + "Structure A3 {\n" + " 0 char[5] 5 a \"\"\n" + " 5 int:3(5) 1 b \"\"\n" + @@ -99,7 +99,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1\n" + - "Aligned\n" + + "pack()\n" + "Structure B1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -115,7 +115,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B1flex"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" + - "Aligned\n" + + "pack()\n" + "Structure B1flex {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -132,7 +132,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2\n" + - "Aligned\n" + + "pack()\n" + "Structure B2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -148,7 +148,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3\n" + - "Aligned\n" + + "pack()\n" + "Structure B3 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -165,7 +165,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1\n" + - "Aligned\n" + + "pack()\n" + "Structure Z1 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(7) 1 \"\"\n" + @@ -182,7 +182,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2\n" + - "Aligned\n" + + "pack()\n" + "Structure Z2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -199,7 +199,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3\n" + - "Aligned\n" + + "pack()\n" + "Structure Z3 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -216,7 +216,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4\n" + - "Aligned\n" + + "pack()\n" + "Structure Z4 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -233,7 +233,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z5"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5\n" + - "Aligned\n" + + "pack()\n" + "Structure Z5 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(7) 1 \"\"\n" + @@ -250,7 +250,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z6"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z6\n" + - "Aligned\n" + + "pack()\n" + "Structure Z6 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(7) 1 \"\"\n" + @@ -270,7 +270,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B1p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -286,7 +286,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B2p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -302,7 +302,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B3p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B3p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -318,7 +318,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z1p1 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(7) 1 \"\"\n" + @@ -335,7 +335,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z2p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -352,7 +352,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z3p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z3p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -369,7 +369,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z3p1T"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p1T\n" + - "Aligned\n" + + "pack()\n" + "Structure Z3p1T {\n" + " 0 char 1 a \"\"\n" + " 1 Z3p1 8 z3p1 \"\"\n" + @@ -383,7 +383,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z4p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z4p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -400,7 +400,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B1p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -416,7 +416,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B2p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -432,7 +432,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B3p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -448,7 +448,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("B4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B4p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -465,7 +465,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z1p2 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(7) 1 \"\"\n" + @@ -482,7 +482,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z1p2x"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p2x\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z1p2x {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(7) 1 \"\"\n" + @@ -517,7 +517,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z2p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -534,7 +534,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z3p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -551,7 +551,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z4p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(2) 1 b \"\"\n" + @@ -568,7 +568,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z5p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z5p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:12(4) 2 b \"\"\n" + @@ -585,7 +585,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x1p2 {\n" + " 0 char 1 a \"\"\n" + "}\n" + @@ -598,7 +598,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x2p2 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(5) 4 b \"\"\n" + @@ -612,7 +612,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x3p2 {\n" + " 0 char 1 a \"\"\n" + " 2 short:0(7) 1 \"\"\n" + @@ -627,7 +627,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x4p2 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(5) 4 b \"\"\n" + @@ -642,7 +642,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("Z5p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure Z5p4 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:12(4) 2 b \"\"\n" + @@ -659,7 +659,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x1p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x1p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x1p4 {\n" + " 0 char 1 a \"\"\n" + "}\n" + @@ -672,7 +672,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x2p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x2p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x2p4 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(5) 4 b \"\"\n" + @@ -686,7 +686,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x3p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x3p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x3p4 {\n" + " 0 char 1 a \"\"\n" + " 2 short:0(7) 1 \"\"\n" + @@ -701,7 +701,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("x4p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x4p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x4p4 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(5) 4 b \"\"\n" + @@ -716,7 +716,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("T1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/T1\n" + - "Aligned\n" + + "pack()\n" + "Structure T1 {\n" + " 0 charTypedef 1 a \"\"\n" + " 1 myEnum:3(5) 1 b \"\"\n" + @@ -732,7 +732,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("T2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/T2\n" + - "Aligned\n" + + "pack()\n" + "Structure T2 {\n" + " 0 charTypedef 1 a \"\"\n" + " 1 intTypedef:17(7) 3 b \"\"\n" + @@ -748,7 +748,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("S1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1\n" + - "Aligned\n" + + "pack()\n" + "Structure S1 {\n" + " 0 B1 4 b1 \"\"\n" + " 4 B2 4 b2 \"\"\n" + @@ -765,7 +765,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("S1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure S1p1 {\n" + " 0 B1 4 b1 \"\"\n" + " 4 B2 4 b2 \"\"\n" + @@ -782,7 +782,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("S2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure S2p1 {\n" + " 0 B1p1 4 b1p1 \"\"\n" + " 4 B2p1 4 b2p1 \"\"\n" + @@ -799,7 +799,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("S1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure S1p2 {\n" + " 0 B1 4 b1 \"\"\n" + " 4 B2 4 b2 \"\"\n" + @@ -816,7 +816,7 @@ public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBit Structure struct = getStructure("S2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure S2p2 {\n" + " 0 B1p2 4 b1p2 \"\"\n" + " 4 B2p2 4 b2p2 \"\"\n" + diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplLittleEndianBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplLittleEndianBitFieldTest.java index 626cf6b186..adb984cfb0 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplLittleEndianBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/StructureImplLittleEndianBitFieldTest.java @@ -73,7 +73,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("A1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A1\n" + - "Aligned\n" + + "pack()\n" + "Structure A1 {\n" + " 0 char[5] 5 a \"\"\n" + " 5 int:3(0) 1 b \"\"\n" + @@ -90,7 +90,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("A2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A2\n" + - "Aligned\n" + + "pack()\n" + "Structure A2 {\n" + " 0 oddStruct 5 a \"\"\n" + " 5 int:3(0) 1 b \"\"\n" + @@ -107,7 +107,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("A3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/A3\n" + - "Aligned\n" + + "pack()\n" + "Structure A3 {\n" + " 0 char[5] 5 a \"\"\n" + " 5 int:3(0) 1 b \"\"\n" + @@ -130,7 +130,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1\n" + - "Aligned\n" + + "pack()\n" + "Structure B1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -146,7 +146,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B1flex"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" + - "Aligned\n" + + "pack()\n" + "Structure B1flex {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -163,7 +163,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2\n" + - "Aligned\n" + + "pack()\n" + "Structure B2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -179,7 +179,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3\n" + - "Aligned\n" + + "pack()\n" + "Structure B3 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + // gcc groups with previous non-bitfield @@ -196,7 +196,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1\n" + - "Aligned\n" + + "pack()\n" + "Structure Z1 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(0) 1 \"\"\n" + @@ -213,7 +213,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2\n" + - "Aligned\n" + + "pack()\n" + "Structure Z2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -230,7 +230,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z3"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3\n" + - "Aligned\n" + + "pack()\n" + "Structure Z3 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -247,7 +247,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4\n" + - "Aligned\n" + + "pack()\n" + "Structure Z4 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -264,7 +264,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z5"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5\n" + - "Aligned\n" + + "pack()\n" + "Structure Z5 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(0) 1 \"\"\n" + @@ -281,7 +281,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z6"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z6\n" + - "Aligned\n" + + "pack()\n" + "Structure Z6 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(0) 1 \"\"\n" + @@ -301,7 +301,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B1p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -317,7 +317,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B2p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -333,7 +333,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B3p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure B3p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -349,7 +349,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z1p1 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(0) 1 \"\"\n" + @@ -366,7 +366,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z2p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -383,7 +383,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z3p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z3p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -400,7 +400,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z3p1T"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p1T\n" + - "Aligned\n" + + "pack()\n" + "Structure Z3p1T {\n" + " 0 char 1 a \"\"\n" + " 1 Z3p1 8 z3p1 \"\"\n" + @@ -414,7 +414,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z4p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure Z4p1 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -431,7 +431,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B1p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -447,7 +447,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B2p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -463,7 +463,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B3p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -479,7 +479,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("B4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/B4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure B4p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -496,7 +496,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z1p2 {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(0) 1 \"\"\n" + @@ -513,7 +513,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z1p2x"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z1p2x\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z1p2x {\n" + " 0 char 1 a \"\"\n" + " 4 int:0(0) 1 \"\"\n" + @@ -548,7 +548,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z2p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -565,7 +565,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z3p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -582,7 +582,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z4p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:6(0) 1 b \"\"\n" + @@ -599,7 +599,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z5p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure Z5p2 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:12(0) 2 b \"\"\n" + @@ -616,7 +616,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x1p2 {\n" + " 0 char 1 a \"\"\n" + "}\n" + @@ -629,7 +629,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x2p2 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(0) 4 b \"\"\n" + @@ -643,7 +643,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x3p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x3p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x3p2 {\n" + " 0 char 1 a \"\"\n" + " 2 short:0(0) 1 \"\"\n" + @@ -658,7 +658,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x4p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x4p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure x4p2 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(0) 4 b \"\"\n" + @@ -673,7 +673,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("Z5p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Z5p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure Z5p4 {\n" + " 0 char 1 a \"\"\n" + " 1 ushort:12(0) 2 b \"\"\n" + @@ -690,7 +690,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x1p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x1p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x1p4 {\n" + " 0 char 1 a \"\"\n" + "}\n" + @@ -703,7 +703,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x2p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x2p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x2p4 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(0) 4 b \"\"\n" + @@ -717,7 +717,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x3p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x3p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x3p4 {\n" + " 0 char 1 a \"\"\n" + " 2 short:0(0) 1 \"\"\n" + @@ -732,7 +732,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("x4p4"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/x4p4\n" + - "Aligned pack(4)\n" + + "pack(4)\n" + "Structure x4p4 {\n" + " 0 char 1 a \"\"\n" + " 1 int:27(0) 4 b \"\"\n" + @@ -747,7 +747,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("T1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/T1\n" + - "Aligned\n" + + "pack()\n" + "Structure T1 {\n" + " 0 charTypedef 1 a \"\"\n" + " 1 myEnum:3(0) 1 b \"\"\n" + @@ -763,7 +763,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("T2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/T2\n" + - "Aligned\n" + + "pack()\n" + "Structure T2 {\n" + " 0 charTypedef 1 a \"\"\n" + " 1 intTypedef:17(0) 3 b \"\"\n" + @@ -779,7 +779,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("S1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1\n" + - "Aligned\n" + + "pack()\n" + "Structure S1 {\n" + " 0 B1 4 b1 \"\"\n" + " 4 B2 4 b2 \"\"\n" + @@ -796,7 +796,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("S1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure S1p1 {\n" + " 0 B1 4 b1 \"\"\n" + " 4 B2 4 b2 \"\"\n" + @@ -813,7 +813,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("S2p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S2p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Structure S2p1 {\n" + " 0 B1p1 4 b1p1 \"\"\n" + " 4 B2p1 4 b2p1 \"\"\n" + @@ -830,7 +830,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("S1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure S1p2 {\n" + " 0 B1 4 b1 \"\"\n" + " 4 B2 4 b2 \"\"\n" + @@ -847,7 +847,7 @@ public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImpl Structure struct = getStructure("S2p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/S2p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Structure S2p2 {\n" + " 0 B1p2 4 b1p2 \"\"\n" + " 4 B2p2 4 b2p2 \"\"\n" + diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplBigEndianBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplBigEndianBitFieldTest.java index 0f87f38031..89316bea5a 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplBigEndianBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplBigEndianBitFieldTest.java @@ -40,7 +40,7 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel Union struct = getUnion("U1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1\n" + - "Aligned\n" + + "pack()\n" + "Union U1 {\n" + " 0 int:4(4) 1 a \"\"\n" + " 0 int:2(6) 1 b \"\"\n" + @@ -54,7 +54,7 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel Union struct = getUnion("U1z"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" + - "Aligned\n" + + "pack()\n" + "Union U1z {\n" + " 0 int:4(4) 1 a \"\"\n" + " 0 longlong:0(7) 1 \"\"\n" + // has no impact @@ -69,7 +69,7 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel Union struct = getUnion("U1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Union U1p1 {\n" + " 0 int:4(4) 1 a \"\"\n" + " 0 int:2(6) 1 b \"\"\n" + @@ -83,7 +83,7 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel Union struct = getUnion("U1p1z"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Union U1p1z {\n" + " 0 int:4(4) 1 a \"\"\n" + " 0 longlong:0(7) 1 \"\"\n" + // has no impact @@ -98,7 +98,7 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel Union struct = getUnion("U1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Union U1p2 {\n" + " 0 int:4(4) 1 a \"\"\n" + " 0 int:2(6) 1 b \"\"\n" + diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplLittleEndianBitFieldTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplLittleEndianBitFieldTest.java index 26122e850f..964902b10d 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplLittleEndianBitFieldTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/data/UnionImplLittleEndianBitFieldTest.java @@ -40,7 +40,7 @@ public class UnionImplLittleEndianBitFieldTest extends AbstractCompositeImplBitF Union struct = getUnion("U1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1\n" + - "Aligned\n" + + "pack()\n" + "Union U1 {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 int:2(0) 1 b \"\"\n" + @@ -54,7 +54,7 @@ public class UnionImplLittleEndianBitFieldTest extends AbstractCompositeImplBitF Union struct = getUnion("U1z"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" + - "Aligned\n" + + "pack()\n" + "Union U1z {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 longlong:0(0) 1 \"\"\n" + // has no impact @@ -69,7 +69,7 @@ public class UnionImplLittleEndianBitFieldTest extends AbstractCompositeImplBitF Union struct = getUnion("U1p1"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Union U1p1 {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 int:2(0) 1 b \"\"\n" + @@ -83,7 +83,7 @@ public class UnionImplLittleEndianBitFieldTest extends AbstractCompositeImplBitF Union struct = getUnion("U1p1z"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" + - "Aligned pack(1)\n" + + "pack(1)\n" + "Union U1p1z {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 longlong:0(0) 1 \"\"\n" + // has no impact @@ -98,7 +98,7 @@ public class UnionImplLittleEndianBitFieldTest extends AbstractCompositeImplBitF Union struct = getUnion("U1p2"); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" + - "Aligned pack(2)\n" + + "pack(2)\n" + "Union U1p2 {\n" + " 0 int:4(0) 1 a \"\"\n" + " 0 int:2(0) 1 b \"\"\n" + diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java index 101b6d4006..262c57ecc1 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java @@ -450,13 +450,8 @@ public class FillOutStructureCmd extends BackgroundCommand { structDT = createNewStruct(var, (int) componentMap.getSize(), f, isThisParam); } else { - int len; - if (structDT.isNotYetDefined()) { - len = 0; - } - else { - len = structDT.getLength(); - } + // FIXME: How should an existing packed structure be handled? Growing and offset-based placement does not apply + int len = structDT.isZeroLength() ? 0 : structDT.getLength(); if (componentMap.getSize() > len) { structDT.growStructure((int) componentMap.getSize() - len); } @@ -521,13 +516,8 @@ public class FillOutStructureCmd extends BackgroundCommand { return null; } Structure structDT = VariableUtilities.findOrCreateClassStruct(f); - int len; - if (structDT.isNotYetDefined()) { - len = 0; // getLength reports as at least size 1 - } - else { - len = structDT.getLength(); - } +// FIXME: How should an existing packed structure be handled? Growing and offset-based placement does not apply + int len = structDT.isZeroLength() ? 0 : structDT.getLength(); if (len < size) { structDT.growStructure(size - len); } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameStructureFieldTask.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameStructureFieldTask.java index 527382b72e..08024495b4 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameStructureFieldTask.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameStructureFieldTask.java @@ -20,6 +20,7 @@ import ghidra.app.decompiler.component.DecompilerPanel; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.data.*; import ghidra.program.model.listing.Program; +import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.InvalidInputException; @@ -37,9 +38,14 @@ public class RenameStructureFieldTask extends RenameTask { @Override public void commit() throws DuplicateNameException, InvalidInputException { - if (structure.isNotYetDefined()) { - DataType newtype = new Undefined1DataType(); - structure.insert(0, newtype); + // FIXME: How should an existing packed structure be handled? Growing and offset-based placement does not apply + int len = structure.isZeroLength() ? 0 : structure.getLength(); + if (len < offset) { + if (!structure.isPackingEnabled()) { + Msg.warn(this, "Structure '" + structure.getName() + "' converted to non-packed"); + structure.setPackingEnabled(false); + } + structure.growStructure(offset); } DataTypeComponent comp = structure.getComponentAt(offset); if (comp.getDataType() == DataType.DEFAULT) { // Is this just a placeholder 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 138bbe65e1..1aae0e185d 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 @@ -266,7 +266,7 @@ public class DefaultCompositeMember extends CompositeMember { } /** - * Adjust unaligned structure following member reconstruction. + * Adjust non-packed structure following member reconstruction. * @param preferredSize preferred size */ private void adjustSize(int preferredSize) { @@ -325,18 +325,21 @@ public class DefaultCompositeMember extends CompositeMember { Composite copy = (Composite) composite.copy(dataTypeManager); int pack = 0; - copy.setPackingValue(pack); + copy.setToDefaultPacking(); boolean alignOK = isGoodAlignment(copy, preferredSize); - if (!alignOK) { - pack = 1; - copy.setPackingValue(pack); - alignOK = isGoodAlignment(copy, preferredSize); - } if (alignOK) { - composite.setPackingValue(pack); + composite.setToDefaultPacking(); } - else if (errorConsumer != null && !isClass) { // don't complain about Class structs which always fail + 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 String anonymousStr = parent != null ? " anonymous " : ""; errorConsumer.accept("PDB " + anonymousStr + memberType + " reconstruction failed to align " + composite.getPathName()); @@ -352,11 +355,11 @@ public class DefaultCompositeMember extends CompositeMember { if (alignOK && isStructureContainer()) { // verify that components did not move Structure struct = (Structure) memberDataType; - DataTypeComponent[] unalignedComponents = struct.getDefinedComponents(); + DataTypeComponent[] nonPackedComponents = struct.getDefinedComponents(); int index = 0; for (DataTypeComponent dtc : testComposite.getComponents()) { - DataTypeComponent unalignedDtc = unalignedComponents[index++]; - if (!isComponentUnchanged(dtc, unalignedDtc)) { + DataTypeComponent nonPackedDtc = nonPackedComponents[index++]; + if (!isComponentUnchanged(dtc, nonPackedDtc)) { alignOK = false; break; } @@ -365,18 +368,18 @@ public class DefaultCompositeMember extends CompositeMember { return alignOK; } - private boolean isComponentUnchanged(DataTypeComponent dtc, DataTypeComponent unalignedDtc) { - if (unalignedDtc.getOffset() != dtc.getOffset() || - unalignedDtc.getLength() != dtc.getLength() || - unalignedDtc.isBitFieldComponent() != dtc.isBitFieldComponent()) { + private boolean isComponentUnchanged(DataTypeComponent dtc, DataTypeComponent nonPackedDtc) { + if (nonPackedDtc.getOffset() != dtc.getOffset() || + nonPackedDtc.getLength() != dtc.getLength() || + nonPackedDtc.isBitFieldComponent() != dtc.isBitFieldComponent()) { return false; } if (dtc.isBitFieldComponent()) { // both components are bit fields BitFieldDataType bitfieldDt = (BitFieldDataType) dtc.getDataType(); - BitFieldDataType unalignedBitfieldDt = (BitFieldDataType) unalignedDtc.getDataType(); - if (bitfieldDt.getBitOffset() != unalignedBitfieldDt.getBitOffset() || - bitfieldDt.getBitSize() != unalignedBitfieldDt.getBitSize()) { + BitFieldDataType nonPackedBitfieldDt = (BitFieldDataType) nonPackedDtc.getDataType(); + if (bitfieldDt.getBitOffset() != nonPackedBitfieldDt.getBitOffset() || + bitfieldDt.getBitSize() != nonPackedBitfieldDt.getBitSize()) { return false; } } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbUtil.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbUtil.java index 64264b2778..364ec85fd6 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbUtil.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbUtil.java @@ -105,32 +105,6 @@ final class PdbUtil { return false; } -// final static void ensureSize(int expectedLength, Composite composite, MessageLog log) { -// int actualLength = composite.getLength(); -// if (actualLength < expectedLength) { -// -// composite.setInternallyAligned(false); -// if (composite instanceof Structure) { -// Structure struct = (Structure) composite; -// // if this is an empty structure, the structure will lie to us -// // and say it has one element so add 1 to growth factor -// struct.growStructure( -// expectedLength - actualLength + (struct.isNotYetDefined() ? 1 : 0)); -// } -// // must be a union data type -// else { -// DataType datatype = new ArrayDataType(DataType.DEFAULT, expectedLength, -// DataType.DEFAULT.getLength()); -// composite.add(datatype); -// } -// } -// else if (actualLength > expectedLength) { -// log.appendMsg("PDB", "Composite data type generated from PDB has size mismatch. " + -// composite.getName() + ": expected 0x" + Integer.toHexString(expectedLength) + -// ", but was 0x" + Integer.toHexString(actualLength)); -// } -// } - final static void clearComponents(Composite composite) { if (composite instanceof Structure) { ((Structure) composite).deleteAll(); 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 d90b454dff..58094a4358 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 @@ -124,7 +124,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/struct\n" + - "Aligned\n" + + "pack()\n" + "Structure struct {\n" + " 0 uchar 1 a \"\"\n" + " 1 uchar:4(0) 1 b \"\"\n" + @@ -159,7 +159,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/struct\n" + - "Aligned\n" + + "pack()\n" + "Structure struct {\n" + " 0 uchar 1 a \"\"\n" + " 1 uchar:2(0) 1 padding \"\"\n" + @@ -222,20 +222,20 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/struct\n" + - "Aligned\n" + + "pack()\n" + "Structure struct {\n" + " 0 struct_u_0 1 null \"\"\n" + "}\n" + "Size = 1 Actual Alignment = 1\n" + "/struct/struct_u_0\n" + - "Aligned\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" + "Size = 1 Actual Alignment = 1\n" + "/struct/struct_u_0/struct_u_0_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure struct_u_0_s_0 {\n" + " 0 char:1(0) 1 a0 \"\"\n" + " 0 char:1(1) 1 padding \"\"\n" + @@ -245,7 +245,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 1 Actual Alignment = 1\n" + "/struct/struct_u_0/struct_u_0_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure struct_u_0_s_1 {\n" + " 0 char:1(0) 1 padding \"\"\n" + " 0 char:1(1) 1 a1 \"\"\n" + @@ -285,7 +285,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/union\n" + - "Aligned\n" + + "pack()\n" + "Union union {\n" + " 0 uchar 1 a \"\"\n" + " 0 union_s_1 1 _s_1 \"\"\n" + @@ -294,14 +294,14 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 2 Actual Alignment = 2\n" + "/union/union_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_1 {\n" + " 0 uchar:4(0) 1 b \"\"\n" + " 0 uchar:4(4) 1 c \"\"\n" + "}\n" + "Size = 1 Actual Alignment = 1\n" + "/union/union_s_2\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_2 {\n" + " 0 uchar:4(0) 1 d \"\"\n" + " 0 uchar:4(4) 1 e \"\"\n" + @@ -328,7 +328,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/struct\n" + - "Aligned\n" + + "pack()\n" + "Structure struct {\n" + " 0 char 1 a \"\"\n" + " char[0] 0 e \"\"\n" + @@ -353,20 +353,20 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest new MyPdbMember("f", "char[0]", 8)); //@formatter:on - assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 12, members, this, + assertTrue(DefaultCompositeMember.applyDataTypeMembers(struct, false, 16, members, this, TaskMonitor.DUMMY)); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/union\n" + - "Aligned\n" + + "pack()\n" + "Union union {\n" + " 0 union_s_0 12 _s_0 \"\"\n" + " 0 union_s_1 8 _s_1 \"\"\n" + "}\n" + - "Size = 12 Actual Alignment = 8\n" + + "Size = 16 Actual Alignment = 8\n" + "/union/union_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_0 {\n" + " 0 int 4 a \"\"\n" + " 4 int 4 b \"\"\n" + @@ -375,7 +375,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 12 Actual Alignment = 4\n" + "/union/union_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_1 {\n" + " 0 longlong 8 e \"\"\n" + " char[0] 0 f \"\"\n" + @@ -405,14 +405,14 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/union\n" + - "Aligned\n" + + "pack()\n" + "Union union {\n" + " 0 union_s_0 12 _s_0 \"\"\n" + " 0 union_s_1 1 _s_1 \"\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/union/union_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_0 {\n" + " 0 int 4 a \"\"\n" + " 4 int 4 b \"\"\n" + @@ -421,7 +421,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 12 Actual Alignment = 4\n" + "/union/union_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_1 {\n" + " char[0] 0 f \"\"\n" + "}\n" + @@ -449,21 +449,21 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/union\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union union {\n" + " 0 union_s_0 1 _s_0 \"\"\n" + " 0 union_s_1 2 _s_1 \"\"\n" + "}\n" + "Size = 2 Actual Alignment = 1\n" + "/union/union_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_0 {\n" + " 0 char 1 a \"\"\n" + " char[0] 0 flex \"\"\n" + "}\n" + "Size = 1 Actual Alignment = 1\n" + "/union/union_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_1 {\n" + " 0 char 1 b \"\"\n" + " 1 char 1 c \"\"\n" + @@ -506,21 +506,21 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/struct\n" + - "Aligned\n" + + "pack()\n" + "Structure struct {\n" + " 0 struct_u_0 1 null \"\"\n" + " 8 struct_u_8 8 null \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/struct/struct_u_0\n" + - "Aligned\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" + "Size = 1 Actual Alignment = 1\n" + "/struct/struct_u_0/struct_u_0_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure struct_u_0_s_0 {\n" + " 0 char:1(0) 1 s0 \"\"\n" + " 0 char:1(1) 1 s1 \"\"\n" + @@ -533,7 +533,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 1 Actual Alignment = 1\n" + "/struct/struct_u_0/struct_u_0_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure struct_u_0_s_1 {\n" + " 0 uchar:1(0) 1 u0 \"\"\n" + " 0 uchar:1(1) 1 u1 \"\"\n" + @@ -546,7 +546,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 1 Actual Alignment = 1\n" + "/struct/struct_u_8\n" + - "Aligned\n" + + "pack()\n" + "Union struct_u_8 {\n" + " 0 ulong 4 a \"\"\n" + " 0 longlong 8 b \"\"\n" + @@ -590,7 +590,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/union\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union union {\n" + " 0 ulong 4 a \"\"\n" + " 0 longlong 8 b \"\"\n" + @@ -598,7 +598,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 8 Actual Alignment = 1\n" + "/union/union_s_2\n" + - "Aligned\n" + + "pack()\n" + "Structure union_s_2 {\n" + " 0 char:1(0) 1 s0 \"\"\n" + " 0 char:1(1) 1 s1 \"\"\n" + @@ -700,7 +700,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/MoreComplicated_s\n" + - "Aligned\n" + + "pack()\n" + "Structure MoreComplicated_s {\n" + " 0 MoreComplicated_s_u_0 1 null \"\"\n" + " 8 MoreComplicated_s_u_8 8 null \"\"\n" + @@ -710,14 +710,14 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 56 Actual Alignment = 8\n" + "/MoreComplicated_s/MoreComplicated_s_u_0\n" + - "Aligned\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" + "Size = 1 Actual Alignment = 1\n" + "/MoreComplicated_s/MoreComplicated_s_u_0/MoreComplicated_s_u_0_s_0\n" + - "Aligned\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" + @@ -730,7 +730,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 1 Actual Alignment = 1\n" + "/MoreComplicated_s/MoreComplicated_s_u_0/MoreComplicated_s_u_0_s_1\n" + - "Aligned\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" + @@ -743,35 +743,35 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 1 Actual Alignment = 1\n" + "/MoreComplicated_s/MoreComplicated_s_u_16\n" + - "Aligned\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" + "Size = 16 Actual Alignment = 8\n" + "/MoreComplicated_s/MoreComplicated_s_u_16/MoreComplicated_s_u_16_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure MoreComplicated_s_u_16_s_0 {\n" + " 0 double 8 da \"\"\n" + " 8 char[8] 8 ca \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/MoreComplicated_s/MoreComplicated_s_u_16/MoreComplicated_s_u_16_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure MoreComplicated_s_u_16_s_1 {\n" + " 0 char[8] 8 cb \"\"\n" + " 8 double 8 db \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/MoreComplicated_s/MoreComplicated_s_u_44\n" + - "Aligned\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 1 _s_1 \"\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_0\n" + - "Aligned\n" + + "pack()\n" + "Structure MoreComplicated_s_u_44_s_0 {\n" + " 0 int 4 fromAddress \"\"\n" + " 4 int 4 toAddress \"\"\n" + @@ -780,13 +780,13 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 12 Actual Alignment = 4\n" + "/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_1\n" + - "Aligned\n" + + "pack()\n" + "Structure MoreComplicated_s_u_44_s_1 {\n" + " char[0] 0 buf \"\"\n" + "}\n" + "Size = 1 Actual Alignment = 1\n" + "/MoreComplicated_s/MoreComplicated_s_u_8\n" + - "Aligned\n" + + "pack()\n" + "Union MoreComplicated_s_u_8 {\n" + " 0 ulong 4 val \"\"\n" + " 0 double 8 d \"\"\n" + @@ -796,7 +796,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 8 Actual Alignment = 8\n" + "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_2\n" + - "Aligned\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" + @@ -817,7 +817,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 8 Actual Alignment = 4\n" + "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_3\n" + - "Aligned\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" + @@ -832,7 +832,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest "}\n" + "Size = 8 Actual Alignment = 4\n" + "/MoreComplicated_s/MoreComplicated_s_u_8/MoreComplicated_s_u_8_s_4\n" + - "Aligned\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" + diff --git a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeTypeTest.java b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeTypeTest.java index d1d4de31a1..5dc07097aa 100644 --- a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeTypeTest.java +++ b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeTypeTest.java @@ -15,7 +15,7 @@ */ package ghidra.app.util.pdb.pdbapplicator; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import java.util.*; @@ -204,8 +204,8 @@ public class CppCompositeTypeTest extends AbstractGenericTest { return; } Address address = iter.next(); - for (int index = 0; index < offsets.size(); index++) { - addresses.add(address.add(offsets.get(index))); + for (Integer offset : offsets) { + addresses.add(address.add(offset)); } } @@ -3002,13 +3002,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/A\n" + - "Aligned\n" + + "pack()\n" + "Structure A {\n" + " 0 A_direct 8 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + @@ -3058,13 +3058,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/A\n" + - "Aligned\n" + + "pack()\n" + "Structure A {\n" + " 0 A_direct 8 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + @@ -3112,13 +3112,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/C\n" + - "Aligned\n" + + "pack()\n" + "Structure C {\n" + " 0 C_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + @@ -3165,13 +3165,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/C\n" + - "Aligned\n" + + "pack()\n" + "Structure C {\n" + " 0 C_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + @@ -3218,13 +3218,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/CC1\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1 {\n" + " 0 CC1_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + @@ -3271,13 +3271,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/CC1\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1 {\n" + " 0 CC1_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + @@ -3324,13 +3324,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/CC2\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2 {\n" + " 0 CC2_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + @@ -3377,13 +3377,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/CC2\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2 {\n" + " 0 CC2_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + @@ -3428,7 +3428,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/CC3\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure CC3 {\n" + "}\n" + "Size = 1 Actual Alignment = 1"; @@ -3472,7 +3472,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/CC3\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure CC3 {\n" + "}\n" + "Size = 1 Actual Alignment = 1"; @@ -3521,19 +3521,19 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/D\n" + - "Aligned\n" + + "pack()\n" + "Structure D {\n" + " 0 D_direct 8 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/D/D_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure D_direct {\n" + " 0 C_direct 4 \"\"\n" + " 4 undefined4 4 d1 \"\"\n" + @@ -3584,19 +3584,19 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/D\n" + - "Aligned\n" + + "pack()\n" + "Structure D {\n" + " 0 D_direct 8 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/D/D_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure D_direct {\n" + " 0 C_direct 4 \"\"\n" + " 4 undefined4 4 d1 \"\"\n" + @@ -3644,13 +3644,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/E\n" + - "Aligned\n" + + "pack()\n" + "Structure E {\n" + " 0 E_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + @@ -3697,13 +3697,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/E\n" + - "Aligned\n" + + "pack()\n" + "Structure E {\n" + " 0 E_direct 4 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + @@ -3756,25 +3756,25 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/F\n" + - "Aligned\n" + + "pack()\n" + "Structure F {\n" + " 0 F_direct 12 \"\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/F/F_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure F_direct {\n" + " 0 C_direct 4 \"\"\n" + " 4 E_direct 4 \"\"\n" + @@ -3829,25 +3829,25 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/F\n" + - "Aligned\n" + + "pack()\n" + "Structure F {\n" + " 0 F_direct 12 \"\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/F/F_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure F_direct {\n" + " 0 C_direct 4 \"\"\n" + " 4 E_direct 4 \"\"\n" + @@ -3906,20 +3906,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/G\n" + - "Aligned\n" + + "pack()\n" + "Structure G {\n" + " 0 G_direct 8 \"\"\n" + " 8 C_direct 4 \"(Virtual Base C)\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + @@ -3978,20 +3978,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/G\n" + - "Aligned\n" + + "pack()\n" + "Structure G {\n" + " 0 G_direct 16 \"\"\n" + " 16 C_direct 4 \"(Virtual Base C)\"\n" + "}\n" + "Size = 24 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + @@ -4049,20 +4049,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/H\n" + - "Aligned\n" + + "pack()\n" + "Structure H {\n" + " 0 H_direct 8 \"\"\n" + " 8 C_direct 4 \"(Virtual Base C)\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + @@ -4121,20 +4121,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/H\n" + - "Aligned\n" + + "pack()\n" + "Structure H {\n" + " 0 H_direct 16 \"\"\n" + " 16 C_direct 4 \"(Virtual Base C)\"\n" + "}\n" + "Size = 24 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + @@ -4197,7 +4197,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/G1\n" + - "Aligned\n" + + "pack()\n" + "Structure G1 {\n" + " 0 G1_direct 8 \"\"\n" + " 8 C_direct 4 \"(Virtual Base C)\"\n" + @@ -4205,19 +4205,19 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 16 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + @@ -4281,7 +4281,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/G1\n" + - "Aligned\n" + + "pack()\n" + "Structure G1 {\n" + " 0 G1_direct 16 \"\"\n" + " 16 C_direct 4 \"(Virtual Base C)\"\n" + @@ -4289,19 +4289,19 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 24 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + @@ -4364,7 +4364,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/H1\n" + - "Aligned\n" + + "pack()\n" + "Structure H1 {\n" + " 0 H1_direct 8 \"\"\n" + " 8 E_direct 4 \"(Virtual Base E)\"\n" + @@ -4372,19 +4372,19 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 16 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + @@ -4448,7 +4448,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/H1\n" + - "Aligned\n" + + "pack()\n" + "Structure H1 {\n" + " 0 H1_direct 16 \"\"\n" + " 16 E_direct 4 \"(Virtual Base E)\"\n" + @@ -4456,19 +4456,19 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 24 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + @@ -4526,20 +4526,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG1\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1 {\n" + " 0 GG1_direct 8 \"\"\n" + " 8 CC1_direct 4 \"(Virtual Base CC1)\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG1/GG1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg11 \"\"\n" + @@ -4598,20 +4598,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG1\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1 {\n" + " 0 GG1_direct 16 \"\"\n" + " 16 CC1_direct 4 \"(Virtual Base CC1)\"\n" + "}\n" + "Size = 24 Actual Alignment = 8\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG1/GG1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg11 \"\"\n" + @@ -4669,20 +4669,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG2\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2 {\n" + " 0 GG2_direct 8 \"\"\n" + " 8 CC2_direct 4 \"(Virtual Base CC2)\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG2/GG2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg21 \"\"\n" + @@ -4741,20 +4741,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG2\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2 {\n" + " 0 GG2_direct 16 \"\"\n" + " 16 CC2_direct 4 \"(Virtual Base CC2)\"\n" + "}\n" + "Size = 24 Actual Alignment = 8\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG2/GG2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg21 \"\"\n" + @@ -4812,20 +4812,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG3\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3 {\n" + " 0 GG3_direct 8 \"\"\n" + " 8 CC2_direct 4 \"(Virtual Base CC2)\"\n" + "}\n" + "Size = 12 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg31 \"\"\n" + @@ -4884,20 +4884,20 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG3\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3 {\n" + " 0 GG3_direct 16 \"\"\n" + " 16 CC2_direct 4 \"(Virtual Base CC2)\"\n" + "}\n" + "Size = 24 Actual Alignment = 8\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg31 \"\"\n" + @@ -4958,13 +4958,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG4\n" + - "Aligned\n" + + "pack()\n" + "Structure GG4 {\n" + " 0 GG4_direct 8 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG4/GG4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG4_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg41 \"\"\n" + @@ -5026,13 +5026,13 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/GG4\n" + - "Aligned\n" + + "pack()\n" + "Structure GG4 {\n" + " 0 GG4_direct 16 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG4/GG4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG4_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg41 \"\"\n" + @@ -5102,34 +5102,34 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I\n" + - "Aligned\n" + + "pack()\n" + "Structure I {\n" + " 0 I_direct 20 \"\"\n" + " 20 C_direct 4 \"(Virtual Base C)\"\n" + "}\n" + "Size = 24 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I/I_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -5204,34 +5204,34 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I\n" + - "Aligned\n" + + "pack()\n" + "Structure I {\n" + " 0 I_direct 40 \"\"\n" + " 40 C_direct 4 \"(Virtual Base C)\"\n" + "}\n" + "Size = 48 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I/I_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -5306,7 +5306,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I1\n" + - "Aligned\n" + + "pack()\n" + "Structure I1 {\n" + " 0 I1_direct 20 \"\"\n" + " 20 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5314,33 +5314,33 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 28 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -5419,7 +5419,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I1\n" + - "Aligned\n" + + "pack()\n" + "Structure I1 {\n" + " 0 I1_direct 40 \"\"\n" + " 40 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5427,33 +5427,33 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 48 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -5529,7 +5529,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I2\n" + - "Aligned\n" + + "pack()\n" + "Structure I2 {\n" + " 0 I2_direct 20 \"\"\n" + " 20 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5537,33 +5537,33 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 28 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -5643,7 +5643,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I2\n" + - "Aligned\n" + + "pack()\n" + "Structure I2 {\n" + " 0 I2_direct 40 \"\"\n" + " 40 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5651,33 +5651,33 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 48 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -5753,7 +5753,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I3\n" + - "Aligned\n" + + "pack()\n" + "Structure I3 {\n" + " 0 I3_direct 20 \"\"\n" + " 20 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5761,33 +5761,33 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 28 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I3/I3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I3_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -5866,7 +5866,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I3\n" + - "Aligned\n" + + "pack()\n" + "Structure I3 {\n" + " 0 I3_direct 40 \"\"\n" + " 40 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5874,33 +5874,33 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 48 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I3/I3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I3_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -5967,7 +5967,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I4\n" + - "Aligned\n" + + "pack()\n" + "Structure I4 {\n" + " 0 I4_direct 12 \"\"\n" + " 12 C_direct 4 \"(Virtual Base C)\"\n" + @@ -5975,26 +5975,26 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I4/I4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I4_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 undefined4 4 i41 \"\"\n" + @@ -6062,7 +6062,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I4\n" + - "Aligned\n" + + "pack()\n" + "Structure I4 {\n" + " 0 I4_direct 24 \"\"\n" + " 24 C_direct 4 \"(Virtual Base C)\"\n" + @@ -6070,26 +6070,26 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 32 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I4/I4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I4_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 undefined4 4 i41 \"\"\n" + @@ -6155,7 +6155,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I5\n" + - "Aligned\n" + + "pack()\n" + "Structure I5 {\n" + " 0 I5_direct 12 \"\"\n" + " 12 E_direct 4 \"(Virtual Base E)\"\n" + @@ -6163,26 +6163,26 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I5/I5_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I5_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 undefined4 4 i51 \"\"\n" + @@ -6201,7 +6201,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I5\n" + - "Aligned\n" + + "pack()\n" + "Structure I5 {\n" + " 0 I5_direct 12 \"\"\n" + " 12 C_direct 4 \"((Speculative Placement) Virtual Base C)\"\n" + @@ -6209,26 +6209,26 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I5/I5_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I5_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 undefined4 4 i51 \"\"\n" + @@ -6292,7 +6292,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I5\n" + - "Aligned\n" + + "pack()\n" + "Structure I5 {\n" + " 0 I5_direct 24 \"\"\n" + " 24 E_direct 4 \"(Virtual Base E)\"\n" + @@ -6300,26 +6300,26 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 32 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I5/I5_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I5_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 undefined4 4 i51 \"\"\n" + @@ -6338,7 +6338,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/I5\n" + - "Aligned\n" + + "pack()\n" + "Structure I5 {\n" + " 0 I5_direct 24 \"\"\n" + " 24 C_direct 4 \"((Speculative Placement) Virtual Base C)\"\n" + @@ -6346,26 +6346,26 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 32 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I5/I5_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I5_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 undefined4 4 i51 \"\"\n" + @@ -6459,7 +6459,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J1\n" + - "Aligned\n" + + "pack()\n" + "Structure J1 {\n" + " 0 J1_direct 44 \"\"\n" + " 44 C_direct 4 \"(Virtual Base C)\"\n" + @@ -6467,47 +6467,47 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 52 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -6515,7 +6515,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -6523,7 +6523,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/J1/J1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J1_direct {\n" + " 0 I1_direct 20 \"\"\n" + " 20 I2_direct 20 \"\"\n" + @@ -6631,7 +6631,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J1\n" + - "Aligned\n" + + "pack()\n" + "Structure J1 {\n" + " 0 J1_direct 88 \"\"\n" + " 88 C_direct 4 \"(Virtual Base C)\"\n" + @@ -6639,47 +6639,47 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 96 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -6687,7 +6687,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -6695,7 +6695,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/J1/J1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J1_direct {\n" + " 0 I1_direct 40 \"\"\n" + " 40 I2_direct 40 \"\"\n" + @@ -6794,7 +6794,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J2\n" + - "Aligned\n" + + "pack()\n" + "Structure J2 {\n" + " 0 J2_direct 44 \"\"\n" + " 44 C_direct 4 \"(Virtual Base C)\"\n" + @@ -6802,47 +6802,47 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 52 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -6850,7 +6850,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -6858,7 +6858,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/J2/J2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J2_direct {\n" + " 0 I2_direct 20 \"\"\n" + " 20 I1_direct 20 \"\"\n" + @@ -6966,7 +6966,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J2\n" + - "Aligned\n" + + "pack()\n" + "Structure J2 {\n" + " 0 J2_direct 88 \"\"\n" + " 88 C_direct 4 \"(Virtual Base C)\"\n" + @@ -6974,47 +6974,47 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 96 Actual Alignment = 8\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -7022,7 +7022,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -7030,7 +7030,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/J2/J2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J2_direct {\n" + " 0 I2_direct 40 \"\"\n" + " 40 I1_direct 40 \"\"\n" + @@ -7134,7 +7134,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J3\n" + - "Aligned\n" + + "pack()\n" + "Structure J3 {\n" + " 0 J3_direct 52 \"\"\n" + " 52 C_direct 4 \"(Virtual Base C)\"\n" + @@ -7142,54 +7142,54 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 60 Actual Alignment = 4\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -7197,7 +7197,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -7205,7 +7205,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/J3/J3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J3_direct {\n" + " 0 I2_direct 20 \"\"\n" + " 20 I1_direct 20 \"\"\n" + @@ -7319,7 +7319,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J3\n" + - "Aligned\n" + + "pack()\n" + "Structure J3 {\n" + " 0 J3_direct 96 \"\"\n" + " 96 C_direct 4 \"(Virtual Base C)\"\n" + @@ -7327,54 +7327,54 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 104 Actual Alignment = 8\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I1/I1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I1_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -7382,7 +7382,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/I2/I2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I2_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -7390,7 +7390,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/J3/J3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J3_direct {\n" + " 0 I2_direct 40 \"\"\n" + " 40 I1_direct 40 \"\"\n" + @@ -7532,7 +7532,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J4\n" + - "Aligned\n" + + "pack()\n" + "Structure J4 {\n" + " 0 J4_direct 60 \"\"\n" + " 60 C_direct 4 \"(Virtual Base C)\"\n" + @@ -7544,87 +7544,87 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 92 Actual Alignment = 4\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG1/GG1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG2/GG2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg21 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg31 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I/I_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -7632,7 +7632,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/I3/I3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I3_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -7640,7 +7640,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/J4/J4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J4_direct {\n" + " 0 I3_direct 20 \"\"\n" + " 20 GG1_direct 8 \"\"\n" + @@ -7799,7 +7799,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J4\n" + - "Aligned\n" + + "pack()\n" + "Structure J4 {\n" + " 0 J4_direct 112 \"\"\n" + " 112 C_direct 4 \"(Virtual Base C)\"\n" + @@ -7811,87 +7811,87 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 160 Actual Alignment = 8\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG1/GG1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG2/GG2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg21 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg31 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I/I_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -7899,7 +7899,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/I3/I3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I3_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -7907,7 +7907,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/J4/J4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J4_direct {\n" + " 0 I3_direct 40 \"\"\n" + " 40 GG1_direct 16 \"\"\n" + @@ -8052,7 +8052,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J5\n" + - "Aligned\n" + + "pack()\n" + "Structure J5 {\n" + " 0 J5_direct 60 \"\"\n" + " 60 CC2_direct 4 \"(Virtual Base CC2)\"\n" + @@ -8064,87 +8064,87 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 92 Actual Alignment = 4\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG1/GG1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG2/GG2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg21 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg31 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/I/I_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I_direct {\n" + " 0 G_direct 8 \"\"\n" + " 8 H_direct 8 \"\"\n" + @@ -8152,7 +8152,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/I3/I3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I3_direct {\n" + " 0 G1_direct 8 \"\"\n" + " 8 H1_direct 8 \"\"\n" + @@ -8160,7 +8160,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 20 Actual Alignment = 4\n" + "/J5/J5_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J5_direct {\n" + " 0 I3_direct 20 \"\"\n" + " 20 GG1_direct 8 \"\"\n" + @@ -8327,7 +8327,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J5\n" + - "Aligned\n" + + "pack()\n" + "Structure J5 {\n" + " 0 J5_direct 112 \"\"\n" + " 112 CC2_direct 4 \"(Virtual Base CC2)\"\n" + @@ -8339,87 +8339,87 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 168 Actual Alignment = 8\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/C/C_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure C_direct {\n" + " 0 undefined4 4 c1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC1/CC1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC1_direct {\n" + " 0 undefined4 4 cc11 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/E/E_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure E_direct {\n" + " 0 undefined4 4 e1 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/G/G_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/G1/G1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure G1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 g11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG1/GG1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG2/GG2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG2_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg21 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg31 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H/H_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h1 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/H1/H1_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure H1_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 h11 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/I/I_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I_direct {\n" + " 0 G_direct 16 \"\"\n" + " 16 H_direct 16 \"\"\n" + @@ -8427,7 +8427,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/I3/I3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure I3_direct {\n" + " 0 G1_direct 16 \"\"\n" + " 16 H1_direct 16 \"\"\n" + @@ -8435,7 +8435,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 40 Actual Alignment = 8\n" + "/J5/J5_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J5_direct {\n" + " 0 I3_direct 40 \"\"\n" + " 40 GG1_direct 16 \"\"\n" + @@ -8532,7 +8532,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J6\n" + - "Aligned\n" + + "pack()\n" + "Structure J6 {\n" + " 0 J6_direct 16 \"\"\n" + " 16 GG4_direct 8 \"(Virtual Base GG4)\"\n" + @@ -8541,34 +8541,34 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 36 Actual Alignment = 4\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg31 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/GG4/GG4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG4_direct {\n" + " 0 int * 4 {vbptr} \"\"\n" + " 4 undefined4 4 gg41 \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/J6/J6_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J6_direct {\n" + " 0 A_direct 8 \"\"\n" + " 8 int * 4 {vbptr} \"\"\n" + @@ -8668,7 +8668,7 @@ public class CppCompositeTypeTest extends AbstractGenericTest { String expected = //@formatter:off "/J6\n" + - "Aligned\n" + + "pack()\n" + "Structure J6 {\n" + " 0 J6_direct 24 \"\"\n" + " 24 GG4_direct 16 \"(Virtual Base GG4)\"\n" + @@ -8677,34 +8677,34 @@ public class CppCompositeTypeTest extends AbstractGenericTest { "}\n" + "Size = 64 Actual Alignment = 8\n" + "/A/A_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure A_direct {\n" + " 0 undefined1 1 c \"\"\n" + " 4 undefined4 4 i \"\"\n" + "}\n" + "Size = 8 Actual Alignment = 4\n" + "/CC2/CC2_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure CC2_direct {\n" + " 0 undefined4 4 cc21 \"\"\n" + "}\n" + "Size = 4 Actual Alignment = 4\n" + "/GG3/GG3_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG3_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg31 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/GG4/GG4_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure GG4_direct {\n" + " 0 int * 8 {vbptr} \"\"\n" + " 8 undefined4 4 gg41 \"\"\n" + "}\n" + "Size = 16 Actual Alignment = 8\n" + "/J6/J6_direct\n" + - "Aligned\n" + + "pack()\n" + "Structure J6_direct {\n" + " 0 A_direct 8 \"\"\n" + " 8 int * 8 {vbptr} \"\"\n" + diff --git a/Ghidra/Framework/Generic/src/main/java/generic/test/TestUtils.java b/Ghidra/Framework/Generic/src/main/java/generic/test/TestUtils.java index dabae31d2e..205afad00e 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/test/TestUtils.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/test/TestUtils.java @@ -126,6 +126,7 @@ public class TestUtils { result = field.get(ownerInstance); } catch (Exception e) { + e.printStackTrace(); throw new RuntimeException("Unable to use reflection to obtain " + "field: " + fieldName + " from class: " + objectClass, e); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java index 5cb68fb9c3..6f7982bd1d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java @@ -201,7 +201,9 @@ public class DataTypeArchiveDB extends DomainObjectAdapterDB @Override protected void close() { super.close(); - dataTypeManager.dispose(); + if (dataTypeManager != null) { + dataTypeManager.dispose(); + } } @Override @@ -283,11 +285,15 @@ public class DataTypeArchiveDB extends DomainObjectAdapterDB * notification the a data type has changed * @param dataTypeID the id of the data type that changed. * @param type the type of the change (moved, renamed, etc.) + * @param isAutoResponseChange true if change is an auto-response change caused by + * another datatype's change (e.g., size, alignment), else false in which case this + * change will be added to archive change-set to aid merge conflict detection. * @param oldValue the old data type. * @param newValue the new data type. */ - public void dataTypeChanged(long dataTypeID, int type, Object oldValue, Object newValue) { - if (recordChanges) { + public void dataTypeChanged(long dataTypeID, int type, boolean isAutoResponseChange, + Object oldValue, Object newValue) { + if (recordChanges && !isAutoResponseChange) { ((DataTypeArchiveDBChangeSet) changeSet).dataTypeChanged(dataTypeID); } changed = true; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java index 907c388cfc..c7b62cced7 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java @@ -813,11 +813,17 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM * notification the a datatype has changed * @param dataTypeID the id of the datatype that changed. * @param type the type of the change (moved, renamed, etc.) + * @param isAutoChange true if change was an automatic change in response to + * another datatype's change (e.g., size, alignment), else false in which case this + * change will be added to program change-set to aid merge conflict detection. * @param oldValue the old datatype. * @param newValue the new datatype. */ - public void dataTypeChanged(long dataTypeID, int type, Object oldValue, Object newValue) { - if (recordChanges) { + public void dataTypeChanged(long dataTypeID, int type, boolean isAutoChange, + Object oldValue, Object newValue) { + // TODO: do not need to record type changes for packed composite change which is in repsonse + // to component size or alignment change. + if (recordChanges && !isAutoChange) { ((ProgramDBChangeSet) changeSet).dataTypeChanged(dataTypeID); } changed = true; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ArrayDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ArrayDB.java index 735e684a72..214ed21de9 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ArrayDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ArrayDB.java @@ -115,6 +115,11 @@ class ArrayDB extends DataTypeDB implements Array { return getDataType().isDynamicallySized(); } + @Override + public boolean isZeroLength() { + return getDataType().isZeroLength(); + } + @Override public int getLength() { checkIsValid(); @@ -244,10 +249,10 @@ class ArrayDB extends DataTypeDB implements Array { notifyNameChanged(myOldName); } if (getLength() != oldLength) { - notifySizeChanged(); + notifySizeChanged(false); } else { - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } } } @@ -265,10 +270,21 @@ class ArrayDB extends DataTypeDB implements Array { public void dataTypeSizeChanged(DataType dt) { lock.acquire(); try { - checkIsValid(); + if (checkIsValid() && dt == getDataType()) { + notifySizeChanged(true); + } + } + finally { + lock.release(); + } + } - if (dt == getDataType()) { - notifySizeChanged(); + @Override + public void dataTypeAlignmentChanged(DataType dt) { + lock.acquire(); + try { + if (checkIsValid() && dt == getDataType()) { + notifyAlignmentChanged(true); } } finally { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java index 10303f9fdf..1c66f7ded6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDB.java @@ -28,17 +28,7 @@ import ghidra.util.exception.AssertException; /** * Database implementation for a structure or union. */ -abstract class CompositeDB extends DataTypeDB implements Composite { - - // Internal Alignment Constants - protected static final int UNALIGNED = CompositeDBAdapter.UNALIGNED; - protected static final int ALIGNED_NO_PACKING = CompositeDBAdapter.ALIGNED_NO_PACKING; - // Otherwise the packing value (1 to (2**32 - 1)). - - // External (Minimum) Alignment Constants - protected static final int MACHINE_ALIGNED = CompositeDBAdapter.MACHINE_ALIGNED; - protected static final int DEFAULT_ALIGNED = CompositeDBAdapter.DEFAULT_ALIGNED; - // Otherwise the alignment value (1 to (2**32 - 1)). +abstract class CompositeDB extends DataTypeDB implements CompositeInternal { protected CompositeDBAdapter compositeAdapter; protected ComponentDBAdapter componentAdapter; @@ -81,7 +71,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { * @return preferred component length */ protected int getPreferredComponentLength(DataType dataType, int length) { - if ((isInternallyAligned() || (this instanceof Union)) && !(dataType instanceof Dynamic)) { + if ((isPackingEnabled() || (this instanceof Union)) && !(dataType instanceof Dynamic)) { length = -1; // force use of datatype size } int dtLength = dataType.getLength(); @@ -114,7 +104,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { * @param bitfieldComponent bitfield component * @param oldDt affected datatype which has been removed or replaced * @param newDt replacement datatype - * @param true if bitfield component was modified + * @return true if bitfield component was modified * @throws InvalidDataTypeException if bitfield was based upon oldDt but new * datatype is invalid for a bitfield */ @@ -200,7 +190,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { @Override public boolean isDynamicallySized() { - return isInternallyAligned(); + return isPackingEnabled(); } @Override @@ -301,7 +291,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { * @throws IllegalArgumentException if the data type is invalid. */ protected void validateDataType(DataType dataType) { - if (isInternallyAligned() && dataType == DataType.DEFAULT) { + if (isPackingEnabled() && dataType == DataType.DEFAULT) { throw new IllegalArgumentException( "The DEFAULT data type is not allowed in an aligned composite data type."); } @@ -335,7 +325,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { checkDeleted(); record.setLongValue(CompositeDBAdapter.COMPOSITE_LAST_CHANGE_TIME_COL, lastChangeTime); compositeAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -352,7 +342,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { checkDeleted(); record.setLongValue(CompositeDBAdapter.COMPOSITE_SOURCE_SYNC_TIME_COL, lastChangeTime); compositeAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -374,7 +364,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { checkDeleted(); record.setLongValue(CompositeDBAdapter.COMPOSITE_UNIVERSAL_DT_ID, id.getValue()); compositeAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -398,7 +388,7 @@ abstract class CompositeDB extends DataTypeDB implements Composite { checkDeleted(); record.setLongValue(CompositeDBAdapter.COMPOSITE_SOURCE_ARCHIVE_ID_COL, id.getValue()); compositeAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -409,56 +399,134 @@ abstract class CompositeDB extends DataTypeDB implements Composite { } - @Override - public int getPackingValue() { - int dbValue = record.getIntValue(CompositeDBAdapter.COMPOSITE_INTERNAL_ALIGNMENT_COL); - if (dbValue == CompositeDB.UNALIGNED || dbValue == CompositeDB.ALIGNED_NO_PACKING) { - return 0; + protected final int getNonPackedAlignment() { + int alignment; + int minimumAlignment = getStoredMinimumAlignment(); + if (minimumAlignment == DEFAULT_ALIGNMENT) { + alignment = 1; + } + else if (minimumAlignment == MACHINE_ALIGNMENT) { + alignment = getDataOrganization().getMachineAlignment(); + } + else { + alignment = minimumAlignment; + } + return alignment; + } + + /** + * Get computed alignment and optionally update record. May only be invoked with + * lock acquired. + * @param updateRecord if true record should be updated without timestamp change + * @return computed alignment + */ + protected abstract int getComputedAlignment(boolean updateRecord); + + @Override + public final int getAlignment() { + lock.acquire(); + try { + return getComputedAlignment(checkIsValid() && dataMgr.isTransactionActive()); + } + finally { + lock.release(); } - return dbValue; } @Override - public void setPackingValue(int packingValue) { - boolean changed = false; - if (!isInternallyAligned()) { - doSetInternallyAligned(true); - changed = true; + public final void repack() { + lock.acquire(); + try { + checkDeleted(); + repack(false, true); } - if (packingValue != getPackingValue()) { - doSetPackingValue(packingValue); - changed = true; - } - if (changed) { - adjustInternalAlignment(false); - notifyAlignmentChanged(); + finally { + lock.release(); } } - public void doSetPackingValue(int packingValue) { - if (packingValue < 0) { - packingValue = NOT_PACKING; + /** + * Repack components within this composite based on the current packing, alignment + * and {@link DataOrganization} settings. Non-packed Structures: change detection + * is limited to component count and length is assumed to already be correct. + * May only be invoked with lock acquired. + *

    + * NOTE: If modifications to stored length are made prior to invoking this method, + * detection of a size change may not be possible. + *

    + * NOTE: Currently a change in calculated alignment can not be provided since + * this value is not stored. + * + * @param isAutoChange true if changes are in response to another another datatype's change. + * @param notify if true notification will be sent to parents if a size change + * or component placement change is detected. + * @return true if a layout change was detected. + */ + protected abstract boolean repack(boolean isAutoChange, boolean notify); + + @Override + public int getStoredPackingValue() { + lock.acquire(); + try { + checkIsValid(); + return record.getIntValue(CompositeDBAdapter.COMPOSITE_PACKING_COL); + } + finally { + lock.release(); + } + } + + @Override + public PackingType getPackingType() { + int packing = getStoredPackingValue(); + if (packing < DEFAULT_PACKING) { + return PackingType.DISABLED; + } + if (packing == DEFAULT_PACKING) { + return PackingType.DEFAULT; + } + return PackingType.EXPLICIT; + } + + @Override + public int getExplicitPackingValue() { + return getStoredPackingValue(); + } + + @Override + public void setExplicitPackingValue(int packingValue) { + if (packingValue <= 0) { + throw new IllegalArgumentException( + "explicit packing value must be positive: " + packingValue); + } + setStoredPackingValue(packingValue); + } + + @Override + public void setToDefaultPacking() { + setStoredPackingValue(DEFAULT_PACKING); + } + + private void setStoredPackingValue(int packingValue) { + if (packingValue < NO_PACKING) { + throw new IllegalArgumentException("invalid packing value: " + packingValue); } lock.acquire(); try { checkDeleted(); - if (packingValue == getPackingValue()) { + int oldPackingValue = getStoredPackingValue(); + if (packingValue == oldPackingValue) { return; } - int dbPackingValue; - if (packingValue == NOT_PACKING) { - if (isInternallyAligned()) { - dbPackingValue = ALIGNED_NO_PACKING; - } - else { - dbPackingValue = UNALIGNED; - } + if (oldPackingValue == NO_PACKING || packingValue == NO_PACKING) { + // force default alignment when transitioning to or from disabled packing + record.setIntValue(CompositeDBAdapter.COMPOSITE_MIN_ALIGN_COL, DEFAULT_ALIGNMENT); } - else { - dbPackingValue = packingValue; - } - record.setIntValue(CompositeDBAdapter.COMPOSITE_INTERNAL_ALIGNMENT_COL, dbPackingValue); + record.setIntValue(CompositeDBAdapter.COMPOSITE_PACKING_COL, packingValue); compositeAdapter.updateRecord(record, true); + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); + } } catch (IOException e) { dataMgr.dbError(e); @@ -469,125 +537,72 @@ abstract class CompositeDB extends DataTypeDB implements Composite { } @Override - public boolean isDefaultAligned() { - int dbValue = record.getIntValue(CompositeDBAdapter.COMPOSITE_EXTERNAL_ALIGNMENT_COL); - return (dbValue == CompositeDB.DEFAULT_ALIGNED); + public AlignmentType getAlignmentType() { + int minimumAlignment = getStoredMinimumAlignment(); + if (minimumAlignment < DEFAULT_ALIGNMENT) { + return AlignmentType.MACHINE; + } + if (minimumAlignment == DEFAULT_ALIGNMENT) { + return AlignmentType.DEFAULT; + } + return AlignmentType.EXPLICIT; } @Override - public boolean isMachineAligned() { - int dbValue = record.getIntValue(CompositeDBAdapter.COMPOSITE_EXTERNAL_ALIGNMENT_COL); - return (dbValue == CompositeDB.MACHINE_ALIGNED); + public void setToDefaultAligned() { + setStoredMinimumAlignment(DEFAULT_ALIGNMENT); } @Override - public int getMinimumAlignment() { - int dbValue = record.getIntValue(CompositeDBAdapter.COMPOSITE_EXTERNAL_ALIGNMENT_COL); - if (dbValue == CompositeDB.MACHINE_ALIGNED) { - return getMachineAlignment(); - } - if (dbValue == CompositeDB.DEFAULT_ALIGNED) { - return getDefaultAlignment(); - } - return dbValue; - } - - private int getDefaultAlignment() { - return Composite.DEFAULT_ALIGNMENT_VALUE; - } - - private int getMachineAlignment() { - return dataMgr.getDataOrganization().getMachineAlignment(); + public void setToMachineAligned() { + setStoredMinimumAlignment(MACHINE_ALIGNMENT); } @Override - public void setMinimumAlignment(int externalAlignment) { - boolean changed = false; - if (!isInternallyAligned()) { - doSetInternallyAligned(true); - changed = true; - } - if (doSetMinimumAlignment(externalAlignment)) { - changed = true; - } - if (changed) { - adjustInternalAlignment(false); - notifyAlignmentChanged(); - } - } - - public boolean doSetMinimumAlignment(int externalAlignment) { - if (externalAlignment < 1) { - externalAlignment = DEFAULT_ALIGNED; - } - return modifyAlignment(externalAlignment); + public int getExplicitMinimumAlignment() { + return getStoredMinimumAlignment(); } @Override - public void setToDefaultAlignment() { - boolean changed = false; - if (!isInternallyAligned()) { - doSetInternallyAligned(true); - changed = true; + public int getStoredMinimumAlignment() { + lock.acquire(); + try { + checkIsValid(); + return record.getIntValue(CompositeDBAdapter.COMPOSITE_MIN_ALIGN_COL); } - if (doSetToDefaultAlignment()) { - changed = true; + finally { + lock.release(); } - if (changed) { - adjustInternalAlignment(false); - notifyAlignmentChanged(); - } - } - - public boolean doSetToDefaultAlignment() { - return modifyAlignment(CompositeDB.DEFAULT_ALIGNED); } @Override - public void setToMachineAlignment() { - boolean changed = false; - if (!isInternallyAligned()) { - doSetInternallyAligned(true); - changed = true; - } - if (doSetToMachineAlignment()) { - changed = true; - } - if (changed) { - adjustInternalAlignment(false); - notifyAlignmentChanged(); + public void setExplicitMinimumAlignment(int minimumAlignment) { + if (minimumAlignment <= 0) { + throw new IllegalArgumentException( + "explicit minimum alignment must be positive: " + minimumAlignment); } + setStoredMinimumAlignment(minimumAlignment); } - public boolean doSetToMachineAlignment() { - return modifyAlignment(CompositeDB.MACHINE_ALIGNED); - } - - private boolean modifyAlignment(int dbExternalAlignment) { + private void setStoredMinimumAlignment(int minimumAlignment) { + if (minimumAlignment < MACHINE_ALIGNMENT) { + throw new IllegalArgumentException( + "invalid minimum alignment value: " + minimumAlignment); + } lock.acquire(); try { checkDeleted(); - if (isMachineAligned()) { - if (dbExternalAlignment == MACHINE_ALIGNED) { - return false; - } + if (minimumAlignment == getStoredMinimumAlignment()) { + return; } - if (isDefaultAligned()) { - if (dbExternalAlignment == DEFAULT_ALIGNED) { - return false; - } - } - else if (dbExternalAlignment == getMinimumAlignment()) { - return false; - } - record.setIntValue(CompositeDBAdapter.COMPOSITE_EXTERNAL_ALIGNMENT_COL, - dbExternalAlignment); + record.setIntValue(CompositeDBAdapter.COMPOSITE_MIN_ALIGN_COL, minimumAlignment); compositeAdapter.updateRecord(record, true); - return true; + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); + } } catch (IOException e) { dataMgr.dbError(e); - return false; } finally { lock.release(); @@ -618,184 +633,40 @@ abstract class CompositeDB extends DataTypeDB implements Composite { } } - /** - * Notification that this composite data type's alignment has changed. - */ - protected void notifyAlignmentChanged() { - // TODO: This method is not properly invoked when new components are - // added which could change the alignment of this composite - for (DataType dt : dataMgr.getParentDataTypes(key)) { - if (dt instanceof Composite) { - Composite composite = (Composite) dt; - composite.dataTypeAlignmentChanged(this); - } - } - dataMgr.dataTypeChanged(this); - } - @Override - public boolean isInternallyAligned() { - int dbValue = record.getIntValue(CompositeDBAdapter.COMPOSITE_INTERNAL_ALIGNMENT_COL); - return dbValue != UNALIGNED; - } - - @Override - public void setInternallyAligned(boolean aligned) { - if (aligned == isInternallyAligned()) { + public void setPackingEnabled(boolean enabled) { + if (enabled == isPackingEnabled()) { return; } - doSetInternallyAligned(aligned); - adjustInternalAlignment(true); - notifyAlignmentChanged(); - } - - protected void doSetInternallyAligned(boolean aligned) { - lock.acquire(); - try { - checkDeleted(); - if (aligned == isInternallyAligned()) { - return; - } - int dbValue = aligned ? CompositeDB.ALIGNED_NO_PACKING : CompositeDB.UNALIGNED; - record.setIntValue(CompositeDBAdapter.COMPOSITE_INTERNAL_ALIGNMENT_COL, dbValue); - if (!aligned) { - int dbExternalAlignment = CompositeDB.DEFAULT_ALIGNED; - record.setIntValue(CompositeDBAdapter.COMPOSITE_EXTERNAL_ALIGNMENT_COL, - dbExternalAlignment); - } - compositeAdapter.updateRecord(record, true); - } - catch (IOException e) { - dataMgr.dbError(e); - } - finally { - lock.release(); - } - } - - protected void setAlignment(Composite composite, boolean notify) { - doSetInternallyAligned(composite.isInternallyAligned()); - - doSetPackingValue(composite.getPackingValue()); - - if (composite.isDefaultAligned()) { - doSetToDefaultAlignment(); - } - else if (composite.isMachineAligned()) { - doSetToMachineAlignment(); - } - else { - doSetMinimumAlignment(composite.getMinimumAlignment()); - } - adjustInternalAlignment(notify); + setStoredPackingValue(enabled ? DEFAULT_PACKING : NO_PACKING); } /** - * Adjusts the internal alignment of components within this composite based on - * the current settings of the internal alignment, packing, alignment type and - * minimum alignment value. This method should be called whenever any of the - * above settings are changed or whenever a components data type is changed or a - * component is added or removed. - * - * @param notify + * Copy packing and alignment settings from specified composite without + * repacking or notification. + * @param composite instance whose packing and alignment are to be copied + * @throws IOException if database IO error occured */ - protected abstract void adjustInternalAlignment(boolean notify); - - @Override - public int getAlignment() { - // TODO: use cached value if available (requires DB change to facilitate) - return CompositeAlignmentHelper.getAlignment(getDataOrganization(), this); - } - - /** - * Dump all components for use in {@link #toString()} representation. - * - * @param buffer string buffer - * @param pad padding to be used with each component output line - */ - protected void dumpComponents(StringBuilder buffer, String pad) { - // limit output of filler components for unaligned structures - DataTypeComponent[] components = getDefinedComponents(); - for (DataTypeComponent dtc : components) { - DataType dataType = dtc.getDataType(); - buffer.append(pad + dtc.getOffset()); - buffer.append(pad + dataType.getName()); - if (dataType instanceof BitFieldDataType) { - BitFieldDataType bfDt = (BitFieldDataType) dataType; - buffer.append("("); - buffer.append(Integer.toString(bfDt.getBitOffset())); - buffer.append(")"); - } - buffer.append(pad + dtc.getLength()); - buffer.append(pad + dtc.getFieldName()); - String comment = dtc.getComment(); - if (comment == null) { - comment = ""; - } - buffer.append(pad + "\"" + comment + "\""); - buffer.append("\n"); - } + protected void doSetPackingAndAlignment(CompositeInternal composite) throws IOException { + record.setIntValue(CompositeDBAdapter.COMPOSITE_MIN_ALIGN_COL, + composite.getStoredMinimumAlignment()); + record.setIntValue(CompositeDBAdapter.COMPOSITE_PACKING_COL, + composite.getStoredPackingValue()); + compositeAdapter.updateRecord(record, true); } @Override public String toString() { - StringBuilder stringBuffer = new StringBuilder(); - stringBuffer.append(getPathName() + "\n"); - stringBuffer.append(getAlignmentSettingsString() + "\n"); - stringBuffer.append(getTypeName() + " " + getDisplayName() + " {\n"); - dumpComponents(stringBuffer, " "); - stringBuffer.append("}\n"); - stringBuffer.append( - "Size = " + getLength() + " Actual Alignment = " + getAlignment() + "\n"); - return stringBuffer.toString(); + return CompositeDataTypeImpl.toString(this); } - - private String getTypeName() { - if (this instanceof Structure) { - return "Structure"; - } - else if (this instanceof Union) { - return "Union"; - } - return ""; - } - - private String getAlignmentSettingsString() { - StringBuffer stringBuffer = new StringBuffer(); - if (!isInternallyAligned()) { - stringBuffer.append("Unaligned"); - } - else if (isDefaultAligned()) { - stringBuffer.append("Aligned"); - } - else if (isMachineAligned()) { - stringBuffer.append("Machine aligned"); - } - else { - long alignment = getMinimumAlignment(); - stringBuffer.append("align(" + alignment + ")"); - } - stringBuffer.append(getPackingString()); - return stringBuffer.toString(); - } - - private String getPackingString() { - if (!isInternallyAligned()) { - return ""; - } - long packingValue = getPackingValue(); - if (packingValue == Composite.NOT_PACKING) { - return ""; - } - return " pack(" + packingValue + ")"; - } - + /** * Perform any neccessary component adjustments based on * sizes and alignment of components differing from their * specification which may be influenced by the data organization. * If this composite changes parents will not be * notified - handling this is the caller's responsibility. + * @throws IOException if database IO error occurs */ - protected abstract void fixupComponents(); + protected abstract void fixupComponents() throws IOException; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapter.java index 06642b19eb..de084a5d83 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapter.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapter.java @@ -18,8 +18,10 @@ package ghidra.program.database.data; import java.io.IOException; import db.*; +import ghidra.program.model.data.CompositeInternal; import ghidra.util.UniversalID; -import ghidra.util.exception.*; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; /** @@ -28,38 +30,29 @@ import ghidra.util.task.TaskMonitor; abstract class CompositeDBAdapter { static final String COMPOSITE_TABLE_NAME = "Composite Data Types"; - static final Schema COMPOSITE_SCHEMA = CompositeDBAdapterV2V3.V2_COMPOSITE_SCHEMA; + static final Schema COMPOSITE_SCHEMA = CompositeDBAdapterV5.V5_COMPOSITE_SCHEMA; - static final int COMPOSITE_NAME_COL = CompositeDBAdapterV2V3.V2_COMPOSITE_NAME_COL; - static final int COMPOSITE_COMMENT_COL = CompositeDBAdapterV2V3.V2_COMPOSITE_COMMENT_COL; - static final int COMPOSITE_IS_UNION_COL = CompositeDBAdapterV2V3.V2_COMPOSITE_IS_UNION_COL; - static final int COMPOSITE_CAT_COL = CompositeDBAdapterV2V3.V2_COMPOSITE_CAT_COL; - static final int COMPOSITE_LENGTH_COL = CompositeDBAdapterV2V3.V2_COMPOSITE_LENGTH_COL; + static final int COMPOSITE_NAME_COL = CompositeDBAdapterV5.V5_COMPOSITE_NAME_COL; + static final int COMPOSITE_COMMENT_COL = CompositeDBAdapterV5.V5_COMPOSITE_COMMENT_COL; + static final int COMPOSITE_IS_UNION_COL = CompositeDBAdapterV5.V5_COMPOSITE_IS_UNION_COL; + static final int COMPOSITE_CAT_COL = CompositeDBAdapterV5.V5_COMPOSITE_CAT_COL; + static final int COMPOSITE_LENGTH_COL = CompositeDBAdapterV5.V5_COMPOSITE_LENGTH_COL; + static final int COMPOSITE_ALIGNMENT_COL = CompositeDBAdapterV5.V5_COMPOSITE_ALIGNMENT_COL; static final int COMPOSITE_NUM_COMPONENTS_COL = - CompositeDBAdapterV2V3.V2_COMPOSITE_NUM_COMPONENTS_COL; + CompositeDBAdapterV5.V5_COMPOSITE_NUM_COMPONENTS_COL; static final int COMPOSITE_SOURCE_ARCHIVE_ID_COL = - CompositeDBAdapterV2V3.V2_COMPOSITE_SOURCE_ARCHIVE_ID_COL; + CompositeDBAdapterV5.V5_COMPOSITE_SOURCE_ARCHIVE_ID_COL; static final int COMPOSITE_UNIVERSAL_DT_ID = - CompositeDBAdapterV2V3.V2_COMPOSITE_UNIVERSAL_DT_ID_COL; + CompositeDBAdapterV5.V5_COMPOSITE_UNIVERSAL_DT_ID_COL; static final int COMPOSITE_SOURCE_SYNC_TIME_COL = - CompositeDBAdapterV2V3.V2_COMPOSITE_SOURCE_SYNC_TIME_COL; + CompositeDBAdapterV5.V5_COMPOSITE_SOURCE_SYNC_TIME_COL; static final int COMPOSITE_LAST_CHANGE_TIME_COL = - CompositeDBAdapterV2V3.V2_COMPOSITE_LAST_CHANGE_TIME_COL; - static final int COMPOSITE_INTERNAL_ALIGNMENT_COL = - CompositeDBAdapterV2V3.V2_COMPOSITE_INTERNAL_ALIGNMENT_COL; - static final int COMPOSITE_EXTERNAL_ALIGNMENT_COL = - CompositeDBAdapterV2V3.V2_COMPOSITE_EXTERNAL_ALIGNMENT_COL; + CompositeDBAdapterV5.V5_COMPOSITE_LAST_CHANGE_TIME_COL; + static final int COMPOSITE_PACKING_COL = + CompositeDBAdapterV5.V5_COMPOSITE_PACK_COL; + static final int COMPOSITE_MIN_ALIGN_COL = CompositeDBAdapterV5.V5_COMPOSITE_MIN_ALIGN_COL; - // Internal Alignment Constants - static final byte UNALIGNED = (byte) -1; - static final byte ALIGNED_NO_PACKING = (byte) 0; - // Otherwise the packing value. - - // External Alignment Constants - static final byte MACHINE_ALIGNED = (byte) -1; - static final byte DEFAULT_ALIGNED = (byte) 0; - - // Otherwise the external minimum alignment value. + // Stored Packing and Minimum Alignment values are consistent with CompositeInternal /** * Gets an adapter for working with the composite data type database table. @@ -75,18 +68,21 @@ abstract class CompositeDBAdapter { */ static CompositeDBAdapter getAdapter(DBHandle handle, int openMode, TaskMonitor monitor) throws VersionException, IOException, CancelledException { + if (openMode == DBConstants.CREATE) { + return new CompositeDBAdapterV5(handle, true); + } try { - return new CompositeDBAdapterV2V3(handle, openMode); + return new CompositeDBAdapterV5(handle, false); } catch (VersionException e) { - if (openMode == DBConstants.CREATE) { - throw new AssertException(); + if (!e.isUpgradable() || openMode == DBConstants.UPDATE) { + throw e; } + CompositeDBAdapter adapter = findReadOnlyAdapter(handle); if (openMode == DBConstants.UPGRADE) { - CompositeDBAdapter adapter = findReadOnlyAdapter(handle); return upgrade(handle, adapter, monitor); } - throw e; + return adapter; } } @@ -100,7 +96,7 @@ abstract class CompositeDBAdapter { static CompositeDBAdapter findReadOnlyAdapter(DBHandle handle) throws VersionException, IOException { try { - return new CompositeDBAdapterV2V3(handle); + return new CompositeDBAdapterV2V4(handle); } catch (VersionException e) { // ignore @@ -132,7 +128,7 @@ abstract class CompositeDBAdapter { long id = tmpHandle.startTransaction(); CompositeDBAdapter tmpAdapter = null; try { - tmpAdapter = new CompositeDBAdapterV2V3(tmpHandle, DBConstants.CREATE); + tmpAdapter = new CompositeDBAdapterV5(tmpHandle, true); RecordIterator it = oldAdapter.getRecords(); while (it.hasNext()) { monitor.checkCanceled(); @@ -140,7 +136,7 @@ abstract class CompositeDBAdapter { tmpAdapter.updateRecord(rec, false); } oldAdapter.deleteTable(handle); - CompositeDBAdapter newAdapter = new CompositeDBAdapterV2V3(handle, DBConstants.CREATE); + CompositeDBAdapter newAdapter = new CompositeDBAdapterV5(handle, true); it = tmpAdapter.getRecords(); while (it.hasNext()) { monitor.checkCanceled(); @@ -162,19 +158,20 @@ abstract class CompositeDBAdapter { * @param isUnion true indicates this data type is a union and all component offsets are at zero. * @param categoryID the ID for the category that contains this array. * @param length the total length or size of this data type. + * @param computedAlignment computed alignment for composite or -1 if not yet computed * @param sourceArchiveID the ID for the source archive where this data type originated. * @param sourceDataTypeID the ID of the associated data type in the source archive. * @param lastChangeTime the time this data type was last changed. - * @param internalAlignment UNALIGNED, ALIGNED_NO_PACKING or the packing value - * currently in use by this data type. - * @param externalAlignment DEFAULT_ALIGNED, MACHINE_ALIGNED or the minimum alignment value - * currently in use by this data type. + * @param packValue {@link CompositeInternal#NO_PACKING}, {@link CompositeInternal#DEFAULT_PACKING} + * or the explicit pack value currently in use by this data type (positive value). + * @param minAlignment {@link CompositeInternal#DEFAULT_ALIGNMENT}, {@link CompositeInternal#MACHINE_ALIGNMENT} + * or the minimum alignment value currently in use by this data type (positive value). * @return the database record for this data type. * @throws IOException if the database can't be accessed. */ abstract DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID, - int length, long sourceArchiveID, long sourceDataTypeID, long lastChangeTime, - int internalAlignment, int externalAlignment) throws IOException; + int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID, + long lastChangeTime, int packValue, int minAlignment) throws IOException; /** * Gets a composite data type record from the database based on its ID. diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV0.java index 42f5c382b2..c5bc3f7d13 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV0.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV0.java @@ -18,8 +18,7 @@ package ghidra.program.database.data; import java.io.IOException; import db.*; -import ghidra.program.model.data.DataType; -import ghidra.program.model.data.DataTypeManager; +import ghidra.program.model.data.*; import ghidra.util.UniversalID; import ghidra.util.UniversalIdGenerator; import ghidra.util.exception.VersionException; @@ -69,8 +68,8 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato @Override public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID, - int length, long sourceArchiveID, long sourceDataTypeID, long lastChangeTime, - int internalAlignment, int externalAlignment) throws IOException { + int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID, + long lastChangeTime, int packValue, int minAlignment) throws IOException { throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION + " of " + COMPOSITE_TABLE_NAME + " table."); } @@ -92,7 +91,8 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato @Override public boolean removeRecord(long compositeID) throws IOException { - return compositeTable.deleteRecord(compositeID); + throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION + + " of " + COMPOSITE_TABLE_NAME + " table."); } @Override @@ -129,8 +129,8 @@ class CompositeDBAdapterV0 extends CompositeDBAdapter implements RecordTranslato rec.setLongValue(COMPOSITE_UNIVERSAL_DT_ID, UniversalIdGenerator.nextID().getValue()); rec.setLongValue(COMPOSITE_SOURCE_SYNC_TIME_COL, DataType.NO_SOURCE_SYNC_TIME); rec.setLongValue(COMPOSITE_LAST_CHANGE_TIME_COL, DataType.NO_LAST_CHANGE_TIME); - rec.setIntValue(COMPOSITE_INTERNAL_ALIGNMENT_COL, CompositeDBAdapter.UNALIGNED); - rec.setIntValue(COMPOSITE_EXTERNAL_ALIGNMENT_COL, CompositeDBAdapter.DEFAULT_ALIGNED); + rec.setIntValue(COMPOSITE_PACKING_COL, CompositeInternal.NO_PACKING); + rec.setIntValue(COMPOSITE_MIN_ALIGN_COL, CompositeInternal.DEFAULT_ALIGNMENT); return rec; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV1.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV1.java index bc75c3ccec..6f59f436aa 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV1.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV1.java @@ -18,6 +18,7 @@ package ghidra.program.database.data; import java.io.IOException; import db.*; +import ghidra.program.model.data.CompositeInternal; import ghidra.util.UniversalID; import ghidra.util.exception.VersionException; @@ -37,13 +38,13 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato static final int V1_COMPOSITE_SOURCE_SYNC_TIME_COL = 8; static final int V1_COMPOSITE_LAST_CHANGE_TIME_COL = 9; - static final Schema V1_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID", - new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE, - LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, LongField.INSTANCE, - LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE }, - new String[] { "Name", "Comment", "Is Union", "Category ID", "Length", - "Number Of Components", "Source Archive ID", "Source Data Type ID", "Source Sync Time", - "Last Change Time" }); +// static final Schema V1_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID", +// new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE, +// LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, LongField.INSTANCE, +// LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE }, +// new String[] { "Name", "Comment", "Is Union", "Category ID", "Length", +// "Number Of Components", "Source Archive ID", "Source Data Type ID", "Source Sync Time", +// "Last Change Time" }); private Table compositeTable; @@ -72,8 +73,8 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato @Override public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID, - int length, long sourceArchiveID, long sourceDataTypeID, long lastChangeTime, - int internalAlignment, int externalAlignment) throws IOException { + int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID, + long lastChangeTime, int packValue, int minAlignment) throws IOException { throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION + " of " + COMPOSITE_TABLE_NAME + " table."); } @@ -95,7 +96,8 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato @Override public boolean removeRecord(long compositeID) throws IOException { - return compositeTable.deleteRecord(compositeID); + throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION + + " of " + COMPOSITE_TABLE_NAME + " table."); } @Override @@ -130,6 +132,7 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato oldRec.getBooleanValue(V1_COMPOSITE_IS_UNION_COL)); rec.setLongValue(COMPOSITE_CAT_COL, oldRec.getLongValue(V1_COMPOSITE_CAT_COL)); rec.setIntValue(COMPOSITE_LENGTH_COL, oldRec.getIntValue(V1_COMPOSITE_LENGTH_COL)); + rec.setIntValue(COMPOSITE_ALIGNMENT_COL, oldRec.getIntValue(-1)); rec.setIntValue(COMPOSITE_NUM_COMPONENTS_COL, oldRec.getIntValue(V1_COMPOSITE_NUM_COMPONENTS_COL)); rec.setLongValue(COMPOSITE_SOURCE_ARCHIVE_ID_COL, @@ -140,8 +143,8 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato oldRec.getLongValue(V1_COMPOSITE_SOURCE_SYNC_TIME_COL)); rec.setLongValue(COMPOSITE_LAST_CHANGE_TIME_COL, oldRec.getLongValue(V1_COMPOSITE_LAST_CHANGE_TIME_COL)); - rec.setIntValue(COMPOSITE_INTERNAL_ALIGNMENT_COL, CompositeDBAdapter.UNALIGNED); - rec.setIntValue(COMPOSITE_EXTERNAL_ALIGNMENT_COL, CompositeDBAdapter.DEFAULT_ALIGNED); + rec.setIntValue(COMPOSITE_PACKING_COL, CompositeInternal.NO_PACKING); + rec.setIntValue(COMPOSITE_MIN_ALIGN_COL, CompositeInternal.DEFAULT_ALIGNMENT); return rec; } @@ -150,8 +153,8 @@ class CompositeDBAdapterV1 extends CompositeDBAdapter implements RecordTranslato Field[] keys = compositeTable.findRecords(new LongField(datatypeID.getValue()), V1_COMPOSITE_UNIVERSAL_DT_ID_COL); - for (int i = 0; i < keys.length; i++) { - DBRecord record = compositeTable.getRecord(keys[i]); + for (Field key : keys) { + DBRecord record = compositeTable.getRecord(key); if (record.getLongValue(V1_COMPOSITE_SOURCE_ARCHIVE_ID_COL) == sourceID.getValue()) { return translateRecord(record); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV2V3.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV2V4.java similarity index 54% rename from Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV2V3.java rename to Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV2V4.java index 5a2b99a956..c3a3180179 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV2V3.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV2V4.java @@ -16,17 +16,15 @@ package ghidra.program.database.data; import java.io.IOException; -import java.util.Date; import db.*; -import ghidra.util.ReadOnlyException; import ghidra.util.UniversalID; import ghidra.util.exception.VersionException; /** - * Version 2-3 implementation for accessing the Composite database table. + * Version 2-4 implementation for accessing the Composite database table. */ -class CompositeDBAdapterV2V3 extends CompositeDBAdapter { +class CompositeDBAdapterV2V4 extends CompositeDBAdapter implements RecordTranslator { // While the addition of flex-array and bitfields does not impact the // actual schema the presence of such components can not be supported @@ -50,8 +48,8 @@ class CompositeDBAdapterV2V3 extends CompositeDBAdapter { static final int V2_COMPOSITE_UNIVERSAL_DT_ID_COL = 7; static final int V2_COMPOSITE_SOURCE_SYNC_TIME_COL = 8; static final int V2_COMPOSITE_LAST_CHANGE_TIME_COL = 9; - static final int V2_COMPOSITE_INTERNAL_ALIGNMENT_COL = 10; - static final int V2_COMPOSITE_EXTERNAL_ALIGNMENT_COL = 11; + static final int V2_COMPOSITE_PACK_COL = 10; // renamed from Internal Alignment + static final int V2_COMPOSITE_MIN_ALIGN_COL = 11; // renamed from External Alignment static final Schema V2_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID", new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE, @@ -60,44 +58,9 @@ class CompositeDBAdapterV2V3 extends CompositeDBAdapter { IntField.INSTANCE }, new String[] { "Name", "Comment", "Is Union", "Category ID", "Length", "Number Of Components", "Source Archive ID", "Source Data Type ID", "Source Sync Time", - "Last Change Time", "Internal Alignment", "External Alignment" }); + "Last Change Time", "Pack", "MinAlign" }); private Table compositeTable; - private boolean readOnly; - - /** - * Gets an adapter for the Composite database table. - * @param handle handle to the database containing the table. - * @param openMode the open mode - * @throws VersionException if the the table's version does not match the expected version - * for this adapter. - */ - public CompositeDBAdapterV2V3(DBHandle handle, int openMode) - throws VersionException, IOException { - readOnly = (openMode == DBConstants.READ_ONLY); - if (openMode == DBConstants.CREATE) { - compositeTable = handle.createTable(COMPOSITE_TABLE_NAME, V2_COMPOSITE_SCHEMA, - new int[] { V2_COMPOSITE_CAT_COL, V2_COMPOSITE_UNIVERSAL_DT_ID_COL }); - } - else { - compositeTable = handle.getTable(COMPOSITE_TABLE_NAME); - if (compositeTable == null) { - throw new VersionException("Missing Table: " + COMPOSITE_TABLE_NAME); - } - int version = compositeTable.getSchema().getVersion(); - if (version != VERSION) { - if (version < VERSION && version >= MIN_READ_ONLY_VERSION) { - if (openMode == DBConstants.READ_ONLY) { - return; // allow read-only immutable use - } - throw new VersionException(VersionException.OLDER_VERSION, true); - } - String msg = "Expected version 2-" + VERSION + " for table " + - COMPOSITE_TABLE_NAME + " but got " + version; - throw new VersionException(msg, VersionException.NEWER_VERSION, false); - } - } - } /** * Gets a read-only adapter for the Composite database table. @@ -105,8 +68,7 @@ class CompositeDBAdapterV2V3 extends CompositeDBAdapter { * @throws VersionException if the the table's version does not match the expected version * for this adapter. */ - public CompositeDBAdapterV2V3(DBHandle handle) throws VersionException { - readOnly = true; + public CompositeDBAdapterV2V4(DBHandle handle) throws VersionException { compositeTable = handle.getTable(COMPOSITE_TABLE_NAME); if (compositeTable == null) { throw new VersionException("Missing Table: " + COMPOSITE_TABLE_NAME); @@ -124,65 +86,31 @@ class CompositeDBAdapterV2V3 extends CompositeDBAdapter { @Override public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID, - int length, long sourceArchiveID, long sourceDataTypeID, long lastChangeTime, - int internalAlignment, int externalAlignment) throws IOException { - if (readOnly) { - throw new ReadOnlyException(); - } - if (internalAlignment == UNALIGNED) { - length = 0; // aligned structures always start empty - } - long tableKey = compositeTable.getKey(); -// if (tableKey <= DataManager.VOID_DATATYPE_ID) { -// tableKey = DataManager.VOID_DATATYPE_ID +1; -// } - long key = DataTypeManagerDB.createKey(DataTypeManagerDB.COMPOSITE, tableKey); - DBRecord record = CompositeDBAdapter.COMPOSITE_SCHEMA.createRecord(key); - - record.setString(V2_COMPOSITE_NAME_COL, name); - record.setString(V2_COMPOSITE_COMMENT_COL, comments); - record.setBooleanValue(V2_COMPOSITE_IS_UNION_COL, isUnion); - record.setLongValue(V2_COMPOSITE_CAT_COL, categoryID); - record.setIntValue(V2_COMPOSITE_LENGTH_COL, length); - record.setIntValue(V2_COMPOSITE_NUM_COMPONENTS_COL, length); - record.setLongValue(V2_COMPOSITE_SOURCE_ARCHIVE_ID_COL, sourceArchiveID); - record.setLongValue(V2_COMPOSITE_UNIVERSAL_DT_ID_COL, sourceDataTypeID); - record.setLongValue(V2_COMPOSITE_SOURCE_SYNC_TIME_COL, lastChangeTime); - record.setLongValue(V2_COMPOSITE_LAST_CHANGE_TIME_COL, lastChangeTime); - record.setIntValue(V2_COMPOSITE_INTERNAL_ALIGNMENT_COL, internalAlignment); - record.setIntValue(V2_COMPOSITE_EXTERNAL_ALIGNMENT_COL, externalAlignment); - compositeTable.putRecord(record); - return record; + int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID, + long lastChangeTime, int packValue, int minAlignment) throws IOException { + throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION + + " of " + COMPOSITE_TABLE_NAME + " table."); } @Override public DBRecord getRecord(long dataTypeID) throws IOException { - return compositeTable.getRecord(dataTypeID); + return translateRecord(compositeTable.getRecord(dataTypeID)); } @Override public RecordIterator getRecords() throws IOException { - return compositeTable.iterator(); + return new TranslatedRecordIterator(compositeTable.iterator(), this); } @Override public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException { - if (readOnly) { - throw new ReadOnlyException(); - } - if (setLastChangeTime) { - record.setLongValue(CompositeDBAdapter.COMPOSITE_LAST_CHANGE_TIME_COL, - (new Date()).getTime()); - } - compositeTable.putRecord(record); + throw new UnsupportedOperationException(); } @Override public boolean removeRecord(long compositeID) throws IOException { - if (readOnly) { - throw new ReadOnlyException(); - } - return compositeTable.deleteRecord(compositeID); + throw new UnsupportedOperationException("Not allowed to update prior version #" + VERSION + + " of " + COMPOSITE_TABLE_NAME + " table."); } @Override @@ -202,15 +130,46 @@ class CompositeDBAdapterV2V3 extends CompositeDBAdapter { V2_COMPOSITE_SOURCE_ARCHIVE_ID_COL); } + /* (non-Javadoc) + * @see db.RecordTranslator#translateRecord(db.Record) + */ + @Override + public DBRecord translateRecord(DBRecord oldRec) { + if (oldRec == null) { + return null; + } + DBRecord rec = CompositeDBAdapter.COMPOSITE_SCHEMA.createRecord(oldRec.getKey()); + rec.setString(COMPOSITE_NAME_COL, oldRec.getString(V2_COMPOSITE_NAME_COL)); + rec.setString(COMPOSITE_COMMENT_COL, oldRec.getString(V2_COMPOSITE_COMMENT_COL)); + rec.setBooleanValue(COMPOSITE_IS_UNION_COL, + oldRec.getBooleanValue(V2_COMPOSITE_IS_UNION_COL)); + rec.setLongValue(COMPOSITE_CAT_COL, oldRec.getLongValue(V2_COMPOSITE_CAT_COL)); + rec.setIntValue(COMPOSITE_LENGTH_COL, oldRec.getIntValue(V2_COMPOSITE_LENGTH_COL)); + rec.setIntValue(COMPOSITE_ALIGNMENT_COL, -1); + rec.setIntValue(COMPOSITE_NUM_COMPONENTS_COL, + oldRec.getIntValue(V2_COMPOSITE_NUM_COMPONENTS_COL)); + rec.setLongValue(COMPOSITE_SOURCE_ARCHIVE_ID_COL, + oldRec.getLongValue(V2_COMPOSITE_SOURCE_ARCHIVE_ID_COL)); + rec.setLongValue(COMPOSITE_UNIVERSAL_DT_ID, + oldRec.getLongValue(V2_COMPOSITE_UNIVERSAL_DT_ID_COL)); + rec.setLongValue(COMPOSITE_SOURCE_SYNC_TIME_COL, + oldRec.getLongValue(V2_COMPOSITE_SOURCE_SYNC_TIME_COL)); + rec.setLongValue(COMPOSITE_LAST_CHANGE_TIME_COL, + oldRec.getLongValue(V2_COMPOSITE_LAST_CHANGE_TIME_COL)); + rec.setIntValue(COMPOSITE_PACKING_COL, oldRec.getIntValue(V2_COMPOSITE_PACK_COL)); + rec.setIntValue(COMPOSITE_MIN_ALIGN_COL, oldRec.getIntValue(V2_COMPOSITE_MIN_ALIGN_COL)); + return rec; + } + @Override DBRecord getRecordWithIDs(UniversalID sourceID, UniversalID datatypeID) throws IOException { Field[] keys = compositeTable.findRecords(new LongField(datatypeID.getValue()), V2_COMPOSITE_UNIVERSAL_DT_ID_COL); - for (int i = 0; i < keys.length; i++) { - DBRecord record = compositeTable.getRecord(keys[i]); + for (Field key : keys) { + DBRecord record = compositeTable.getRecord(key); if (record.getLongValue(V2_COMPOSITE_SOURCE_ARCHIVE_ID_COL) == sourceID.getValue()) { - return record; + return translateRecord(record); } } return null; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV5.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV5.java new file mode 100644 index 0000000000..5d7ba54b78 --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/CompositeDBAdapterV5.java @@ -0,0 +1,176 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.database.data; + +import java.io.IOException; +import java.util.Date; + +import db.*; +import ghidra.program.model.data.CompositeInternal; +import ghidra.util.UniversalID; +import ghidra.util.exception.VersionException; + +/** + * Version 5 implementation for accessing the Composite database table. + * This version introduces the retained computed alignment to reduce + * need for recalculation and to allow for improved change detection. + */ +class CompositeDBAdapterV5 extends CompositeDBAdapter { + + static final int VERSION = 5; + + static final int V5_COMPOSITE_NAME_COL = 0; + static final int V5_COMPOSITE_COMMENT_COL = 1; + static final int V5_COMPOSITE_IS_UNION_COL = 2; + static final int V5_COMPOSITE_CAT_COL = 3; + static final int V5_COMPOSITE_LENGTH_COL = 4; + static final int V5_COMPOSITE_ALIGNMENT_COL = 5; + static final int V5_COMPOSITE_NUM_COMPONENTS_COL = 6; + static final int V5_COMPOSITE_SOURCE_ARCHIVE_ID_COL = 7; + static final int V5_COMPOSITE_UNIVERSAL_DT_ID_COL = 8; + static final int V5_COMPOSITE_SOURCE_SYNC_TIME_COL = 9; + static final int V5_COMPOSITE_LAST_CHANGE_TIME_COL = 10; + static final int V5_COMPOSITE_PACK_COL = 11; + static final int V5_COMPOSITE_MIN_ALIGN_COL = 12; + + static final Schema V5_COMPOSITE_SCHEMA = new Schema(VERSION, "Data Type ID", + new Field[] { StringField.INSTANCE, StringField.INSTANCE, BooleanField.INSTANCE, + LongField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, IntField.INSTANCE, + LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, + IntField.INSTANCE, IntField.INSTANCE }, + new String[] { "Name", "Comment", "Is Union", "Category ID", "Length", "Alignment", + "Number Of Components", "Source Archive ID", "Source Data Type ID", "Source Sync Time", + "Last Change Time", "Pack", "MinAlign" }); + + private Table compositeTable; + + /** + * Gets an adapter for the Composite database table. + * @param handle handle to the database containing the table. + * @param create true if this constructor should create the table. + * @throws VersionException if the the table's version does not match the expected version + * for this adapter. + * @throws IOException if IO error occurs + */ + public CompositeDBAdapterV5(DBHandle handle, boolean create) + throws VersionException, IOException { + if (create) { + compositeTable = handle.createTable(COMPOSITE_TABLE_NAME, V5_COMPOSITE_SCHEMA, + new int[] { V5_COMPOSITE_CAT_COL, V5_COMPOSITE_UNIVERSAL_DT_ID_COL }); + } + else { + compositeTable = handle.getTable(COMPOSITE_TABLE_NAME); + if (compositeTable == null) { + throw new VersionException("Missing Table: " + COMPOSITE_TABLE_NAME); + } + int version = compositeTable.getSchema().getVersion(); + if (version != VERSION) { + String msg = "Expected version " + VERSION + " for table " + COMPOSITE_TABLE_NAME + + " but got " + version; + if (version < VERSION) { + throw new VersionException(msg, VersionException.OLDER_VERSION, true); + } + throw new VersionException(msg, VersionException.NEWER_VERSION, false); + } + } + } + + @Override + public DBRecord createRecord(String name, String comments, boolean isUnion, long categoryID, + int length, int computedAlignment, long sourceArchiveID, long sourceDataTypeID, + long lastChangeTime, int packValue, int minAlignment) throws IOException { + if (packValue < CompositeInternal.DEFAULT_ALIGNMENT) { + packValue = CompositeInternal.NO_PACKING; + } + else { + length = 0; // aligned structures always start empty + } + long key = + DataTypeManagerDB.createKey(DataTypeManagerDB.COMPOSITE, compositeTable.getKey()); + DBRecord record = CompositeDBAdapter.COMPOSITE_SCHEMA.createRecord(key); + + record.setString(V5_COMPOSITE_NAME_COL, name); + record.setString(V5_COMPOSITE_COMMENT_COL, comments); + record.setBooleanValue(V5_COMPOSITE_IS_UNION_COL, isUnion); + record.setLongValue(V5_COMPOSITE_CAT_COL, categoryID); + record.setIntValue(V5_COMPOSITE_LENGTH_COL, length); + record.setIntValue(V5_COMPOSITE_ALIGNMENT_COL, computedAlignment); + record.setIntValue(V5_COMPOSITE_NUM_COMPONENTS_COL, length); + record.setLongValue(V5_COMPOSITE_SOURCE_ARCHIVE_ID_COL, sourceArchiveID); + record.setLongValue(V5_COMPOSITE_UNIVERSAL_DT_ID_COL, sourceDataTypeID); + record.setLongValue(V5_COMPOSITE_SOURCE_SYNC_TIME_COL, lastChangeTime); + record.setLongValue(V5_COMPOSITE_LAST_CHANGE_TIME_COL, lastChangeTime); + record.setIntValue(V5_COMPOSITE_PACK_COL, packValue); + record.setIntValue(V5_COMPOSITE_MIN_ALIGN_COL, minAlignment); + compositeTable.putRecord(record); + return record; + } + + @Override + public DBRecord getRecord(long dataTypeID) throws IOException { + return compositeTable.getRecord(dataTypeID); + } + + @Override + public RecordIterator getRecords() throws IOException { + return compositeTable.iterator(); + } + + @Override + public void updateRecord(DBRecord record, boolean setLastChangeTime) throws IOException { + if (setLastChangeTime) { + record.setLongValue(CompositeDBAdapter.COMPOSITE_LAST_CHANGE_TIME_COL, + (new Date()).getTime()); + } + compositeTable.putRecord(record); + } + + @Override + public boolean removeRecord(long compositeID) throws IOException { + return compositeTable.deleteRecord(compositeID); + } + + @Override + void deleteTable(DBHandle handle) throws IOException { + handle.deleteTable(COMPOSITE_TABLE_NAME); + } + + @Override + public Field[] getRecordIdsInCategory(long categoryID) throws IOException { + return compositeTable.findRecords(new LongField(categoryID), + CompositeDBAdapter.COMPOSITE_CAT_COL); + } + + @Override + Field[] getRecordIdsForSourceArchive(long archiveID) throws IOException { + return compositeTable.findRecords(new LongField(archiveID), + V5_COMPOSITE_SOURCE_ARCHIVE_ID_COL); + } + + @Override + DBRecord getRecordWithIDs(UniversalID sourceID, UniversalID datatypeID) throws IOException { + Field[] keys = compositeTable.findRecords(new LongField(datatypeID.getValue()), + V5_COMPOSITE_UNIVERSAL_DT_ID_COL); + + for (Field key : keys) { + DBRecord record = compositeTable.getRecord(key); + if (record.getLongValue(V5_COMPOSITE_SOURCE_ARCHIVE_ID_COL) == sourceID.getValue()) { + return record; + } + } + return null; + } +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeComponentDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeComponentDB.java index fd6036582f..02b679a601 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeComponentDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeComponentDB.java @@ -148,7 +148,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent { @Override public int getOffset() { if (isFlexibleArrayComponent) { - if (parent.isNotYetDefined()) { + if (parent.isZeroLength()) { // some structures have only a flexible array defined return 0; } @@ -223,7 +223,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent { if (record != null) { record.setString(ComponentDBAdapter.COMPONENT_COMMENT_COL, comment); adapter.updateRecord(record); - notifyChanged(); + dataMgr.dataTypeChanged(getParent(), false); } } catch (IOException e) { @@ -268,7 +268,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent { } record.setString(ComponentDBAdapter.COMPONENT_FIELD_NAME_COL, name); adapter.updateRecord(record); - notifyChanged(); + dataMgr.dataTypeChanged(getParent(), false); } } catch (IOException e) { @@ -279,7 +279,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent { private void checkDuplicateName(String name) throws DuplicateNameException { DataTypeComponentImpl.checkDefaultFieldName(name); - for (DataTypeComponent comp : parent.getComponents()) { + for (DataTypeComponent comp : parent.getDefinedComponents()) { if (comp == this) { continue; } @@ -344,7 +344,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent { } DataType myParent = getParent(); boolean aligned = - (myParent instanceof Composite) ? ((Composite) myParent).isInternallyAligned() : false; + (myParent instanceof Composite) ? ((Composite) myParent).isPackingEnabled() : false; // Components don't need to have matching offset when they are aligned // NOTE: use getOffset() method since returned values will differ from // stored values for flexible array component @@ -452,11 +452,6 @@ class DataTypeComponentDB implements InternalDataTypeComponent { } } - private void notifyChanged() { - DataType dt = getParent(); - dataMgr.dataTypeChanged(dt); - } - @Override public String toString() { StringBuffer buffer = new StringBuffer(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeDB.java index 385460394f..8d2bca488c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeDB.java @@ -19,9 +19,6 @@ import java.io.IOException; import java.net.URL; import java.util.List; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - import db.DBRecord; import ghidra.docking.settings.Settings; import ghidra.docking.settings.SettingsDefinition; @@ -38,7 +35,7 @@ import ghidra.util.exception.NotYetImplementedException; * * */ -abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeListener { +abstract class DataTypeDB extends DatabaseObject implements DataType { protected DBRecord record; protected final DataTypeManagerDB dataMgr; @@ -125,9 +122,11 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList return false; } - /** - * @see ghidra.program.model.data.DataType#getDisplayName() - */ + @Override + public boolean isZeroLength() { + return false; + } + @Override public String getDisplayName() { return getName(); @@ -159,9 +158,6 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList return name; } - /** - * @see ghidra.program.model.data.DataType#getDefaultSettings() - */ @Override public Settings getDefaultSettings() { Settings localDefaultSettings = defaultSettings; @@ -182,9 +178,6 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList } - /** - * @see ghidra.program.model.data.DataType#getDocs() - */ @Override public URL getDocs() { return null; @@ -203,49 +196,31 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList throw new NotYetImplementedException("setValue() not implemented"); } - /** - * @see ghidra.program.model.data.DataType#getSettingsDefinitions() - */ @Override public SettingsDefinition[] getSettingsDefinitions() { return EMPTY_DEFINITIONS; } - /** - * @see ghidra.program.model.data.DataType#isDeleted() - */ @Override public boolean isDeleted() { return isDeleted(lock); } - /** - * @see ghidra.program.model.data.DataType#update(ghidra.program.model.data.DataType) - */ @Override public void dataTypeSizeChanged(DataType dt) { - // no-op + // do nothing } - /** - * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) - */ @Override - public void stateChanged(ChangeEvent e) { - dataMgr.dataTypeChanged(this); + public void dataTypeAlignmentChanged(DataType dt) { + // do nothing } - /** - * @see ghidra.program.model.data.DataType#getDataTypeManager() - */ @Override public DataTypeManager getDataTypeManager() { return dataMgr; } - /** - * @see ghidra.program.model.data.DataType#setDefaultSettings(ghidra.docking.settings.Settings) - */ @Override public void setDefaultSettings(Settings settings) { checkIsValid(); @@ -259,12 +234,9 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList return 1; } DataOrganization dataOrganization = dataMgr.getDataOrganization(); - return dataOrganization.getAlignment(this, length); + return dataOrganization.getAlignment(this); } - /** - * @see ghidra.program.model.data.DataType#getPathName() - */ @Override public String getPathName() { return getDataTypePath().getPath(); @@ -320,9 +292,6 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList return new DataTypePath(getCategoryPath(), getName()); } - /** - * @see ghidra.program.model.data.DataType#setName(java.lang.String) - */ @Override public void setName(String name) throws InvalidNameException, DuplicateNameException { lock.acquire(); @@ -357,9 +326,6 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList } - /** - * @see ghidra.program.model.data.DataType#setCategoryPath(ghidra.program.model.data.CategoryPath) - */ @Override public void setCategoryPath(CategoryPath path) throws DuplicateNameException { lock.acquire(); @@ -450,11 +416,28 @@ abstract class DataTypeDB extends DatabaseObject implements DataType, ChangeList } } - protected void notifySizeChanged() { + /** + * Notify all parents that the size of this datatype has changed or + * other significant change that may affect a parent containing this + * datatype. + * @param isAutoChange true if changes are in response to another datatype's change. + */ + protected void notifySizeChanged(boolean isAutoChange) { for (DataType dt : dataMgr.getParentDataTypes(key)) { dt.dataTypeSizeChanged(this); } - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, isAutoChange); + } + + /** + * Notification that this composite data type's alignment has changed. + * @param isAutoChange true if changes are in response to another datatype's change. + */ + protected void notifyAlignmentChanged(boolean isAutoChange) { + for (DataType dt : dataMgr.getParentDataTypes(key)) { + dt.dataTypeAlignmentChanged(this); + } + dataMgr.dataTypeChanged(this, isAutoChange); } protected void notifyNameChanged(String oldName) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java index d13259b763..4c16940a5a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java @@ -490,6 +490,16 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } } + /** + * Determine if transaction is active. With proper lock established + * this method may be useful for determining if a lazy record update + * may be performed. + * @return true if database transaction if active, else false + */ + protected final boolean isTransactionActive() { + return dbHandle.isTransactionActive(); + } + abstract protected String getDomainFileID(); abstract protected String getPath(); @@ -983,19 +993,19 @@ abstract public class DataTypeManagerDB implements DataTypeManager { try { if (existingDataType instanceof StructureDB) { - if (!(dataType instanceof Structure)) { + if (!(dataType instanceof StructureInternal)) { return false; } StructureDB existingStruct = (StructureDB) existingDataType; - existingStruct.doReplaceWith((Structure) dataType, true); + existingStruct.doReplaceWith((StructureInternal) dataType, true); return true; } else if (existingDataType instanceof UnionDB) { - if (!(dataType instanceof Union)) { + if (!(dataType instanceof UnionInternal)) { return false; } UnionDB existingUnion = (UnionDB) existingDataType; - existingUnion.doReplaceWith((Union) dataType, true); + existingUnion.doReplaceWith((UnionInternal) dataType, true); return true; } } @@ -1121,7 +1131,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { long lastChangeTime = dataType.getLastChangeTime(); existingDataType.setLastChangeTime(lastChangeTime); existingDataType.setLastChangeTimeInSourceArchive(lastChangeTime); - dataTypeChanged(existingDataType); + dataTypeChanged(existingDataType, false); return existingDataType; } @@ -1725,7 +1735,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { idsToDataTypeMap.removeDataType(sourceArchive, oldDtID); } - dataTypeChanged(dataType); + dataTypeChanged(dataType, false); } finally { lock.release(); @@ -2307,8 +2317,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager { int len = ptr.isDynamicallySized() ? -1 : ptr.getLength(); newDataType = createPointer(ptr.getDataType(), cat, (byte) len, handler); } - else if (dt instanceof Structure) { - Structure structure = (Structure) dt; + else if (dt instanceof StructureInternal) { + StructureInternal structure = (StructureInternal) dt; newDataType = createStructure(structure, name, cat, sourceArchiveIdValue, id.getValue()); } @@ -2317,8 +2327,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager { newDataType = createTypeDef(typedef, name, cat, sourceArchiveIdValue, id.getValue()); } - else if (dt instanceof Union) { - Union union = (Union) dt; + else if (dt instanceof UnionInternal) { + UnionInternal union = (UnionInternal) dt; newDataType = createUnion(union, name, cat, sourceArchiveIdValue, id.getValue()); } @@ -2352,7 +2362,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { return null; } - private Structure createStructure(Structure struct, String name, CategoryDB category, + private Structure createStructure(StructureInternal struct, String name, CategoryDB category, long sourceArchiveIdValue, long universalIdValue) throws IOException { try { @@ -2361,13 +2371,13 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } creatingDataType++; int len = struct.getLength(); - if (struct.isNotYetDefined() || struct.isInternallyAligned()) { + if (struct.isZeroLength() || struct.isPackingEnabled()) { len = 0; } DBRecord record = compositeAdapter.createRecord(name, struct.getDescription(), false, - category.getID(), len, sourceArchiveIdValue, universalIdValue, - struct.getLastChangeTime(), getInternalAlignment(struct), - getExternalAlignment(struct)); + category.getID(), len, -1, sourceArchiveIdValue, + universalIdValue, struct.getLastChangeTime(), + struct.getStoredPackingValue(), struct.getStoredMinimumAlignment()); StructureDB structDB = new StructureDB(this, dtCache, compositeAdapter, componentAdapter, record); @@ -2378,7 +2388,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { structDB.doReplaceWith(struct, false); structDB.setDescription(struct.getDescription()); // structDB.notifySizeChanged(); - // doReplaceWith updated the last change time so set it back to what we want. + // doReplaceWith may have updated the last change time so set it back to what we want. structDB.setLastChangeTime(struct.getLastChangeTime()); return structDB; @@ -2395,32 +2405,32 @@ abstract public class DataTypeManagerDB implements DataTypeManager { return dbHandle.isChanged(); } - private int getExternalAlignment(Composite struct) { - if (struct.isDefaultAligned()) { - return CompositeDB.DEFAULT_ALIGNED; - } - else if (struct.isMachineAligned()) { - return CompositeDB.MACHINE_ALIGNED; - } - else { - int alignment = struct.getMinimumAlignment(); - if (alignment == 0) { - return CompositeDB.DEFAULT_ALIGNED; - } - return alignment; - } - } +// private int getExternalAlignment(Composite struct) { +// if (struct.isDefaultAligned()) { +// return CompositeDB.DEFAULT_ALIGNED; +// } +// else if (struct.isMachineAligned()) { +// return CompositeDB.MACHINE_ALIGNED; +// } +// else { +// int alignment = struct.getAlignment(); +// if (alignment <= 0) { +// return CompositeDB.DEFAULT_ALIGNED; +// } +// return alignment; +// } +// } - private int getInternalAlignment(Composite struct) { - if (struct.isInternallyAligned()) { - int packingValue = struct.getPackingValue(); - if (packingValue == 0) { - return CompositeDB.ALIGNED_NO_PACKING; - } - return packingValue; - } - return CompositeDB.UNALIGNED; - } +// private int getInternalAlignment(Composite struct) { +// if (struct.isPackingEnabled()) { +// int packingValue = struct.getPackingValue(); +// if (packingValue == 0) { +// return CompositeDB.ALIGNED_NO_PACKING; +// } +// return packingValue; +// } +// return CompositeDB.UNALIGNED; +// } private TypeDef createTypeDef(TypeDef typedef, String name, Category cat, long sourceArchiveIdValue, long universalIdValue) @@ -2437,7 +2447,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { return typedefDB; } - private Union createUnion(Union union, String name, CategoryDB category, + private Union createUnion(UnionInternal union, String name, CategoryDB category, long sourceArchiveIdValue, long universalIdValue) throws IOException { if (name == null || name.length() == 0) { @@ -2446,8 +2456,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager { try { creatingDataType++; DBRecord record = compositeAdapter.createRecord(name, null, true, category.getID(), 0, - sourceArchiveIdValue, universalIdValue, union.getLastChangeTime(), - getInternalAlignment(union), getExternalAlignment(union)); + -1, sourceArchiveIdValue, universalIdValue, + union.getLastChangeTime(), union.getStoredPackingValue(), union.getStoredMinimumAlignment()); UnionDB unionDB = new UnionDB(this, dtCache, compositeAdapter, componentAdapter, record); @@ -3585,7 +3595,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } @Override - public void dataTypeChanged(DataType dt) { + public void dataTypeChanged(DataType dt, boolean isAutoChange) { if (dt instanceof Enum) { enumValueMap = null; } @@ -3852,6 +3862,9 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } } + catch (IOException e) { + dbError(e); + } finally { lock.release(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/EnumDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/EnumDB.java index 7e9bfc7fae..25fae1ab2b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/EnumDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/EnumDB.java @@ -19,8 +19,8 @@ import java.io.IOException; import java.math.BigInteger; import java.util.*; -import db.Field; import db.DBRecord; +import db.Field; import ghidra.docking.settings.Settings; import ghidra.docking.settings.SettingsDefinition; import ghidra.program.database.DBObjectCache; @@ -216,7 +216,7 @@ class EnumDB extends DataTypeDB implements Enum { valueAdapter.createRecord(key, valueName, value); adapter.updateRecord(record, true); addToCache(valueName, value); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { @@ -263,7 +263,7 @@ class EnumDB extends DataTypeDB implements Enum { } } adapter.updateRecord(record, true); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -309,10 +309,10 @@ class EnumDB extends DataTypeDB implements Enum { } if (oldLength != newLength) { - notifySizeChanged(); + notifySizeChanged(false); } else { - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } } catch (IOException e) { @@ -386,7 +386,7 @@ class EnumDB extends DataTypeDB implements Enum { checkDeleted(); record.setString(EnumDBAdapter.ENUM_COMMENT_COL, description); adapter.updateRecord(record, true); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -620,7 +620,7 @@ class EnumDB extends DataTypeDB implements Enum { checkDeleted(); record.setLongValue(EnumDBAdapter.ENUM_UNIVERSAL_DT_ID_COL, id.getValue()); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -642,7 +642,7 @@ class EnumDB extends DataTypeDB implements Enum { checkDeleted(); record.setLongValue(EnumDBAdapter.ENUM_SOURCE_ARCHIVE_ID_COL, id.getValue()); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -659,7 +659,7 @@ class EnumDB extends DataTypeDB implements Enum { checkDeleted(); record.setLongValue(EnumDBAdapter.ENUM_LAST_CHANGE_TIME_COL, lastChangeTime); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -677,7 +677,7 @@ class EnumDB extends DataTypeDB implements Enum { record.setLongValue(EnumDBAdapter.ENUM_SOURCE_SYNC_TIME_COL, lastChangeTimeInSourceArchive); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/FunctionDefinitionDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/FunctionDefinitionDB.java index f9cdd08e93..a69b9e5c17 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/FunctionDefinitionDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/FunctionDefinitionDB.java @@ -18,8 +18,8 @@ package ghidra.program.database.data; import java.io.IOException; import java.util.*; -import db.Field; import db.DBRecord; +import db.Field; import ghidra.docking.settings.Settings; import ghidra.program.database.DBObjectCache; import ghidra.program.model.data.*; @@ -268,7 +268,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { } loadParameters(); funDefAdapter.updateRecord(record, true); // update last change time - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -293,7 +293,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { dataMgr.getID(resolvedDt)); funDefAdapter.updateRecord(record, true); resolvedDt.addParent(this); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -310,7 +310,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { checkDeleted(); record.setString(FunctionDefinitionDBAdapter.FUNCTION_DEF_COMMENT_COL, comment); funDefAdapter.updateRecord(record, true); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -523,7 +523,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { record.setByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_FLAGS_COL, flags); try { funDefAdapter.updateRecord(record, true); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -552,7 +552,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { record.setByteValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_FLAGS_COL, flags); try { funDefAdapter.updateRecord(record, true); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -600,7 +600,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { record.setLongValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_LAST_CHANGE_TIME_COL, lastChangeTime); funDefAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -618,7 +618,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { record.setLongValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_SOURCE_SYNC_TIME_COL, lastChangeTime); funDefAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -642,7 +642,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { record.setLongValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_SOURCE_DT_ID_COL, id.getValue()); funDefAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -666,7 +666,7 @@ class FunctionDefinitionDB extends DataTypeDB implements FunctionDefinition { record.setLongValue(FunctionDefinitionDBAdapter.FUNCTION_DEF_SOURCE_ARCHIVE_ID_COL, id.getValue()); funDefAdapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ParameterDefinitionDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ParameterDefinitionDB.java index 81194843c7..2c9a15fced 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ParameterDefinitionDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ParameterDefinitionDB.java @@ -76,7 +76,7 @@ final class ParameterDefinitionDB implements ParameterDefinition { record.setIntValue(FunctionParameterAdapter.PARAMETER_DT_LENGTH_COL, type.getLength()); try { adapter.updateRecord(record); - dataMgr.dataTypeChanged(parent); + dataMgr.dataTypeChanged(parent, false); } catch (IOException e) { dataMgr.dbError(e); @@ -109,7 +109,7 @@ final class ParameterDefinitionDB implements ParameterDefinition { record.setString(FunctionParameterAdapter.PARAMETER_NAME_COL, name); try { adapter.updateRecord(record); - dataMgr.dataTypeChanged(parent); + dataMgr.dataTypeChanged(parent, false); } catch (IOException e) { dataMgr.dbError(e); @@ -126,7 +126,7 @@ final class ParameterDefinitionDB implements ParameterDefinition { record.setString(FunctionParameterAdapter.PARAMETER_COMMENT_COL, comment); try { adapter.updateRecord(record); - dataMgr.dataTypeChanged(parent); + dataMgr.dataTypeChanged(parent, false); } catch (IOException e) { dataMgr.dbError(e); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java index 3732d38535..a9c41bdb60 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java @@ -130,12 +130,13 @@ public class ProgramDataTypeManager extends DataTypeManagerDB } @Override - public void dataTypeChanged(DataType dt) { - super.dataTypeChanged(dt); + public void dataTypeChanged(DataType dt, boolean isAutoChange) { + super.dataTypeChanged(dt, isAutoChange); if (!isCreatingDataType()) { program.getCodeManager().invalidateCache(false); program.getFunctionManager().invalidateCache(false); - program.dataTypeChanged(getID(dt), ChangeManager.DOCR_DATA_TYPE_CHANGED, null, dt); + program.dataTypeChanged(getID(dt), ChangeManager.DOCR_DATA_TYPE_CHANGED, + isAutoChange, null, dt); } } @@ -149,7 +150,8 @@ public class ProgramDataTypeManager extends DataTypeManagerDB protected void dataTypeReplaced(long existingDtID, DataTypePath existingPath, DataType replacementDt) { super.dataTypeReplaced(existingDtID, existingPath, replacementDt); - program.dataTypeChanged(existingDtID, ChangeManager.DOCR_DATA_TYPE_REPLACED, existingPath, + program.dataTypeChanged(existingDtID, ChangeManager.DOCR_DATA_TYPE_REPLACED, true, + existingPath, replacementDt); } @@ -157,20 +159,20 @@ public class ProgramDataTypeManager extends DataTypeManagerDB protected void dataTypeDeleted(long deletedID, DataTypePath deletedDataTypePath) { super.dataTypeDeleted(deletedID, deletedDataTypePath); program.dataTypeChanged(deletedID, ChangeManager.DOCR_DATA_TYPE_REMOVED, - deletedDataTypePath, null); + false, deletedDataTypePath, null); } @Override protected void dataTypeMoved(DataType dt, DataTypePath oldPath, DataTypePath newPath) { super.dataTypeMoved(dt, oldPath, newPath); Category category = getCategory(oldPath.getCategoryPath()); - program.dataTypeChanged(getID(dt), ChangeManager.DOCR_DATA_TYPE_MOVED, category, dt); + program.dataTypeChanged(getID(dt), ChangeManager.DOCR_DATA_TYPE_MOVED, false, category, dt); } @Override protected void dataTypeNameChanged(DataType dt, String oldName) { super.dataTypeNameChanged(dt, oldName); - program.dataTypeChanged(getID(dt), ChangeManager.DOCR_DATA_TYPE_RENAMED, oldName, dt); + program.dataTypeChanged(getID(dt), ChangeManager.DOCR_DATA_TYPE_RENAMED, false, oldName, dt); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java index 009b565cba..a7ad073dd5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java @@ -97,12 +97,12 @@ public class ProjectDataTypeManager extends DataTypeManagerDB //////////////////// @Override - public void dataTypeChanged(DataType dt) { - super.dataTypeChanged(dt); + public void dataTypeChanged(DataType dt, boolean isAutoChange) { + super.dataTypeChanged(dt, isAutoChange); // dataTypeArchive.getCodeManager().invalidateCache(false); // TODO dataTypeArchive.dataTypeChanged(getID(dt), - DataTypeArchiveChangeManager.DOCR_DATA_TYPE_CHANGED, null, dt); + DataTypeArchiveChangeManager.DOCR_DATA_TYPE_CHANGED, isAutoChange, null, dt); } @Override @@ -118,14 +118,15 @@ public class ProjectDataTypeManager extends DataTypeManagerDB DataType replacementDt) { super.dataTypeReplaced(existingDtID, existingPath, replacementDt); dataTypeArchive.dataTypeChanged(existingDtID, - DataTypeArchiveChangeManager.DOCR_DATA_TYPE_REPLACED, existingPath, replacementDt); + DataTypeArchiveChangeManager.DOCR_DATA_TYPE_REPLACED, false, existingPath, + replacementDt); } @Override protected void dataTypeDeleted(long deletedID, DataTypePath deletedDataTypePath) { super.dataTypeDeleted(deletedID, deletedDataTypePath); dataTypeArchive.dataTypeChanged(deletedID, - DataTypeArchiveChangeManager.DOCR_DATA_TYPE_REMOVED, deletedDataTypePath, null); + DataTypeArchiveChangeManager.DOCR_DATA_TYPE_REMOVED, false, deletedDataTypePath, null); } @Override @@ -133,14 +134,14 @@ public class ProjectDataTypeManager extends DataTypeManagerDB super.dataTypeMoved(dt, oldPath, newPath); Category category = getCategory(oldPath.getCategoryPath()); dataTypeArchive.dataTypeChanged(getID(dt), - DataTypeArchiveChangeManager.DOCR_DATA_TYPE_MOVED, category, dt); + DataTypeArchiveChangeManager.DOCR_DATA_TYPE_MOVED, false, category, dt); } @Override protected void dataTypeNameChanged(DataType dt, String oldName) { super.dataTypeNameChanged(dt, oldName); dataTypeArchive.dataTypeChanged(getID(dt), - DataTypeArchiveChangeManager.DOCR_DATA_TYPE_RENAMED, oldName, dt); + DataTypeArchiveChangeManager.DOCR_DATA_TYPE_RENAMED, false, oldName, dt); } @Override diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/SettingsDBManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/SettingsDBManager.java index 951d095629..43308626e6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/SettingsDBManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/SettingsDBManager.java @@ -18,8 +18,8 @@ package ghidra.program.database.data; import java.io.IOException; import java.util.*; -import db.Field; import db.DBRecord; +import db.Field; import ghidra.docking.settings.Settings; import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataTypeComponent; @@ -63,11 +63,13 @@ class SettingsDBManager implements Settings { } private void settingsChanged() { + // NOTE: There is currently no merge support for settings so recording within + // domain object change set is unneccessary if (dtc != null) { - dataMgr.dataTypeChanged(dtc.getParent()); + dataMgr.dataTypeChanged(dtc.getParent(), true); } else { - dataMgr.dataTypeChanged(dataType); + dataMgr.dataTypeChanged(dataType, true); } } @@ -178,11 +180,11 @@ class SettingsDBManager implements Settings { try { Field[] keys = adapter.getSettingsKeys(dataTypeID); - for (int i = 0; i < keys.length; i++) { - DBRecord rec = adapter.getSettingsRecord(keys[i].getLongValue()); + for (Field key : keys) { + DBRecord rec = adapter.getSettingsRecord(key.getLongValue()); String settingsName = rec.getString(SettingsDBAdapter.SETTINGS_NAME_COL); if (settingsName.equals(name)) { - adapter.removeSettingsRecord(keys[i].getLongValue()); + adapter.removeSettingsRecord(key.getLongValue()); settingsChanged(); return; } @@ -197,8 +199,8 @@ class SettingsDBManager implements Settings { public void clearAllSettings() { try { Field[] keys = adapter.getSettingsKeys(dataTypeID); - for (int i = 0; i < keys.length; i++) { - adapter.removeSettingsRecord(keys[i].getLongValue()); + for (Field key : keys) { + adapter.removeSettingsRecord(key.getLongValue()); } settingsChanged(); } @@ -212,8 +214,8 @@ class SettingsDBManager implements Settings { List list = new ArrayList(); try { Field[] keys = adapter.getSettingsKeys(dataTypeID); - for (int i = 0; i < keys.length; i++) { - DBRecord rec = adapter.getSettingsRecord(keys[i].getLongValue()); + for (Field key : keys) { + DBRecord rec = adapter.getSettingsRecord(key.getLongValue()); String name = rec.getString(SettingsDBAdapter.SETTINGS_NAME_COL); if (!list.contains(name)) { list.add(name); @@ -242,8 +244,8 @@ class SettingsDBManager implements Settings { void update(Settings settings) { clearAllSettings(); String[] names = settings.getNames(); - for (int i = 0; i < names.length; i++) { - setValue(names[i], settings.getValue(names[i])); + for (String name : names) { + setValue(name, settings.getValue(name)); } } @@ -278,8 +280,8 @@ class SettingsDBManager implements Settings { private DBRecord getRecord(String name) { try { Field[] keys = adapter.getSettingsKeys(dataTypeID); - for (int i = 0; i < keys.length; i++) { - DBRecord rec = adapter.getSettingsRecord(keys[i].getLongValue()); + for (Field key : keys) { + DBRecord rec = adapter.getSettingsRecord(key.getLongValue()); if (rec.getString(SettingsDBAdapter.SETTINGS_NAME_COL).equals(name)) { return rec; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java index 8361f1ddcc..e9007008df 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java @@ -18,8 +18,8 @@ package ghidra.program.database.data; import java.io.IOException; import java.util.*; -import db.Field; import db.DBRecord; +import db.Field; import ghidra.docking.settings.Settings; import ghidra.program.database.DBObjectCache; import ghidra.program.model.data.*; @@ -33,17 +33,15 @@ import ghidra.util.exception.AssertException; * * */ -class StructureDB extends CompositeDB implements Structure { - private static OrdinalComparator ordinalComparator = new OrdinalComparator(); - private static OffsetComparator offsetComparator = new OffsetComparator(); - private static ComponentComparator componentComparator = new ComponentComparator(); - protected static Comparator bitOffsetComparatorLE = new BitOffsetComparator(false); - protected static Comparator bitOffsetComparatorBE = new BitOffsetComparator(true); +class StructureDB extends CompositeDB implements StructureInternal { + private int structLength; - private int numComponents; // If aligned, this does not include the undefined data types. - private ArrayList components; + private int structAlignment; // reflects stored alignment, -1 if not yet stored + private int computedAlignment = -1; // cached alignment if not yet stored + + private int numComponents; // If packed, this does not include the undefined components. + private List components; private DataTypeComponentDB flexibleArrayComponent; - private int alignment = -1; /** * Constructor @@ -83,9 +81,11 @@ class StructureDB extends CompositeDB implements Structure { dataMgr.dbError(e); } - Collections.sort(components, componentComparator); + Collections.sort(components, ComponentComparator.INSTANCE); structLength = record.getIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL); + structAlignment = record.getIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL); + computedAlignment = -1; numComponents = record.getIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL); } @@ -109,13 +109,16 @@ class StructureDB extends CompositeDB implements Structure { } private DataTypeComponent doAdd(DataType dataType, int length, String name, String comment, - boolean validateAlignAndNotify) + boolean validatePackAndNotify) throws DataTypeDependencyException, IllegalArgumentException { + + // TODO: May want to standardize flex-array use with StructureDataType + lock.acquire(); try { checkDeleted(); - if (validateAlignAndNotify) { + if (validatePackAndNotify) { validateDataType(dataType); dataType = resolve(dataType); checkAncestry(dataType); @@ -124,6 +127,7 @@ class StructureDB extends CompositeDB implements Structure { DataTypeComponentDB dtc = null; try { if (dataType == DataType.DEFAULT) { + // FIXME: verify - does not appear to modify structure dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, key, numComponents, structLength); } @@ -137,22 +141,20 @@ class StructureDB extends CompositeDB implements Structure { } int structureGrowth = dtc.getLength(); - if (!isInternallyAligned() && length > 0) { + if (!isPackingEnabled() && length > 0) { structureGrowth = length; } ++numComponents; structLength += structureGrowth; - if (validateAlignAndNotify) { - + if (validatePackAndNotify) { + repack(false, false); // may not recognize length change record.setIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL, numComponents); record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength); - compositeAdapter.updateRecord(record, true); - - adjustInternalAlignment(false); - notifySizeChanged(); + compositeAdapter.updateRecord(record, true); // update timestamp + notifySizeChanged(false); } } catch (IOException e) { @@ -166,13 +168,16 @@ class StructureDB extends CompositeDB implements Structure { } private DataTypeComponent doAddFlexArray(DataType dataType, String name, String comment, - boolean validateAlignAndNotify) + boolean validatePackAndNotify) throws DataTypeDependencyException, IllegalArgumentException { + + // TODO: May want to standardize implementation with StructureDataType + lock.acquire(); try { checkDeleted(); - if (validateAlignAndNotify) { + if (validatePackAndNotify) { validateDataType(dataType); dataType = resolve(dataType); if (isInvalidFlexArrayDataType(dataType)) { @@ -185,8 +190,6 @@ class StructureDB extends CompositeDB implements Structure { DataTypeComponentDB dtc = null; try { - int oldLength = structLength; - if (flexibleArrayComponent != null) { flexibleArrayComponent.getDataType().removeParent(this); componentAdapter.removeRecord(flexibleArrayComponent.getKey()); @@ -199,14 +202,10 @@ class StructureDB extends CompositeDB implements Structure { dataType.addParent(this); flexibleArrayComponent = dtc; - if (validateAlignAndNotify) { - adjustInternalAlignment(false); - if (oldLength != structLength) { - notifySizeChanged(); - } - else { - dataMgr.dataTypeChanged(this); - } + if (validatePackAndNotify) { + repack(false, false); + compositeAdapter.updateRecord(record, true); + notifySizeChanged(false); } } catch (IOException e) { @@ -221,14 +220,15 @@ class StructureDB extends CompositeDB implements Structure { @Override public void growStructure(int amount) { + if (isPackingEnabled()) { + return; + } lock.acquire(); try { checkDeleted(); - if (!isInternallyAligned()) { - doGrowStructure(amount); - } - adjustInternalAlignment(true); - notifySizeChanged(); + doGrowStructure(amount); + repack(false, false); + notifySizeChanged(false); } finally { lock.release(); @@ -236,7 +236,7 @@ class StructureDB extends CompositeDB implements Structure { } private void doGrowStructure(int amount) { - if (!isInternallyAligned()) { + if (!isPackingEnabled()) { numComponents += amount; } record.setIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL, numComponents); @@ -257,7 +257,7 @@ class StructureDB extends CompositeDB implements Structure { try { checkDeleted(); if (ordinal < 0 || ordinal > numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } if (ordinal == numComponents) { return add(dataType, length, name, comment); @@ -268,14 +268,14 @@ class StructureDB extends CompositeDB implements Structure { checkAncestry(dataType); int idx; - if (isInternallyAligned()) { + if (isPackingEnabled()) { idx = ordinal; } else { // TODO: could improve insertion of bitfield which does not intersect // existing ordinal bitfield at the bit-level idx = Collections.binarySearch(components, Integer.valueOf(ordinal), - ordinalComparator); + OrdinalComparator.INSTANCE); if (idx > 0) { DataTypeComponentDB existingDtc = components.get(idx); if (existingDtc.isBitFieldComponent()) { @@ -291,9 +291,9 @@ class StructureDB extends CompositeDB implements Structure { idx = -idx - 1; } if (dataType == DataType.DEFAULT) { - // assume unaligned insert of DEFAULT + // assume non-packed insert of DEFAULT shiftOffsets(idx, 1, 1); - notifySizeChanged(); + notifySizeChanged(false); return getComponent(ordinal); } @@ -306,8 +306,8 @@ class StructureDB extends CompositeDB implements Structure { dataType.addParent(this); shiftOffsets(idx, 1, dtc.getLength()); components.add(idx, dtc); - adjustInternalAlignment(true); - notifySizeChanged(); + repack(false, false); + notifySizeChanged(false); return dtc; } catch (DataTypeDependencyException e) { @@ -336,16 +336,16 @@ class StructureDB extends CompositeDB implements Structure { @Override public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset, DataType baseDataType, int bitSize, String componentName, String comment) - throws InvalidDataTypeException, ArrayIndexOutOfBoundsException { + throws InvalidDataTypeException, IndexOutOfBoundsException { lock.acquire(); try { checkDeleted(); if (ordinal < 0 || ordinal > numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } - if (!isInternallyAligned()) { + if (!isPackingEnabled()) { int offset = structLength; if (ordinal < numComponents) { offset = getComponent(ordinal).getOffset(); @@ -399,7 +399,7 @@ class StructureDB extends CompositeDB implements Structure { byteWidth, effectiveBitSize, bitOffset, bigEndian); Comparator bitOffsetComparator = - bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE; + bigEndian ? BitOffsetComparator.INSTANCE_BE : BitOffsetComparator.INSTANCE_LE; int startIndex = Collections.binarySearch(components, Integer.valueOf(startBitOffset), bitOffsetComparator); if (startIndex < 0) { @@ -425,7 +425,7 @@ class StructureDB extends CompositeDB implements Structure { ordinal = startIndex; } - if (isInternallyAligned()) { + if (isPackingEnabled()) { insertBitField(ordinal, 0, 0, baseDataType, effectiveBitSize, componentName, comment); } @@ -480,8 +480,8 @@ class StructureDB extends CompositeDB implements Structure { bitfieldDt.addParent(this); // has no affect components.add(startIndex, dtc); - adjustUnalignedComponents(); - notifySizeChanged(); + adjustNonPackedComponents(true); + notifySizeChanged(false); return dtc; } catch (IOException e) { @@ -499,26 +499,26 @@ class StructureDB extends CompositeDB implements Structure { try { checkDeleted(); if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } int idx; - if (isInternallyAligned()) { + if (isPackingEnabled()) { idx = ordinal; } else { idx = Collections.binarySearch(components, Integer.valueOf(ordinal), - ordinalComparator); + OrdinalComparator.INSTANCE); } if (idx >= 0) { - doDelete(idx); - adjustInternalAlignment(false); + doDelete(idx); // updates timestamp } else { - // assume unaligned removal of DEFAULT + // assume non-packed removal of DEFAULT idx = -idx - 1; - shiftOffsets(idx, -1, -1); + shiftOffsets(idx, -1, -1); // updates timestamp } - notifySizeChanged(); + repack(false, false); + notifySizeChanged(false); } finally { lock.release(); @@ -534,7 +534,7 @@ class StructureDB extends CompositeDB implements Structure { catch (IOException e) { dataMgr.dbError(e); } - if (isInternallyAligned()) { + if (isPackingEnabled()) { return; } int shiftAmount = dtc.isBitFieldComponent() ? 0 : dtc.getLength(); @@ -542,42 +542,84 @@ class StructureDB extends CompositeDB implements Structure { } @Override - public void delete(int[] ordinals) { + public void delete(Set ordinals) { lock.acquire(); try { checkDeleted(); - for (int ordinal : ordinals) { - if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + + if (ordinals.isEmpty()) { + return; + } + + boolean bitFieldRemoved = false; + + TreeSet treeSet = null; + if (!isPackingEnabled()) { + // treeSet only used to track undefined filler removal + treeSet = new TreeSet<>(ordinals); + } + + List newComponents = new ArrayList<>(); + int ordinalAdjustment = 0; + int offsetAdjustment = 0; + int lastDefinedOrdinal = -1; + for (DataTypeComponentDB dtc : components) { + int ordinal = dtc.getOrdinal(); + if (treeSet != null && lastDefinedOrdinal < (ordinal - 1)) { + // Identify removed filler since last defined component + Set removedFillerSet = treeSet.subSet(lastDefinedOrdinal + 1, ordinal); + if (!removedFillerSet.isEmpty()) { + int undefinedRemoveCount = removedFillerSet.size(); + ordinalAdjustment -= undefinedRemoveCount; + offsetAdjustment -= undefinedRemoveCount; + } + } + if (ordinals.contains(ordinal)) { + // defined component removed + if (dtc.isBitFieldComponent()) { + // defer reconciling bitfield space to repack + bitFieldRemoved = true; + } + else { + offsetAdjustment -= dtc.getLength(); + } + --ordinalAdjustment; + lastDefinedOrdinal = ordinal; + } + else { + if (ordinalAdjustment != 0) { + shiftOffset(dtc, ordinalAdjustment, offsetAdjustment); + } + newComponents.add(dtc); + lastDefinedOrdinal = ordinal; + } + } + if (treeSet != null) { + // Identify removed filler after last defined component + Set removedFillerSet = + treeSet.subSet(lastDefinedOrdinal + 1, numComponents); + if (!removedFillerSet.isEmpty()) { + int undefinedRemoveCount = removedFillerSet.size(); + ordinalAdjustment -= undefinedRemoveCount; + offsetAdjustment -= undefinedRemoveCount; } } - // delete ordinals in reverse order so that they remain valid - // during individual deletes - int[] sortedOrdinals = ordinals.clone(); - Arrays.sort(sortedOrdinals); + components = newComponents; + updateNumComponents(numComponents + ordinalAdjustment); - for (int i = sortedOrdinals.length - 1; i >= 0; i--) { - int ordinal = sortedOrdinals[i]; - int idx; - if (isInternallyAligned()) { - idx = ordinal; - } - else { - idx = Collections.binarySearch(components, Integer.valueOf(ordinal), - ordinalComparator); - } - if (idx >= 0) { - doDelete(idx); - } - else { - // assume unaligned removal of DEFAULT - idx = -idx - 1; - shiftOffsets(idx, -1, -1); + if (isPackingEnabled()) { + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); } } - adjustInternalAlignment(true); - notifySizeChanged(); + else { + structLength += offsetAdjustment; + if (bitFieldRemoved) { + repack(false, false); + } + notifySizeChanged(false); + } } finally { lock.release(); @@ -642,13 +684,14 @@ class StructureDB extends CompositeDB implements Structure { return flexibleArrayComponent; } if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } - if (isInternallyAligned()) { + if (isPackingEnabled()) { return components.get(ordinal); } int idx = - Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator); + Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); if (idx >= 0) { return components.get(idx); } @@ -688,7 +731,7 @@ class StructureDB extends CompositeDB implements Structure { /** * Create copy of structure for target dtm (source archive information is discarded). *

    - * WARNING! copying unaligned structures which contain bitfields can produce invalid results when + * WARNING! copying non-packed structures which contain bitfields can produce invalid results when * switching endianess due to the differences in packing order. * * @param dtm target data type manager @@ -705,7 +748,7 @@ class StructureDB extends CompositeDB implements Structure { /** * Create cloned structure for target dtm preserving source archive information. WARNING! - * cloning unaligned structures which contain bitfields can produce invalid results when + * cloning non-packed structures which contain bitfields can produce invalid results when * switching endianess due to the differences in packing order. * * @param dtm target data type manager @@ -714,7 +757,7 @@ class StructureDB extends CompositeDB implements Structure { @Override public Structure clone(DataTypeManager dtm) { StructureDataType struct = - new StructureDataType(getCategoryPath(), getName(), getLength(), getUniversalID(), + new StructureDataType(getCategoryPath(), getName(), structLength, getUniversalID(), getSourceArchive(), getLastChangeTime(), getLastChangeTimeInSourceArchive(), dtm); struct.setDescription(getDescription()); struct.replaceWith(this); @@ -727,16 +770,38 @@ class StructureDB extends CompositeDB implements Structure { } @Override - public int getAlignment() { - if (!isInternallyAligned()) { - return 1; // Unaligned + protected int getComputedAlignment(boolean updateRecord) { + if (structAlignment > 0) { + return structAlignment; } - if (alignment <= 0) { - // just in case - alignment should have been previously determined and stored - StructurePackResult packResult = AlignedStructureInspector.packComponents(this); - alignment = packResult.alignment; + if (computedAlignment <= 0) { + if (isPackingEnabled()) { + StructurePackResult packResult = AlignedStructureInspector.packComponents(this); + computedAlignment = packResult.alignment; + } + else { + computedAlignment = getNonPackedAlignment(); + } } - return alignment; + if (updateRecord) { + // perform lazy update of stored computed alignment + record.setIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL, computedAlignment); + try { + compositeAdapter.updateRecord(record, false); + } + catch (IOException e) { + dataMgr.dbError(e); + } + structAlignment = computedAlignment; + computedAlignment = -1; + return structAlignment; + } + return computedAlignment; + } + + @Override + public boolean isZeroLength() { + return structLength == 0; } @Override @@ -759,17 +824,16 @@ class StructureDB extends CompositeDB implements Structure { lock.acquire(); try { checkDeleted(); + if (isPackingEnabled()) { + delete(ordinal); + return; + } if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); - } - int idx; - if (isInternallyAligned()) { - idx = ordinal; - } - else { - idx = Collections.binarySearch(components, Integer.valueOf(ordinal), - ordinalComparator); + throw new IndexOutOfBoundsException(ordinal); } + + int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); if (idx >= 0) { DataTypeComponentDB dtc = components.remove(idx); dtc.getDataType().removeParent(this); @@ -781,12 +845,18 @@ class StructureDB extends CompositeDB implements Structure { } int len = dtc.getLength(); if (len > 1) { - shiftOffsets(idx, len - 1, 0); + shiftOffsets(idx, len - 1, 0); // updates timestamp } - adjustInternalAlignment(true); - dataMgr.dataTypeChanged(this); + else { + compositeAdapter.updateRecord(record, true); // update timestamp + } + repack(false, false); + dataMgr.dataTypeChanged(this, false); } } + catch (IOException e) { + dataMgr.dbError(e); + } finally { lock.release(); } @@ -797,7 +867,7 @@ class StructureDB extends CompositeDB implements Structure { * normal components the specified ordinal will be returned, however for bit-fields the ordinal * of the first bit-field containing the specified offset will be returned. * - * @param ordinal component ordinal + * @param index defined component index * @param offset offset within structure * @return index of first defined component containing specific offset. */ @@ -822,7 +892,7 @@ class StructureDB extends CompositeDB implements Structure { * normal components the specified ordinal will be returned, however for bit-fields the ordinal * of the last bit-field containing the specified offset will be returned. * - * @param ordinal component ordinal + * @param index defined component index * @param offset offset within structure * @return index of last defined component containing specific offset. */ @@ -851,7 +921,8 @@ class StructureDB extends CompositeDB implements Structure { return; } int index = - Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator); + Collections.binarySearch(components, Integer.valueOf(offset), + OffsetComparator.INSTANCE); int offsetDelta = 0; int ordinalDelta = 0; @@ -859,22 +930,21 @@ class StructureDB extends CompositeDB implements Structure { index = -index - 1; --ordinalDelta; offsetDelta = -1; - shiftOffsets(index, ordinalDelta, offsetDelta); + shiftOffsets(index, ordinalDelta, offsetDelta); // updates timestamp } else { index = advanceToLastComponentContainingOffset(index, offset); DataTypeComponentDB dtc = components.get(index); while (dtc.containsOffset(offset)) { - doDelete(index); + doDelete(index); // updates timestamp if (--index < 0) { break; } dtc = components.get(index); } } - - adjustInternalAlignment(true); - notifySizeChanged(); + repack(false, false); + notifySizeChanged(false); } finally { lock.release(); @@ -890,7 +960,8 @@ class StructureDB extends CompositeDB implements Structure { return null; } int index = - Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator); + Collections.binarySearch(components, Integer.valueOf(offset), + OffsetComparator.INSTANCE); if (index >= 0) { DataTypeComponent dtc = components.get(index); if (dtc.isBitFieldComponent()) { @@ -899,7 +970,7 @@ class StructureDB extends CompositeDB implements Structure { } return dtc; } - else if (isInternallyAligned()) { + else if (isPackingEnabled()) { return null; } index = -index - 1; @@ -981,13 +1052,14 @@ class StructureDB extends CompositeDB implements Structure { dataType = resolve(dataType); checkAncestry(dataType); - if ((offset > structLength) && !isInternallyAligned()) { + if ((offset > structLength) && !isPackingEnabled()) { numComponents = numComponents + (offset - structLength); structLength = offset; } int index = - Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator); + Collections.binarySearch(components, Integer.valueOf(offset), + OffsetComparator.INSTANCE); int additionalShift = 0; if (index >= 0) { @@ -1006,10 +1078,10 @@ class StructureDB extends CompositeDB implements Structure { } if (dataType == DataType.DEFAULT) { - // assume unaligned insert of DEFAULT + // assume non-packed insert of DEFAULT shiftOffsets(index, 1 + additionalShift, 1 + additionalShift); - adjustInternalAlignment(true); - notifySizeChanged(); + repack(false, false); + notifySizeChanged(false); return new DataTypeComponentDB(dataMgr, componentAdapter, this, key, ordinal, offset); } @@ -1022,8 +1094,8 @@ class StructureDB extends CompositeDB implements Structure { DataTypeComponentDB dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec); shiftOffsets(index, 1 + additionalShift, dtc.getLength() + additionalShift); components.add(index, dtc); - adjustInternalAlignment(true); - notifySizeChanged(); + repack(false, false); + notifySizeChanged(false); return dtc; } catch (DataTypeDependencyException e) { @@ -1040,13 +1112,13 @@ class StructureDB extends CompositeDB implements Structure { @Override public DataTypeComponent replace(int ordinal, DataType dataType, int length, String name, - String comment) throws IllegalArgumentException { + String comment) { lock.acquire(); try { checkDeleted(); if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } validateDataType(dataType); @@ -1068,13 +1140,22 @@ class StructureDB extends CompositeDB implements Structure { length = getPreferredComponentLength(dataType, length); DataTypeComponent replaceComponent = - replaceComponent(origDtc, dataType, length, name, comment, true); - adjustInternalAlignment(true); + replaceComponent(origDtc, dataType, length, name, comment); + + repack(false, false); + record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength); + compositeAdapter.updateRecord(record, true); + notifySizeChanged(false); + return replaceComponent; } catch (DataTypeDependencyException e) { throw new IllegalArgumentException(e.getMessage(), e); } + catch (IOException e) { + dataMgr.dbError(e); + return null; + } finally { lock.release(); } @@ -1121,14 +1202,22 @@ class StructureDB extends CompositeDB implements Structure { length = getPreferredComponentLength(dataType, length); DataTypeComponent replaceComponent = - replaceComponent(origDtc, dataType, length, name, comment, true); + replaceComponent(origDtc, dataType, length, name, comment); + + repack(false, false); + record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength); + compositeAdapter.updateRecord(record, true); + notifySizeChanged(false); - adjustInternalAlignment(true); return replaceComponent; } catch (DataTypeDependencyException e) { throw new IllegalArgumentException(e.getMessage(), e); } + catch (IOException e) { + dataMgr.dbError(e); + return null; + } finally { lock.release(); } @@ -1146,14 +1235,14 @@ class StructureDB extends CompositeDB implements Structure { */ @Override public void replaceWith(DataType dataType) { - if (!(dataType instanceof Structure)) { + if (!(dataType instanceof StructureInternal)) { throw new IllegalArgumentException(); } lock.acquire(); boolean isResolveCacheOwner = dataMgr.activateResolveCache(); try { checkDeleted(); - doReplaceWith((Structure) dataType, true); + doReplaceWith((StructureInternal) dataType, true); } catch (DataTypeDependencyException e) { throw new IllegalArgumentException(e.getMessage(), e); @@ -1170,15 +1259,15 @@ class StructureDB extends CompositeDB implements Structure { } /** - * Perform component replacement. + * Replaces the internal components of this structure with components of the given structure + * including packing and alignment settings. * - * @param struct - * @param notify - * @return true if fully completed else false if pointer component post resolve required - * @throws DataTypeDependencyException - * @throws IOException + * @param struct structure to be copied + * @param notify provide notification if true + * @throws DataTypeDependencyException if circular dependency detected + * @throws IOException if database IO error occurs */ - void doReplaceWith(Structure struct, boolean notify) + void doReplaceWith(StructureInternal struct, boolean notify) throws DataTypeDependencyException, IOException { // pre-resolved component types to catch dependency issues early @@ -1197,16 +1286,10 @@ class StructureDB extends CompositeDB implements Structure { } } - int oldLength = structLength; - int oldMinAlignment = getMinimumAlignment(); - for (DataTypeComponentDB dtc : components) { dtc.getDataType().removeParent(this); componentAdapter.removeRecord(dtc.getKey()); } - components.clear(); - numComponents = 0; - structLength = 0; if (flexibleArrayComponent != null) { flexibleArrayComponent.getDataType().removeParent(this); @@ -1214,9 +1297,15 @@ class StructureDB extends CompositeDB implements Structure { flexibleArrayComponent = null; } - setAlignment(struct, false); + components.clear(); + numComponents = 0; + structLength = 0; + structAlignment = -1; + computedAlignment = -1; - if (struct.isInternallyAligned()) { + doSetPackingAndAlignment(struct); // updates timestamp + + if (struct.isPackingEnabled()) { doReplaceWithAligned(struct, resolvedDts); } else { @@ -1228,23 +1317,16 @@ class StructureDB extends CompositeDB implements Structure { false); } + repack(false, false); + + // must force record update record.setIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL, numComponents); record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength); - - compositeAdapter.updateRecord(record, false); - - adjustInternalAlignment(false); + record.setIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL, structAlignment); + compositeAdapter.updateRecord(record, notify); if (notify) { - if (oldMinAlignment != getMinimumAlignment()) { - notifyAlignmentChanged(); - } - else if (oldLength != structLength) { - notifySizeChanged(); - } - else { - dataMgr.dataTypeChanged(this); - } + notifySizeChanged(false); } if (pointerPostResolveRequired) { @@ -1271,7 +1353,7 @@ class StructureDB extends CompositeDB implements Structure { private void doReplaceWithUnaligned(Structure struct, DataType[] resolvedDts) throws IOException { // assumes components is clear and that alignment characteristics have been set. - if (struct.isNotYetDefined()) { + if (struct.isZeroLength()) { return; } @@ -1308,7 +1390,7 @@ class StructureDB extends CompositeDB implements Structure { new DataTypeComponentDB(dataMgr, componentAdapter, this, rec); components.add(newDtc); } - adjustComponents(false); + repack(false, false); } @Override @@ -1338,12 +1420,12 @@ class StructureDB extends CompositeDB implements Structure { lock.acquire(); try { checkDeleted(); - boolean didChange = false; + boolean changed = false; if (flexibleArrayComponent != null && flexibleArrayComponent.getDataType() == dt) { flexibleArrayComponent.getDataType().removeParent(this); componentAdapter.removeRecord(flexibleArrayComponent.getKey()); flexibleArrayComponent = null; - didChange = true; + changed = true; } int n = components.size(); for (int i = n - 1; i >= 0; i--) { @@ -1355,15 +1437,16 @@ class StructureDB extends CompositeDB implements Structure { } if (removeBitFieldComponent || dtc.getDataType() == dt) { dt.removeParent(this); +// FIXME: Consider replacing with undefined type instead of removing (don't remove bitfield) components.remove(i); shiftOffsets(i, dtc.getLength() - 1, 0); // ordinals only componentAdapter.removeRecord(dtc.getKey()); - didChange = true; + --numComponents; // may be revised by repack + changed = true; } } - if (didChange) { - adjustInternalAlignment(true); - notifySizeChanged(); + if (changed && !repack(false, true)) { + dataMgr.dataTypeChanged(this, false); } } catch (IOException e) { @@ -1382,18 +1465,20 @@ class StructureDB extends CompositeDB implements Structure { lock.acquire(); try { checkDeleted(); - if (isInternallyAligned()) { - adjustComponents(true); // notifies parents + if (isPackingEnabled()) { + if (!repack(true, true)) { + dataMgr.dataTypeChanged(this, true); + } return; } - boolean didChange = false; + int oldLength = structLength; + boolean changed = false; boolean warn = false; int n = components.size(); for (int i = 0; i < n; i++) { DataTypeComponentDB dtc = components.get(i); if (dtc.getDataType() == dt) { - // assume no impact to bitfields since base types - // should not change size + // assume no impact to bitfields since base types should not change size int dtcLen = dtc.getLength(); int length = dt.getLength(); if (length <= 0) { @@ -1402,14 +1487,14 @@ class StructureDB extends CompositeDB implements Structure { if (length < dtcLen) { dtc.setLength(length, true); shiftOffsets(i + 1, dtcLen - length, 0); - didChange = true; + changed = true; } else if (length > dtcLen) { int consumed = consumeBytesAfter(i, length - dtcLen); if (consumed > 0) { dtc.updateRecord(); shiftOffsets(i + 1, -consumed, 0); - didChange = true; + changed = true; } } if (dtc.getLength() != length) { @@ -1417,14 +1502,19 @@ class StructureDB extends CompositeDB implements Structure { } } } - if (didChange) { - adjustInternalAlignment(false); - notifySizeChanged(); // notifies parents - } if (warn) { Msg.warn(this, "Failed to resize one or more structure components: " + getPathName()); } + if (changed) { + repack(false, false); + if (oldLength != structLength) { + notifySizeChanged(false); + } + else { + dataMgr.dataTypeChanged(this, false); + } + } } finally { lock.release(); @@ -1432,14 +1522,8 @@ class StructureDB extends CompositeDB implements Structure { } @Override - protected void fixupComponents() { - if (isInternallyAligned()) { - // Do not notify parents - if (adjustComponents(false)) { - dataMgr.dataTypeChanged(this); - } - return; - } + protected void fixupComponents() throws IOException { + boolean isPacked = isPackingEnabled(); boolean didChange = false; boolean warn = false; int n = components.size(); @@ -1456,7 +1540,11 @@ class StructureDB extends CompositeDB implements Structure { length = dtcLen; } if (dtcLen != length) { - if (length < dtcLen) { + if (isPacked) { + dtc.setLength(length, true); + didChange = true; + } + else if (length < dtcLen) { dtc.setLength(length, true); shiftOffsets(i + 1, dtcLen - length, 0); didChange = true; @@ -1475,9 +1563,10 @@ class StructureDB extends CompositeDB implements Structure { } } if (didChange) { - // Do not notify parents - adjustInternalAlignment(false); - dataMgr.dataTypeChanged(this); + // Do not notify parents - must be invoked in composite dependency order + repack(false, false); + compositeAdapter.updateRecord(record, true); + dataMgr.dataTypeChanged(this, false); } if (warn) { Msg.warn(this, "Failed to resize one or more structure components: " + getPathName()); @@ -1488,8 +1577,10 @@ class StructureDB extends CompositeDB implements Structure { public void dataTypeAlignmentChanged(DataType dt) { lock.acquire(); try { - checkDeleted(); - adjustInternalAlignment(true); + if (isPackingEnabled()) { + checkDeleted(); + repack(true, true); + } } finally { lock.release(); @@ -1501,7 +1592,7 @@ class StructureDB extends CompositeDB implements Structure { if (dataType == this) { return true; } - if (!(dataType instanceof Structure)) { + if (!(dataType instanceof StructureInternal)) { return false; } @@ -1520,13 +1611,12 @@ class StructureDB extends CompositeDB implements Structure { try { isEquivalent = false; - Structure struct = (Structure) dataType; - if (isInternallyAligned() != struct.isInternallyAligned() || - isDefaultAligned() != struct.isDefaultAligned() || - isMachineAligned() != struct.isMachineAligned() || - getMinimumAlignment() != struct.getMinimumAlignment() || - getPackingValue() != struct.getPackingValue() || - (!isInternallyAligned() && (getLength() != struct.getLength()))) { + StructureInternal struct = (StructureInternal) dataType; + int otherLength = struct.isZeroLength() ? 0 : struct.getLength(); + int packing = getStoredPackingValue(); + if (packing != struct.getStoredPackingValue() || + getStoredMinimumAlignment() != struct.getStoredMinimumAlignment() || + (packing == NO_PACKING && structLength != otherLength)) { return false; } @@ -1611,7 +1701,7 @@ class StructureDB extends CompositeDB implements Structure { shiftOffset(dtc, deltaOrdinal, deltaOffset); } structLength += deltaOffset; - if (!isInternallyAligned()) { + if (!isPackingEnabled()) { numComponents += deltaOrdinal; } record.setIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL, numComponents); @@ -1640,78 +1730,63 @@ class StructureDB extends CompositeDB implements Structure { * @param name the field name of the new component * @param comment the comment for the new component * @return the new component or null if the new component couldn't fit. + * @throws IOException if database IO error occurs */ private DataTypeComponent replaceComponent(DataTypeComponent origDtc, DataType resolvedDataType, - int length, String name, String comment, boolean doNotify) { + int length, String name, String comment) throws IOException { -// FIXME: Unsure how to support replace operation with bit-fields. Within unaligned structure +// FIXME: Unsure how to support replace operation with bit-fields. Within non-packed structure // the packing behavior for bit-fields prevents a one-for-one replacement and things may shift -// around which the unaligned structure tries to avoid. Insert and delete are less of a concern +// around which the non-packed structure tries to avoid. Insert and delete are less of a concern // since movement already can occur, although insert at offset may not retain the offset if it // interacts with bit-fields. - try { - int ordinal = origDtc.getOrdinal(); - int newOffset = origDtc.getOffset(); - int dtcLength = origDtc.getLength(); - int bytesNeeded = length - dtcLength; - int deltaOrdinal = -bytesNeeded; - int origStructLength = structLength; - if (!isInternallyAligned() && bytesNeeded > 0) { - int bytesAvailable = getNumUndefinedBytes(ordinal + 1); - if (bytesAvailable < bytesNeeded) { - if (ordinal == getLastDefinedComponentIndex()) { - growStructure(bytesNeeded - bytesAvailable); - } - else { - throw new IllegalArgumentException("Not enough undefined bytes to fit " + - resolvedDataType.getPathName() + " in structure " + getPathName() + - " at offset 0x" + Integer.toHexString(newOffset) + "." + " It needs " + - (bytesNeeded - bytesAvailable) + " more byte(s) to be able to fit."); - } + int ordinal = origDtc.getOrdinal(); + int newOffset = origDtc.getOffset(); + int dtcLength = origDtc.getLength(); + int bytesNeeded = length - dtcLength; + int deltaOrdinal = -bytesNeeded; + if (!isPackingEnabled() && bytesNeeded > 0) { + int bytesAvailable = getNumUndefinedBytes(ordinal + 1); + if (bytesAvailable < bytesNeeded) { + if (ordinal == getLastDefinedComponentIndex()) { + growStructure(bytesNeeded - bytesAvailable); + } + else { + throw new IllegalArgumentException("Not enough undefined bytes to fit " + + resolvedDataType.getPathName() + " in structure " + getPathName() + + " at offset 0x" + Integer.toHexString(newOffset) + "." + " It needs " + + (bytesNeeded - bytesAvailable) + " more byte(s) to be able to fit."); } } - DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(resolvedDataType), key, - length, ordinal, newOffset, name, comment); - resolvedDataType.addParent(this); - DataTypeComponentDB newDtc = - new DataTypeComponentDB(dataMgr, componentAdapter, this, rec); - int index; - if (isInternallyAligned()) { - index = ordinal; - } - else { - index = Collections.binarySearch(components, Integer.valueOf(ordinal), - ordinalComparator); - } - if (index < 0) { - index = -index - 1; - } - else { - DataTypeComponentDB dataTypeComponentDB = components.get(index); // TODO Remove this. - dataTypeComponentDB.getDataType().removeParent(this); - DataTypeComponentDB dtc = components.remove(index); - componentAdapter.removeRecord(dtc.getKey()); - } - components.add(index, newDtc); - if (deltaOrdinal != 0) { - shiftOffsets(index + 1, deltaOrdinal, 0); - } - if (structLength != origStructLength) { - record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength); - compositeAdapter.updateRecord(record, true); - adjustInternalAlignment(false); - notifySizeChanged(); - } - else if (doNotify) { - dataMgr.dataTypeChanged(this); - } - return newDtc; } - catch (IOException e) { - dataMgr.dbError(e); + DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(resolvedDataType), key, + length, ordinal, newOffset, name, comment); + resolvedDataType.addParent(this); + DataTypeComponentDB newDtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec); + int index; + if (isPackingEnabled()) { + index = ordinal; } - return null; + else { + index = + Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); + } + if (index < 0) { + index = -index - 1; + } + else { + DataTypeComponentDB dataTypeComponentDB = components.get(index); // TODO Remove this. + dataTypeComponentDB.getDataType().removeParent(this); + DataTypeComponentDB dtc = components.remove(index); + componentAdapter.removeRecord(dtc.getKey()); + } + components.add(index, newDtc); + if (deltaOrdinal != 0) { + shiftOffsets(index + 1, deltaOrdinal, 0); + } + return newDtc; } /** @@ -1722,13 +1797,14 @@ class StructureDB extends CompositeDB implements Structure { * @return the number of contiguous undefined bytes */ private int getNumUndefinedBytes(int ordinal) { - if (isInternallyAligned()) { + if (isPackingEnabled()) { return 0; } if (ordinal >= numComponents) { return 0; } - int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator); + int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); DataTypeComponentDB dtc = null; if (idx < 0) { idx = -idx - 1; @@ -1804,7 +1880,7 @@ class StructureDB extends CompositeDB implements Structure { } } else if (comp.getDataType() == oldDt) { - if (replacementDt == DEFAULT && isInternallyAligned()) { + if (replacementDt == DEFAULT && isPackingEnabled()) { Msg.error(this, "Invalid replacement type " + newDt.getName() + ", removing component " + comp.getDataType().getName() + ": " + @@ -1826,8 +1902,9 @@ class StructureDB extends CompositeDB implements Structure { } } if (changed) { - adjustInternalAlignment(false); - notifySizeChanged(); + repack(false, false); + compositeAdapter.updateRecord(record, true); // update timestamp + notifySizeChanged(false); } } catch (IOException e) { @@ -1841,38 +1918,44 @@ class StructureDB extends CompositeDB implements Structure { private void setComponentDataType(DataTypeComponentDB comp, DataType replacementDt, int nextIndex) { - comp.getDataType().removeParent(this); - comp.setDataType(replacementDt); - replacementDt.addParent(this); - - if (isInternallyAligned()) { - return; // caller must invoke adjustInternalAlignment + int oldLen = comp.getLength(); + int len = replacementDt.getLength(); + if (len < 1) { + len = oldLen; } - int len = replacementDt.getLength(); - int oldLen = comp.getLength(); - if (len > 0) { - if (len < oldLen) { + comp.getDataType().removeParent(this); + + if (isPackingEnabled()) { + comp.setLength(len, false); // do before record save below + } + comp.setDataType(replacementDt); // saves component record + replacementDt.addParent(this); + + if (isPackingEnabled()) { + return; + } + + if (len < oldLen) { + comp.setLength(len, true); + shiftOffsets(nextIndex, oldLen - len, 0); + } + else if (len > oldLen) { + int bytesAvailable = getNumUndefinedBytes(comp.getOrdinal() + 1); + int bytesNeeded = len - oldLen; + if (bytesNeeded <= bytesAvailable) { comp.setLength(len, true); - shiftOffsets(nextIndex, oldLen - len, 0); + shiftOffsets(nextIndex, -bytesNeeded, 0); } - else if (len > oldLen) { - int bytesAvailable = getNumUndefinedBytes(comp.getOrdinal() + 1); - int bytesNeeded = len - oldLen; - if (bytesNeeded <= bytesAvailable) { - comp.setLength(len, true); - shiftOffsets(nextIndex, -bytesNeeded, 0); - } - else if (comp.getOrdinal() == getLastDefinedComponentIndex()) { - // we are the last defined component, grow structure - doGrowStructure(bytesNeeded - bytesAvailable); - comp.setLength(len, true); - shiftOffsets(nextIndex, -bytesNeeded, 0); - } - else { - comp.setLength(oldLen + bytesAvailable, true); - shiftOffsets(nextIndex, -bytesAvailable, 0); - } + else if (comp.getOrdinal() == getLastDefinedComponentIndex()) { + // we are the last defined component, grow structure + doGrowStructure(bytesNeeded - bytesAvailable); + comp.setLength(len, true); + shiftOffsets(nextIndex, -bytesNeeded, 0); + } + else { + comp.setLength(oldLen + bytesAvailable, true); + shiftOffsets(nextIndex, -bytesAvailable, 0); } } } @@ -1909,8 +1992,7 @@ class StructureDB extends CompositeDB implements Structure { record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, 0); record.setIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL, 0); compositeAdapter.updateRecord(record, true); - adjustInternalAlignment(true); - notifySizeChanged(); + notifySizeChanged(false); } catch (IOException e) { dataMgr.dbError(e); @@ -1921,74 +2003,56 @@ class StructureDB extends CompositeDB implements Structure { } /** - * ComponentComparator provides ability to compare two DataTypeComponent objects - * based upon their ordinal. Intended to be used to sort components based upon ordinal. + * Perform structure member repack. + * Perform lazy update of stored alignment introduced with v5 adapter. */ - private static class ComponentComparator implements Comparator { - @Override - public int compare(DataTypeComponent dtc1, DataTypeComponent dtc2) { - return dtc1.getOrdinal() - dtc2.getOrdinal(); - } - } - - /** - * Adjust the alignment, packing and padding of components within this structure based upon the - * current alignment and packing attributes for this structure. This method should be called to - * basically fix up the layout of the internal components of the structure after other code has - * changed the attributes of the structure.
    - * When switching between internally aligned and unaligned this method corrects the component - * ordinal numbering also. - * - * @param notify if true this method will do data type change notification when it changes the - * layout of the components or when it changes the overall size of the structure. - * @return true if the structure was changed by this method. - */ - private boolean adjustComponents(boolean notify) { + @Override + protected boolean repack(boolean isAutoChange, boolean notify) { lock.acquire(); try { checkDeleted(); - boolean changed = false; - alignment = -1; - - if (!isInternallyAligned()) { - changed |= adjustUnalignedComponents(); - if (notify && changed) { - dataMgr.dataTypeChanged(this); - } - return changed; - } - int oldLength = structLength; - - StructurePackResult packResult = - AlignedStructurePacker.packComponents(this, components); - changed = packResult.componentsChanged; - - // Adjust the structure - changed |= updateComposite(packResult.numComponents, packResult.structureLength, - packResult.alignment, false); - - if (changed) { - if (notify) { - if (oldLength != structLength) { - notifySizeChanged(); - } - else { - dataMgr.dataTypeChanged(this); - } - } - return true; + int oldAlignment = getComputedAlignment(true); // ensure that alignment has been stored + + computedAlignment = -1; // clear cached alignment + + boolean changed; + if (!isPackingEnabled()) { + changed = adjustNonPackedComponents(!isAutoChange); } - return false; + else { + StructurePackResult packResult = + AlignedStructurePacker.packComponents(this, components); + changed = packResult.componentsChanged; + changed |= updateComposite(packResult.numComponents, packResult.structureLength, + packResult.alignment, !isAutoChange); + } + + if (changed && notify) { + if (oldLength != structLength) { + notifySizeChanged(isAutoChange); + } + else if (oldAlignment != structAlignment) { + notifyAlignmentChanged(isAutoChange); + } + dataMgr.dataTypeChanged(this, isAutoChange); + } + return changed; } finally { lock.release(); } } - private boolean adjustUnalignedComponents() { + /** + * Updates non-packed component ordinals and numComponents. + * If numComponents changes record update will be performed + * with new timestamp. + * @return true if change detected else false + */ + private boolean adjustNonPackedComponents(boolean setLastChangeTime) { boolean changed = false; int componentCount = 0; int currentOffset = 0; @@ -2006,11 +2070,11 @@ class StructureDB extends CompositeDB implements Structure { } componentCount++; } + int numUndefinedsAfter = structLength - currentOffset; componentCount += numUndefinedsAfter; - if (updateNumComponents(componentCount)) { - changed = true; - } + changed |= updateComposite(componentCount, structLength, getNonPackedAlignment(), + setLastChangeTime); return changed; } @@ -2039,6 +2103,7 @@ class StructureDB extends CompositeDB implements Structure { if (numComponents != currentNumComponents) { numComponents = currentNumComponents; record.setIntValue(CompositeDBAdapter.COMPOSITE_NUM_COMPONENTS_COL, numComponents); + setLastChangeTime = true; compositeChanged = true; } if (structLength != currentLength) { @@ -2046,8 +2111,9 @@ class StructureDB extends CompositeDB implements Structure { record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, structLength); compositeChanged = true; } - if (alignment != currentAlignment) { - alignment = currentAlignment; + if (structAlignment != currentAlignment) { + structAlignment = currentAlignment; + record.setIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL, structAlignment); compositeChanged = true; } if (compositeChanged) { @@ -2062,23 +2128,6 @@ class StructureDB extends CompositeDB implements Structure { return false; } - @Override - public void realign() { - if (isInternallyAligned()) { - adjustInternalAlignment(true); - } - } - - @Override - public void pack(int packingSize) { - setPackingValue(packingSize); - } - - @Override - protected void adjustInternalAlignment(boolean notify) { - adjustComponents(notify); - } - @Override public boolean hasFlexibleArrayComponent() { return flexibleArrayComponent != null; @@ -2128,30 +2177,16 @@ class StructureDB extends CompositeDB implements Structure { catch (IOException e) { dataMgr.dbError(e); } - adjustInternalAlignment(true); - notifySizeChanged(); + repack(false, false); + compositeAdapter.updateRecord(record, true); + notifySizeChanged(false); + } + catch (IOException e) { + dataMgr.dbError(e); } finally { lock.release(); } } - @Override - protected void dumpComponents(StringBuilder buffer, String pad) { - super.dumpComponents(buffer, pad); - DataTypeComponent dtc = getFlexibleArrayComponent(); - if (dtc != null) { - DataType dataType = dtc.getDataType(); - buffer.append(pad + dataType.getDisplayName() + "[0]"); - buffer.append(pad + dtc.getLength()); - buffer.append(pad + dtc.getFieldName()); - String comment = dtc.getComment(); - if (comment == null) { - comment = ""; - } - buffer.append(pad + "\"" + comment + "\""); - buffer.append("\n"); - } - } - } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/TypedefDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/TypedefDB.java index 054ebb7bc9..44088e7654 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/TypedefDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/TypedefDB.java @@ -76,6 +76,11 @@ class TypedefDB extends DataTypeDB implements TypeDef { return getDisplayName(); } + @Override + public boolean isZeroLength() { + return getDataType().isZeroLength(); + } + @Override public int getLength() { return getDataType().getLength(); @@ -108,7 +113,20 @@ class TypedefDB extends DataTypeDB implements TypeDef { lock.acquire(); try { if (checkIsValid() && dt == getDataType()) { - notifySizeChanged(); + notifySizeChanged(true); + } + } + finally { + lock.release(); + } + } + + @Override + public void dataTypeAlignmentChanged(DataType dt) { + lock.acquire(); + try { + if (checkIsValid() && dt == getDataType()) { + notifyAlignmentChanged(true); } } finally { @@ -204,10 +222,10 @@ class TypedefDB extends DataTypeDB implements TypeDef { dataMgr.dbError(e); } if (oldLen != getLength()) { - notifySizeChanged(); + notifySizeChanged(false); } else { - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } } } @@ -297,7 +315,7 @@ class TypedefDB extends DataTypeDB implements TypeDef { checkDeleted(); record.setLongValue(TypedefDBAdapter.TYPEDEF_UNIVERSAL_DT_ID_COL, id.getValue()); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -319,7 +337,7 @@ class TypedefDB extends DataTypeDB implements TypeDef { checkDeleted(); record.setLongValue(TypedefDBAdapter.TYPEDEF_SOURCE_ARCHIVE_ID_COL, id.getValue()); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -336,7 +354,7 @@ class TypedefDB extends DataTypeDB implements TypeDef { checkDeleted(); record.setLongValue(TypedefDBAdapter.TYPEDEF_LAST_CHANGE_TIME_COL, lastChangeTime); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); @@ -354,7 +372,7 @@ class TypedefDB extends DataTypeDB implements TypeDef { record.setLongValue(TypedefDBAdapter.TYPEDEF_SOURCE_SYNC_TIME_COL, lastChangeTimeInSourceArchive); adapter.updateRecord(record, false); - dataMgr.dataTypeChanged(this); + dataMgr.dataTypeChanged(this, false); } catch (IOException e) { dataMgr.dbError(e); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java index 3a069e2aa0..be09f16686 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/UnionDB.java @@ -18,8 +18,8 @@ package ghidra.program.database.data; import java.io.IOException; import java.util.*; -import db.Field; import db.DBRecord; +import db.Field; import ghidra.docking.settings.Settings; import ghidra.program.database.DBObjectCache; import ghidra.program.model.data.*; @@ -29,11 +29,13 @@ import ghidra.util.Msg; /** * Database implementation for the Union data type. */ -class UnionDB extends CompositeDB implements Union { +class UnionDB extends CompositeDB implements UnionInternal { - private ArrayList components; private int unionLength; - private static MemberComparator comparator = new MemberComparator(); + private int unionAlignment; // reflects stored alignment, -1 if not yet stored + private int computedAlignment = -1; // cached alignment if not yet stored + + private List components; /** * Constructor @@ -65,9 +67,10 @@ class UnionDB extends CompositeDB implements Union { catch (IOException e) { dataMgr.dbError(e); } - Collections.sort(components, comparator); + Collections.sort(components, ComponentComparator.INSTANCE); unionLength = record.getIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL); - + unionAlignment = record.getIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL); + computedAlignment = -1; } @Override @@ -89,8 +92,11 @@ class UnionDB extends CompositeDB implements Union { lock.acquire(); try { checkDeleted(); + getComputedAlignment(true); // ensure previous alignment has been stored DataTypeComponent dtc = doAdd(dataType, length, componentName, comment, true); - adjustLength(true, true); + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); + } return dtc; } catch (DataTypeDependencyException e) { @@ -103,7 +109,7 @@ class UnionDB extends CompositeDB implements Union { private int getBitFieldAllocation(BitFieldDataType bitfieldDt) { - BitFieldPacking bitFieldPacking = getBitFieldPacking(); + BitFieldPacking bitFieldPacking = getDataOrganization().getBitFieldPacking(); if (bitFieldPacking.useMSConvention()) { return bitfieldDt.getBaseTypeSize(); } @@ -113,8 +119,8 @@ class UnionDB extends CompositeDB implements Union { } int length = bitfieldDt.getBaseTypeSize(); - int packValue = getPackingValue(); - if (packValue != NOT_PACKING && length > packValue) { + int packValue = getStoredPackingValue(); + if (packValue > 0 && length > packValue) { length = DataOrganizationImpl.getLeastCommonMultiple(bitfieldDt.getStorageSize(), packValue); } @@ -179,6 +185,8 @@ class UnionDB extends CompositeDB implements Union { dataType = resolve(dataType); checkAncestry(dataType); + getComputedAlignment(true); // ensure previous alignment has been stored + length = getPreferredComponentLength(dataType, length); DataTypeComponentDB dtc = @@ -187,7 +195,9 @@ class UnionDB extends CompositeDB implements Union { shiftOrdinals(ordinal, 1); components.add(ordinal, dtc); - adjustLength(true, true); + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); + } return dtc; } catch (DataTypeDependencyException e) { @@ -207,10 +217,10 @@ class UnionDB extends CompositeDB implements Union { @Override public DataTypeComponent insertBitField(int ordinal, DataType baseDataType, int bitSize, String componentName, String comment) - throws InvalidDataTypeException, ArrayIndexOutOfBoundsException { + throws InvalidDataTypeException, IndexOutOfBoundsException { if (ordinal < 0 || ordinal > components.size()) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } BitFieldDataType bitFieldDt = new BitFieldDBDataType(baseDataType, bitSize, 0); @@ -223,12 +233,16 @@ class UnionDB extends CompositeDB implements Union { try { checkDeleted(); + getComputedAlignment(true); // ensure previous alignment has been stored + DataTypeComponentDB dtc = components.remove(ordinal); dtc.getDataType().removeParent(this); removeComponent(dtc.getKey()); shiftOrdinals(ordinal, -1); - adjustLength(true, true); + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); + } } finally { lock.release(); @@ -236,26 +250,70 @@ class UnionDB extends CompositeDB implements Union { } @Override - public void delete(int[] ordinals) { - for (int ordinal : ordinals) { - delete(ordinal); + public void delete(Set ordinals) { + if (ordinals.isEmpty()) { + return; + } + + lock.acquire(); + try { + checkDeleted(); + + if (isPackingEnabled()) { + getComputedAlignment(true); // ensure previous alignment has been stored + } + + List newComponents = new ArrayList<>(); + int newLength = 0; + int ordinalAdjustment = 0; + for (DataTypeComponentDB dtc : components) { + int ordinal = dtc.getOrdinal(); + if (ordinals.contains(ordinal)) { + // component removed + --ordinalAdjustment; + } + else { + if (ordinalAdjustment != 0) { + dtc.setOrdinal(dtc.getOrdinal() + ordinalAdjustment, true); + } + newComponents.add(dtc); + newLength = Math.max(newLength, dtc.getLength()); + } + } + components = newComponents; + + if (isPackingEnabled()) { + if (!repack(false, true)) { + dataMgr.dataTypeChanged(this, false); + } + } + else { + unionLength = newLength; + notifySizeChanged(false); + } + } + finally { + lock.release(); } } @Override public void replaceWith(DataType dataType) { - if (!(dataType instanceof Union)) { + if (!(dataType instanceof UnionInternal)) { throw new IllegalArgumentException(); } lock.acquire(); boolean isResolveCacheOwner = dataMgr.activateResolveCache(); try { checkDeleted(); - doReplaceWith((Union) dataType, true); + doReplaceWith((UnionInternal) dataType, true); } catch (DataTypeDependencyException e) { throw new IllegalArgumentException(e.getMessage(), e); } + catch (IOException e) { + dataMgr.dbError(e); + } finally { if (isResolveCacheOwner) { dataMgr.flushResolveQueue(true); @@ -264,8 +322,8 @@ class UnionDB extends CompositeDB implements Union { } } - void doReplaceWith(Union union, boolean notify) - throws DataTypeDependencyException { + void doReplaceWith(UnionInternal union, boolean notify) + throws DataTypeDependencyException, IOException { // pre-resolved component types to catch dependency issues early DataTypeComponent[] otherComponents = union.getComponents(); @@ -275,34 +333,25 @@ class UnionDB extends CompositeDB implements Union { checkAncestry(resolvedDts[i]); } - int oldLength = unionLength; - int oldMinAlignment = getMinimumAlignment(); - for (DataTypeComponentDB dtc : components) { dtc.getDataType().removeParent(this); removeComponent(dtc.getKey()); } components.clear(); + unionAlignment = -1; + computedAlignment = -1; - setAlignment(union, false); + doSetPackingAndAlignment(union); for (int i = 0; i < otherComponents.length; i++) { DataTypeComponent dtc = otherComponents[i]; doAdd(resolvedDts[i], dtc.getLength(), dtc.getFieldName(), dtc.getComment(), false); } - adjustLength(false, false); + repack(false, false); if (notify) { - if (oldMinAlignment != getMinimumAlignment()) { - notifyAlignmentChanged(); - } - else if (oldLength != unionLength) { - notifySizeChanged(); - } - else { - dataMgr.dataTypeChanged(this); - } + notifySizeChanged(false); // assume size and/or alignment changed } if (pointerPostResolveRequired) { @@ -394,7 +443,7 @@ class UnionDB extends CompositeDB implements Union { } @Override - public DataType clone(DataTypeManager dtm) { + public Union clone(DataTypeManager dtm) { UnionDataType union = new UnionDataType(getCategoryPath(), getName(), getUniversalID(), getSourceArchive(), getLastChangeTime(), getLastChangeTimeInSourceArchive(), dtm); union.setDescription(getDescription()); @@ -402,6 +451,11 @@ class UnionDB extends CompositeDB implements Union { return union; } + @Override + public boolean isZeroLength() { + return unionLength == 0; + } + @Override public int getLength() { lock.acquire(); @@ -417,6 +471,52 @@ class UnionDB extends CompositeDB implements Union { } } + @Override + protected void fixupComponents() { + boolean changed = false; + for (DataTypeComponentDB dtc : components) { + DataType dt = dtc.getDataType(); + if (dt instanceof BitFieldDataType) { + dt = adjustBitField(dt); // in case base type changed + } + int dtcLen = dtc.getLength(); + int length = dt.getLength(); + if (length <= 0) { + length = dtcLen; + } + if (length != dtcLen) { + dtc.setLength(length, true); + changed = true; + } + } + if (changed) { + // NOTE: since we do not retain our external alignment we have no way of knowing if + // it has changed, so we must assume it has if we are an aligned union + // Do not notify parents + if (!repack(false, false)) { + dataMgr.dataTypeChanged(this, false); + } + } + } + + @Override + public void dataTypeAlignmentChanged(DataType dt) { + if (!isPackingEnabled()) { + return; + } + if (dt instanceof BitFieldDataType) { + return; // unsupported + } + lock.acquire(); + try { + checkDeleted(); + repack(true, true); + } + finally { + lock.release(); + } + } + @Override public void dataTypeSizeChanged(DataType dt) { if (dt instanceof BitFieldDataType) { @@ -436,8 +536,8 @@ class UnionDB extends CompositeDB implements Union { changed = true; } } - if (changed) { - adjustLength(true, false); // notifies parents + if (changed && !repack(true, true)) { + dataMgr.dataTypeChanged(this, true); } } finally { @@ -445,38 +545,6 @@ class UnionDB extends CompositeDB implements Union { } } - @Override - protected void fixupComponents() { - boolean changed = false; - for (DataTypeComponentDB dtc : components) { - DataType dt = dtc.getDataType(); - if (dt instanceof BitFieldDataType) { - dt = adjustBitField(dt); // in case base type changed - } - int dtcLen = dtc.getLength(); - int length = dt.getLength(); - if (length <= 0) { - length = dtcLen; - } - if (length != dtcLen) { - dtc.setLength(length, true); - changed = true; - } - } - if (changed || isInternallyAligned()) { - // NOTE: since we do not retain our external alignment we have no way of knowing if - // it has changed, so we must assume it has if we are an aligned union - // Do not notify parents - adjustLength(false, false); - dataMgr.dataTypeChanged(this); - } - } - - @Override - public void dataTypeAlignmentChanged(DataType dt) { - adjustInternalAlignment(true); - } - private DataType adjustBitField(DataType dataType) { if (!(dataType instanceof BitFieldDataType)) { @@ -488,8 +556,8 @@ class UnionDB extends CompositeDB implements Union { DataType baseDataType = bitfieldDt.getBaseDataType(); baseDataType = resolve(baseDataType); - // Both aligned and unaligned bitfields use same adjustment - // unaligned must force bitfield placement at byte offset 0 + // Both aligned and non-packed bitfields use same adjustment + // non-packed must force bitfield placement at byte offset 0 int bitSize = bitfieldDt.getDeclaredBitSize(); int effectiveBitSize = BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength()); @@ -522,32 +590,94 @@ class UnionDB extends CompositeDB implements Union { return bitfieldDt; } - private void adjustLength(boolean notify, boolean setLastChangeTime) { + @Override + protected int getComputedAlignment(boolean updateRecord) { + if (unionAlignment > 0) { + return unionAlignment; + } + if (computedAlignment <= 0) { + if (isPackingEnabled()) { + computedAlignment = + CompositeAlignmentHelper.getAlignment(getDataOrganization(), this); + } + else { + computedAlignment = getNonPackedAlignment(); + } + } + if (updateRecord) { + // perform lazy update of stored computed alignment + record.setIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL, computedAlignment); + try { + compositeAdapter.updateRecord(record, false); + } + catch (IOException e) { + dataMgr.dbError(e); + } + unionAlignment = computedAlignment; + computedAlignment = -1; + return unionAlignment; + } + return computedAlignment; + } + + /** + * Perform union member repack. + * Perform lazy update of stored alignment introduced with v5 adapter. + */ + @Override + protected boolean repack(boolean isAutoChange, boolean notify) { lock.acquire(); try { checkDeleted(); + int oldLength = unionLength; + boolean storeAlignment = (unionAlignment <= 0); // lazy upgrade for v5 adapter + int oldAlignment = getComputedAlignment(false); unionLength = 0; for (DataTypeComponent dtc : components) { - + // TODO: compute alignment in this loop int length = dtc.getLength(); - if (isInternallyAligned() && dtc.isBitFieldComponent()) { + if (isPackingEnabled() && dtc.isBitFieldComponent()) { // revise length to reflect compiler bitfield allocation rules length = getBitFieldAllocation((BitFieldDataType) dtc.getDataType()); } - unionLength = Math.max(length, unionLength); } - DataOrganization dataOrganization = getDataOrganization(); - int alignment = dataOrganization.getAlignment(this, unionLength); - int amountFilled = unionLength % alignment; - if (amountFilled > 0) { - unionLength += alignment - amountFilled; + computedAlignment = -1; // force recompute of unionAlignment + unionAlignment = -1; + unionAlignment = getComputedAlignment(false); + + if (isPackingEnabled()) { + unionLength = DataOrganizationImpl.getAlignedOffset(unionAlignment, unionLength); } - updateLength(oldLength, notify, setLastChangeTime); + boolean changed = (oldLength != unionLength) || (oldAlignment != unionAlignment); + + if (changed || storeAlignment) { + record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, unionLength); + record.setIntValue(CompositeDBAdapter.COMPOSITE_ALIGNMENT_COL, unionAlignment); + try { + compositeAdapter.updateRecord(record, changed && !isAutoChange); + } + catch (IOException e) { + dataMgr.dbError(e); + } + } + + if (changed & notify) { + if (oldLength != unionLength) { + notifySizeChanged(isAutoChange); + } + else if (oldAlignment != unionAlignment) { + notifyAlignmentChanged(isAutoChange); + } + else { + dataMgr.dataTypeChanged(this, isAutoChange); + } + } + return changed; } finally { lock.release(); @@ -559,7 +689,7 @@ class UnionDB extends CompositeDB implements Union { lock.acquire(); try { checkDeleted(); - boolean didChange = false; + boolean changed = false; for (int i = components.size() - 1; i >= 0; i--) { // reverse order DataTypeComponentDB dtc = components.get(i); boolean removeBitFieldComponent = false; @@ -572,11 +702,11 @@ class UnionDB extends CompositeDB implements Union { components.remove(i); removeComponent(dtc.getKey()); shiftOrdinals(i, -1); - didChange = true; + changed = true; } } - if (didChange) { - adjustLength(true, true); + if (changed && !repack(false, true)) { + dataMgr.dataTypeChanged(this, false); } } finally { @@ -590,7 +720,7 @@ class UnionDB extends CompositeDB implements Union { if (dataType == this) { return true; } - if (!(dataType instanceof Union)) { + if (!(dataType instanceof UnionInternal)) { return false; } @@ -609,13 +739,10 @@ class UnionDB extends CompositeDB implements Union { try { isEquivalent = false; - Union union = (Union) dataType; - if (isInternallyAligned() != union.isInternallyAligned() || - isDefaultAligned() != union.isDefaultAligned() || - isMachineAligned() != union.isMachineAligned() || - getMinimumAlignment() != union.getMinimumAlignment() || - getPackingValue() != union.getPackingValue()) { - // rely on component match instead of checking length + UnionInternal union = (UnionInternal) dataType; + if (getStoredPackingValue() != union.getStoredPackingValue() || + getStoredMinimumAlignment() != union.getStoredMinimumAlignment()) { + // rely on component match instead of checking length // since dynamic component sizes could affect length return false; } @@ -637,24 +764,6 @@ class UnionDB extends CompositeDB implements Union { return true; } - private void updateLength(int oldLength, boolean notify, boolean setLastChangeTime) { - if (oldLength != unionLength) { - record.setIntValue(CompositeDBAdapter.COMPOSITE_LENGTH_COL, unionLength); - try { - compositeAdapter.updateRecord(record, setLastChangeTime); - } - catch (IOException e) { - dataMgr.dbError(e); - } - if (notify) { - notifySizeChanged(); - } - } - else if (notify) { - dataMgr.dataTypeChanged(this); - } - } - private void shiftOrdinals(int ordinal, int deltaOrdinal) { for (int i = ordinal; i < components.size(); i++) { DataTypeComponentDB dtc = components.get(i); @@ -729,8 +838,8 @@ class UnionDB extends CompositeDB implements Union { changed = true; } } - if (changed) { - adjustLength(true, true); + if (changed && !repack(false, true)) { + dataMgr.dataTypeChanged(this, false); } } finally { @@ -759,27 +868,9 @@ class UnionDB extends CompositeDB implements Union { } } - private static class MemberComparator implements Comparator { - @Override - public int compare(DataTypeComponent dtc1, DataTypeComponent dtc2) { - return dtc1.getOrdinal() - dtc2.getOrdinal(); - } - } - @Override public String getDefaultLabelPrefix() { return "UNION_" + getName(); } - @Override - public void realign() { - if (isInternallyAligned()) { - adjustInternalAlignment(true); - } - } - - @Override - public void adjustInternalAlignment(boolean notify) { - adjustLength(notify, false); - } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractDataType.java index 05b433dba6..dd767e8b15 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractDataType.java @@ -112,6 +112,11 @@ public abstract class AbstractDataType implements DataType { return false; } + @Override + public boolean isZeroLength() { + return false; + } + @Override public String toString() { return getDisplayName(); @@ -138,6 +143,11 @@ public abstract class AbstractDataType implements DataType { // do nothing } + @Override + public void dataTypeAlignmentChanged(DataType dt) { + // do nothing + } + @Override public void dataTypeDeleted(DataType dt) { // do nothing diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractFloatDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractFloatDataType.java index c316674273..c32d402abb 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractFloatDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractFloatDataType.java @@ -42,6 +42,7 @@ public abstract class AbstractFloatDataType extends BuiltIn { * * @see ghidra.program.model.data.DataType#getMnemonic(Settings) */ + @Override public String getMnemonic(Settings settings) { return name; } @@ -49,6 +50,7 @@ public abstract class AbstractFloatDataType extends BuiltIn { /** * @see ghidra.program.model.data.DataType#isDynamicallySized() */ + @Override public boolean isDynamicallySized() { return false; } @@ -57,6 +59,7 @@ public abstract class AbstractFloatDataType extends BuiltIn { * * @see ghidra.program.model.data.DataType#getDescription() */ + @Override public String getDescription() { return "IEEE-754 Float"; } @@ -65,6 +68,7 @@ public abstract class AbstractFloatDataType 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) { try { int len = getLength(); // use type length (ignore length arg) @@ -97,10 +101,12 @@ public abstract class AbstractFloatDataType extends BuiltIn { * * @see ghidra.program.model.data.DataType#getRepresentation(MemBuffer, Settings, int) */ + @Override 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(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedComponentPacker.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedComponentPacker.java index 2aa9e1d85f..cd79ff9e9e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedComponentPacker.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedComponentPacker.java @@ -43,7 +43,7 @@ class AlignedComponentPacker { private InternalDataTypeComponent lastComponent; - private int externalAlignment = 1; + private int defaultAlignment = 1; private boolean componentsChanged; AlignedComponentPacker(int packValue, DataOrganization dataOrganization) { @@ -68,7 +68,7 @@ class AlignedComponentPacker { lastComponent = dtc; ++nextOrdinal; - externalAlignment = getComponentAlignmentLCM(externalAlignment); + defaultAlignment = getComponentAlignmentLCM(defaultAlignment); } /** @@ -80,13 +80,13 @@ class AlignedComponentPacker { } /** - * Get the external structure alignment after all components have been added. - * This value does not factor in the affects of any trailing flexible array component - * which may exist. + * Get the external structure alignment after all components have been packed. + * NOTE: This value does not factor in the affects of any trailing flexible array component + * which may exist or the alignment which may have been explicitly set on the structure. * @return external alignment */ - int getExternalAlignment() { - return externalAlignment; + int getDefaultAlignment() { + return defaultAlignment; } /** @@ -108,12 +108,11 @@ class AlignedComponentPacker { offset = lastComponent.getOffset() + lastComponent.getLength(); if (!bitFieldPacking.useMSConvention() && lastComponent.isZeroBitFieldComponent()) { // factor in trailing zero-length bitfield + // TODO: does pack setting need to be considered? BitFieldDataType bitfieldDt = (BitFieldDataType) lastComponent.getDataType(); - int sizeAlignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization, - Composite.NOT_PACKING, bitfieldDt.getBaseDataType(), - bitfieldDt.getBaseTypeSize()); + int sizeAlignment = bitfieldDt.getBaseDataType().getAlignment(); getBitFieldAlignment((BitFieldDataType) lastComponent.getDataType()); - offset += DataOrganizationImpl.getPaddingSize(sizeAlignment, offset); + offset = DataOrganizationImpl.getAlignedOffset(sizeAlignment, offset); } } return offset; @@ -129,13 +128,13 @@ class AlignedComponentPacker { private int getBitFieldAlignment(BitFieldDataType bitfieldDt) { - if (!bitFieldPacking.useMSConvention() && packValue != Composite.NOT_PACKING) { + if (!bitFieldPacking.useMSConvention() && packValue != CompositeInternal.DEFAULT_PACKING) { // GCC always uses 1 when packing regardless of pack value return 1; } - return CompositeAlignmentHelper.getPackedAlignment(dataOrganization, packValue, - bitfieldDt.getBaseDataType(), bitfieldDt.getBaseTypeSize()); + return CompositeAlignmentHelper + .getPackedAlignment(bitfieldDt.getBaseDataType().getAlignment(), packValue); } private boolean isIgnoredZeroBitField(BitFieldDataType zeroBitFieldDt) { @@ -167,11 +166,11 @@ class AlignedComponentPacker { if (!bitFieldPacking.useMSConvention() && !isLastComponent) { // GCC ignores pack value for :0 bitfield alignment but considers it when // passing alignment along to structure - pack = Composite.NOT_PACKING; + pack = CompositeInternal.NO_PACKING; } - return CompositeAlignmentHelper.getPackedAlignment(dataOrganization, pack, - zeroBitFieldDt.getBaseDataType(), zeroBitFieldDt.getBaseTypeSize()); + return CompositeAlignmentHelper + .getPackedAlignment(zeroBitFieldDt.getBaseDataType().getAlignment(), pack); } private void initGroup(InternalDataTypeComponent dataTypeComponent, boolean isLastComponent) { @@ -248,8 +247,8 @@ class AlignedComponentPacker { */ private void adjustZeroLengthBitField(int ordinal, int minimumAlignment) { - int minOffset = DataOrganizationImpl.getOffset(minimumAlignment, groupOffset); - int zeroAlignmentOffset = DataOrganizationImpl.getOffset(zeroAlignment, groupOffset); + int minOffset = DataOrganizationImpl.getAlignedOffset(minimumAlignment, groupOffset); + int zeroAlignmentOffset = DataOrganizationImpl.getAlignedOffset(zeroAlignment, groupOffset); // Determine component offset of zero-length bitfield and the component // which immediately follows it. @@ -312,8 +311,8 @@ class AlignedComponentPacker { dtSize = dataTypeComponent.getLength(); } - int alignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization, packValue, - componentDt, dtSize); + int alignment = + CompositeAlignmentHelper.getPackedAlignment(componentDt.getAlignment(), packValue); int offset; if (lastComponent != null && lastComponent.isZeroBitFieldComponent()) { @@ -322,7 +321,7 @@ class AlignedComponentPacker { offset = groupOffset; } else { - offset = DataOrganizationImpl.getOffset(alignment, minOffset); + offset = DataOrganizationImpl.getAlignedOffset(alignment, minOffset); if (lastComponent == null) { groupOffset = offset; // establish corrected group offset after alignment } @@ -345,14 +344,14 @@ class AlignedComponentPacker { int bitsConsumed; // update lastAlignment to be conveyed onto structure alignment - int alignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization, packValue, - bitfieldDt.getPrimitiveBaseDataType(), bitfieldDt.getBaseTypeSize()); + int alignment = CompositeAlignmentHelper.getPackedAlignment( + bitfieldDt.getPrimitiveBaseDataType().getAlignment(), packValue); // Set conveyed alignment early since bitfield alignment may be reduced below lastAlignment = Math.max(alignment, lastAlignment); if (lastComponent == null) { - offset = DataOrganizationImpl.getOffset(alignment, groupOffset); + offset = DataOrganizationImpl.getAlignedOffset(alignment, groupOffset); bitsConsumed = 0; groupOffset = offset; // establish corrected group offset after alignment } @@ -406,10 +405,10 @@ class AlignedComponentPacker { if (offset % alignment != 0 || byteSize > bitfieldDt.getBaseTypeSize()) { // offset is not an aligned offset (which may be OK when packing with lastComponent) int alignedBaseOffset = - DataOrganizationImpl.getOffset(alignment, offset) - alignment; + DataOrganizationImpl.getAlignedOffset(alignment, offset) - alignment; if (endOffset >= alignedBaseOffset + bitfieldDt.getBaseTypeSize()) { // skip ahead to next aligned offset - offset = DataOrganizationImpl.getOffset(alignment, offset + 1); + offset = DataOrganizationImpl.getAlignedOffset(alignment, offset + 1); endOffset = offset + byteSize - 1; bitsConsumed = 0; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java index 71d8178b12..57842c80f5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java @@ -31,13 +31,13 @@ import ghidra.util.exception.DuplicateNameException; */ public class AlignedStructureInspector extends AlignedStructurePacker { - private AlignedStructureInspector(Structure structure) { + private AlignedStructureInspector(StructureInternal structure) { super(structure, getComponentWrappers(structure)); } private static List getComponentWrappers(Structure structure) { List list = new ArrayList<>(); - for (DataTypeComponent c : structure.getComponents()) { + for (DataTypeComponent c : structure.getDefinedComponents()) { list.add(new ReadOnlyComponentWrapper(c)); } return list; @@ -168,7 +168,7 @@ public class AlignedStructureInspector extends AlignedStructurePacker { * @param structure * @return aligned packing result */ - public static StructurePackResult packComponents(Structure structure) { + public static StructurePackResult packComponents(StructureInternal structure) { AlignedStructureInspector packer = new AlignedStructureInspector(structure); return packer.pack(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructurePacker.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructurePacker.java index 78525c8db2..6ca069481d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructurePacker.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructurePacker.java @@ -27,7 +27,7 @@ import java.util.List; */ public class AlignedStructurePacker { - private final Structure structure; + private final StructureInternal structure; private final List components; private final DataOrganization dataOrganization; @@ -38,7 +38,7 @@ public class AlignedStructurePacker { * during packing (ordinal, offset, length and bit-field datatypes may be modified) * @param components list of mutable component */ - protected AlignedStructurePacker(Structure structure, + protected AlignedStructurePacker(StructureInternal structure, List components) { this.structure = structure; this.components = components; @@ -75,7 +75,7 @@ public class AlignedStructurePacker { int componentCount = 0; AlignedComponentPacker packer = - new AlignedComponentPacker(structure.getPackingValue(), dataOrganization); + new AlignedComponentPacker(structure.getStoredPackingValue(), dataOrganization); // Remove any default components from list Iterator componentIterator = components.iterator(); @@ -95,7 +95,7 @@ public class AlignedStructurePacker { packer.addComponent(dataTypeComponent, isLastComponent); } - int externalAlignment = packer.getExternalAlignment(); + int defaultAlignment = packer.getDefaultAlignment(); int length = packer.getLength(); componentsChanged |= packer.componentsChanged(); @@ -104,22 +104,25 @@ public class AlignedStructurePacker { if (flexibleArrayComponent != null) { // account for flexible array type and any end of structure padding required int componentAlignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization, - structure.getPackingValue(), flexibleArrayComponent); - length = DataOrganizationImpl.getOffset(componentAlignment, length); - externalAlignment = - DataOrganizationImpl.getLeastCommonMultiple(externalAlignment, componentAlignment); + structure.getStoredPackingValue(), flexibleArrayComponent); + length = DataOrganizationImpl.getAlignedOffset(componentAlignment, length); + defaultAlignment = + DataOrganizationImpl.getLeastCommonMultiple(defaultAlignment, componentAlignment); } - int alignment = structure.getMinimumAlignment(); - if (alignment < externalAlignment) { - alignment = externalAlignment; + int alignment = defaultAlignment; + AlignmentType alignmentType = structure.getAlignmentType(); + if (alignmentType != AlignmentType.DEFAULT) { + // Apply minimum alignment if applicable - may be reduced by explicit pack + // Simplified logic assumes pack and align values which are a power of 2 (1,2,4,8,16...) + int minAlign = + alignmentType == AlignmentType.MACHINE ? dataOrganization.getMachineAlignment() + : structure.getExplicitMinimumAlignment(); + alignment = Math.max(defaultAlignment, minAlign); } if (length != 0) { - int padSize = DataOrganizationImpl.getPaddingSize(alignment, length); - if (padSize > 0) { - length += padSize; - } + length = DataOrganizationImpl.getAlignedOffset(alignment, length); } return new StructurePackResult(componentCount, length, alignment, componentsChanged); @@ -135,7 +138,7 @@ public class AlignedStructurePacker { * @param components structure components (excludes any trailing flexible array). * @return aligned packing result */ - public static StructurePackResult packComponents(Structure structure, + public static StructurePackResult packComponents(StructureInternal structure, List components) { AlignedStructurePacker packer = new AlignedStructurePacker(structure, components); return packer.pack(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignmentType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignmentType.java new file mode 100644 index 0000000000..96665a19ff --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignmentType.java @@ -0,0 +1,41 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.model.data; + +/** + * AlignmentType specifies the type of alignment which applies to a composite data type. + * This can be DEFAULT, MACHINE, EXPLICIT. For packed composites, the length of the composite + * will be padded to force the length to a multiple of the computed alignment. + */ +public enum AlignmentType { + /** + * DEFAULT - this data type's alignment is computed based upon its current pack setting + * and data organization rules. If packing is disabled the computed alignment will be 1. + */ + DEFAULT, + /** + * MACHINE - this data type's alignment will be a multiple of the machine alignment + * specified by the data organization. In general, and for all non-packed composites, the + * computed alignment will match the machine alignment if this setting is used. + */ + MACHINE, + /** + * MACHINE - this data type's alignment will be a multiple of the explicit alignment + * value specified for the datatype. For all non-packed composites, the + * computed alignment will match the machine alignment if this setting is used. + */ + EXPLICIT; +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ArrayDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ArrayDataType.java index fc39685ced..60913b8964 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ArrayDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ArrayDataType.java @@ -130,6 +130,11 @@ public class ArrayDataType extends DataTypeImpl implements Array { return DataTypeUtilities.getMnemonic(this, false, settings); } + @Override + public boolean isZeroLength() { + return dataType.isZeroLength(); + } + @Override public int getLength() { return numElements * getElementLength(); @@ -160,11 +165,18 @@ public class ArrayDataType extends DataTypeImpl implements Array { @Override public void dataTypeSizeChanged(DataType dt) { - if (dt.equals(dataType)) { + if (dt == dataType) { notifySizeChanged(); } } + @Override + public void dataTypeAlignmentChanged(DataType dt) { + if (dt == dataType) { + notifyAlignmentChanged(); + } + } + @Override public Class getValueClass(Settings settings) { return getArrayValueClass(settings); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Composite.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Composite.java index dd4887bd7e..ae01c91e41 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Composite.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Composite.java @@ -15,56 +15,13 @@ */ package ghidra.program.model.data; +import java.util.Set; + /** * Interface for common methods in Structure and Union */ public interface Composite extends DataType { - /** - * AlignmentType defined the three states for the type of alignment of a composite data type. - * This can be default aligned, machine aligned or aligned by value. - *
    This controls how this data type will be aligned within other data types. - *
    Default Aligned means to determine this data type's alignment based upon the - * alignments of its components. This is controlled by the Data Organization that is provided - * by its data type manager. If there is no data type manager then a default data organization - * is used. - *
    Machine Aligned means this data type's alignment will use a minimum alignment that - * is the machine alignment specified by the data organization. - *
    Align By Value means that a "minimum alignment value", which is a power of 2 and - * specified elsewhere, will affect the alignment so that it will be at least the - * indicated value and will be a multiple of the minimum value and of the default value. - *
    Note: If the data organization specifies a maximum alignment, other than 0, then the - * alignment value will not be allowed to exceed the maximum alignment for any of these types. - */ - public static enum AlignmentType implements NamedAlignment { - DEFAULT_ALIGNED("Default Aligned"), - MACHINE_ALIGNED("Machine Aligned"), - ALIGNED_BY_VALUE("Align By Value"); - - private String name; - - AlignmentType(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public String toString() { - return name; - } - } - - interface NamedAlignment { - public String getName(); - } - - public final static int DEFAULT_ALIGNMENT_VALUE = 0; - public final static int NOT_PACKING = 0; - /** * Sets the string describing this data type. * @param desc the new description. @@ -74,8 +31,8 @@ public interface Composite extends DataType { /** * Gets the number of component data types in this composite. - * The count will include all undefined filler components which may be present - * within an unaligned structure. Structures do not include the + * If this is Structure with packing disabled, the count will include all undefined filler + * components which may be present. In addition, Structures do not include the * optional trailing flexible array component in this count * (see {@link Structure#hasFlexibleArrayComponent()}). * @return the number of components that make up this composite @@ -84,9 +41,13 @@ public interface Composite extends DataType { /** * Returns the number of explicitly defined components in this composite. - * For Unions and aligned Structures this is equivalent to {@link #getNumComponents()} - * since they do not contain undefined components. The count will exclude all undefined - * filler components which may be present within an unaligned structure. + * For Unions and packed Structures this is equivalent to {@link #getNumComponents()} + * since they do not contain undefined components. + * This count will always exclude all undefined filler components which may be present + * within a Structure whoose packing is disabled (see {@link #isPackingEnabled()}). + * In addition, Structures do not include the + * optional trailing flexible array component in this count + * (see {@link Structure#hasFlexibleArrayComponent()}). * @return the number of explicitly defined components in this composite */ public abstract int getNumDefinedComponents(); @@ -95,27 +56,28 @@ public interface Composite extends DataType { * Returns the component of this data type with the indicated ordinal. * @param ordinal the component's ordinal (zero based). * @return the data type component. - * @throws ArrayIndexOutOfBoundsException if the ordinal is out of bounds + * @throws IndexOutOfBoundsException if the ordinal is out of bounds */ - public abstract DataTypeComponent getComponent(int ordinal); + public abstract DataTypeComponent getComponent(int ordinal) throws IndexOutOfBoundsException; /** * Returns an array of Data Type Components that make up this composite including - * undefined filler components which may be present within an unaligned structure. + * undefined filler components which may be present within a Structure whch has packing disabled. + * Structures do not include the optional trailing flexible array component in the returned array. * The number of components corresponds to {@link #getNumComponents()}. - * @return list all components + * @return array all components */ public abstract DataTypeComponent[] getComponents(); /** * Returns an array of Data Type Components that make up this composite excluding - * undefined filler components which may be present within an unaligned structure. - * The number of components corresponds to {@link #getNumComponents()}. For Unions and - * aligned Structures this is equivalent to {@link #getComponents()} - * since they do not contain undefined components. Structures do not include the - * optional trailing flexible array component in this list + * undefined filler components which may be present within Structures where packing is disabled. + * The number of components corresponds to {@link #getNumDefinedComponents()}. For Unions and + * packed Structures this is equivalent to {@link #getComponents()} + * since they do not contain undefined filler components. Structures do not include the + * optional trailing flexible array component in the returned array * (see {@link Structure#getFlexibleArrayComponent()}). - * @return list all explicitly defined components + * @return array all explicitly defined components */ public abstract DataTypeComponent[] getDefinedComponents(); @@ -164,9 +126,9 @@ public interface Composite extends DataType { /** * Adds a new bitfield to the end of this composite. This method is intended - * to be used with aligned structures/unions only where the bitfield will be + * to be used with packed structures/unions only where the bitfield will be * appropriately packed. The minimum storage storage byte size will be applied. - * It will not provide useful results within unaligned composites. + * It will not provide useful results for composites with packing disabled. * @param baseDataType the bitfield base datatype (certain restrictions apply). * @param bitSize the bitfield size in bits * @param componentName the field name to associate with this component. @@ -208,9 +170,10 @@ public interface Composite extends DataType { * allowed to be inserted into this composite data type. * For example, suppose dt1 contains dt2. Therefore it is not valid * to insert dt1 to dt2 since this would cause a cyclic dependency. - * @throws ArrayIndexOutOfBoundsException if component ordinal is out of bounds + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ - public DataTypeComponent insert(int ordinal, DataType dataType) throws IllegalArgumentException; + public DataTypeComponent insert(int ordinal, DataType dataType) + throws IndexOutOfBoundsException, IllegalArgumentException; /** * Inserts a new datatype at the specified ordinal position in this composite. @@ -226,10 +189,10 @@ public interface Composite extends DataType { * length is specified. * For example, suppose dt1 contains dt2. Therefore it is not valid * to insert dt1 to dt2 since this would cause a cyclic dependency. - * @throws ArrayIndexOutOfBoundsException if component ordinal is out of bounds + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ public DataTypeComponent insert(int ordinal, DataType dataType, int length) - throws IllegalArgumentException; + throws IndexOutOfBoundsException, IllegalArgumentException; /** * Inserts a new datatype at the specified ordinal position in this composite. @@ -247,28 +210,28 @@ public interface Composite extends DataType { * is specified. * For example, suppose dt1 contains dt2. Therefore it is not valid * to insert dt1 to dt2 since this would cause a cyclic dependency. - * @throws ArrayIndexOutOfBoundsException if component ordinal is out of bounds + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ public DataTypeComponent insert(int ordinal, DataType dataType, int length, String name, - String comment) throws ArrayIndexOutOfBoundsException, IllegalArgumentException; + String comment) throws IndexOutOfBoundsException, IllegalArgumentException; /** * Deletes the component at the given ordinal position. - *
    Note: Removal of bitfields from an unaligned structure will - * not shift other components with vacated bytes reverting to undefined. + *
    Note: Removal of bitfields from a structure with packing disabled will + * not shift other components causing vacated bytes to revert to undefined filler. * @param ordinal the ordinal of the component to be deleted. - * @throws ArrayIndexOutOfBoundsException if component ordinal is out of bounds + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ - public void delete(int ordinal) throws ArrayIndexOutOfBoundsException; + public void delete(int ordinal) throws IndexOutOfBoundsException; /** - * Deletes the components at the given ordinal positions. - *
    Note: Removal of bitfields from an unaligned structure will - * not shift other components with vacated bytes reverting to undefined. + * Deletes the specified set of components at the given ordinal positions. + *
    Note: Removal of bitfields from a structure with packing disabled will + * not shift other components causing vacated bytes to revert to undefined filler. * @param ordinals the ordinals of the component to be deleted. - * @throws ArrayIndexOutOfBoundsException if any specified component ordinal is out of bounds + * @throws IndexOutOfBoundsException if any specified component ordinal is out of bounds */ - public void delete(int[] ordinals) throws ArrayIndexOutOfBoundsException; + public void delete(Set ordinals) throws IndexOutOfBoundsException; /** * Check if a data type is part of this data type. A data type could @@ -283,111 +246,194 @@ public interface Composite extends DataType { public abstract boolean isPartOf(DataType dataType); /** - * Updates the composite to any changes in the data organization. If the composite is not - * internally aligned, this method does nothing. - */ - public void realign(); - - /** - * Determine if this data type has its internal components currently aligned. - * @return true if this data type's components are aligned relative to each other using the - * current data organization. When internally aligned the end of this data type will be padded - * to a multiple of its actual alignment. - */ - public boolean isInternallyAligned(); - - /** - * Sets whether this data type's internal components are currently aligned or unaligned. - * @param aligned true means align the internal components of this data type. - * false means don't align it. True also causes the end of this data type to be padded - * to a multiple of its actual alignment. - */ - public void setInternallyAligned(boolean aligned); - - /** - * The overall (external) alignment changed for the specified data type. - * In other words, the data type has a different alignment when placed inside other structures. + * The alignment changed for the specified data type. If packing is enabled for this + * composite, the placement of the component may be affected by a change in its alignment. + * A non-packed composite can ignore this notification. * @param dt the data type whose alignment changed. */ + @Override public void dataTypeAlignmentChanged(DataType dt); /** - * Gets the current packing value (typically a power of 2). If this isn't a packed data - * type then NOT_PACKING is returned. The packing value only pertains to internally aligned composite - * data types. Aligned structures allow packing. - * @return the current packing value or NOT_PACKING. + * Updates packed composite to any changes in the data organization. If the composite does + * not have packing enabled this method does nothing. + *
    + * NOTE: Changes to data organization is discouraged. Attempts to use this method in such + * cases should be performed on all composites in dependency order (ignoring pointer components). */ - public int getPackingValue(); + public void repack(); /** - * Sets the current packing value (usually a power of 2). A value of NOT_PACKING should be passed - * if this isn't a packed data type. Otherwise this value indicates a maximum alignment - * for any component within this data type. Calling this method will cause the data type to - * become an internally aligned data type. - *
    Note: If a component's data type has a specific external alignment, it will - * override this value if necessary. - * @param packingValue the new packing value or 0 for NOT_PACKING. - * A negative value will be treated the same as 0. + * @return the packing type set for this composite */ - public void setPackingValue(int packingValue); + public PackingType getPackingType(); /** - * Get the external alignment (a minimum alignment) for this DataType. - * This controls where this data type will get aligned within other data types. - * It also causes the end of this data type to get padded so its length is a multiple - * of the alignment. - * @return the external alignment for this DataType or DEFAULT_ALIGNMENT_VALUE. + * Determine if this data type has its internal components currently packed + * based upon alignment and packing settings. If disabled, component placement + * is based upon explicit placement by offset. + * @return true if this data type's components auto-packed */ - public int getMinimumAlignment(); - - /** - * Sets the external alignment (a minimum alignment) for this DataType. - * This controls where this data type will get aligned within other data types. - * It also causes the end of this data type to get padded so its length is a multiple - * of the alignment. Calling this method will cause the data type to - * become an internally aligned data type. - * @param minimumAlignment the external (minimum) alignment for this DataType. - * Any value less than 1 will revert to default alignment. - */ - public void setMinimumAlignment(int minimumAlignment); - - /** - * Sets this data type's external (minimum) alignment to the default alignment. This data type's - * external alignment will be based upon the components it contains. This should be used - * when a data type doesn't have an alignment attribute specified. Calling this method will - * cause the data type to become an internally aligned data type. - */ - public void setToDefaultAlignment(); - - /** - * Sets this data type's external (minimum) alignment to a multiple of the machine alignment that is - * specified in the DataOrganization. The machine alignment is defined as the maximum useful - * alignment for the target machine. This should be used when a data type has an alignment - * attribute specified without a size (indicating to use the machine alignment). - * Calling this method will cause the data type to become an internally aligned data type. - */ - public void setToMachineAlignment(); - - /** - * Whether or not this data type is using the default external (minimum) alignment. - * @return true if this data type has the default external alignment. - */ - public boolean isDefaultAligned(); - - /** - * Whether or not this data type is using the machine alignment value from the - * DataOrganization for its external (minimum) alignment. - * @return true if this data type is using the machine alignment as the minimum alignment. - */ - public boolean isMachineAligned(); - - /** - * Get the bitfield packing information associated with the underlying - * data organization. - * @return bitfield packing information - */ - public default BitFieldPacking getBitFieldPacking() { - return getDataOrganization().getBitFieldPacking(); + public default boolean isPackingEnabled() { + return getPackingType() != PackingType.DISABLED; } + /** + * Sets whether this data type's internal components are currently packed. The + * affect of disabled packing differs between {@link Structure} and {@link Union}. When + * packing disabled: + *

      + *
    • Structures utilize explicit component offsets and produce undefined filler + * components where defined components do not consume space.
    • + *
    • Unions always place components at offset 0 and do not pad for alignment. + *
    + * In addition, when packing is disabled the default alignment is always 1 unless a + * different minimum alignment has been set. When packing is enabled the overall + * composite length infleunced by the composite's minimum alignment setting. + * If a change in enablement occurs, the default alignment and packing behavior + * will be used. + * @param enabled true enables packing of components respecting component + * alignment and pack setting, whereas false disables packing. + */ + public void setPackingEnabled(boolean enabled); + + /** + * Determine if packing is enabled with an explicit packing value (see {@link #getExplicitPackingValue()}). + * @return true if packing is enabled with an explicit packing value, else false. + */ + public default boolean hasExplicitPackingValue() { + return getPackingType() == PackingType.EXPLICIT; + } + + /** + * Determine if default packing is enabled. + * @return true if default packing is enabled. + */ + public default boolean hasDefaultPacking() { + return getPackingType() == PackingType.DEFAULT; + } + + /** + * Gets the current packing value (typically a power of 2). + * If this isn't a packed composite with an explicit packing value (see {@link #hasExplicitPackingValue()}) + * then the return value is undefined. + * @return the current packing value or an undefined non-positive value + */ + public int getExplicitPackingValue(); + + /** + * Sets the pack value for this composite (positive value, usually a power of 2). + * If packing was previously disabled, packing will be enabled. This value will + * establish the maximum effective alignment for this composite and each of the + * components during the alignment computation (e.g., a value of 1 will eliminate + * any padding). The overall composite length may be infleunced by the composite's + * minimum alignment setting. + * @param packingValue the new positive packing value. + * @throws IllegalArgumentException if a non-positive value is specified. + */ + public void setExplicitPackingValue(int packingValue); + + /** + * Same as {@link #setExplicitPackingValue(int)}. + * @param packingValue the new positive packing value. + * @throws IllegalArgumentException if a non-positive value is specified. + */ + public default void pack(int packingValue) { + setExplicitPackingValue(packingValue); + } + + /** + * Enables default packing behavior. + * If packing was previously disabled, packing will be enabled. + * Composite will automatically pack based upon the alignment requirements + * of its components with overall composite length possibly infleunced by the composite's + * minimum alignment setting. + */ + public void setToDefaultPacking(); + + /** + * Get the computed alignment for this composite based upon packing and minimum + * alignment settings as well as component alignment. If packing is disabled, + * the alignment will always be 1 unless a minimum alignment has been set. + * @return this composites alignment + */ + @Override + abstract int getAlignment(); + + /** + * @return the alignment type set for this composite + */ + abstract AlignmentType getAlignmentType(); + + /** + * Whether or not this data type is using the default alignment. When Structure packing + * is disabled the default alignment is always 1 (see {@link Structure#setPackingEnabled(boolean)}. + * @return true if this data type is using its default alignment. + */ + public default boolean isDefaultAligned() { + return getAlignmentType() == AlignmentType.DEFAULT; + } + + /** + * Whether or not this data type is using the machine alignment value, specified by + * {@link DataOrganization#getMachineAlignment()}, for its alignment. + * @return true if this data type is using the machine alignment as its alignment. + */ + public default boolean isMachineAligned() { + return getAlignmentType() == AlignmentType.MACHINE; + } + + /** + * Determine if an explicit minimum alignment has been set (see {@link #getExplicitMinimumAlignment()}). + * An undefined value is returned if default alignment or machine alignment is enabled. + * @return true if an explicit minimum alignment has been set, else false + */ + public default boolean hasExplicitMinimumAlignment() { + return getAlignmentType() == AlignmentType.EXPLICIT; + } + + /** + * Get the explicitminimum alignment setting for this Composite which contributes + * to the actual computed alignment value (see {@link #getAlignment()}. + * @return the minimum alignment setting for this Composite or an undefined + * non-positive value if an explicit minimum alignment has not been set. + */ + public int getExplicitMinimumAlignment(); + + /** + * Sets this data type's explicit minimum alignment (positive value). + * Together with the pack setting and component alignments will + * affect the actual computed alignment of this composite. + * When packing is enabled, the alignment setting may also affect padding + * at the end of the composite and its length. When packing is disabled, + * this setting will not affect the length of thhis composite. + * @param minAlignment the minimum alignment for this Composite. + * @throws IllegalArgumentException if a non-positive value is specified + */ + public void setExplicitMinimumAlignment(int minAlignment); + + /** + * Same as {@link #setExplicitMinimumAlignment(int)}. + * @param minAlignment the explicit minimum alignment for this Composite. + * @throws IllegalArgumentException if a non-positive value is specified + */ + public default void align(int minAlignment) { + setExplicitMinimumAlignment(minAlignment); + } + + /** + * Sets this data type's alignment to its default alignment. For packed + * composites, this data type's alignment will be based upon the components it contains and + * its current pack settings. This is the default state and only needs to be used + * when changing from a non-default alignment type. + */ + public void setToDefaultAligned(); + + /** + * Sets this data type's minimum alignment to the machine alignment which is + * specified by {@link DataOrganization#getMachineAlignment()}. The machine alignment is + * defined as the maximum useful alignment for the target machine. + */ + public void setToMachineAligned(); + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeAlignmentHelper.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeAlignmentHelper.java index 51e8f63007..beedd5cdfa 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeAlignmentHelper.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeAlignmentHelper.java @@ -18,14 +18,14 @@ package ghidra.program.model.data; public class CompositeAlignmentHelper { private static int getCompositeAlignmentMultiple(DataOrganization dataOrganization, - Composite composite) { + CompositeInternal composite) { int allComponentsLCM = 1; - int packingAlignment = composite.getPackingValue(); + int packingValue = composite.getStoredPackingValue(); DataTypeComponent[] dataTypeComponents = composite.getDefinedComponents(); for (DataTypeComponent dataTypeComponent : dataTypeComponents) { int impartedAlignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization, - packingAlignment, dataTypeComponent); + packingValue, dataTypeComponent); if (impartedAlignment != 0) { allComponentsLCM = DataOrganizationImpl.getLeastCommonMultiple(allComponentsLCM, impartedAlignment); @@ -36,7 +36,7 @@ public class CompositeAlignmentHelper { DataTypeComponent flexibleArrayComponent = struct.getFlexibleArrayComponent(); if (flexibleArrayComponent != null) { allComponentsLCM = getComponentAlignmentLCM(dataOrganization, allComponentsLCM, - packingAlignment, flexibleArrayComponent); + packingValue, flexibleArrayComponent); } } return allComponentsLCM; @@ -58,53 +58,33 @@ public class CompositeAlignmentHelper { // Zero-length bitfields ignored within unions for non-MSVC cases return 0; } - DataType componentDt = component.getDataType(); - int dtSize = componentDt.getLength(); - if (dtSize <= 0) { - dtSize = component.getLength(); - } - return getPackedAlignment(dataOrganization, packingValue, componentDt, dtSize); + return getPackedAlignment(componentDt.getAlignment(), packingValue); } - private static int getPackedAlignment(int componentAlignment, int forcedAlignment, - int packingAlignment) { - // Only do packing if we are not forcing an alignment. + static int getPackedAlignment(int componentAlignment, int packingValue) { int alignment = componentAlignment; - if (packingAlignment != Composite.NOT_PACKING) { // TODO Should this be packingValue > 0? - if (forcedAlignment > packingAlignment) { - alignment = forcedAlignment; - } - else if (alignment > packingAlignment) { - alignment = packingAlignment; - } + if (packingValue > 0 && packingValue < componentAlignment) { + alignment = packingValue; } return alignment; } - public static int getPackedAlignment(DataOrganization dataOrganization, int packingAlignment, - DataType componentDt, int dtSize) { - int componentAlignment = dataOrganization.getAlignment(componentDt, dtSize); - int componentForcedAlignment = dataOrganization.getForcedAlignment(componentDt); - boolean componentForcingAlignment = componentForcedAlignment > 0; - if (componentForcingAlignment) { - componentAlignment = DataOrganizationImpl.getLeastCommonMultiple(componentAlignment, - componentForcedAlignment); - } - return getPackedAlignment(componentAlignment, componentForcedAlignment, packingAlignment); - } - - public static int getAlignment(DataOrganization dataOrganization, Composite dataType) { + public static int getAlignment(DataOrganization dataOrganization, CompositeInternal composite) { // TODO: goal is to eliminate this method in favor of pack once and remember alignment - if (!dataType.isInternallyAligned()) { - return 1; // Unaligned + int minimumAlignment = composite.getStoredMinimumAlignment(); + if (minimumAlignment < CompositeInternal.DEFAULT_ALIGNMENT) { + minimumAlignment = dataOrganization.getMachineAlignment(); + } + + if (!composite.isPackingEnabled()) { + return minimumAlignment == CompositeInternal.DEFAULT_ALIGNMENT ? 1 : minimumAlignment; } - int lcm = getCompositeAlignmentMultiple(dataOrganization, dataType); - int minimumAlignment = dataType.getMinimumAlignment(); - if ((minimumAlignment != Composite.DEFAULT_ALIGNMENT_VALUE) && + int lcm = getCompositeAlignmentMultiple(dataOrganization, composite); + if ((minimumAlignment != CompositeInternal.DEFAULT_ALIGNMENT) && (lcm % minimumAlignment != 0)) { lcm = DataOrganizationImpl.getLeastCommonMultiple(lcm, minimumAlignment); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeDataTypeImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeDataTypeImpl.java index 810734a006..0e7295c295 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeDataTypeImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeDataTypeImpl.java @@ -26,17 +26,18 @@ import ghidra.util.exception.NotYetImplementedException; /** * Common implementation methods for structure and union */ -public abstract class CompositeDataTypeImpl extends GenericDataType implements Composite { - private final static long serialVersionUID = 1; +public abstract class CompositeDataTypeImpl extends GenericDataType implements CompositeInternal { + + // Strings used for toString formatting + private static final String ALIGN_NAME = "aligned"; + private static final String PACKING_NAME = "pack"; + private static final String DISABLED_PACKING_NAME = "disabled"; + private static final String DEFAULT_PACKING_NAME = ""; + private String description; - protected boolean aligned = false; // WARNING, changing the initial value for this will cause - // subtle errors - One I know of is in the StructureDataType - // copyComponent method. It has built in assumptions about this. - - protected AlignmentType alignmentType = AlignmentType.DEFAULT_ALIGNED; - protected int packingValue = NOT_PACKING; - protected int externalAlignment = DEFAULT_ALIGNMENT_VALUE; + protected int minimumAlignment = DEFAULT_ALIGNMENT; + protected int packing = NO_PACKING; /** * Construct a new composite with the given name @@ -67,6 +68,21 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C description = ""; } + @Override + public int getStoredPackingValue() { + return packing; + } + + @Override + public int getStoredMinimumAlignment() { + return minimumAlignment; + } + + @Override + public void dataTypeNameChanged(DataType dt, String oldName) { + // ignored + } + /** * Get the preferred length for a new component. For Unions and internally * aligned structures the preferred component length for a fixed-length dataType @@ -80,9 +96,6 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C * @return preferred component length */ protected int getPreferredComponentLength(DataType dataType, int length) { - if ((isInternallyAligned() || (this instanceof Union)) && !(dataType instanceof Dynamic)) { - length = -1; // force use of datatype size - } int dtLength = dataType.getLength(); if (length <= 0) { length = dtLength; @@ -99,7 +112,7 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C @Override public boolean isDynamicallySized() { - return isInternallyAligned(); + return true; // assume dynamically sized component datatype may be present } @Override @@ -135,10 +148,6 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C * @throws IllegalArgumentException if the data type is invalid. */ protected void validateDataType(DataType dataType) { - if (isInternallyAligned() && dataType == DataType.DEFAULT) { - throw new IllegalArgumentException( - "The DEFAULT data type is not allowed in an aligned composite data type."); - } if (dataType instanceof FactoryDataType) { throw new IllegalArgumentException("The \"" + dataType.getName() + "\" data type is not allowed in a composite data type."); @@ -250,139 +259,161 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C } @Override - public int getPackingValue() { - return packingValue; - } - - @Override - public void setPackingValue(int packingValue) { - if (packingValue < 0) { - packingValue = NOT_PACKING; - } - aligned = true; - this.packingValue = packingValue; - adjustInternalAlignment(); - } - - @Override - public int getMinimumAlignment() { - if (alignmentType == AlignmentType.MACHINE_ALIGNED) { - return getMachineAlignment(); - } - if (alignmentType == AlignmentType.DEFAULT_ALIGNED) { - return Composite.DEFAULT_ALIGNMENT_VALUE; - } - return externalAlignment; - } - - @Override - public void setMinimumAlignment(int externalAlignment) { - if (externalAlignment < 1) { - this.externalAlignment = DEFAULT_ALIGNMENT_VALUE; - alignmentType = AlignmentType.DEFAULT_ALIGNED; - } - else { - this.externalAlignment = externalAlignment; - alignmentType = AlignmentType.ALIGNED_BY_VALUE; - } - aligned = true; - adjustInternalAlignment(); - } - - private int getMachineAlignment() { - return getDataOrganization().getMachineAlignment(); - } - - @Override - public boolean isInternallyAligned() { - return aligned; - } - - @Override - public boolean isDefaultAligned() { - return alignmentType == AlignmentType.DEFAULT_ALIGNED; - } - - @Override - public boolean isMachineAligned() { - return alignmentType == AlignmentType.MACHINE_ALIGNED; - } - - @Override - public void setInternallyAligned(boolean aligned) { - if (this.aligned != aligned) { - this.aligned = aligned; - if (!aligned) { - alignmentType = AlignmentType.DEFAULT_ALIGNED; - packingValue = Composite.NOT_PACKING; - } - } - adjustInternalAlignment(); - } - - @Override - public void setToDefaultAlignment() { - aligned = true; - alignmentType = AlignmentType.DEFAULT_ALIGNED; - adjustInternalAlignment(); - } - - @Override - public void setToMachineAlignment() { - aligned = true; - alignmentType = AlignmentType.MACHINE_ALIGNED; - adjustInternalAlignment(); + public final void repack() { + repack(true); } /** - * Notify any parent data types that this composite data type's alignment has - * changed. + * Repack components within this composite based on the current packing, alignment + * and {@link DataOrganization} settings. Non-packed Structures: change detection + * is limited to component count and length is assumed to already be correct. + *

    + * NOTE: If modifications to stored length are made prior to invoking this method, + * detection of a size change may not be possible. + *

    + * NOTE: Currently a change in calculated alignment can not be provided since + * this value is not stored. + * + * @param notify if true notification will be sent to parents if a size change + * or component placement change is detected. + * @return true if a layout change was detected. */ - protected void notifyAlignmentChanged() { - DataType[] parents = getParents(); - for (DataType dataType : parents) { - if (dataType instanceof Composite) { - Composite composite = (Composite) dataType; - composite.dataTypeAlignmentChanged(this); - } - } - } - - /** - * Adjusts the internal alignment of components within this composite based on - * the current settings of the internal alignment, packing, alignment type and - * minimum alignment value. This method should be called whenever any of the - * above settings are changed or whenever a components data type is changed or a - * component is added or removed. - */ - protected abstract void adjustInternalAlignment(); + public abstract boolean repack(boolean notify); @Override - public int getAlignment() { - return CompositeAlignmentHelper.getAlignment(getDataOrganization(), this); + public void setPackingEnabled(boolean enabled) { + if (enabled == isPackingEnabled()) { + return; + } + setStoredPackingValue(enabled ? DEFAULT_PACKING : NO_PACKING); } - // set my alignment info to the same as the given composite - protected void setAlignment(Composite composite) { - - aligned = composite.isInternallyAligned(); - - if (composite.isDefaultAligned()) { - alignmentType = AlignmentType.DEFAULT_ALIGNED; + @Override + public PackingType getPackingType() { + if (packing < DEFAULT_PACKING) { + return PackingType.DISABLED; } - else if (composite.isMachineAligned()) { - alignmentType = AlignmentType.MACHINE_ALIGNED; + if (packing == DEFAULT_PACKING) { + return PackingType.DEFAULT; + } + return PackingType.EXPLICIT; + } + + @Override + public void setToDefaultPacking() { + setStoredPackingValue(DEFAULT_PACKING); + } + + @Override + public int getExplicitPackingValue() { + return packing; + } + + @Override + public void setExplicitPackingValue(int packingValue) { + if (packingValue <= 0) { + throw new IllegalArgumentException( + "explicit packing value must be positive: " + packingValue); + } + setStoredPackingValue(packingValue); + } + + private void setStoredPackingValue(int packingValue) { + if (minimumAlignment < NO_PACKING) { + throw new IllegalArgumentException("invalid packing value: " + packingValue); + } + if (packingValue == this.packing) { + return; + } + if (this.packing == NO_PACKING || packingValue == NO_PACKING) { + // force default alignment when transitioning to or from disabled packing + this.minimumAlignment = DEFAULT_ALIGNMENT; + } + this.packing = packingValue; + repack(true); + } + + @Override + public AlignmentType getAlignmentType() { + if (minimumAlignment < DEFAULT_ALIGNMENT) { + return AlignmentType.MACHINE; + } + if (minimumAlignment == DEFAULT_ALIGNMENT) { + return AlignmentType.DEFAULT; + } + return AlignmentType.EXPLICIT; + } + + @Override + public void setToDefaultAligned() { + setStoredMinimumAlignment(DEFAULT_ALIGNMENT); + } + + @Override + public void setToMachineAligned() { + setStoredMinimumAlignment(MACHINE_ALIGNMENT); + } + + @Override + public int getExplicitMinimumAlignment() { + return minimumAlignment; + } + + @Override + public void setExplicitMinimumAlignment(int minimumAlignment) { + if (minimumAlignment <= 0) { + throw new IllegalArgumentException( + "explicit minimum alignment must be positive: " + minimumAlignment); + } + setStoredMinimumAlignment(minimumAlignment); + } + + private void setStoredMinimumAlignment(int minimumAlignment) { + if (minimumAlignment < MACHINE_ALIGNMENT) { + throw new IllegalArgumentException( + "invalid minimum alignment value: " + minimumAlignment); + } + if (this.minimumAlignment == minimumAlignment) { + return; + } + this.minimumAlignment = minimumAlignment; + repack(true); + } + + protected final int getNonPackedAlignment() { + int alignment; + if (minimumAlignment == DEFAULT_ALIGNMENT) { + alignment = 1; + } + else if (minimumAlignment == MACHINE_ALIGNMENT) { + alignment = getDataOrganization().getMachineAlignment(); } else { - if (alignmentType != AlignmentType.ALIGNED_BY_VALUE) { - alignmentType = AlignmentType.ALIGNED_BY_VALUE; - } - externalAlignment = composite.getMinimumAlignment(); + alignment = minimumAlignment; } + return alignment; + } - packingValue = composite.getPackingValue(); + @Override + public abstract int getAlignment(); + + @Override + public String toString() { + return toString(this); + } + + public static String toString(Composite composite) { + + StringBuilder stringBuffer = new StringBuilder(); + stringBuffer.append(composite.getPathName() + "\n"); + stringBuffer.append(getAlignmentAndPackingString(composite) + "\n"); + stringBuffer.append(getTypeName(composite) + " " + composite.getDisplayName() + " {\n"); + dumpComponents(composite, stringBuffer, " "); + stringBuffer.append("}\n"); + stringBuffer.append("Size = " + composite.getLength() + " Actual Alignment = " + + composite.getAlignment() + "\n"); + return stringBuffer.toString(); - adjustInternalAlignment(); } /** @@ -391,11 +422,13 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C * @param buffer string buffer * @param pad padding to be used with each component output line */ - protected void dumpComponents(StringBuilder buffer, String pad) { - // limit output of filler components for unaligned structures - DataTypeComponent[] components = getDefinedComponents(); + private static void dumpComponents(Composite composite, StringBuilder buffer, String pad) { + // limit output of filler components for non-packed structures + DataTypeComponent[] components = composite.getDefinedComponents(); for (DataTypeComponent dtc : components) { DataType dataType = dtc.getDataType(); +// buffer.append(pad + dtc.getOrdinal()); +// buffer.append(") "); buffer.append(pad + dtc.getOffset()); buffer.append(pad + dataType.getName()); if (dataType instanceof BitFieldDataType) { @@ -413,57 +446,76 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C buffer.append(pad + "\"" + comment + "\""); buffer.append("\n"); } + if (composite instanceof Structure) { + DataTypeComponent dtc = ((Structure) composite).getFlexibleArrayComponent(); + if (dtc != null) { + DataType dataType = dtc.getDataType(); + buffer.append(pad + dataType.getDisplayName() + "[0]"); + buffer.append(pad + dtc.getLength()); + buffer.append(pad + dtc.getFieldName()); + String comment = dtc.getComment(); + if (comment == null) { + comment = ""; + } + buffer.append(pad + "\"" + comment + "\""); + buffer.append("\n"); + } + } } - @Override - public String toString() { - StringBuilder stringBuffer = new StringBuilder(); - stringBuffer.append(getPathName() + "\n"); - stringBuffer.append(getAlignmentSettingsString() + "\n"); - stringBuffer.append(getTypeName() + " " + getDisplayName() + " {\n"); - dumpComponents(stringBuffer, " "); - stringBuffer.append("}\n"); - stringBuffer.append( - "Size = " + getLength() + " Actual Alignment = " + getAlignment() + "\n"); - return stringBuffer.toString(); - } - - private String getTypeName() { - if (this instanceof Structure) { + private static String getTypeName(Composite composite) { + if (composite instanceof Structure) { return "Structure"; } - else if (this instanceof Union) { + else if (composite instanceof Union) { return "Union"; } return ""; } - private String getAlignmentSettingsString() { - StringBuffer stringBuffer = new StringBuffer(); - if (!isInternallyAligned()) { - stringBuffer.append("Unaligned"); + public static String getAlignmentAndPackingString(Composite composite) { + StringBuilder buf = + new StringBuilder(getMinAlignmentString(composite)); + if (buf.length() != 0) { + buf.append(" "); } - else if (isDefaultAligned()) { - stringBuffer.append("Aligned"); - } - else if (isMachineAligned()) { - stringBuffer.append("Machine aligned"); - } - else { - long alignment = getMinimumAlignment(); - stringBuffer.append("align(" + alignment + ")"); - } - stringBuffer.append(getPackingString()); - return stringBuffer.toString(); + buf.append(getPackingString(composite)); + return buf.toString(); } - private String getPackingString() { - if (!isInternallyAligned()) { + public static String getMinAlignmentString(Composite composite) { + if (composite.isDefaultAligned()) { return ""; } - if (packingValue == Composite.NOT_PACKING) { - return ""; + StringBuilder buf = new StringBuilder(ALIGN_NAME); + buf.append("("); + if (composite.isMachineAligned()) { + buf.append("machine:"); + buf.append(composite.getDataOrganization().getMachineAlignment()); } - return " pack(" + packingValue + ")"; + else { + buf.append(composite.getExplicitMinimumAlignment()); + } + buf.append(")"); + return buf.toString(); } + + public static String getPackingString(Composite composite) { + StringBuilder buf = new StringBuilder(PACKING_NAME); + buf.append("("); + if (composite.isPackingEnabled()) { + if (composite.hasExplicitPackingValue()) { + buf.append(composite.getExplicitPackingValue()); + } + else { + buf.append(DEFAULT_PACKING_NAME); + } + } + else { + buf.append(DISABLED_PACKING_NAME); // NO_PACKING + } + buf.append(")"); + return buf.toString(); + } + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeInternal.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeInternal.java new file mode 100644 index 0000000000..7742102263 --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/CompositeInternal.java @@ -0,0 +1,154 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.model.data; + +import java.util.Comparator; + +/** + * Interface for common methods in Structure and Union + */ +public interface CompositeInternal extends Composite { + + /** + * The stored packing value which corresponds to a composite that will automatically pack + * based upon the alignment requirements of its components. A positive pack value will + * also pack in a similar fashion but will use the pack value as a maximum alignment + * for each component. + * See {@link #getStoredPackingValue}. + */ + public final static int DEFAULT_PACKING = 0; + + /** + * The stored packing value which corresponds to a composite whoose packing has been disabled. + * In the case of structures this will permit explicit component placement by + * offset within the structure and undefined filler components will be used. + * This is the initial state of all newly instantiated structures. + * See {@link #getStoredPackingValue()}. + */ + public final static int NO_PACKING = -1; + + /** + * The stored minimum alignment value which indicates the default alignment + * should be used based upon the packing and component alignment requirements. + * See {@link #getStoredMinimumAlignment}. + */ + public final static int DEFAULT_ALIGNMENT = 0; + + /** + * The stored minimum alignment value which indicates the machine alignment + * should be used as the minimum alignment (as defined by the current + * {@link DataOrganization#getMachineAlignment()}). + * See {@link #getStoredMinimumAlignment()}. + */ + public final static int MACHINE_ALIGNMENT = -1; + + /** + * Gets the current packing value (typically a power of 2). Other special values + * which may be returned include {@value #DEFAULT_PACKING} and {@value #NO_PACKING}. + * @return the current positive packing value, {@value #DEFAULT_PACKING} or {@value #NO_PACKING}. + */ + public int getStoredPackingValue(); + + /** + * Sets the current packing behavior (positive value, usually a power of 2). If a positive + * value is specified the use of packing will be enabled if it was previously disabled + * (see {@link #setPackingEnabled(boolean)}. A positive value will set the maximum + * alignment for this composite and each component within a structure + * (e.g., a value of 1 will eliminate any padding). + *
    + * Special packing values which may be specified include: + *

      + *
    • {@value #DEFAULT_PACKING} will perform default packing based upon the alignment + * requirements of the individual components.
    • + *
    • {@link #NO_PACKING} (or any negative value) will disable packing
    • + *
    + * @param packingValue the new positive packing value, or {@value #DEFAULT_PACKING} or + * {@link #NO_PACKING}. A negative value will be treated the same as {@link #NO_PACKING}. + */ +// public void setStoredPackingValue(int packingValue); + + /** + * Get the minimum alignment setting for this Composite which contributes + * to the actual computed alignment value (see {@link #getAlignment()}. + * @return the minimum alignment setting for this Composite or a reserved value to indicate + * either {@link #DEFAULT_ALIGNMENT} or {@link #MACHINE_ALIGNMENT}. + */ + public int getStoredMinimumAlignment(); + + /** + * ComponentComparator provides ability to compare two DataTypeComponent objects + * based upon their ordinal. Intended to be used to sort components based upon ordinal. + */ + public static class ComponentComparator implements Comparator { + + public static final ComponentComparator INSTANCE = new ComponentComparator(); + + @Override + public int compare(DataTypeComponent dtc1, DataTypeComponent dtc2) { + return dtc1.getOrdinal() - dtc2.getOrdinal(); + } + } + + /** + * OffsetComparator provides ability to compare an Integer offset with a + * DataTypeComponent object. The offset will be consider equal (0) if the component contains the + * offset. + */ + public static class OffsetComparator implements Comparator { + + public static final OffsetComparator INSTANCE = new OffsetComparator(); + + @Override + public int compare(Object o1, Object o2) { + if (o1 instanceof Integer) { + return -compare(o2, o1); + } + DataTypeComponent dtc = (DataTypeComponent) o1; + int offset = ((Integer) o2).intValue(); + if (offset < dtc.getOffset()) { + return 1; + } + else if (offset > dtc.getEndOffset()) { + return -1; + } + return 0; + } + + } + + /** + * OrdinalComparator provides ability to compare an Integer ordinal with a + * DataTypeComponent object. The ordinal will be consider equal (0) if the component corresponds + * to the specified ordinal. + *

    + */ + public static class OrdinalComparator implements Comparator { + + public static final OrdinalComparator INSTANCE = new OrdinalComparator(); + + @Override + public int compare(Object o1, Object o2) { + if (o1 instanceof Integer) { + return -compare(o2, o1); + } + DataTypeComponent dtc = (DataTypeComponent) o1; + int ordinal = ((Integer) o2).intValue(); + return dtc.getOrdinal() - ordinal; + } + + } + +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganization.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganization.java index f99045fb88..d3c4bacc23 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganization.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganization.java @@ -132,11 +132,6 @@ public interface DataOrganization { */ BitFieldPacking getBitFieldPacking(); - /** - * Remove all entries from the size alignment map - */ - void clearSizeAlignmentMap(); - /** * Gets the number of sizes that have an alignment specified. * @return the number of sizes with an alignment mapped to them. @@ -161,24 +156,20 @@ public interface DataOrganization { /** * Determines the alignment value for the indicated data type. (i.e. how the data type gets - * aligned within other data types.) NOTE: the alignment of bitfields is dependent upon packing - * rules which must be considered at the composite level. + * aligned within other data types.) NOTE: this method should not be used for bitfields + * which are highly dependent upon packing for a composite. This method will always return 1 + * for Dynamic and FactoryDataTypes. * @param dataType the data type - * @param dtSize the data type's size or component size - * @return the alignment + * @return the datatype alignment */ - int getAlignment(DataType dataType, int dtSize); + int getAlignment(DataType dataType); - boolean isForcingAlignment(DataType dataType); - - int getForcedAlignment(DataType dataType); - - /** - * Determines the offset where the specified data type should be placed to be properly aligned. - * @param minimumOffset the minimum allowable offset where the data type can be placed. - * @param dataType the data type - * @param dtSize the data type's size - * @return the aligned offset for the data type - */ - int getAlignmentOffset(int minimumOffset, DataType dataType, int dtSize); +// /** +// * Determines the offset where the specified data type should be placed to be properly aligned. +// * @param minimumOffset the minimum allowable offset where the data type can be placed. +// * @param dataType the data type +// * @param dtSize the data type's size +// * @return the aligned offset for the data type +// */ +// int getAlignmentOffset(int minimumOffset, DataType dataType, int dtSize); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java index c4543a9c75..efc8d0cd22 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataOrganizationImpl.java @@ -15,10 +15,10 @@ */ package ghidra.program.model.data; -import java.util.Arrays; +import java.util.*; import ghidra.program.model.lang.Language; -import ghidra.util.datastruct.IntIntHashtable; +import ghidra.util.SystemUtilities; import ghidra.util.exception.NoValueException; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.XmlElement; @@ -56,7 +56,7 @@ public class DataOrganizationImpl implements DataOrganization { /* * Map for determining the alignment of a data type based upon its size. */ - private final IntIntHashtable sizeAlignmentMap = new IntIntHashtable(); + private final HashMap sizeAlignmentMap = new HashMap<>(); /** * Creates a new default DataOrganization. This has a mapping which defines the alignment @@ -166,7 +166,7 @@ public class DataOrganizationImpl implements DataOrganization { /** * Set data endianess - * @param bigEndian is true to set big endian + * @param bigEndian true if big-endian, false if little-endian */ public void setBigEndian(boolean bigEndian) { this.bigEndian = bigEndian; @@ -411,9 +411,8 @@ public class DataOrganizationImpl implements DataOrganization { /** * Remove all entries from the size alignment map */ - @Override public void clearSizeAlignmentMap() { - sizeAlignmentMap.removeAll(); + sizeAlignmentMap.clear(); } /** @@ -431,7 +430,12 @@ public class DataOrganizationImpl implements DataOrganization { */ @Override public int[] getSizes() { - int[] keys = sizeAlignmentMap.getKeys(); + Set keySet = sizeAlignmentMap.keySet(); + int[] keys = new int[keySet.size()]; + int index = 0; + for (Integer k : keySet) { + keys[index++] = k; + } Arrays.sort(keys); return keys; } @@ -466,28 +470,19 @@ public class DataOrganizationImpl implements DataOrganization { } @Override - public int getAlignment(DataType dataType, int dtSize) { - // Don't do alignment on dynamic data types. - if (dataType instanceof Dynamic) { -// throw new AssertException("Dynamic data types don't have an alignment. \"" + -// dataType.getName() + "\" is dynamic."); + public int getAlignment(DataType dataType) { + int dtSize = dataType.getLength(); + if (dataType instanceof Dynamic || dataType instanceof FactoryDataType || dtSize <= 0) { return 1; } // Typedef is aligned the same as its underlying data type is aligned. if (dataType instanceof TypeDef) { - return getAlignment(((TypeDef) dataType).getBaseDataType(), dtSize); + return getAlignment(((TypeDef) dataType).getBaseDataType()); } // Array alignment is the alignment of its element data type. if (dataType instanceof Array) { DataType elementDt = ((Array) dataType).getDataType(); - int elementLength = ((Array) dataType).getElementLength(); - return getAlignment(elementDt, elementLength); - } - // Pointer alignment is based on its size or default pointer alignment if there is no size???? - if (dataType instanceof Pointer) { - if (dtSize <= 0) { - return getDefaultPointerAlignment(); - } + return getAlignment(elementDt); } // Structure's or Union's alignment is a multiple of the least common multiple of // the components. It can also be adjusted by packing and alignment attributes. @@ -499,19 +494,14 @@ public class DataOrganizationImpl implements DataOrganization { // See AlignedStructurePacker. if (dataType instanceof BitFieldDataType) { BitFieldDataType bitfieldDt = (BitFieldDataType) dataType; - return getAlignment(bitfieldDt.getBaseDataType(), bitfieldDt.getBaseTypeSize()); + return getAlignment(bitfieldDt.getBaseDataType()); } // Otherwise get the alignment based on the size. - if (sizeAlignmentMap.contains(dtSize)) { - try { - int sizeAlignment = sizeAlignmentMap.get(dtSize); - return ((absoluteMaxAlignment == 0) || (sizeAlignment < absoluteMaxAlignment)) - ? sizeAlignment - : absoluteMaxAlignment; - } - catch (NoValueException e) { - // Simply fall through to the default value. - } + if (sizeAlignmentMap.containsKey(dtSize)) { + int sizeAlignment = sizeAlignmentMap.get(dtSize); + return ((absoluteMaxAlignment == 0) || (sizeAlignment < absoluteMaxAlignment)) + ? sizeAlignment + : absoluteMaxAlignment; } if (dataType instanceof Pointer) { return getDefaultPointerAlignment(); @@ -519,114 +509,26 @@ public class DataOrganizationImpl implements DataOrganization { // Otherwise just assume the default alignment. return getDefaultAlignment(); } - - @Override - public boolean isForcingAlignment(DataType dataType) { - return getForcedAlignment(dataType) > 0; - } - - @Override - public int getForcedAlignment(DataType dataType) { - // Don't do forced alignment on dynamic data types. - if (dataType instanceof Dynamic) { - return 0; - } - // Typedef is aligned the same as its underlying data type is aligned. - if (dataType instanceof TypeDef) { - return getForcedAlignment(((TypeDef) dataType).getBaseDataType()); - } - // Array alignment is the alignment of its element data type. - if (dataType instanceof Array) { - DataType elementDt = ((Array) dataType).getDataType(); - return getForcedAlignment(elementDt); - } - // We don't allow alignment attribute on pointers. - if (dataType instanceof Pointer) { - return 0; - } - - // Structure's or Union's alignment is a multiple of the least common multiple of - // the components. It can also be adjusted by packing and alignment attributes. - if (dataType instanceof Composite) { - // Check whether this composite forces the alignment. - int forcedLCM = 0; - Composite composite = (Composite) dataType; - if (!composite.isInternallyAligned()) { - return 0; - } - if (!composite.isDefaultAligned()) { - int minimumAlignment = composite.getMinimumAlignment(); - forcedLCM = (minimumAlignment > 0) ? minimumAlignment : 0; - } - - // Check each component and get the least common multiple of their forced minimum alignments. - int componentForcedLCM = 0; - for (DataTypeComponent dataTypeComponent : composite.getDefinedComponents()) { - if (dataTypeComponent.isBitFieldComponent()) { - continue; - } - DataType componentDt = dataTypeComponent.getDataType(); - int forcedAlignment = getForcedAlignment(componentDt); - if (forcedAlignment > 0) { - if (componentForcedLCM > 0) { - componentForcedLCM = - getLeastCommonMultiple(componentForcedLCM, forcedAlignment); - } - else { - componentForcedLCM = forcedAlignment; - } - } - } - - if (forcedLCM > 0) { - if (componentForcedLCM > 0) { - // Both this composite and one or more of its children force the alignment. - return getLeastCommonMultiple(forcedLCM, componentForcedLCM); - } - // Children don't force alignment but this composite does. - return forcedLCM; - } - // This composite's forced alignment is based only on its children's forced alignments. - return componentForcedLCM; - } - // Otherwise not forcing alignment. - return 0; - } - - /** - * Determines the offset where the specified data type should be placed to be properly aligned. - * @param minimumOffset the minimum allowable offset where the data type can be placed. - * @param dataType the data type - * @param dtSize the data type's size - * @return the aligned offset for the data type - */ - @Override - public int getAlignmentOffset(int minimumOffset, DataType dataType, int dtSize) { - int alignment = getAlignment(dataType, dtSize); - return getOffset(alignment, minimumOffset); - } - + /** * Determines the first offset that is equal to or greater than the minimum offset which - * has the specified alignment. - * @param alignment the desired alignment + * has the specified alignment. If a non-positive alignment is specified the origina + * minimumOffset will be return. + * @param alignment the desired alignment (positive value) * @param minimumOffset the minimum offset * @return the aligned offset */ - public static int getOffset(int alignment, int minimumOffset) { - return alignment + ((minimumOffset - 1) & ~(alignment - 1)); - } - - /** - * Determines the amount of padding that should be added to a structure at the indicated - * offset in order to get the next component (member) to be aligned with the specified - * alignment within the structure. - * @param alignment the desired alignment - * @param offset the offset that the padding would be placed at to achieve the desired alignment. - * @return the padding needed at the offset. - */ - public static int getPaddingSize(int alignment, int offset) { - return (alignment - (offset % alignment)) % alignment; + public static int getAlignedOffset(int alignment, int minimumOffset) { + if (alignment <= 0) { + return minimumOffset; + } + if ((alignment & 1) == 0) { + // handle alignment which is a power-of-2 + return alignment + ((minimumOffset - 1) & ~(alignment - 1)); + } + int offcut = (minimumOffset % alignment); + int adj = (offcut != 0) ? (alignment - offcut) : 0; + return minimumOffset + adj; } /** @@ -731,17 +633,10 @@ public class DataOrganizationImpl implements DataOrganization { buffer.append("/>\n"); } if (sizeAlignmentMap.size() != 0) { - int[] keys = sizeAlignmentMap.getKeys(); buffer.append("\n"); - for (int key : keys) { + for (int key : sizeAlignmentMap.keySet()) { buffer.append("\n"); @@ -884,21 +779,16 @@ public class DataOrganizationImpl implements DataOrganization { if (pointerSize != op2.pointerSize || pointerShift != op2.pointerShift) { return false; } - int[] keys = sizeAlignmentMap.getKeys(); - int[] op2keys = op2.sizeAlignmentMap.getKeys(); - if (keys.length != op2keys.length) { + Set keys = sizeAlignmentMap.keySet(); + Set op2keys = op2.sizeAlignmentMap.keySet(); + if (keys.size() != op2keys.size()) { return false; } - try { - for (int i = 0; i < keys.length; ++i) { - if (sizeAlignmentMap.get(keys[i]) != op2.sizeAlignmentMap.get(op2keys[i])) { - return false; - } + for (int k : keys) { + if (!SystemUtilities.isEqual(sizeAlignmentMap.get(k), op2.sizeAlignmentMap.get(k))) { + return false; } } - catch (NoValueException ex) { - return false; - } return true; } @@ -922,14 +812,8 @@ public class DataOrganizationImpl implements DataOrganization { hash = 79 * hash + pointerSize; hash = 79 * hash + shortSize; hash = 79 * hash + wideCharSize; - int[] keys = sizeAlignmentMap.getKeys(); - try { - for (int key : keys) { - hash = 79 * hash + sizeAlignmentMap.get(key); - } - } - catch (NoValueException ex) { - hash = 0; + for (int k : sizeAlignmentMap.keySet()) { + hash = 79 * hash + sizeAlignmentMap.get(k); } return hash; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java index ef9f8ed813..285a4004f5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataType.java @@ -64,16 +64,20 @@ public interface DataType { public Settings getDefaultSettings(); /** - * Returns a new instance of this DataType with its universalID and SourceArchive identity retained. - * Note: for built-in DataType's, clone and copy should have the same affect. + * Returns an instance of this DataType with its universalID and SourceArchive identity retained. + * The current instanceof will be returned if this datatype's DataTypeManager matches + * the specified dtm. The recursion depth of a clone will stop on any datatype whose + * DataTypeManager matches the specified dtm and simply use the existing datatype instance. * @param dtm the data-type manager instance whose data-organization should apply. + * @return cloned instance which may be the same as this instance */ public DataType clone(DataTypeManager dtm); /** - * Returns a new instance of this DataType with a new identity. - * Note: for built-in DataType's, clone and copy should have the same affect. + * Returns a new instance (shallow copy) of this DataType with a new identity. + * Any reference to other datatypes will use {@link #clone(DataTypeManager)}. * @param dtm the data-type manager instance whose data-organization should apply. + * @return new instanceof of this datatype */ public DataType copy(DataTypeManager dtm); @@ -91,12 +95,14 @@ public interface DataType { /** * @param path set the categoryPath associated with this data type - * @throws DuplicateNameException + * @throws DuplicateNameException if an attempt to place this datatype into the + * specified category resulted in a name collision. This should not occur for non-DB + * DataType instances. */ public void setCategoryPath(CategoryPath path) throws DuplicateNameException; /** - * Returns the DataTypeManager that is associated with this dataType. + * @return the DataTypeManager that is associated with this dataType. * This association should not be used to indicate whether this DataType has been * resolved, but is intended to indicate whether the appropriate DataOrganization * is being used. @@ -110,13 +116,13 @@ public interface DataType { public String getDisplayName(); /** - * Return that name of the data type + * @return the name of this data type */ public String getName(); /** - * Returns the full category path name that includes this dataType's name. If - * the category is null, then this just returns the dataType's name. + * @return the full category path name that includes this dataType's name. If + * the category is null, then this just the dataType's name is returned. */ public String getPathName(); @@ -144,7 +150,7 @@ public interface DataType { /** * Get the mnemonic for this DataType. - * + * @param settings settings which may influence the result or null * @return the mnemonic for this DataType. */ public String getMnemonic(Settings settings); @@ -155,6 +161,17 @@ public interface DataType { */ public int getLength(); + /** + * Indicates is this datatype is defined with a zero length. + * This method should not be confused with {@link #isNotYetDefined()} + * which indicates that nothing but the name and basic type is known. + * NOTE: Support for zero-length datatypes is not yet fully supported, as a result + * they will generally return a non-zero length. + * @return true if type definition has a length of 0 even though it may report + * a length of 1, else false. + */ + public boolean isZeroLength(); + /** * Get a String briefly describing this DataType. * @@ -240,7 +257,7 @@ public interface DataType { * @param settings the Settings object * @param len the length of the data. * @param options options for how to format the default label prefix. - * @param offcutOffset + * @param offcutOffset offset into datatype * @return the default label prefix. */ public String getDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len, @@ -277,18 +294,26 @@ public interface DataType { * Notification that the given dataType's size has changed. DataTypes may * need to make internal changes in response. *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param dt the dataType that has changed. */ public void dataTypeSizeChanged(DataType dt); + /** + * Notification that the given dataType's alignment has changed. DataTypes may + * need to make internal changes in response. + *
    + * TODO: This method is reserved for internal DB use. + *
    + * @param dt the dataType that has changed. + */ + public void dataTypeAlignmentChanged(DataType dt); + /** * Informs this dataType that the given dataType has been deleted. *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param dt the dataType that has been deleted. */ @@ -297,8 +322,7 @@ public interface DataType { /** * Informs this data type that the given oldDT has been replaced with newDT *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param oldDt old data type * @param newDt new data type @@ -308,8 +332,7 @@ public interface DataType { /** * Set the default settings for this data type. *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param settings the settings to be used as this dataTypes default settings. */ @@ -318,8 +341,7 @@ public interface DataType { /** * Inform this data type that it has the given parent *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param dt parent data type */ @@ -328,8 +350,7 @@ public interface DataType { /** * Remove a parent data type *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param dt parent data type */ @@ -338,8 +359,7 @@ public interface DataType { /** * Informs this data type that its name has changed from the indicated old name. *
    - * TODO: This method is reserved for internal DB use and should be removed - * from the public DataType interface!! + * TODO: This method is reserved for internal DB use. *
    * @param dt the data type whose name changed * @param oldName the data type's old name @@ -362,6 +382,8 @@ public interface DataType { * For example byte[] depends on byte. If byte were deleted, then byte[] would * also be deleted. * @param dt the dataType to test that this dataType depends on. + * @return true if the existence of this datatype relies on the existence + * of the specified datatype dt. */ public boolean dependsOn(DataType dt); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeComponentImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeComponentImpl.java index 464511a870..6dcbd43876 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeComponentImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeComponentImpl.java @@ -107,7 +107,7 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali @Override public int getOffset() { if (isFlexibleArrayComponent) { - if (parent.isNotYetDefined()) { + if (parent.isZeroLength()) { // some structures have only a flexible array defined return 0; } @@ -179,7 +179,7 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali if (parent == null) { return; // Bad situation } - for (DataTypeComponent comp : parent.getComponents()) { + for (DataTypeComponent comp : parent.getDefinedComponents()) { if (comp != this && name.equals(comp.getFieldName())) { throw new DuplicateNameException("Duplicate field name: " + name); } @@ -328,7 +328,7 @@ public class DataTypeComponentImpl implements InternalDataTypeComponent, Seriali DataType otherDt = dtc.getDataType(); DataType myParent = getParent(); boolean aligned = - (myParent instanceof Composite) ? ((Composite) myParent).isInternallyAligned() : false; + (myParent instanceof Composite) ? ((Composite) myParent).isPackingEnabled() : false; // Components don't need to have matching offset when they are aligned // NOTE: use getOffset() method since returned values will differ from // stored values for flexible array component diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeImpl.java index e7dd5aeea4..57116ad57e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeImpl.java @@ -15,8 +15,9 @@ */ package ghidra.program.model.data; -import java.util.ArrayList; -import java.util.Iterator; +import java.lang.ref.WeakReference; +import java.util.*; +import java.util.function.Consumer; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -31,7 +32,7 @@ public abstract class DataTypeImpl extends AbstractDataType implements ChangeLis private final static SettingsDefinition[] EMPTY_DEFINITIONS = new SettingsDefinition[0]; protected Settings defaultSettings; - private ArrayList parentList; + private List> parentList; private UniversalID universalID; private SourceArchive sourceArchive; private long lastChangeTime; @@ -102,59 +103,78 @@ public abstract class DataTypeImpl extends AbstractDataType implements ChangeLis if (length < 0) { return 1; } - return getDataOrganization().getAlignment(this, length); + return getDataOrganization().getAlignment(this); } @Override public void addParent(DataType dt) { - parentList.add(dt); + parentList.add(new WeakReference<>(dt)); } @Override public void removeParent(DataType dt) { - parentList.remove(dt); + Iterator> iterator = parentList.iterator(); + while (iterator.hasNext()) { + WeakReference ref = iterator.next(); + DataType dataType = ref.get(); + if (dataType == null) { + iterator.remove(); + } + else if (dt == dataType) { + iterator.remove(); + break; + } + } } @Override public DataType[] getParents() { - DataType[] dts = new DataType[parentList.size()]; - return parentList.toArray(dts); - + List parents = new ArrayList<>(); + Iterator> iterator = parentList.iterator(); + while (iterator.hasNext()) { + WeakReference ref = iterator.next(); + DataType dataType = ref.get(); + if (dataType == null) { + iterator.remove(); + } + else { + parents.add(dataType); + } + } + DataType[] array = new DataType[parents.size()]; + return parents.toArray(array); } /** - * Notify any parent data types that my size has changed. + * Notify all parents that the size of this datatype has changed or + * other significant change that may affect a parent containing this + * datatype. */ protected void notifySizeChanged() { - Iterator it = parentList.iterator(); - while (it.hasNext()) { - DataType dt = it.next(); - dt.dataTypeSizeChanged(this); - } + notifyParents(dt -> dt.dataTypeSizeChanged(this)); } /** - * Notify any parents that my name has changed. + * Notify all parents that this datatype's alignment has changed + */ + protected void notifyAlignmentChanged() { + notifyParents(dt -> dt.dataTypeAlignmentChanged(this)); + } + + /** + * Notify all parents that this datatype's name has changed * * @param oldName */ protected void notifyNameChanged(String oldName) { - Iterator it = parentList.iterator(); - while (it.hasNext()) { - DataType dt = it.next(); - dt.dataTypeNameChanged(this, oldName); - } + notifyParents(dt -> dt.dataTypeNameChanged(this, oldName)); } /** - * Notify any parents that I am deleted. + * Notify all parents that this datatype has been deleted */ protected void notifyDeleted() { - Iterator it = parentList.iterator(); - while (it.hasNext()) { - DataType dt = it.next(); - dt.dataTypeDeleted(this); - } + notifyParents(dt -> dt.dataTypeDeleted(this)); } /** @@ -162,10 +182,20 @@ public abstract class DataTypeImpl extends AbstractDataType implements ChangeLis * @param replacement replacement data type */ protected void notifyReplaced(DataType replacement) { - Iterator it = parentList.iterator(); - while (it.hasNext()) { - DataType dt = it.next(); - dt.dataTypeReplaced(this, replacement); + notifyParents(dt -> dt.dataTypeReplaced(this, replacement)); + } + + protected final void notifyParents(Consumer consumer) { + Iterator> iterator = parentList.iterator(); + while (iterator.hasNext()) { + WeakReference ref = iterator.next(); + DataType dataType = ref.get(); + if (dataType == null) { + iterator.remove(); + } + else { + consumer.accept(dataType); + } } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeManager.java index d03c5c938f..b585844da4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeManager.java @@ -249,8 +249,10 @@ public interface DataTypeManager { /** * Notification when data type is changed. * @param dataType data type that is changed + * @param isAutoChange true if change was an automatic change in response to + * another datatype's change (e.g., size, alignment). */ - public void dataTypeChanged(DataType dataType); + public void dataTypeChanged(DataType dataType, boolean isAutoChange); /** * Add a listener that is notified when the dataTypeManger changes. diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/EnumDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/EnumDataType.java index 1e336b6f9a..4bcbe8e474 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/EnumDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/EnumDataType.java @@ -383,37 +383,12 @@ public class EnumDataType extends GenericDataType implements Enum { valueMap = new HashMap<>(); setLength(enumm.getLength()); String[] names = enumm.getNames(); - for (int i = 0; i < names.length; i++) { - add(names[i], enumm.getValue(names[i])); + for (String name2 : names) { + add(name2, enumm.getValue(name2)); } stateChanged(null); } - @Override - public void dataTypeSizeChanged(DataType dt) { - // not applicable - } - - @Override - public void dataTypeDeleted(DataType dt) { - // not applicable - } - - @Override - public void dataTypeNameChanged(DataType dt, String oldName) { - // not applicable - } - - @Override - public void dataTypeReplaced(DataType oldDt, DataType newDt) { - // not applicable - } - - @Override - public boolean dependsOn(DataType dt) { - return false; - } - @Override public String getDefaultLabelPrefix() { return name == null ? null : name.toUpperCase(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/GenericDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/GenericDataType.java index 421a6ce21c..f751925721 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/GenericDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/GenericDataType.java @@ -24,8 +24,6 @@ import ghidra.util.exception.DuplicateNameException; */ public abstract class GenericDataType extends DataTypeImpl { - protected boolean packed = false; - protected GenericDataType(CategoryPath path, String name, DataTypeManager dataMgr) { super(path, name, dataMgr); if (!DataUtilities.isValidDataTypeName(name)) { @@ -72,8 +70,9 @@ public abstract class GenericDataType extends DataTypeImpl { } private void doSetCategoryPath(CategoryPath path) { - if (path == null) + if (path == null) { path = CategoryPath.ROOT; + } categoryPath = path; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PackingType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PackingType.java new file mode 100644 index 0000000000..d9d618591d --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PackingType.java @@ -0,0 +1,42 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.model.data; + +/** + * PackingType specifies the pack setting which applies to a composite data type. + * This can be DISABLED, DEFAULT, EXPLICIT. + */ +public enum PackingType { + /** + * DISABLED - indicates that automatic component placement should not be performed, with + * components placed at specified offsets and undefined components used to + * reflects padding/unused bytes. This mode is commonly used when reverse-engineering a + * composite since a complete and accurate definition may not be known. + */ + DISABLED, + /** + * DEFAULT - indicates that components should be placed automatically based upon + * their alignment. This is intended to reflect the default behavior of a compiler + * when a complete definition of a composite is known as well as the alignment of each + * component. + */ + DEFAULT, + /** + * EXPLICIT - indicates an explicit pack value has been specified and that components + * should be placed automatically based upon their alignment, not to exceed the pack value. + */ + EXPLICIT; +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ReadOnlyDataTypeComponent.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ReadOnlyDataTypeComponent.java index ad0e66a975..215a1e2d30 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ReadOnlyDataTypeComponent.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ReadOnlyDataTypeComponent.java @@ -248,7 +248,7 @@ public class ReadOnlyDataTypeComponent implements DataTypeComponent, Serializabl int otherLength = dtc.getLength(); DataType myParent = getParent(); boolean aligned = - (myParent instanceof Composite) ? ((Composite) myParent).isInternallyAligned() : false; + (myParent instanceof Composite) ? ((Composite) myParent).isPackingEnabled() : false; // Components don't need to have matching offset when they are aligned, only matching ordinal. if ((!aligned && (offset != dtc.getOffset())) || // Components don't need to have matching length when they are aligned. Is this correct? diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Structure.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Structure.java index b96be093ea..e470429cf4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Structure.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Structure.java @@ -23,14 +23,14 @@ import java.util.Comparator; * NOTE: Structures containing only a flexible array will report a length of 1 which will result in * improper code unit sizing since we are unable to support a defined data of length 0. *

    - * NOTE: The use of zero-length bitfields within unaligned structures is discouraged since they have - * no real affect and are easily misplaced. Their use should be reserved for aligned/packed + * NOTE: The use of zero-length bitfields within non-packed structures is discouraged since they have + * no real affect and are easily misplaced. Their use should be reserved for packed * structures. */ public interface Structure extends Composite { @Override - Structure clone(DataTypeManager dtm); + public Structure clone(DataTypeManager dtm); /** * Returns the component of this structure with the indicated ordinal. If the specified ordinal @@ -39,12 +39,12 @@ public interface Structure extends Composite { * {@link #getFlexibleArrayComponent()} is preferred for obtaining this special trailing * component. * - * @param ordinal the component's ordinal (zero based). + * @param ordinal the ordinal of the component requested. * @return the data type component. - * @throws ArrayIndexOutOfBoundsException if the ordinal is out of bounds + * @throws IndexOutOfBoundsException if the ordinal is out of bounds */ @Override - public abstract DataTypeComponent getComponent(int ordinal); + public abstract DataTypeComponent getComponent(int ordinal) throws IndexOutOfBoundsException; /** * Gets the immediate child component that contains the byte at the given offset. If the @@ -68,23 +68,23 @@ public interface Structure extends Composite { public abstract DataTypeComponent getDataTypeAt(int offset); /** - * Inserts a new bitfield at the specified ordinal position in this structure. Within aligned + * Inserts a new bitfield at the specified ordinal position in this structure. Within packed * structures the specified byteWidth and bitOffset will be ignored since packing will occur at * the specified ordinal position. The resulting component length and bitfield details will * reflect the use of minimal storage sizing. *

    - * For unaligned structures, a component shift will only occur if the bitfield placement + * For structures with packing disabled, a component shift will only occur if the bitfield placement * conflicts with another component. If no conflict occurs, the bitfield will be placed at the * specified location consuming any DEFAULT components as needed. When a conflict does occur a * shift will be performed at the ordinal position based upon the specified byteWidth. When * located onto existing bitfields they will be packed together provided they do not conflict, * otherwise the conflict rule above applies. *

    - * Supported aligned packing starts with bit-0 (lsb) of the first byte for little-endian, and + * Supported packing starts with bit-0 (lsb) of the first byte for little-endian, and * with bit-7 (msb) of the first byte for big-endian. This is the default behavior for most * compilers. Insertion behavior may not work as expected if packing rules differ from this. * - * @param ordinal the ordinal where the new datatype is to be inserted. + * @param ordinal the ordinal of the component to be inserted. * @param byteWidth the storage allocation unit width which contains the bitfield. Must be large * enough to contain the "effective bit size" and corresponding bitOffset. The actual * component size used will be recomputed during insertion. @@ -99,22 +99,22 @@ public interface Structure extends Composite { * @return the bitfield component created whose associated data type will be BitFieldDataType. * @throws InvalidDataTypeException if the specified baseDataType is not a valid base type for * bitfields. - * @throws ArrayIndexOutOfBoundsException if ordinal is less than 0 or greater than the current + * @throws IndexOutOfBoundsException if ordinal is less than 0 or greater than the current * number of components. */ public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset, DataType baseDataType, int bitSize, String componentName, String comment) - throws InvalidDataTypeException, ArrayIndexOutOfBoundsException; + throws InvalidDataTypeException, IndexOutOfBoundsException; /** * Inserts a new bitfield at the specified location in this composite. This method is intended - * to be used with unaligned structures where the bitfield will be precisely placed. Within an - * aligned structure the specified byteOffset, byteWidth and bitOffset will be used to identify + * to be used with structures with packing disabled where the bitfield will be precisely placed. Within an + * packed structure the specified byteOffset, byteWidth and bitOffset will be used to identify * the appropriate ordinal but may not be preserved. The component length will be computed based * upon the specified parameters and will be reduced from byteWidth to its minimal size for the * new component. *

    - * For unaligned mode, a component shift will only occur if the bitfield placement conflicts + * When packing disabled, a component shift will only occur if the bitfield placement conflicts * with another component. If no conflict occurs, the bitfield will be placed at the specified * location consuming any DEFAULT components as needed. When a conflict does occur a shift will * be performed at the point of conflict based upon the specified byteWidth. When located onto @@ -125,8 +125,8 @@ public interface Structure extends Composite { * Insertion behavior may not work as expected if packing rules differ from this. *

    * - * Zero length bitfields may be inserted although they have no real affect for unaligned - * structures. Only the resulting byte offset within the structure is of significance in + * Zero length bitfields may be inserted although they have no real affect when packing disabled. + * Only the resulting byte offset within the structure is of significance in * determining its ordinal placement. *

    * @@ -200,67 +200,69 @@ public interface Structure extends Composite { /** * Remove all components from this structure (including flex-array), effectively setting the - * length to zero. + * length to zero. Packing and minimum alignment settings are unaffected. */ public void deleteAll(); /** - * Clears the defined component at the given component index. Clearing a component causes a - * defined component to be replaced with a number of undefined dataTypes to offset the removal - * of the defined dataType. + * Clears the defined component at the given component ordinal. Clearing a component within + * a non-packed structure causes a defined component to be replaced with a number of undefined + * dataTypes to offset the removal of the defined dataType. In the case of a packed + * structure the component is deleted without backfill. * - * @param index the index of the component to clear. - * @throws ArrayIndexOutOfBoundsException if component ordinal is out of bounds + * @param ordinal the ordinal of the component to clear. + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ - public void clearComponent(int index) throws ArrayIndexOutOfBoundsException; + public void clearComponent(int ordinal) throws IndexOutOfBoundsException; /** - * Replaces the component at the given component index with a new component of the indicated + * Replaces the component at the given component ordinal with a new component of the indicated * data type. * - * @param index the index where the datatype is to be replaced. + * @param ordinal the ordinal of the component to be replaced. * @param dataType the datatype to insert. * @param length the length of the dataType to insert. For fixed length types a length <= 0 * will use the length of the resolved dataType. - * @return the new componentDataType at the index. + * @return the new component * @throws IllegalArgumentException if the specified data type is not allowed to replace a * component in this composite data type or an invalid length is specified. For * example, suppose dt1 contains dt2. Therefore it is not valid to replace a dt2 * component with dt1 since this would cause a cyclic dependency. In addition, any * attempt to replace an existing bit-field component or specify a * {@link BitFieldDataType} will produce this error. - * @throws ArrayIndexOutOfBoundsException if component index is out of bounds + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ - public DataTypeComponent replace(int index, DataType dataType, int length) - throws ArrayIndexOutOfBoundsException, IllegalArgumentException; + public DataTypeComponent replace(int ordinal, DataType dataType, int length) + throws IndexOutOfBoundsException, IllegalArgumentException; /** - * Replaces the component at the given component index with a new component of the indicated + * Replaces the component at the given component ordinal with a new component of the indicated * data type. * - * @param index the index where the datatype is to be replaced. + * @param ordinal the ordinal of the component to be replaced. * @param dataType the datatype to insert. * @param length the length to associate with the dataType. For fixed length types a length * <= 0 will use the length of the resolved dataType. * @param name the field name to associate with this component. * @param comment the comment to associate with this component. - * @return the new componentDataType at the index. + * @return the new component. * @throws IllegalArgumentException if the specified data type is not allowed to replace a * component in this composite data type or an invalid length is specified. For * example, suppose dt1 contains dt2. Therefore it is not valid to replace a dt2 * component with dt1 since this would cause a cyclic dependency. In addition, any * attempt to replace an existing bit-field component or specify a * {@link BitFieldDataType} will produce this error. - * @throws ArrayIndexOutOfBoundsException if component index is out of bounds + * @throws IndexOutOfBoundsException if component ordinal is out of bounds */ - public DataTypeComponent replace(int index, DataType dataType, int length, String name, - String comment) throws ArrayIndexOutOfBoundsException, IllegalArgumentException; + public DataTypeComponent replace(int ordinal, DataType dataType, int length, String name, + String comment) throws IndexOutOfBoundsException, IllegalArgumentException; /** * Replaces the component at the specified byte offset with a new component of the indicated * data type. If the offset corresponds to a bit-field, all bit-fields at that offset will be * removed and replaced by the specified component. Keep in mind bit-field or any component - * removal must clear sufficient space for an unaligned structure to complete the replacement. + * removal must clear sufficient space in a structure with packing disabled to complete + * the replacement. * * @param offset the byte offset into the structure where the datatype is to be replaced. * @param dataType the datatype to insert. @@ -268,7 +270,7 @@ public interface Structure extends Composite { * <= 0 will use the length of the resolved dataType. * @param name the field name to associate with this component. * @param comment the comment to associate with this component. - * @return the new componentDataType at the index. + * @return the new component. * @throws IllegalArgumentException if the specified data type is not allowed to replace a * component in this composite data type or an invalid length is specified. For * example, suppose dt1 contains dt2. Therefore it is not valid to replace a dt2 @@ -288,6 +290,12 @@ public interface Structure extends Composite { /** * Get the optional trailing flexible array component associated with this structure. + *

    + * NOTE: The trailing flexable array may be assigned an incorrect offset + * when packing is enabled and the minimum alignment is specified. In such cases, + * the flex array may be less than the overall structure length. Currently, it is + * assumed the trailing flex array will have an offset equal to the overall + * structure length. * * @return optional trailing flexible array component associated with this structure or null if * not present. @@ -314,25 +322,14 @@ public interface Structure extends Composite { public void clearFlexibleArrayComponent(); /** - * Increases the size of the structure by the given amount by adding undefined datatypes at the - * end of the structure. + * Increases the size of the structure by the given amount by adding undefined filler at the + * end of the structure. NOTE: This method only has an affect on structures with packing disabled. * * @param amount the amount by which to grow the structure. * @throws IllegalArgumentException if amount < 1 */ public void growStructure(int amount); - /** - * Sets the current packing value (usually a power of 2). A value of NOT_PACKING should be - * passed if this isn't a packed data type. Otherwise this value indicates a maximum alignment - * for any component within this data type. Calling this method will cause the data type to - * become an internally aligned data type. (Same as {@link Composite#setPackingValue(int)}) - * - * @param maxAlignment the new packing value or 0 for NOT_PACKING. A negative value will be - * treated the same as 0. - */ - public void pack(int maxAlignment); - /** * BitOffsetComparator provides ability to compare an normalized bit offset (see * {@link #getNormalizedBitfieldOffset(int, int, int, int, boolean)}) with a @@ -365,6 +362,9 @@ public interface Structure extends Composite { */ public static class BitOffsetComparator implements Comparator { + public static final Comparator INSTANCE_LE = new BitOffsetComparator(false); + public static final Comparator INSTANCE_BE = new BitOffsetComparator(true); + private boolean bigEndian; public BitOffsetComparator(boolean bigEndian) { @@ -439,47 +439,4 @@ public interface Structure extends Composite { } - /** - * OffsetComparator provides ability to compare an Integer offset with a - * DataTypeComponent object. The offset will be consider equal (0) if the component contains the - * offset. - */ - public static class OffsetComparator implements Comparator { - - @Override - public int compare(Object o1, Object o2) { - if (o1 instanceof Integer) { - return -compare(o2, o1); - } - DataTypeComponent dtc = (DataTypeComponent) o1; - int offset = ((Integer) o2).intValue(); - if (offset < dtc.getOffset()) { - return 1; - } - else if (offset > dtc.getEndOffset()) { - return -1; - } - return 0; - } - - } - - /** - * OrdinalComparator provides ability to compare an Integer ordinal with a - * DataTypeComponent object. The offset will be consider equal (0) if the component corresponds - * to the specified ordinal. - */ - public static class OrdinalComparator implements Comparator { - - @Override - public int compare(Object o1, Object o2) { - if (o1 instanceof Integer) { - return -compare(o2, o1); - } - DataTypeComponent dtc = (DataTypeComponent) o1; - int ordinal = ((Integer) o2).intValue(); - return dtc.getOrdinal() - ordinal; - } - - } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java index 3ee3002c1a..4433e44031 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java @@ -25,19 +25,18 @@ import ghidra.util.UniversalID; import ghidra.util.exception.AssertException; /** - * Basic implementation of the structure data type + * Basic implementation of the structure data type. + * NOTE: Implementation is not thread safe when being modified. */ -public class StructureDataType extends CompositeDataTypeImpl implements Structure { - private final static long serialVersionUID = 1; - private static Comparator ordinalComparator = new OrdinalComparator(); - protected static Comparator offsetComparator = new OffsetComparator(); - protected static Comparator bitOffsetComparatorLE = new BitOffsetComparator(false); - protected static Comparator bitOffsetComparatorBE = new BitOffsetComparator(true); +public class StructureDataType extends CompositeDataTypeImpl implements StructureInternal { + protected int structLength; + private int structAlignment; + protected int numComponents; // excludes optional flexible array component protected List components; + private DataTypeComponentImpl flexibleArrayComponent; - private int alignment = -1; /** * Construct a new structure with the given name and length. The root category will be used. @@ -133,19 +132,23 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur @Override public boolean isNotYetDefined() { - return structLength == 0 && flexibleArrayComponent == null; + return structLength == 0 && flexibleArrayComponent == null && + isDefaultAligned() && !isPackingEnabled(); } @Override public int getAlignment() { - if (!isInternallyAligned()) { - return 1; // Unaligned + if (structAlignment > 0) { + return structAlignment; } - if (alignment <= 0) { + if (isPackingEnabled()) { StructurePackResult packResult = AlignedStructureInspector.packComponents(this); - alignment = packResult.alignment; + structAlignment = packResult.alignment; } - return alignment; + else { + structAlignment = getNonPackedAlignment(); + } + return structAlignment; } @Override @@ -153,7 +156,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (offset >= structLength || offset < 0) { return null; } - int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator); + int index = Collections.binarySearch(components, Integer.valueOf(offset), + OffsetComparator.INSTANCE); if (index >= 0) { DataTypeComponent dtc = components.get(index); if (dtc.isBitFieldComponent()) { @@ -162,7 +166,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } return dtc; } - else if (isInternallyAligned()) { + else if (isPackingEnabled()) { return null; } index = -index - 1; @@ -186,10 +190,15 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur return dtc; } + @Override + public boolean isZeroLength() { + return structLength == 0; + } + @Override public int getLength() { if (structLength == 0) { - return 1; // lie about our length if not yet defined + return 1; // 0-length datatype not supported } return structLength; } @@ -197,31 +206,32 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur @Override public void delete(int ordinal) { if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } int idx; - if (isInternallyAligned()) { + if (isPackingEnabled()) { idx = ordinal; } else { - idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator); + idx = Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); } if (idx >= 0) { doDelete(idx); - adjustInternalAlignment(); } else { - // assume unaligned removal of DEFAULT + // assume non-packed removal of DEFAULT idx = -idx - 1; shiftOffsets(idx, -1, -1); } + repack(false); notifySizeChanged(); } private void doDelete(int index) { DataTypeComponentImpl dtc = components.remove(index); dtc.getDataType().removeParent(this); - if (isInternallyAligned()) { + if (isPackingEnabled()) { return; } int shiftAmount = dtc.isBitFieldComponent() ? 0 : dtc.getLength(); @@ -229,40 +239,79 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } @Override - public void delete(int[] ordinals) { + public void delete(Set ordinals) { - for (int ordinal : ordinals) { - if (ordinal < 0 || ordinal >= numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + if (ordinals.isEmpty()) { + return; + } + + boolean bitFieldRemoved = false; + + TreeSet treeSet = null; + if (!isPackingEnabled()) { + // treeSet only used to track undefined filler removal + treeSet = new TreeSet<>(ordinals); + } + + List newComponents = new ArrayList<>(); + int ordinalAdjustment = 0; + int offsetAdjustment = 0; + int lastDefinedOrdinal = -1; + for (DataTypeComponentImpl dtc : components) { + int ordinal = dtc.getOrdinal(); + if (treeSet != null && lastDefinedOrdinal < (ordinal - 1)) { + // Identify removed filler since last defined component + Set removedFillerSet = treeSet.subSet(lastDefinedOrdinal + 1, ordinal); + if (!removedFillerSet.isEmpty()) { + int undefinedRemoveCount = removedFillerSet.size(); + ordinalAdjustment -= undefinedRemoveCount; + offsetAdjustment -= undefinedRemoveCount; + } + } + if (ordinals.contains(ordinal)) { + // defined component removed + if (dtc.isBitFieldComponent()) { + // defer reconciling bitfield space to repack + bitFieldRemoved = true; + } + else { + offsetAdjustment -= dtc.getLength(); + } + --ordinalAdjustment; + lastDefinedOrdinal = ordinal; + } + else { + + if (ordinalAdjustment != 0) { + shiftOffset(dtc, ordinalAdjustment, offsetAdjustment); + } + newComponents.add(dtc); + lastDefinedOrdinal = ordinal; + } + } + if (treeSet != null) { + // Identify removed filler after last defined component + Set removedFillerSet = treeSet.subSet(lastDefinedOrdinal + 1, numComponents); + if (!removedFillerSet.isEmpty()) { + int undefinedRemoveCount = removedFillerSet.size(); + ordinalAdjustment -= undefinedRemoveCount; + offsetAdjustment -= undefinedRemoveCount; } } - // delete ordinals in reverse order so that they remain valid - // during individual deletes - int[] sortedOrdinals = ordinals.clone(); - Arrays.sort(sortedOrdinals); + components = newComponents; + numComponents += ordinalAdjustment; - for (int i = sortedOrdinals.length - 1; i >= 0; i--) { - int ordinal = sortedOrdinals[i]; - int idx; - if (isInternallyAligned()) { - idx = ordinal; - } - else { - idx = Collections.binarySearch(components, Integer.valueOf(ordinal), - ordinalComparator); - } - if (idx >= 0) { - doDelete(idx); - } - else { - // assume unaligned removal of DEFAULT - idx = -idx - 1; - shiftOffsets(idx, -1, -1); - } + if (isPackingEnabled()) { + repack(true); + } + else { + structLength += offsetAdjustment; + if (bitFieldRemoved) { + repack(false); + } + notifySizeChanged(); } - adjustInternalAlignment(); - notifySizeChanged(); } private void shiftOffsets(int index, int deltaOrdinal, int deltaOffset) { @@ -285,13 +334,14 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur return flexibleArrayComponent; } if (index < 0 || index >= numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + throw new IndexOutOfBoundsException(index); } - int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator); + int idx = Collections.binarySearch(components, Integer.valueOf(index), + OrdinalComparator.INSTANCE); if (idx >= 0) { return components.get(idx); } - // assume unaligned DEFAULT + // assume non-packed DEFAULT int offset = 0; idx = -idx - 1; if (idx == 0) { @@ -315,6 +365,24 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur return components.size(); } + @Override + protected int getPreferredComponentLength(DataType dataType, int length) { + if (isPackingEnabled() && !(dataType instanceof Dynamic)) { + length = -1; + } + 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); @@ -347,12 +415,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur dataType = dataType.clone(dataMgr); checkAncestry(dataType); - if ((offset > structLength) && !isInternallyAligned()) { + if ((offset > structLength) && !isPackingEnabled()) { numComponents = numComponents + (offset - structLength); structLength = offset; } - int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator); + int index = Collections.binarySearch(components, Integer.valueOf(offset), + OffsetComparator.INSTANCE); int additionalShift = 0; if (index >= 0) { @@ -371,7 +440,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } if (dataType == DataType.DEFAULT) { - // assume unaligned insert of DEFAULT + // assume non-packed insert of DEFAULT shiftOffsets(index, 1 + additionalShift, 1 + additionalShift); return new DataTypeComponentImpl(DataType.DEFAULT, this, 1, ordinal, offset); } @@ -383,7 +452,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur dataType.addParent(this); shiftOffsets(index, 1 + additionalShift, dtc.getLength() + additionalShift); components.add(index, dtc); - adjustInternalAlignment(); + repack(false); notifySizeChanged(); return dtc; } @@ -391,13 +460,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur @Override public DataTypeComponent add(DataType dataType, int length, String componentName, String comment) { - return doAdd(dataType, length, false, componentName, comment); + return doAdd(dataType, length, false, componentName, comment, true); } /** * Add a new component to the end of this structure. *

    - * NOTE: This method differs from inserting to the end the structure for the unaligned case in + * NOTE: This method differs from inserting to the end the structure for the non-packed case in * that this method will always grow the structure by the positive length specified while the * insert may limit its growth by the length of a smaller fixed-length dataType. * @@ -408,22 +477,30 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur * @param isFlexibleArray if true length is ignored and the trailing flexible array will be set * based upon the specified fixed-length dataType; * @param componentName component name - * @param comment componetn comment + * @param comment component comment + * @param packAndNotify if true perform repack and provide change notification * @return newly added component * @throws IllegalArgumentException if the specified data type is not allowed to be added to * this composite data type or an invalid length is specified. */ private DataTypeComponent doAdd(DataType dataType, int length, boolean isFlexibleArray, - String componentName, String comment) throws IllegalArgumentException { + 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()); + } checkAncestry(dataType); DataTypeComponentImpl dtc; if (dataType == DataType.DEFAULT) { - dtc = new DataTypeComponentImpl(DataType.DEFAULT, this, 1, numComponents, structLength); + // FIXME: verify - does not appear to modify structure + dtc = + new DataTypeComponentImpl(DataType.DEFAULT, this, 1, numComponents, structLength); } else { @@ -455,31 +532,36 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (!isFlexibleArray) { int structureGrowth = dtc.getLength(); - if (!isInternallyAligned() && length > 0) { + if (!isPackingEnabled() && length > 0) { structureGrowth = length; } numComponents++; structLength += structureGrowth; } - adjustInternalAlignment(); - notifySizeChanged(); + if (packAndNotify) { + repack(false); + notifySizeChanged(); + } return dtc; } @Override public void growStructure(int amount) { + if (isPackingEnabled()) { + return; + } numComponents += amount; structLength += amount; - adjustInternalAlignment(); + repack(false); notifySizeChanged(); } @Override public DataTypeComponent insert(int index, DataType dataType, int length, String componentName, - String comment) throws ArrayIndexOutOfBoundsException, IllegalArgumentException { + String comment) throws IndexOutOfBoundsException, IllegalArgumentException { if (index < 0 || index > numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + throw new IndexOutOfBoundsException(index); } if (index == numComponents) { return add(dataType, length, componentName, comment); @@ -490,13 +572,14 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur checkAncestry(dataType); int idx; - if (isInternallyAligned()) { + if (isPackingEnabled()) { idx = index; } else { // TODO: could improve insertion of bitfield which does not intersect // existing ordinal bitfield at the bit-level - idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator); + idx = Collections.binarySearch(components, Integer.valueOf(index), + OrdinalComparator.INSTANCE); if (idx > 0) { DataTypeComponentImpl existingDtc = components.get(idx); if (existingDtc.isBitFieldComponent()) { @@ -512,7 +595,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur idx = -idx - 1; } if (dataType == DataType.DEFAULT) { - // assume unaligned insert of DEFAULT + // assume non-packed insert of DEFAULT shiftOffsets(idx, 1, 1); return getComponent(index); } @@ -525,7 +608,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur dataType.addParent(this); shiftOffsets(idx, 1, dtc.getLength()); components.add(idx, dtc); - adjustInternalAlignment(); + repack(false); notifySizeChanged(); return dtc; } @@ -544,16 +627,16 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur @Override public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset, DataType baseDataType, int bitSize, String componentName, String comment) - throws InvalidDataTypeException, ArrayIndexOutOfBoundsException { + throws InvalidDataTypeException, IndexOutOfBoundsException { if (ordinal < 0 || ordinal > numComponents) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } BitFieldDataType.checkBaseDataType(baseDataType); baseDataType = baseDataType.clone(dataMgr); - if (!isInternallyAligned()) { + if (!isPackingEnabled()) { int offset = structLength; if (ordinal < numComponents) { offset = getComponent(ordinal).getOffset(); @@ -601,7 +684,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur effectiveBitSize, bitOffset, bigEndian); Comparator bitOffsetComparator = - bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE; + bigEndian ? BitOffsetComparator.INSTANCE_BE : BitOffsetComparator.INSTANCE_LE; int startIndex = Collections.binarySearch(components, Integer.valueOf(startBitOffset), bitOffsetComparator); if (startIndex < 0) { @@ -627,7 +710,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur ordinal = startIndex; } - if (isInternallyAligned()) { + if (isPackingEnabled()) { insertBitField(ordinal, 0, 0, baseDataType, effectiveBitSize, componentName, comment); } @@ -679,7 +762,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur bitfieldDt.addParent(this); // currently has no affect components.add(startIndex, dtc); - adjustUnalignedComponents(); + adjustNonPackedComponents(); notifySizeChanged(); return dtc; } @@ -689,7 +772,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur * normal components the specified ordinal will be returned, however for bit-fields the ordinal * of the first bit-field containing the specified offset will be returned. * - * @param ordinal component ordinal + * @param index component ordinal * @param offset offset within structure * @return index of first defined component containing specific offset. */ @@ -714,7 +797,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur * normal components the specified ordinal will be returned, however for bit-fields the ordinal * of the last bit-field containing the specified offset will be returned. * - * @param ordinal component ordinal + * @param index defined component index * @param offset offset within structure * @return index of last defined component containing specific offset. */ @@ -739,7 +822,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (offset >= structLength) { return; } - int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator); + int index = Collections.binarySearch(components, Integer.valueOf(offset), + OffsetComparator.INSTANCE); int offsetDelta = 0; int ordinalDelta = 0; @@ -760,8 +844,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur dtc = components.get(index); } } - - adjustInternalAlignment(); + repack(false); notifySizeChanged(); return; } @@ -772,17 +855,16 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (dataType == this) { return true; } - if (!(dataType instanceof Structure)) { + if (!(dataType instanceof StructureInternal)) { return false; } - Structure struct = (Structure) dataType; - if (isInternallyAligned() != struct.isInternallyAligned() || - isDefaultAligned() != struct.isDefaultAligned() || - isMachineAligned() != struct.isMachineAligned() || - getMinimumAlignment() != struct.getMinimumAlignment() || - getPackingValue() != struct.getPackingValue() || - (!isInternallyAligned() && (getLength() != struct.getLength()))) { + StructureInternal struct = (StructureInternal) dataType; + int otherLength = struct.isZeroLength() ? 0 : struct.getLength(); + if (packing != struct.getStoredPackingValue() || + minimumAlignment != struct.getStoredMinimumAlignment() || + isZeroLength() != struct.isZeroLength() || + (packing == NO_PACKING && structLength != otherLength)) { return false; } @@ -821,11 +903,12 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (dt instanceof BitFieldDataType) { return; // unsupported } - if (isInternallyAligned()) { - adjustInternalAlignment(); + if (isPackingEnabled()) { + repack(true); return; } - boolean didChange = false; + int oldLength = structLength; + boolean changed = false; int n = components.size(); for (int i = 0; i < n; i++) { DataTypeComponentImpl dtc = components.get(i); @@ -840,33 +923,35 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (length < dtcLen) { dtc.setLength(length); shiftOffsets(i + 1, dtcLen - length, 0); - didChange = true; + changed = true; } else if (length > dtcLen) { int consumed = consumeBytesAfter(i, length - dtcLen); if (consumed > 0) { shiftOffsets(i + 1, 0 - consumed, 0); - didChange = true; + changed = true; } } } } - if (didChange) { - adjustInternalAlignment(); - notifySizeChanged(); + if (changed) { + repack(false); + if (oldLength != structLength) { + notifySizeChanged(); + } } } @Override public void dataTypeAlignmentChanged(DataType dt) { - if (isInternallyAligned()) { - adjustInternalAlignment(); + if (isPackingEnabled()) { + repack(true); } } /** * - * @param index the index of the defined component that is consuming the bytes. + * @param definedComponentIndex the index of the defined component that is consuming the bytes. * @param numBytes the number of undefined bytes to consume * @return the number of bytes actually consumed */ @@ -900,7 +985,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur /** * Create copy of structure for target dtm (source archive information is discarded). *

    - * WARNING! copying unaligned structures which contain bitfields can produce invalid results when + * WARNING! copying non-packed structures which contain bitfields can produce invalid results when * switching endianess due to the differences in packing order. * * @param dtm target data type manager @@ -908,7 +993,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur */ @Override public DataType copy(DataTypeManager dtm) { - StructureDataType struct = new StructureDataType(categoryPath, getName(), getLength(), dtm); + StructureDataType struct = + new StructureDataType(categoryPath, getName(), structLength, dtm); struct.setDescription(getDescription()); struct.replaceWith(this); return struct; @@ -916,7 +1002,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur /** * Create cloned structure for target dtm preserving source archive information. WARNING! - * cloning unaligned structures which contain bitfields can produce invalid results when + * cloning non-packed structures which contain bitfields can produce invalid results when * switching endianess due to the differences in packing order. * * @param dtm target data type manager @@ -928,7 +1014,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur return this; } StructureDataType struct = - new StructureDataType(categoryPath, getName(), getLength(), getUniversalID(), + new StructureDataType(categoryPath, getName(), structLength, getUniversalID(), getSourceArchive(), getLastChangeTime(), getLastChangeTimeInSourceArchive(), dtm); struct.setDescription(getDescription()); struct.replaceWith(this); @@ -937,11 +1023,16 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } @Override - public void clearComponent(int index) { - if (index < 0 || index >= numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + public void clearComponent(int ordinal) { + if (isPackingEnabled()) { + delete(ordinal); + return; } - int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator); + if (ordinal < 0 || ordinal >= numComponents) { + throw new IndexOutOfBoundsException(ordinal); + } + int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); if (idx >= 0) { DataTypeComponent dtc = components.remove(idx); dtc.getDataType().removeParent(this); @@ -949,12 +1040,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (len > 1) { shiftOffsets(idx, len - 1, 0); } + repack(false); } - adjustInternalAlignment(); } /** - * Replaces the internal components of this structure with components of the given structure. + * Replaces the internal components of this structure with components of the given structure + * including packing and alignment settings. * * @param dataType the structure to get the component information from. * @throws IllegalArgumentException if any of the component data types are not allowed to @@ -964,22 +1056,26 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur */ @Override public void replaceWith(DataType dataType) { - if (!(dataType instanceof Structure)) { + if (!(dataType instanceof StructureInternal)) { throw new IllegalArgumentException(); } - Structure struct = (Structure) dataType; - - int oldLength = structLength; + StructureInternal struct = (StructureInternal) dataType; components.clear(); - structLength = 0; numComponents = 0; - flexibleArrayComponent = null; + structLength = 0; + structAlignment = -1; - setAlignment(struct); + if (flexibleArrayComponent != null) { + flexibleArrayComponent.getDataType().removeParent(this); + flexibleArrayComponent = null; + } - if (struct.isInternallyAligned()) { + this.packing = struct.getStoredPackingValue(); + this.minimumAlignment = struct.getStoredMinimumAlignment(); + + if (struct.isPackingEnabled()) { doReplaceWithAligned(struct); } else { @@ -988,28 +1084,29 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur DataTypeComponent flexComponent = struct.getFlexibleArrayComponent(); if (flexComponent != null) { - setFlexibleArrayComponent(flexComponent.getDataType(), flexComponent.getFieldName(), - flexComponent.getComment()); + doAdd(flexComponent.getDataType(), 0, true, flexComponent.getFieldName(), + flexComponent.getComment(), false); } - if (oldLength != structLength) { - notifySizeChanged(); - } + repack(false); + notifySizeChanged(); } +// TODO: Rename private void doReplaceWithAligned(Structure struct) { // assumes components is clear and that alignment characteristics have been set DataTypeComponent[] otherComponents = struct.getDefinedComponents(); for (DataTypeComponent dtc : otherComponents) { DataType dt = dtc.getDataType(); int length = (dt instanceof Dynamic) ? dtc.getLength() : -1; - add(dt, length, dtc.getFieldName(), dtc.getComment()); + doAdd(dt, length, false, dtc.getFieldName(), dtc.getComment(), false); } } +// TODO: Rename private void doReplaceWithUnaligned(Structure struct) throws IllegalArgumentException { // assumes components is clear and that alignment characteristics have been set. - if (struct.isNotYetDefined()) { + if (struct.isZeroLength()) { return; } @@ -1042,16 +1139,16 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur components.add(new DataTypeComponentImpl(dt, this, length, dtc.getOrdinal(), dtc.getOffset(), dtc.getFieldName(), dtc.getComment())); } - adjustComponents(); + repack(false); } @Override public void dataTypeDeleted(DataType dt) { - boolean didChange = false; + boolean changed = false; if (flexibleArrayComponent != null && flexibleArrayComponent.getDataType() == dt) { flexibleArrayComponent.getDataType().removeParent(this); flexibleArrayComponent = null; - didChange = true; + changed = true; } int n = components.size(); for (int i = n - 1; i >= 0; i--) { @@ -1063,14 +1160,15 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } if (removeBitFieldComponent || dtc.getDataType() == dt) { dt.removeParent(this); +// FIXME: Consider replacing with undefined type instead of removing (don't remove bitfield) components.remove(i); shiftOffsets(i, dtc.getLength() - 1, 0); - didChange = true; + --numComponents; // may be revised by repack + changed = true; } } - if (didChange) { - adjustInternalAlignment(); - notifySizeChanged(); + if (changed) { + repack(true); } } @@ -1126,7 +1224,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } } else if (comp.getDataType() == oldDt) { - if (replacementDt == DEFAULT && isInternallyAligned()) { + if (replacementDt == DEFAULT && isPackingEnabled()) { Msg.error(this, "Invalid replacement type " + newDt.getName() + ", removing component " + comp.getDataType().getName() + ": " + getPathName()); @@ -1147,38 +1245,47 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } if (changed) { - adjustInternalAlignment(); + repack(false); notifySizeChanged(); } } private void setComponentDataType(DataTypeComponentImpl comp, DataType newDt, int nextIndex) { + + int oldLen = comp.getLength(); + int len = newDt.getLength(); + if (len < 1) { + len = oldLen; + } + comp.getDataType().removeParent(this); comp.setDataType(newDt); newDt.addParent(this); - int len = newDt.getLength(); - int oldLen = comp.getLength(); - if (len > 0) { - if (len < oldLen) { + + if (isPackingEnabled()) { + comp.setLength(len); + return; + } + + if (len < oldLen) { + comp.setLength(len); + shiftOffsets(nextIndex, oldLen - len, 0); + } + else if (len > oldLen) { + int bytesAvailable = getNumUndefinedBytes(comp.getOrdinal() + 1); + int bytesNeeded = len - oldLen; + if (bytesNeeded <= bytesAvailable) { comp.setLength(len); - shiftOffsets(nextIndex, oldLen - len, 0); + shiftOffsets(nextIndex, -bytesNeeded, 0); } - else if (len > oldLen) { - int bytesAvailable = getNumUndefinedBytes(comp.getOrdinal() + 1); - int bytesNeeded = len - oldLen; - if (bytesNeeded <= bytesAvailable) { - comp.setLength(len); - shiftOffsets(nextIndex, -bytesNeeded, 0); - } - else if (comp.getOrdinal() == getLastDefinedComponentIndex()) { // we are the last defined component, grow structure - doGrowStructure(bytesNeeded - bytesAvailable); - comp.setLength(len); - shiftOffsets(nextIndex, -bytesNeeded, 0); - } - else { - comp.setLength(oldLen + bytesAvailable); - shiftOffsets(nextIndex, -bytesAvailable, 0); - } + else if (comp.getOrdinal() == getLastDefinedComponentIndex()) { // we are the last defined component, grow structure + doGrowStructure(bytesNeeded - bytesAvailable); + comp.setLength(len); + shiftOffsets(nextIndex, -bytesNeeded, 0); + } + else { + comp.setLength(oldLen + bytesAvailable); + shiftOffsets(nextIndex, -bytesAvailable, 0); } } } @@ -1199,9 +1306,9 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur @Override public DataTypeComponent replace(int index, DataType dataType, int length, String componentName, - String comment) throws ArrayIndexOutOfBoundsException, IllegalArgumentException { + String comment) throws IndexOutOfBoundsException, IllegalArgumentException { if (index < 0 || index >= numComponents) { - throw new ArrayIndexOutOfBoundsException(index); + throw new IndexOutOfBoundsException(index); } validateDataType(dataType); @@ -1223,7 +1330,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur DataTypeComponent replacement = replaceComponent(origDtc, dataType, length, componentName, comment); - adjustInternalAlignment(); + repack(false); + notifySizeChanged(); return replacement; } @@ -1239,8 +1347,11 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur throw new IllegalArgumentException("Offset cannot be negative."); } if (offset >= structLength) { + if (!isPackingEnabled() && offset < getLength()) { + return insertAtOffset(offset, dataType, length, componentName, comment); + } throw new IllegalArgumentException( - "Offset " + offset + " is beyond end of structure (" + structLength + ")."); + "Offset " + offset + " is beyond end of structure (" + getLength() + ")."); } validateDataType(dataType); @@ -1264,7 +1375,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur DataTypeComponent replacement = replaceComponent(origDtc, dataType, length, componentName, comment); - adjustInternalAlignment(); + repack(false); + notifySizeChanged(); return replacement; } @@ -1281,15 +1393,15 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur * component in this composite data type. For example, suppose dt1 contains dt2. * Therefore it is not valid to replace a dt2 component with dt1 since this would * cause a cyclic dependency. In addition, any attempt to replace an existing - * bit-field component or specify a {@link BitFieldDatatype} will produce this + * bit-field component or specify a {@link BitFieldDataType} will produce this * error. */ private DataTypeComponent replaceComponent(DataTypeComponentImpl origDtc, DataType dataType, int length, String componentName, String comment) { -// FIXME: Unsure how o support replace operation with bit-fields. Within unaligned structure +// FIXME: Unsure how o support replace operation with bit-fields. Within non-packed structure // the packing behavior for bit-fields prevents a one-for-one replacement and things may shift -// around which the unaligned structure tries to avoid. Insert and delete are less of a concern +// around which the non-packed structure tries to avoid. Insert and delete are less of a concern // since movement already can occur, although insert at offset may not retain the offset if it // interacts with bit-fields. @@ -1317,7 +1429,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } } int index = - Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator); + Collections.binarySearch(components, Integer.valueOf(ordinal), + OrdinalComparator.INSTANCE); if (index < 0) { index = -index - 1; } @@ -1352,7 +1465,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (index >= numComponents) { return 0; } - int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator); + int idx = Collections.binarySearch(components, Integer.valueOf(index), + OrdinalComparator.INSTANCE); DataTypeComponent dtc = null; if (idx < 0) { idx = -idx - 1; @@ -1366,10 +1480,6 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } - @Override - public void dataTypeNameChanged(DataType dt, String oldName) { - } - @Override public boolean dependsOn(DataType dt) { return false; @@ -1384,7 +1494,6 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur structLength = 0; numComponents = 0; flexibleArrayComponent = null; - adjustInternalAlignment(); notifySizeChanged(); } @@ -1394,59 +1503,39 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } @Override - public void realign() { - adjustInternalAlignment(); - } - - @Override - public void pack(int packingSize) { - setPackingValue(packingSize); - } - - /** - * Adjust the alignment, packing and padding of components within this structure based upon the - * current alignment and packing attributes for this structure. This method should be called to - * fix up the layout of the internal components of the structure after other code has changed - * the attributes of the structure.
    - * When switching between internally aligned and unaligned this method corrects the component - * ordinal numbering also. - * - * @return true if the structure was changed by this method. - */ - protected boolean adjustComponents() { + public boolean repack(boolean notify) { int oldLength = structLength; + int oldAlignment = getAlignment(); - boolean changed = false; - alignment = -1; - - if (!isInternallyAligned()) { - changed |= adjustUnalignedComponents(); - if (changed) { - if (oldLength != structLength) { - notifySizeChanged(); - } - } - return changed; + boolean changed; + if (!isPackingEnabled()) { + changed = adjustNonPackedComponents(); + } + else { + StructurePackResult packResult = + AlignedStructurePacker.packComponents(this, components); + changed = packResult.componentsChanged; + changed |= (structLength != packResult.structureLength) || + (structAlignment != packResult.alignment) || + (numComponents != packResult.numComponents); + structLength = packResult.structureLength; + structAlignment = packResult.alignment; + numComponents = packResult.numComponents; } - StructurePackResult packResult = AlignedStructurePacker.packComponents(this, components); - changed = packResult.componentsChanged; - - // Adjust the structure - changed |= updateComposite(packResult.numComponents, packResult.structureLength, - packResult.alignment); - - if (changed) { + if (changed && notify) { if (oldLength != structLength) { notifySizeChanged(); } - return true; + else if (oldAlignment != structAlignment) { + notifyAlignmentChanged(); + } } - return false; + return changed; } - private boolean adjustUnalignedComponents() { + private boolean adjustNonPackedComponents() { boolean changed = false; int componentCount = 0; int currentOffset = 0; @@ -1464,44 +1553,28 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur } componentCount++; } + int numUndefinedsAfter = structLength - currentOffset; componentCount += numUndefinedsAfter; - if (updateComposite(componentCount, structLength, 1)) { + if (numComponents != componentCount) { + numComponents = componentCount; + changed = true; + } + int alignment = getNonPackedAlignment(); + if (alignment != structAlignment) { + structAlignment = alignment; changed = true; } return changed; } - private boolean updateComposite(int currentNumComponents, int currentLength, - int currentAlignment) { - boolean compositeChanged = false; - if (numComponents != currentNumComponents) { - numComponents = currentNumComponents; - compositeChanged = true; - } - if (structLength != currentLength) { - structLength = currentLength; - compositeChanged = true; - } - if (alignment != currentAlignment) { - alignment = currentAlignment; - compositeChanged = true; - } - return compositeChanged; - } - private void doGrowStructure(int amount) { - if (!isInternallyAligned()) { + if (!isPackingEnabled()) { numComponents += amount; } structLength += amount; } - @Override - public void adjustInternalAlignment() { - adjustComponents(); - } - @Override public boolean hasFlexibleArrayComponent() { return flexibleArrayComponent != null; @@ -1525,7 +1598,10 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur throw new IllegalArgumentException( "Unsupported flexType: " + flexType.getDisplayName()); } - return doAdd(flexType, 0, true, name, comment); + DataTypeComponent dtc = doAdd(flexType, 0, true, name, comment, false); + repack(false); + notifySizeChanged(); + return dtc; } @Override @@ -1534,25 +1610,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur return; } flexibleArrayComponent = null; - adjustInternalAlignment(); + repack(false); notifySizeChanged(); } - @Override - protected void dumpComponents(StringBuilder buffer, String pad) { - super.dumpComponents(buffer, pad); - DataTypeComponent dtc = getFlexibleArrayComponent(); - if (dtc != null) { - DataType dataType = dtc.getDataType(); - buffer.append(pad + dataType.getDisplayName() + "[0]"); - buffer.append(pad + dtc.getLength()); - buffer.append(pad + dtc.getFieldName()); - String comment = dtc.getComment(); - if (comment == null) { - comment = ""; - } - buffer.append(pad + "\"" + comment + "\""); - buffer.append("\n"); - } - } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureInternal.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureInternal.java new file mode 100644 index 0000000000..73ac8176a3 --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureInternal.java @@ -0,0 +1,20 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.model.data; + +public interface StructureInternal extends Structure, CompositeInternal { + +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/TypedefDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/TypedefDataType.java index f20222b209..1f94fa83c5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/TypedefDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/TypedefDataType.java @@ -141,6 +141,11 @@ public class TypedefDataType extends GenericDataType implements TypeDef { return dataType.getDescription(); } + @Override + public boolean isZeroLength() { + return dataType.isZeroLength(); + } + @Override public int getLength() { return dataType.getLength(); @@ -182,6 +187,13 @@ public class TypedefDataType extends GenericDataType implements TypeDef { } } + @Override + public void dataTypeAlignmentChanged(DataType dt) { + if (dt == dataType) { + notifyAlignmentChanged(); + } + } + @Override public DataType getBaseDataType() { if (dataType instanceof TypeDef) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Union.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Union.java index 44acf0da71..8ede124ba1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Union.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Union.java @@ -24,9 +24,12 @@ package ghidra.program.model.data; */ public interface Union extends Composite { + @Override + public Union clone(DataTypeManager dtm); + /** * Inserts a new bitfield at the specified ordinal position in this union. - * For both aligned and unaligned unions the bitfield starts with bit-0 (lsb) of the first byte + * For all Unions, bitfield starts with bit-0 (lsb) of the first byte * for little-endian, and with bit-7 (msb) of the first byte for big-endian. This is the * default behavior for most compilers. Insertion behavior may not work as expected if * packing rules differ from this. @@ -40,10 +43,10 @@ public interface Union extends Composite { * be BitFieldDataType. * @throws InvalidDataTypeException if the specified baseDataType is * not a valid base type for bitfields. - * @throws ArrayIndexOutOfBoundsException if ordinal is less than 0 or greater than the + * @throws IndexOutOfBoundsException if ordinal is less than 0 or greater than the * current number of components. */ public DataTypeComponent insertBitField(int ordinal, DataType baseDataType, int bitSize, String componentName, String comment) - throws InvalidDataTypeException, ArrayIndexOutOfBoundsException; + throws InvalidDataTypeException, IndexOutOfBoundsException; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java index 298bcbd5c2..be7e7c4ff8 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionDataType.java @@ -15,8 +15,7 @@ */ package ghidra.program.model.data; -import java.util.ArrayList; -import java.util.Iterator; +import java.util.*; import ghidra.docking.settings.Settings; import ghidra.program.model.mem.MemBuffer; @@ -24,11 +23,15 @@ import ghidra.util.Msg; import ghidra.util.UniversalID; /** - * Basic implementation of the union data type + * Basic implementation of the union data type. + * NOTE: Implementation is not thread safe when being modified. */ -public class UnionDataType extends CompositeDataTypeImpl implements Union { - private ArrayList components; +public class UnionDataType extends CompositeDataTypeImpl implements UnionInternal { + private int unionLength; + private int unionAlignment; + + private List components; /** * Construct a new empty union with the given name within the @@ -96,7 +99,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { @Override public boolean isNotYetDefined() { - return components.size() == 0; + return unionLength == 0 && isDefaultAligned() && !isPackingEnabled(); } @Override @@ -124,17 +127,30 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { return components.size(); } + @Override + protected int getPreferredComponentLength(DataType dataType, int length) { + if (!(dataType instanceof Dynamic)) { + length = -1; + } + return super.getPreferredComponentLength(dataType, length); + } + @Override public DataTypeComponent add(DataType dataType, int length, String componentName, String comment) throws IllegalArgumentException { + + int oldAlignment = getAlignment(); + DataTypeComponent dtc = doAdd(dataType, length, componentName, comment); - adjustLength(true); + if (!repack(true) && isPackingEnabled() && oldAlignment != getAlignment()) { + notifyAlignmentChanged(); + } return dtc; } private int getBitFieldAllocation(BitFieldDataType bitfieldDt) { - BitFieldPacking bitFieldPacking = getBitFieldPacking(); + BitFieldPacking bitFieldPacking = getDataOrganization().getBitFieldPacking(); if (bitFieldPacking.useMSConvention()) { return bitfieldDt.getBaseTypeSize(); } @@ -144,10 +160,9 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { } int length = bitfieldDt.getBaseTypeSize(); - int packValue = getPackingValue(); - if (packValue != NOT_PACKING && length > packValue) { + if (packing > 0 && length > packing) { length = - DataOrganizationImpl.getLeastCommonMultiple(bitfieldDt.getStorageSize(), packValue); + DataOrganizationImpl.getLeastCommonMultiple(bitfieldDt.getStorageSize(), packing); } return length; } @@ -177,6 +192,8 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { String componentName, String comment) throws IllegalArgumentException { validateDataType(dataType); + int oldAlignment = getAlignment(); + dataType = adjustBitField(dataType); dataType = dataType.clone(dataMgr); @@ -190,7 +207,9 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { shiftOrdinals(ordinal, 1); components.add(ordinal, dtc); - adjustLength(true); + if (!repack(true) && isPackingEnabled() && oldAlignment != getAlignment()) { + notifyAlignmentChanged(); + } return dtc; } @@ -203,10 +222,10 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { @Override public DataTypeComponent insertBitField(int ordinal, DataType baseDataType, int bitSize, String componentName, String comment) - throws InvalidDataTypeException, ArrayIndexOutOfBoundsException { + throws InvalidDataTypeException, IndexOutOfBoundsException { if (ordinal < 0 || ordinal > components.size()) { - throw new ArrayIndexOutOfBoundsException(ordinal); + throw new IndexOutOfBoundsException(ordinal); } BitFieldDataType.checkBaseDataType(baseDataType); @@ -216,16 +235,21 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment); } + @Override + public boolean isZeroLength() { + return unionLength == 0; + } + @Override public int getLength() { if (unionLength == 0) { - return 1; + return 1; // 0-length datatype not supported } return unionLength; } @Override - public DataType clone(DataTypeManager dtm) { + public Union clone(DataTypeManager dtm) { if (dataMgr == dtm) { return this; } @@ -246,16 +270,54 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { @Override public void delete(int ordinal) { + + int oldAlignment = getAlignment(); + DataTypeComponent dtc = components.remove(ordinal); dtc.getDataType().removeParent(this); shiftOrdinals(ordinal, -1); - adjustLength(true); + + if (!repack(true) && isPackingEnabled() && oldAlignment != getAlignment()) { + notifyAlignmentChanged(); + } } @Override - public void delete(int[] ordinals) { - for (int ordinal : ordinals) { - delete(ordinal); + public void delete(Set ordinals) { + + if (ordinals.isEmpty()) { + return; + } + + int oldAlignment = getAlignment(); + + List newComponents = new ArrayList<>(); + int newLength = 0; + int ordinalAdjustment = 0; + for (DataTypeComponentImpl dtc : components) { + int ordinal = dtc.getOrdinal(); + if (ordinals.contains(ordinal)) { + // component removed + --ordinalAdjustment; + } + else { + if (ordinalAdjustment != 0) { + dtc.setOrdinal(dtc.getOrdinal() + ordinalAdjustment); + } + newComponents.add(dtc); + newLength = Math.max(newLength, dtc.getLength()); + } + } + components = newComponents; + + if (isPackingEnabled()) { + if (!repack(true) && oldAlignment != getAlignment()) { + notifyAlignmentChanged(); + } + } + else { + unionLength = newLength; + notifySizeChanged(); } } @@ -270,8 +332,8 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { DataType baseDataType = bitfieldDt.getBaseDataType(); baseDataType = baseDataType.clone(dataMgr); - // Both aligned and unaligned bitfields use same adjustment - // unaligned must force bitfield placement at byte offset 0 + // Both aligned and non-packed bitfields use same adjustment + // non-packed must force bitfield placement at byte offset 0 int bitSize = bitfieldDt.getDeclaredBitSize(); int effectiveBitSize = BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength()); @@ -303,22 +365,55 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { return bitfieldDt; } - private void adjustLength(boolean notify) { + @Override + public int getAlignment() { + if (unionAlignment > 0) { + return unionAlignment; + } + if (isPackingEnabled()) { + unionAlignment = CompositeAlignmentHelper.getAlignment(getDataOrganization(), this); + } + else { + unionAlignment = getNonPackedAlignment(); + } + return unionAlignment; + } + + @Override + public boolean repack(boolean notify) { + int oldLength = unionLength; + int oldAlignment = getAlignment(); + unionLength = 0; for (DataTypeComponent dtc : components) { - + // TODO: compute alignment in this loop int length = dtc.getLength(); - if (isInternallyAligned() && dtc.isBitFieldComponent()) { + if (isPackingEnabled() && dtc.isBitFieldComponent()) { // revise length to reflect compiler bitfield allocation rules length = getBitFieldAllocation((BitFieldDataType) dtc.getDataType()); } - unionLength = Math.max(length, unionLength); } - if (notify && oldLength != unionLength) { - notifySizeChanged(); + + unionAlignment = -1; // force recompute of unionAlignment + getAlignment(); + + if (isPackingEnabled()) { + unionLength = DataOrganizationImpl.getAlignedOffset(unionAlignment, unionLength); } + + boolean changed = (oldLength != unionLength) || (oldAlignment != unionAlignment); + + if (changed && notify) { + if (oldLength != unionLength) { + notifySizeChanged(); + } + else if (oldAlignment != unionAlignment) { + notifyAlignmentChanged(); + } + } + return changed; } @Override @@ -330,13 +425,10 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { return false; } - if (dt instanceof Union) { - Union union = (Union) dt; - if (isInternallyAligned() != union.isInternallyAligned() || - isDefaultAligned() != union.isDefaultAligned() || - isMachineAligned() != union.isMachineAligned() || - getMinimumAlignment() != union.getMinimumAlignment() || - getPackingValue() != union.getPackingValue()) { + if (dt instanceof UnionInternal) { + UnionInternal union = (UnionInternal) dt; + if (packing != union.getStoredPackingValue() || + minimumAlignment != union.getStoredMinimumAlignment()) { // rely on component match instead of checking length // since dynamic component sizes could affect length return false; @@ -365,8 +457,23 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { @Override public void dataTypeAlignmentChanged(DataType dt) { - if (isInternallyAligned()) { - adjustInternalAlignment(); + if (!isPackingEnabled()) { + return; + } + if (dt instanceof BitFieldDataType) { + return; // unsupported + } + boolean hasPossibleChange = false; + for (DataTypeComponentImpl dtc : components) { + if (dtc.getDataType() == dt) { + hasPossibleChange = true; + break; + } + } + if (hasPossibleChange && !repack(true) && isPackingEnabled()) { + // NOTE: Must assume alignment change since we are unable to determine + // without stored alignment + notifyAlignmentChanged(); } } @@ -386,8 +493,10 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { changed = true; } } - if (changed) { - adjustLength(true); + if (changed && !repack(true) && isPackingEnabled()) { + // NOTE: Must assume alignment change since we are unable to determine + // without stored alignment + notifyAlignmentChanged(); } } @@ -451,13 +560,14 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { } } if (changed) { - adjustLength(true); + repack(false); + notifySizeChanged(); } } @Override public void dataTypeDeleted(DataType dt) { - boolean didDelete = false; + boolean changed = false; for (int i = components.size() - 1; i >= 0; i--) { // reverse order DataTypeComponentImpl dtc = components.get(i); boolean removeBitFieldComponent = false; @@ -469,21 +579,23 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { dt.removeParent(this); components.remove(i); shiftOrdinals(i, -1); - didDelete = true; + changed = true; } } - if (didDelete) { - adjustLength(true); + if (changed && !repack(true) && isPackingEnabled()) { + // NOTE: Must assume alignment change since we are unable to determine + // without stored alignment + notifyAlignmentChanged(); } } @Override public void replaceWith(DataType dataType) throws IllegalArgumentException { - if (!(dataType instanceof Union)) { + if (!(dataType instanceof UnionInternal)) { throw new IllegalArgumentException(); } - Union union = (Union) dataType; + UnionInternal union = (UnionInternal) dataType; Iterator it = components.iterator(); while (it.hasNext()) { @@ -491,8 +603,10 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { dtc.getDataType().removeParent(this); } components.clear(); + unionAlignment = -1; - setAlignment(union); + this.packing = union.getStoredPackingValue(); + this.minimumAlignment = union.getStoredMinimumAlignment(); DataTypeComponent[] compArray = union.getComponents(); for (DataTypeComponent dtc : compArray) { @@ -500,12 +614,8 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { doAdd(dt, dtc.getLength(), dtc.getFieldName(), dtc.getComment()); } - adjustLength(true); - } - - @Override - public void dataTypeNameChanged(DataType dt, String oldName) { - // ignored + repack(false); + notifySizeChanged(); // assume size and/or alignment changed } @Override @@ -522,16 +632,4 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union { return "UNION_" + getName(); } - @Override - public void realign() { - if (isInternallyAligned()) { - adjustInternalAlignment(); - } - } - - @Override - public void adjustInternalAlignment() { - adjustLength(true); - } - } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionInternal.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionInternal.java new file mode 100644 index 0000000000..d387fa8d63 --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/UnionInternal.java @@ -0,0 +1,20 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.program.model.data; + +public interface UnionInternal extends Union, CompositeInternal { + +} diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/StructureDBTest.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/StructureDBTest.java index 86937a9c36..fe8710697b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/StructureDBTest.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/StructureDBTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.*; import org.junit.*; +import com.google.common.collect.Sets; + import generic.test.AbstractGTest; import ghidra.program.model.data.*; import ghidra.util.InvalidNameException; @@ -89,10 +91,12 @@ public class StructureDBTest extends AbstractGTest { public void testEmpty() throws Exception { Structure s = new StructureDataType("foo", 0); assertTrue(s.isNotYetDefined()); + assertTrue(s.isZeroLength()); assertEquals(0, s.getNumComponents()); assertEquals(0, s.getNumDefinedComponents()); Structure s2 = (Structure) dataMgr.resolve(s, null); assertTrue(s2.isNotYetDefined()); + assertTrue(s2.isZeroLength()); assertEquals(0, s2.getNumComponents()); assertEquals(0, s.getNumDefinedComponents()); } @@ -101,10 +105,12 @@ public class StructureDBTest extends AbstractGTest { public void testSizeOne() throws Exception { Structure s = new StructureDataType("foo", 1); assertFalse(s.isNotYetDefined()); + assertFalse(s.isZeroLength()); assertEquals(1, s.getNumComponents()); assertEquals(0, s.getNumDefinedComponents()); Structure s2 = (Structure) dataMgr.resolve(s, null); assertFalse(s2.isNotYetDefined()); + assertFalse(s2.isZeroLength()); assertEquals(1, s2.getNumComponents()); assertEquals(0, s2.getNumDefinedComponents()); } @@ -442,7 +448,7 @@ public class StructureDBTest extends AbstractGTest { @Test public void testSetFlexArray() throws Exception { - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); struct.delete(2); // remove dword to verify flex array alignment below @@ -450,7 +456,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 2 word 2 null \"Comment2\"\n" + @@ -464,7 +470,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 2 word 2 null \"Comment2\"\n" + @@ -478,7 +484,7 @@ public class StructureDBTest extends AbstractGTest { @Test public void testZeroBitFields() throws Exception { - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); struct.delete(2); // remove dword to verify flex array alignment below @@ -488,7 +494,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 int:3(0) 1 bf1 \"bf1Comment\"\n" + " 4 int:0(0) 1 \"zero bitfield 1\"\n" + @@ -504,7 +510,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 int:3(0) 1 bf1 \"bf1Comment\"\n" + " 4 int:0(0) 1 \"zero bitfield 1\"\n" + @@ -525,7 +531,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -543,7 +549,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -562,7 +568,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -585,7 +591,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -605,7 +611,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -630,7 +636,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -649,7 +655,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -669,7 +675,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -697,7 +703,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -716,7 +722,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -751,7 +757,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -770,7 +776,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -790,7 +796,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -809,7 +815,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -828,7 +834,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -859,7 +865,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1084,7 +1090,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -1101,7 +1107,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -1118,7 +1124,7 @@ public class StructureDBTest extends AbstractGTest { @Test public void testReplaceFlexArrayDependency() throws DataTypeDependencyException { - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); struct.delete(2); // remove dword to verify flex array alignment below @@ -1129,7 +1135,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 2 word 2 null \"Comment2\"\n" + @@ -1146,7 +1152,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 2 word 2 null \"Comment2\"\n" + @@ -1161,7 +1167,7 @@ public class StructureDBTest extends AbstractGTest { public void testReplaceBitFieldDependency() throws InvalidDataTypeException, DataTypeDependencyException { - struct.setInternallyAligned(true); + struct.setPackingEnabled(true); TypeDef td = new TypedefDataType("Foo", IntegerDataType.dataType); td = (TypeDef) dataMgr.resolve(td, null); @@ -1172,7 +1178,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 2 word 2 null \"Comment2\"\n" + @@ -1189,7 +1195,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Aligned\n" + + "pack()\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 2 word 2 null \"Comment2\"\n" + @@ -1206,7 +1212,7 @@ public class StructureDBTest extends AbstractGTest { @Test public void testReplaceWith() throws InvalidDataTypeException { - // NOTE: unaligned bitfields should remain unchanged when + // NOTE: non-packed bitfields should remain unchanged when // transitioning endianess even though it makes little sense. // Unaligned structures are not intended to be portable! @@ -1222,7 +1228,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -1246,7 +1252,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/bigStruct\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure bigStruct {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 1 word 2 null \"Comment2\"\n" + @@ -1263,6 +1269,129 @@ public class StructureDBTest extends AbstractGTest { //@formatter:on } + @Test + public void testReplaceWithConflict() { + + // Test case where structure BAR contains a not-yet-defined structure FOO (impl) + // which has previously been resolved as fully defined. Test verifies that resolving + // BAR properly handles the conflict replacement of the FOO component with a larger + // fully defined datatype. + + Structure fooNotYetDefined = new StructureDataType("FOO", 0); + + Structure fooDefined = new StructureDataType("FOO", 0); + fooDefined.add(new ArrayDataType(ByteDataType.dataType, 20, 1)); + fooDefined = (Structure) dataMgr.resolve(fooDefined, null); + + Structure barStruct = new StructureDataType("BAR", 40); + barStruct.replaceAtOffset(0, fooNotYetDefined, -1, "f1", null); + barStruct.replaceAtOffset(10, ByteDataType.dataType, 1, "f2", null); + + barStruct = (Structure) dataMgr.resolve(barStruct, + DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/BAR\n" + + "pack(disabled)\n" + + "Structure BAR {\n" + + " 0 FOO 10 f1 \"\"\n" + + " 10 byte 1 f2 \"\"\n" + + "}\n" + + "Size = 40 Actual Alignment = 1", barStruct); + //@formatter:on + + DataTypeComponent dtc1 = barStruct.getDefinedComponents()[1]; + assertEquals(1, dtc1.getOrdinal()); + assertEquals(dtc1, barStruct.getComponent(1)); + } + + @Test + public void testReplaceWithConflict2() { + + // Test case where structure BAR contains a not-yet-defined structure FOO (impl) + // which has previously been resolved as fully defined. Test verifies that resolving + // BAR properly handles the conflict replacement of the FOO component with a larger + // fully defined datatype. + + Structure fooNotYetDefined = new StructureDataType("FOO", 0); + + Structure fooDefined = new StructureDataType("FOO", 0); + fooDefined.add(new ArrayDataType(ByteDataType.dataType, 5, 1)); + fooDefined = (Structure) dataMgr.resolve(fooDefined, null); + + Structure barStruct = new StructureDataType("BAR", 40); + barStruct.replaceAtOffset(0, fooNotYetDefined, -1, "f1", null); + barStruct.replaceAtOffset(10, ByteDataType.dataType, 1, "f2", null); + + barStruct = (Structure) dataMgr.resolve(barStruct, + DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/BAR\n" + + "pack(disabled)\n" + + "Structure BAR {\n" + + " 0 FOO 5 f1 \"\"\n" + + " 10 byte 1 f2 \"\"\n" + + "}\n" + + "Size = 40 Actual Alignment = 1", barStruct); + //@formatter:on + + DataTypeComponent dtc1 = barStruct.getDefinedComponents()[1]; + assertEquals(6, dtc1.getOrdinal()); + assertEquals(dtc1, barStruct.getComponent(6)); + + } + + @Test + public void testDeleteMany() throws InvalidDataTypeException { + + struct.insertBitFieldAt(2, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment"); + struct.insertBitFieldAt(2, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment"); + struct.insertBitFieldAt(2, 4, 6, IntegerDataType.dataType, 15, "bf3", "bf3Comment"); + struct.insertBitFieldAt(2, 4, 21, IntegerDataType.dataType, 11, "bf4", "bf4Comment"); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + + "pack(disabled)\n" + + "Structure Test {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + + " 2 int:3(0) 1 bf1 \"bf1Comment\"\n" + + " 2 int:3(3) 1 bf2 \"bf2Comment\"\n" + + " 2 int:15(6) 3 bf3 \"bf3Comment\"\n" + + " 4 int:11(5) 2 bf4 \"bf4Comment\"\n" + + " 6 word 2 null \"Comment2\"\n" + + " 8 dword 4 field3 \"\"\n" + + " 12 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 13 Actual Alignment = 1", struct); + //@formatter:on + + struct.delete(Sets.newHashSet(1, 2, 3, 4, 5, 6)); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + + "pack(disabled)\n" + + "Structure Test {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + +// " 1 undefined 1 null \"\"\n" + +// " 2 undefined 1 null \"\"\n" + +// " 3 undefined 1 null \"\"\n" + +// " 4 undefined 1 null \"\"\n" + + " 5 dword 4 field3 \"\"\n" + + " 9 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 10 Actual Alignment = 1", struct); + //@formatter:on + + assertEquals(10, struct.getLength()); + assertEquals(7, struct.getNumComponents()); + assertEquals(3, struct.getNumDefinedComponents()); + DataTypeComponent[] comps = struct.getDefinedComponents(); + assertEquals(DWordDataType.class, comps[1].getDataType().getClass()); + assertEquals(5, comps[1].getOffset()); + } + @Test public void testDelete() throws InvalidDataTypeException { @@ -1273,7 +1402,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1292,7 +1421,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1310,7 +1439,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1327,7 +1456,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1344,7 +1473,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1362,7 +1491,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1380,7 +1509,7 @@ public class StructureDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Test\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Structure Test {\n" + " 0 byte 1 field1 \"Comment1\"\n" + // " 1 undefined 1 null \"\"\n" + @@ -1446,6 +1575,7 @@ public class StructureDBTest extends AbstractGTest { s.deleteAll(); assertEquals(1, s.getLength()); assertTrue(s.isNotYetDefined()); + assertTrue(s.isZeroLength()); assertEquals(0, s.getNumComponents()); } diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/UnionDBTest.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/UnionDBTest.java index ed910b11a0..d63611dc97 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/UnionDBTest.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/data/UnionDBTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.*; import org.junit.*; +import com.google.common.collect.Sets; + import generic.test.AbstractGTest; import ghidra.program.model.data.*; import ghidra.util.task.TaskMonitor; @@ -169,7 +171,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 short 2 null \"\"\n" + " 0 int:2(0) 1 bf1 \"bf1Comment\"\n" + @@ -179,7 +181,7 @@ public class UnionDBTest extends AbstractGTest { } @Test - public void testAlignedBitFieldUnion() throws Exception { + public void testPackedBitFieldUnion() throws Exception { int cnt = union.getNumComponents(); for (int i = 0; i < cnt; i++) { @@ -187,11 +189,11 @@ public class UnionDBTest extends AbstractGTest { } union.insertBitField(0, IntegerDataType.dataType, 2, "bf1", "bf1Comment"); union.insert(0, ShortDataType.dataType); - union.setInternallyAligned(true); + union.setPackingEnabled(true); //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Aligned\n" + + "pack()\n" + "Union TestUnion {\n" + " 0 short 2 null \"\"\n" + " 0 int:2(0) 1 bf1 \"bf1Comment\"\n" + @@ -208,7 +210,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -231,7 +233,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -255,7 +257,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -271,7 +273,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -294,7 +296,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -310,7 +312,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field1 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -357,6 +359,42 @@ public class UnionDBTest extends AbstractGTest { assertEquals(2, union.getLength()); } + @Test + public void testDeleteMany() throws Exception { + Structure struct = createStructure("struct_1", 0); + struct.add(new ByteDataType()); + struct.add(new StringDataType(), 10); + union.add(struct); + assertEquals(11, union.getLength()); + + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + + "pack(disabled)\n" + + "Union TestUnion {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + + " 0 word 2 null \"Comment2\"\n" + + " 0 dword 4 field3 \"\"\n" + + " 0 byte 1 field4 \"Comment4\"\n" + + " 0 struct_1 11 null \"\"\n" + + "}\n" + + "Size = 11 Actual Alignment = 1", union); + //@formatter:on + + union.delete(Sets.newHashSet(2, 4)); + + assertEquals(2, union.getLength()); + //@formatter:off + CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + + "pack(disabled)\n" + + "Union TestUnion {\n" + + " 0 byte 1 field1 \"Comment1\"\n" + + " 0 word 2 null \"Comment2\"\n" + + " 0 byte 1 field4 \"Comment4\"\n" + + "}\n" + + "Size = 2 Actual Alignment = 1", union); + //@formatter:on + } + @Test public void testIsPartOf() { Structure struct = createStructure("struct_1", 0); @@ -388,7 +426,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/Replaced\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union Replaced {\n" + " 0 byte 1 field0 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + @@ -403,7 +441,7 @@ public class UnionDBTest extends AbstractGTest { //@formatter:off CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" + - "Unaligned\n" + + "pack(disabled)\n" + "Union TestUnion {\n" + " 0 byte 1 field0 \"Comment1\"\n" + " 0 word 2 null \"Comment2\"\n" + diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataType.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataType.java index 8c7069498b..adb30d2312 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataType.java @@ -128,6 +128,11 @@ public class TestDoubleDataType implements DataType { throw new UnsupportedOperationException(); } + @Override + public boolean isZeroLength() { + throw new UnsupportedOperationException(); + } + @Override public String getDescription() { throw new UnsupportedOperationException(); @@ -195,6 +200,11 @@ public class TestDoubleDataType implements DataType { throw new UnsupportedOperationException(); } + @Override + public void dataTypeAlignmentChanged(DataType dt) { + throw new UnsupportedOperationException(); + } + @Override public void dataTypeDeleted(DataType dt) { throw new UnsupportedOperationException(); diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataTypeManager.java index 0cca736b6c..bb5969fc34 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDoubleDataTypeManager.java @@ -142,7 +142,7 @@ public class TestDoubleDataTypeManager implements DataTypeManager { } @Override - public void dataTypeChanged(DataType dataType) { + public void dataTypeChanged(DataType dataType, boolean isAutoChange) { throw new UnsupportedOperationException(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDummyDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDummyDataTypeManager.java index 023252a05e..140ca5282b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDummyDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/data/TestDummyDataTypeManager.java @@ -156,7 +156,7 @@ public class TestDummyDataTypeManager implements DataTypeManager { } @Override - public void dataTypeChanged(DataType dataType) { + public void dataTypeChanged(DataType dataType, boolean isAutoChange) { // stub } diff --git a/Ghidra/Framework/Utility/hs_err_pid16061.log b/Ghidra/Framework/Utility/hs_err_pid16061.log new file mode 100644 index 0000000000..4966b9436f --- /dev/null +++ b/Ghidra/Framework/Utility/hs_err_pid16061.log @@ -0,0 +1,33 @@ +# +# A fatal error has been detected by the Java Runtime Environment: +# +# SIGSEGV (0xb) at pc=0x00007fa057435098, pid=16061, tid=16081 +# +# JRE version: OpenJDK Runtime Environment Corretto-11.0.10.9.1 (11.0.10+9) (build 11.0.10+9-LTS) +# Java VM: OpenJDK 64-Bit Server VM Corretto-11.0.10.9.1 (11.0.10+9-LTS, mixed mode, tiered, compressed oops, g1 gc, linux-amd64) +# Problematic frame: +# C [libjimage.so+0x4098] ImageStrings::find(Endian*, char const*, int*, unsigned int)+0x68 +# +# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again +# +# If you would like to submit a bug report, please visit: +# https://github.com/corretto/corretto-11/issues/ +# + +--------------- S U M M A R Y ------------ + +Command Line: -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:37943 -XX:+IgnoreUnrecognizedVMOptions -Djava.system.class.loader=ghidra.GhidraClassLoader -Xshare:off -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Dsun.java2d.pmoffscreen=false -Dsun.java2d.xrender=true -Dsun.java2d.d3d=false -Xdock:name=Ghidra -Dvisualvm.display.name=Ghidra -Dpython.console.encoding=UTF-8 -DContinuesInterceptor.disabled=true --illegal-access=permit -javaagent:/home/jdirish/eclipse/java-2020-06/eclipse/configuration/org.eclipse.osgi/537/0/.cp/lib/javaagent-shaded.jar ghidra.GhidraLauncher ghidra.GhidraRun + +Host: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz, 4 cores, 15G, Amazon Linux release 2 (Karoo) +Time: Fri Apr 9 19:29:24 2021 EDT elapsed time: 20998.917517 seconds (0d 5h 49m 58s) + +--------------- T H R E A D --------------- + +Current thread (0x00007fa050287800): JavaThread "Signal Dispatcher" daemon [_thread_in_vm, id=16081, stack(0x00007fa0380ac000,0x00007fa0381ad000)] + +Stack: [0x00007fa0380ac000,0x00007fa0381ad000], sp=0x00007fa0381aa140, free space=1016k +Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) +C [libjimage.so+0x4098] ImageStrings::find(Endian*, char const*, int*, unsigned int)+0x68 +C [libjimage.so+0x4baa] ImageFileReader::find_location_index(char const*, unsigned long long*) const+0x3a +C [libjimage.so+0x5070] JIMAGE_FindResource+0xf0 +V [libjvm.so+0x5e578e] \ No newline at end of file diff --git a/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic24DInitAnalyzer.java b/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic24DInitAnalyzer.java index 95f5ac3ae7..afcf743da7 100644 --- a/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic24DInitAnalyzer.java +++ b/Ghidra/Processors/PIC/src/main/java/ghidra/app/plugin/core/analysis/Pic24DInitAnalyzer.java @@ -75,7 +75,7 @@ public class Pic24DInitAnalyzer extends AbstractAnalyzer { long available = dinitBlock.getSize(); Structure dataRecordType = new StructureDataType("data_record", 0, program.getDataTypeManager()); - dataRecordType.setInternallyAligned(true); + dataRecordType.setPackingEnabled(true); dataRecordType.add(PointerDataType.dataType, "dst", null); // NOTE: long is used instead of int to ensure that 4-bytes within ROM are consumed dataRecordType.add(LongDataType.dataType, "len", null); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataTypeEditorsScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataTypeEditorsScreenShots.java index 8578f9cace..7b460868be 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataTypeEditorsScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DataTypeEditorsScreenShots.java @@ -227,7 +227,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator { } @Test - public void testStructureEditorAligned() { + public void testStructureEditorPacked() { createDetailedStructure(0x40d2b8, true, false); @@ -285,9 +285,9 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator { } @Test - public void testUnionEditorAligned() { + public void testUnionEditorPacked() { - createAlignedUnion(0x40d2b8); + createPackedUnion(0x40d2b8); goToListing(0x40d2b8, true); performAction("Edit Data Type", "DataPlugin", true); @@ -299,18 +299,18 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator { goToListing(address); - StructureDataType struct = new StructureDataType("MyUnalignedStruct", 0); - struct.add(new ByteDataType(), "myByteElement", "unaligned byte"); + StructureDataType struct = new StructureDataType("MyNonPackedStruct", 0); + struct.add(new ByteDataType(), "myByteElement", "non-packed byte"); struct.add(new ByteDataType(), "", "undefined element"); - struct.add(new WordDataType(), "myWordElement", "unaligned word"); - struct.add(new ByteDataType(), "myByteElement2", "another unaligned byte"); - struct.add(new DWordDataType(), "myDWordElement", "unaligned dword"); + struct.add(new WordDataType(), "myWordElement", "non-packed word"); + struct.add(new ByteDataType(), "myByteElement2", "another non-packed byte"); + struct.add(new DWordDataType(), "myDWordElement", "non-packed dword"); if (includeFlexArray) { struct.setFlexibleArrayComponent(CharDataType.dataType, "flex", "unsized flexible array"); } struct.clearComponent(1); - struct.setDescription("This is an example of an unaligned structure " + + struct.setDescription("This is an example of an non-packed structure " + (includeFlexArray ? "with a flexible char array" : "of size 9") + "."); CreateDataCmd createDataCmd = new CreateDataCmd(addr(address), struct); @@ -318,13 +318,13 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator { waitForBusyTool(tool); } - private void createDetailedStructure(long address, boolean aligned, + private void createDetailedStructure(long address, boolean packed, boolean includeBitFieldsAndFlexArray) { goToListing(address); - StructureDataType struct = new StructureDataType("MyAlignedStruct", 0); - struct.setInternallyAligned(true); // allow proper default packing + StructureDataType struct = new StructureDataType("MyPackedStruct", 0); + struct.setPackingEnabled(true); // allow proper default packing struct.add(new ByteDataType(), "myByteElement", "alignment 1"); struct.add(new ByteDataType(), "", "This is my undefined element"); struct.add(new WordDataType(), "myWordElement", "alignment 2"); @@ -345,11 +345,11 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator { "unsized flexible array"); } struct.clearComponent(1); - struct.setDescription("Members internally aligned " + + struct.setDescription("Members packed " + (includeBitFieldsAndFlexArray ? "with bitfields and a flexible char array" : "according to their alignment size") + ". "); - struct.setInternallyAligned(aligned); + struct.setPackingEnabled(packed); CreateDataCmd createDataCmd = new CreateDataCmd(addr(address), struct); tool.execute(createDataCmd, program); @@ -361,28 +361,28 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator { goToListing(address); UnionDataType union = new UnionDataType("MyUnion"); - union.add(new ByteDataType(), "myByteElement", "unaligned byte"); - union.add(new WordDataType(), "myWordElement", "unaligned word"); - union.add(new DWordDataType(), "myDWordElement", "unaligned dword"); - union.add(new QWordDataType(), "myQWordElement", "unaligned qword"); - union.setDescription("This is an example of an unaligned union."); + union.add(new ByteDataType(), "myByteElement", "non-packed byte"); + union.add(new WordDataType(), "myWordElement", "non-packed word"); + union.add(new DWordDataType(), "myDWordElement", "non-packed dword"); + union.add(new QWordDataType(), "myQWordElement", "non-packed qword"); + union.setDescription("This is an example of an non-packed union."); CreateDataCmd createDataCmd = new CreateDataCmd(addr(address), union); tool.execute(createDataCmd, program); waitForBusyTool(tool); } - private void createAlignedUnion(long address) { + private void createPackedUnion(long address) { goToListing(address); UnionDataType union = new UnionDataType("MyUnion"); - union.add(new ByteDataType(), "myByteElement", "aligned byte"); - union.add(new WordDataType(), "myWordElement", "aligned word"); - union.add(new DWordDataType(), "myDWordElement", "aligned dword"); - union.add(new QWordDataType(), "myQWordElement", "aligned qword"); - union.setDescription("This is an example of an aligned union."); - union.setInternallyAligned(true); + union.add(new ByteDataType(), "myByteElement", "packed byte"); + union.add(new WordDataType(), "myWordElement", "packed word"); + union.add(new DWordDataType(), "myDWordElement", "packed dword"); + union.add(new QWordDataType(), "myQWordElement", "packed qword"); + union.setDescription("This is an example of an packed union."); + union.setPackingEnabled(true); CreateDataCmd createDataCmd = new CreateDataCmd(addr(address), union); tool.execute(createDataCmd, program);