BitFields - additional refinements and added help content

This commit is contained in:
ghidra1 2019-07-09 14:49:51 -04:00
parent 84a70220dd
commit 486ce82586
12 changed files with 233 additions and 65 deletions

View file

@ -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|

View file

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before After
Before After

View file

@ -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));
} }

View file

@ -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() {

View file

@ -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;
} }

View file

@ -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;
} }
/** /**

View file

@ -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, " ");

View file

@ -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);