BitFields - additional refinements and added help content
|
@ -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/NumDuplicates.png||GHIDRA||||END|
|
||||||
src/main/help/help/topics/DataTypeEditors/images/NumElementsPrompt.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/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/StructureEditor.png||GHIDRA||||END|
|
||||||
src/main/help/help/topics/DataTypeEditors/images/StructureEditorAligned.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|
|
src/main/help/help/topics/DataTypeEditors/images/StructureEditorWithFlexArray.png||GHIDRA||||END|
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
within the bit view of the component, it will be omitted. However, holding down the Shift-key
|
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
|
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
|
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
|
and reflect single component selections with the table. Within the bit view any <i>padding</i> bits not visible within
|
||||||
table view as a component will include a small dot in the center of the displayed bit cell.<BR>
|
the table view as a component will include a small dot in the center of the displayed bit cell.<BR>
|
||||||
|
|
||||||
<P>The Union Editor is very similar to the Structure Editor, but is used to create or modify a
|
<P>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
|
union data type. All the components of a Union are at an offset of 0. The following illustrates
|
||||||
|
@ -332,30 +332,33 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>A bitfield datatype may not exist anywhere other than within a structure or union.</li>
|
<li>A bitfield datatype may not exist anywhere other than within a structure or union.</li>
|
||||||
<li>A bitfield datatype may not be selected via the datatype chooser or tree since it
|
<li>A bitfield datatype may not be selected via the datatype chooser or tree since it
|
||||||
requires the specification of additional attributes (bit-size, bit-offset, etc.). The
|
requires the specification of additional attributes (e.g., bit-size, bit-offset). The
|
||||||
bit-size is generally appended to the base-datatype for entry and presentation purposes
|
bit-size is generally appended to the base-datatype for datatype specification and
|
||||||
(e.g., char:1). NOTE: At the API level there is no public or default constructor for the
|
presentation purposes (e.g., char:1).</li>
|
||||||
<I>BitFieldDataType</I>. Specific API methods exist for adding bitfields to structures and unions.</li>
|
|
||||||
<li>A zero-length bitfield may be defined within a byte but its' precise bit position
|
<li>A zero-length bitfield may be defined within a byte but its' precise bit position
|
||||||
is controlled by endianess alone. A zero-length bitfield has no affect within an unaligned
|
is controlled by endianess alone. A zero-length bitfield has no affect within an unaligned
|
||||||
structure and is intended for use within aligned structures where it may impart alignment
|
structure and is intended for use within aligned structures where it may impart alignment
|
||||||
affects based upon compiler conventions.</li>
|
affects based upon compiler conventions.</li>
|
||||||
<li>Inserting or moving bitfields may cause component shifts based upon allocation unit
|
<li>Inserting a bitfield within an unaligned structure may cause component shifts based
|
||||||
byte size and possible placement conflicts.</li>
|
upon the specified offset and allocation unit byte size when a placement conflict occurs.</li>
|
||||||
<li>The start/end byte offsets may be shared with adjacent bitfield components.</li>
|
<li>The start/end byte offsets may be shared with adjacent bitfield components.</li>
|
||||||
<li>Unoccupied bits within a partially occupied byte are not represented by any component
|
<li>Unoccupied bits within a partially occupied byte are not represented by any component
|
||||||
(similar to padding bytes within aligned structures). Using the bit view provides
|
(similar to padding bytes within aligned structures).</li>
|
||||||
a precise bit-level view of a component. When a single component is selected, the bit
|
<li>A separate <a href="#Structure_Bitfield_Editor">Bitfield Editor</a>, for use with unaligned structures only,
|
||||||
view will highlight the corresponding component block.</li>
|
must be used to precisely place a bitfield component. Adding a bitfield component via the
|
||||||
<li>A separate Bitfield Editor, for use with unaligned structures only,
|
structure table view via datatype text entry (e.g., char:1) provides only rough placement for unaligned
|
||||||
must be used to precisley place a bitfield component. Adding a bitfield component via the
|
structures since additional bytes will be introduced.
|
||||||
structure table view via datatype text entry (e.g., char:1) provides only rough placement.
|
|
||||||
The BitField Editor may be displayed using the the Add Bitfield and
|
The BitField Editor may be displayed using the the Add Bitfield and
|
||||||
Edit Bitfield popup actions on a selected structure component. The datatype text entry approach
|
Edit Bitfield popup menu actions on a selected structure component. The datatype text entry approach
|
||||||
must be used for all unions and aligned strctures.</li>
|
must be used for all unions and aligned structures.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<P><IMG alt="Note:" src="../../shared/note.png">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).</P>
|
||||||
|
|
||||||
<P><IMG alt="Note:" src="../../shared/note.png">The use of bitfield components is not
|
<P><IMG alt="Note:" src="../../shared/note.png">The use of bitfield components is not
|
||||||
currently reflected in decompiler results or assembly markup. </P>
|
currently reflected in decompiler results or assembly markup. </P>
|
||||||
|
|
||||||
|
@ -620,6 +623,34 @@
|
||||||
</BLOCKQUOTE><BR>
|
</BLOCKQUOTE><BR>
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
<H2><A name="Structure_Editor_Bitfield_Actions"></A>Bitfield Actions (unaligned structures)</H2>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>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).</P>
|
||||||
|
|
||||||
|
<H3><A name="Structure_Editor_Add_Bitfield"></A>Add Bitfield</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>With a structure row selected in the vicinity of the desire bitfield placement, the popup
|
||||||
|
menu action (right mouse-click) <B>Add Bitfield</B> may be selected to launch the
|
||||||
|
<a href="#Structure_Bitfield_Editor">Bitfield Editor</a> for a new bitfield.</P>
|
||||||
|
|
||||||
|
<P><IMG alt="Note:" src="../../shared/note.png"> 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.</P>
|
||||||
|
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3><A name="Structure_Editor_Edit_Bitfield"></A>Edit Bitfield</H3>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>With a defined bitfield component row selected, the popup
|
||||||
|
menu action (right mouse-click) <B>Edit Bitfield</B> may be selected to launch the
|
||||||
|
<a href="#Structure_Bitfield_Editor">Bitfield Editor</a>.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H2><A name="Structure_Editor_Component_Fields"></A>Component Fields</H2>
|
<H2><A name="Structure_Editor_Component_Fields"></A>Component Fields</H2>
|
||||||
|
|
||||||
|
@ -1219,6 +1250,99 @@
|
||||||
</U></P>
|
</U></P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H2><A name="Structure_Bitfield_Editor"></A>Bitfield Editor (unaligned structures only)</H2>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P>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).</P>
|
||||||
|
|
||||||
|
<P>The Structure Editor popup menu actions <B>Add Bitfield</B> and <B>Edit Bitfield</B> 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., <B>Add Bitfield</B>,
|
||||||
|
<B>Edit Bitfield</B>, <B>Delete</B>). These actions relate to the component at the current
|
||||||
|
mouse cursor location. Invoking either the <B>Add Bitfield</B> or
|
||||||
|
<B>Edit Bitfield</B> local popup menu actions will immediately cancel the current bitfield
|
||||||
|
operation if one is active.</P>
|
||||||
|
|
||||||
|
<P>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 <B>Byte Offset</B> 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 <B>Component Bits</B>
|
||||||
|
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.</P>
|
||||||
|
|
||||||
|
<BR>
|
||||||
|
<DIV align="center" style="margin-top: 10px;">
|
||||||
|
<IMG src="images/StructureEditBitfield.png" alt=""><BR>
|
||||||
|
</DIV>
|
||||||
|
<BR>
|
||||||
|
|
||||||
|
<P><IMG alt="Tip:" src="../../shared/tip.png"> 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.</P>
|
||||||
|
|
||||||
|
<H3>Bitfield Parameters</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
|
||||||
|
<P><B>Structure Offset of Allocation Unit</B> - controls the minimum byte offset of the
|
||||||
|
storage allocation unit represented by the bitfield edit view. This offset is controlled
|
||||||
|
via the <IMG alt="-" src="images/Minus.png"> and
|
||||||
|
<IMG alt="+" src="images/Plus.png"> buttons at the top of the bitfield editor.</P>
|
||||||
|
|
||||||
|
<P><B>Allocation Bytes</B> - controls the size of the storage allocation unit to be utilized
|
||||||
|
in the event a bit conflict exists and the user chooses to <I>Move Conflicts</I>. 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.</P>
|
||||||
|
|
||||||
|
<P><B>Bit Size</B> - 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.</P>
|
||||||
|
|
||||||
|
<P><B>Bit Offset</B> - 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.</P>
|
||||||
|
|
||||||
|
<P><B>Base Datatype</B> - (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.</P>
|
||||||
|
|
||||||
|
<P><B>Field Name</B> - (optional) specifies the structure component name to be assigned to
|
||||||
|
the bitfield. This entry utilizes a simple text entry field.</P>
|
||||||
|
|
||||||
|
<P><IMG alt="Tip:" src="../../shared/tip.png"> The bitfield offset and size may be fully
|
||||||
|
specified by clicking and dragging over the visual bit-range where the bitfield
|
||||||
|
should reside.</P>
|
||||||
|
|
||||||
|
<P><IMG alt="Note:" src="../../shared/note.png"> 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.</P>
|
||||||
|
|
||||||
|
<P><IMG alt="Note:" src="../../shared/note.png"> 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.</P>
|
||||||
|
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P class="providedbyplugin">Provided by: <I>Data Type Manager</I> Plugin</P>
|
<P class="providedbyplugin">Provided by: <I>Data Type Manager</I> Plugin</P>
|
||||||
|
|
||||||
<P class="relatedtopic">Related Topics:</P>
|
<P class="relatedtopic">Related Topics:</P>
|
||||||
|
|
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 60 KiB |
|
@ -26,6 +26,7 @@ import docking.action.DockingAction;
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
|
|
||||||
public class BitFieldEditorDialog extends DialogComponentProvider {
|
public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||||
|
@ -52,6 +53,8 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||||
setRememberSize(false);
|
setRememberSize(false);
|
||||||
|
|
||||||
addActions();
|
addActions();
|
||||||
|
|
||||||
|
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Bitfield_Editor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addButtons() {
|
private void addButtons() {
|
||||||
|
@ -81,7 +84,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||||
EditBitFieldAction() {
|
EditBitFieldAction() {
|
||||||
super("Edit Bitfield", "BitFieldEditorDialog");
|
super("Edit Bitfield", "BitFieldEditorDialog");
|
||||||
setPopupMenuData(new MenuData(new String[] { getName() }, EDIT_ICON));
|
setPopupMenuData(new MenuData(new String[] { getName() }, EDIT_ICON));
|
||||||
|
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Editor_Edit_Bitfield"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -104,6 +107,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||||
AddBitFieldAction() {
|
AddBitFieldAction() {
|
||||||
super("Add Bitfield", "BitFieldEditorDialog");
|
super("Add Bitfield", "BitFieldEditorDialog");
|
||||||
setPopupMenuData(new MenuData(new String[] { getName() }, ADD_ICON));
|
setPopupMenuData(new MenuData(new String[] { getName() }, ADD_ICON));
|
||||||
|
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Editor_Add_Bitfield"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -129,7 +133,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||||
private class DeleteComponentAction extends DockingAction {
|
private class DeleteComponentAction extends DockingAction {
|
||||||
|
|
||||||
DeleteComponentAction() {
|
DeleteComponentAction() {
|
||||||
super("Delete Component", "BitFieldEditorDialog");
|
super("Delete", "BitFieldEditorDialog");
|
||||||
setPopupMenuData(new MenuData(new String[] { getName() }, DELETE_ICON));
|
setPopupMenuData(new MenuData(new String[] { getName() }, DELETE_ICON));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
|
||||||
import javax.swing.event.CellEditorListener;
|
import javax.swing.event.CellEditorListener;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
|
|
||||||
|
@ -274,15 +273,17 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
if (e.isConsumed()) {
|
if (e.isConsumed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||||
e.consume();
|
e.consume();
|
||||||
selectionActive = false;
|
selectionActive = false;
|
||||||
if (e.getButton() == MouseEvent.BUTTON1 && bitOffsetInput.isEnabled()) {
|
if (bitOffsetInput.isEnabled()) {
|
||||||
bitSizeModel.setValue(1L); // must change size first
|
bitSizeModel.setValue(1L); // must change size first
|
||||||
startBit = setBitFieldOffset(e.getPoint());
|
startBit = setBitFieldOffset(e.getPoint());
|
||||||
lastBit = startBit;
|
lastBit = startBit;
|
||||||
selectionActive = startBit >= 0;
|
selectionActive = startBit >= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseDragged(MouseEvent e) {
|
public void mouseDragged(MouseEvent e) {
|
||||||
|
@ -329,15 +330,6 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel createPlacementPanel() {
|
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 = new BitFieldPlacementComponent(composite);
|
||||||
placementComponent.setFont(UIManager.getFont("TextField.font"));
|
placementComponent.setFont(UIManager.getFont("TextField.font"));
|
||||||
|
@ -347,17 +339,23 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
placementComponent.addMouseListener(bitSelectionHandler);
|
placementComponent.addMouseListener(bitSelectionHandler);
|
||||||
placementComponent.addMouseMotionListener(bitSelectionHandler);
|
placementComponent.addMouseMotionListener(bitSelectionHandler);
|
||||||
|
|
||||||
JPanel p = new JPanel(new BorderLayout());
|
JPanel bitViewPanel = new JPanel(new PairLayout(0, 5));
|
||||||
p.add(placementComponent, BorderLayout.WEST);
|
|
||||||
p.setBorder(new EmptyBorder(0, 0, 5, 0));
|
|
||||||
|
|
||||||
JScrollPane scrollPane = new JScrollPane(p, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
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);
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
scrollPane.getViewport().setBackground(getBackground());
|
scrollPane.getViewport().setBackground(getBackground());
|
||||||
scrollPane.setBorder(null);
|
scrollPane.setBorder(null);
|
||||||
|
|
||||||
midPanel.add(scrollPane);
|
bitViewPanel.add(scrollPane);
|
||||||
return midPanel;
|
return bitViewPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkValidBaseDataType() {
|
private boolean checkValidBaseDataType() {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import javax.swing.*;
|
||||||
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Composite;
|
import ghidra.program.model.data.Composite;
|
||||||
|
import ghidra.util.HTMLUtilities;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.layout.VerticalLayout;
|
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 BIT_SEPARATOR_THICKNESS = 1;
|
||||||
private static final int BYTE_SEPARATOR_THICKNESS = 2;
|
private static final int BYTE_SEPARATOR_THICKNESS = 2;
|
||||||
// private static final int BYTE_WIDTHx = 8 * (BIT_WIDTH + BIT_SEPARATOR_THICKNESS);
|
// 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 MY_HEIGHT = (2 * CELL_HEIGHT) + (3 * BYTE_SEPARATOR_THICKNESS);
|
||||||
|
|
||||||
private static final int LENEND_BOX_SIZE = 16;
|
private static final int LENEND_BOX_SIZE = 16;
|
||||||
|
@ -476,8 +477,14 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||||
@Override
|
@Override
|
||||||
public String getToolTipText(MouseEvent e) {
|
public String getToolTipText(MouseEvent e) {
|
||||||
BitAttributes attrs = getBitAttributes(e.getPoint());
|
BitAttributes attrs = getBitAttributes(e.getPoint());
|
||||||
String dtcInfo = attrs != null ? (attrs.getTip() + "<BR>") : "";
|
if (attrs == null) {
|
||||||
return "<HTML><div style=\"text-align:center\">" + dtcInfo +
|
return null;
|
||||||
|
}
|
||||||
|
String tip = attrs.getTip();
|
||||||
|
if (tip == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return "<HTML><div style=\"text-align:center\">" + HTMLUtilities.escapeHTML(tip) +
|
||||||
"<div style=\"color: gray;font-style: italic\">(Shift-wheel to zoom)</div></div></HTML>";
|
"<div style=\"color: gray;font-style: italic\">(Shift-wheel to zoom)</div></div></HTML>";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -930,19 +937,19 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isAddBitField() {
|
private boolean isAddBitField() {
|
||||||
return !unallocated && dtc == null;
|
return !unallocated && dtc == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isEditField() {
|
private boolean isEditField() {
|
||||||
return dtc != null && dtc.getOrdinal() == editOrdinal;
|
return dtc != null && dtc.getOrdinal() == editOrdinal;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasConflict() {
|
private boolean hasConflict() {
|
||||||
return getConflict() != null;
|
return getConflict() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataTypeComponent getConflict() {
|
private DataTypeComponent getConflict() {
|
||||||
BitAttributes c = conflict;
|
BitAttributes c = conflict;
|
||||||
while (c != null && c.dtc.isZeroBitFieldComponent()) {
|
while (c != null && c.dtc.isZeroBitFieldComponent()) {
|
||||||
// TODO: improve conflict detection
|
// TODO: improve conflict detection
|
||||||
|
@ -961,7 +968,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void paint(Graphics g, BitAttributes bitAttrsToLeft, boolean paintRightLine) {
|
private void paint(Graphics g, BitAttributes bitAttrsToLeft, boolean paintRightLine) {
|
||||||
// bit box
|
// bit box
|
||||||
Color c = getColor();
|
Color c = getColor();
|
||||||
g.setColor(c);
|
g.setColor(c);
|
||||||
|
@ -1017,7 +1024,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Color getColor() {
|
private Color getColor() {
|
||||||
if (unallocated) {
|
if (unallocated) {
|
||||||
return UNDEFINED_BIT_COLOR;
|
return UNDEFINED_BIT_COLOR;
|
||||||
}
|
}
|
||||||
|
@ -1035,7 +1042,10 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||||
: NON_BITFIELD_COMPONENT_COLOR;
|
: NON_BITFIELD_COMPONENT_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getTip() {
|
private String getTip() {
|
||||||
|
if (unallocated) {
|
||||||
|
return "<padding>";
|
||||||
|
}
|
||||||
if (dtc == null) {
|
if (dtc == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ import ghidra.program.model.data.Composite.AlignmentType;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
|
import ghidra.util.layout.PairLayout;
|
||||||
|
import ghidra.util.layout.VerticalLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel for editing a composite with a blank line at the bottom of the table
|
* Panel for editing a composite with a blank line at the bottom of the table
|
||||||
|
@ -215,19 +217,24 @@ public class CompEditorPanel extends CompositeEditorPanel {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
JPanel p = new JPanel();
|
JPanel bitViewPanel = new JPanel(new PairLayout(0, 5));
|
||||||
p.add(bitViewComponent);
|
|
||||||
//p.setBorder(new EmptyBorder(5, 5, 0, 15));
|
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 bitViewScrollPane =
|
JScrollPane bitViewScrollPane =
|
||||||
new JScrollPane(p, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
new JScrollPane(bitViewComponent, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
|
|
||||||
bitViewScrollPane.getViewport().setBackground(getBackground());
|
bitViewScrollPane.getViewport().setBackground(getBackground());
|
||||||
bitViewScrollPane.setBorder(null);
|
bitViewScrollPane.setBorder(null);
|
||||||
|
|
||||||
JPanel bitViewerPanel = new JPanel(new BorderLayout());
|
bitViewPanel.add(bitViewScrollPane);
|
||||||
bitViewerPanel.add(bitViewScrollPane, BorderLayout.CENTER);
|
return bitViewPanel;
|
||||||
return bitViewerPanel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class BytesFieldFactory extends FieldFactory {
|
||||||
fieldOptions.registerOption(REVERSE_INSTRUCTION_BYTE_ORDERING, false, hl,
|
fieldOptions.registerOption(REVERSE_INSTRUCTION_BYTE_ORDERING, false, hl,
|
||||||
"Reverses the normal order of the bytes in the bytes field." +
|
"Reverses the normal order of the bytes in the bytes field." +
|
||||||
" Only used for instructions in Little Endian format");
|
" Only used for instructions in Little Endian format");
|
||||||
fieldOptions.registerOption(DISPLAY_STRUCTURE_ALIGNMENT_BYTES_MSG, false, hl,
|
fieldOptions.registerOption(DISPLAY_STRUCTURE_ALIGNMENT_BYTES_MSG, true, hl,
|
||||||
"Display trailing alignment bytes in structures.");
|
"Display trailing alignment bytes in structures.");
|
||||||
|
|
||||||
delim = fieldOptions.getString(DELIMITER_MSG, " ");
|
delim = fieldOptions.getString(DELIMITER_MSG, " ");
|
||||||
|
|
|
@ -229,7 +229,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||||
@Test
|
@Test
|
||||||
public void testStructureEditorAligned() {
|
public void testStructureEditorAligned() {
|
||||||
|
|
||||||
createAlignedDetailedStructure(0x40d2b8, false);
|
createDetailedStructure(0x40d2b8, true, false);
|
||||||
|
|
||||||
goToListing(0x40d2b8, true);
|
goToListing(0x40d2b8, true);
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||||
@Test
|
@Test
|
||||||
public void testStructureEditorWithFlexArray() {
|
public void testStructureEditorWithFlexArray() {
|
||||||
|
|
||||||
createAlignedDetailedStructure(0x40d2b8, true);
|
createDetailedStructure(0x40d2b8, true, true);
|
||||||
|
|
||||||
goToListing(0x40d2b8, true);
|
goToListing(0x40d2b8, true);
|
||||||
|
|
||||||
|
@ -250,6 +250,29 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||||
captureProvider(StructureEditorProvider.class);
|
captureProvider(StructureEditorProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStructureEditBitfield() {
|
||||||
|
|
||||||
|
createDetailedStructure(0x40d2b8, false, true);
|
||||||
|
|
||||||
|
goToListing(0x40d2b8, true);
|
||||||
|
|
||||||
|
performAction("Edit Data Type", "DataPlugin", true);
|
||||||
|
|
||||||
|
ComponentProvider structureEditor = getProvider(StructureEditorProvider.class);
|
||||||
|
|
||||||
|
// get structure table and select a row
|
||||||
|
CompositeEditorPanel editorPanel =
|
||||||
|
(CompositeEditorPanel) getInstanceField("editorPanel", structureEditor);
|
||||||
|
JTable table = editorPanel.getTable();
|
||||||
|
selectRow(table, 4); // select byte:3 bitfield
|
||||||
|
|
||||||
|
performAction("Editor: Edit Bitfield", "DataTypeManagerPlugin", structureEditor, false);
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
captureDialog();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnionEditor() {
|
public void testUnionEditor() {
|
||||||
|
|
||||||
|
@ -295,12 +318,13 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||||
waitForBusyTool(tool);
|
waitForBusyTool(tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAlignedDetailedStructure(long address,
|
private void createDetailedStructure(long address, boolean aligned,
|
||||||
boolean includeBitFieldsAndFlexArray) {
|
boolean includeBitFieldsAndFlexArray) {
|
||||||
|
|
||||||
goToListing(address);
|
goToListing(address);
|
||||||
|
|
||||||
StructureDataType struct = new StructureDataType("MyAlignedStruct", 0);
|
StructureDataType struct = new StructureDataType("MyAlignedStruct", 0);
|
||||||
|
struct.setInternallyAligned(true); // allow proper default packing
|
||||||
struct.add(new ByteDataType(), "myByteElement", "alignment 1");
|
struct.add(new ByteDataType(), "myByteElement", "alignment 1");
|
||||||
struct.add(new ByteDataType(), "", "This is my undefined element");
|
struct.add(new ByteDataType(), "", "This is my undefined element");
|
||||||
struct.add(new WordDataType(), "myWordElement", "alignment 2");
|
struct.add(new WordDataType(), "myWordElement", "alignment 2");
|
||||||
|
@ -325,7 +349,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||||
(includeBitFieldsAndFlexArray ? "with bitfields and a flexible char array"
|
(includeBitFieldsAndFlexArray ? "with bitfields and a flexible char array"
|
||||||
: "according to their alignment size") +
|
: "according to their alignment size") +
|
||||||
". ");
|
". ");
|
||||||
struct.setInternallyAligned(true);
|
struct.setInternallyAligned(aligned);
|
||||||
|
|
||||||
CreateDataCmd createDataCmd = new CreateDataCmd(addr(address), struct);
|
CreateDataCmd createDataCmd = new CreateDataCmd(addr(address), struct);
|
||||||
tool.execute(createDataCmd, program);
|
tool.execute(createDataCmd, program);
|
||||||
|
|