mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
BitFields - added preliminary support for composite bitfields
This commit is contained in:
parent
c23ae691e2
commit
a7345527c9
209 changed files with 18617 additions and 6720 deletions
|
@ -163,6 +163,8 @@
|
|||
be specified.<BR>
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<H3>Unaligned Structures</H3>
|
||||
|
||||
|
@ -301,7 +303,9 @@
|
|||
<IMG alt="" src="images/UnionEditorAligned.png">
|
||||
</DIV>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Structure_Editor_Flex_Array"></A>Flexible Array Component</H2>
|
||||
|
||||
<P>A structure may be defined with a trailing flexible array component which corresponds to
|
||||
|
@ -321,7 +325,17 @@
|
|||
be reflected in decompilation results. Its primary purpose if to reflect the C source definition
|
||||
of a structure with correct alignment and structure sizing.</P>
|
||||
|
||||
<DIV style="text-align: center;">
|
||||
<P><IMG alt="Note:" src="../../shared/note.png"> The equivalent of having <SPAN style=
|
||||
"font-style: italic;">no C #pragma pack attribute</SPAN> on the structure or union is to
|
||||
choose <SPAN style="font-weight: bold;">none</SPAN>. The equivalent for a C code attribute of
|
||||
<SPAN style="font-style: italic;">#pragma pack()</SPAN> without a value is to specify a <SPAN
|
||||
style="font-weight: bold;">pack value</SPAN> of <SPAN style="font-weight: bold;">1</SPAN>.
|
||||
The equivalent of <SPAN style="font-style: italic;"># pragma</SPAN> <SPAN style=
|
||||
"font-style: italic;">pack(4)</SPAN> is to specify a <SPAN style="font-weight: bold;">pack
|
||||
value</SPAN> of 4.<BR>
|
||||
</P>
|
||||
|
||||
<DIV style="text-align: center;">
|
||||
<IMG alt="" src="images/StructureEditorWithFlexArray.png"><BR>
|
||||
<BR>
|
||||
</DIV>
|
||||
|
@ -334,6 +348,8 @@
|
|||
table. There are also short-cut keys associated with each of the edit actions.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Structure_Editor_Insert_Undefined_Byte"></A> <IMG src="images/Plus.png" alt="">
|
||||
Insert Undefined Byte</H3>
|
||||
|
||||
|
@ -557,6 +573,7 @@
|
|||
is created and a component containing it replaces the selected components.</P>
|
||||
</BLOCKQUOTE><BR>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2><A name="Structure_Editor_Component_Fields"></A>Component Fields</H2>
|
||||
|
||||
|
|
|
@ -23,16 +23,17 @@ import java.util.Map.Entry;
|
|||
import javax.swing.tree.TreePath;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.plugin.core.datamgr.archive.Archive;
|
||||
import ghidra.app.plugin.core.datamgr.archive.DuplicateIdException;
|
||||
import ghidra.app.plugin.core.datamgr.archive.*;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeArchiveUtility;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeComparator;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.DataTypeArchive;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.UniversalID;
|
||||
|
||||
class DefaultDataTypeManagerService implements DataTypeManagerService {
|
||||
// FIXME!! TESTING
|
||||
public class DefaultDataTypeManagerService implements DataTypeManagerService {
|
||||
|
||||
private Map<String, FileDataTypeManager> archiveMap = new HashMap<>();
|
||||
private DataTypeManager builtInDataTypesManager = BuiltInDataTypeManager.getDataTypeManager();
|
||||
|
@ -156,6 +157,9 @@ class DefaultDataTypeManagerService implements DataTypeManagerService {
|
|||
|
||||
@Override
|
||||
public DataType getDataType(TreePath selectedTreeNode) {
|
||||
if (selectedTreeNode == null) {
|
||||
return null;
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -171,7 +175,11 @@ class DefaultDataTypeManagerService implements DataTypeManagerService {
|
|||
|
||||
@Override
|
||||
public List<DataType> getSortedDataTypeList() {
|
||||
throw new UnsupportedOperationException();
|
||||
List<DataType> dataTypes =
|
||||
builtInDataTypesManager.getDataTypes(BuiltInSourceArchive.INSTANCE);
|
||||
dataTypes.sort(new DataTypeComparator());
|
||||
return dataTypes;
|
||||
// throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/* ###
|
||||
* 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.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.DockingWindowManager;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* Action for use in the composite data type editor.
|
||||
* This action has help associated with it.
|
||||
*/
|
||||
public class AddBitFieldAction extends CompositeEditorTableAction {
|
||||
|
||||
private final static String ACTION_NAME = "Add Bitfield";
|
||||
private final static String GROUP_NAME = BITFIELD_ACTION_GROUP;
|
||||
private final static String DESCRIPTION =
|
||||
"Add a bitfield at the position of a selected component";
|
||||
private static String[] popupPath = new String[] { ACTION_NAME };
|
||||
|
||||
public AddBitFieldAction(CompositeEditorProvider provider) {
|
||||
super(provider, EDIT_ACTION_PREFIX + ACTION_NAME, GROUP_NAME, popupPath, null, null);
|
||||
setDescription(DESCRIPTION);
|
||||
if (!(model instanceof CompEditorModel)) {
|
||||
throw new AssertException("unsupported use");
|
||||
}
|
||||
adjustEnablement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
|
||||
CompEditorModel editorModel = (CompEditorModel) model;
|
||||
if (editorModel.getNumSelectedRows() != 1 || editorModel.isFlexibleArraySelection()) {
|
||||
return;
|
||||
}
|
||||
int rowIndex = model.getSelectedRows()[0];
|
||||
|
||||
if (editorModel.isAligned()) {
|
||||
// Insert before selected component
|
||||
// ordinal based, user input needed:
|
||||
// 1. bitfield base datatype
|
||||
// 2. bitfield size
|
||||
// 3. bitfield name (can be renamed later)
|
||||
int ordinal = -1;
|
||||
DataType baseDataType = null;
|
||||
if (!editorModel.isAtEnd(rowIndex)) {
|
||||
DataTypeComponent component = editorModel.getComponent(rowIndex);
|
||||
ordinal = component.getOrdinal();
|
||||
if (component.isBitFieldComponent()) {
|
||||
BitFieldDataType currentBitfield = (BitFieldDataType) component.getDataType();
|
||||
baseDataType = currentBitfield.getBaseDataType();
|
||||
}
|
||||
}
|
||||
insertBitField(ordinal, baseDataType);
|
||||
}
|
||||
else {
|
||||
BitFieldEditorDialog dlg =
|
||||
new BitFieldEditorDialog(editorModel.viewComposite, provider.dtmService,
|
||||
-(rowIndex + 1), ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
||||
Component c = provider.getComponent();
|
||||
Window w = SwingUtilities.windowForComponent(c);
|
||||
DockingWindowManager.showDialog(w, dlg, c);
|
||||
}
|
||||
|
||||
requestTableFocus();
|
||||
}
|
||||
|
||||
private void refreshTableAndSelection(CompEditorModel editorModel, int ordinal) {
|
||||
editorModel.fireTableDataChanged();
|
||||
editorModel.compositeInfoChanged();
|
||||
JTable editorTable = provider.getTable();
|
||||
editorTable.getSelectionModel().setSelectionInterval(ordinal, ordinal);
|
||||
}
|
||||
|
||||
private void insertBitField(int ordinal, DataType baseDataType) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustEnablement() {
|
||||
boolean enabled = true;
|
||||
CompEditorModel editorModel = (CompEditorModel) model;
|
||||
if (editorModel.viewComposite == null || editorModel.getNumSelectedRows() != 1 ||
|
||||
editorModel.isFlexibleArraySelection()) {
|
||||
enabled = false;
|
||||
}
|
||||
setEnabled(enabled);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
/* ###
|
||||
* 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.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.*;
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.MenuData;
|
||||
import ghidra.GhidraApplicationLayout;
|
||||
import ghidra.app.plugin.core.analysis.DefaultDataTypeManagerService;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.framework.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||
|
||||
private static final Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png");
|
||||
private static final Icon EDIT_ICON = ResourceManager.loadImage("images/move.png");
|
||||
private static final Icon DELETE_ICON = ResourceManager.loadImage("images/edit-delete.png");
|
||||
|
||||
private DataTypeManagerService dtmService;
|
||||
private Composite composite;
|
||||
private CompositeChangeListener listener;
|
||||
|
||||
private BitFieldEditorPanel bitFieldEditorPanel; // for unaligned use case
|
||||
|
||||
BitFieldEditorDialog(Composite composite, DataTypeManagerService dtmService, int editOrdinal,
|
||||
CompositeChangeListener listener) {
|
||||
super("Edit " + getCompositeType(composite) + " Bitfield");
|
||||
this.composite = composite;
|
||||
this.listener = listener;
|
||||
this.dtmService = dtmService;
|
||||
addButtons();
|
||||
addWorkPanel(buildWorkPanel(editOrdinal));
|
||||
setRememberLocation(false);
|
||||
setRememberSize(false);
|
||||
|
||||
addActions();
|
||||
}
|
||||
|
||||
private void addButtons() {
|
||||
addOKButton();
|
||||
addCancelButton();
|
||||
if (composite instanceof Structure) {
|
||||
addApplyButton();
|
||||
setApplyEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static DataTypeComponent getEditComponent(ActionContext context, boolean bitFieldOnly) {
|
||||
if (!(context instanceof BitFieldEditorPanel.BitFieldEditorContext)) {
|
||||
return null;
|
||||
}
|
||||
BitFieldEditorPanel.BitFieldEditorContext editorContext =
|
||||
(BitFieldEditorPanel.BitFieldEditorContext) context;
|
||||
DataTypeComponent dtc = editorContext.getSelectedComponent();
|
||||
if (dtc != null && (!bitFieldOnly || dtc.isBitFieldComponent())) {
|
||||
return dtc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class EditBitFieldAction extends DockingAction {
|
||||
|
||||
EditBitFieldAction() {
|
||||
super("Edit Bitfield", "BitFieldEditorDialog");
|
||||
setPopupMenuData(new MenuData(new String[] { getName() }, EDIT_ICON));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
DataTypeComponent bitfieldDtc = getEditComponent(context, true);
|
||||
if (bitfieldDtc == null || !bitFieldEditorPanel.endCurrentEdit()) {
|
||||
return;
|
||||
}
|
||||
initEdit(bitfieldDtc.getOrdinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
return getEditComponent(context, true) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private class AddBitFieldAction extends DockingAction {
|
||||
|
||||
AddBitFieldAction() {
|
||||
super("Add Bitfield", "BitFieldEditorDialog");
|
||||
setPopupMenuData(new MenuData(new String[] { getName() }, ADD_ICON));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
if (!bitFieldEditorPanel.endCurrentEdit()) {
|
||||
return;
|
||||
}
|
||||
BitFieldEditorPanel.BitFieldEditorContext editorContext =
|
||||
(BitFieldEditorPanel.BitFieldEditorContext) context;
|
||||
|
||||
bitFieldEditorPanel.initAdd(null, editorContext.getAllocationOffset(),
|
||||
editorContext.getSelectedBitOffset(), true);
|
||||
setApplyEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
return (context instanceof BitFieldEditorPanel.BitFieldEditorContext) &&
|
||||
!bitFieldEditorPanel.isAdding();
|
||||
}
|
||||
}
|
||||
|
||||
private class DeleteComponentAction extends DockingAction {
|
||||
|
||||
DeleteComponentAction() {
|
||||
super("Delete Component", "BitFieldEditorDialog");
|
||||
setPopupMenuData(new MenuData(new String[] { getName() }, DELETE_ICON));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
DataTypeComponent bitfieldDtc = getEditComponent(context, false);
|
||||
if (bitfieldDtc == null) {
|
||||
return;
|
||||
}
|
||||
int ordinal = bitfieldDtc.getOrdinal();
|
||||
composite.delete(ordinal);
|
||||
bitFieldEditorPanel.componentDeleted(ordinal);
|
||||
if (listener != null) {
|
||||
listener.componentChanged(ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
return getEditComponent(context, false) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addActions() {
|
||||
addAction(new AddBitFieldAction());
|
||||
addAction(new EditBitFieldAction());
|
||||
addAction(new DeleteComponentAction());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyCallback() {
|
||||
if (bitFieldEditorPanel.isEditing() && bitFieldEditorPanel.apply(listener)) {
|
||||
setApplyEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void okCallback() {
|
||||
applyCallback();
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionContext getActionContext(MouseEvent event) {
|
||||
ActionContext context = bitFieldEditorPanel.getActionContext(event);
|
||||
if (context != null) {
|
||||
return context;
|
||||
}
|
||||
return super.getActionContext(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cancelCallback() {
|
||||
// TODO: Should we cancel without asking?
|
||||
if (!bitFieldEditorPanel.endCurrentEdit()) {
|
||||
return;
|
||||
}
|
||||
super.cancelCallback();
|
||||
}
|
||||
|
||||
private JComponent buildWorkPanel(int editOrdinal) {
|
||||
bitFieldEditorPanel = new BitFieldEditorPanel(composite, dtmService);
|
||||
if (editOrdinal < 0) {
|
||||
initAdd(-editOrdinal - 1);
|
||||
}
|
||||
else {
|
||||
initEdit(editOrdinal);
|
||||
}
|
||||
return bitFieldEditorPanel;
|
||||
}
|
||||
|
||||
private static String getCompositeType(Composite composite) {
|
||||
// currently supports unaligned case only!
|
||||
if (composite.isInternallyAligned()) {
|
||||
throw new IllegalArgumentException("Aligned use not supported");
|
||||
}
|
||||
String alignmentMode = composite.isInternallyAligned() ? "Aligned" : "Unaligned";
|
||||
String type = (composite instanceof Union) ? "Union" : "Structure";
|
||||
return alignmentMode + " " + type;
|
||||
}
|
||||
|
||||
private void initAdd(int ordinal) {
|
||||
DataType baseDataType = null;
|
||||
int offset = 0;
|
||||
if (ordinal < composite.getNumComponents()) {
|
||||
DataTypeComponent dtc = composite.getComponent(ordinal);
|
||||
offset = dtc.getOffset();
|
||||
if (dtc.isBitFieldComponent()) {
|
||||
baseDataType = ((BitFieldDataType) dtc.getDataType()).getBaseDataType();
|
||||
}
|
||||
}
|
||||
else if (!composite.isNotYetDefined()) {
|
||||
offset = composite.getLength();
|
||||
}
|
||||
|
||||
// use previous or default base datatype
|
||||
bitFieldEditorPanel.initAdd(baseDataType, offset, 0, false);
|
||||
setApplyEnabled(true);
|
||||
}
|
||||
|
||||
private void initEdit(int editOrdinal) throws ArrayIndexOutOfBoundsException {
|
||||
DataTypeComponent dtc = composite.getComponent(editOrdinal);
|
||||
if (!dtc.isBitFieldComponent()) {
|
||||
throw new IllegalArgumentException("editOrdinal does not correspond to bitfield");
|
||||
}
|
||||
bitFieldEditorPanel.initEdit(dtc, getPreferredAllocationOffset(dtc), false);
|
||||
setApplyEnabled(true);
|
||||
}
|
||||
|
||||
private int getPreferredAllocationOffset(DataTypeComponent bitfieldDtc) {
|
||||
if (composite instanceof Union) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt = (BitFieldDataType) bitfieldDtc.getDataType();
|
||||
int offset = bitfieldDtc.getOffset();
|
||||
int baseTypeSize = bitfieldDt.getBaseTypeSize();
|
||||
if (bitfieldDtc.getLength() >= baseTypeSize) {
|
||||
return offset; // do not adjust
|
||||
}
|
||||
|
||||
DataOrganization dataOrganization = composite.getDataOrganization();
|
||||
|
||||
// Assume a reasonable alignment in identifying aligned offset
|
||||
int alignment = CompositeAlignmentHelper.getPackedAlignment(dataOrganization,
|
||||
Composite.NOT_PACKING, bitfieldDt.getBaseDataType(), bitfieldDt.getBaseTypeSize());
|
||||
|
||||
int adjustedOffset = offset - (offset % alignment);
|
||||
|
||||
// only adjust if bitfield fits within aligned offset
|
||||
if (bitfieldDtc.getEndOffset() <= (adjustedOffset + baseTypeSize - 1)) {
|
||||
return adjustedOffset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
//UniversalIdGenerator.initialize();
|
||||
ApplicationConfiguration configuration = new HeadlessGhidraApplicationConfiguration();
|
||||
configuration.setInitializeLogging(false);
|
||||
Application.initializeApplication(new GhidraApplicationLayout(), configuration);
|
||||
|
||||
Structure s = new StructureDataType("Foo", 0);
|
||||
DataTypeComponent dtcA =
|
||||
s.insertBitFieldAt(0, 4, 16, IntegerDataType.dataType, 4, "BitA", null);
|
||||
DataTypeComponent dtcZ =
|
||||
s.insertBitFieldAt(0, 4, 16, IntegerDataType.dataType, 0, "BitZ", null);
|
||||
DataTypeComponent dtcB =
|
||||
s.insertBitFieldAt(0, 4, 12, IntegerDataType.dataType, 4, "BitB", null);
|
||||
DataTypeComponent dtcC =
|
||||
s.insertBitFieldAt(0, 4, 4, IntegerDataType.dataType, 4, "BitC", null);
|
||||
|
||||
DockingWindowManager winMgr = new DockingWindowManager("TEST", null, null);
|
||||
|
||||
BitFieldEditorDialog dlg =
|
||||
new BitFieldEditorDialog(s, new DefaultDataTypeManagerService(), -1, null);
|
||||
|
||||
SystemUtilities.runSwingNow(() -> {
|
||||
winMgr.setVisible(true);
|
||||
DockingWindowManager.showDialog(null, dlg);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,581 @@
|
|||
/* ###
|
||||
* 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.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.CellEditorListener;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.widgets.DropDownSelectionTextField;
|
||||
import docking.widgets.OptionDialog;
|
||||
import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitAttributes;
|
||||
import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitFieldAllocation;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
||||
import ghidra.app.util.datatype.NavigationDirection;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||
import ghidra.util.layout.*;
|
||||
import resources.ResourceManager;
|
||||
|
||||
/**
|
||||
* <code>BitFieldEditorPanel</code> provides the ability to place bitfields
|
||||
* within unaligned structures and unions.
|
||||
*/
|
||||
public class BitFieldEditorPanel extends JPanel {
|
||||
|
||||
private static final Icon DECREMENT_ICON = ResourceManager.loadImage("images/Minus.png");
|
||||
private static final Icon INCREMENT_ICON = ResourceManager.loadImage("images/Plus.png");
|
||||
|
||||
private static final String ENTRY_ERROR_DIALOG_TITLE = "Bitfield Entry Error";
|
||||
|
||||
private DataTypeManagerService dtmService;
|
||||
private Composite composite;
|
||||
|
||||
private JLabel allocationOffsetLabel;
|
||||
JButton decrementButton;
|
||||
JButton incrementButton;
|
||||
|
||||
private BitFieldPlacementComponent placementComponent;
|
||||
private DataType baseDataType;
|
||||
|
||||
private DataTypeSelectionEditor dtChoiceEditor;
|
||||
private JTextField fieldNameTextField;
|
||||
private SpinnerNumberModel allocSizeModel;
|
||||
private JSpinnerWithMouseWheel allocSizeInput;
|
||||
private SpinnerNumberModel bitOffsetModel;
|
||||
private JSpinnerWithMouseWheel bitOffsetInput;
|
||||
private SpinnerNumberModel bitSizeModel;
|
||||
private JSpinnerWithMouseWheel bitSizeInput;
|
||||
|
||||
private boolean updating = false;
|
||||
|
||||
BitFieldEditorPanel(Composite composite, DataTypeManagerService dtmService) {
|
||||
super();
|
||||
this.composite = composite;
|
||||
|
||||
if (composite.isInternallyAligned()) {
|
||||
// A different bitfield editor should be used for aligned composites
|
||||
throw new IllegalArgumentException("composite must be unaligned");
|
||||
}
|
||||
|
||||
setLayout(new VerticalLayout(5));
|
||||
setFocusTraversalKeysEnabled(true);
|
||||
|
||||
this.dtmService = dtmService;
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
|
||||
createPlacementPanel();
|
||||
|
||||
if (composite instanceof Structure) {
|
||||
add(createAllocationOffsetPanel());
|
||||
}
|
||||
add(placementComponent);
|
||||
add(createEntryPanel());
|
||||
|
||||
enableControls(false);
|
||||
}
|
||||
|
||||
private JPanel createAllocationOffsetPanel() {
|
||||
|
||||
JPanel panel = new JPanel(new HorizontalLayout(5));
|
||||
|
||||
decrementButton = new JButton(DECREMENT_ICON);
|
||||
decrementButton.setFocusable(false);
|
||||
decrementButton.setToolTipText("Decrement allocation unit offset");
|
||||
decrementButton.addActionListener(e -> adjustAllocationOffset(-1));
|
||||
panel.add(decrementButton);
|
||||
|
||||
incrementButton = new JButton(INCREMENT_ICON);
|
||||
incrementButton.setFocusable(false);
|
||||
incrementButton.setToolTipText("Increment allocation unit offset");
|
||||
incrementButton.addActionListener(e -> adjustAllocationOffset(1));
|
||||
panel.add(incrementButton);
|
||||
|
||||
allocationOffsetLabel = new JLabel();
|
||||
allocationOffsetLabel.setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
panel.add(allocationOffsetLabel);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void adjustAllocationOffset(int delta) {
|
||||
int adjustedOffset = placementComponent.getAllocationOffset() + delta;
|
||||
if (adjustedOffset < 0 || adjustedOffset > composite.getLength()) {
|
||||
return;
|
||||
}
|
||||
placementComponent.setAllocationOffset(adjustedOffset);
|
||||
updateAllocationOffsetLabel();
|
||||
}
|
||||
|
||||
private void updateAllocationOffsetLabel() {
|
||||
if (composite instanceof Structure) {
|
||||
String text =
|
||||
"Structure Offset of Allocation Unit: " + placementComponent.getAllocationOffset();
|
||||
allocationOffsetLabel.setText(text);
|
||||
|
||||
int offset = placementComponent.getAllocationOffset();
|
||||
decrementButton.setEnabled(offset > 0);
|
||||
int length = composite.isNotYetDefined() ? 0 : composite.getLength();
|
||||
incrementButton.setEnabled(offset < length);
|
||||
}
|
||||
}
|
||||
|
||||
private JPanel createEntryPanel() {
|
||||
|
||||
JComponent baseDataTypeEditor = createDataTypeChoiceEditor();
|
||||
|
||||
fieldNameTextField = new JTextField(20);
|
||||
fieldNameTextField.setFocusable(true);
|
||||
|
||||
allocSizeModel = new SpinnerNumberModel(Long.valueOf(4), Long.valueOf(1), Long.valueOf(16),
|
||||
Long.valueOf(1));
|
||||
allocSizeInput = new JSpinnerWithMouseWheel(allocSizeModel);
|
||||
|
||||
bitOffsetModel = new SpinnerNumberModel(Long.valueOf(0), Long.valueOf(0), Long.valueOf(31),
|
||||
Long.valueOf(1));
|
||||
bitOffsetInput = new JSpinnerWithMouseWheel(bitOffsetModel);
|
||||
|
||||
bitSizeModel = new SpinnerNumberModel(Long.valueOf(4), Long.valueOf(0), Long.valueOf(4 * 8),
|
||||
Long.valueOf(1));
|
||||
bitSizeInput = new JSpinnerWithMouseWheel(bitSizeModel);
|
||||
|
||||
allocSizeModel.addChangeListener(e -> update());
|
||||
bitSizeModel.addChangeListener(e -> update());
|
||||
bitOffsetModel.addChangeListener(e -> update());
|
||||
|
||||
JPanel entryPanel = new JPanel(new TwoColumnPairLayout(5, 15, 5, 0));
|
||||
entryPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(),
|
||||
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
|
||||
entryPanel.setFocusCycleRoot(true);
|
||||
|
||||
entryPanel.add(new JLabel("Base Datatype:"));
|
||||
entryPanel.add(baseDataTypeEditor);
|
||||
|
||||
entryPanel.add(new JLabel("Allocation Bytes:"));
|
||||
entryPanel.add(allocSizeInput);
|
||||
|
||||
entryPanel.add(new JLabel("Field Name:"));
|
||||
entryPanel.add(fieldNameTextField);
|
||||
|
||||
entryPanel.add(new JLabel("Bit Size:"));
|
||||
entryPanel.add(bitSizeInput);
|
||||
|
||||
entryPanel.add(new JPanel());
|
||||
entryPanel.add(new JPanel());
|
||||
|
||||
entryPanel.add(new JLabel("Bit Offset:"));
|
||||
entryPanel.add(bitOffsetInput);
|
||||
return entryPanel;
|
||||
}
|
||||
|
||||
private JComponent createDataTypeChoiceEditor() {
|
||||
|
||||
dtChoiceEditor = new DataTypeSelectionEditor(dtmService, -1, AllowedDataTypes.BITFIELD_USE);
|
||||
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
||||
dtChoiceEditor.setTabCommitsEdit(true);
|
||||
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
||||
|
||||
final DropDownSelectionTextField<DataType> dtChoiceTextField =
|
||||
dtChoiceEditor.getDropDownTextField();
|
||||
dtChoiceTextField.setBorder(UIManager.getBorder("TextField.border"));
|
||||
|
||||
dtChoiceEditor.addCellEditorListener(new CellEditorListener() {
|
||||
@Override
|
||||
public void editingCanceled(ChangeEvent e) {
|
||||
dtChoiceEditor.setCellEditorValue(baseDataType); // restore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editingStopped(ChangeEvent e) {
|
||||
if (!checkValidBaseDataType()) {
|
||||
dtChoiceTextField.selectAll();
|
||||
}
|
||||
else {
|
||||
baseDataType = dtChoiceEditor.getCellEditorValueAsDataType();
|
||||
if (baseDataType != null) {
|
||||
baseDataType = baseDataType.clone(composite.getDataTypeManager());
|
||||
}
|
||||
updateBitSizeModel();
|
||||
NavigationDirection direction = dtChoiceEditor.getNavigationDirection();
|
||||
if (direction == NavigationDirection.FORWARD) {
|
||||
allocSizeInput.requestFocus();
|
||||
}
|
||||
else if (direction == NavigationDirection.BACKWARD) {
|
||||
bitOffsetInput.requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dtChoiceEditor.getBrowseButton().setFocusable(false);
|
||||
|
||||
JComponent editorComponent = dtChoiceEditor.getEditorComponent();
|
||||
Dimension preferredSize = editorComponent.getPreferredSize();
|
||||
editorComponent.setPreferredSize(new Dimension(200, preferredSize.height));
|
||||
return editorComponent;
|
||||
}
|
||||
|
||||
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"));
|
||||
placementComponent.addMouseWheelListener(e -> bitSizeInput.mouseWheelMoved(e));
|
||||
|
||||
placementComponent.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1 &&
|
||||
bitOffsetInput.isEnabled()) {
|
||||
setBitFieldOffset(e.getPoint());
|
||||
}
|
||||
// if (e.getClickCount() == 2 && endCurrentEdit() &&
|
||||
// editBitFieldComponent(e.getPoint())) {
|
||||
// enableControls(true);
|
||||
// }
|
||||
}
|
||||
// public void mousePressed(MouseEvent e) {
|
||||
// if (e.isPopupTrigger()) {
|
||||
// setBitFieldPopupContext(e.getPoint());
|
||||
// }
|
||||
// };
|
||||
});
|
||||
|
||||
JScrollPane scrollPane =
|
||||
new JScrollPane(placementComponent, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
scrollPane.getViewport().setBackground(getBackground());
|
||||
|
||||
midPanel.add(scrollPane);
|
||||
return midPanel;
|
||||
}
|
||||
|
||||
private boolean checkValidBaseDataType() {
|
||||
DropDownSelectionTextField<DataType> textField = dtChoiceEditor.getDropDownTextField();
|
||||
String dtName = textField.getText().trim();
|
||||
try {
|
||||
if (dtName.length() == 0 || !dtChoiceEditor.validateUserSelection()) {
|
||||
Msg.showError(BitFieldEditorPanel.class, textField, ENTRY_ERROR_DIALOG_TITLE,
|
||||
"Valid bitfield base datatype entry required");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
Msg.showError(BitFieldEditorPanel.class, textField, ENTRY_ERROR_DIALOG_TITLE,
|
||||
"Invalid bitfield base datatype: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void initAdd(DataType initialBaseDataType, int allocationOffset, int bitOffset,
|
||||
boolean useCurrentAllocation) {
|
||||
if (initialBaseDataType == null) {
|
||||
initialBaseDataType = baseDataType;
|
||||
}
|
||||
if (!BitFieldDataType.isValidBaseDataType(initialBaseDataType)) {
|
||||
initialBaseDataType = IntegerDataType.dataType.clone(composite.getDataTypeManager());
|
||||
}
|
||||
placementComponent.setAllocationOffset(allocationOffset);
|
||||
long allocationSize = useCurrentAllocation ? (Long) allocSizeModel.getValue()
|
||||
: initialBaseDataType.getLength();
|
||||
placementComponent.initAdd((int) allocationSize, 1, bitOffset);
|
||||
initControls(null, initialBaseDataType);
|
||||
enableControls(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize for edit of existing component or no component if bitfieldDtc is null.
|
||||
* If null an allocation size of 4-bytes will be used but may be adjusted.
|
||||
* @param bitfieldDtc bitfield component or null
|
||||
* @param allocationOffset allocation offset to be used
|
||||
* @param useCurrentAllocation retain current allocation size, otherwise
|
||||
* use size of base datatype.
|
||||
*/
|
||||
void initEdit(DataTypeComponent bitfieldDtc, int allocationOffset,
|
||||
boolean useCurrentAllocation) {
|
||||
String initialFieldName = null;
|
||||
DataType initialBaseDataType = null;
|
||||
int allocationSize = -1;
|
||||
BitFieldAllocation bitFieldAllocation = placementComponent.getBitFieldAllocation();
|
||||
if (bitFieldAllocation != null) {
|
||||
allocationSize = bitFieldAllocation.getAllocationByteSize();
|
||||
}
|
||||
if (bitfieldDtc != null) {
|
||||
if (!bitfieldDtc.isBitFieldComponent()) {
|
||||
throw new IllegalArgumentException("unsupport data type component");
|
||||
}
|
||||
initialFieldName = bitfieldDtc.getFieldName();
|
||||
BitFieldDataType bitfieldDt = (BitFieldDataType) bitfieldDtc.getDataType();
|
||||
initialBaseDataType = bitfieldDt.getBaseDataType();
|
||||
if (!useCurrentAllocation || allocationSize < 1) {
|
||||
allocationSize = initialBaseDataType.getLength();
|
||||
}
|
||||
}
|
||||
if (allocationSize < 1) {
|
||||
allocationSize = 4;
|
||||
}
|
||||
// TODO: adjust offset and allocationSize if needed
|
||||
placementComponent.setAllocationOffset(allocationOffset);
|
||||
placementComponent.init(allocationSize, bitfieldDtc);
|
||||
initControls(initialFieldName, initialBaseDataType);
|
||||
enableControls(bitfieldDtc != null);
|
||||
}
|
||||
|
||||
void componentDeleted(int ordinal) {
|
||||
placementComponent.componentDeleted(ordinal);
|
||||
}
|
||||
|
||||
private void initControls(String initialFieldName, DataType initialBaseDataType) {
|
||||
updating = true;
|
||||
try {
|
||||
baseDataType = initialBaseDataType;
|
||||
dtChoiceEditor.setCellEditorValue(initialBaseDataType);
|
||||
fieldNameTextField.setText(initialFieldName);
|
||||
|
||||
// Use current placementComponent to obtain initial values
|
||||
BitFieldAllocation bitFieldAllocation = placementComponent.getBitFieldAllocation();
|
||||
allocSizeModel.setValue((long) bitFieldAllocation.getAllocationByteSize());
|
||||
int allocBits = 8 * bitFieldAllocation.getAllocationByteSize();
|
||||
bitSizeModel.setValue(1L);
|
||||
bitOffsetModel.setMaximum((long) allocBits - 1);
|
||||
bitOffsetModel.setValue((long) bitFieldAllocation.getBitOffset());
|
||||
updateBitSizeModel();
|
||||
|
||||
updateAllocationOffsetLabel();
|
||||
}
|
||||
finally {
|
||||
updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if actively editing or adding a bitfield
|
||||
*/
|
||||
boolean isEditing() {
|
||||
return placementComponent.isEditing();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if actively adding a bitfield
|
||||
*/
|
||||
boolean isAdding() {
|
||||
return placementComponent.isAdding();
|
||||
}
|
||||
|
||||
boolean endCurrentEdit() {
|
||||
if (placementComponent.isEditing()) {
|
||||
String currentOp = placementComponent.isAdding() ? "add" : "edit";
|
||||
int option = OptionDialog.showYesNoDialog(this, "Confirm Edit Action",
|
||||
"Cancel current bitfield " + currentOp + " operation?");
|
||||
if (option != OptionDialog.YES_OPTION) {
|
||||
return false;
|
||||
}
|
||||
placementComponent.cancelEdit();
|
||||
enableControls(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean apply(CompositeChangeListener listener) {
|
||||
boolean deleteConflicts = false;
|
||||
if (placementComponent.hasApplyConflict()) {
|
||||
long allocationSize = (Long) allocSizeModel.getValue();
|
||||
int option = OptionDialog.showOptionDialog(this, "Bitfield Conflict(s)",
|
||||
"Bitfield placement conflicts with one or more components.\n" +
|
||||
"Would you like to delete conflicts or move conflicts by " + allocationSize +
|
||||
" bytes?",
|
||||
"Delete Conflicts", "Move Conflicts", OptionDialog.WARNING_MESSAGE);
|
||||
if (option == OptionDialog.CANCEL_OPTION) {
|
||||
return false;
|
||||
}
|
||||
deleteConflicts = (option == OptionDialog.OPTION_ONE);
|
||||
}
|
||||
placementComponent.applyBitField(baseDataType, fieldNameTextField.getText().trim(),
|
||||
deleteConflicts, listener);
|
||||
enableControls(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void enableControls(boolean enable) {
|
||||
allocSizeInput.setEnabled(enable);
|
||||
bitSizeInput.setEnabled(enable);
|
||||
bitOffsetInput.setEnabled(enable);
|
||||
if (!enable) {
|
||||
// TODO: set placementComponent mode to NONE
|
||||
bitOffsetModel.setValue(0L);
|
||||
bitSizeModel.setValue(1L);
|
||||
fieldNameTextField.setText(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void setBitFieldOffset(Point point) {
|
||||
int bitOffset = placementComponent.getBitOffset(point);
|
||||
if (bitOffset >= 0) {
|
||||
// long cast is required for auto-box to Long object
|
||||
bitOffsetModel.setValue((long) bitOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private DataTypeComponent getDataTypeComponent(Point p) {
|
||||
BitAttributes attrs = placementComponent.getBitAttributes(p);
|
||||
if (attrs != null) {
|
||||
return attrs.getDataTypeComponent(true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateBitSizeModel() {
|
||||
int allocSize = allocSizeModel.getNumber().intValue();
|
||||
int allocBits = 8 * allocSize;
|
||||
int baseTypeBits = baseDataType != null ? (8 * baseDataType.getLength()) : allocBits;
|
||||
long maxBitSize = Math.min(allocBits, baseTypeBits);
|
||||
bitSizeModel.setMaximum(maxBitSize);
|
||||
if (maxBitSize < (Long) bitSizeModel.getValue()) {
|
||||
bitSizeModel.setValue(maxBitSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (updating) {
|
||||
return;
|
||||
}
|
||||
updating = true;
|
||||
try {
|
||||
int allocSize = allocSizeModel.getNumber().intValue();
|
||||
int allocBits = 8 * allocSize;
|
||||
updateBitSizeModel();
|
||||
bitOffsetModel.setMaximum(Long.valueOf(allocBits - 1));
|
||||
int bitSize = bitSizeModel.getNumber().intValue();
|
||||
|
||||
int boff = bitOffsetModel.getNumber().intValue();
|
||||
int total = bitSize + boff;
|
||||
if (total > allocBits) {
|
||||
boff -= total - allocBits;
|
||||
if (boff < 0) {
|
||||
boff = 0;
|
||||
}
|
||||
}
|
||||
if (bitSize == 0) {
|
||||
// force preferred placement of zero-length bit-field
|
||||
// little-endian: lsb of byte
|
||||
// big-endian: msb of byte
|
||||
boff = 8 * (boff / 8);
|
||||
if (placementComponent.isBigEndian()) {
|
||||
boff += 7;
|
||||
}
|
||||
bitOffsetModel.setStepSize((long) 8);
|
||||
}
|
||||
else {
|
||||
bitOffsetModel.setStepSize((long) 1);
|
||||
}
|
||||
bitOffsetModel.setValue(Long.valueOf(boff));
|
||||
if (bitSize > allocBits) {
|
||||
bitSize = allocBits;
|
||||
bitSizeModel.setValue(Long.valueOf(bitSize));
|
||||
}
|
||||
placementComponent.refresh(allocSize, bitSize, boff);
|
||||
}
|
||||
finally {
|
||||
updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
ActionContext getActionContext(MouseEvent event) {
|
||||
if (placementComponent == event.getSource()) {
|
||||
Point p = event.getPoint();
|
||||
return new BitFieldEditorContext(getDataTypeComponent(p),
|
||||
placementComponent.getBitOffset(p));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
class BitFieldEditorContext extends ActionContext {
|
||||
|
||||
private int selectedBitOffset;
|
||||
private DataTypeComponent selectedDtc;
|
||||
|
||||
private BitFieldEditorContext(DataTypeComponent selectedDtc, int selectedBitOffset) {
|
||||
this.selectedDtc = selectedDtc;
|
||||
this.selectedBitOffset = selectedBitOffset;
|
||||
}
|
||||
|
||||
DataTypeComponent getSelectedComponent() {
|
||||
return selectedDtc;
|
||||
}
|
||||
|
||||
public int getAllocationOffset() {
|
||||
return placementComponent.getAllocationOffset();
|
||||
}
|
||||
|
||||
public int getSelectedBitOffset() {
|
||||
return selectedBitOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class JSpinnerWithMouseWheel extends JSpinner implements MouseWheelListener {
|
||||
|
||||
JSpinnerWithMouseWheel(SpinnerNumberModel model) {
|
||||
super(model);
|
||||
addMouseWheelListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestFocus() {
|
||||
DefaultEditor editor = (DefaultEditor) getEditor();
|
||||
editor.getTextField().requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent mwe) {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (mwe.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) {
|
||||
return;
|
||||
}
|
||||
SpinnerNumberModel m = (SpinnerNumberModel) getModel();
|
||||
if (mwe.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) {
|
||||
// TODO: Handle other mouse wheel modes
|
||||
return;
|
||||
}
|
||||
Long value =
|
||||
mwe.getUnitsToScroll() > 0 ? (Long) m.getPreviousValue() : (Long) m.getNextValue();
|
||||
if (value != null) {
|
||||
setValue(value);
|
||||
mwe.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,746 @@
|
|||
/* ###
|
||||
* 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.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ToolTipManager;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.Composite;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
public class BitFieldPlacementComponent extends JPanel {
|
||||
|
||||
private static final int CELL_HEIGHT = 30;
|
||||
private static final int BIT_WIDTH = 10;
|
||||
private static final int ZERO_BIT_WIDTH = 3;
|
||||
private static final int BIT_SEPARATOR_THICKNESS = 1;
|
||||
private static final int BYTE_SEPARATOR_THICKNESS = 2;
|
||||
private static final int BYTE_WIDTH = 8 * (BIT_WIDTH + BIT_SEPARATOR_THICKNESS);
|
||||
private static final int SCROLLBAR_THICKNESS = 10;
|
||||
private static final int MY_HEIGHT = (2 * CELL_HEIGHT) + (3 * BYTE_SEPARATOR_THICKNESS);
|
||||
|
||||
private static final Color TEXT_COLOR = Color.black;
|
||||
private static final Color LINE_COLOR = Color.black;
|
||||
private static final Color BYTE_HEADER_COLOR = new Color(0xdfdfdf);
|
||||
private static final Color UNDEFINED_BIT_COLOR = new Color(0xe8e8e8);
|
||||
private static final Color BITFIELD_BITS_COLOR = Color.green;
|
||||
private static final Color CONFLICT_BITS_COLOR = Color.yellow;
|
||||
private static final Color BITFIELD_COMPONENT_COLOR = new Color(0xcfcfff);
|
||||
private static final Color NON_BITFIELD_COMPONENT_COLOR = new Color(0xafafff);
|
||||
private static final Color INTERIOR_LINE_COLOR = new Color(0xbfbfbf);
|
||||
|
||||
private final Composite composite;
|
||||
private final boolean bigEndian;
|
||||
|
||||
private int allocationOffset;
|
||||
private BitFieldAllocation bitFieldAllocation;
|
||||
|
||||
private EditMode editMode = EditMode.NONE;
|
||||
private int editOrdinal = -1; // FIXME: improve insert use
|
||||
|
||||
BitFieldPlacementComponent(Composite composite) {
|
||||
this.composite = composite;
|
||||
bigEndian = composite.getDataOrganization().isBigEndian();
|
||||
updatePreferredSize();
|
||||
setSize(getPreferredSize());
|
||||
setMinimumSize(getPreferredSize());
|
||||
ToolTipManager.sharedInstance().registerComponent(this);
|
||||
}
|
||||
|
||||
private int getPreferredHeight() {
|
||||
return MY_HEIGHT + SCROLLBAR_THICKNESS;
|
||||
}
|
||||
|
||||
private int getPreferredWidth() {
|
||||
if (bitFieldAllocation == null) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
int extraLineSpace = BYTE_SEPARATOR_THICKNESS - BIT_SEPARATOR_THICKNESS;
|
||||
return (bitFieldAllocation.allocationByteSize * BYTE_WIDTH) + BYTE_SEPARATOR_THICKNESS +
|
||||
extraLineSpace;
|
||||
}
|
||||
|
||||
public boolean isBigEndian() {
|
||||
return bigEndian;
|
||||
}
|
||||
|
||||
public BitFieldAllocation getBitFieldAllocation() {
|
||||
return bitFieldAllocation;
|
||||
}
|
||||
|
||||
int getBitOffset(Point point) {
|
||||
int bitWidthWithLine = BIT_WIDTH + BIT_SEPARATOR_THICKNESS;
|
||||
int cellIndex = (point.x - BYTE_SEPARATOR_THICKNESS) / bitWidthWithLine;
|
||||
return (8 * bitFieldAllocation.allocationByteSize) - cellIndex - 1;
|
||||
}
|
||||
|
||||
private void updatePreferredSize() {
|
||||
setPreferredSize(new Dimension(getPreferredWidth(), getPreferredHeight()));
|
||||
revalidate();
|
||||
}
|
||||
|
||||
void refresh(int allocationByteSize, int bitSize, int bitOffset) {
|
||||
bitFieldAllocation = new BitFieldAllocation(allocationByteSize, bitSize, bitOffset);
|
||||
updatePreferredSize();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void setAllocationOffset(int allocationOffset) {
|
||||
this.allocationOffset = allocationOffset;
|
||||
if (bitFieldAllocation != null) {
|
||||
bitFieldAllocation.refresh();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
int getAllocationOffset() {
|
||||
return allocationOffset;
|
||||
}
|
||||
|
||||
void initAdd(int allocationByteSize, int bitSize, int bitOffset) {
|
||||
editMode = EditMode.ADD;
|
||||
editOrdinal = -1;
|
||||
refresh(allocationByteSize, bitSize, bitOffset);
|
||||
}
|
||||
|
||||
void init(int allocationByteSize, DataTypeComponent editComponent) {
|
||||
|
||||
if (editComponent == null) {
|
||||
editMode = EditMode.NONE;
|
||||
editOrdinal = -1;
|
||||
refresh(allocationByteSize, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: consider showing a animated hashed-box around original bit boundary
|
||||
// of the component being modified
|
||||
|
||||
editMode = EditMode.EDIT;
|
||||
editOrdinal = editComponent.getOrdinal();
|
||||
|
||||
BitFieldPlacement placement = new BitFieldPlacement(editComponent, allocationByteSize);
|
||||
bitFieldAllocation =
|
||||
new BitFieldAllocation(allocationByteSize, placement.rightBit - placement.leftBit + 1,
|
||||
(8 * allocationByteSize) - placement.rightBit - 1);
|
||||
updatePreferredSize();
|
||||
repaint();
|
||||
}
|
||||
|
||||
boolean hasApplyConflict() {
|
||||
if (composite instanceof Union) {
|
||||
return false;
|
||||
}
|
||||
for (BitAttributes attrs : bitFieldAllocation.bitAttributes) {
|
||||
if (attrs.hasConflict() && (attrs.isAddBitField() || attrs.isEditField())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if editing or adding a bitfield
|
||||
*/
|
||||
boolean isEditing() {
|
||||
return editMode != EditMode.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if adding a bitfield
|
||||
*/
|
||||
boolean isAdding() {
|
||||
return editMode == EditMode.ADD;
|
||||
}
|
||||
|
||||
void cancelEdit() {
|
||||
if (editMode != EditMode.NONE) {
|
||||
editMode = EditMode.NONE;
|
||||
editOrdinal = -1;
|
||||
refresh(bitFieldAllocation.allocationByteSize, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void componentDeleted(int ordinal) {
|
||||
if (editMode == EditMode.EDIT) {
|
||||
if (ordinal == editOrdinal) {
|
||||
// unexpected removal
|
||||
editMode = EditMode.ADD;
|
||||
editOrdinal = -1;
|
||||
}
|
||||
else if (ordinal < editOrdinal) {
|
||||
--editOrdinal;
|
||||
}
|
||||
}
|
||||
bitFieldAllocation.refresh();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void applyBitField(DataType baseDataType, String fieldName, boolean deleteConflicts,
|
||||
CompositeChangeListener listener) {
|
||||
HashSet<Integer> ordinalDeleteSet = new HashSet<>();
|
||||
if (editOrdinal >= 0) {
|
||||
composite.delete(editOrdinal);
|
||||
}
|
||||
if (deleteConflicts) {
|
||||
for (BitAttributes attrs : bitFieldAllocation.bitAttributes) {
|
||||
if (attrs.hasConflict() && (attrs.isAddBitField() || attrs.isEditField())) {
|
||||
// Edit component will always be on top of conflict
|
||||
ordinalDeleteSet.add(attrs.getConflict().getOrdinal());
|
||||
}
|
||||
}
|
||||
}
|
||||
Integer[] ordinalsToDelete = ordinalDeleteSet.toArray(new Integer[ordinalDeleteSet.size()]);
|
||||
Arrays.sort(ordinalsToDelete); // delete from end first
|
||||
int ordinal = composite.getNumComponents();
|
||||
for (int i = ordinalsToDelete.length - 1; i >= 0; i--) {
|
||||
ordinal = ordinalsToDelete[i];
|
||||
composite.delete(ordinal);
|
||||
}
|
||||
|
||||
try {
|
||||
String name = (fieldName != null && fieldName.length() != 0) ? fieldName : null;
|
||||
DataTypeComponent dtc;
|
||||
if (composite instanceof Union) {
|
||||
dtc = composite.insertBitField(ordinal, bitFieldAllocation.allocationByteSize,
|
||||
bitFieldAllocation.bitOffset, baseDataType, bitFieldAllocation.bitSize, name,
|
||||
null);
|
||||
}
|
||||
else {
|
||||
Structure struct = (Structure) composite;
|
||||
dtc = struct.insertBitFieldAt(allocationOffset,
|
||||
bitFieldAllocation.allocationByteSize, bitFieldAllocation.bitOffset,
|
||||
baseDataType, bitFieldAllocation.bitSize, name, null);
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.componentChanged(dtc.getOrdinal());
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException | InvalidDataTypeException e) {
|
||||
Msg.error(this, "Unexpected bitfield apply error", e);
|
||||
}
|
||||
finally {
|
||||
editMode = EditMode.NONE;
|
||||
editOrdinal = -1;
|
||||
bitFieldAllocation.refresh();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
BitAttributes getBitAttributes(Point p) {
|
||||
if (bitFieldAllocation == null) {
|
||||
return null;
|
||||
}
|
||||
for (BitAttributes attrs : bitFieldAllocation.bitAttributes) {
|
||||
if (attrs.rectangle != null && attrs.rectangle.contains(p)) {
|
||||
return attrs;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText(MouseEvent e) {
|
||||
BitAttributes attrs = getBitAttributes(e.getPoint());
|
||||
return attrs != null ? attrs.getTip() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
|
||||
//super.paintComponent(g);
|
||||
|
||||
int height = getHeight();
|
||||
int width = getWidth();
|
||||
|
||||
g.setColor(getBackground());
|
||||
g.fillRect(0, 0, width, height);
|
||||
|
||||
if (bitFieldAllocation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
width = getPreferredWidth();
|
||||
height = MY_HEIGHT;
|
||||
|
||||
g.setColor(LINE_COLOR);
|
||||
g.fillRect(0, 0, width, BYTE_SEPARATOR_THICKNESS); // top line
|
||||
g.fillRect(0, 0, BYTE_SEPARATOR_THICKNESS, height); // left line (full height)
|
||||
g.fillRect(width - BYTE_SEPARATOR_THICKNESS, 0, BYTE_SEPARATOR_THICKNESS, height); // right line (full height)
|
||||
int y = CELL_HEIGHT + BYTE_SEPARATOR_THICKNESS;
|
||||
g.fillRect(0, y, width, BYTE_SEPARATOR_THICKNESS); // next horizontal line
|
||||
y += CELL_HEIGHT + BYTE_SEPARATOR_THICKNESS;
|
||||
g.fillRect(0, y, width, BYTE_SEPARATOR_THICKNESS); // bottom line
|
||||
|
||||
paintByteHeader(g, BYTE_SEPARATOR_THICKNESS, allocationOffset);
|
||||
paintBits((Graphics2D) g, (2 * BYTE_SEPARATOR_THICKNESS) + CELL_HEIGHT);
|
||||
}
|
||||
|
||||
private void paintByteHeader(Graphics g, int y, int baseOffset) {
|
||||
int byteSize = bitFieldAllocation.allocationByteSize;
|
||||
int x = BYTE_SEPARATOR_THICKNESS;
|
||||
for (int i = 0; i < byteSize; i++) {
|
||||
// last byte header needs to slightly wider
|
||||
int w = BYTE_WIDTH;
|
||||
if (i == (byteSize - 1)) {
|
||||
w += BYTE_SEPARATOR_THICKNESS - BIT_SEPARATOR_THICKNESS;
|
||||
}
|
||||
paintByte(g, x, y, w, i, baseOffset);
|
||||
x += w;
|
||||
g.fillRect(x - BYTE_SEPARATOR_THICKNESS, y, BYTE_SEPARATOR_THICKNESS, CELL_HEIGHT); // line after each byte
|
||||
}
|
||||
}
|
||||
|
||||
private void paintByte(Graphics g, int x, int y, int width, int byteIndex, int baseOffset) {
|
||||
|
||||
Color curColor = g.getColor();
|
||||
Font curFont = g.getFont();
|
||||
|
||||
int offset = byteIndex;
|
||||
if (!bigEndian) {
|
||||
offset = bitFieldAllocation.allocationByteSize - byteIndex - 1;
|
||||
}
|
||||
offset += baseOffset;
|
||||
|
||||
g.setColor(BYTE_HEADER_COLOR);
|
||||
g.fillRect(x, y, width - BYTE_SEPARATOR_THICKNESS, CELL_HEIGHT); // byte fill
|
||||
|
||||
g.setColor(TEXT_COLOR);
|
||||
Font textFont = getFont().deriveFont(Font.BOLD);
|
||||
g.setFont(textFont);
|
||||
|
||||
String offsetStr = Integer.toString(offset);
|
||||
FontMetrics fontMetrics = g.getFontMetrics();
|
||||
int textY = y + (CELL_HEIGHT + fontMetrics.getMaxAscent()) / 2;
|
||||
int textX = x + (width - BYTE_SEPARATOR_THICKNESS - fontMetrics.stringWidth(offsetStr)) / 2;
|
||||
g.drawString(offsetStr, textX, textY);
|
||||
|
||||
g.setColor(curColor);
|
||||
g.setFont(curFont);
|
||||
}
|
||||
|
||||
private void paintBits(Graphics2D g, int y) {
|
||||
|
||||
Color curColor = g.getColor();
|
||||
|
||||
BitAttributes[] bitAttributes = bitFieldAllocation.bitAttributes;
|
||||
|
||||
int x = BYTE_SEPARATOR_THICKNESS;
|
||||
|
||||
if (bitAttributes[0] != null && bitAttributes[0].leftEndType == EndBitType.TRUNCATED_END) {
|
||||
// adjust left-most line to reflect truncated component
|
||||
x -= BIT_SEPARATOR_THICKNESS; // backup to left line location
|
||||
drawTruncationLine(g, x, y, CELL_HEIGHT);
|
||||
x += BIT_SEPARATOR_THICKNESS;
|
||||
}
|
||||
|
||||
BitAttributes prevAttrs = null;
|
||||
|
||||
for (int n = 0; n < bitAttributes.length; n++) {
|
||||
BitAttributes attrs = bitAttributes[n];
|
||||
boolean paintRightLine = n != (bitAttributes.length - 1);
|
||||
attrs.paint(g, prevAttrs, paintRightLine);
|
||||
x += attrs.rectangle.width;
|
||||
prevAttrs = attrs;
|
||||
}
|
||||
|
||||
if (prevAttrs != null && prevAttrs.rightEndType == EndBitType.TRUNCATED_END) {
|
||||
x -= BIT_SEPARATOR_THICKNESS; // backup to right line location
|
||||
drawTruncationLine(g, x, y, CELL_HEIGHT);
|
||||
}
|
||||
|
||||
g.setColor(curColor);
|
||||
}
|
||||
|
||||
private static final Stroke DASH = new BasicStroke(1, BasicStroke.CAP_SQUARE,
|
||||
BasicStroke.JOIN_MITER, 2, new float[] { 3, 3 }, 0);
|
||||
|
||||
private void drawTruncationLine(Graphics2D g, int x, int y, int height) {
|
||||
|
||||
Color c = g.getColor();
|
||||
Stroke s = g.getStroke();
|
||||
|
||||
g.setColor(getBackground()); // draw over black line
|
||||
g.setStroke(DASH);
|
||||
g.drawLine(x, y, x, y + height - 1);
|
||||
|
||||
g.setColor(c);
|
||||
g.setStroke(s);
|
||||
|
||||
}
|
||||
|
||||
private class BitFieldPlacement {
|
||||
int leftBit;
|
||||
int rightBit;
|
||||
boolean truncateLeft;
|
||||
boolean truncateRight;
|
||||
boolean zeroBitField;
|
||||
|
||||
BitFieldPlacement(DataTypeComponent component, int allocationByteSize) {
|
||||
int startOffset = component.getOffset();
|
||||
int offsetAdjBytes = startOffset - allocationOffset;
|
||||
if (!bigEndian) {
|
||||
offsetAdjBytes = allocationByteSize - offsetAdjBytes - component.getLength();
|
||||
}
|
||||
int leftAdj = 8 * offsetAdjBytes;
|
||||
if (component.isBitFieldComponent()) {
|
||||
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
|
||||
// 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();
|
||||
if (bitSize == 0) {
|
||||
zeroBitField = true;
|
||||
leftBit = rightBit;
|
||||
}
|
||||
else {
|
||||
leftBit = rightBit - bitSize + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int componentSize = 8 * component.getLength();
|
||||
rightBit = leftAdj + componentSize - 1;
|
||||
leftBit = leftAdj;
|
||||
}
|
||||
|
||||
// System.out.println(component.toString() + " >>> " + leftBit + " - " + rightBit +
|
||||
// " oa: " + offsetAdjBytes);
|
||||
|
||||
// clip to allocation region
|
||||
int allocBitSize = 8 * allocationByteSize;
|
||||
truncateRight = false;
|
||||
if (rightBit >= allocBitSize) {
|
||||
truncateRight = true;
|
||||
rightBit = allocBitSize - 1;
|
||||
}
|
||||
truncateLeft = false;
|
||||
if (leftBit < 0) {
|
||||
truncateLeft = true;
|
||||
leftBit = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BitFieldAllocation {
|
||||
|
||||
private final int allocationByteSize;
|
||||
private int bitSize;
|
||||
private int bitOffset;
|
||||
private boolean hasConflict;
|
||||
|
||||
// bit layout normalized to big-endian layout
|
||||
// left-most allocation msb has array index of 0
|
||||
private BitAttributes[] bitAttributes;
|
||||
|
||||
BitFieldAllocation(int allocationByteSize, int bitSize, int bitOffset) {
|
||||
if (allocationByteSize <= 0 || (bitSize + bitOffset) > (8 * allocationByteSize)) {
|
||||
throw new IllegalArgumentException("allocation size too small");
|
||||
}
|
||||
this.allocationByteSize = allocationByteSize;
|
||||
this.bitSize = bitSize;
|
||||
this.bitOffset = bitOffset;
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
allocateBits();
|
||||
layoutBits();
|
||||
}
|
||||
|
||||
private void allocateBits() {
|
||||
bitAttributes = new BitAttributes[8 * allocationByteSize];
|
||||
|
||||
if (composite instanceof Structure) {
|
||||
allocateStructureMembers((Structure) composite);
|
||||
}
|
||||
|
||||
if (editMode != EditMode.NONE) {
|
||||
int rightMostBit = bitAttributes.length - bitOffset - 1;
|
||||
if (bitSize == 0) {
|
||||
allocateZeroBitField(null, rightMostBit);
|
||||
}
|
||||
else {
|
||||
int leftMostBit = rightMostBit - bitSize + 1;
|
||||
allocateBits(null, leftMostBit, rightMostBit, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
// fill-in unallocated bits
|
||||
for (int i = 0; i < bitAttributes.length; i++) {
|
||||
if (bitAttributes[i] == null) {
|
||||
bitAttributes[i] = new BitAttributes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void layoutBits() {
|
||||
int x = BYTE_SEPARATOR_THICKNESS;
|
||||
int y = (2 * BYTE_SEPARATOR_THICKNESS) + CELL_HEIGHT;
|
||||
int width = BIT_WIDTH + BIT_SEPARATOR_THICKNESS;
|
||||
for (BitAttributes attrs : bitAttributes) {
|
||||
attrs.layout(x, y, width, CELL_HEIGHT);
|
||||
x += width;
|
||||
}
|
||||
}
|
||||
|
||||
private void allocateStructureMembers(Structure struct) {
|
||||
|
||||
int allocationEndOffset = allocationOffset + allocationByteSize - 1;
|
||||
|
||||
for (DataTypeComponent component : struct.getDefinedComponents()) {
|
||||
if (component.getOrdinal() == editOrdinal) {
|
||||
continue;
|
||||
}
|
||||
int startOffset = component.getOffset();
|
||||
int endOffset = component.getEndOffset();
|
||||
if (endOffset < allocationOffset) {
|
||||
continue;
|
||||
}
|
||||
if (startOffset > allocationEndOffset) {
|
||||
continue;
|
||||
}
|
||||
BitFieldPlacement placement = new BitFieldPlacement(component, allocationByteSize);
|
||||
if (placement.zeroBitField) {
|
||||
allocateZeroBitField(component, placement.rightBit);
|
||||
}
|
||||
else {
|
||||
allocateBits(component, placement.leftBit, placement.rightBit,
|
||||
placement.truncateLeft, placement.truncateRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void allocateBits(DataTypeComponent dtc, int leftBit, int rightBit,
|
||||
boolean truncatedLeft, boolean truncatedRight) {
|
||||
if (truncatedLeft && truncatedRight && leftBit == rightBit) {
|
||||
throw new AssertException();
|
||||
}
|
||||
int startIndex = Math.max(0, leftBit);
|
||||
int endIndex = Math.min(bitAttributes.length - 1, rightBit);
|
||||
for (int i = startIndex; i <= endIndex; i++) {
|
||||
EndBitType leftEndType = EndBitType.NOT_END;
|
||||
EndBitType rightEndType = EndBitType.NOT_END;
|
||||
if (dtc != null) {
|
||||
if (i == leftBit) {
|
||||
leftEndType = truncatedLeft ? EndBitType.TRUNCATED_END : EndBitType.END;
|
||||
}
|
||||
if (i == rightBit) {
|
||||
rightEndType = truncatedLeft ? EndBitType.TRUNCATED_END : EndBitType.END;
|
||||
}
|
||||
}
|
||||
bitAttributes[i] =
|
||||
new BitAttributes(dtc, leftEndType, rightEndType, bitAttributes[i]);
|
||||
hasConflict |= bitAttributes[i].hasConflict();
|
||||
}
|
||||
}
|
||||
|
||||
private void allocateZeroBitField(DataTypeComponent dtc, int bitIndex) {
|
||||
bitAttributes[bitIndex] = new BitAttributes(dtc, bitAttributes[bitIndex]);
|
||||
}
|
||||
|
||||
public int getAllocationByteSize() {
|
||||
return allocationByteSize;
|
||||
}
|
||||
|
||||
public int getBitOffset() {
|
||||
return bitOffset;
|
||||
}
|
||||
|
||||
public int getBitSize() {
|
||||
return bitSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static enum EditMode {
|
||||
NONE, ADD, EDIT;
|
||||
}
|
||||
|
||||
static enum EndBitType {
|
||||
NOT_END, END, TRUNCATED_END;
|
||||
}
|
||||
|
||||
class BitAttributes {
|
||||
|
||||
private final DataTypeComponent dtc;
|
||||
private final EndBitType leftEndType;
|
||||
private final EndBitType rightEndType;
|
||||
private final BitAttributes conflict;
|
||||
|
||||
private boolean zeroBitfield;
|
||||
private boolean unallocated;
|
||||
|
||||
Rectangle rectangle;
|
||||
|
||||
/**
|
||||
* Unallocated bitfield
|
||||
* @param dtc
|
||||
* @param conflict
|
||||
*/
|
||||
BitAttributes() {
|
||||
dtc = null;
|
||||
leftEndType = EndBitType.NOT_END;
|
||||
rightEndType = EndBitType.NOT_END;
|
||||
conflict = null;
|
||||
unallocated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zero-length bitfield
|
||||
* @param dtc
|
||||
* @param conflict
|
||||
*/
|
||||
BitAttributes(DataTypeComponent dtc, BitAttributes conflict) {
|
||||
this(dtc, dtc != null ? EndBitType.END : EndBitType.NOT_END,
|
||||
dtc != null ? EndBitType.END : EndBitType.NOT_END, conflict);
|
||||
zeroBitfield = true;
|
||||
}
|
||||
|
||||
BitAttributes(DataTypeComponent dtc, EndBitType leftEndType, EndBitType rightEndType,
|
||||
BitAttributes conflict) {
|
||||
this.dtc = dtc;
|
||||
this.leftEndType = leftEndType;
|
||||
this.rightEndType = rightEndType;
|
||||
this.conflict = conflict;
|
||||
if (conflict != null) {
|
||||
leftEndType = conflict.leftEndType;
|
||||
rightEndType = conflict.rightEndType;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAddBitField() {
|
||||
return !unallocated && dtc == null;
|
||||
}
|
||||
|
||||
boolean isEditField() {
|
||||
return dtc != null && dtc.getOrdinal() == editOrdinal;
|
||||
}
|
||||
|
||||
boolean hasConflict() {
|
||||
return getConflict() != null;
|
||||
}
|
||||
|
||||
public DataTypeComponent getConflict() {
|
||||
BitAttributes c = conflict;
|
||||
while (c != null && c.dtc.isZeroBitFieldComponent()) {
|
||||
c = conflict.conflict;
|
||||
}
|
||||
return c != null ? c.dtc : null;
|
||||
}
|
||||
|
||||
void layout(int x, int y, int width, int height) {
|
||||
rectangle = new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
void paint(Graphics g, BitAttributes bitAttrsToLeft, boolean paintRightLine) {
|
||||
// bit box
|
||||
Color c = getColor();
|
||||
g.setColor(c);
|
||||
g.fillRect(rectangle.x, rectangle.y, BIT_WIDTH, CELL_HEIGHT);
|
||||
|
||||
if (zeroBitfield ||
|
||||
(dtc != null && conflict != null && conflict.dtc.isZeroBitFieldComponent())) {
|
||||
c = BITFIELD_BITS_COLOR;
|
||||
Color lineColor = INTERIOR_LINE_COLOR;
|
||||
if (dtc != null) {
|
||||
c = BITFIELD_COMPONENT_COLOR;
|
||||
lineColor = LINE_COLOR;
|
||||
}
|
||||
// little-endian: place strip on right-side of bit
|
||||
// big-endian: place strip on left-side of bit
|
||||
int xStrip = bigEndian ? rectangle.x : (rectangle.x + BIT_WIDTH - ZERO_BIT_WIDTH);
|
||||
int xLine =
|
||||
bigEndian ? (xStrip + ZERO_BIT_WIDTH) : (xStrip - BIT_SEPARATOR_THICKNESS);
|
||||
g.setColor(c);
|
||||
g.fillRect(xStrip, rectangle.y, ZERO_BIT_WIDTH, CELL_HEIGHT);
|
||||
g.setColor(lineColor);
|
||||
g.fillRect(xLine, rectangle.y, BIT_SEPARATOR_THICKNESS, CELL_HEIGHT);
|
||||
}
|
||||
|
||||
if (bitAttrsToLeft != null && dtc != null && bitAttrsToLeft.unallocated) {
|
||||
// draw left bit line if we know better than the undefined to our left
|
||||
g.setColor(LINE_COLOR);
|
||||
g.fillRect(rectangle.x - BIT_SEPARATOR_THICKNESS, rectangle.y,
|
||||
BIT_SEPARATOR_THICKNESS, CELL_HEIGHT);
|
||||
}
|
||||
|
||||
if (paintRightLine) {
|
||||
// draw right bit line
|
||||
Color lineColor = LINE_COLOR;
|
||||
if (rightEndType == EndBitType.NOT_END) {
|
||||
lineColor = INTERIOR_LINE_COLOR;
|
||||
}
|
||||
g.setColor(lineColor);
|
||||
g.fillRect(rectangle.x + BIT_WIDTH, rectangle.y, BIT_SEPARATOR_THICKNESS,
|
||||
CELL_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
Color getColor() {
|
||||
// zero-length stripe will be added later and
|
||||
// should treated as a conflict
|
||||
if (unallocated) {
|
||||
return UNDEFINED_BIT_COLOR;
|
||||
}
|
||||
if (conflict != null && !conflict.unallocated) {
|
||||
if (zeroBitfield) {
|
||||
return conflict.getColor();
|
||||
}
|
||||
if (!conflict.dtc.isZeroBitFieldComponent()) {
|
||||
return CONFLICT_BITS_COLOR;
|
||||
}
|
||||
}
|
||||
if (zeroBitfield) {
|
||||
return UNDEFINED_BIT_COLOR;
|
||||
}
|
||||
if (dtc == null) {
|
||||
return BITFIELD_BITS_COLOR; // edit field
|
||||
}
|
||||
return dtc.isBitFieldComponent() ? BITFIELD_COMPONENT_COLOR
|
||||
: NON_BITFIELD_COMPONENT_COLOR;
|
||||
}
|
||||
|
||||
String getTip() {
|
||||
if (dtc == null) {
|
||||
return null;
|
||||
}
|
||||
String name = dtc.getFieldName();
|
||||
return dtc.getDataType().getDisplayName() +
|
||||
(name != null ? (" " + dtc.getFieldName()) : "");
|
||||
}
|
||||
|
||||
DataTypeComponent getDataTypeComponent(boolean ignoreEditComponent) {
|
||||
if (dtc != null && (dtc.getOrdinal() != editOrdinal || !ignoreEditComponent)) {
|
||||
return dtc;
|
||||
}
|
||||
if (conflict != null) {
|
||||
return conflict.dtc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -457,8 +457,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
|||
protected abstract DataTypeComponent insert(int rowIndex, DataType dataType, int length,
|
||||
String name, String comment) throws InvalidDataTypeException;
|
||||
|
||||
protected abstract void insert(int rowIndex, DataType dataType, int length, String name,
|
||||
String comment, int numCopies) throws InvalidDataTypeException;
|
||||
protected abstract void insert(int rowIndex, DataType dataType, int length, int numCopies) throws InvalidDataTypeException;
|
||||
|
||||
/**
|
||||
* Add a DataType component into to an editable structure
|
||||
|
@ -479,7 +478,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
|||
return;
|
||||
}
|
||||
|
||||
insert(rowIndex, dataType, dtLen, null, null, multiple);
|
||||
insert(rowIndex, dataType, dtLen, multiple);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* ###
|
||||
* 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.app.plugin.core.compositeeditor;
|
||||
|
||||
public interface CompositeChangeListener {
|
||||
|
||||
/**
|
||||
* Indicates the ordinal of the component which has been added, updated or cleared.
|
||||
* @param ordinal component ordinal
|
||||
*/
|
||||
void componentChanged(int ordinal);
|
||||
|
||||
}
|
|
@ -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.
|
||||
|
@ -16,18 +15,18 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.compositeeditor;
|
||||
|
||||
|
||||
public interface EditorAction extends CompositeEditorModelListener {
|
||||
|
||||
static final String BASIC_ACTION_GROUP = "1_BASIC_EDITOR_ACTION";
|
||||
static final String FAVORITES_ACTION_GROUP = "2_FAVORITE_DT_EDITOR_ACTION";
|
||||
static final String CYCLE_ACTION_GROUP = "3_CYCLE_DT_EDITOR_ACTION";
|
||||
static final String COMPONENT_ACTION_GROUP = "4_COMPONENT_EDITOR_ACTION";
|
||||
|
||||
static final String BITFIELD_ACTION_GROUP = "5_COMPONENT_EDITOR_ACTION";
|
||||
|
||||
/**
|
||||
* Method to set the action's enablement based on the associated editor
|
||||
* model's current state.
|
||||
*/
|
||||
public void adjustEnablement();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -997,13 +997,14 @@ class StructureEditorModel extends CompEditorModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void insert(int rowIndex, DataType dataType, int length, String name, String comment,
|
||||
int numCopies) throws InvalidDataTypeException {
|
||||
protected void insert(int rowIndex, DataType dataType, int length, int numCopies)
|
||||
throws InvalidDataTypeException {
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
int componentOrdinal = convertRowToOrdinal(rowIndex);
|
||||
try {
|
||||
((Structure) viewComposite).insert(componentOrdinal, dataType, length, name, comment,
|
||||
numCopies);
|
||||
for (int i = 0; i < numCopies; i++) {
|
||||
viewComposite.insert(componentOrdinal, dataType, length);
|
||||
}
|
||||
if (rowIndex <= row) {
|
||||
row += numCopies;
|
||||
}
|
||||
|
@ -1026,9 +1027,6 @@ class StructureEditorModel extends CompEditorModel {
|
|||
return struct.setFlexibleArrayComponent(dt, dtc.getFieldName(), dtc.getComment());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.datamanager.editor.CompositeEditorModel#replace(int, ghidra.program.model.data.DataType, int, java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.compositeeditor;
|
||||
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.program.model.data.Structure;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import resources.ResourceManager;
|
||||
|
||||
/**
|
||||
|
@ -45,44 +44,44 @@ public class StructureEditorProvider extends CompositeEditorProvider {
|
|||
editorModel.selectionChanged();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.datamanager.editor.EditorProvider#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Structure Editor";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.compositeeditor.CompositeEditorProvider#createActions()
|
||||
*/
|
||||
@Override
|
||||
protected CompositeEditorTableAction[] createActions() {
|
||||
//@formatter:off
|
||||
return new CompositeEditorTableAction[] {
|
||||
new ApplyAction(this),
|
||||
// new ToggleLockAction(this),
|
||||
new InsertUndefinedAction(this), new MoveUpAction(this), new MoveDownAction(this),
|
||||
new ClearAction(this), new DuplicateAction(this), new DuplicateMultipleAction(this),
|
||||
new DeleteAction(this), new PointerAction(this), new ArrayAction(this),
|
||||
new ShowComponentPathAction(this), new UnpackageAction(this),
|
||||
new EditComponentAction(this), new EditFieldAction(this), new HexNumbersAction(this),
|
||||
new CreateInternalStructureAction(this) };
|
||||
// new ToggleLockAction(this),
|
||||
new InsertUndefinedAction(this),
|
||||
new MoveUpAction(this),
|
||||
new MoveDownAction(this),
|
||||
new ClearAction(this),
|
||||
new DuplicateAction(this),
|
||||
new DuplicateMultipleAction(this),
|
||||
new DeleteAction(this),
|
||||
new PointerAction(this),
|
||||
new ArrayAction(this),
|
||||
new ShowComponentPathAction(this),
|
||||
new UnpackageAction(this),
|
||||
new EditComponentAction(this),
|
||||
new EditFieldAction(this),
|
||||
new HexNumbersAction(this),
|
||||
new CreateInternalStructureAction(this),
|
||||
new AddBitFieldAction(this)
|
||||
};
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.compositeeditor.CompositeEditorProvider#getHelpName()
|
||||
*/
|
||||
@Override
|
||||
public String getHelpName() {
|
||||
return "Structure_Editor";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.compositeeditor.CompositeEditorProvider#getHelpTopic()
|
||||
*/
|
||||
@Override
|
||||
public String getHelpTopic() {
|
||||
return "DataTypeEditors";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -410,10 +410,10 @@ class UnionEditorModel extends CompEditorModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void insert(int rowIndex, DataType dataType, int length, String name, String comment,
|
||||
int numCopies) throws InvalidDataTypeException {
|
||||
public void insert(int rowIndex, DataType dataType, int length, int numCopies)
|
||||
throws InvalidDataTypeException {
|
||||
for (int ii = 0; ii < numCopies; ++ii) {
|
||||
insert(rowIndex + ii, dataType, length, name, comment);
|
||||
insert(rowIndex + ii, dataType, length, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.compositeeditor;
|
||||
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.program.model.data.Union;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.program.model.data.Union;
|
||||
import resources.ResourceManager;
|
||||
|
||||
/**
|
||||
|
@ -49,32 +48,34 @@ public class UnionEditorProvider extends CompositeEditorProvider {
|
|||
return "Union Editor";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.compositeeditor.CompositeEditorProvider#createActions()
|
||||
*/
|
||||
@Override
|
||||
protected CompositeEditorTableAction[] createActions() {
|
||||
return new CompositeEditorTableAction[] { new ApplyAction(this), new MoveUpAction(this),
|
||||
new MoveDownAction(this), new DuplicateAction(this), new DuplicateMultipleAction(this),
|
||||
new DeleteAction(this), new PointerAction(this), new ArrayAction(this),
|
||||
new ShowComponentPathAction(this), new EditComponentAction(this),
|
||||
new EditFieldAction(this), new HexNumbersAction(this) };
|
||||
//@formatter:off
|
||||
return new CompositeEditorTableAction[] {
|
||||
new ApplyAction(this),
|
||||
new MoveUpAction(this),
|
||||
new MoveDownAction(this),
|
||||
new DuplicateAction(this),
|
||||
new DuplicateMultipleAction(this),
|
||||
new DeleteAction(this),
|
||||
new PointerAction(this),
|
||||
new ArrayAction(this),
|
||||
new ShowComponentPathAction(this),
|
||||
new EditComponentAction(this),
|
||||
new EditFieldAction(this),
|
||||
new HexNumbersAction(this),
|
||||
new AddBitFieldAction(this)
|
||||
};
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.compositeeditor.CompositeEditorProvider#getHelpName()
|
||||
*/
|
||||
@Override
|
||||
public String getHelpName() {
|
||||
return "Structure_Editor";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.compositeeditor.CompositeEditorProvider#getHelpTopic()
|
||||
*/
|
||||
@Override
|
||||
public String getHelpTopic() {
|
||||
return "DataTypeEditors";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
|||
private GoToService goToService;
|
||||
private DockingAction addAction;
|
||||
private DockingAction deleteAction;
|
||||
private DataTypeManager dataTypeManager;
|
||||
private LayeredDataTypeManager dataTypeManager;
|
||||
private Program activeProgram;
|
||||
|
||||
private SwingUpdateManager updateManager = new SwingUpdateManager(650, () -> updatePreview());
|
||||
|
@ -156,7 +156,33 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
|||
updateModel();
|
||||
}
|
||||
|
||||
void updateModel() {
|
||||
private List<DataTypePath> getModelDataTypePaths() {
|
||||
// retain order as they currently exist within model
|
||||
List<DataTypePath> list = new ArrayList<>();
|
||||
for (Preview preview : model.getModelData()) {
|
||||
if (preview instanceof DataTypePreview) {
|
||||
list.add(preview.getDataType().getDataTypePath());
|
||||
}
|
||||
else if (preview instanceof DataTypeComponentPreview) {
|
||||
DataTypeComponentPreview componentPreview = (DataTypeComponentPreview) preview;
|
||||
if (componentPreview.getParent() == null) {
|
||||
list.add(preview.getDataType().getDataTypePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void updateModel() {
|
||||
|
||||
// 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<DataTypePath> dtPaths = getModelDataTypePaths();
|
||||
model.removeAll();
|
||||
dataTypeManager.invalidate();
|
||||
|
||||
int transactionId = dataTypeManager.startTransaction("realign");
|
||||
try {
|
||||
Iterator<Composite> allComposites = dataTypeManager.getAllComposites();
|
||||
|
@ -164,14 +190,19 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
|||
Composite composite = allComposites.next();
|
||||
if (composite.isInternallyAligned()) {
|
||||
composite.realign();
|
||||
model.removeAll(composite);
|
||||
model.add(composite);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
dataTypeManager.endTransaction(transactionId, true);
|
||||
}
|
||||
|
||||
for (DataTypePath dtPath : dtPaths) {
|
||||
DataType dataType = dataTypeManager.getDataType(dtPath);
|
||||
if (dataType != null) {
|
||||
model.add(dataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -693,5 +724,9 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
|||
return super.getDataOrganization();
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
protected void shiftOffsets(int startIndex, int endIndex, int deltaOrdinal, int deltaOffset) {
|
||||
for (int i = startIndex; i <= endIndex && i < components.size(); i++) {
|
||||
DataTypeComponentImpl dtc = components.get(i);
|
||||
shiftOffsets(dtc, deltaOrdinal, deltaOffset);
|
||||
shiftOffset(dtc, deltaOrdinal, deltaOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length,
|
||||
public DataTypeComponentImpl insertAtOffset(int offset, DataType dataType, int length,
|
||||
String newName, String comment) {
|
||||
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -297,11 +297,6 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
return dtc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length) {
|
||||
return insertAtOffset(offset, dataType, length, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent add(DataType dataType, int length, String newName, String comment) {
|
||||
return addPositive(dataType, length, newName, comment);
|
||||
|
@ -374,7 +369,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
structLength += absAmount;
|
||||
notifySizeChanged();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insert(int index, DataType dataType, int length, String newName,
|
||||
String comment) {
|
||||
|
@ -407,12 +402,6 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
// return dtc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(int ordinal, DataType dataType, int length, String name, String comment,
|
||||
int numCopies) {
|
||||
throw new AssertException("BiDirectionDataType.insert() not implemented.");
|
||||
}
|
||||
|
||||
protected void insertAtOffset(int offset, int numBytes) {
|
||||
if (offset < splitOffset - negativeLength || offset > splitOffset + positiveLength) {
|
||||
throw new IllegalArgumentException("Offset " + offset +
|
||||
|
@ -676,7 +665,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
// dtMgr.dataTypeChanged(this);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataTypeComponent[] getDefinedComponents() {
|
||||
return components.toArray(new DataTypeComponent[components.size()]);
|
||||
|
@ -704,12 +693,6 @@ public abstract class BiDirectionDataType extends StructureDataType
|
|||
return replace(origDtc, dataType, length, newName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent replace(int index, DataType dataType, int length) {
|
||||
validateDataType(dataType);
|
||||
return replace(index, dataType, length, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent replaceAtOffset(int offset, DataType dataType, int length,
|
||||
String newName, String comment) {
|
||||
|
|
|
@ -24,8 +24,6 @@ import ghidra.program.model.pcode.Varnode;
|
|||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
|
||||
public class StackPieceDataType extends DataTypeImpl {
|
||||
|
||||
private final Variable variable;
|
||||
|
@ -66,13 +64,13 @@ public class StackPieceDataType extends DataTypeImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException, DuplicateNameException {
|
||||
public void setName(String name) throws InvalidNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameAndCategory(CategoryPath path, String name) throws InvalidNameException,
|
||||
DuplicateNameException {
|
||||
public void setNameAndCategory(CategoryPath path, String name)
|
||||
throws InvalidNameException, DuplicateNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import ghidra.util.InvalidNameException;
|
|||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
class MSRichProductBuildNumberDataType extends DataTypeImpl {
|
||||
|
||||
|
||||
private final CompId compid;
|
||||
|
||||
public MSRichProductBuildNumberDataType(CompId compid) {
|
||||
|
@ -58,7 +58,7 @@ class MSRichProductBuildNumberDataType extends DataTypeImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException, DuplicateNameException {
|
||||
public void setName(String name) throws InvalidNameException {
|
||||
// ignored
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class MSRichProductIDDataType extends DataTypeImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException, DuplicateNameException {
|
||||
public void setName(String name) throws InvalidNameException {
|
||||
// ignored
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ class MSRichProductIDDataType extends DataTypeImpl {
|
|||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
|
||||
return compid.getProductDescription();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -58,7 +58,7 @@ class RichObjectCountDataType extends DataTypeImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException, DuplicateNameException {
|
||||
public void setName(String name) throws InvalidNameException {
|
||||
// ignored
|
||||
}
|
||||
|
||||
|
|
|
@ -27,11 +27,8 @@ import ghidra.program.model.data.*;
|
|||
*/
|
||||
|
||||
public class CompositeHandler {
|
||||
private DataType lastBitFieldType = null; // type that has a bitfield
|
||||
private int bitLength = 0; // how many bits have been used
|
||||
private int anonCnt = 0; // count of anonymous unions created
|
||||
|
||||
private Composite parent; // parent container for bitfields
|
||||
private Composite bitFieldUnion; // artificial union to contain subfields
|
||||
|
||||
public CompositeHandler(Composite parent) {
|
||||
super();
|
||||
|
@ -42,7 +39,7 @@ public class CompositeHandler {
|
|||
return parent;
|
||||
}
|
||||
|
||||
public void add(Declaration dec) {
|
||||
public void add(Declaration dec) throws IllegalArgumentException {
|
||||
if (dec == null || dec.getDataType() == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -52,7 +49,6 @@ public class CompositeHandler {
|
|||
}
|
||||
// not a bitfield, just add the data type to composite
|
||||
if (!dec.isBitField()) {
|
||||
initialize();
|
||||
if (dec.isFlexArray() && parent instanceof Structure) {
|
||||
((Structure) parent).setFlexibleArrayComponent(dec.getDataType(), dec.getName(),
|
||||
dec.getComment());
|
||||
|
@ -62,72 +58,16 @@ public class CompositeHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
// add bit-field component
|
||||
DataType dataType = dec.getDataType();
|
||||
int bitSize = dec.getBitFieldSize();
|
||||
|
||||
// if data type different, start new subfield
|
||||
handleFullBitfieldUnion(dataType, bitSize);
|
||||
|
||||
// add the bitfield to the continer union
|
||||
String bitoff =
|
||||
(bitSize == 1 ? "" + bitLength : bitLength + "-" + (bitLength + bitSize - 1));
|
||||
bitFieldUnion.add(dataType, dec.getName(), ": bits " + bitoff);
|
||||
lastBitFieldType = dataType;
|
||||
bitLength += bitSize;
|
||||
try {
|
||||
parent.addBitField(dataType, dec.getBitFieldSize(), dec.getName(), dec.getComment());
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
// TODO Auto-generated catch block
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid bitfield " + dec.getName() + " : " + dec.getBitFieldSize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bitfield union container if one not created yet or the current
|
||||
* is full.
|
||||
*
|
||||
* @param dataType - type that is about to be added to container
|
||||
* @param bitSize
|
||||
*/
|
||||
private void handleFullBitfieldUnion(DataType dataType, int bitSize) {
|
||||
if (!bitfieldFull(dataType, bitSize)) {
|
||||
return;
|
||||
}
|
||||
// create an anonymous union to hold sub bitfields
|
||||
bitFieldUnion = new UnionDataType(parent.getCategoryPath(),
|
||||
"anon_" + parent.getName() + "_bitfield_" + ++anonCnt);
|
||||
bitFieldUnion = (Composite) parent.add(bitFieldUnion).getDataType();
|
||||
bitLength = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a new union needs to be created
|
||||
*
|
||||
* @param dataType type that will be added to the union
|
||||
* @param bitSize size of the bitfield to be added
|
||||
*
|
||||
* @return true if a new bitfied union needs to be added
|
||||
*/
|
||||
private boolean bitfieldFull(DataType dataType, int bitSize) {
|
||||
if (parent instanceof Union) {
|
||||
bitFieldUnion = parent;
|
||||
return false;
|
||||
}
|
||||
|
||||
// no union yet
|
||||
if (bitFieldUnion == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// datatype has changed
|
||||
if (!dataType.equals(lastBitFieldType)) {
|
||||
return true;
|
||||
}
|
||||
// union has overflowed
|
||||
return (bitLength + bitSize) > (dataType.getLength() * 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any residual bitfield info so a new bitfield container will
|
||||
* be created when necessary.
|
||||
*/
|
||||
private void initialize() {
|
||||
lastBitFieldType = null;
|
||||
bitLength = 0;
|
||||
bitFieldUnion = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public class Declaration {
|
|||
private DataType dt;
|
||||
private String name;
|
||||
private String comment;
|
||||
private int bitSize = 0;
|
||||
private int bitSize = -1;
|
||||
private boolean flexArray = false; // true if this is a zero size flex array component
|
||||
|
||||
public Declaration() {
|
||||
|
@ -97,9 +97,6 @@ public class Declaration {
|
|||
if (name == null) {
|
||||
return "";
|
||||
}
|
||||
if (isBitField()) {
|
||||
return name + ":" + bitSize;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -133,7 +130,7 @@ public class Declaration {
|
|||
* @return true if a bitfield size has been set
|
||||
*/
|
||||
boolean isBitField() {
|
||||
return bitSize != 0;
|
||||
return bitSize >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,14 +15,6 @@
|
|||
*/
|
||||
package ghidra.app.util.datatype;
|
||||
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeChooserDialog;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.data.DataTypeParser;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -31,6 +23,12 @@ import javax.swing.tree.TreePath;
|
|||
|
||||
import docking.options.editor.ButtonPanelFactory;
|
||||
import docking.widgets.DropDownSelectionTextField;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeChooserDialog;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.data.DataTypeParser;
|
||||
|
||||
/**
|
||||
* An editor that is used to show the {@link DropDownSelectionTextField} for the entering of
|
||||
|
@ -58,6 +56,7 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
|
||||
private JPanel editorPanel;
|
||||
private DropDownSelectionTextField<DataType> selectionField;
|
||||
private JButton browseButton;
|
||||
private DataTypeManagerService dataTypeManagerService;
|
||||
private int maxSize = -1;
|
||||
private DataTypeManager dataTypeManager;
|
||||
|
@ -109,9 +108,8 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
}
|
||||
|
||||
private void init() {
|
||||
selectionField =
|
||||
new DropDownSelectionTextField<DataType>(new DataTypeDropDownSelectionDataModel(
|
||||
dataTypeManagerService));
|
||||
selectionField = new DropDownSelectionTextField<>(
|
||||
new DataTypeDropDownSelectionDataModel(dataTypeManagerService));
|
||||
selectionField.addCellEditorListener(new CellEditorListener() {
|
||||
@Override
|
||||
public void editingCanceled(ChangeEvent e) {
|
||||
|
@ -128,15 +126,9 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
|
||||
selectionField.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
|
||||
|
||||
JButton browseButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE);
|
||||
browseButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE);
|
||||
browseButton.setToolTipText("Browse the Data Manager");
|
||||
browseButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// show the data type manager
|
||||
showDataTypeBrowser();
|
||||
}
|
||||
});
|
||||
browseButton.addActionListener(e -> showDataTypeBrowser());
|
||||
|
||||
editorPanel = new JPanel();
|
||||
editorPanel.setLayout(new BoxLayout(editorPanel, BoxLayout.X_AXIS));
|
||||
|
@ -196,7 +188,7 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
* Returns the component that allows the user to edit.
|
||||
* @return the component that allows the user to edit.
|
||||
*/
|
||||
public Component getEditorComponent() {
|
||||
public JComponent getEditorComponent() {
|
||||
return editorPanel;
|
||||
}
|
||||
|
||||
|
@ -204,6 +196,10 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
return selectionField;
|
||||
}
|
||||
|
||||
public JButton getBrowseButton() {
|
||||
return browseButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initially selected node in the data type tree that the user can choose to
|
||||
* show.
|
||||
|
@ -321,11 +317,11 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
// look for the case where the user made a selection from the matching window, but
|
||||
// then changed the text field text.
|
||||
DataType selectedDataType = selectionField.getSelectedValue();
|
||||
if (selectedDataType != null && selectionField.getText().equals(selectedDataType.getName())) {
|
||||
if (selectedDataType != null &&
|
||||
selectionField.getText().equals(selectedDataType.getName())) {
|
||||
DataTypeParser.ensureIsAllowableType(selectedDataType, allowedDataTypes);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -346,6 +342,11 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
// TODO: implement in the future to allow the user to create data types
|
||||
private boolean promptUserToCreateDataType() throws InvalidDataTypeException {
|
||||
|
||||
if (selectionField.getText().trim().length() == 0) {
|
||||
// no need to invoke parser on empty string
|
||||
return false;
|
||||
}
|
||||
|
||||
// we will create new pointer and array types by default
|
||||
DataType newDataType = null;
|
||||
// try {
|
||||
|
|
|
@ -81,10 +81,10 @@ public class MUIResourceDataType extends DynamicDataType {
|
|||
if (checkMagic(memBuffer)) {
|
||||
StructureDataType sdt = MUIStructureHeader();
|
||||
tempOffset = addComp(sdt, sdt.getLength(), "muiResourceHeader",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
sdt = MUIStructureData(tempOffset, memBuffer, offsets, sizes);
|
||||
tempOffset = addComp(sdt, sdt.getLength(), "muiResourceData",
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
memBuffer.getAddress().add(tempOffset), comps, tempOffset);
|
||||
}
|
||||
else {
|
||||
Msg.debug(this, "Not an MUI resource data type at " + mbIn.getAddress());
|
||||
|
@ -107,7 +107,7 @@ public class MUIResourceDataType extends DynamicDataType {
|
|||
"0x01 = internal, 0x02 = external");
|
||||
|
||||
ArrayDataType adt16 = new ArrayDataType(ByteDataType.dataType, 16, 1);
|
||||
ArrayDataType adt24 = new ArrayDataType(ByteDataType.dataType, 16, 1);
|
||||
ArrayDataType adt24 = new ArrayDataType(ByteDataType.dataType, 24, 1);
|
||||
|
||||
struct.add(adt16, 16, "serviceChecksum", "");
|
||||
struct.add(adt16, 16, "checksum", "");
|
||||
|
@ -195,9 +195,8 @@ public class MUIResourceDataType extends DynamicDataType {
|
|||
private int addComp(DataType dataType, int length, String fieldName, Address address,
|
||||
List<DataTypeComponent> comps, int currentOffset) {
|
||||
if (length > 0) {
|
||||
ReadOnlyDataTypeComponent readOnlyDataTypeComponent =
|
||||
new ReadOnlyDataTypeComponent(dataType, this, length, comps.size(), currentOffset,
|
||||
fieldName, null);
|
||||
ReadOnlyDataTypeComponent readOnlyDataTypeComponent = new ReadOnlyDataTypeComponent(
|
||||
dataType, this, length, comps.size(), currentOffset, fieldName, null);
|
||||
comps.add(readOnlyDataTypeComponent);
|
||||
currentOffset += length;
|
||||
}
|
||||
|
|
|
@ -308,7 +308,7 @@ public class BytesFieldFactory extends FieldFactory {
|
|||
}
|
||||
alignSize = (int) (nextComponent.getMinAddress().subtract(data.getMaxAddress())) - 1;
|
||||
}
|
||||
if (alignSize == 0) {
|
||||
if (alignSize <= 0) {
|
||||
return null;
|
||||
}
|
||||
int alignmentOffset = data.getParentOffset() + data.getLength();
|
||||
|
|
|
@ -271,8 +271,8 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
|
|||
int offset = (int) address.subtract(parent.getMinAddress());
|
||||
data = parent.getComponentAt(offset);
|
||||
|
||||
// Need to handle filler in aligned structures in a special way.
|
||||
if (data == null && ((Structure) dt).isInternallyAligned()) {
|
||||
// Need to handle filler in a special way.
|
||||
if (data == null) {
|
||||
// So look for next non-filler address.
|
||||
offset++;
|
||||
int length = dt.getLength();
|
||||
|
@ -280,7 +280,7 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
|
|||
// If not beyond structure's end, check for non-filler.
|
||||
data = parent.getComponentAt(offset);
|
||||
if (data != null) { // Found non filler address so return it.
|
||||
return parent.getMinAddress().add(offset);
|
||||
return data.getMinAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,9 +315,12 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
|
|||
}
|
||||
}
|
||||
else {
|
||||
// otherwise just return the next dataComponent after this one
|
||||
if (index < parent.getNumComponents() - 1) {
|
||||
return parent.getComponent(index + 1).getMinAddress();
|
||||
while (index < parent.getNumComponents() - 1) {
|
||||
index++;
|
||||
Data component = parent.getComponent(index);
|
||||
if (address.compareTo(component.getMinAddress()) < 0) {
|
||||
return component.getAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -369,7 +372,9 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
|
|||
}
|
||||
else {
|
||||
int offset = (int) addr.subtract(parent.getMinAddress());
|
||||
data = parent.getComponentAt(offset - 1);
|
||||
List<Data> componentsContaining = parent.getComponentsContaining(offset - 1);
|
||||
data = componentsContaining.isEmpty() ? null
|
||||
: componentsContaining.get(componentsContaining.size() - 1);
|
||||
}
|
||||
if (data == null) {
|
||||
return addr.previous();
|
||||
|
@ -415,14 +420,18 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Data tmpData = data.getComponentAt((int) addr.subtract(dataAddr));
|
||||
if (tmpData != null) {
|
||||
if (tmpData.getMinAddress().equals(addr)) {
|
||||
list.add(tmpData);
|
||||
}
|
||||
if (tmpData.getNumComponents() > 0) {
|
||||
addOpenData(list, tmpData, addr);
|
||||
else { // Structure
|
||||
List<Data> dataList = data.getComponentsContaining((int) addr.subtract(dataAddr));
|
||||
if (dataList != null) { // nested flex-arrays can cause odd behavior
|
||||
for (Data subData : dataList) {
|
||||
// The only case where more than one subData exists is for bit-fields.
|
||||
// Depending upon the packing, bit-fields at different offsets may overlap
|
||||
if (subData.getMinAddress().equals(addr)) {
|
||||
list.add(subData);
|
||||
}
|
||||
if (subData.getNumComponents() > 0) {
|
||||
addOpenData(list, subData, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
*/
|
||||
package ghidra.util.data;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
|
@ -45,7 +46,12 @@ public class DataTypeParser {
|
|||
/**
|
||||
* Only Fixed-length data types and string data types
|
||||
*/
|
||||
STRINGS_AND_FIXED_LENGTH
|
||||
STRINGS_AND_FIXED_LENGTH,
|
||||
/**
|
||||
* Only Enums, Integer types and those Typedefs based on them
|
||||
* for use as a bitfield base datatype
|
||||
*/
|
||||
BITFIELD_USE
|
||||
}
|
||||
|
||||
private DataTypeManager sourceDataTypeManager; // may be null
|
||||
|
@ -57,7 +63,7 @@ public class DataTypeParser {
|
|||
* A constructor that does not use the source or destination data type managers. In terms of
|
||||
* the source data type manager, this means that all data type managers will be used when
|
||||
* resolving data types.
|
||||
*
|
||||
*
|
||||
* @param dataTypeManagerService
|
||||
* @param allowedTypes
|
||||
*/
|
||||
|
@ -73,7 +79,7 @@ public class DataTypeParser {
|
|||
* @param destinationDataTypeManager target data-type manager, or null
|
||||
* @param dataTypeManagerService data-type manager tool service, or null
|
||||
* @param allowedTypes constrains which data-types may be parsed
|
||||
*
|
||||
*
|
||||
* @see #DataTypeParser(DataTypeManagerService, AllowedDataTypes)
|
||||
*/
|
||||
public DataTypeParser(DataTypeManager sourceDataTypeManager,
|
||||
|
@ -118,7 +124,7 @@ public class DataTypeParser {
|
|||
* Parse a data-type string specification using the specified baseDatatype.
|
||||
* @param suggestedBaseDataType base data-type (may be null), this will be used as the base data-type if
|
||||
* its name matches the base name in the specified dataTypeString.
|
||||
* @param dataTypeString a base data-type followed by a sequence of zero or more pointer/array decorations to be applied.
|
||||
* @param dataTypeString a base data-type followed by a sequence of zero or more pointer/array decorations to be applied.
|
||||
* The string may start with the baseDataType's name.
|
||||
* @return parsed data-type or null if not found
|
||||
* @throws InvalidDataTypeException if data-type string is invalid or length exceeds specified maxSize
|
||||
|
@ -180,6 +186,12 @@ public class DataTypeParser {
|
|||
throw new InvalidDataTypeException("fixed-length or string data-type required");
|
||||
}
|
||||
break;
|
||||
case BITFIELD_USE:
|
||||
if (!BitFieldDataType.isValidBaseDataType(dt)) {
|
||||
throw new InvalidDataTypeException(
|
||||
"enum or integer derived data-type required");
|
||||
}
|
||||
break;
|
||||
case ALL:
|
||||
// do nothing
|
||||
break;
|
||||
|
@ -334,8 +346,7 @@ public class DataTypeParser {
|
|||
|
||||
// see if one of the data types belongs to the program or the built in types, where the
|
||||
// program is more important than the builtin
|
||||
for (Iterator<DataType> iter = dtList.iterator(); iter.hasNext();) {
|
||||
DataType dataType = iter.next();
|
||||
for (DataType dataType : dtList) {
|
||||
DataTypeManager manager = dataType.getDataTypeManager();
|
||||
if (manager instanceof BuiltInDataTypeManager) {
|
||||
programDataType = dataType;
|
||||
|
@ -350,8 +361,7 @@ public class DataTypeParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
for (Iterator<DataType> iter = dtList.iterator(); iter.hasNext();) {
|
||||
DataType dataType = iter.next();
|
||||
for (DataType dataType : dtList) {
|
||||
// just one non-matching case means that we can't use the program's data type
|
||||
if (!programDataType.isEquivalent(dataType)) {
|
||||
return null;
|
||||
|
|
|
@ -1674,17 +1674,19 @@ Composite StructOrUnion() : {Composite comp;}
|
|||
{
|
||||
(
|
||||
<STRUCT> ( DeclSpec() )* { comp = new StructureDataType(ANONYMOUS_STRUCT_PREFIX + cnt++, 0);
|
||||
try {
|
||||
// always set the packing, because by default structures should be aligned
|
||||
|
||||
// Always set the packing, because by default structures should be aligned
|
||||
// setting 0 turns off packing, but sets structures to be aligned
|
||||
// TODO: is this correct, should this be changed and controlled by the
|
||||
// compiler spec.
|
||||
comp.setPackingValue(this.packSize);
|
||||
} catch (InvalidInputException e1) {
|
||||
e1.printStackTrace(); }
|
||||
|
||||
}
|
||||
|
|
||||
<UNION> ( DeclSpec() )* { comp = new UnionDataType(ANONYMOUS_UNION_PREFIX + cnt++); }
|
||||
<UNION> ( 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);
|
||||
}
|
||||
)
|
||||
{
|
||||
try {
|
||||
|
@ -1813,7 +1815,14 @@ void StructDeclarator(Declaration dt, Composite comp, CompositeHandler composite
|
|||
}
|
||||
}]
|
||||
|
|
||||
":" ConstantExpression()
|
||||
":" bitSizeObj = ConstantExpression() {
|
||||
Integer bitSize = getConstantValue(bitSizeObj,0);
|
||||
if (bitSize != 0) {
|
||||
throw new ParseException("invalid bit-field declaration: ':" + bitSize);
|
||||
}
|
||||
dec = new Declaration(dt);
|
||||
dec.setBitFieldSize(0);
|
||||
}
|
||||
)
|
||||
{
|
||||
try {
|
||||
|
|
|
@ -51,8 +51,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
builder = new ToyProgramBuilder("Call Node Test", true);
|
||||
builder.createMemory(".text", "0x0", 0x3000);
|
||||
|
||||
|
@ -64,8 +64,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
node = new OutgoingFunctionCallNode(program, function, source, true, new AtomicInteger(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_SelfRecursiveCall() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_SelfRecursiveCall() throws Exception {
|
||||
|
||||
builder.createMemoryCallReference(nodeAddress, nodeAddress);
|
||||
|
||||
|
@ -73,8 +73,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_CalledFunctionExists() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_CalledFunctionExists() throws Exception {
|
||||
String otherAddress = "0x1000";
|
||||
builder.createEmptyFunction("Function_2", otherAddress, 10, DataType.DEFAULT);
|
||||
builder.createMemoryCallReference(nodeAddress, otherAddress);
|
||||
|
@ -84,8 +84,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertEquals("Function_2", children.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_CalledFunctionExists_ExternalCall() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_CalledFunctionExists_ExternalCall() throws Exception {
|
||||
String otherAddress = "0x1000";
|
||||
|
||||
String externalFunctionName = "External_Function";
|
||||
|
@ -100,8 +100,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertEquals(externalFunctionName, children.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ExternalFunction_NoFunctionInMemory()
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ExternalFunction_NoFunctionInMemory()
|
||||
throws Exception {
|
||||
|
||||
builder.createMemoryCallReference(nodeAddress, "EXTERNAL:00000001");
|
||||
|
@ -111,8 +111,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertEquals("EXTERNAL:00000001", children.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ToPointer_ToExternalFunction() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ToPointer_ToExternalFunction() throws Exception {
|
||||
|
||||
//
|
||||
// Function A
|
||||
|
@ -137,8 +137,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertEquals(externalFunctionName, children.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ToPointer_ToNonExternalFunction()
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ToPointer_ToNonExternalFunction()
|
||||
throws Exception {
|
||||
|
||||
//
|
||||
|
@ -162,8 +162,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.get(0) instanceof DeadEndNode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ToPointer_Offcut() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_CallReference_ToPointer_Offcut() throws Exception {
|
||||
|
||||
//
|
||||
// Bad code case; expected reference to pointer, but no data there
|
||||
|
@ -179,21 +179,22 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.get(0) instanceof DeadEndNode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_WriteReference() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_WriteReference() throws Exception {
|
||||
|
||||
//
|
||||
// Have a reference in the function to a place that is not another function, and the
|
||||
// reference is a write reference. No call node is created.
|
||||
//
|
||||
|
||||
builder.createMemoryReference(nodeAddress, "0x1000", RefType.WRITE, SourceType.USER_DEFINED);
|
||||
builder.createMemoryReference(nodeAddress, "0x1000", RefType.WRITE,
|
||||
SourceType.USER_DEFINED);
|
||||
List<GTreeNode> children = node.generateChildren(TaskMonitor.DUMMY);
|
||||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_NullInstruction() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_NullInstruction() throws Exception {
|
||||
|
||||
//
|
||||
// Have a reference in the function to a place that is not another function, and the
|
||||
|
@ -208,8 +209,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_NotCallInstruction() throws Exception {
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_NotCallInstruction() throws Exception {
|
||||
|
||||
//
|
||||
// Read reference to an instruction with a flow type that is not a call
|
||||
|
@ -223,8 +224,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_InstructionAtToAddress()
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_InstructionAtToAddress()
|
||||
throws Exception {
|
||||
|
||||
//
|
||||
|
@ -243,8 +244,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_NoReference()
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_NoReference()
|
||||
throws Exception {
|
||||
|
||||
//
|
||||
|
@ -258,8 +259,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_NonExternalReference()
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_NonExternalReference()
|
||||
throws Exception {
|
||||
|
||||
//
|
||||
|
@ -277,8 +278,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_ExternalReference_NonFunctionSymbol()
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_ExternalReference_NonFunctionSymbol()
|
||||
throws Exception {
|
||||
|
||||
//
|
||||
|
@ -296,8 +297,8 @@ public class OutgoingFunctionCallNodeTest extends AbstractGenericTest {
|
|||
assertTrue(children.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_ExternalReference_FunctionSymbol()
|
||||
@Test
|
||||
public void testGenerateChildren_ReadReference_CallInstruction_ToData_ExternalReference_FunctionSymbol()
|
||||
throws Exception {
|
||||
|
||||
//
|
||||
|
|
|
@ -28,6 +28,7 @@ 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 {
|
||||
|
@ -118,11 +119,16 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest {
|
|||
|
||||
@Test
|
||||
public void testEditedDtCategoryRemoved() throws Exception {
|
||||
|
||||
DataTypeManager dtm = complexUnion.getDataTypeManager();
|
||||
Union refUnion = (Union) dtm.getDataType("/testCat/refUnion");
|
||||
assertNotNull(refUnion);
|
||||
|
||||
Category tempCat;
|
||||
try {
|
||||
startTransaction("Modify Program");
|
||||
tempCat = pgmRootCat.createCategory("Temp");
|
||||
tempCat.moveDataType(complexUnion, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
tempCat.moveDataType(refUnion, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
finally {
|
||||
endTransaction(true);
|
||||
|
@ -142,7 +148,7 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest {
|
|||
});
|
||||
|
||||
waitForSwing();
|
||||
// refUnion* gets removed since it has only a complexUnion* that was removed.
|
||||
// refUnion* gets removed
|
||||
assertEquals(num - 1, model.getNumComponents());
|
||||
assertTrue(dt18.isEquivalent(getDataType(18)));
|
||||
assertTrue(dt20.isEquivalent(getDataType(19)));
|
||||
|
@ -409,16 +415,31 @@ public class UnionEditorNotifiedTest extends AbstractUnionEditorTest {
|
|||
init(complexUnion, pgmTestCat, false);
|
||||
|
||||
int num = model.getNumComponents();
|
||||
|
||||
// Clone the data types we want to hold onto for comparison later, since reload can close the viewDTM.
|
||||
DataType dt18 = getDataType(18).clone(programDTM);
|
||||
DataType dt20 = getDataType(20).clone(programDTM);
|
||||
SwingUtilities.invokeLater(() -> complexUnion.getDataTypeManager().remove(complexUnion,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR));
|
||||
|
||||
DataTypeManager dtm = complexUnion.getDataTypeManager();
|
||||
Union refUnion = (Union) dtm.getDataType("/testCat/refUnion");
|
||||
assertNotNull(refUnion);
|
||||
|
||||
SwingUtilities.invokeLater(() -> dtm.remove(refUnion, TaskMonitor.DUMMY)); // remove refUnion
|
||||
waitForSwing();
|
||||
// refUnion* gets removed since it has only a complexUnion* that was removed.
|
||||
assertEquals(num - 1, model.getNumComponents());
|
||||
|
||||
// refUnion* gets removed (1 component)
|
||||
num -= 1;
|
||||
assertEquals(num, model.getNumComponents());
|
||||
assertTrue(dt18.isEquivalent(getDataType(18)));
|
||||
assertTrue(dt20.isEquivalent(getDataType(19)));
|
||||
|
||||
SwingUtilities.invokeLater(
|
||||
() -> simpleUnion.getDataTypeManager().remove(simpleUnion, TaskMonitor.DUMMY));
|
||||
waitForSwing();
|
||||
|
||||
// All components (3 total) which were dependent upon simpleUnion are removed
|
||||
num -= 3;
|
||||
assertEquals(num, model.getNumComponents());
|
||||
}
|
||||
finally {
|
||||
cleanup();
|
||||
|
|
|
@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
|
|||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.app.events.ProgramActivatedPluginEvent;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||
import ghidra.app.plugin.core.datapreview.DataTypePreviewPlugin.DTPPTableModel;
|
||||
|
@ -209,12 +210,19 @@ public class DataTypePreviewPluginTest extends AbstractGhidraHeadedIntegrationTe
|
|||
assertEquals("61004D00200065h", model.getValueAt(4, DTPPTableModel.PREVIEW_COL));// 8-byte long at offset 4
|
||||
assertEquals("72h", model.getValueAt(5, DTPPTableModel.PREVIEW_COL));// 2-byte short at offset 12
|
||||
|
||||
// deactivate program
|
||||
plugin.getTool().firePluginEvent(new ProgramActivatedPluginEvent("Test", null));
|
||||
waitForPostedSwingRunnables();
|
||||
|
||||
// NOTE: Altering data organization on-the-fly is not supported
|
||||
dataOrganization.setDefaultAlignment(2);
|
||||
dataOrganization.setShortSize(3);
|
||||
dataOrganization.setIntegerSize(3);
|
||||
dataOrganization.setLongSize(6);
|
||||
|
||||
plugin.updateModel();
|
||||
// activate program
|
||||
plugin.getTool().firePluginEvent(new ProgramActivatedPluginEvent("Test", program));
|
||||
waitForPostedSwingRunnables();
|
||||
|
||||
gotoService.goTo(addr(program, 0x100df26));
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.junit.*;
|
|||
import ghidra.app.cmd.memory.MoveBlockListener;
|
||||
import ghidra.app.cmd.memory.MoveBlockTask;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.data.DataTypeManagerDB;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
|
@ -81,7 +80,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
model.initialize(block);
|
||||
|
||||
int transactionID = x8051.startTransaction("Set settings");
|
||||
DataTypeManagerDB dtm = ((ProgramDB) x8051).getDataManager();
|
||||
DataTypeManagerDB dtm = (DataTypeManagerDB) x8051.getDataTypeManager();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Address a = getAddr(x8051, "BITS", i);
|
||||
dtm.setStringSettingsValue(a, "color", "red" + i);
|
||||
|
@ -197,8 +196,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
waitForCondition(() -> moveCompleted && x8051.canLock());
|
||||
|
||||
// make sure settings on data got moved
|
||||
DataTypeManagerDB dtm = ((ProgramDB) x8051).getDataManager();
|
||||
|
||||
DataTypeManagerDB dtm = (DataTypeManagerDB) x8051.getDataTypeManager();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Address a = getAddr(x8051, "CODE", 0x2000 + i);
|
||||
|
||||
|
|
|
@ -439,7 +439,7 @@ public class FollowFlowProgramBuilder extends ProgramBuilder {
|
|||
startTransaction();
|
||||
ProgramDB program = getProgram();
|
||||
Listing listing = program.getListing();
|
||||
Structure struct = new StructureDataType(name, thisStructureSize, program.getDataManager());
|
||||
Structure struct = new StructureDataType(name, thisStructureSize, program.getDataTypeManager());
|
||||
struct.replaceAtOffset(0, new FloatDataType(), 4, null, null);
|
||||
struct.replaceAtOffset(pointerOffset, new Pointer32DataType(), 4, null, null);
|
||||
listing.createData(addr(startOfStruct), struct);
|
||||
|
@ -473,7 +473,7 @@ public class FollowFlowProgramBuilder extends ProgramBuilder {
|
|||
startTransaction();
|
||||
ProgramDB program = getProgram();
|
||||
Listing listing = program.getListing();
|
||||
Structure struct = new StructureDataType(name, thisStructureSize, program.getDataManager());
|
||||
Structure struct = new StructureDataType(name, thisStructureSize, program.getDataTypeManager());
|
||||
struct.replaceAtOffset(0, new FloatDataType(), 4, null, null);
|
||||
struct.replaceAtOffset(pointerOffset, new Pointer32DataType(), 4, null, null);
|
||||
struct.replaceAtOffset(pointerOffset + pointerSize, new Pointer32DataType(), 4, null, null);
|
||||
|
|
|
@ -441,13 +441,8 @@ public class DataTypeSelectionDialogTest extends AbstractGhidraHeadedIntegration
|
|||
// Check that more than 2 non-equivalent data types trigger the dialog to appear.
|
||||
//
|
||||
Category secondCategory = rootCategory.createCategory("testCategory2");
|
||||
dataType = new CustomDataType(secondCategory.getCategoryPath(), crazyName, 2) {
|
||||
@Override
|
||||
public DataTypeManager getDataTypeManager() {
|
||||
return getProgramDataTypeManager(dataTypeManagers);
|
||||
}
|
||||
|
||||
};
|
||||
dataType = new CustomDataType(secondCategory.getCategoryPath(), crazyName, 2,
|
||||
getProgramDataTypeManager(dataTypeManagers));
|
||||
addDataType(secondCategory, dataType);
|
||||
|
||||
showDialogWithoutBlocking(tool, dialog);
|
||||
|
@ -1099,6 +1094,10 @@ public class DataTypeSelectionDialogTest extends AbstractGhidraHeadedIntegration
|
|||
}
|
||||
|
||||
private class CustomDataType extends StructureDataType {
|
||||
public CustomDataType(CategoryPath path, String name, int length, DataTypeManager dtm) {
|
||||
super(path, name, length, dtm);
|
||||
}
|
||||
|
||||
public CustomDataType(CategoryPath path, String name, int length) {
|
||||
super(path, name, length);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ArrayTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
public void setUp() throws Exception {
|
||||
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
listing = program.getListing();
|
||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||
transactionID = program.startTransaction("Test");
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/* ###
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private ProgramDB program;
|
||||
private int transactionID;
|
||||
|
||||
private Structure struct;
|
||||
private AddressSpace space;
|
||||
private TestEnv env;
|
||||
private CodeBrowserPlugin plugin;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram("Test", ProgramBuilder._TOY, this); // big-endian
|
||||
startTransaction();
|
||||
|
||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||
|
||||
program.getMemory().createInitializedBlock("m", addr(0x1000), 0x100, (byte) 0,
|
||||
TaskMonitor.DUMMY, false);
|
||||
|
||||
struct = createStructure("Test", 0);
|
||||
struct.setInternallyAligned(true);
|
||||
struct.addBitField(IntegerDataType.dataType, 3, "bf1", "Nuts");
|
||||
struct.addBitField(IntegerDataType.dataType, 24, "bf2", null);
|
||||
struct.addBitField(IntegerDataType.dataType, 4, "bf3", null);
|
||||
struct.addBitField(IntegerDataType.dataType, 12, "bf4", null);
|
||||
struct.addBitField(IntegerDataType.dataType, 3, "bf4a", null);
|
||||
struct.addBitField(IntegerDataType.dataType, 3, "bf5", null);
|
||||
struct.addBitField(IntegerDataType.dataType, 3, "b6", null);
|
||||
struct.add(new ByteDataType(), "field0", "Comment1");
|
||||
struct.add(new WordDataType(), null, "Comment2");
|
||||
struct.add(new DWordDataType(), "field3", null);
|
||||
struct.add(new ByteDataType(), "field4", "Comment4");
|
||||
|
||||
program.getListing().createData(addr(0x1010), struct);
|
||||
env = new TestEnv();
|
||||
PluginTool tool = env.launchDefaultTool(program);
|
||||
plugin = getPlugin(tool, CodeBrowserPlugin.class);
|
||||
}
|
||||
|
||||
private Address addr(long value) {
|
||||
return space.getAddress(value);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
endTransaction();
|
||||
env.dispose();
|
||||
}
|
||||
|
||||
protected Structure createStructure(String name, int length) {
|
||||
return (Structure) getDataTypeManager().resolve(new StructureDataType(name, length), null);
|
||||
}
|
||||
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
return program.getDataTypeManager();
|
||||
}
|
||||
|
||||
private void startTransaction() {
|
||||
transactionID = program.startTransaction("Test");
|
||||
}
|
||||
|
||||
private void endTransaction() {
|
||||
program.endTransaction(transactionID, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitField() throws Exception {
|
||||
openStructure(addr(0x1010));
|
||||
assertMnemonic("Test", addr(0x1010), 0);
|
||||
assertMnemonic("int:3", addr(0x1010), 1);
|
||||
assertMnemonic("int:24", addr(0x1010), 2);
|
||||
assertMnemonic("int:4", addr(0x1013), 0);
|
||||
assertMnemonic("int:12", addr(0x1014), 0);
|
||||
assertMnemonic("int:3", addr(0x1015), 0);
|
||||
assertMnemonic("int:3", addr(0x1015), 1);
|
||||
assertMnemonic("int:3", addr(0x1016), 0);
|
||||
assertMnemonic("db", addr(0x1017), 0);
|
||||
assertMnemonic("dw", addr(0x1018), 0);
|
||||
|
||||
System.out.println("wait");
|
||||
}
|
||||
|
||||
private void assertMnemonic(String expectedValue, Address addr, int occurrence) {
|
||||
plugin.goToField(addr, "Mnemonic", occurrence, 0, 0);
|
||||
assertEquals(expectedValue, plugin.getCurrentFieldText());
|
||||
}
|
||||
|
||||
private void openStructure(Address address) {
|
||||
// open the structure
|
||||
plugin.goToField(address, "+", 0, 0);
|
||||
click(plugin, 1);
|
||||
waitForSwing();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -73,7 +73,7 @@ public class CategoryTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
public void setUp() throws Exception {
|
||||
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
eventRecordingListener = new CategoryTestListener();
|
||||
dataMgr.addDataTypeManagerListener(eventRecordingListener);
|
||||
root = dataMgr.getRootCategory();
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ConflictHandlerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
startTransaction();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class DataManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
startTransaction();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public class EnumTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram("Test", ProgramBuilder._TOY, this);
|
||||
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
transactionID = program.startTransaction("Test");
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class FunctionDefinitionDBTest extends AbstractGhidraHeadedIntegrationTes
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
dtm = program.getDataManager();
|
||||
dtm = program.getDataTypeManager();
|
||||
startTransaction();
|
||||
FunctionDefinitionDataType fdt = new FunctionDefinitionDataType("test");
|
||||
fdt.setComment("My comments");
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
listing = program.getListing();
|
||||
transactionID = program.startTransaction("Test");
|
||||
addBlock();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -629,7 +629,7 @@ public class FunctionDBTest extends AbstractGhidraHeadedIntegrationTest implemen
|
|||
int initialParamCnt = f.getParameterCount();
|
||||
|
||||
Structure bar = new StructureDataType("bar", 20);
|
||||
Pointer barPtr = program.getDataManager().getPointer(bar);
|
||||
Pointer barPtr = program.getDataTypeManager().getPointer(bar);
|
||||
|
||||
Parameter returnVar = f.getReturn();
|
||||
Parameter p1 = f.getParameter(0);
|
||||
|
@ -697,7 +697,7 @@ public class FunctionDBTest extends AbstractGhidraHeadedIntegrationTest implemen
|
|||
int initialParamCnt = f.getParameterCount();
|
||||
|
||||
Structure bar = new StructureDataType("bar", 20);
|
||||
Pointer barPtr = program.getDataManager().getPointer(bar);
|
||||
Pointer barPtr = program.getDataTypeManager().getPointer(bar);
|
||||
|
||||
Parameter returnVar = f.getReturn();
|
||||
Parameter p1 = f.getParameter(0);
|
||||
|
|
|
@ -114,6 +114,7 @@ public class DataTypeUtilsTest {
|
|||
}
|
||||
|
||||
private class DataTypeDummy implements DataType {
|
||||
|
||||
String wrappedString;
|
||||
UniversalID id;
|
||||
|
||||
|
@ -132,6 +133,11 @@ public class DataTypeUtilsTest {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "This is a wrapper for: " + wrappedString;
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.List;
|
|||
import org.junit.*;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.cparser.C.ParseException;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
|
@ -39,6 +40,7 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
private volatile boolean dataChangeCalled;
|
||||
private Structure bigStruct;
|
||||
private ProgramDB program;
|
||||
private DataTypeManagerService service;
|
||||
private volatile boolean tableRowsChanged;
|
||||
|
||||
class MyModelChangeListener implements ModelChangeListener {
|
||||
|
@ -61,7 +63,6 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
program = builder.getProgram();
|
||||
bigStruct = new StructureDataType("bigStruct", 20);
|
||||
resolveBigStruct();
|
||||
|
||||
model = new FunctionEditorModel(null /* use default parser*/, fun);
|
||||
model.setModelChangeListener(new MyModelChangeListener());
|
||||
}
|
||||
|
@ -73,7 +74,6 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
Function fun = builder.createEmptyFunction("bob", "1000", 20, new VoidDataType());
|
||||
program = builder.getProgram();
|
||||
resolveBigStruct();
|
||||
|
||||
model = new FunctionEditorModel(null /* use default parser*/, fun);
|
||||
model.setModelChangeListener(new MyModelChangeListener());
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
private void resolveBigStruct() {
|
||||
int txId = program.startTransaction("Resolve bigStruct");
|
||||
try {
|
||||
program.getDataManager().resolve(bigStruct, null);
|
||||
program.getDataTypeManager().resolve(bigStruct, null);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
|
@ -972,9 +972,9 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
assertEquals("Stack[0x4]:1", param.getStorage().toString());
|
||||
|
||||
DataType struct = new StructureDataType("bigStruct", 100);
|
||||
DataType structPtr = PointerDataType.getPointer(struct, program.getDataManager());
|
||||
DataType structPtr = PointerDataType.getPointer(struct, program.getDataTypeManager());
|
||||
DataType voidPtr =
|
||||
PointerDataType.getPointer(VoidDataType.dataType, program.getDataManager());
|
||||
PointerDataType.getPointer(VoidDataType.dataType, program.getDataTypeManager());
|
||||
|
||||
model.setCallingConventionName(CompilerSpec.CALLING_CONVENTION_thiscall);
|
||||
|
||||
|
@ -1081,9 +1081,10 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
assertEquals("CL:1", param.getStorage().toString());
|
||||
|
||||
DataType struct = new StructureDataType("bigStruct", 100);
|
||||
DataType structPtr = PointerDataType.getPointer(struct, program.getDataManager());
|
||||
DataType structPtr = PointerDataType.getPointer(struct, program.getDataTypeManager());
|
||||
|
||||
DataType voidPtr =
|
||||
PointerDataType.getPointer(VoidDataType.dataType, program.getDataManager());
|
||||
PointerDataType.getPointer(VoidDataType.dataType, program.getDataTypeManager());
|
||||
|
||||
model.setCallingConventionName(CompilerSpec.CALLING_CONVENTION_thiscall);
|
||||
|
||||
|
@ -1722,7 +1723,7 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
int txId = program.startTransaction("Add TypeDef jjjjjj");
|
||||
try {
|
||||
DataType dt = new TypedefDataType("jjjjjj", ByteDataType.dataType);
|
||||
program.getDataManager().resolve(dt, null);
|
||||
program.getDataTypeManager().resolve(dt, null);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
|
@ -1919,4 +1920,5 @@ public class FunctionEditorModelTest extends AbstractGenericTest {
|
|||
private String getSignatureText() {
|
||||
return model.getFunctionSignatureTextFromModel();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class DWARFTestBase extends AbstractGhidraHeadedIntegrationTest {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program = createDefaultProgram(testName.getMethodName(), ProgramBuilder._TOY, this);
|
||||
dataMgr = program.getDataManager();
|
||||
dataMgr = program.getDataTypeManager();
|
||||
startTransaction();
|
||||
|
||||
AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
|
||||
|
|
|
@ -1407,11 +1407,11 @@ public class HTMLDataTypeRepresentationTest extends AbstractGenericTest {
|
|||
String name = componentAtIndex.getFieldName();
|
||||
|
||||
if (optionalName != null) {
|
||||
destinationComposite.insert(insertIndex, componentCopy, componentCopy.getLength(),
|
||||
destinationComposite.insert(insertIndex, componentCopy, componentAtIndex.getLength(),
|
||||
optionalName, null);
|
||||
}
|
||||
else {
|
||||
destinationComposite.insert(insertIndex, componentCopy, componentCopy.getLength(),
|
||||
destinationComposite.insert(insertIndex, componentCopy, componentAtIndex.getLength(),
|
||||
name + " Copy", null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
|
||||
public class MSVCStructureDBBitFieldTest extends MSVCStructureImplBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
getDataTypeManager().startTransaction("Test");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCStructureDBBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
dataMgr = new StandAloneDataTypeManager("Test");
|
||||
DataOrganizationImpl dataOrg = (DataOrganizationImpl) dataMgr.getDataOrganization();
|
||||
DataOrganizationTestUtils.initDataOrganizationWindows64BitX86(dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
|
||||
public class MSVCUnionDBBitFieldTest extends MSVCUnionImplBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
getDataTypeManager().startTransaction("Test");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCUnionDBBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
dataMgr = new StandAloneDataTypeManager("Test");
|
||||
DataOrganizationImpl dataOrg = (DataOrganizationImpl) dataMgr.getDataOrganization();
|
||||
DataOrganizationTestUtils.initDataOrganizationWindows64BitX86(dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
|
||||
public class StructureDBBigEndianBitFieldTest extends StructureImplBigEndianBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
getDataTypeManager().startTransaction("Test");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCStructureDBBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
dataMgr = new StandAloneDataTypeManager("Test");
|
||||
DataOrganizationImpl dataOrg = (DataOrganizationImpl) dataMgr.getDataOrganization();
|
||||
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
|
||||
public class StructureDBLittleEndianBitFieldTest extends StructureImplLittleEndianBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
getDataTypeManager().startTransaction("Test");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCStructureDBBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
dataMgr = new StandAloneDataTypeManager("Test");
|
||||
DataOrganizationImpl dataOrg = (DataOrganizationImpl) dataMgr.getDataOrganization();
|
||||
DataOrganizationTestUtils.initDataOrganizationGcc64BitX86(dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,21 +22,30 @@ import static org.junit.Assert.*;
|
|||
|
||||
import org.junit.*;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import generic.test.AbstractGTest;
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class StructureImplTest extends AbstractGenericTest {
|
||||
public class StructureDataTypeTest extends AbstractGTest {
|
||||
|
||||
private Structure struct;
|
||||
|
||||
/**
|
||||
* @param arg0
|
||||
*/
|
||||
public StructureImplTest() {
|
||||
super();
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
struct = createStructure("TestStruct", 0);
|
||||
struct.add(new ByteDataType(), "field1", "Comment1");
|
||||
struct.add(new WordDataType(), null, "Comment2");
|
||||
struct.add(new DWordDataType(), "field3", null);
|
||||
struct.add(new ByteDataType(), "field4", "Comment4");
|
||||
}
|
||||
|
||||
private void transitionToBigEndian() {
|
||||
|
||||
// transition default little-endian structure to big-endian
|
||||
DataTypeManager beDtm = new MyBigEndianDataTypeManager();
|
||||
struct = (Structure) struct.clone(beDtm);
|
||||
}
|
||||
|
||||
private Structure createStructure(String name, int length) {
|
||||
|
@ -56,21 +65,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
}
|
||||
|
||||
private Pointer createPointer(DataType dataType, int length) {
|
||||
return new Pointer32DataType(dataType);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
struct = createStructure("Test", 0);
|
||||
struct.add(new ByteDataType(), "field0", "Comment1");
|
||||
struct.add(new WordDataType(), null, "Comment2");
|
||||
struct.add(new DWordDataType(), "field3", null);
|
||||
struct.add(new ByteDataType(), "field4", "Comment4");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
|
||||
return new PointerDataType(dataType, length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -81,14 +76,15 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
DataTypeComponent dtc = struct.getComponent(0);
|
||||
assertEquals(0, dtc.getOffset());
|
||||
assertEquals(0, dtc.getOrdinal());
|
||||
assertEquals("field0", dtc.getFieldName());
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("Comment1", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(1);
|
||||
assertEquals(1, dtc.getOffset());
|
||||
assertEquals(1, dtc.getOrdinal());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals("field_0x1", dtc.getDefaultFieldName());
|
||||
assertEquals(null, dtc.getFieldName());
|
||||
assertEquals("Comment2", dtc.getComment());
|
||||
assertEquals(WordDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
|
@ -115,8 +111,8 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
assertEquals(10, struct.getLength());
|
||||
assertEquals(10, struct.getNumComponents());
|
||||
|
||||
struct.add(new ByteDataType(), "field0", "Comment1");
|
||||
struct.add(new WordDataType(), "field1", "Comment2");
|
||||
struct.add(new ByteDataType(), "field1", "Comment1");
|
||||
struct.add(new WordDataType(), null, "Comment2");
|
||||
struct.add(new DWordDataType(), "field3", null);
|
||||
struct.add(new ByteDataType(), "field4", "Comment4");
|
||||
|
||||
|
@ -126,28 +122,33 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
DataTypeComponent dtc = struct.getComponent(0);
|
||||
assertEquals(0, dtc.getOffset());
|
||||
assertEquals(0, dtc.getOrdinal());
|
||||
assertEquals("field_0x0", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals(null, dtc.getComment());
|
||||
assertNull(dtc.getComment());
|
||||
assertEquals(DataType.DEFAULT, dtc.getDataType());
|
||||
|
||||
dtc = struct.getComponent(1);
|
||||
assertEquals(1, dtc.getOffset());
|
||||
assertEquals(1, dtc.getOrdinal());
|
||||
assertEquals("field_0x1", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
|
||||
assertEquals(null, dtc.getComment());
|
||||
assertEquals(DataType.DEFAULT, dtc.getDataType());
|
||||
|
||||
dtc = struct.getComponent(10);
|
||||
assertEquals(10, dtc.getOffset());
|
||||
assertEquals(10, dtc.getOrdinal());
|
||||
assertEquals("field0", dtc.getFieldName());
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("Comment1", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(11);
|
||||
assertEquals(11, dtc.getOffset());
|
||||
assertEquals(11, dtc.getOrdinal());
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("field_0xb", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
|
||||
assertEquals("Comment2", dtc.getComment());
|
||||
assertEquals(WordDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
|
@ -168,20 +169,22 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
DataTypeComponent dtc = struct.getComponent(0);
|
||||
assertEquals(0, dtc.getOffset());
|
||||
assertEquals(0, dtc.getOrdinal());
|
||||
assertEquals(null, dtc.getFieldName());
|
||||
assertEquals(null, dtc.getComment());
|
||||
assertEquals("field_0x0", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertNull(dtc.getComment());
|
||||
assertEquals(FloatDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(1);
|
||||
assertEquals(4, dtc.getOffset());
|
||||
assertEquals(1, dtc.getOrdinal());
|
||||
assertEquals("field0", dtc.getFieldName());
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("Comment1", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(2);
|
||||
assertEquals(5, dtc.getOffset());
|
||||
assertEquals(2, dtc.getOrdinal());
|
||||
assertEquals("field_0x5", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals("Comment2", dtc.getComment());
|
||||
assertEquals(WordDataType.class, dtc.getDataType().getClass());
|
||||
|
@ -204,6 +207,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testInsert_end() {
|
||||
|
||||
struct.insert(4, new FloatDataType());
|
||||
assertEquals(12, struct.getLength());
|
||||
assertEquals(5, struct.getNumComponents());
|
||||
|
@ -211,14 +215,15 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
DataTypeComponent dtc = struct.getComponent(0);
|
||||
assertEquals(0, dtc.getOffset());
|
||||
assertEquals(0, dtc.getOrdinal());
|
||||
assertEquals("field0", dtc.getFieldName());
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("Comment1", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(1);
|
||||
assertEquals(1, dtc.getOffset());
|
||||
assertEquals(1, dtc.getOrdinal());
|
||||
assertEquals(null, dtc.getFieldName());
|
||||
assertEquals("field_0x1", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals("Comment2", dtc.getComment());
|
||||
assertEquals(WordDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
|
@ -239,6 +244,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
dtc = struct.getComponent(4);
|
||||
assertEquals(8, dtc.getOffset());
|
||||
assertEquals(4, dtc.getOrdinal());
|
||||
assertEquals("field_0x8", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals(null, dtc.getComment());
|
||||
assertEquals(FloatDataType.class, dtc.getDataType().getClass());
|
||||
|
@ -247,6 +253,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testInsert_middle() {
|
||||
|
||||
struct.insert(2, new FloatDataType());
|
||||
assertEquals(12, struct.getLength());
|
||||
assertEquals(5, struct.getNumComponents());
|
||||
|
@ -254,13 +261,14 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
DataTypeComponent dtc = struct.getComponent(0);
|
||||
assertEquals(0, dtc.getOffset());
|
||||
assertEquals(0, dtc.getOrdinal());
|
||||
assertEquals("field0", dtc.getFieldName());
|
||||
assertEquals("field1", dtc.getFieldName());
|
||||
assertEquals("Comment1", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(1);
|
||||
assertEquals(1, dtc.getOffset());
|
||||
assertEquals(1, dtc.getOrdinal());
|
||||
assertEquals("field_0x1", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals("Comment2", dtc.getComment());
|
||||
assertEquals(WordDataType.class, dtc.getDataType().getClass());
|
||||
|
@ -268,8 +276,9 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
dtc = struct.getComponent(2);
|
||||
assertEquals(3, dtc.getOffset());
|
||||
assertEquals(2, dtc.getOrdinal());
|
||||
assertEquals("field_0x3", dtc.getDefaultFieldName());
|
||||
assertNull(dtc.getFieldName());
|
||||
assertEquals(null, dtc.getComment());
|
||||
assertNull(dtc.getComment());
|
||||
assertEquals(FloatDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
dtc = struct.getComponent(3);
|
||||
|
@ -285,6 +294,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
assertEquals("field4", dtc.getFieldName());
|
||||
assertEquals("Comment4", dtc.getComment());
|
||||
assertEquals(ByteDataType.class, dtc.getDataType().getClass());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -403,6 +413,304 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
assertEquals(104, struct.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertBitFieldLittleEndianAppend() throws Exception {
|
||||
|
||||
struct.insertBitField(4, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 word 2 null \"Comment2\"\n" +
|
||||
" 3 dword 4 field3 \"\"\n" +
|
||||
" 7 byte 1 field4 \"Comment4\"\n" +
|
||||
" 8 int:3(0) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 9 undefined 1 null \"\"\n" +
|
||||
" 10 undefined 1 null \"\"\n" +
|
||||
" 11 undefined 1 null \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
struct.insertBitField(4, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 word 2 null \"Comment2\"\n" +
|
||||
" 3 dword 4 field3 \"\"\n" +
|
||||
" 7 byte 1 field4 \"Comment4\"\n" +
|
||||
" 8 int:3(0) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 8 int:3(3) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 9 undefined 1 null \"\"\n" +
|
||||
" 10 undefined 1 null \"\"\n" +
|
||||
" 11 undefined 1 null \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertBitFieldAtLittleEndianAppend() throws Exception {
|
||||
|
||||
struct.insertBitFieldAt(10, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 word 2 null \"Comment2\"\n" +
|
||||
" 3 dword 4 field3 \"\"\n" +
|
||||
" 7 byte 1 field4 \"Comment4\"\n" +
|
||||
" 8 undefined 1 null \"\"\n" +
|
||||
" 9 undefined 1 null \"\"\n" +
|
||||
" 10 int:3(0) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 11 undefined 1 null \"\"\n" +
|
||||
" 12 undefined 1 null \"\"\n" +
|
||||
" 13 undefined 1 null \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 14 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
struct.insertBitFieldAt(10, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 word 2 null \"Comment2\"\n" +
|
||||
" 3 dword 4 field3 \"\"\n" +
|
||||
" 7 byte 1 field4 \"Comment4\"\n" +
|
||||
" 8 undefined 1 null \"\"\n" +
|
||||
" 9 undefined 1 null \"\"\n" +
|
||||
" 10 int:3(0) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 10 int:3(3) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 11 undefined 1 null \"\"\n" +
|
||||
" 12 undefined 1 null \"\"\n" +
|
||||
" 13 undefined 1 null \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 14 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertBitFieldAtLittleEndian() throws Exception {
|
||||
|
||||
struct.insertBitFieldAt(2, 4, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\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 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.insertBitFieldAt(2, 4, 3, IntegerDataType.dataType, 3, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\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" +
|
||||
" 3 undefined 1 null \"\"\n" +
|
||||
" 4 undefined 1 null \"\"\n" +
|
||||
" 5 undefined 1 null \"\"\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.insertBitFieldAt(2, 4, 6, IntegerDataType.dataType, 15, "bf3", "bf3Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\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" +
|
||||
" 5 undefined 1 null \"\"\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
|
||||
|
||||
try {
|
||||
struct.insertBitFieldAt(2, 4, 21, IntegerDataType.dataType, 12, "bf4", "bf4Comment");
|
||||
fail(
|
||||
"expected - IllegalArgumentException: Bitfield does not fit within specified constraints");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
struct.insertBitFieldAt(2, 4, 21, IntegerDataType.dataType, 11, "bf4", "bf4Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\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
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertBitFieldAtBigEndian() throws Exception {
|
||||
|
||||
transitionToBigEndian();
|
||||
|
||||
try {
|
||||
struct.insertBitFieldAt(2, 4, 30, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
|
||||
fail(
|
||||
"expected - IllegalArgumentException: Bitfield does not fit within specified constraints");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
struct.insertBitFieldAt(2, 4, 29, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 undefined 1 null \"\"\n" +
|
||||
" 2 int:3(5) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 3 undefined 1 null \"\"\n" +
|
||||
" 4 undefined 1 null \"\"\n" +
|
||||
" 5 undefined 1 null \"\"\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.insertBitFieldAt(2, 4, 26, IntegerDataType.dataType, 3, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 undefined 1 null \"\"\n" +
|
||||
" 2 int:3(5) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 2 int:3(2) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 3 undefined 1 null \"\"\n" +
|
||||
" 4 undefined 1 null \"\"\n" +
|
||||
" 5 undefined 1 null \"\"\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.insertBitFieldAt(2, 4, 11, IntegerDataType.dataType, 15, "bf3", "bf3Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 undefined 1 null \"\"\n" +
|
||||
" 2 int:3(5) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 2 int:3(2) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 2 int:15(3) 3 bf3 \"bf3Comment\"\n" +
|
||||
" 5 undefined 1 null \"\"\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.insertBitFieldAt(2, 4, 0, IntegerDataType.dataType, 11, "bf4", "bf4Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 undefined 1 null \"\"\n" +
|
||||
" 2 int:3(5) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 2 int:3(2) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 2 int:15(3) 3 bf3 \"bf3Comment\"\n" +
|
||||
" 4 int:11(0) 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
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertAtOffsetAfterBeforeBitField() throws Exception {
|
||||
|
||||
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");
|
||||
|
||||
struct.insertAtOffset(2, FloatDataType.dataType, 4);
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 undefined 1 null \"\"\n" +
|
||||
" 2 float 4 null \"\"\n" +
|
||||
" 6 int:3(0) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 6 int:3(3) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 6 int:15(6) 3 bf3 \"bf3Comment\"\n" +
|
||||
" 8 int:11(5) 2 bf4 \"bf4Comment\"\n" +
|
||||
" 10 word 2 null \"Comment2\"\n" +
|
||||
" 12 dword 4 field3 \"\"\n" +
|
||||
" 16 byte 1 field4 \"Comment4\"\n" +
|
||||
"}\n" +
|
||||
"Size = 17 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearComponent() {
|
||||
struct.clearComponent(0);
|
||||
|
@ -444,7 +752,17 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testReplace1() {// bigger, space below
|
||||
public void testReplace() { // bigger, no space below
|
||||
try {
|
||||
struct.replace(0, new QWordDataType(), 8);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplace1() { // bigger, space below
|
||||
struct.insert(1, new QWordDataType());
|
||||
struct.clearComponent(1);
|
||||
assertEquals(16, struct.getLength());
|
||||
|
@ -459,7 +777,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testReplace2() {// same size
|
||||
public void testReplace2() { // same size
|
||||
struct.replace(0, new CharDataType(), 1);
|
||||
assertEquals(8, struct.getLength());
|
||||
assertEquals(4, struct.getNumComponents());
|
||||
|
@ -470,7 +788,7 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testReplace3() {// smaller
|
||||
public void testReplace3() { // smaller
|
||||
struct.replace(1, new CharDataType(), 1);
|
||||
assertEquals(8, struct.getLength());
|
||||
assertEquals(5, struct.getNumComponents());
|
||||
|
@ -623,13 +941,66 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
s.add(new FloatDataType());
|
||||
|
||||
struct.add(s);
|
||||
|
||||
s.deleteAll();
|
||||
assertEquals(1, s.getLength());
|
||||
assertTrue(s.isNotYetDefined());
|
||||
assertEquals(0, s.getNumComponents());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponents() {
|
||||
struct = createStructure("Test", 8);
|
||||
struct.insert(2, new ByteDataType(), 1, "field3", "Comment1");
|
||||
struct.insert(5, new WordDataType(), 2, null, "Comment2");
|
||||
struct.insert(7, new DWordDataType(), 4, "field8", null);
|
||||
assertEquals(15, struct.getLength());
|
||||
assertEquals(11, struct.getNumComponents());
|
||||
DataTypeComponent[] dtcs = struct.getComponents();
|
||||
assertEquals(11, dtcs.length);
|
||||
int offset = 0;
|
||||
for (int i = 0; i < 11; i++) {
|
||||
assertEquals(i, dtcs[i].getOrdinal());
|
||||
assertEquals(offset, dtcs[i].getOffset());
|
||||
offset += dtcs[i].getLength();
|
||||
}
|
||||
assertEquals(DataType.DEFAULT, dtcs[0].getDataType());
|
||||
assertEquals(DataType.DEFAULT, dtcs[1].getDataType());
|
||||
assertEquals(ByteDataType.class, dtcs[2].getDataType().getClass());
|
||||
assertEquals(DataType.DEFAULT, dtcs[3].getDataType());
|
||||
assertEquals(DataType.DEFAULT, dtcs[4].getDataType());
|
||||
assertEquals(WordDataType.class, dtcs[5].getDataType().getClass());
|
||||
assertEquals(DataType.DEFAULT, dtcs[6].getDataType());
|
||||
assertEquals(DWordDataType.class, dtcs[7].getDataType().getClass());
|
||||
assertEquals(DataType.DEFAULT, dtcs[8].getDataType());
|
||||
assertEquals(DataType.DEFAULT, dtcs[9].getDataType());
|
||||
assertEquals(DataType.DEFAULT, dtcs[10].getDataType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefinedComponents() {
|
||||
struct = createStructure("Test", 8);
|
||||
struct.insert(2, new ByteDataType(), 1, "field3", "Comment1");
|
||||
struct.insert(5, new WordDataType(), 2, null, "Comment2");
|
||||
struct.insert(7, new DWordDataType(), 4, "field8", null);
|
||||
assertEquals(15, struct.getLength());
|
||||
assertEquals(11, struct.getNumComponents());
|
||||
DataTypeComponent[] dtcs = struct.getDefinedComponents();
|
||||
assertEquals(3, dtcs.length);
|
||||
|
||||
assertEquals(ByteDataType.class, dtcs[0].getDataType().getClass());
|
||||
assertEquals(2, dtcs[0].getOrdinal());
|
||||
assertEquals(2, dtcs[0].getOffset());
|
||||
|
||||
assertEquals(WordDataType.class, dtcs[1].getDataType().getClass());
|
||||
assertEquals(5, dtcs[1].getOrdinal());
|
||||
assertEquals(5, dtcs[1].getOffset());
|
||||
|
||||
assertEquals(DWordDataType.class, dtcs[2].getDataType().getClass());
|
||||
assertEquals(7, dtcs[2].getOrdinal());
|
||||
assertEquals(8, dtcs[2].getOffset());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetComponentAt() {
|
||||
DataTypeComponent dtc = struct.getComponentAt(4);
|
||||
|
@ -638,19 +1009,6 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
assertEquals(3, dtc.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataTypeAt() {
|
||||
Structure s1 = createStructure("Test1", 0);
|
||||
s1.add(new WordDataType());
|
||||
s1.add(struct);
|
||||
s1.add(new ByteDataType());
|
||||
|
||||
DataTypeComponent dtc = s1.getComponentAt(7);
|
||||
assertEquals(struct, dtc.getDataType());
|
||||
dtc = s1.getDataTypeAt(7);
|
||||
assertEquals(DWordDataType.class, dtc.getDataType().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddVarLengthDataTypes() {
|
||||
Structure s1 = createStructure("Test1", 0);
|
||||
|
@ -732,6 +1090,134 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
assertEquals("NewTypedef", typdef.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDataTypeAt() {
|
||||
Structure s1 = createStructure("Test1", 0);
|
||||
s1.add(new WordDataType());
|
||||
s1.add(struct);
|
||||
s1.add(new ByteDataType());
|
||||
|
||||
DataTypeComponent dtc = s1.getComponentAt(7);
|
||||
assertEquals(struct, dtc.getDataType());
|
||||
dtc = s1.getDataTypeAt(7);
|
||||
assertEquals(DWordDataType.class, dtc.getDataType().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceWith() {
|
||||
assertEquals(8, struct.getLength());
|
||||
assertEquals(4, struct.getNumComponents());
|
||||
|
||||
Structure newStruct = createStructure("Replaced", 8);
|
||||
newStruct.setDescription("testReplaceWith()");
|
||||
DataTypeComponent dtc0 = newStruct.insert(2, new ByteDataType(), 1, "field3", "Comment1");
|
||||
DataTypeComponent dtc1 = newStruct.insert(5, new WordDataType(), 2, null, "Comment2");
|
||||
DataTypeComponent dtc2 = newStruct.insert(7, new DWordDataType(), 4, "field8", null);
|
||||
|
||||
struct.replaceWith(newStruct);
|
||||
assertEquals(15, struct.getLength());
|
||||
assertEquals(11, struct.getNumComponents());
|
||||
DataTypeComponent[] dtcs = struct.getDefinedComponents();
|
||||
assertEquals(3, dtcs.length);
|
||||
assertEquals(dtc0, dtcs[0]);
|
||||
assertEquals(dtc1, dtcs[1]);
|
||||
assertEquals(dtc2, dtcs[2]);
|
||||
assertEquals("TestStruct", struct.getName());
|
||||
assertEquals("", struct.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceWith2() throws InvalidDataTypeException {
|
||||
|
||||
// NOTE: unaligned bitfields should remain unchanged when
|
||||
// transitioning endianess even though it makes little sense.
|
||||
// Unaligned structures are not intended to be portable!
|
||||
|
||||
TypeDef td = new TypedefDataType("Foo", IntegerDataType.dataType);
|
||||
|
||||
struct.insertBitFieldAt(9, 1, 0, td, 4, "MyBit1", "bitComment1");
|
||||
struct.insertBitFieldAt(9, 1, 4, td, 3, "MyBit2", "bitComment2");
|
||||
struct.insertBitFieldAt(9, 2, 7, td, 2, "MyBit3", "bitComment3");
|
||||
struct.growStructure(1);
|
||||
|
||||
struct.setFlexibleArrayComponent(td, "myFlex", "flexComment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure TestStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 word 2 null \"Comment2\"\n" +
|
||||
" 3 dword 4 field3 \"\"\n" +
|
||||
" 7 byte 1 field4 \"Comment4\"\n" +
|
||||
" 8 undefined 1 null \"\"\n" +
|
||||
" 9 Foo:4(0) 1 MyBit1 \"bitComment1\"\n" +
|
||||
" 9 Foo:3(4) 1 MyBit2 \"bitComment2\"\n" +
|
||||
" 9 Foo:2(7) 2 MyBit3 \"bitComment3\"\n" +
|
||||
" 11 undefined 1 null \"\"\n" +
|
||||
" Foo[0] 0 myFlex \"flexComment\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
|
||||
DataTypeManager beDtm = new MyBigEndianDataTypeManager();
|
||||
|
||||
Structure newStruct = new StructureDataType("bigStruct", 0, beDtm);
|
||||
newStruct.replaceWith(struct);
|
||||
|
||||
assertTrue(newStruct.getDataOrganization().isBigEndian());
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/bigStruct\n" +
|
||||
"Unaligned\n" +
|
||||
"Structure bigStruct {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 1 word 2 null \"Comment2\"\n" +
|
||||
" 3 dword 4 field3 \"\"\n" +
|
||||
" 7 byte 1 field4 \"Comment4\"\n" +
|
||||
" 8 undefined 1 null \"\"\n" +
|
||||
" 9 Foo:4(0) 1 MyBit1 \"bitComment1\"\n" +
|
||||
" 9 Foo:3(4) 1 MyBit2 \"bitComment2\"\n" +
|
||||
" 9 Foo:2(7) 2 MyBit3 \"bitComment3\"\n" +
|
||||
" 11 undefined 1 null \"\"\n" +
|
||||
" Foo[0] 0 myFlex \"flexComment\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 1", newStruct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a structure can't ... ???
|
||||
*/
|
||||
@Test
|
||||
public void testCyclingProblem() {
|
||||
Structure newStruct = createStructure("TestStruct", 80);
|
||||
newStruct.setDescription("testReplaceWith()");
|
||||
newStruct.add(new ByteDataType(), "field0", "Comment1");
|
||||
newStruct.add(struct, "field1", null);
|
||||
newStruct.add(new WordDataType(), null, "Comment2");
|
||||
newStruct.add(new DWordDataType(), "field3", null);
|
||||
|
||||
try {
|
||||
struct.add(newStruct);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
struct.insert(0, newStruct);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
struct.replace(0, newStruct, newStruct.getLength());
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a structure can't be added to itself.
|
||||
*/
|
||||
|
@ -1049,4 +1535,13 @@ public class StructureImplTest extends AbstractGenericTest {
|
|||
}
|
||||
}
|
||||
|
||||
protected class MyBigEndianDataTypeManager extends StandAloneDataTypeManager {
|
||||
MyBigEndianDataTypeManager() {
|
||||
super("BEdtm");
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
dataOrg.setBigEndian(true);
|
||||
this.dataOrganization = dataOrg;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
|
||||
public class UnionDBBigEndianBitFieldTest extends UnionImplBigEndianBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
getDataTypeManager().startTransaction("Test");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCStructureDBBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
dataMgr = new StandAloneDataTypeManager("Test");
|
||||
DataOrganizationImpl dataOrg = (DataOrganizationImpl) dataMgr.getDataOrganization();
|
||||
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
|
||||
public class UnionDBLittleEndianBitFieldTest extends UnionImplLittleEndianBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
getDataTypeManager().startTransaction("Test");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCStructureDBBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
dataMgr = new StandAloneDataTypeManager("Test");
|
||||
DataOrganizationImpl dataOrg = (DataOrganizationImpl) dataMgr.getDataOrganization();
|
||||
DataOrganizationTestUtils.initDataOrganizationGcc64BitX86(dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,79 +13,59 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package ghidra.program.database.data;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import generic.test.AbstractGTest;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
|
||||
/**
|
||||
* Test the database implementation of Union data type.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class UnionTest extends AbstractGenericTest {
|
||||
public class UnionDataTypeTest extends AbstractGTest {
|
||||
|
||||
private Union union;
|
||||
private ProgramDB program;
|
||||
private DataTypeManagerDB dataMgr;
|
||||
private int transactionID;
|
||||
|
||||
/**
|
||||
* Constructor for UnionTest.
|
||||
* @param name
|
||||
*/
|
||||
public UnionTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
private Structure createStructure(String name, int length) {
|
||||
return (Structure) dataMgr.resolve(new StructureDataType(name, length),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
|
||||
private Union createUnion(String name) {
|
||||
return (Union) dataMgr.resolve(new UnionDataType(name),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
|
||||
private TypeDef createTypeDef(DataType dataType) {
|
||||
return (TypeDef) dataMgr.resolve(
|
||||
new TypedefDataType(dataType.getName() + "TypeDef", dataType), null);
|
||||
}
|
||||
|
||||
private Array createArray(DataType dataType, int numElements) {
|
||||
return (Array) dataMgr.resolve(
|
||||
new ArrayDataType(dataType, numElements, dataType.getLength()), null);
|
||||
}
|
||||
|
||||
private Pointer createPointer(DataType dataType, int length) {
|
||||
return (Pointer) dataMgr.resolve(new Pointer32DataType(dataType), null);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program =
|
||||
AbstractGhidraHeadlessIntegrationTest.createDefaultProgram("Test", ProgramBuilder._TOY, this);
|
||||
dataMgr = program.getDataManager();
|
||||
transactionID = program.startTransaction("Test");
|
||||
union = createUnion("Test");
|
||||
union = createUnion("TestUnion");
|
||||
union.add(new ByteDataType(), "field1", "Comment1");
|
||||
union.add(new WordDataType(), null, "Comment2");
|
||||
union.add(new DWordDataType(), "field3", null);
|
||||
union.add(new ByteDataType(), "field4", "Comment4");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
program.endTransaction(transactionID, true);
|
||||
program.release(this);
|
||||
private void transitionToBigEndian() {
|
||||
|
||||
// transition default little-endian structure to big-endian
|
||||
DataTypeManager beDtm = new MyBigEndianDataTypeManager();
|
||||
union = (Union) union.clone(beDtm);
|
||||
}
|
||||
|
||||
private Union createUnion(String name) {
|
||||
return new UnionDataType(name);
|
||||
}
|
||||
|
||||
private Structure createStructure(String name, int size) {
|
||||
return new StructureDataType(name, size);
|
||||
}
|
||||
|
||||
private TypeDef createTypeDef(DataType dataType) {
|
||||
return new TypedefDataType(dataType.getName() + "TypeDef", dataType);
|
||||
}
|
||||
|
||||
private Array createArray(DataType dataType, int numElements) {
|
||||
return new ArrayDataType(dataType, numElements, dataType.getLength());
|
||||
}
|
||||
|
||||
private Pointer createPointer(DataType dataType, int length) {
|
||||
return new PointerDataType(dataType, length);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -109,12 +89,11 @@ public class UnionTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testAdd2() {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
Structure struct = createStructure("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new StringDataType(), 10);
|
||||
|
||||
union.add(struct);
|
||||
|
||||
union.delete(4);
|
||||
assertEquals(4, union.getNumComponents());
|
||||
assertEquals(4, union.getLength());
|
||||
|
@ -122,7 +101,7 @@ public class UnionTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testGetComponent() {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
Structure struct = createStructure("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new StringDataType(), 10);
|
||||
DataTypeComponent newdtc = union.add(struct, "field5", "comments");
|
||||
|
@ -135,7 +114,7 @@ public class UnionTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testGetComponents() {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
Structure struct = createStructure("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new StringDataType(), 10);
|
||||
union.add(struct, "field5", "comments");
|
||||
|
@ -147,7 +126,7 @@ public class UnionTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testInsert() {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
Structure struct = createStructure("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new StringDataType(), 10);
|
||||
|
||||
|
@ -161,20 +140,92 @@ public class UnionTest extends AbstractGenericTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetName() {
|
||||
assertEquals("Test", union.getName());
|
||||
public void testBitFieldUnionLength() throws Exception {
|
||||
|
||||
int cnt = union.getNumComponents();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
union.delete(0);
|
||||
}
|
||||
union.insertBitField(0, 4, 12, IntegerDataType.dataType, 2, "bf1", "bf1Comment");
|
||||
union.insert(0, ShortDataType.dataType);
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
"Unaligned\n" +
|
||||
"Union TestUnion {\n" +
|
||||
" 0 short 2 null \"\"\n" +
|
||||
" 1 byte:2(4) 1 bf1 \"bf1Comment\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", union);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClone() throws Exception {
|
||||
public void testInsertBitFieldLittleEndian() throws Exception {
|
||||
|
||||
union.insertBitField(2, 4, 0, IntegerDataType.dataType, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, 1, 0, ByteDataType.dataType, 4, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
"Unaligned\n" +
|
||||
"Union TestUnion {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 0 word 2 null \"Comment2\"\n" +
|
||||
" 0 int:4(0) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 0 byte:4(0) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 0 dword 4 field3 \"\"\n" +
|
||||
" 0 byte 1 field4 \"Comment4\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", union);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertBitFieldBigEndian() throws Exception {
|
||||
|
||||
transitionToBigEndian();
|
||||
|
||||
union.insertBitField(2, 4, 0, IntegerDataType.dataType, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, 1, 0, ByteDataType.dataType, 4, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
"Unaligned\n" +
|
||||
"Union TestUnion {\n" +
|
||||
" 0 byte 1 field1 \"Comment1\"\n" +
|
||||
" 0 word 2 null \"Comment2\"\n" +
|
||||
" 0 int:4(4) 1 bf1 \"bf1Comment\"\n" +
|
||||
" 0 byte:4(4) 1 bf2 \"bf2Comment\"\n" +
|
||||
" 0 dword 4 field3 \"\"\n" +
|
||||
" 0 byte 1 field4 \"Comment4\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", union);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetName() {
|
||||
assertEquals("TestUnion", union.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloneRetainIdentity() throws Exception {
|
||||
Union unionCopy = (Union) union.clone(null);
|
||||
assertNull(unionCopy.getDataTypeManager());
|
||||
assertEquals(4, union.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyDontRetain() throws Exception {
|
||||
Union unionCopy = (Union) union.copy(null);
|
||||
assertNull(unionCopy.getDataTypeManager());
|
||||
assertEquals(4, union.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
Structure struct = createStructure("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new StringDataType(), 10);
|
||||
union.add(struct);
|
||||
|
@ -189,16 +240,15 @@ public class UnionTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testIsPartOf() {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
Structure struct = createStructure("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
DataTypeComponent dtc = struct.add(new StringDataType(), 10);
|
||||
DataTypeComponent newdtc = union.add(struct);
|
||||
dtc = union.getComponent(4);
|
||||
DataTypeComponent dtc = struct.add(createStructure("mystring", 10));
|
||||
DataType dt = dtc.getDataType();
|
||||
DataTypeComponent newdtc = union.add(struct);
|
||||
assertTrue(union.isPartOf(dt));
|
||||
|
||||
Structure newstruct = (Structure) newdtc.getDataType();
|
||||
Structure s1 = (Structure) newstruct.add(new StructureDataType("s1", 1)).getDataType();
|
||||
Structure s1 = (Structure) newstruct.add(createStructure("s1", 1)).getDataType();
|
||||
dt = s1.add(new QWordDataType()).getDataType();
|
||||
|
||||
assertTrue(union.isPartOf(dt));
|
||||
|
@ -206,18 +256,48 @@ public class UnionTest extends AbstractGenericTest {
|
|||
|
||||
@Test
|
||||
public void testReplaceWith() {
|
||||
Structure struct = new StructureDataType("struct_1", 0);
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new StringDataType(), 10);
|
||||
Union newunion = new UnionDataType("newunion");
|
||||
newunion.add(struct);
|
||||
assertEquals(4, union.getLength());
|
||||
assertEquals(4, union.getNumComponents());
|
||||
|
||||
union.replaceWith(newunion);
|
||||
assertEquals(1, newunion.getNumComponents());
|
||||
DataType dt = dataMgr.getDataType("/struct_1");
|
||||
assertNotNull(dt);
|
||||
Union newUnion = createUnion("Replaced");
|
||||
newUnion.setDescription("testReplaceWith()");
|
||||
DataTypeComponent dtc2 = newUnion.insert(0, new DWordDataType(), 4, "field2", null);
|
||||
DataTypeComponent dtc1 = newUnion.insert(0, new WordDataType(), 2, null, "Comment2");
|
||||
DataTypeComponent dtc0 = newUnion.insert(0, new ByteDataType(), 1, "field0", "Comment1");
|
||||
|
||||
assertEquals(dt, union.getComponent(0).getDataType());
|
||||
union.replaceWith(newUnion);
|
||||
assertEquals(4, union.getLength());
|
||||
assertEquals(3, union.getNumComponents());
|
||||
DataTypeComponent[] dtcs = union.getComponents();
|
||||
assertEquals(3, dtcs.length);
|
||||
assertEquals(dtc0, dtcs[0]);
|
||||
assertEquals(dtc1, dtcs[1]);
|
||||
assertEquals(dtc2, dtcs[2]);
|
||||
assertEquals("TestUnion", union.getName());
|
||||
assertEquals("", union.getDescription()); // unchanged
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCyclingProblem() {
|
||||
Union newUnion = createUnion("Test");
|
||||
newUnion.setDescription("testReplaceWith()");
|
||||
newUnion.add(new ByteDataType(), "field0", "Comment1");
|
||||
newUnion.add(union, "field1", null);
|
||||
newUnion.add(new WordDataType(), null, "Comment2");
|
||||
newUnion.add(new DWordDataType(), "field3", null);
|
||||
|
||||
try {
|
||||
union.add(newUnion);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
union.insert(0, newUnion);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -453,4 +533,12 @@ public class UnionTest extends AbstractGenericTest {
|
|||
}
|
||||
}
|
||||
|
||||
protected class MyBigEndianDataTypeManager extends StandAloneDataTypeManager {
|
||||
MyBigEndianDataTypeManager() {
|
||||
super("BEdtm");
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
dataOrg.setBigEndian(true);
|
||||
this.dataOrganization = dataOrg;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/* ###
|
||||
* 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 static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import generic.test.AbstractGTest;
|
||||
import ghidra.app.util.cparser.C.CParser;
|
||||
import ghidra.util.Msg;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public abstract class AbstractCompositeImplBitFieldTest extends AbstractGTest {
|
||||
|
||||
protected static final String C_SOURCE_FILE = "ghidra/app/util/cparser/bitfields.h";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
DataTypeManager dataMgr = getDataTypeManager();
|
||||
if (dataMgr.getDataTypeCount(false) != 0) {
|
||||
Msg.info(this, "Using previously parsed data types");
|
||||
return; // already have types
|
||||
}
|
||||
|
||||
Msg.info(this, "Parsing data types from " + C_SOURCE_FILE);
|
||||
|
||||
CParser parser = new CParser(dataMgr, true, null);
|
||||
|
||||
try (InputStream is = ResourceManager.getResourceAsStream(C_SOURCE_FILE)) {
|
||||
if (is == null) {
|
||||
throw new FileNotFoundException("Resource not found: " + C_SOURCE_FILE);
|
||||
}
|
||||
Msg.debug(this, "Parsing C headers from " + C_SOURCE_FILE);
|
||||
parser.parse(is);
|
||||
}
|
||||
}
|
||||
|
||||
protected class MyDataTypeManager extends StandAloneDataTypeManager {
|
||||
MyDataTypeManager(String name, DataOrganization dataOrg) {
|
||||
super(name);
|
||||
this.dataOrganization = dataOrg;
|
||||
}
|
||||
}
|
||||
|
||||
abstract DataTypeManager getDataTypeManager();
|
||||
|
||||
Structure getStructure(String name) {
|
||||
DataType dataType = getDataTypeManager().getDataType("/" + name);
|
||||
assertTrue("Data type not found: " + name, dataType instanceof Structure);
|
||||
return (Structure) dataType;
|
||||
}
|
||||
|
||||
Union getUnion(String name) {
|
||||
DataType dataType = getDataTypeManager().getDataType("/" + name);
|
||||
assertTrue("Data type not found: " + name, dataType instanceof Union);
|
||||
return (Union) dataType;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,753 @@
|
|||
/* ###
|
||||
* 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 org.junit.Test;
|
||||
|
||||
public class MSVCStructureImplBitFieldTest extends AbstractCompositeImplBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCStructureImplBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
DataOrganizationTestUtils.initDataOrganizationWindows64BitX86(dataOrg);
|
||||
dataMgr = new MyDataTypeManager("test", dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1() {
|
||||
Structure struct = getStructure("B1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2() {
|
||||
Structure struct = getStructure("B2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 5 int:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3() {
|
||||
Structure struct = getStructure("B3");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B3 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1() {
|
||||
Structure struct = getStructure("Z1");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 int:0(0) 1 \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2() {
|
||||
Structure struct = getStructure("Z2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 int:0(0) 1 \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3() {
|
||||
Structure struct = getStructure("Z3");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z3 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 5 int:4(0) 1 d \"\"\n" +
|
||||
" 7 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4() {
|
||||
Structure struct = getStructure("Z4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 16 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5() {
|
||||
Structure struct = getStructure("Z5");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z5 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 8 int:0(0) 1 \"\"\n" +
|
||||
" 8 longlong:6(0) 1 b \"\"\n" +
|
||||
" 16 int:8(0) 1 c \"\"\n" +
|
||||
" 20 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 24 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ6() {
|
||||
Structure struct = getStructure("Z6");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z6\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z6 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 8 int:0(0) 1 \"\"\n" +
|
||||
" 8 longlong:6(0) 1 b \"\"\n" +
|
||||
" 16 int:8(0) 1 c \"\"\n" +
|
||||
" 20 char 1 d \"\"\n" +
|
||||
" 24 longlong:6(0) 1 e \"\"\n" +
|
||||
" 32 int:8(0) 1 f \"\"\n" +
|
||||
" 36 char 1 g \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 40 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1p1() {
|
||||
Structure struct = getStructure("B1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B1p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 7 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2p1() {
|
||||
Structure struct = getStructure("B2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B2p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 4 int:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 7 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3p1() {
|
||||
Structure struct = getStructure("B3p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B3p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 7 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p1() {
|
||||
Structure struct = getStructure("Z1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z1p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:0(0) 1 \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 7 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2p1() {
|
||||
Structure struct = getStructure("Z2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z2p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 7 int:0(0) 1 \"\"\n" +
|
||||
" 7 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p1() {
|
||||
Structure struct = getStructure("Z3p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z3p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 4 int:4(0) 1 d \"\"\n" +
|
||||
" 6 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 7 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p1T() {
|
||||
Structure struct = getStructure("Z3p1T");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p1T\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z3p1T {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 Z3p1 7 z3p1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4p1() {
|
||||
Structure struct = getStructure("Z4p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z4p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 3 int:8(0) 1 c \"\"\n" +
|
||||
" 7 longlong:0(0) 1 \"\"\n" +
|
||||
" 7 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1p2() {
|
||||
Structure struct = getStructure("B1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2p2() {
|
||||
Structure struct = getStructure("B2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 5 int:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3p2() {
|
||||
Structure struct = getStructure("B3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB4p2() {
|
||||
Structure struct = getStructure("B4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 longlong 8 d \"\"\n" +
|
||||
" 16 int:4(0) 1 e \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 20 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p2() {
|
||||
Structure struct = getStructure("Z1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 int:0(0) 1 \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p2x() {
|
||||
Structure struct = getStructure("Z1p2x");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p2x\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z1p2x {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 int:0(0) 1 \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
" 8 short:4(4) 1 d1 \"\"\n" +
|
||||
" 9 short:4(0) 1 d2 \"\"\n" +
|
||||
" 9 short:4(4) 1 d3 \"\"\n" +
|
||||
" 10 short:4(0) 1 d4 \"\"\n" +
|
||||
" 10 short:4(4) 1 d5 \"\"\n" +
|
||||
" 11 short:4(0) 1 d6 \"\"\n" +
|
||||
" 11 short:4(4) 1 d7 \"\"\n" +
|
||||
" 12 short:0(0) 1 \"\"\n" +
|
||||
" 12 ushort:6(0) 1 _b \"\"\n" +
|
||||
" 14 int:8(0) 1 _c \"\"\n" +
|
||||
" 18 short:4(0) 1 _d \"\"\n" +
|
||||
" 18 short:4(4) 1 _d1 \"\"\n" +
|
||||
" 19 short:4(0) 1 _d2 \"\"\n" +
|
||||
" 19 short:4(4) 1 _d3 \"\"\n" +
|
||||
" 20 short:4(0) 1 _d4 \"\"\n" +
|
||||
" 20 short:4(4) 1 _d5 \"\"\n" +
|
||||
" 21 short:4(0) 1 _d6 \"\"\n" +
|
||||
" 21 short:4(4) 1 _d7 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 22 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2p2() {
|
||||
Structure struct = getStructure("Z2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 int:0(0) 1 \"\"\n" +
|
||||
" 8 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p2() {
|
||||
Structure struct = getStructure("Z3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 5 int:4(0) 1 d \"\"\n" +
|
||||
" 7 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4p2() {
|
||||
Structure struct = getStructure("Z4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5p2() {
|
||||
Structure struct = getStructure("Z5p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z5p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:12(0) 2 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x1p2() {
|
||||
Structure struct = getStructure("x1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x2p2() {
|
||||
Structure struct = getStructure("x2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x3p2() {
|
||||
Structure struct = getStructure("x3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 short:0(0) 1 \"\"\n" +
|
||||
" 2 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x4p2() {
|
||||
Structure struct = getStructure("x4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 int:27(0) 4 b \"\"\n" +
|
||||
" 5 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5p4() {
|
||||
Structure struct = getStructure("Z5p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure Z5p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 ushort:12(0) 2 b \"\"\n" +
|
||||
" 4 int:8(0) 1 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x1p4() {
|
||||
Structure struct = getStructure("x1p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x1p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x1p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x2p4() {
|
||||
Structure struct = getStructure("x2p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x2p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x2p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x3p4() {
|
||||
Structure struct = getStructure("x3p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x3p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x3p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 short:0(0) 1 \"\"\n" +
|
||||
" 4 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x4p4() {
|
||||
Structure struct = getStructure("x4p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x4p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x4p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:27(0) 4 b \"\"\n" +
|
||||
" 7 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsT1() {
|
||||
Structure struct = getStructure("T1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/T1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure T1 {\n" +
|
||||
" 0 charTypedef 1 a \"\"\n" +
|
||||
" 4 myEnum:3(0) 1 b \"\"\n" +
|
||||
" 4 enumTypedef:3(3) 1 c \"\"\n" +
|
||||
" 8 charTypedef:7(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsT2() {
|
||||
Structure struct = getStructure("T2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/T2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure T2 {\n" +
|
||||
" 0 charTypedef 1 a \"\"\n" +
|
||||
" 4 intTypedef:17(0) 3 b \"\"\n" +
|
||||
" 6 enumTypedef:3(1) 1 c \"\"\n" +
|
||||
" 8 charTypedef:3(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1() {
|
||||
Structure struct = getStructure("S1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure S1 {\n" +
|
||||
" 0 B1 12 b1 \"\"\n" +
|
||||
" 12 B2 8 b2 \"\"\n" +
|
||||
" 20 Z1 12 z1 \"\"\n" +
|
||||
" 32 Z2 12 z2 \"\"\n" +
|
||||
" 48 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 56 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1p1() {
|
||||
Structure struct = getStructure("S1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure S1p1 {\n" +
|
||||
" 0 B1 12 b1 \"\"\n" +
|
||||
" 12 B2 8 b2 \"\"\n" +
|
||||
" 20 Z1 12 z1 \"\"\n" +
|
||||
" 32 Z2 12 z2 \"\"\n" +
|
||||
" 44 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 52 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS2p1() {
|
||||
Structure struct = getStructure("S2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure S2p1 {\n" +
|
||||
" 0 B1p1 9 b1p1 \"\"\n" +
|
||||
" 9 B2p1 7 b2p1 \"\"\n" +
|
||||
" 16 Z1p1 9 z1p1 \"\"\n" +
|
||||
" 25 Z2p1 9 z2p1 \"\"\n" +
|
||||
" 34 Z3p1 7 z3p1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 41 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1p2() {
|
||||
Structure struct = getStructure("S1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure S1p2 {\n" +
|
||||
" 0 B1 12 b1 \"\"\n" +
|
||||
" 12 B2 8 b2 \"\"\n" +
|
||||
" 20 Z1 12 z1 \"\"\n" +
|
||||
" 32 Z2 12 z2 \"\"\n" +
|
||||
" 44 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 52 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS2p2() {
|
||||
Structure struct = getStructure("S2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure S2p2 {\n" +
|
||||
" 0 B1p2 10 b1p2 \"\"\n" +
|
||||
" 10 B2p2 8 b2p2 \"\"\n" +
|
||||
" 18 Z1p2 10 z1p2 \"\"\n" +
|
||||
" 28 Z2p2 10 z2p2 \"\"\n" +
|
||||
" 38 Z3p2 8 z3p2 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 46 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/* ###
|
||||
* 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 org.junit.Test;
|
||||
|
||||
public class MSVCUnionImplBitFieldTest extends AbstractCompositeImplBitFieldTest {
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (MSVCUnionImplBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
DataOrganizationTestUtils.initDataOrganizationWindows64BitX86(dataOrg);
|
||||
dataMgr = new MyDataTypeManager("test", dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1() {
|
||||
Union struct = getUnion("U1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
|
||||
"Aligned\n" +
|
||||
"Union U1 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1z() {
|
||||
Union struct = getUnion("U1z");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" +
|
||||
"Aligned\n" +
|
||||
"Union U1z {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 longlong:0(0) 1 \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p1() {
|
||||
Union struct = getUnion("U1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Union U1p1 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p1z() {
|
||||
Union struct = getUnion("U1p1z");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Union U1p1z {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 longlong:0(0) 1 \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p2() {
|
||||
Union struct = getUnion("U1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Union U1p2 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,755 @@
|
|||
/* ###
|
||||
* 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 org.junit.Test;
|
||||
|
||||
public class StructureImplBigEndianBitFieldTest extends AbstractCompositeImplBitFieldTest {
|
||||
|
||||
// NOTE: verified bitfields sample built with mips-elf-gcc (GCC) 4.9.2
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (StructureImplBigEndianBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
|
||||
dataMgr = new MyDataTypeManager("test", dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1() {
|
||||
Structure struct = getStructure("B1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2() {
|
||||
Structure struct = getStructure("B2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3() {
|
||||
Structure struct = getStructure("B3");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B3 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 3 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1() {
|
||||
Structure struct = getStructure("Z1");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 ushort:6(2) 1 b \"\"\n" +
|
||||
" 4 int:8(2) 2 c \"\"\n" +
|
||||
" 6 short:4(4) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2() {
|
||||
Structure struct = getStructure("Z2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 short:4(4) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3() {
|
||||
Structure struct = getStructure("Z3");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z3 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
" 3 longlong:0(7) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4() {
|
||||
Structure struct = getStructure("Z4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 8 longlong:0(7) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5() {
|
||||
Structure struct = getStructure("Z5");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z5 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 longlong:6(2) 1 b \"\"\n" +
|
||||
" 4 int:8(2) 2 c \"\"\n" +
|
||||
" 6 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ6() {
|
||||
Structure struct = getStructure("Z6");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z6\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z6 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 longlong:6(2) 1 b \"\"\n" +
|
||||
" 4 int:8(2) 2 c \"\"\n" +
|
||||
" 6 char 1 d \"\"\n" +
|
||||
" 7 longlong:6(2) 1 e \"\"\n" +
|
||||
" 8 int:8(0) 1 f \"\"\n" +
|
||||
" 9 char 1 g \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 16 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1p1() {
|
||||
Structure struct = getStructure("B1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B1p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2p1() {
|
||||
Structure struct = getStructure("B2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B2p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3p1() {
|
||||
Structure struct = getStructure("B3p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B3p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 3 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p1() {
|
||||
Structure struct = getStructure("Z1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z1p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 ushort:6(2) 1 b \"\"\n" +
|
||||
" 4 int:8(2) 2 c \"\"\n" +
|
||||
" 5 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 7 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2p1() {
|
||||
Structure struct = getStructure("Z2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z2p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 short:4(4) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 5 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p1() {
|
||||
Structure struct = getStructure("Z3p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z3p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
" 3 longlong:0(7) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p1T() {
|
||||
Structure struct = getStructure("Z3p1T");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p1T\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z3p1T {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 Z3p1 8 z3p1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4p1() {
|
||||
Structure struct = getStructure("Z4p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z4p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 8 longlong:0(7) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1p2() {
|
||||
Structure struct = getStructure("B1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2p2() {
|
||||
Structure struct = getStructure("B2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3p2() {
|
||||
Structure struct = getStructure("B3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 3 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB4p2() {
|
||||
Structure struct = getStructure("B4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 4 longlong 8 d \"\"\n" +
|
||||
" 12 int:4(4) 1 e \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 14 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p2() {
|
||||
Structure struct = getStructure("Z1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 ushort:6(2) 1 b \"\"\n" +
|
||||
" 4 int:8(2) 2 c \"\"\n" +
|
||||
" 5 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p2x() {
|
||||
Structure struct = getStructure("Z1p2x");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p2x\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z1p2x {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 ushort:6(2) 1 b \"\"\n" +
|
||||
" 4 int:8(2) 2 c \"\"\n" +
|
||||
" 5 short:4(6) 2 d \"\"\n" +
|
||||
" 6 short:4(2) 1 d1 \"\"\n" +
|
||||
" 6 short:4(6) 2 d2 \"\"\n" +
|
||||
" 7 short:4(2) 1 d3 \"\"\n" +
|
||||
" 7 short:4(6) 2 d4 \"\"\n" +
|
||||
" 8 short:4(2) 1 d5 \"\"\n" +
|
||||
" 8 short:4(6) 2 d6 \"\"\n" +
|
||||
" 9 short:4(2) 1 d7 \"\"\n" +
|
||||
" 10 short:0(7) 1 \"\"\n" +
|
||||
" 10 ushort:6(2) 1 _b \"\"\n" +
|
||||
" 10 int:8(2) 2 _c \"\"\n" +
|
||||
" 11 short:4(6) 2 _d \"\"\n" +
|
||||
" 12 short:4(2) 1 _d1 \"\"\n" +
|
||||
" 12 short:4(6) 2 _d2 \"\"\n" +
|
||||
" 13 short:4(2) 1 _d3 \"\"\n" +
|
||||
" 13 short:4(6) 2 _d4 \"\"\n" +
|
||||
" 14 short:4(2) 1 _d5 \"\"\n" +
|
||||
" 14 short:4(6) 2 _d6 \"\"\n" +
|
||||
" 15 short:4(2) 1 _d7 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 16 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2p2() {
|
||||
Structure struct = getStructure("Z2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 4 int:0(7) 1 \"\"\n" +
|
||||
" 4 short:4(4) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p2() {
|
||||
Structure struct = getStructure("Z3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
" 3 longlong:0(7) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4p2() {
|
||||
Structure struct = getStructure("Z4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(2) 1 b \"\"\n" +
|
||||
" 1 int:8(2) 2 c \"\"\n" +
|
||||
" 8 longlong:0(7) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5p2() {
|
||||
Structure struct = getStructure("Z5p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z5p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:12(4) 2 b \"\"\n" +
|
||||
" 2 int:8(4) 2 c \"\"\n" +
|
||||
" 8 longlong:0(7) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x1p2() {
|
||||
Structure struct = getStructure("x1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x2p2() {
|
||||
Structure struct = getStructure("x2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(5) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x3p2() {
|
||||
Structure struct = getStructure("x3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 short:0(7) 1 \"\"\n" +
|
||||
" 2 int:27(5) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x4p2() {
|
||||
Structure struct = getStructure("x4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(5) 4 b \"\"\n" +
|
||||
" 4 longlong:0(7) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5p4() {
|
||||
Structure struct = getStructure("Z5p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure Z5p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:12(4) 2 b \"\"\n" +
|
||||
" 2 int:8(4) 2 c \"\"\n" +
|
||||
" 8 longlong:0(7) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x1p4() {
|
||||
Structure struct = getStructure("x1p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x1p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x1p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x2p4() {
|
||||
Structure struct = getStructure("x2p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x2p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x2p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(5) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x3p4() {
|
||||
Structure struct = getStructure("x3p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x3p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x3p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 short:0(7) 1 \"\"\n" +
|
||||
" 2 int:27(5) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x4p4() {
|
||||
Structure struct = getStructure("x4p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x4p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x4p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(5) 4 b \"\"\n" +
|
||||
" 4 longlong:0(7) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsT1() {
|
||||
Structure struct = getStructure("T1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/T1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure T1 {\n" +
|
||||
" 0 charTypedef 1 a \"\"\n" +
|
||||
" 1 myEnum:3(5) 1 b \"\"\n" +
|
||||
" 1 enumTypedef:3(2) 1 c \"\"\n" +
|
||||
" 2 charTypedef:7(1) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsT2() {
|
||||
Structure struct = getStructure("T2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/T2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure T2 {\n" +
|
||||
" 0 charTypedef 1 a \"\"\n" +
|
||||
" 1 intTypedef:17(7) 3 b \"\"\n" +
|
||||
" 3 enumTypedef:3(4) 1 c \"\"\n" +
|
||||
" 3 charTypedef:3(1) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1() {
|
||||
Structure struct = getStructure("S1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure S1 {\n" +
|
||||
" 0 B1 4 b1 \"\"\n" +
|
||||
" 4 B2 4 b2 \"\"\n" +
|
||||
" 8 Z1 8 z1 \"\"\n" +
|
||||
" 16 Z2 8 z2 \"\"\n" +
|
||||
" 24 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 32 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1p1() {
|
||||
Structure struct = getStructure("S1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure S1p1 {\n" +
|
||||
" 0 B1 4 b1 \"\"\n" +
|
||||
" 4 B2 4 b2 \"\"\n" +
|
||||
" 8 Z1 8 z1 \"\"\n" +
|
||||
" 16 Z2 8 z2 \"\"\n" +
|
||||
" 24 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 32 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS2p1() {
|
||||
Structure struct = getStructure("S2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure S2p1 {\n" +
|
||||
" 0 B1p1 4 b1p1 \"\"\n" +
|
||||
" 4 B2p1 4 b2p1 \"\"\n" +
|
||||
" 8 Z1p1 7 z1p1 \"\"\n" +
|
||||
" 15 Z2p1 5 z2p1 \"\"\n" +
|
||||
" 20 Z3p1 8 z3p1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 28 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1p2() {
|
||||
Structure struct = getStructure("S1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure S1p2 {\n" +
|
||||
" 0 B1 4 b1 \"\"\n" +
|
||||
" 4 B2 4 b2 \"\"\n" +
|
||||
" 8 Z1 8 z1 \"\"\n" +
|
||||
" 16 Z2 8 z2 \"\"\n" +
|
||||
" 24 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 32 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS2p2() {
|
||||
Structure struct = getStructure("S2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure S2p2 {\n" +
|
||||
" 0 B1p2 4 b1p2 \"\"\n" +
|
||||
" 4 B2p2 4 b2p2 \"\"\n" +
|
||||
" 8 Z1p2 8 z1p2 \"\"\n" +
|
||||
" 16 Z2p2 6 z2p2 \"\"\n" +
|
||||
" 22 Z3p2 8 z3p2 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 30 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,816 @@
|
|||
/* ###
|
||||
* 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.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class StructureImplLittleEndianBitFieldTest extends AbstractCompositeImplBitFieldTest {
|
||||
|
||||
// NOTE: verified bitfields sample built with Apple LLVM version 9.0.0 (clang-900.0.39.2)
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
// uncomment to generate datatype archive
|
||||
// writeArchive();
|
||||
}
|
||||
|
||||
private void writeArchive() throws IOException {
|
||||
URL resource = ResourceManager.getResource(C_SOURCE_FILE);
|
||||
File f = new File(resource.getPath() + ".gdt");
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
}
|
||||
|
||||
FileDataTypeManager fileDtMgr = FileDataTypeManager.createFileArchive(f);
|
||||
int txId = fileDtMgr.startTransaction("Save Datatypes");
|
||||
try {
|
||||
Iterator<Composite> composites = getDataTypeManager().getAllComposites();
|
||||
while (composites.hasNext()) {
|
||||
fileDtMgr.addDataType(composites.next(), null);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
fileDtMgr.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
fileDtMgr.save();
|
||||
fileDtMgr.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (StructureImplBigEndianBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
DataOrganizationTestUtils.initDataOrganizationGcc64BitX86(dataOrg);
|
||||
dataMgr = new MyDataTypeManager("test", dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1() {
|
||||
Structure struct = getStructure("B1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2() {
|
||||
Structure struct = getStructure("B2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3() {
|
||||
Structure struct = getStructure("B3");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3\n" +
|
||||
"Aligned\n" +
|
||||
"Structure B3 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" + // gcc groups with previous non-bitfield
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 3 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1() {
|
||||
Structure struct = getStructure("Z1");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(6) 2 c \"\"\n" +
|
||||
" 6 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2() {
|
||||
Structure struct = getStructure("Z2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3() {
|
||||
Structure struct = getStructure("Z3");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z3 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
" 3 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4() {
|
||||
Structure struct = getStructure("Z4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5() {
|
||||
Structure struct = getStructure("Z5");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z5 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 longlong:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(6) 2 c \"\"\n" +
|
||||
" 6 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ6() {
|
||||
Structure struct = getStructure("Z6");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z6\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z6 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 longlong:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(6) 2 c \"\"\n" +
|
||||
" 6 char 1 d \"\"\n" +
|
||||
" 7 longlong:6(0) 1 e \"\"\n" +
|
||||
" 8 int:8(0) 1 f \"\"\n" +
|
||||
" 9 char 1 g \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 16 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1p1() {
|
||||
Structure struct = getStructure("B1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B1p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2p1() {
|
||||
Structure struct = getStructure("B2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B2p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3p1() {
|
||||
Structure struct = getStructure("B3p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure B3p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 3 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p1() {
|
||||
Structure struct = getStructure("Z1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z1p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(6) 2 c \"\"\n" +
|
||||
" 5 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 7 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2p1() {
|
||||
Structure struct = getStructure("Z2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z2p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 5 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p1() {
|
||||
Structure struct = getStructure("Z3p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z3p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
" 3 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p1T() {
|
||||
Structure struct = getStructure("Z3p1T");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p1T\n" +
|
||||
"Aligned\n" +
|
||||
"Structure Z3p1T {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 Z3p1 8 z3p1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4p1() {
|
||||
Structure struct = getStructure("Z4p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure Z4p1 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 9 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB1p2() {
|
||||
Structure struct = getStructure("B1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB2p2() {
|
||||
Structure struct = getStructure("B2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB3p2() {
|
||||
Structure struct = getStructure("B3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 3 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsB4p2() {
|
||||
Structure struct = getStructure("B4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/B4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure B4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 4 longlong 8 d \"\"\n" +
|
||||
" 12 int:4(0) 1 e \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 14 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p2() {
|
||||
Structure struct = getStructure("Z1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(6) 2 c \"\"\n" +
|
||||
" 5 short:4(6) 2 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ1p2x() {
|
||||
Structure struct = getStructure("Z1p2x");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z1p2x\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z1p2x {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 ushort:6(0) 1 b \"\"\n" +
|
||||
" 4 int:8(6) 2 c \"\"\n" +
|
||||
" 5 short:4(6) 2 d \"\"\n" +
|
||||
" 6 short:4(2) 1 d1 \"\"\n" +
|
||||
" 6 short:4(6) 2 d2 \"\"\n" +
|
||||
" 7 short:4(2) 1 d3 \"\"\n" +
|
||||
" 7 short:4(6) 2 d4 \"\"\n" +
|
||||
" 8 short:4(2) 1 d5 \"\"\n" +
|
||||
" 8 short:4(6) 2 d6 \"\"\n" +
|
||||
" 9 short:4(2) 1 d7 \"\"\n" +
|
||||
" 10 short:0(0) 1 \"\"\n" +
|
||||
" 10 ushort:6(0) 1 _b \"\"\n" +
|
||||
" 10 int:8(6) 2 _c \"\"\n" +
|
||||
" 11 short:4(6) 2 _d \"\"\n" +
|
||||
" 12 short:4(2) 1 _d1 \"\"\n" +
|
||||
" 12 short:4(6) 2 _d2 \"\"\n" +
|
||||
" 13 short:4(2) 1 _d3 \"\"\n" +
|
||||
" 13 short:4(6) 2 _d4 \"\"\n" +
|
||||
" 14 short:4(2) 1 _d5 \"\"\n" +
|
||||
" 14 short:4(6) 2 _d6 \"\"\n" +
|
||||
" 15 short:4(2) 1 _d7 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 16 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ2p2() {
|
||||
Structure struct = getStructure("Z2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 4 int:0(0) 1 \"\"\n" +
|
||||
" 4 short:4(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ3p2() {
|
||||
Structure struct = getStructure("Z3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 2 int:4(6) 2 d \"\"\n" +
|
||||
" 3 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ4p2() {
|
||||
Structure struct = getStructure("Z4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:6(0) 1 b \"\"\n" +
|
||||
" 1 int:8(6) 2 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5p2() {
|
||||
Structure struct = getStructure("Z5p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure Z5p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:12(0) 2 b \"\"\n" +
|
||||
" 2 int:8(4) 2 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 10 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x1p2() {
|
||||
Structure struct = getStructure("x1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x1p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x2p2() {
|
||||
Structure struct = getStructure("x2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x2p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x3p2() {
|
||||
Structure struct = getStructure("x3p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x3p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x3p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 short:0(0) 1 \"\"\n" +
|
||||
" 2 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 6 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x4p2() {
|
||||
Structure struct = getStructure("x4p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x4p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure x4p2 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(0) 4 b \"\"\n" +
|
||||
" 4 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsZ5p4() {
|
||||
Structure struct = getStructure("Z5p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/Z5p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure Z5p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 ushort:12(0) 2 b \"\"\n" +
|
||||
" 2 int:8(4) 2 c \"\"\n" +
|
||||
" 8 longlong:0(0) 1 \"\"\n" +
|
||||
" 8 char 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 12 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x1p4() {
|
||||
Structure struct = getStructure("x1p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x1p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x1p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x2p4() {
|
||||
Structure struct = getStructure("x2p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x2p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x2p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x3p4() {
|
||||
Structure struct = getStructure("x3p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x3p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x3p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 2 short:0(0) 1 \"\"\n" +
|
||||
" 2 int:27(0) 4 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFields_x4p4() {
|
||||
Structure struct = getStructure("x4p4");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/x4p4\n" +
|
||||
"Aligned pack(4)\n" +
|
||||
"Structure x4p4 {\n" +
|
||||
" 0 char 1 a \"\"\n" +
|
||||
" 1 int:27(0) 4 b \"\"\n" +
|
||||
" 4 longlong:0(0) 1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 8 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsT1() {
|
||||
Structure struct = getStructure("T1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/T1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure T1 {\n" +
|
||||
" 0 charTypedef 1 a \"\"\n" +
|
||||
" 1 myEnum:3(0) 1 b \"\"\n" +
|
||||
" 1 enumTypedef:3(3) 1 c \"\"\n" +
|
||||
" 2 charTypedef:7(0) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsT2() {
|
||||
Structure struct = getStructure("T2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/T2\n" +
|
||||
"Aligned\n" +
|
||||
"Structure T2 {\n" +
|
||||
" 0 charTypedef 1 a \"\"\n" +
|
||||
" 1 intTypedef:17(0) 3 b \"\"\n" +
|
||||
" 3 enumTypedef:3(1) 1 c \"\"\n" +
|
||||
" 3 charTypedef:3(4) 1 d \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1() {
|
||||
Structure struct = getStructure("S1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1\n" +
|
||||
"Aligned\n" +
|
||||
"Structure S1 {\n" +
|
||||
" 0 B1 4 b1 \"\"\n" +
|
||||
" 4 B2 4 b2 \"\"\n" +
|
||||
" 8 Z1 8 z1 \"\"\n" +
|
||||
" 16 Z2 8 z2 \"\"\n" +
|
||||
" 24 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 32 Actual Alignment = 8", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1p1() {
|
||||
Structure struct = getStructure("S1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure S1p1 {\n" +
|
||||
" 0 B1 4 b1 \"\"\n" +
|
||||
" 4 B2 4 b2 \"\"\n" +
|
||||
" 8 Z1 8 z1 \"\"\n" +
|
||||
" 16 Z2 8 z2 \"\"\n" +
|
||||
" 24 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 32 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS2p1() {
|
||||
Structure struct = getStructure("S2p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S2p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Structure S2p1 {\n" +
|
||||
" 0 B1p1 4 b1p1 \"\"\n" +
|
||||
" 4 B2p1 4 b2p1 \"\"\n" +
|
||||
" 8 Z1p1 7 z1p1 \"\"\n" +
|
||||
" 15 Z2p1 5 z2p1 \"\"\n" +
|
||||
" 20 Z3p1 8 z3p1 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 28 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS1p2() {
|
||||
Structure struct = getStructure("S1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure S1p2 {\n" +
|
||||
" 0 B1 4 b1 \"\"\n" +
|
||||
" 4 B2 4 b2 \"\"\n" +
|
||||
" 8 Z1 8 z1 \"\"\n" +
|
||||
" 16 Z2 8 z2 \"\"\n" +
|
||||
" 24 Z3 8 z3 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 32 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructureBitFieldsS2p2() {
|
||||
Structure struct = getStructure("S2p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/S2p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Structure S2p2 {\n" +
|
||||
" 0 B1p2 4 b1p2 \"\"\n" +
|
||||
" 4 B2p2 4 b2p2 \"\"\n" +
|
||||
" 8 Z1p2 8 z1p2 \"\"\n" +
|
||||
" 16 Z2p2 6 z2p2 \"\"\n" +
|
||||
" 22 Z3p2 8 z3p2 \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 30 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testStructureBitFieldsFOO() {
|
||||
// Structure struct = getStructure("Z3p1T");
|
||||
//
|
||||
// System.out.println(struct.toString());
|
||||
//
|
||||
// DataTypeManager dtm = struct.getDataTypeManager();
|
||||
// if (dtm instanceof StandAloneDataTypeManager) {
|
||||
// ((StandAloneDataTypeManager) dtm).startTransaction("TEST");
|
||||
// }
|
||||
// else if (dtm instanceof ProgramDataTypeManager) {
|
||||
// ((ProgramDataTypeManager) dtm).getProgram().startTransaction("TEST");
|
||||
// }
|
||||
//
|
||||
// ArrayList<InternalDataTypeComponent> components =
|
||||
// (ArrayList<InternalDataTypeComponent>) getInstanceField("components", struct);
|
||||
//
|
||||
// AlignedStructurePacker.packComponents(struct, components);
|
||||
//
|
||||
// //@formatter:off
|
||||
// CompositeTestUtils.assertExpectedComposite(this, "", struct);
|
||||
// //@formatter:on
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/* ###
|
||||
* 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 org.junit.Test;
|
||||
|
||||
public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFieldTest {
|
||||
|
||||
// NOTE: verified bitfields sample built with mips-elf-gcc (GCC) 4.9.2
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (StructureImplBigEndianBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
|
||||
dataMgr = new MyDataTypeManager("test", dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1() {
|
||||
Union struct = getUnion("U1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
|
||||
"Aligned\n" +
|
||||
"Union U1 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1z() {
|
||||
Union struct = getUnion("U1z");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" +
|
||||
"Aligned\n" +
|
||||
"Union U1z {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 longlong:0(0) 1 \"\"\n" + // has no impact
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p1() {
|
||||
Union struct = getUnion("U1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Union U1p1 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p1z() {
|
||||
Union struct = getUnion("U1p1z");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Union U1p1z {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 longlong:0(0) 1 \"\"\n" + // has no impact
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p2() {
|
||||
Union struct = getUnion("U1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Union U1p2 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 2 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/* ###
|
||||
* 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 org.junit.Test;
|
||||
|
||||
public class UnionImplLittleEndianBitFieldTest extends AbstractCompositeImplBitFieldTest {
|
||||
|
||||
// NOTE: verified bitfields sample built with Apple LLVM version 9.0.0 (clang-900.0.39.2)
|
||||
|
||||
private static DataTypeManager dataMgr;
|
||||
|
||||
@Override
|
||||
protected DataTypeManager getDataTypeManager() {
|
||||
synchronized (StructureImplBigEndianBitFieldTest.class) {
|
||||
if (dataMgr == null) {
|
||||
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
|
||||
DataOrganizationTestUtils.initDataOrganizationGcc64BitX86(dataOrg);
|
||||
dataMgr = new MyDataTypeManager("test", dataOrg);
|
||||
}
|
||||
return dataMgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1() {
|
||||
Union struct = getUnion("U1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
|
||||
"Aligned\n" +
|
||||
"Union U1 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1z() {
|
||||
Union struct = getUnion("U1z");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" +
|
||||
"Aligned\n" +
|
||||
"Union U1z {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 longlong:0(0) 1 \"\"\n" + // has no impact
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 4 Actual Alignment = 4", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p1() {
|
||||
Union struct = getUnion("U1p1");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Union U1p1 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p1z() {
|
||||
Union struct = getUnion("U1p1z");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" +
|
||||
"Aligned pack(1)\n" +
|
||||
"Union U1p1z {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 longlong:0(0) 1 \"\"\n" + // has no impact
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 1 Actual Alignment = 1", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnionBitFieldsU1p2() {
|
||||
Union struct = getUnion("U1p2");
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" +
|
||||
"Aligned pack(2)\n" +
|
||||
"Union U1p2 {\n" +
|
||||
" 0 int:4(0) 1 a \"\"\n" +
|
||||
" 0 int:2(0) 1 b \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 2 Actual Alignment = 2", struct);
|
||||
//@formatter:on
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "bitfields.h"
|
||||
|
||||
|
||||
struct B1 B1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B2 B2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B3 B3 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
|
||||
struct Z1 Z1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z2 Z2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z3 Z3 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z4 Z4 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z5 Z5 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z6 Z6 = { 5, 0x2A, -1, 0xA, 0x2A, -1, 0xA };
|
||||
|
||||
|
||||
struct B1p1 B1p1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B2p1 B2p1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B3p1 B3p1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
|
||||
struct Z1p1 Z1p1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z2p1 Z2p1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z3p1 Z3p1 = { 5, 0x2A, -1, 0xA };
|
||||
struct Z3p1T Z3p1T = { 7, { 5, 0x2A, -1, 0xA }};
|
||||
|
||||
struct Z4p1 Z4p1 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
|
||||
struct B1p2 B1p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B2p2 B2p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B3p2 B3p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct B4p2 B4p2 = { 5, 0x2A, -1, 0x5555555555555555, 0xA };
|
||||
|
||||
|
||||
struct Z1p2 Z1p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z1p2x Z1p2x = { 5, 0x2A, -1, 0xA, -1, 0, -1, 0, -1, 0, -1, 0x2A, -1, 0xA, -1, 0, -1, 0, -1, 0, -1 };
|
||||
|
||||
struct Z2p2 Z2p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z3p2 Z3p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z4p2 Z4p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct Z5p2 Z5p2 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct x1p2 x1p2 = { 5 };
|
||||
|
||||
struct x2p2 x2p2 = { 5, 0x2A };
|
||||
|
||||
struct x3p2 x3p2 = { 5, 0x2A };
|
||||
|
||||
struct x4p2 x4p2 = { 5, 0x2A };
|
||||
|
||||
|
||||
struct Z5p4 Z5p4 = { 5, 0x2A, -1, 0xA };
|
||||
|
||||
struct x1p4 x1p4 = { 5 };
|
||||
|
||||
struct x2p4 x2p4 = { 5, 0x2A };
|
||||
|
||||
struct x3p4 x3p4 = { 5, 0x2A };
|
||||
|
||||
struct x4p4 x4p4 = { 5, 0x2A };
|
||||
|
||||
|
||||
struct S1 S1 = { { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA } };
|
||||
|
||||
|
||||
struct S1p1 S1p1 = { { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA } };
|
||||
|
||||
struct S2p1 S2p1 = { { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA } };
|
||||
|
||||
|
||||
struct S1p2 S1p2 = { { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA } };
|
||||
|
||||
struct S2p2 S2p2 = { { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA }, { 5, 0x2A, -1, 0xA } };
|
||||
|
||||
struct T1 T1 = { 5, TWO, THREE, 1 };
|
||||
|
||||
struct T2 T2 = { 5, 0x2A, THREE, 1 };
|
||||
|
||||
union U1 U1;
|
||||
union U1z U1z;
|
||||
union U1p1 U1p1;
|
||||
union U1p1z U1p1z;
|
||||
union U1p2 U1p2;
|
||||
|
||||
struct SUp1 SUp1;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("len B1: %d\n", sizeof(struct B1));
|
||||
printf("len B2: %d\n", sizeof(struct B2));
|
||||
printf("len B3: %d\n", sizeof(struct B3));
|
||||
|
||||
printf("len Z1: %d\n", sizeof(struct Z1));
|
||||
printf("len Z2: %d\n", sizeof(struct Z2));
|
||||
printf("len Z3: %d\n", sizeof(struct Z3));
|
||||
printf("len Z4: %d\n", sizeof(struct Z4));
|
||||
printf("len Z5: %d\n", sizeof(struct Z5));
|
||||
printf("len Z6: %d\n", sizeof(struct Z6));
|
||||
|
||||
printf("len B1p1: %d\n", sizeof(struct B1p1));
|
||||
printf("len B2p1: %d\n", sizeof(struct B2p1));
|
||||
printf("len B3p1: %d\n", sizeof(struct B3p1));
|
||||
|
||||
printf("len Z1p1: %d\n", sizeof(struct Z1p1));
|
||||
printf("len Z2p1: %d\n", sizeof(struct Z2p1));
|
||||
printf("len Z3p1: %d\n", sizeof(struct Z3p1));
|
||||
printf("len Z3p1T: %d\n", sizeof(struct Z3p1T));
|
||||
printf("len Z4p1: %d\n", sizeof(struct Z4p1));
|
||||
|
||||
printf("len B1p2: %d\n", sizeof(struct B1p2));
|
||||
printf("len B2p2: %d\n", sizeof(struct B2p2));
|
||||
printf("len B3p2: %d\n", sizeof(struct B3p2));
|
||||
printf("len B4p2: %d\n", sizeof(struct B4p2));
|
||||
|
||||
printf("len Z1p2: %d\n", sizeof(struct Z1p2));
|
||||
printf("len Z1p2x: %d\n", sizeof(struct Z1p2x));
|
||||
printf("len Z2p2: %d\n", sizeof(struct Z2p2));
|
||||
printf("len Z3p2: %d\n", sizeof(struct Z3p2));
|
||||
printf("len Z4p2: %d\n", sizeof(struct Z4p2));
|
||||
printf("len Z5p2: %d\n", sizeof(struct Z5p2));
|
||||
printf("len x1p2: %d\n", sizeof(struct x1p2));
|
||||
printf("len x2p2: %d\n", sizeof(struct x2p2));
|
||||
printf("len x3p2: %d\n", sizeof(struct x3p2));
|
||||
printf("len x4p2: %d\n", sizeof(struct x4p2));
|
||||
|
||||
printf("len Z5p4: %d\n", sizeof(struct Z5p4));
|
||||
printf("len x1p4: %d\n", sizeof(struct x1p4));
|
||||
printf("len x2p4: %d\n", sizeof(struct x2p4));
|
||||
printf("len x3p4: %d\n", sizeof(struct x3p4));
|
||||
printf("len x4p4: %d\n", sizeof(struct x4p4));
|
||||
|
||||
printf("len S1: %d\n", sizeof(struct S1));
|
||||
|
||||
printf("len S1p1: %d\n", sizeof(struct S1p1));
|
||||
printf("len S2p1: %d\n", sizeof(struct S2p1));
|
||||
|
||||
printf("len S1p2: %d\n", sizeof(struct S1p2));
|
||||
printf("len S2p2: %d\n", sizeof(struct S2p2));
|
||||
|
||||
printf("len T1: %d\n", sizeof(struct T1));
|
||||
printf("len T2: %d\n", sizeof(struct T2));
|
||||
|
||||
printf("len U1: %d\n", sizeof(union U1));
|
||||
printf("len U1z: %d\n", sizeof(union U1z));
|
||||
printf("len U1p1: %d\n", sizeof(union U1p1));
|
||||
printf("len U1p1z: %d\n", sizeof(union U1p1z));
|
||||
printf("len U1p2: %d\n", sizeof(union U1p2));
|
||||
|
||||
printf("len SUp1: %d\n", sizeof(struct SUp1));
|
||||
}
|
|
@ -0,0 +1,445 @@
|
|||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
// Verify bitfield grouping and alignment without zero-length bitfields
|
||||
|
||||
struct B1 {
|
||||
char a;
|
||||
unsigned short b:6; // gcc groups with previous non-bitfield
|
||||
int c:8; // gcc groups with previous two fields (including non-bitfield)
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct B2 {
|
||||
char a;
|
||||
unsigned short b:6; // gcc groups with previous non-bitfield
|
||||
int c:8;
|
||||
int d:4;
|
||||
};
|
||||
|
||||
struct B3 {
|
||||
char a;
|
||||
unsigned short b:6; // gcc groups with previous non-bitfield
|
||||
int c:8;
|
||||
char d; // gcc groups with int bit-field
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Verify bitfield grouping and alignment with zero-length bitfields
|
||||
|
||||
struct Z1 {
|
||||
char a;
|
||||
int :0; // MSVC ignores field, gcc forces break and does not combine with previous field
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct Z2 {
|
||||
char a;
|
||||
unsigned short b:6; // gcc groups with previous non-bitfield
|
||||
int c:8;
|
||||
int :0;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct Z3 {
|
||||
char a;
|
||||
unsigned short b:6; // gcc groups with previous non-bitfield
|
||||
int c:8; // gcc groups with previous two fields (including non-bitfield)
|
||||
int d:4;
|
||||
long long :0; // trailing :0 imposes alignment onto structure
|
||||
};
|
||||
|
||||
struct Z4 {
|
||||
char a;
|
||||
unsigned short b:6; // gcc groups with previous non-bitfield
|
||||
int c:8; // gcc groups with previous two fields (including non-bitfield)
|
||||
long long :0; // forced alignment of non-bitfield
|
||||
char d;
|
||||
};
|
||||
|
||||
struct Z5 {
|
||||
char a;
|
||||
int :0;
|
||||
long long b:6;
|
||||
int c:8;
|
||||
char d;
|
||||
};
|
||||
|
||||
struct Z6 {
|
||||
char a;
|
||||
int :0;
|
||||
long long b:6;
|
||||
int c:8;
|
||||
char d;
|
||||
long long e:6;
|
||||
int f:8;
|
||||
char g;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
// Verify bitfield grouping and alignment without zero-length bitfields
|
||||
|
||||
struct B1p1 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct B2p1 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
int d:4;
|
||||
};
|
||||
|
||||
struct B3p1 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
char d; // gcc groups with int bit-field
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Verify bitfield grouping and alignment with zero-length bitfields
|
||||
|
||||
struct Z1p1 {
|
||||
char a;
|
||||
int :0; // MSVC ignores field
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct Z2p1 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
int :0;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct Z3p1 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
int d:4;
|
||||
long long :0; // trailing :0 (ignore when packing ?) - case needs more testing
|
||||
};
|
||||
|
||||
struct Z4p1 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
long long :0; // forced alignment of non-bitfield
|
||||
char d;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
// packed structure contained within default aligned structure
|
||||
struct Z3p1T {
|
||||
char a;
|
||||
struct Z3p1 z3p1;
|
||||
};
|
||||
|
||||
#pragma pack(2)
|
||||
|
||||
|
||||
// Verify bitfield grouping and alignment without zero-length bitfields
|
||||
|
||||
struct B1p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct B2p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
int d:4;
|
||||
};
|
||||
|
||||
struct B3p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
char d; // gcc groups with int bit-field
|
||||
};
|
||||
|
||||
struct B4p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
long long d;
|
||||
int e:4;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Verify bitfield grouping and alignment with zero-length bitfields
|
||||
|
||||
struct Z1p2 {
|
||||
char a;
|
||||
int :0; // MSVC ignores field
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
short d:4; // NOTE: gcc appears ignore short alignment constraint due to int :0 ???
|
||||
};
|
||||
|
||||
struct Z1p2x {
|
||||
char a;
|
||||
int :0; // MSVC ignores field
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
short d:4; // NOTE: gcc appears ignore short alignment constraint due to int :0 ???
|
||||
short d1:4;
|
||||
short d2:4;
|
||||
short d3:4;
|
||||
short d4:4;
|
||||
short d5:4;
|
||||
short d6:4;
|
||||
short d7:4;
|
||||
|
||||
short :0;
|
||||
unsigned short _b:6;
|
||||
int _c:8;
|
||||
short _d:4; // NOTE: gcc appears ignore short alignment constraint due to int :0 ???
|
||||
short _d1:4;
|
||||
short _d2:4;
|
||||
short _d3:4;
|
||||
short _d4:4;
|
||||
short _d5:4;
|
||||
short _d6:4;
|
||||
short _d7:4;
|
||||
|
||||
};
|
||||
|
||||
struct Z2p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
int :0;
|
||||
short d:4;
|
||||
};
|
||||
|
||||
struct Z3p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
int d:4;
|
||||
long long :0; // trailing :0 (ignore when packing ?) - case needs more testing
|
||||
};
|
||||
|
||||
struct Z4p2 {
|
||||
char a;
|
||||
unsigned short b:6;
|
||||
int c:8;
|
||||
long long :0; // forced alignment of non-bitfield
|
||||
char d;
|
||||
};
|
||||
|
||||
struct Z5p2 {
|
||||
char a;
|
||||
unsigned short b:12;
|
||||
int c:8;
|
||||
long long :0; // forced alignment of non-bitfield
|
||||
char d;
|
||||
};
|
||||
|
||||
struct x1p2 {
|
||||
char a;
|
||||
};
|
||||
|
||||
struct x2p2 {
|
||||
char a;
|
||||
int b:27;
|
||||
};
|
||||
|
||||
struct x3p2 {
|
||||
char a;
|
||||
short :0;
|
||||
int b:27;
|
||||
};
|
||||
|
||||
struct x4p2 {
|
||||
char a;
|
||||
int b:27;
|
||||
long long :0;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(4)
|
||||
|
||||
struct Z5p4 {
|
||||
char a;
|
||||
unsigned short b:12;
|
||||
int c:8;
|
||||
long long :0; // forced alignment of non-bitfield
|
||||
char d;
|
||||
};
|
||||
|
||||
struct x1p4 {
|
||||
char a;
|
||||
};
|
||||
|
||||
struct x2p4 {
|
||||
char a;
|
||||
int b:27;
|
||||
};
|
||||
|
||||
struct x3p4 {
|
||||
char a;
|
||||
short :0;
|
||||
int b:27;
|
||||
};
|
||||
|
||||
struct x4p4 {
|
||||
char a;
|
||||
int b:27;
|
||||
long long :0;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
// Structures within structures
|
||||
|
||||
struct S1 {
|
||||
struct B1 b1;
|
||||
struct B2 b2;
|
||||
struct Z1 z1;
|
||||
struct Z2 z2;
|
||||
struct Z3 z3;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct S1p1 {
|
||||
struct B1 b1;
|
||||
struct B2 b2;
|
||||
struct Z1 z1;
|
||||
struct Z2 z2;
|
||||
struct Z3 z3;
|
||||
};
|
||||
|
||||
struct S2p1 {
|
||||
struct B1p1 b1p1;
|
||||
struct B2p1 b2p1;
|
||||
struct Z1p1 z1p1;
|
||||
struct Z2p1 z2p1;
|
||||
struct Z3p1 z3p1;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
#pragma pack(2)
|
||||
|
||||
struct S1p2 {
|
||||
struct B1 b1;
|
||||
struct B2 b2;
|
||||
struct Z1 z1;
|
||||
struct Z2 z2;
|
||||
struct Z3 z3;
|
||||
};
|
||||
|
||||
struct S2p2 {
|
||||
struct B1p2 b1p2;
|
||||
struct B2p2 b2p2;
|
||||
struct Z1p2 z1p2;
|
||||
struct Z2p2 z2p2;
|
||||
struct Z3p2 z3p2;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
enum myEnum { ONE, TWO, THREE };
|
||||
|
||||
typedef enum myEnum enumTypedef;
|
||||
|
||||
typedef int intTypedef;
|
||||
|
||||
typedef char charTypedef;
|
||||
|
||||
typedef short shortTypedef;
|
||||
|
||||
struct T1 {
|
||||
charTypedef a;
|
||||
enum myEnum b:3;
|
||||
enumTypedef c:3;
|
||||
charTypedef d:7;
|
||||
};
|
||||
|
||||
struct T2 {
|
||||
charTypedef a;
|
||||
intTypedef b:17;
|
||||
enumTypedef c:3;
|
||||
charTypedef d:3;
|
||||
};
|
||||
|
||||
// Unions
|
||||
|
||||
union U1 {
|
||||
int a:4;
|
||||
int b:2;
|
||||
};
|
||||
|
||||
union U1z {
|
||||
int a:4;
|
||||
long long :0;
|
||||
int b:2;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
union U1p1 {
|
||||
int a:4;
|
||||
int b:2;
|
||||
};
|
||||
|
||||
union U1p1z {
|
||||
int a:4;
|
||||
long long :0;
|
||||
int b:2;
|
||||
};
|
||||
|
||||
struct SUp1 {
|
||||
char a;
|
||||
union U1p1z u;
|
||||
};
|
||||
|
||||
#pragma pack(2)
|
||||
|
||||
union U1p2 {
|
||||
int a:4;
|
||||
int b:2;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue