diff --git a/Ghidra/Features/Base/certification.manifest b/Ghidra/Features/Base/certification.manifest
index ed2497532a..97e4615371 100644
--- a/Ghidra/Features/Base/certification.manifest
+++ b/Ghidra/Features/Base/certification.manifest
@@ -199,6 +199,7 @@ src/main/help/help/topics/DataTypeEditors/images/MultiDuplicateData.png||GHIDRA|
src/main/help/help/topics/DataTypeEditors/images/NumDuplicates.png||GHIDRA||||END|
src/main/help/help/topics/DataTypeEditors/images/NumElementsPrompt.png||GHIDRA||||END|
src/main/help/help/topics/DataTypeEditors/images/Plus.png||GHIDRA||||END|
+src/main/help/help/topics/DataTypeEditors/images/StructureEditBitfield.png||GHIDRA||||END|
src/main/help/help/topics/DataTypeEditors/images/StructureEditor.png||GHIDRA||||END|
src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.png||GHIDRA||||END|
src/main/help/help/topics/DataTypeEditors/images/StructureEditorWithFlexArray.png||GHIDRA||||END|
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/StructureEditor.htm b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/StructureEditor.htm
index 05ca018477..e166461286 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/StructureEditor.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/StructureEditor.htm
@@ -32,8 +32,8 @@
within the bit view of the component, it will be omitted. However, holding down the Shift-key
while using the mouse wheel on a component will zoom the view in and out
allowing component labels to appear when space permits. The bit view may also be used to make
- and reflect single component selections with the table. Within the bit view any padding bits not visible within
- table view as a component will include a small dot in the center of the displayed bit cell.
+ and reflect single component selections with the table. Within the bit view any padding bits not visible within
+ the table view as a component will include a small dot in the center of the displayed bit cell.
The Union Editor is very similar to the Structure Editor, but is used to create or modify a union data type. All the components of a Union are at an offset of 0. The following illustrates @@ -332,33 +332,36 @@
While packing of bitfields within aligned
+ 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).
The use of bitfield components is not
currently reflected in decompiler results or assembly markup.
A structure may be defined with a trailing flexible array component which corresponds to
@@ -620,7 +623,35 @@
+
++ +The following bitfield actions are available when modifying unaligned structures only 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 + table view (e.g., char:1).
+ +Add Bitfield
+++ +With a structure row selected in the vicinity of the desire bitfield placement, the popup + menu action (right mouse-click) Add Bitfield may be selected to launch the + Bitfield Editor for a new bitfield.
+ ++ +
A direct text entry of a bitfield + datatype may be specified within the table datatype column (e.g., char:1), although it + will always be placed at a default offset.
Edit Bitfield
+ +++With a defined bitfield component row selected, the popup + menu action (right mouse-click) Edit Bitfield may be selected to launch the + Bitfield Editor.
+Component Fields
Each row displays information about a component in this structure or union. The DataType, @@ -1218,6 +1249,99 @@
To select an option simply click on the check box.
+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., + bitfields are specified via datatype text entry within the structure/union table view).
+ +The Structure Editor popup menu actions Add Bitfield and Edit Bitfield are + used to launch the Bitfield Editor. While the Bitfield Editor is displayed local popup menu actions + are provided which can facilitate additional component manipulations (e.g., Add Bitfield, + Edit Bitfield, Delete). These actions relate to the component at the current + mouse cursor location. Invoking either the Add Bitfield or + Edit Bitfield local popup menu actions will immediately cancel the current bitfield + operation if one is active.
+ +The Bitfield Editor includes a visual depiction of the storage allocation bytes and associated + bits (8-bits per byte, with a left-toright sequence of 7..0). The displayed byte ordering as + conveyed by the Byte Offset header + will differ for big-endian vs. little-endian. This is done to ensure that bitfields which span + byte boundaries will always visually appear as a consecutive range of bits. The Component Bits + display provides both a popup menu and mouse assisted bitfield manipulations. Component labels + are included within each component when space permits. The color legend indicates the bit + color scheme reflecting Defined bitfields, Defined non-bitfields, Edit bitfield bits, Conflict bits + and Undefined bits. A dot in the center of an Undefined bit indicates a padding bit not included + within any defined component.
+ +
+++
+
+ ++ +
A component zoom feature is provided which can + allow the user to increase the visual bit size allowing for component labels to be shown + as size permits. While with the mouse cursor is over a component, use mouse wheel while the + Shift key is depressed.
Bitfield Parameters
++ ++ +Structure Offset of Allocation Unit - controls the minimum byte offset of the + storage allocation unit represented by the bitfield edit view. This offset is controlled + via the
+ +and +
buttons at the top of the bitfield editor.
Allocation Bytes - controls the size of the storage allocation unit to be utilized + in the event a bit conflict exists and the user chooses to Move Conflicts. This numeric + entry can be directly entered within the range of 1 through 16 bytes. The mouse wheel may + also be used while the cursor is over this entry.
+ +Bit Size - specifies the size of the bitfield in bits. This size may not exceed + the size of the specified Base Datatype. This numeric + entry can be directly entered or via the mouse wheel while the cursor is over this entry field + or the rendered bitfield.
+ +Bit Offset - specifies the offset of the rightmost bit of the bitfield within + the displayed allocation unit. This numeric + entry can be directly entered or via the mouse wheel while the cursor is over this entry field.
+ +Base Datatype - (required) specifies the numeric datatype associated with the bitfield. + Valid datatypes include primitive integer types (e.g., char, int, etc.), enum types, and + typedef types of integer or enum types. This input allows direct text input with auto-complete + assistance or via full access to a datatype tree chooser by clicking the '...' button.
+ +Field Name - (optional) specifies the structure component name to be assigned to + the bitfield. This entry utilizes a simple text entry field.
+ ++ +
The bitfield offset and size may be fully + specified by clicking and dragging over the visual bit-range where the bitfield + should reside.
+ +
Within the Bitfield Editor the bit + size may not exceed the size of the Base Datatype based upon the structure's + associated compiler convention (i.e., + data organization). Since archives use default + integer type sizes which may differ from a target program's datatype sizing, the use of fixed-size base + datatypes may be preferred. Otherwise, structure edits should be performed within the + target program where datatype sizes may be larger. If an existing bitfield size exceeds + the size of the base datatype within + the associated data organization the "effective" bitfield size will be reduced. As with other + components, structure component sizing may change when moving between a datatype archive and + a target program.
+ +
It is important to note that the retained bitfield + storage specification (byte offset, component byte size, bit offset) will utilize the smallest possible + values while preserving bitfield positioning within the structure. The allocation unit offset and size + conveyed by the editor are for editor use only.
Provided by: Data Type Manager Plugin
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditBitfield.png b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditBitfield.png new file mode 100644 index 0000000000..99d68e5a92 Binary files /dev/null and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditBitfield.png differ 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 d1efa1528c..d9e6996cf0 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 index a59fdce95b..dbf2be9ed9 100644 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.png and b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.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 227720092f..95a78a830e 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/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/BitFieldEditorDialog.java index 3346ab32d4..26327b8c70 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 @@ -26,6 +26,7 @@ import docking.action.DockingAction; import docking.action.MenuData; import ghidra.app.services.DataTypeManagerService; import ghidra.program.model.data.*; +import ghidra.util.HelpLocation; import resources.ResourceManager; public class BitFieldEditorDialog extends DialogComponentProvider { @@ -52,6 +53,8 @@ public class BitFieldEditorDialog extends DialogComponentProvider { setRememberSize(false); addActions(); + + setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Bitfield_Editor")); } private void addButtons() { @@ -81,7 +84,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider { EditBitFieldAction() { super("Edit Bitfield", "BitFieldEditorDialog"); setPopupMenuData(new MenuData(new String[] { getName() }, EDIT_ICON)); - + setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Editor_Edit_Bitfield")); } @Override @@ -104,6 +107,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider { AddBitFieldAction() { super("Add Bitfield", "BitFieldEditorDialog"); setPopupMenuData(new MenuData(new String[] { getName() }, ADD_ICON)); + setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Editor_Add_Bitfield")); } @Override @@ -129,7 +133,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider { private class DeleteComponentAction extends DockingAction { DeleteComponentAction() { - super("Delete Component", "BitFieldEditorDialog"); + super("Delete", "BitFieldEditorDialog"); setPopupMenuData(new MenuData(new String[] { getName() }, DELETE_ICON)); } 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 b973ac3c92..d82026f57f 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 @@ -19,7 +19,6 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; -import javax.swing.border.EmptyBorder; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; @@ -274,13 +273,15 @@ public class BitFieldEditorPanel extends JPanel { if (e.isConsumed()) { return; } - e.consume(); - selectionActive = false; - if (e.getButton() == MouseEvent.BUTTON1 && bitOffsetInput.isEnabled()) { - bitSizeModel.setValue(1L); // must change size first - startBit = setBitFieldOffset(e.getPoint()); - lastBit = startBit; - selectionActive = startBit >= 0; + if (e.getButton() == MouseEvent.BUTTON1) { + e.consume(); + selectionActive = false; + if (bitOffsetInput.isEnabled()) { + bitSizeModel.setValue(1L); // must change size first + startBit = setBitFieldOffset(e.getPoint()); + lastBit = startBit; + selectionActive = startBit >= 0; + } } } @@ -329,15 +330,6 @@ public class BitFieldEditorPanel extends JPanel { } private JPanel createPlacementPanel() { - JPanel midPanel = new JPanel(new PairLayout(5, 5)); - - JPanel leftMidPanel = new JPanel(new VerticalLayout(13)); - leftMidPanel.setBorder(BorderFactory.createEmptyBorder(12, 8, 12, 0)); - JLabel byteOffsetLabel = new JLabel("Byte Offset:", SwingConstants.RIGHT); - byteOffsetLabel.setToolTipText("Byte Offset is relative to start of allocation unit"); - leftMidPanel.add(byteOffsetLabel); - leftMidPanel.add(new JLabel("Bits:", SwingConstants.RIGHT)); - midPanel.add(leftMidPanel); placementComponent = new BitFieldPlacementComponent(composite); placementComponent.setFont(UIManager.getFont("TextField.font")); @@ -347,17 +339,23 @@ public class BitFieldEditorPanel extends JPanel { placementComponent.addMouseListener(bitSelectionHandler); placementComponent.addMouseMotionListener(bitSelectionHandler); - JPanel p = new JPanel(new BorderLayout()); - p.add(placementComponent, BorderLayout.WEST); - p.setBorder(new EmptyBorder(0, 0, 5, 0)); + JPanel bitViewPanel = new JPanel(new PairLayout(0, 5)); - JScrollPane scrollPane = new JScrollPane(p, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, - ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + JPanel labelPanel = new JPanel(new VerticalLayout(7)); + labelPanel.setBorder(BorderFactory.createEmptyBorder(7, 5, 0, 0)); + JLabel byteOffsetLabel = new JLabel("Byte Offset:", SwingConstants.RIGHT); + labelPanel.add(byteOffsetLabel); + labelPanel.add(new JLabel("Component Bits:", SwingConstants.RIGHT)); + bitViewPanel.add(labelPanel); + + JScrollPane scrollPane = + new JScrollPane(placementComponent, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.getViewport().setBackground(getBackground()); scrollPane.setBorder(null); - midPanel.add(scrollPane); - return midPanel; + bitViewPanel.add(scrollPane); + return bitViewPanel; } private boolean checkValidBaseDataType() { 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 6f23f639d6..76d0e2f30c 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 @@ -24,6 +24,7 @@ import javax.swing.*; import ghidra.program.model.data.*; import ghidra.program.model.data.Composite; +import ghidra.util.HTMLUtilities; import ghidra.util.Msg; import ghidra.util.exception.AssertException; import ghidra.util.layout.VerticalLayout; @@ -37,7 +38,7 @@ public class BitFieldPlacementComponent extends JPanel { private static final int BIT_SEPARATOR_THICKNESS = 1; private static final int BYTE_SEPARATOR_THICKNESS = 2; // private static final int BYTE_WIDTHx = 8 * (BIT_WIDTH + BIT_SEPARATOR_THICKNESS); - private static final int SCROLLBAR_THICKNESS = 10; + private static final int SCROLLBAR_THICKNESS = 15; private static final int MY_HEIGHT = (2 * CELL_HEIGHT) + (3 * BYTE_SEPARATOR_THICKNESS); private static final int LENEND_BOX_SIZE = 16; @@ -476,8 +477,14 @@ public class BitFieldPlacementComponent extends JPanel { @Override public String getToolTipText(MouseEvent e) { BitAttributes attrs = getBitAttributes(e.getPoint()); - String dtcInfo = attrs != null ? (attrs.getTip() + "