mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
BitFields - added direct parse support of bitfield entry within
composite. Restrict use of bitfield datatype.
This commit is contained in:
parent
5ac462441a
commit
1fcad78bc4
13 changed files with 153 additions and 43 deletions
|
@ -239,7 +239,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
||||||
if (!dtc.isBitFieldComponent()) {
|
if (!dtc.isBitFieldComponent()) {
|
||||||
throw new IllegalArgumentException("editOrdinal does not correspond to bitfield");
|
throw new IllegalArgumentException("editOrdinal does not correspond to bitfield");
|
||||||
}
|
}
|
||||||
bitFieldEditorPanel.initEdit(dtc, getPreferredAllocationOffset(dtc), false);
|
bitFieldEditorPanel.initEdit(dtc, getPreferredAllocationOffset(dtc));
|
||||||
setApplyEnabled(true);
|
setApplyEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,8 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
|
|
||||||
private JComponent createDataTypeChoiceEditor() {
|
private JComponent createDataTypeChoiceEditor() {
|
||||||
|
|
||||||
dtChoiceEditor = new DataTypeSelectionEditor(dtmService, -1, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
dtChoiceEditor =
|
||||||
|
new DataTypeSelectionEditor(dtmService, -1, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
||||||
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
||||||
dtChoiceEditor.setTabCommitsEdit(true);
|
dtChoiceEditor.setTabCommitsEdit(true);
|
||||||
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
||||||
|
@ -368,11 +369,8 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
* If null an allocation size of 4-bytes will be used but may be adjusted.
|
* If null an allocation size of 4-bytes will be used but may be adjusted.
|
||||||
* @param bitfieldDtc bitfield component or null
|
* @param bitfieldDtc bitfield component or null
|
||||||
* @param allocationOffset allocation offset to be used
|
* @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,
|
void initEdit(DataTypeComponent bitfieldDtc, int allocationOffset) {
|
||||||
boolean useCurrentAllocation) {
|
|
||||||
String initialFieldName = null;
|
String initialFieldName = null;
|
||||||
DataType initialBaseDataType = null;
|
DataType initialBaseDataType = null;
|
||||||
int allocationSize = -1;
|
int allocationSize = -1;
|
||||||
|
@ -387,9 +385,13 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
initialFieldName = bitfieldDtc.getFieldName();
|
initialFieldName = bitfieldDtc.getFieldName();
|
||||||
BitFieldDataType bitfieldDt = (BitFieldDataType) bitfieldDtc.getDataType();
|
BitFieldDataType bitfieldDt = (BitFieldDataType) bitfieldDtc.getDataType();
|
||||||
initialBaseDataType = bitfieldDt.getBaseDataType();
|
initialBaseDataType = bitfieldDt.getBaseDataType();
|
||||||
if (!useCurrentAllocation || allocationSize < 1) {
|
if (allocationSize < 1) {
|
||||||
allocationSize = initialBaseDataType.getLength();
|
allocationSize = initialBaseDataType.getLength();
|
||||||
}
|
}
|
||||||
|
int allocationAdjust = composite.getLength() - allocationOffset - allocationSize;
|
||||||
|
if (allocationAdjust < 0) {
|
||||||
|
allocationSize += allocationAdjust;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (allocationSize < 1) {
|
if (allocationSize < 1) {
|
||||||
allocationSize = 4;
|
allocationSize = 4;
|
||||||
|
|
|
@ -1216,6 +1216,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
||||||
private DataTypeSelectionEditor editor;
|
private DataTypeSelectionEditor editor;
|
||||||
private DataType dt;
|
private DataType dt;
|
||||||
private int maxLength;
|
private int maxLength;
|
||||||
|
private boolean bitfieldAllowed;
|
||||||
|
|
||||||
private JPanel editorPanel;
|
private JPanel editorPanel;
|
||||||
|
|
||||||
|
@ -1224,6 +1225,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
||||||
boolean isSelected, int row, int column) {
|
boolean isSelected, int row, int column) {
|
||||||
model.clearStatus();
|
model.clearStatus();
|
||||||
maxLength = model.getMaxAddLength(row);
|
maxLength = model.getMaxAddLength(row);
|
||||||
|
bitfieldAllowed = model.isBitFieldAllowed();
|
||||||
init();
|
init();
|
||||||
|
|
||||||
DataTypeInstance dti = (DataTypeInstance) value;
|
DataTypeInstance dti = (DataTypeInstance) value;
|
||||||
|
@ -1243,7 +1245,9 @@ public abstract class CompositeEditorPanel extends JPanel
|
||||||
|
|
||||||
Plugin plugin = provider.getPlugin();
|
Plugin plugin = provider.getPlugin();
|
||||||
final PluginTool tool = plugin.getTool();
|
final PluginTool tool = plugin.getTool();
|
||||||
editor = new DataTypeSelectionEditor(tool, maxLength, AllowedDataTypes.SIZABLE_DYNAMIC);
|
editor = new DataTypeSelectionEditor(tool, maxLength,
|
||||||
|
bitfieldAllowed ? AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD
|
||||||
|
: AllowedDataTypes.SIZABLE_DYNAMIC);
|
||||||
editor.setTabCommitsEdit(true);
|
editor.setTabCommitsEdit(true);
|
||||||
DataTypeManager originalDataTypeManager = model.getOriginalDataTypeManager();
|
DataTypeManager originalDataTypeManager = model.getOriginalDataTypeManager();
|
||||||
editor.setPreferredDataTypeManager(originalDataTypeManager);
|
editor.setPreferredDataTypeManager(originalDataTypeManager);
|
||||||
|
|
|
@ -87,6 +87,11 @@ public interface EditorModel {
|
||||||
*/
|
*/
|
||||||
public boolean isArrayAllowed();
|
public boolean isArrayAllowed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not a bitfield is allowed at the current location.
|
||||||
|
*/
|
||||||
|
public boolean isBitFieldAllowed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not clearing the selected components is allowed.
|
* Returns whether or not clearing the selected components is allowed.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -181,8 +181,7 @@ class StructureEditorModel extends CompEditorModel {
|
||||||
@Override
|
@Override
|
||||||
public DataTypeComponent getComponent(int rowIndex) {
|
public DataTypeComponent getComponent(int rowIndex) {
|
||||||
int numComponents = getNumComponents();
|
int numComponents = getNumComponents();
|
||||||
|
if (numComponents == 0 || rowIndex < 0 || rowIndex == numComponents) {
|
||||||
if (rowIndex < 0 || rowIndex == numComponents) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Structure viewStruct = (Structure) viewComposite;
|
Structure viewStruct = (Structure) viewComposite;
|
||||||
|
@ -571,6 +570,11 @@ class StructureEditorModel extends CompEditorModel {
|
||||||
// Begin methods for determining if a type of edit action is allowed.
|
// Begin methods for determining if a type of edit action is allowed.
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBitFieldAllowed() {
|
||||||
|
return isSingleRowSelection() && !isFlexibleArraySelection();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the selection
|
* Returns whether or not the selection
|
||||||
* is allowed to be changed into an array.
|
* is allowed to be changed into an array.
|
||||||
|
|
|
@ -213,13 +213,18 @@ class UnionEditorModel extends CompEditorModel {
|
||||||
// Begin methods for determining if a type of edit action is allowed.
|
// Begin methods for determining if a type of edit action is allowed.
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBitFieldAllowed() {
|
||||||
|
return isSingleRowSelection();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the selection
|
* Returns whether or not the selection
|
||||||
* is allowed to be changed into an array.
|
* is allowed to be changed into an array.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isArrayAllowed() {
|
public boolean isArrayAllowed() {
|
||||||
return (getNumSelectedComponentRows() == 1);
|
return isSingleRowSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -687,9 +687,14 @@ class StackEditorModel extends CompositeEditorModel {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBitFieldAllowed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isArrayAllowed() {
|
public boolean isArrayAllowed() {
|
||||||
if (getNumSelectedRows() != 1) {
|
if (getNumSelectedRows() != 1 || viewComposite == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int index = getMinIndexSelected();
|
int index = getMinIndexSelected();
|
||||||
|
@ -1437,11 +1442,17 @@ class StackEditorModel extends CompositeEditorModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataTypeComponent getComponent(int rowIndex) {
|
public DataTypeComponent getComponent(int rowIndex) {
|
||||||
|
if (viewComposite == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return viewComposite.getComponent(rowIndex);
|
return viewComposite.getComponent(rowIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getNumComponents() {
|
public int getNumComponents() {
|
||||||
|
if (viewComposite == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return viewComposite.getNumComponents();
|
return viewComposite.getNumComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,7 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
|
|
||||||
// if it is not a known type, the prompt user to create new one
|
// if it is not a known type, the prompt user to create new one
|
||||||
if (!isValidDataType()) {
|
if (!isValidDataType()) {
|
||||||
return promptUserToCreateDataType();
|
return parseDataTypeTextEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -339,8 +339,12 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement in the future to allow the user to create data types
|
/**
|
||||||
private boolean promptUserToCreateDataType() throws InvalidDataTypeException {
|
* Parse datatype text entry using {@link DataTypeParser}. Allows addition
|
||||||
|
* of supported modifiers (e.g., arrays, pointers, etc.).
|
||||||
|
* @return true if parse successful else false
|
||||||
|
*/
|
||||||
|
private boolean parseDataTypeTextEntry() throws InvalidDataTypeException {
|
||||||
|
|
||||||
if (selectionField.getText().trim().length() == 0) {
|
if (selectionField.getText().trim().length() == 0) {
|
||||||
// no need to invoke parser on empty string
|
// no need to invoke parser on empty string
|
||||||
|
@ -349,9 +353,8 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
|
|
||||||
// we will create new pointer and array types by default
|
// we will create new pointer and array types by default
|
||||||
DataType newDataType = null;
|
DataType newDataType = null;
|
||||||
// try {
|
DataTypeParser parser = new DataTypeParser(dataTypeManager, dataTypeManager,
|
||||||
DataTypeParser parser =
|
dataTypeManagerService, allowedDataTypes);
|
||||||
new DataTypeParser(dataTypeManager, null, dataTypeManagerService, allowedDataTypes);
|
|
||||||
newDataType = parser.parse(selectionField.getText(), getDataTypeRootForCurrentText());
|
newDataType = parser.parse(selectionField.getText(), getDataTypeRootForCurrentText());
|
||||||
if (newDataType != null) {
|
if (newDataType != null) {
|
||||||
if (maxSize >= 0 && newDataType.getLength() > newDataType.getLength()) {
|
if (maxSize >= 0 && newDataType.getLength() > newDataType.getLength()) {
|
||||||
|
@ -360,23 +363,6 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
selectionField.setSelectedValue(newDataType);
|
selectionField.setSelectedValue(newDataType);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
// // squash these exceptions, as this method returns false if we were unable to create the
|
|
||||||
// // given data type
|
|
||||||
// catch ( CancelledException ce ) {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// prompt user
|
|
||||||
/*
|
|
||||||
int userChoice = JOptionPane.showOptionDialog( selectionField,
|
|
||||||
"Data type \"" + selectionField.getText() + "\" does not exist. Would you " +
|
|
||||||
"like to create it?", "Create New Data Type?",
|
|
||||||
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null );
|
|
||||||
|
|
||||||
if ( userChoice == JOptionPane.YES_OPTION ) {
|
|
||||||
return createNewDataTypeForUserSelection();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import ghidra.app.services.DataTypeManagerService;
|
||||||
import ghidra.program.database.data.DataTypeUtilities;
|
import ghidra.program.database.data.DataTypeUtilities;
|
||||||
import ghidra.program.database.data.ProgramDataTypeManager;
|
import ghidra.program.database.data.ProgramDataTypeManager;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
public class DataTypeParser {
|
public class DataTypeParser {
|
||||||
|
|
||||||
|
@ -39,6 +40,15 @@ public class DataTypeParser {
|
||||||
* All fixed-length data-types and sizable Dynamic(i.e., canSpecifyLength) data-types
|
* All fixed-length data-types and sizable Dynamic(i.e., canSpecifyLength) data-types
|
||||||
*/
|
*/
|
||||||
SIZABLE_DYNAMIC,
|
SIZABLE_DYNAMIC,
|
||||||
|
/**
|
||||||
|
* All fixed-length data-types, sizable Dynamic data-types.
|
||||||
|
* In addition a bitfield specification may be specified (e.g., int:2)
|
||||||
|
* for use when defining structure and union components only
|
||||||
|
* (see {@link ProxyBitFieldDataType}). Parser must be properly constructed
|
||||||
|
* with the intended {@link DataTypeParser#destinationDataTypeManager}.
|
||||||
|
* If a bitfield is returned special handling is required.
|
||||||
|
*/
|
||||||
|
SIZABLE_DYNAMIC_AND_BITFIELD,
|
||||||
/**
|
/**
|
||||||
* Only Fixed-length data-types
|
* Only Fixed-length data-types
|
||||||
*/
|
*/
|
||||||
|
@ -54,6 +64,26 @@ public class DataTypeParser {
|
||||||
BITFIELD_BASE_TYPE
|
BITFIELD_BASE_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>ProxyBitFieldDataType</code> provides acts as a proxy bitfield
|
||||||
|
* whose specification may be used when defining a structure or
|
||||||
|
* union bitfield. This datatype may not be directly applied to a program.
|
||||||
|
*/
|
||||||
|
private static class ProxyBitFieldDataType extends BitFieldDataType {
|
||||||
|
/**
|
||||||
|
* Construct proxy bitfield datatype for use when defining
|
||||||
|
* a structure or union bitfield.
|
||||||
|
* @param baseDataType a supported primitive integer data type or TypeDef to such a type.
|
||||||
|
* A deep clone of this type will be performed using the specified dataMgr.
|
||||||
|
* @param bitSize size of bit-field expressed as number of bits
|
||||||
|
* @throws InvalidDataTypeException if specified baseDataType is not permitted
|
||||||
|
*/
|
||||||
|
private ProxyBitFieldDataType(DataType baseDataType, int bitSize)
|
||||||
|
throws InvalidDataTypeException {
|
||||||
|
super(baseDataType, bitSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private DataTypeManager sourceDataTypeManager; // may be null
|
private DataTypeManager sourceDataTypeManager; // may be null
|
||||||
private DataTypeManager destinationDataTypeManager; // may be null
|
private DataTypeManager destinationDataTypeManager; // may be null
|
||||||
private DataTypeManagerService dataTypeManagerService; // may be null
|
private DataTypeManagerService dataTypeManagerService; // may be null
|
||||||
|
@ -162,6 +192,12 @@ public class DataTypeParser {
|
||||||
*/
|
*/
|
||||||
public static void ensureIsAllowableType(DataType dt, AllowedDataTypes allowedTypes)
|
public static void ensureIsAllowableType(DataType dt, AllowedDataTypes allowedTypes)
|
||||||
throws InvalidDataTypeException {
|
throws InvalidDataTypeException {
|
||||||
|
if (dt instanceof BitFieldDataType) {
|
||||||
|
if (allowedTypes != AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD) {
|
||||||
|
throw new InvalidDataTypeException("bitfield data-type not allowed");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (allowedTypes) {
|
switch (allowedTypes) {
|
||||||
case DYNAMIC:
|
case DYNAMIC:
|
||||||
if (dt instanceof FactoryDataType) {
|
if (dt instanceof FactoryDataType) {
|
||||||
|
@ -169,6 +205,7 @@ public class DataTypeParser {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SIZABLE_DYNAMIC:
|
case SIZABLE_DYNAMIC:
|
||||||
|
case SIZABLE_DYNAMIC_AND_BITFIELD:
|
||||||
if (dt instanceof FactoryDataType) {
|
if (dt instanceof FactoryDataType) {
|
||||||
throw new InvalidDataTypeException("factory data-type not allowed");
|
throw new InvalidDataTypeException("factory data-type not allowed");
|
||||||
}
|
}
|
||||||
|
@ -205,7 +242,11 @@ public class DataTypeParser {
|
||||||
throws InvalidDataTypeException {
|
throws InvalidDataTypeException {
|
||||||
int arraySequenceStartIndex = -1;
|
int arraySequenceStartIndex = -1;
|
||||||
List<DtPiece> modifiers = new ArrayList<>();
|
List<DtPiece> modifiers = new ArrayList<>();
|
||||||
|
boolean terminalModifier = false;
|
||||||
for (String piece : splitDataTypeModifiers(dataTypeModifiers)) {
|
for (String piece : splitDataTypeModifiers(dataTypeModifiers)) {
|
||||||
|
if (terminalModifier) {
|
||||||
|
throw new InvalidDataTypeException("Invalid data type modifier");
|
||||||
|
}
|
||||||
if (piece.startsWith("*")) {
|
if (piece.startsWith("*")) {
|
||||||
modifiers.add(new PointerSpecPiece(piece));
|
modifiers.add(new PointerSpecPiece(piece));
|
||||||
arraySequenceStartIndex = -1;
|
arraySequenceStartIndex = -1;
|
||||||
|
@ -221,6 +262,10 @@ public class DataTypeParser {
|
||||||
modifiers.add(arraySpec);
|
modifiers.add(arraySpec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (piece.startsWith(":")) {
|
||||||
|
terminalModifier = true;
|
||||||
|
modifiers.add(new BitfieldSpecPiece(piece));
|
||||||
|
}
|
||||||
else if (piece.startsWith("{")) {
|
else if (piece.startsWith("{")) {
|
||||||
// # indicates the size of an array element when the base data type is dynamic.
|
// # indicates the size of an array element when the base data type is dynamic.
|
||||||
modifiers.add(new ElementSizeSpecPiece(piece));
|
modifiers.add(new ElementSizeSpecPiece(piece));
|
||||||
|
@ -241,11 +286,22 @@ public class DataTypeParser {
|
||||||
elementLength = ((ElementSizeSpecPiece) modifier).getElementSize();
|
elementLength = ((ElementSizeSpecPiece) modifier).getElementSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if (modifier instanceof ArraySpecPiece) {
|
||||||
int elementCount = ((ArraySpecPiece) modifier).getElementCount();
|
int elementCount = ((ArraySpecPiece) modifier).getElementCount();
|
||||||
dt = createArrayDataType(dt, elementLength, elementCount);
|
dt = createArrayDataType(dt, elementLength, elementCount);
|
||||||
elementLength = dt.getLength();
|
elementLength = dt.getLength();
|
||||||
}
|
}
|
||||||
|
else if (modifier instanceof BitfieldSpecPiece) {
|
||||||
|
if (allowedTypes != AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD) {
|
||||||
|
throw new InvalidDataTypeException("bitfield not permitted");
|
||||||
|
}
|
||||||
|
if (destinationDataTypeManager == null) {
|
||||||
|
throw new AssertException(
|
||||||
|
"bitfields require destination datatype manager to be specified");
|
||||||
|
}
|
||||||
|
int bitSize = ((BitfieldSpecPiece) modifier).getBitSize();
|
||||||
|
dt = new ProxyBitFieldDataType(dt.clone(destinationDataTypeManager), bitSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
|
@ -375,7 +431,7 @@ public class DataTypeParser {
|
||||||
int nextIndex = 0;
|
int nextIndex = 0;
|
||||||
while (nextIndex < dataTypeString.length()) {
|
while (nextIndex < dataTypeString.length()) {
|
||||||
char c = dataTypeString.charAt(nextIndex);
|
char c = dataTypeString.charAt(nextIndex);
|
||||||
if (c == '*' || c == '[' || c == '{') {
|
if (c == '*' || c == '[' || c == ':' || c == '{') {
|
||||||
return dataTypeString.substring(0, nextIndex).trim();
|
return dataTypeString.substring(0, nextIndex).trim();
|
||||||
}
|
}
|
||||||
++nextIndex;
|
++nextIndex;
|
||||||
|
@ -384,7 +440,7 @@ public class DataTypeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] splitDataTypeModifiers(String dataTypeModifiers) {
|
private static String[] splitDataTypeModifiers(String dataTypeModifiers) {
|
||||||
dataTypeModifiers = dataTypeModifiers.replaceAll("[ \\t]", "");
|
dataTypeModifiers = dataTypeModifiers.replaceAll(":[ \\t]", "");
|
||||||
if (dataTypeModifiers.length() == 0) {
|
if (dataTypeModifiers.length() == 0) {
|
||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
|
@ -393,7 +449,7 @@ public class DataTypeParser {
|
||||||
int nextIndex = 1;
|
int nextIndex = 1;
|
||||||
while (nextIndex < dataTypeModifiers.length()) {
|
while (nextIndex < dataTypeModifiers.length()) {
|
||||||
char c = dataTypeModifiers.charAt(nextIndex);
|
char c = dataTypeModifiers.charAt(nextIndex);
|
||||||
if (c == '*' || c == '[' || c == '{') {
|
if (c == '*' || c == '[' || c == ':' || c == '{') {
|
||||||
list.add(dataTypeModifiers.substring(startIndex, nextIndex));
|
list.add(dataTypeModifiers.substring(startIndex, nextIndex));
|
||||||
startIndex = nextIndex;
|
startIndex = nextIndex;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +476,7 @@ public class DataTypeParser {
|
||||||
destinationDataTypeManager);
|
destinationDataTypeManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int parseArraySize(String numStr) {
|
private static int parseSize(String numStr) {
|
||||||
numStr = (numStr == null ? "" : numStr.trim());
|
numStr = (numStr == null ? "" : numStr.trim());
|
||||||
if (numStr.length() == 0) {
|
if (numStr.length() == 0) {
|
||||||
throw new NumberFormatException();
|
throw new NumberFormatException();
|
||||||
|
@ -435,6 +491,30 @@ public class DataTypeParser {
|
||||||
// dummy interface so we don't have to use Object in the list container
|
// dummy interface so we don't have to use Object in the list container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class BitfieldSpecPiece implements DtPiece {
|
||||||
|
int bitSize;
|
||||||
|
|
||||||
|
BitfieldSpecPiece(String piece) throws InvalidDataTypeException {
|
||||||
|
if (piece.startsWith(":")) {
|
||||||
|
String bitSizeStr = piece.substring(1);
|
||||||
|
try {
|
||||||
|
bitSize = parseSize(bitSizeStr);
|
||||||
|
if (bitSize >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e) {
|
||||||
|
// handled below
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new InvalidDataTypeException("invalid bitfield specification: " + piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBitSize() {
|
||||||
|
return bitSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ArraySpecPiece implements DtPiece {
|
private static class ArraySpecPiece implements DtPiece {
|
||||||
int elementCount;
|
int elementCount;
|
||||||
|
|
||||||
|
@ -442,7 +522,7 @@ public class DataTypeParser {
|
||||||
if (piece.startsWith("[") && piece.endsWith("]")) {
|
if (piece.startsWith("[") && piece.endsWith("]")) {
|
||||||
String elementCountStr = piece.substring(1, piece.length() - 1);
|
String elementCountStr = piece.substring(1, piece.length() - 1);
|
||||||
try {
|
try {
|
||||||
elementCount = parseArraySize(elementCountStr);
|
elementCount = parseSize(elementCountStr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
|
@ -492,7 +572,7 @@ public class DataTypeParser {
|
||||||
if (piece.startsWith("{") && piece.endsWith("}")) {
|
if (piece.startsWith("{") && piece.endsWith("}")) {
|
||||||
String elementSizeStr = piece.substring(1, piece.length() - 1);
|
String elementSizeStr = piece.substring(1, piece.length() - 1);
|
||||||
try {
|
try {
|
||||||
elementSize = parseArraySize(elementSizeStr);
|
elementSize = parseSize(elementSizeStr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
|
|
|
@ -72,6 +72,10 @@ public class ArrayDataType extends DataTypeImpl implements Array {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validate(DataType dt) {
|
private void validate(DataType dt) {
|
||||||
|
if (dt instanceof BitFieldDataType) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Array data-type may not be a bitfield: " + dt.getName());
|
||||||
|
}
|
||||||
if (dt instanceof FactoryDataType) {
|
if (dt instanceof FactoryDataType) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Array data-type may not be a Factory data-type: " + dt.getName());
|
"Array data-type may not be a Factory data-type: " + dt.getName());
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class BitFieldDataType extends AbstractDataType {
|
||||||
/**
|
/**
|
||||||
* Construct a bit-field type based upon a supported baseDataType.
|
* Construct a bit-field type based upon a supported baseDataType.
|
||||||
* @param baseDataType a supported primitive integer data type or TypeDef to such a type.
|
* @param baseDataType a supported primitive integer data type or TypeDef to such a type.
|
||||||
* A deep clone of this type will be performed using the specified dataMgr.
|
* The baseType must already be cloned to the target datatype manager.
|
||||||
* @param bitSize size of bit-field expressed as number of bits
|
* @param bitSize size of bit-field expressed as number of bits
|
||||||
* @throws InvalidDataTypeException if specified baseDataType is not permitted
|
* @throws InvalidDataTypeException if specified baseDataType is not permitted
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -112,6 +112,11 @@ public class PointerDataType extends BuiltIn implements Pointer {
|
||||||
public PointerDataType(DataType referencedDataType, int length, DataTypeManager dtm) {
|
public PointerDataType(DataType referencedDataType, int length, DataTypeManager dtm) {
|
||||||
super(referencedDataType != null ? referencedDataType.getCategoryPath() : null,
|
super(referencedDataType != null ? referencedDataType.getCategoryPath() : null,
|
||||||
constructUniqueName(referencedDataType, length), dtm);
|
constructUniqueName(referencedDataType, length), dtm);
|
||||||
|
if (referencedDataType instanceof BitFieldDataType) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Pointer reference data-type may not be a bitfield: " +
|
||||||
|
referencedDataType.getName());
|
||||||
|
}
|
||||||
this.length = length <= 0 ? -1 : length;
|
this.length = length <= 0 ? -1 : length;
|
||||||
this.referencedDataType = referencedDataType;
|
this.referencedDataType = referencedDataType;
|
||||||
if (referencedDataType != null) {
|
if (referencedDataType != null) {
|
||||||
|
|
|
@ -75,6 +75,10 @@ public class TypedefDataType extends GenericDataType implements TypeDef {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validate(DataType dt) {
|
private void validate(DataType dt) {
|
||||||
|
if (dt instanceof BitFieldDataType) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"TypeDef data-type may not be a bitfield: " + dt.getName());
|
||||||
|
}
|
||||||
if (dt instanceof FactoryDataType) {
|
if (dt instanceof FactoryDataType) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"TypeDef data-type may not be a Factory data-type: " + dt.getName());
|
"TypeDef data-type may not be a Factory data-type: " + dt.getName());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue