GP-943 Added support for zero-length arrays and

zero-length components.  NOTE: We still never return 0 for
DataType.getLength().  Added DataType.isZeroLength().
This commit is contained in:
ghidra1 2021-08-10 17:51:35 -04:00
parent 579e3bacf7
commit cfdec26da4
188 changed files with 7968 additions and 6645 deletions

View file

@ -116,8 +116,14 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
}
}
@Deprecated
@Override
default DBTraceDefinedDataAdapter getComponentAt(int offset) {
return getComponentContaining(offset);
}
@Override
default DBTraceDefinedDataAdapter getComponentContaining(int offset) {
// We may write to the cache
try (LockHold hold = LockHold.lock(getTrace().getReadWriteLock().writeLock())) {
if (offset < 0 || offset >= getLength()) {
@ -133,7 +139,7 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
}
if (baseDataType instanceof Structure) {
Structure structure = (Structure) baseDataType;
DataTypeComponent dtc = structure.getComponentAt(offset);
DataTypeComponent dtc = structure.getComponentContaining(offset);
return dtc == null ? null : getComponent(dtc.getOrdinal());
}
if (baseDataType instanceof Union) {
@ -155,7 +161,6 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
if (offset < 0 || offset >= getLength()) {
return null;
}
DataType baseDataType = getBaseDataType();
if (baseDataType instanceof Array) {
Array array = (Array) baseDataType;
@ -163,24 +168,30 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
int index = offset / elementLength;
return Collections.singletonList(getComponent(index));
}
if (baseDataType instanceof Structure) {
Structure structure = (Structure) baseDataType;
DataTypeComponent dtc = structure.getComponentAt(offset);
else if (baseDataType instanceof Structure) {
Structure struct = (Structure) baseDataType;
List<Data> result = new ArrayList<>();
// Logic handles overlapping bit fields
for (DataTypeComponent dtc : struct.getComponentsContaining(offset)) {
result.add(getComponent(dtc.getOrdinal()));
}
return result;
}
else if (baseDataType instanceof DynamicDataType) {
DynamicDataType ddt = (DynamicDataType) baseDataType;
DataTypeComponent dtc = ddt.getComponentAt(offset, this);
List<Data> result = new ArrayList<>();
// Logic handles overlapping bit-fields
// Include if offset is contained within bounds of component
while (dtc != null && offset >= dtc.getOffset() &&
offset <= dtc.getOffset() + dtc.getLength() - 1) {
int ordinal = dtc.getOrdinal(); // TODO: Seems I could move this before while
result.add(getComponent(ordinal));
ordinal++;
dtc = ordinal < structure.getNumComponents() ? structure.getComponent(ordinal)
while (dtc != null && (offset >= dtc.getOffset()) &&
(offset < (dtc.getOffset() + dtc.getLength()))) {
int ordinal = dtc.getOrdinal();
result.add(getComponent(ordinal++));
dtc = ordinal < ddt.getNumComponents(this) ? ddt.getComponent(ordinal, this)
: null;
}
return result;
}
if (baseDataType instanceof Union) {
/** NOTE: The {@link DataDB} implementation seems hasty */
else if (baseDataType instanceof Union) {
Union union = (Union) baseDataType;
List<Data> result = new ArrayList<>();
for (DataTypeComponent dtc : union.getComponents()) {
@ -190,12 +201,6 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
}
return result;
}
if (baseDataType instanceof DynamicDataType) {
DynamicDataType dynamic = (DynamicDataType) baseDataType;
DataTypeComponent dtc = dynamic.getComponentAt(offset, this);
return dtc == null ? Collections.emptyList()
: Collections.singletonList(getComponent(dtc.getOrdinal()));
}
return Collections.emptyList();
}
}

View file

@ -237,6 +237,11 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey
return null;
}
@Override
public Data getComponentContaining(int offset) {
return null;
}
@Override
public List<Data> getComponentsContaining(int offset) {
if (offset < 0 || offset >= getLength()) {

View file

@ -1414,8 +1414,8 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest
assertNull(u3fff.getFieldName());
assertNull(s4000.getFieldName());
assertEquals("nuD", s4000nuD.getFieldName());
assertEquals("field_0x4", s4000lE.getFieldName());
assertEquals("field_0x8", s4000pF.getFieldName());
assertEquals("field2_0x4", s4000lE.getFieldName());
assertEquals("field3_0x8", s4000pF.getFieldName());
// TODO: DAT... may change when proper symbols are implemented
assertEquals("DAT_00003fff", u3fff.getPathName());

View file

@ -85,6 +85,10 @@ public abstract class DBDomainObjectSupport extends DomainObjectAdapterDB {
}
catch (VersionException e) {
versionExc = e.combine(versionExc);
// TODO: (see GP-1238) Consider properly supporting VersionException and upgrades.
// Returning a null manager will likely induce an NPE down the line.
return null;
}
}

View file

@ -373,28 +373,22 @@
<P><IMG alt="Note:" src="../../shared/note.png">The use of bitfield components is not
currently reflected in decompiler results or assembly markup. </P>
<H2><A name="Structure_Editor_Flex_Array"></A>Flexible Array Component</H2>
<H2><A name="Structure_Editor_Flex_Array"></A>Zero-Element / Flexible Array Components</H2>
<P>A structure may be defined with a trailing flexible array component which corresponds to
an unsized array (e.g., char[0]). Such a component, if it exists, is always displayed as the
last row within the structure editor with the open edit row for additional components located
directly above it. The <I>DataType</I> column for a flexible array always shows
the base type of the unsized array which can be modified similar to other components. A
flexible array is added to the end of a structure by adding a last row specified by the base
<I>DataType</I> (e.g. char)
then invoking the array action and specifying an element count of 0. Attempting to specify
an element count of 0 is only permitted on the last component row when a flexible array component
does not already exist. The presence of a flexible array component does not affect the size of a
structure and will not appear within the structure when applied to Data within memory as it
corresponds to the memory location which immediately follows the end of the structure.</P>
<P>A structure may be defined with zero-element array components, also referred to as a
flexible array, which correspond to an unsized array (e.g., char[0]). Such a component
is created by simply specifying a zero-element array datatype as you would a sized-array component
(see <A href="#Structure_Editor_Create_FlexArray">Create
Zero-Element / Flexible Array Component</A>).
The resulting component will not consume any space within the structure and will report a component
size of 0. As such, it may reside at the same offset as a subsequent component and/or may have an offset
equal to the length of the structure. When packing is enabled such a component may influence the
overall alignment of the structure and its length.
<P><IMG alt="Note:" src="../../shared/note.png">The use of flexible array components is not
currently reflected in decompiler results or listing reference markup. Its primary purpose
if to reflect the C/C++ source definition of a structure with correct alignment and structure sizing.</P>
<P><IMG alt="Note:" src="../../shared/note.png">While C/C++ support flexible arrays anywhere
within a structure, Ghidra only supports the case where it is the last structure component.</P>
<DIV style="text-align: center;">
<IMG alt="" src="images/StructureEditorWithFlexArray.png"><BR>
<BR>
@ -415,7 +409,7 @@
<BLOCKQUOTE>
<P>Within a non-packed structure <i>undefined</i> components are inserted before the current selection by clicking the <IMG src=
"images/Plus.png" alt=""> <B>Insert Undefined Byte</B> button. Within a packed structure an <i>undefined1<i> datatype component
"images/Plus.png" alt=""> <B>Insert Undefined Byte</B> button. Within a packed structure an <i>undefined1</i> datatype component
is inserted in a similar fashion, although in packed structures it is more appropriate to use a properly sized datatype (e.g., modify datatype
on inserted component).</P>
</BLOCKQUOTE>
@ -587,24 +581,14 @@
</BLOCKQUOTE>
<H3><A name="Structure_Editor_Create_FlexArray"></A> <IMG src="images/Array.png" alt="">Create
Flexible Array</H3>
Zero-Element / Flexible Array Component</H3>
<BLOCKQUOTE>
<P>To create an unsized flexible array as the last structure component (assuming one
is not already defined):</P>
<OL>
<LI>Add a component whose <I>DataType</I> corresponds to the base type of the unsized array.</LI>
<LI>Select this last structure component in the table.</LI>
<LI>Press the <IMG src="images/Array.png" alt=""> <B>Create Array</B> button or the '['
action key binding.</LI>
<LI>A dialog pops up to request
the number of elements in the array. Specify 0 as the number of elements in the popup
dialog and click OK.</LI>
</OL>
<P>To create an unsized flexible array component you must use the datatype cell edit feature
to select/enter the datatype by name including the array-sizing-specification (e.g., char[0]).
To initiate edit mode for a component datatype you must double-click the datatype cell for the component
you wish to modify. This may be an existing component or the empty row at the end of the table.
See <A href="#Structure_Editor_Editing_DataType">Editing the DataType Field</A> for more details.
</BLOCKQUOTE>
<H3><A name="Structure_Editor_Unpackage_Component"></A> <IMG src="images/Unpackage.gif" alt="">
@ -617,8 +601,7 @@
button. For example, the array component Word[4] would become four Word components. If the
structure struct_1 was composed of a Float and a DWord, then unpackaging it would replace the
struct_1 component with a Float component and a DWord component.</P>
</BLOCKQUOTE><BR>
</BLOCKQUOTE>
<H3><A name="Structure_Editor_Create_Structure_From_Selection"></A> <IMG src=
"images/cstruct.png" alt=""> Create Structure From Selection</H3>
@ -778,43 +761,75 @@
session top to bottom in the table.</P>
</BLOCKQUOTE>
<H3>Editing the <I>DataType</I> Field</H3>
<H3><A name="Structure_Editor_Editing_DataType"></A>Editing the <I>DataType</I> Field</H3>
<P>This can be any data type that is available in the data type manager. To edit the data
type double-click the data type cell. This will show the <A href=
<P>To edit the data type double-click the data type cell. This will show the <A href=
"help/topics/DataTypeEditors/DataTypeSelectionDialog.htm">Data Type Selection Dialog</A>,
which allows you to easily enter a data type. It can also be Undefined, a pointer to a data
type, or an array.</P>
which allows you to easily enter a data type or select/modify an existing one from one of the open
datatype managers. It can also be Undefined, a pointer to a datatype, or an array.</P>
<P><IMG alt="Note:" src="../../shared/note.png"> Certain restrictions may apply when specifying
or modifying a component's datatype which could cause a modification to fail. Some common restrictions include
but are not limited to:</P>
<BLOCKQUOTE>
<P><B>Basic Data Type</B></P>
<ul>
<li>Fit (non-packed structure only) - when modifying a component
there must be adequate space to place the component. Any undefined components which immediately follow
the modified component may be consumed or added based upon the component size change. It may be neccessary to
insert undefined bytes or clear other components before the modification may be completed.</li>
<li>Illegal Datatype - certain datatypes are not permitted (e.g., data driven Dynamic types, Factory types).</li>
<li>Zero-Length Components (non-packed structure only) - modification of an existing zero-length component may
not change its size.</li>
</ul>
</BLOCKQUOTE>
<P>This can be a built-in data type (Byte, Word, etc.), a structure, a union, or a
typedef.</P>
<P>Examples of datatypes which may be specified, include:</P>
<P>For example, Word.</P>
<BLOCKQUOTE>
<P><A name="Structure_Editor_Basic_Data_Type"></A><B>Basic Data Type</B></P>
<P>This can be any fixed-length built-in data type (e.g., byte, word, etc.), structure, union, typedef, or enum.
<P><B>Sizable Dynamic Data Type</B></P>
<P>A sizable built-in Dynamic data type such as <i>string</i> may be specified in which case the user
will be prompted to specify the component size.</P>
<P><B>Pointer Data Type</B></P>
<P>This can be the basic Pointer data type or a pointer to a data type. A pointer to a data
type is indicated by following the data type with an *.</P>
<P>This can be a named Pointer data type (e.g., <i>pointer</i>, <i>pointer16</i>, etc.) or a pointer to a specific data type. A pointer to a data
type is indicated by following the data type name with an * (i.e., asterisk symbol). It is also possible to stipulate a specific pointer-size, although it should be
only done when the default pointer size is inappropriate. A stipulated pointer size may be specified by following the * with its bit-size
(16,24,32..64). The pointer * designation may also be stacked for a pointer-to-pointer type.</P>
<P>For example, Word * is a pointer to a Word.</P>
<P>For example, <i>word*</i> is a pointer to a Word using the default pointer size. If a non-default size is needed <i>word*16</i> would force
the use of a 16-bit pointer.</P>
<P><B>Array</B></P>
<P>This can be a multidimensional array of any data type.</P>
<P>A single or multidimensional array of any <A href="#Structure_Editor_Basic_Data_Type">basic data type</A> may be specified.</P>
<P>For example, DWord[2][4] is an array with 2 elements, where each element is an array
with 4 elements that are DWords.</P>
<P>For example, <i>dword[2][4]</i> is an array with 2 elements, where each element is an array
with 4 elements that are DWords; In a similar fashion a zero-element character array may be specified
as <i>char[0]</i>.</P>
<P><B>Array of Pointers</B></P>
<P>Arrays of pointers can also be specified.</P>
<P>Arrays of pointers may also be specified.</P>
<P>For example, Float*[5] is an array with five elements where each element is a pointer to
<P>For example, <i>float*[5]</i> is an array with five elements where each element is a pointer to
a Float.</P>
<P><B>Bitfields</B></P>
<P>A bitfield may be specified by appending <b>:&lt;bitsize&gt;</b> to the end of a valid base datatype. Valid base datatypes include
all integer types (e.g., byte, char, int, etc.), a defined enum, or a typedef which corresponds to an integer-type or enum.
It is important to note that specifying a bitfield in this manner works well for packed structures, however for non-packed
structures it may be neccessary to use the <A href="#Structure_Editor_Bitfield_Actions">Bitfield Actions</A> to properly define a bitfield.</P>
<P>For example, <i>int:4</i> defines a signed integer bitfield which is 4-bits in length.
<H4><A name="EffectOfChangingDataTypeSize"></A> <U>Effect of Changing a Component's
Size</U></H4>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Before After
Before After

View file

@ -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.
@ -22,9 +21,10 @@ import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
/**
* Command to create an array.
* Command to create an array. All conflicting data will be cleared.
*
*/
public class CreateArrayCmd implements Command {
@ -38,8 +38,10 @@ public class CreateArrayCmd implements Command {
* Constructs a new command for creating arrays.
* @param addr The address at which to create an array.
* @param numElements the number of elements in the array to be created.
* A 0 element count is permitted but a minimum length will apply for all array instances.
* @param dt the dataType of the elements in the array to be created.
* @param elementLength the size of an element in the array.
* @param elementLength the size of an element in the array. Only used for Dynamic
* datatype <code>dt</code> when {@link Dynamic#canSpecifyLength()} returns true.
*/
public CreateArrayCmd(Address addr, int numElements, DataType dt, int elementLength) {
this.addr = addr;
@ -48,68 +50,46 @@ public class CreateArrayCmd implements Command {
this.elementLength = elementLength;
}
/**
*
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
*/
@Override
public boolean applyTo(DomainObject obj) {
Program program = (Program)obj;
Listing listing = program.getListing();
if (dataType instanceof FactoryDataType) {
msg = "Array not allowed on a Factory data-type: " + dataType.getName();
return false;
}
if (dataType instanceof Dynamic && !((Dynamic)dataType).canSpecifyLength()) {
msg = "Array not allowed on a non-sizable Dynamic data-type: " + dataType.getName();
return false;
}
if (elementLength <=0) {
msg = "DataType must have fixed size > 0, not "+dataType.getLength();
return false;
}
if (numElements <= 0) {
msg = "Number of elements must be positive, not "+numElements;
return false;
}
int length = numElements*elementLength;
Address endAddr;
try {
endAddr = addr.addNoWrap(length - 1);
} catch (AddressOverflowException e1) {
msg = "Can't create data because length exceeds address space";
return false;
}
ArrayDataType adt = new ArrayDataType(dataType, numElements, elementLength,
program.getDataTypeManager());
int length = adt.getLength();
Address endAddr = addr.addNoWrap(length - 1);
AddressSet set = new AddressSet(addr, endAddr);
InstructionIterator iter = listing.getInstructions(set, true);
if (iter.hasNext()) {
msg = "Can't create data because the current selection contains instructions";
return false;
}
listing.clearCodeUnits(addr, endAddr, false);
ArrayDataType adt = new ArrayDataType(dataType, numElements, elementLength);
try {
listing.createData(addr, adt, adt.getLength());
} catch(CodeUnitInsertionException e) {
} catch (AddressOverflowException e1) {
msg = "Can't create data because length exceeds address space";
return false;
}
catch (IllegalArgumentException | CodeUnitInsertionException e) {
msg = e.getMessage();
return false;
}
catch (RuntimeException e) {
msg = "Unexpected error: " + e.toString();
Msg.error(this, msg, e);
return false;
}
return true;
}
/**
* @see ghidra.framework.cmd.Command#getStatusMsg()
*/
@Override
public String getStatusMsg() {
return msg;
}
/**
* @see ghidra.framework.cmd.Command#getName()
*/
@Override
public String getName() {
return "Create Array";
}

View file

@ -20,9 +20,11 @@ import ghidra.framework.model.DomainObject;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.util.Msg;
/**
* Command to create an array inside of a structure.
* Command to create an array inside of a structure. All conflicting components
* within the targeted structure will be replaced with the new array component.
*
*/
public class CreateArrayInStructureCmd implements Command {
@ -32,13 +34,20 @@ public class CreateArrayInStructureCmd implements Command {
private DataType dataType;
private int[] compPath;
// NOTE: This command does not currently handle Dynamic types whose length may
// be specified since no elementLength parameter exists.
/**
* Constructs a new command for creating arrays inside of structures.
* The specified component will be replaced as will subsequent components within
* the structure required to make room for the new array component.
* NOTE: This is intended for replacing existing components and not for
* simply inserting an array component.
* @param addr The address of the structure that will contain the new array.
* @param numElements the number of elements in the array to be created.
* @param numElements the number of elements in the array to be created. A 0 element count is permitted.
* @param dt the dataType of the elements in the array to be created.
* @param compPath the component path within the structure at which to create
* the array. The component path is an array of integers where each integer
* @param compPath the target component path within the structure of an existing component where
* the array should be created. The component path is an array of integers where each integer
* is a component index of the component above it.
*/
public CreateArrayInStructureCmd(Address addr, int numElements, DataType dt,
@ -48,42 +57,18 @@ public class CreateArrayInStructureCmd implements Command {
this.dataType = dt;
this.compPath = compPath;
}
/**
*
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
*/
@Override
public boolean applyTo(DomainObject obj) {
Program program = (Program)obj;
Listing listing = program.getListing();
if (dataType instanceof FactoryDataType) {
msg = "Array not allowed on a Factory data-type: " + dataType.getName();
return false;
}
if (dataType instanceof Dynamic && !((Dynamic)dataType).canSpecifyLength()) {
msg = "Array not allowed on a non-sizable Dynamic data-type: " + dataType.getName();
return false;
}
if (numElements <= 0) {
msg = "Number of elements must be positive, not "+numElements;
return false;
}
Data data = listing.getDataContaining(addr);
Data compData = data.getComponent(compPath);
int elementLength;
if (dataType instanceof Dynamic) {
elementLength = compData.getLength();
}
else {
elementLength = dataType.getLength();
}
if (elementLength <=0) {
msg = "DataType must have fixed size > 0, not "+elementLength;
if (compData == null) {
msg = "Invalid target component path specified";
return false;
}
int length = numElements*elementLength;
int index = compData.getComponentIndex();
int offset = compData.getParentOffset();
@ -94,23 +79,34 @@ public class CreateArrayInStructureCmd implements Command {
return false;
}
Structure struct = (Structure)parentDataType;
if (offset+length > struct.getLength()) {
msg = "Array too big for structure";
DataType baseDt = dataType;
if (dataType instanceof TypeDef) {
baseDt = ((TypeDef) dataType).getBaseDataType();
}
if (baseDt instanceof Dynamic) {
msg = "Dynamic data-type may not be specified: " + dataType.getName();
return false;
}
try {
ArrayDataType adt = new ArrayDataType(dataType, numElements, dataType.getLength());
int length = adt.isZeroLength() ? 0 : adt.getLength();
if (!struct.isPackingEnabled() && (offset + length) > struct.getLength()) {
msg = "Array too big for structure";
return false;
}
clearStruct(struct, compData.getParentOffset(), length);
if (struct.isPackingEnabled()) {
struct.insert(index, adt, adt.getLength());
struct.insert(index, adt, -1);
}
else {
struct.replace(index, adt, adt.getLength());
struct.replace(index, adt, -1);
}
}
catch(Exception e) {
msg = e.getMessage();
catch (RuntimeException e) {
msg = "Unexpected error: " + e.toString();
Msg.error(this, msg, e);
return false;
}
return true;
@ -129,6 +125,7 @@ public class CreateArrayInStructureCmd implements Command {
/**
* @see ghidra.framework.cmd.Command#getStatusMsg()
*/
@Override
public String getStatusMsg() {
return msg;
}
@ -136,6 +133,7 @@ public class CreateArrayInStructureCmd implements Command {
/**
* @see ghidra.framework.cmd.Command#getName()
*/
@Override
public String getName() {
return "Create Array";
}

View file

@ -1094,62 +1094,6 @@ public class DataTypeMergeManager implements MergeResolver {
}
}
private void updateFlexArray(long sourceDtID, Structure sourceDt, Structure destStruct,
Map<Long, DataType> resolvedDataTypes) {
DataTypeComponent flexDtc = sourceDt.getFlexibleArrayComponent();
if (flexDtc == null) {
return;
}
DataTypeManager sourceDTM = sourceDt.getDataTypeManager();
DataType sourceCompDt = flexDtc.getDataType();
String comment = flexDtc.getComment();
long sourceComponentID = sourceDTM.getID(sourceCompDt);
// Try to get a mapping of the source data type to a result data type.
DataType resultCompDt = getResolvedComponent(sourceComponentID, resolvedDataTypes);
if (resultCompDt == null) {
// We didn't have a map entry for the data type.
if (!myDtAddedList.contains(Long.valueOf(sourceComponentID))) {
// Not added so should be in result if it wasn't deleted there.
DataType rDt = dtms[RESULT].getDataType(sourceComponentID);
if (rDt != null) {
resultCompDt = rDt;
}
}
if (resultCompDt == null) {
// Not added/resolved yet
// put an entry in the fixup list
fixUpList.add(new FixUpInfo(sourceDtID, sourceComponentID, Integer.MAX_VALUE,
resolvedDataTypes));
fixUpIDSet.add(sourceDtID);
// substitute datatype to preserve component name for subsequent fixup
resultCompDt = Undefined1DataType.dataType;
}
}
try {
// Apply resultCompDt as flex array
try {
destStruct.setFlexibleArrayComponent(resultCompDt, flexDtc.getFieldName(), comment);
}
catch (IllegalArgumentException e) {
displayError(destStruct, e);
DataType badDt = Undefined1DataType.dataType;
comment = "Couldn't add " + resultCompDt.getDisplayName() + " here. " +
e.getMessage() + " " + ((comment != null) ? (" " + comment) : "");
destStruct.setFlexibleArrayComponent(badDt, flexDtc.getFieldName(), comment);
}
}
catch (IllegalArgumentException e) {
displayError(destStruct, e);
}
}
private void updateStructure(long sourceDtID, Structure sourceDt, Structure destStruct,
Map<Long, DataType> resolvedDataTypes) {
@ -1332,8 +1276,6 @@ public class DataTypeMergeManager implements MergeResolver {
if (!aligned) {
adjustStructureSize(destStruct, sourceDt.getLength());
}
updateFlexArray(sourceDtID, sourceDt, destStruct, resolvedDataTypes);
}
/**
@ -1343,7 +1285,7 @@ public class DataTypeMergeManager implements MergeResolver {
*/
private static void adjustStructureSize(Structure struct, int preferredSize) {
DataTypeComponent dtc = struct.getComponentAt(preferredSize);
DataTypeComponent dtc = struct.getComponentContaining(preferredSize);
if (dtc == null) {
struct.growStructure(preferredSize - struct.getLength());
return;
@ -1895,16 +1837,6 @@ public class DataTypeMergeManager implements MergeResolver {
}
checkOffsets = true;
}
DataTypeComponent flexDtc1 = ((Structure) c1).getFlexibleArrayComponent();
DataTypeComponent flexDtc2 = ((Structure) c2).getFlexibleArrayComponent();
if (flexDtc1 != null && flexDtc2 != null) {
if (isChangedComponent(flexDtc1, flexDtc2, dtm1, dtm2, false)) {
return true;
}
}
else if (flexDtc1 != null || flexDtc2 != null) {
return true;
}
}
DataTypeComponent[] c1Components = c1.getDefinedComponents();
@ -2384,7 +2316,7 @@ public class DataTypeMergeManager implements MergeResolver {
}
/**
* Process fixup for aligned structure component or trailing flexible array
* Process fixup for aligned structure component
* @param info fixup info
* @param struct result structure
* @param dt component datatype
@ -2392,35 +2324,15 @@ public class DataTypeMergeManager implements MergeResolver {
*/
private boolean fixUpAlignedStructureComponent(FixUpInfo info, Structure struct, DataType dt) {
int ordinal = info.index;
boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE);
DataTypeComponent dtc = null;
if (isFlexArrayFixup) {
dtc = struct.getFlexibleArrayComponent();
}
else {
if (ordinal >= 0 || ordinal < struct.getNumComponents()) {
dtc = struct.getComponent(ordinal);
}
}
if (dtc == null) {
return false;
}
if (isFlexArrayFixup) {
try {
struct.setFlexibleArrayComponent(dt, dtc.getFieldName(), dtc.getComment());
}
catch (IllegalArgumentException e) {
displayError(struct, e);
DataType badDt = Undefined1DataType.dataType;
String comment = dtc.getComment();
comment = "Couldn't add " + dt.getDisplayName() + "[ ] here. " + e.getMessage() +
" " + ((comment != null) ? (" " + comment) : "");
struct.replace(ordinal, badDt, dtc.getLength(), dtc.getFieldName(), comment);
struct.setFlexibleArrayComponent(badDt, dtc.getFieldName(), comment);
}
}
else if (dtc.isBitFieldComponent()) {
if (dtc.isBitFieldComponent()) {
if (BitFieldDataType.isValidBaseDataType(dt)) {
// replace bitfield base datatype - silent if updated type is not a valid base type
BitFieldDataType bfDt = (BitFieldDataType) dtc.getDataType();
@ -2542,13 +2454,10 @@ public class DataTypeMergeManager implements MergeResolver {
DataType compDt = resolve(info.compID, info.getDataTypeManager(), info.ht);
boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE);
if (compDt != null) {
if (struct.isPackingEnabled() || isFlexArrayFixup) {
if (struct.isPackingEnabled()) {
if (!fixUpAlignedStructureComponent(info, struct, compDt)) {
String msg =
isFlexArrayFixup ? "flex-array component" : ("component " + info.index);
String msg = "component " + info.index;
Msg.warn(this, "Structure Merge: Couldn't get " + msg + " in " +
struct.getPathName() + " data type during fix up.");
return false; // Don't remove this FixUpInfo from the fixupList so the user will get notified.
@ -2565,9 +2474,6 @@ public class DataTypeMergeManager implements MergeResolver {
}
// Datatype failed to resolved - check to see if we have a placeholder
else if (isFlexArrayFixup) {
struct.clearFlexibleArrayComponent();
}
else if (struct.isPackingEnabled()) {
int ordinal = info.index;
int numComponents = struct.getNumComponents();
@ -3291,7 +3197,7 @@ public class DataTypeMergeManager implements MergeResolver {
if (composite.isPackingEnabled() || (composite instanceof Union)) {
return dtc.getOrdinal();
}
return dtc.getOffset();
return dtc.getOffset(); // TODO: use of offset could be problematic with shared offset
}
/**
@ -3301,7 +3207,7 @@ public class DataTypeMergeManager implements MergeResolver {
private class FixUpInfo {
long id;
long compID;
int index;
int index; // TODO: index as offset could be problematic with shared offset
Map<Long, DataType> ht;
// bitfield info
@ -3315,7 +3221,6 @@ public class DataTypeMergeManager implements MergeResolver {
* @param compID id of either component or base type
* @param index offset into non-packed structure, or ordinal into union or packed
* structure; or parameter/return ordinal; for other data types index is not used (specify -1).
* For structure trailing flex-array specify {@link Integer#MAX_VALUE}.
* @param resolvedDataTypes hashtable used for resolving the data type
*/
FixUpInfo(long id, long compID, int index,

View file

@ -87,44 +87,44 @@ class DataTypePanel extends JPanel {
pathAttrSet = new SimpleAttributeSet();
pathAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
pathAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11));
pathAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
pathAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
pathAttrSet.addAttribute(StyleConstants.Foreground, MergeConstants.CONFLICT_COLOR);
nameAttrSet = new SimpleAttributeSet();
nameAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
nameAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11));
nameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
nameAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
sourceAttrSet = new SimpleAttributeSet();
sourceAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
sourceAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11));
sourceAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
sourceAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
sourceAttrSet.addAttribute(StyleConstants.Foreground, SOURCE_COLOR);
offsetAttrSet = new SimpleAttributeSet();
offsetAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
offsetAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
offsetAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
offsetAttrSet.addAttribute(StyleConstants.Foreground, Color.BLACK);
contentAttrSet = new SimpleAttributeSet();
contentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
contentAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
contentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
contentAttrSet.addAttribute(StyleConstants.Foreground, Color.BLUE);
fieldNameAttrSet = new SimpleAttributeSet();
fieldNameAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
fieldNameAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
fieldNameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
fieldNameAttrSet.addAttribute(StyleConstants.Foreground, new Color(204, 0, 204));
commentAttrSet = new SimpleAttributeSet();
commentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
commentAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
commentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
commentAttrSet.addAttribute(StyleConstants.Foreground, new Color(0, 204, 51));
deletedAttrSet = new SimpleAttributeSet();
deletedAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
deletedAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
deletedAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
deletedAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
deletedAttrSet.addAttribute(StyleConstants.Foreground, Color.RED);
@ -149,7 +149,7 @@ class DataTypePanel extends JPanel {
}
private void formatAlignment(Composite composite) {
String str = CompositeDataTypeImpl.getAlignmentAndPackingString(composite);
String str = CompositeInternal.getAlignmentAndPackingString(composite);
insertString(str + "\n\n", sourceAttrSet);
}
@ -178,10 +178,7 @@ class DataTypePanel extends JPanel {
DataType dt = dtc.getDataType();
StringBuilder buffer = new StringBuilder();
buffer.append(dt.getName());
if (dtc.isFlexibleArrayComponent()) {
buffer.append("[0]");
}
else if (dt instanceof BitFieldDataType &&
if (dt instanceof BitFieldDataType &&
!((Composite) dtc.getParent()).isPackingEnabled()) {
BitFieldDataType bfDt = (BitFieldDataType) dt;
buffer.append("(");
@ -204,14 +201,9 @@ class DataTypePanel extends JPanel {
offsetWidth += 2; // factor in 0x prefix
String offsetStr = "";
if (offsetWidth > 0) {
if (!dtc.isFlexibleArrayComponent()) {
offsetStr = "0x" + Integer.toHexString(dtc.getOffset());
offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth - offsetStr.length());
offsetStr += ": ";
}
else {
offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth + 2);
}
insertString(" " + offsetStr + " ", offsetAttrSet);
}
fieldName = pad(fieldName, fieldNameWidth);
@ -233,10 +225,8 @@ class DataTypePanel extends JPanel {
boolean showComponentOffset = false;
DataTypeComponent[] components = comp.getDefinedComponents();
DataTypeComponent flexDtc = null;
if (comp instanceof Structure) {
showComponentOffset = !comp.isPackingEnabled();
flexDtc = ((Structure) comp).getFlexibleArrayComponent();
}
int offsetLength = showComponentOffset ? Integer.toHexString(comp.getLength()).length() : 0;
@ -246,17 +236,10 @@ class DataTypePanel extends JPanel {
maxDtNameLength = max(getDataTypeName(component), maxDtNameLength);
maxFieldNameLength = max(component.getFieldName(), maxFieldNameLength);
}
if (flexDtc != null) {
maxDtNameLength = max(getDataTypeName(flexDtc), maxDtNameLength);
maxFieldNameLength = max(flexDtc.getFieldName(), maxFieldNameLength);
}
for (DataTypeComponent component : components) {
renderComponent(component, maxDtNameLength, maxFieldNameLength, offsetLength);
}
if (flexDtc != null) {
renderComponent(flexDtc, maxDtNameLength, maxFieldNameLength, offsetLength);
}
insertString("}\n\n", contentAttrSet);
insertAlignment(comp);

View file

@ -47,7 +47,7 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
public void actionPerformed(ActionContext context) {
CompEditorModel editorModel = (CompEditorModel) model;
if (editorModel.getNumSelectedRows() != 1 || editorModel.isFlexibleArraySelection()) {
if (editorModel.getNumSelectedRows() != 1) {
return;
}
int rowIndex = model.getSelectedRows()[0];
@ -71,7 +71,7 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
CompEditorModel editorModel = (CompEditorModel) model;
// Union do not support non-packed placement of bitfields
if (!(editorModel.viewComposite instanceof Structure) || editorModel.isPackingEnabled() ||
editorModel.getNumSelectedRows() != 1 || editorModel.isFlexibleArraySelection()) {
editorModel.getNumSelectedRows() != 1) {
enabled = false;
}
setEnabled(enabled);

View file

@ -370,7 +370,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
void init(DataTypeComponent editDtc) {
if (editDtc == null || editDtc.isFlexibleArrayComponent()) {
if (editDtc == null) {
editMode = EditMode.NONE;
editOrdinal = -1;
this.editComponent = null;
@ -401,6 +401,12 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
return false;
}
return bitFieldAllocation.hasConflict;
// TODO: Improve conflict detection with zero-length components.
// Zero-length components can share common offset, although
// zero-length components should have a lower ordinal than a
// sized component at the same offset.
}
/**
@ -603,7 +609,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
String conflictTip = "'" + conflict.getDataType().getDisplayName() +
(conflictName != null ? (" " + conflictName) : "") + "' at offset " +
conflict.getOffset();
conflictMsg += "<div style=\"color: red;font-style: italic\">conflict with " +
conflictMsg += "<div style=\"color: red;font-style: italic\">overlaps " +
HTMLUtilities.escapeHTML(conflictTip) + "</div>";
}
return "<HTML><div style=\"text-align:center\">" + HTMLUtilities.escapeHTML(tip) +
@ -842,12 +848,22 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
BitFieldPlacement(DataTypeComponent component) {
int startOffset = component.getOffset();
int componentLength = component.getLength();
int offsetAdjBytes = startOffset - allocationByteOffset;
if (!bigEndian) {
offsetAdjBytes = allocationByteSize - offsetAdjBytes - component.getLength();
offsetAdjBytes = allocationByteSize - offsetAdjBytes - componentLength;
}
int leftAdj = 8 * offsetAdjBytes;
if (component.isBitFieldComponent()) {
if (componentLength == 0) {
// treat all zero-length fields the same
zeroBitField = true;
rightBit = leftAdj - 8;
if (!isBigEndian()) {
rightBit += 7;
}
leftBit = rightBit;
}
else if (component.isBitFieldComponent()) {
BitFieldDataType bitfield = (BitFieldDataType) component.getDataType();
int storageSize = 8 * bitfield.getStorageSize();
rightBit = leftAdj + storageSize - bitfield.getBitOffset() - 1;
@ -855,14 +871,8 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
// 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;
@ -1075,7 +1085,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
int allocationEndOffset = offset + allocationBytes - 1;
int numComponents = struct.getNumComponents();
DataTypeComponent component = struct.getComponentAt(offset);
DataTypeComponent component = struct.getDefinedComponentAtOrAfterOffset(offset);
while (component != null) {
if (component.getOffset() > allocationEndOffset) {
break;
@ -1149,7 +1159,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
// determine placement attribute index within allocationBytes which
// may have been reduced from allocationByteSize based upon visibility.
int index = bitIndex - (8 * rightChopBytes);
int index = bitIndex - (8 * leftChopBytes);
if (index >= 0 && index < bitAttributes.length) {
bitAttributes[index] = new BitAttributes(dtc, bitAttributes[index]);
}
@ -1245,11 +1255,11 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
private DataTypeComponent getConflict() {
BitAttributes c = conflict;
while (c != null && c.dtc.isZeroBitFieldComponent()) {
while (c != null && c.dtc.getLength() == 0 && c.conflict != null) {
// TODO: improve conflict detection
// Zero-length bitfield could be conflict if placement is
// Zero-length components could be conflict if placement is
// offcut with another component (currently ignored)
c = conflict.conflict;
c = c.conflict;
}
// NOTE: DEFAULT undefined datatype can be ignored as conflict
return c != null && c.dtc.getDataType() != DataType.DEFAULT ? c.dtc : null;
@ -1301,7 +1311,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
}
else {
g.fillRect(rectangle.x, rectangle.y, bitWidth, CELL_HEIGHT);
if (conflict != null && conflict.dtc.isZeroBitFieldComponent()) {
if (conflict != null && conflict.dtc.getLength() == 0) {
conflict.paint(g, null, false);
}
}

View file

@ -536,7 +536,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
if (isEditingField()) {
endFieldEditing();
}
checkIsAllowableDataType(datatype, true);
checkIsAllowableDataType(datatype);
if (length < 1) {
DataTypeInstance dti = DataTypeHelper.getSizedDataType(getProvider(), datatype,
lastNumBytes, Integer.MAX_VALUE);
@ -575,7 +575,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
endFieldEditing();
}
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
insertMultiple(rowIndex, dataType, dtLen, multiple, monitor);
fixSelection();
componentEdited();
@ -741,14 +741,8 @@ public abstract class CompEditorModel extends CompositeEditorModel {
return null;
}
checkIsAllowableDataType(datatype, !oldDtc.isFlexibleArrayComponent());
checkIsAllowableDataType(datatype);
DataTypeComponent dtc;
if (oldDtc.isFlexibleArrayComponent()) {
// flexible array only supports fixed-length types
dtc = replace(rowIndex, datatype);
}
else {
int oldCompSize = oldDtc.getLength();
int newCompSize = length;
int sizeDiff = newCompSize - oldCompSize;
@ -761,9 +755,9 @@ public abstract class CompEditorModel extends CompositeEditorModel {
}
// Replace the component at index.
dtc = replace(rowIndex, datatype, newCompSize, oldDtc.getFieldName(),
oldDtc.getComment());
}
DataTypeComponent dtc =
replace(rowIndex, datatype, newCompSize, oldDtc.getFieldName(), oldDtc.getComment());
fixSelection();
componentEdited();
selectionChanged();
@ -793,11 +787,11 @@ public abstract class CompEditorModel extends CompositeEditorModel {
}
DataTypeComponent oldDtc = getComponent(startRowIndex);
if (oldDtc == null || oldDtc.isFlexibleArrayComponent()) {
if (oldDtc == null) {
throw new AssertException();
}
checkIsAllowableDataType(datatype, true);
checkIsAllowableDataType(datatype);
//
// Note: if the range being replaced is large enough, then the UI could lock-up. If we
@ -839,7 +833,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
if (dtc == null) {
return false;
}
if (!isShowingUndefinedBytes() || dtc.isFlexibleArrayComponent()) {
if (!isShowingUndefinedBytes()) {
return true;
}
// Does the new data type fit by replacing the component at index.
@ -869,10 +863,10 @@ public abstract class CompEditorModel extends CompositeEditorModel {
protected abstract void replaceOriginalComponents();
@Override
protected void checkIsAllowableDataType(DataType datatype, boolean dynamicSizingAllowed)
protected void checkIsAllowableDataType(DataType datatype)
throws InvalidDataTypeException {
super.checkIsAllowableDataType(datatype, dynamicSizingAllowed);
super.checkIsAllowableDataType(datatype);
// Verify that we aren't adding this structure or anything that it is
// part of to this editable structure.
@ -1021,12 +1015,6 @@ public abstract class CompEditorModel extends CompositeEditorModel {
// Get data type to make into array.
DataType dt = comp.getDataType();
if (numElements == 0) {
// assume if 0 was permitted flexible array support has been provided
convertToFlexibleArray(rowIndex);
return;
}
ArrayDataType array = new ArrayDataType(dt, numElements, comp.getLength(), viewDTM);
if (getNumSelectedComponentRows() > 1) {
@ -1244,17 +1232,17 @@ public abstract class CompEditorModel extends CompositeEditorModel {
}
@Override
public void setComponentDataTypeInstance(int rowIndex, DataTypeInstance dti)
public void setComponentDataTypeInstance(int rowIndex, DataType dt, int length)
throws UsrException {
if (getComponent(rowIndex) == null) {
// Replacing data type in unlocked mode replaces only
// that data type and structure size may change.
insert(rowIndex, dti.getDataType(), dti.getLength());
insert(rowIndex, dt, length);
}
else {
// Replacing data type in unlocked mode replaces only
// that data type and structure size may change.
replace(rowIndex, dti.getDataType(), dti.getLength());
replace(rowIndex, dt, length);
}
}
@ -1268,14 +1256,11 @@ public abstract class CompEditorModel extends CompositeEditorModel {
@Override
public void setComponentName(int rowIndex, String name)
throws InvalidInputException, InvalidNameException, DuplicateNameException {
if (name.equals("")) {
name = null;
}
if (nameExistsElsewhere(name, rowIndex)) {
throw new InvalidNameException("Name \"" + name + "\" already exists.");
}
try {
getComponent(rowIndex).setFieldName(name);
getComponent(rowIndex).setFieldName(name); // setFieldName handles trimming
}
catch (DuplicateNameException exc) {
throw new InvalidNameException(exc.getMessage());
@ -1552,9 +1537,6 @@ public abstract class CompEditorModel extends CompositeEditorModel {
if (!isContiguousSelection()) {
return 0;
}
if (isFlexibleArraySelection()) {
return Integer.MAX_VALUE;
}
int rowIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
if (rowIndex < getNumComponents()) {

View file

@ -177,7 +177,13 @@ public class CompEditorPanel extends CompositeEditorPanel {
validate();
}
if (dtc != null && dtc.getOffset() >= length) {
// likely trailing zero-length component - not in range for bitViewComponent
bitViewComponent.init(null);
}
else {
bitViewComponent.init(dtc);
}
}
});
@ -821,7 +827,7 @@ public class CompEditorPanel extends CompositeEditorPanel {
sizeTextField.setEditable(editable);
if (editable) {
// editable - use same background as category field
sizeTextField.setBackground(categoryStatusTextField.getBackground());
sizeTextField.setBackground(descriptionTextField.getBackground());
}
else {
// not editable - use same background as panel

View file

@ -177,17 +177,14 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
rowIndex = range.getStart().getIndex().intValue();
}
boolean dynamicSizingAllowed = true;
DataType currentDt = null;
DataTypeComponent dtc = getComponent(rowIndex);
if (dtc != null) {
dynamicSizingAllowed = !dtc.isFlexibleArrayComponent();
currentDt = dtc.getDataType();
}
if (!(currentDt instanceof Pointer)) {
// stacking on pointer allows any data type
checkIsAllowableDataType(dt, dynamicSizingAllowed);
checkIsAllowableDataType(dt);
}
DataType resultDt = DataUtilities.reconcileAppliedDataType(currentDt, dt, true);
@ -358,7 +355,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
dtName = previousDt.getDisplayName();
}
DataType newDt = null;
int newLength = 0;
int newLength = -1;
if (dataTypeObject instanceof DataTypeInstance) {
DataTypeInstance dti = (DataTypeInstance) dataTypeObject;
newDt = dti.getDataType();
@ -382,9 +379,14 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
return; // Was nothing and is nothing.
}
checkIsAllowableDataType(newDt, element == null || !element.isFlexibleArrayComponent());
if (DataTypeComponent.usesZeroLengthComponent(newDt)) {
newLength = 0;
}
checkIsAllowableDataType(newDt);
newDt = resolveDataType(newDt, viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
if (newLength < 0) {
// prefer previous size first
int suggestedLength = (previousLength <= 0) ? lastNumBytes : previousLength;
@ -393,22 +395,22 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
if (sizedDataType == null) {
return;
}
newDt = resolveDataType(sizedDataType.getDataType(), viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
newLength = sizedDataType.getLength();
if (newLength <= 0) {
throw new UsrException("Can't currently add this data type.");
}
}
if ((previousDt != null) && newDt.isEquivalent(previousDt) && newLength == previousLength) {
return;
}
int maxLength = getMaxReplaceLength(rowIndex);
if (newLength <= 0) {
throw new UsrException("Can't currently add this data type.");
}
if (maxLength > 0 && newLength > maxLength) {
throw new UsrException(newDt.getDisplayName() + " doesn't fit within " + maxLength +
" bytes, need " + newLength + " bytes");
}
setComponentDataTypeInstance(rowIndex,
DataTypeInstance.getDataTypeInstance(newDt, newLength));
setComponentDataTypeInstance(rowIndex, newDt, newLength);
notifyCompositeChanged();
}
@ -458,10 +460,6 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
int max = getMaxElements();
if (isSingleRowSelection()) {
if (max != 0) {
int currentIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
if (canConvertToFlexibleArray(currentIndex)) {
min = 0; // allow flexible array
}
int initial = getLastNumElements();
NumberInputDialog numberInputDialog =
new NumberInputDialog("elements", ((initial > 0) ? initial : 1), min, max);
@ -492,20 +490,6 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
}
}
/**
* Determine if the existing composite component identified by its rowIndex can
* be converted to a flexible array (i.e., unsized array).
* @param rowIndex existing component index
* @return true if conversion to flexible array permitted.
*/
protected boolean canConvertToFlexibleArray(int rowIndex) {
return false;
}
protected void convertToFlexibleArray(int rowIndex) throws UsrException {
throw new UsrException("Flexible array not permitted");
}
protected void createArray(int numElements)
throws InvalidDataTypeException, DataTypeConflictException, UsrException {
if (selection.getNumRanges() != 1) {
@ -777,6 +761,10 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
*/
protected boolean nameExistsElsewhere(String name, int rowIndex) {
if (name != null) {
name = name.trim();
if (name.length() == 0) {
return false;
}
int numComponents = getNumComponents();
for (int i = 0; i < rowIndex && i < numComponents; i++) {
if (name.equals(getComponent(i).getFieldName())) {
@ -797,12 +785,18 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
* If invalid, an exception will be thrown.
*
* @param datatype the data type
* @param dynamicSizingAllowed true signals to allow dynamic types
* @throws InvalidDataTypeException if the structure being edited is part
* of the data type being inserted or doesn't have a valid size.
*/
protected void checkIsAllowableDataType(DataType datatype, boolean dynamicSizingAllowed)
protected void checkIsAllowableDataType(DataType datatype)
throws InvalidDataTypeException {
if (!allowsZeroLengthComponents() && DataTypeComponent.usesZeroLengthComponent(datatype)) {
throw new InvalidDataTypeException(
"Zero-length datatype not permitted: " + datatype.getName());
}
if (!allowsBitFields() && (datatype instanceof BitFieldDataType)) {
throw new InvalidDataTypeException("Bitfield not permitted: " + datatype.getName());
}
if (datatype instanceof TypeDef) {
datatype = ((TypeDef) datatype).getBaseDataType();
}
@ -811,17 +805,21 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
"Factory data types are not " + "allowed in a composite data type.");
}
else if (datatype instanceof Dynamic) {
if (!dynamicSizingAllowed) {
throw new InvalidDataTypeException(
"Dynamic data type is not permitted in current context");
}
else if (!((Dynamic) datatype).canSpecifyLength()) {
if (!((Dynamic) datatype).canSpecifyLength()) {
throw new InvalidDataTypeException("Non-sizable Dynamic data types are not " +
"allowed in a composite data type.");
}
}
}
protected boolean allowsZeroLengthComponents() {
return true;
}
protected boolean allowsBitFields() {
return true;
}
@Override
public boolean isAddAllowed(int currentIndex, DataType datatype) {
return false;
@ -1114,7 +1112,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
throw new AssertException("Can't set data type to null.");
}
checkIsAllowableDataType(newDt, element == null || !element.isFlexibleArrayComponent());
checkIsAllowableDataType(newDt);
newLength = newDt.getLength();
if (newLength < 0) {

View file

@ -32,7 +32,7 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
* @param composite the composite data type that is being edited. (cannot be null).
*/
public CompositeViewerDataTypeManager(String rootName, Composite composite) {
super(rootName);
super(rootName, composite.getDataTypeManager().getDataOrganization());
transactionID = startTransaction("");
originalDTM = composite.getDataTypeManager();
universalID = originalDTM.getUniversalID(); // mimic original DTM
@ -50,10 +50,4 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
return originalDTM.getType();
}
@Override
public DataOrganization getDataOrganization() {
// get the alignment from the original data type manager.
return originalDTM.getDataOrganization();
}
}

View file

@ -516,10 +516,7 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
* Returns the number of component rows in the viewer. There may be a
* blank row at the end for selecting. Therefore this number can be
* different than the actual number of components currently in the
* structure being viewed. In addition, if a flexible array component
* exists which is not included in {@link #getNumComponents()} it
* will be included in this count and would appear after the blank row
* (e.g., getComponent(getNumComponents()+1) ).
* structure being viewed.
*
* @return the number of rows in the model
*/
@ -530,23 +527,17 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
/**
* Returns the number of components in this structure or union.
* NOTE: This number does not include the flexible array component which may exist
* within a structure.
* @return the number of components in the model
*/
public int getNumComponents() {
if (viewComposite == null) {
return 0;
}
return viewComposite.getNumComponents();
return (viewComposite != null) ? viewComposite.getNumComponents() : 0;
}
/**
* Return the nth component for the structure being viewed. Since the number of rows
* can exceed the number of components defined within the composite
* ({@link Composite#getNumComponents()}) this method will return null for a blank
* row or a flexible array component which may appear as an additional rows for
* structures.
* row.
* @param rowIndex the index of the component to return. First component is index of 0.
* @return the component
*/
@ -588,37 +579,34 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
return "";
}
String value;
DataType dt;
int dtLen;
DataTypeComponent dtc = viewComposite.getComponent(rowIndex);
if (columnIndex == getOffsetColumn()) {
int offset = viewComposite.getComponent(rowIndex).getOffset();
int offset = dtc.getOffset();
value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset);
}
else if (columnIndex == getLengthColumn()) {
int length = viewComposite.getComponent(rowIndex).getLength();
value = showHexNumbers ? getHexString(length, true) : Integer.toString(length);
int compLen = dtc.getLength();
value = showHexNumbers ? getHexString(compLen, true) : Integer.toString(compLen);
}
else if (columnIndex == getMnemonicColumn()) {
DataTypeComponent comp = viewComposite.getComponent(rowIndex);
dt = comp.getDataType();
DataType dt = dtc.getDataType();
value = dt.getMnemonic(new SettingsImpl());
int compLen = comp.getLength();
dtLen = comp.getDataType().getLength();
int compLen = dtc.getLength();
int dtLen = dt.isZeroLength() ? 0 : dt.getLength();
if (dtLen > compLen) {
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
}
}
else if (columnIndex == getDataTypeColumn()) {
DataTypeComponent dtc = viewComposite.getComponent(rowIndex);
dt = dtc.getDataType();
dtLen = dt.getLength();
DataType dt = dtc.getDataType();
int dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength());
}
else if (columnIndex == getNameColumn()) {
value = viewComposite.getComponent(rowIndex).getFieldName();
value = dtc.getFieldName();
}
else if (columnIndex == getCommentColumn()) {
value = viewComposite.getComponent(rowIndex).getComment();
value = dtc.getComment();
}
else {
value = "UNKNOWN";
@ -1173,20 +1161,6 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
return (selection.getNumRanges() == 1);
}
/**
* Returns true if the current single row selection corresponds to a flexible array component
* @return true if the current single row selection corresponds to a flexible array component
*/
public boolean isFlexibleArraySelection() {
if (!isSingleRowSelection()) {
return false;
}
FieldRange range = selection.getFieldRange(0);
int rowIndex = range.getStart().getIndex().intValue();
DataTypeComponent component = getComponent(rowIndex);
return component != null && component.isFlexibleArrayComponent();
}
/**
* Returns true if the component list selection is a single component
* @return true if the component list selection is a single component

View file

@ -102,9 +102,7 @@ public class DataTypeHelper {
if (newDt == null) {
throw new InvalidDataTypeException("valid data-type not specified");
}
DataTypeComponent element = editModel.getComponent(index);
editModel.checkIsAllowableDataType(newDt,
element == null || !element.isFlexibleArrayComponent());
editModel.checkIsAllowableDataType(newDt);
int mrl = editModel.getMaxReplaceLength(index);
if ((mrl != -1) && (newDt.getLength() > mrl)) {
throw new InvalidDataTypeException(newDt.getDisplayName() + " doesn't fit within " +

View file

@ -214,9 +214,11 @@ public interface EditorModel {
/**
* Sets the data type for the component at the indicated row index.
* @param rowIndex the row index of the component
* @param dataTypeInstance
* @param dt component datatype
* @param length component length
* @throws UsrException if invalid datatype or length specified
*/
public void setComponentDataTypeInstance(int rowIndex, DataTypeInstance dataTypeInstance)
public void setComponentDataTypeInstance(int rowIndex, DataType dt, int length)
throws UsrException;
/**

View file

@ -102,10 +102,6 @@ class StructureEditorModel extends CompEditorModel {
public int getRowCount() {
int componentCount = getNumComponents();
int rowCount = componentCount + 1; // add blank edit row
Structure viewStruct = (Structure) viewComposite;
if (viewStruct != null && viewStruct.hasFlexibleArrayComponent()) {
++rowCount;
}
return rowCount;
}
@ -129,7 +125,6 @@ class StructureEditorModel extends CompEditorModel {
}
DataTypeComponent dtc = getComponent(rowIndex);
if (dtc == null) {
if (columnIndex == getDataTypeColumn()) {
return null;
@ -137,42 +132,34 @@ class StructureEditorModel extends CompEditorModel {
return "";
}
boolean isFlexArrayComponent = dtc.isFlexibleArrayComponent();
String value = null;
DataType dt;
int dtLen;
if (columnIndex == getOffsetColumn()) {
int offset = dtc.getOffset();
value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset);
}
else if (columnIndex == getLengthColumn()) {
int length = dtc.getLength();
value = showHexNumbers ? getHexString(length, true) : Integer.toString(length);
int compLen = dtc.getLength();
value = showHexNumbers ? getHexString(compLen, true) : Integer.toString(compLen);
}
else if (columnIndex == getMnemonicColumn()) {
dt = dtc.getDataType();
DataType dt = dtc.getDataType();
value = dt.getMnemonic(new SettingsImpl());
if (isFlexArrayComponent) {
value += "[0]";
}
else {
int compLen = dtc.getLength();
dtLen = dtc.getDataType().getLength();
int dtLen = dt.isZeroLength() ? 0 : dt.getLength();
if (dtLen > compLen) {
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
}
}
}
else if (columnIndex == getDataTypeColumn()) {
dt = dtc.getDataType();
dtLen = dt.getLength();
DataType dt = dtc.getDataType();
int dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength());
}
else if (columnIndex == getNameColumn()) {
value = getComponent(rowIndex).getFieldName();
value = dtc.getFieldName();
}
else if (columnIndex == getCommentColumn()) {
value = getComponent(rowIndex).getComment();
value = dtc.getComment();
}
return (value == null) ? "" : value;
@ -185,9 +172,6 @@ class StructureEditorModel extends CompEditorModel {
return null;
}
Structure viewStruct = (Structure) viewComposite;
if (rowIndex == (numComponents + 1)) {
return viewStruct.getFlexibleArrayComponent();
}
if (rowIndex > numComponents) {
return null;
}
@ -203,73 +187,48 @@ class StructureEditorModel extends CompEditorModel {
return viewComposite == null ? 0 : viewComposite.getNumComponents();
}
@Override
protected boolean canConvertToFlexibleArray(int rowIndex) {
if (!(viewComposite instanceof Structure)) {
return false;
}
if (((Structure) viewComposite).hasFlexibleArrayComponent()) {
return false;
}
if (rowIndex != (getNumComponents() - 1)) {
return false;
}
DataTypeComponent dtc = getComponent(rowIndex);
DataType dt = dtc.getDataType();
if (dt instanceof TypeDef) {
dt = ((TypeDef) dt).getBaseDataType();
}
if (dt instanceof Dynamic || dt instanceof FactoryDataType) {
return false;
}
return true;
}
@Override
protected void convertToFlexibleArray(int rowIndex) throws UsrException {
if (!canConvertToFlexibleArray(rowIndex)) {
// should be avoided by constraining minimum array size and data type
throw new UsrException("Flexible array not permitted");
}
DataTypeComponent dtc = getComponent(rowIndex);
Structure struct = (Structure) viewComposite;
struct.setFlexibleArrayComponent(dtc.getDataType(), dtc.getFieldName(), dtc.getComment());
delete(rowIndex);
selection.addRange(rowIndex + 1, rowIndex + 2); // select flex component
selectionChanged();
}
@Override
protected boolean isSizeEditable() {
return !isPackingEnabled();
}
void setStructureSize(int size) {
if (viewComposite == null) {
if (viewComposite == null || viewComposite.isPackingEnabled()) {
return;
}
int currentLength = viewComposite.isZeroLength() ? 0 : viewComposite.getLength();
int currentLength = (viewComposite.isZeroLength()) ? 0 : viewComposite.getLength();
if (currentLength == size) {
return;
}
Structure structure = (Structure) viewComposite;
if (currentLength > size) {
int numComponents = structure.getNumComponents();
DataTypeComponent dtc = structure.getComponentContaining(size);
int ordinal = dtc.getOrdinal();
// retain any zero-length components which have an offset equal the new size
while (dtc.getOffset() == size && dtc.getLength() == 0 &&
(ordinal + 1) < numComponents) {
dtc = structure.getComponent(++ordinal);
}
// remove trailing components outside of new size
for (int index = numComponents - 1; index >= ordinal; index--) {
structure.delete(index);
int bitFieldResidualBytes = structure.getNumComponents() - index;
for (int i = 0; i < bitFieldResidualBytes; i++) {
// bitfield removal may cause injection of undefined bytes - remove them
structure.delete(index);
}
}
// structure may shrink too much from component removal - may need to grow
currentLength = (viewComposite.isZeroLength()) ? 0 : viewComposite.getLength();
}
if (currentLength < size) {
// Increasing structure length.
structure.growStructure(size - currentLength);
}
else {
DataTypeComponent dtc = structure.getComponentAt(size);
int ordinal = dtc.getOrdinal();
if (dtc.getOffset() != size) {
structure.clearComponent(ordinal);
dtc = structure.getComponentAt(size);
ordinal = dtc.getOrdinal();
}
int numComponents = structure.getNumComponents();
for (int index = numComponents - 1; index >= ordinal; index--) {
structure.delete(index);
}
}
updateAndCheckChangeState();
fireTableDataChanged();
}
@ -292,9 +251,6 @@ class StructureEditorModel extends CompEditorModel {
if (dtc == null) {
return false;
}
if (dtc.isFlexibleArrayComponent()) {
return true;
}
DataType dt = dtc.getDataType();
if (dt == DataType.DEFAULT) {
return false;
@ -398,12 +354,12 @@ class StructureEditorModel extends CompEditorModel {
}
DataTypeComponent originalComp = getComponent(index);
if (originalComp == null || originalComp.isFlexibleArrayComponent()) {
if (originalComp == null) {
throw new IllegalArgumentException("Invalid component index specified");
}
DataType dt = originalComp.getDataType();
int dtLen = dt.getLength();
checkIsAllowableDataType(dt, true);
checkIsAllowableDataType(dt);
int startIndex = index + 1;
if (isShowingUndefinedBytes() && (dt != DataType.DEFAULT)) {
@ -570,7 +526,7 @@ class StructureEditorModel extends CompEditorModel {
@Override
public boolean isBitFieldAllowed() {
return isSingleRowSelection() && !isFlexibleArraySelection();
return isSingleRowSelection();
}
/**
@ -587,7 +543,7 @@ class StructureEditorModel extends CompEditorModel {
FieldRange range = selection.getFieldRange(0);
DataTypeComponent comp = getComponent(range.getStart().getIndex().intValue());
if (comp == null || comp.isFlexibleArrayComponent() || comp.isBitFieldComponent()) {
if (comp == null || comp.isBitFieldComponent()) {
return false;
}
@ -615,29 +571,6 @@ class StructureEditorModel extends CompEditorModel {
return getComponent(rowIndex) != null;
}
@Override
public void deleteSelectedComponents() throws UsrException {
if (!isDeleteAllowed()) {
throw new UsrException("Deleting is not allowed.");
}
if (isEditingField()) {
endFieldEditing();
}
int rowIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
DataTypeComponent dtc = getComponent(rowIndex);
if (dtc.isFlexibleArrayComponent()) {
// Remove flexible array component
((Structure) viewComposite).clearFlexibleArrayComponent();
componentEdited();
selection.addRange(rowIndex - 1, rowIndex);
fixSelection();
selectionChanged();
return;
}
super.deleteSelectedComponents();
}
@Override
public boolean isDuplicateAllowed() {
@ -813,7 +746,7 @@ class StructureEditorModel extends CompEditorModel {
}
try {
checkIsAllowableDataType(dataType, !dtc.isFlexibleArrayComponent());
checkIsAllowableDataType(dataType);
}
catch (InvalidDataTypeException e) {
return false;
@ -898,9 +831,7 @@ class StructureEditorModel extends CompEditorModel {
else if (comp == null) {
return 0; // No such component. Not at valid edit index.
}
else if (comp.isFlexibleArrayComponent()) {
return Integer.MAX_VALUE;
}
// Otherwise, get size of component and number of Undefined bytes after it.
FieldRange range = getSelectedRangeContaining(currentIndex);
if (range == null ||
@ -936,18 +867,11 @@ class StructureEditorModel extends CompEditorModel {
@Override
protected DataTypeComponent insert(int rowIndex, DataType dataType, int length, String name,
String comment) throws InvalidDataTypeException {
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
try {
DataTypeComponent dtc = getComponent(rowIndex);
if (dtc != null && dtc.isFlexibleArrayComponent()) {
Structure struct = (Structure) viewComposite;
dtc = struct.setFlexibleArrayComponent(dataType, dtc.getFieldName(),
dtc.getComment());
}
else {
DataTypeComponent dtc;
if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) {
dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name,
comment);
dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name, comment);
}
else {
BitFieldDataType bitfield = (BitFieldDataType) dataType;
@ -958,7 +882,6 @@ class StructureEditorModel extends CompEditorModel {
if (rowIndex <= row) {
row++;
}
}
adjustSelection(rowIndex, 1);
// Consume undefined bytes that may have been added, if needed.
consumeByComponent(rowIndex - 1);
@ -973,7 +896,7 @@ class StructureEditorModel extends CompEditorModel {
protected void insert(int rowIndex, DataType dataType, int length, int numCopies,
TaskMonitor monitor) throws InvalidDataTypeException, CancelledException {
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
int componentOrdinal = convertRowToOrdinal(rowIndex);
monitor.initialize(numCopies);
try {
@ -997,21 +920,10 @@ class StructureEditorModel extends CompEditorModel {
}
}
@Override
public DataTypeComponent replace(int rowIndex, DataType dt) throws UsrException {
DataTypeComponent dtc = getComponent(rowIndex);
if (dtc == null || !dtc.isFlexibleArrayComponent()) {
return super.replace(rowIndex, dt);
}
Structure struct = (Structure) viewComposite;
return struct.setFlexibleArrayComponent(dt, dtc.getFieldName(), dtc.getComment());
}
@Override
protected DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name,
String comment) throws InvalidDataTypeException {
// It is assumed that the replaced component is not a flexible array
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
try {
DataTypeComponent dtc = null;
boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex));

View file

@ -294,7 +294,7 @@ class UnionEditorModel extends CompEditorModel {
if (currentIndex < 0 || currentIndex > getNumComponents()) {
return false;
}
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
}
catch (InvalidDataTypeException e) {
return false;
@ -378,7 +378,7 @@ class UnionEditorModel extends CompEditorModel {
@Override
public DataTypeComponent insert(int rowIndex, DataType dataType, int length, String name,
String comment) throws InvalidDataTypeException {
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
try {
DataTypeComponent dtc =
((Union) viewComposite).insert(rowIndex, dataType, length, name, comment);
@ -409,7 +409,7 @@ class UnionEditorModel extends CompEditorModel {
@Override
public DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name,
String comment) throws InvalidDataTypeException {
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
try {
boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex));
((Union) viewComposite).delete(rowIndex);

View file

@ -63,6 +63,8 @@ import util.CollectionUtils;
//@formatter:on
public class DataTypePreviewPlugin extends ProgramPlugin {
private static final String ROOT_NAME = "DataTypePreviewer";
private DTPPComponentProvider provider;
private DTPPTableModel model;
private DTPPTable table;
@ -71,7 +73,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
private GoToService goToService;
private DockingAction addAction;
private DockingAction deleteAction;
private LayeredDataTypeManager dataTypeManager;
private DataTypeManager dataTypeManager;
private Program activeProgram;
private SwingUpdateManager updateManager = new SwingUpdateManager(650, () -> updatePreview());
@ -101,7 +103,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
model = new DTPPTableModel();
table = new DTPPTable(model);
component = new DTPPScrollPane(table);
dataTypeManager = new LayeredDataTypeManager(activeProgram);
dataTypeManager = createLayeredDataTypeManager();
addDataType(new ByteDataType());
addDataType(new WordDataType());
@ -177,7 +179,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
private void updateModel() {
LayeredDataTypeManager newDtm = new LayeredDataTypeManager(activeProgram);
DataTypeManager newDtm = createLayeredDataTypeManager();
int transactionId = newDtm.startTransaction("add datatypes");
try {
@ -197,7 +199,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
List<DataTypePath> dtPaths = getModelDataTypePaths();
model.removeAll();
LayeredDataTypeManager oldDtm = dataTypeManager;
DataTypeManager oldDtm = dataTypeManager;
dataTypeManager = newDtm;
oldDtm.close();
@ -711,24 +713,11 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
}
}
private class LayeredDataTypeManager extends StandAloneDataTypeManager {
DataOrganization layeredDataOrganization1;
public LayeredDataTypeManager(Program program) {
super("DataTypePreviewer");
this.layeredDataOrganization1 =
program != null ? program.getDataTypeManager().getDataOrganization() : null;
}
@Override
public DataOrganization getDataOrganization() {
if (layeredDataOrganization1 == null) {
return super.getDataOrganization();
}
return layeredDataOrganization1;
}
private DataTypeManager createLayeredDataTypeManager() {
DataOrganization dataOrg =
(activeProgram != null) ? activeProgram.getCompilerSpec().getDataOrganization()
: DataOrganizationImpl.getDefaultOrganization();
return new StandAloneDataTypeManager(ROOT_NAME, dataOrg);
}
}

View file

@ -1,62 +0,0 @@
/* ###
* 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.function.editor;
import ghidra.program.model.data.*;
class DataTypeManagerStub extends StandAloneDataTypeManager {
protected DataTypeManagerStub(String name) {
super(name);
populate();
}
/**
* Add the built in data types to the default built in folder if they
* were not found in any other category.
*/
protected void populate() {
int id = super.startTransaction("Populate");
try {
resolve(new ByteDataType(), null);
resolve(new CharDataType(), null);
resolve(new BooleanDataType(), null);
resolve(new DoubleDataType(), null);
resolve(new StringDataType(), null);
resolve(new Undefined1DataType(), null);
resolve(new Undefined2DataType(), null);
resolve(new Undefined4DataType(), null);
resolve(new Undefined8DataType(), null);
resolve(new UnicodeDataType(), null);
resolve(new VoidDataType(), null);
resolve(new IntegerDataType(), null);
resolve(new ShortDataType(), null);
StructureDataType struct1 = new StructureDataType("abc", 4);
struct1.setCategoryPath(new CategoryPath("/foo"));
resolve(struct1, null);
StructureDataType struct2 = new StructureDataType("abc", 4);
struct2.setCategoryPath(new CategoryPath("/bar"));
resolve(struct2, null);
}
finally {
super.endTransaction(id, true);
}
}
}

View file

@ -55,6 +55,18 @@ public abstract class BiDirectionDataType extends StructureDataType
this.splitOffset = splitOffset;
}
@Override
protected DataType validateDataType(DataType dataType) {
if (DataTypeComponent.usesZeroLengthComponent(dataType)) {
throw new IllegalArgumentException(
"Zero-length datatype not permitted: " + dataType.getName());
}
if (dataType instanceof BitFieldDataType) {
throw new IllegalArgumentException("Bitfield not permitted: " + dataType.getName());
}
return super.validateDataType(dataType);
}
@Override
public int getAlignment() {
throw new UnsupportedOperationException(
@ -91,18 +103,11 @@ public abstract class BiDirectionDataType extends StructureDataType
// ignore
}
@Override
public DataTypeComponent setFlexibleArrayComponent(DataType flexType, String name,
String comment) {
throw new UnsupportedOperationException(
"BiDirectionDataType.setFlexibleArrayComponent() not implemented.");
}
protected DataTypeComponent getDefinedComponentAt(int offset) {
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
return null;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) {
return components.get(index);
}
@ -114,7 +119,7 @@ public abstract class BiDirectionDataType extends StructureDataType
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
return null;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) {
return components.get(index);
}
@ -240,7 +245,7 @@ public abstract class BiDirectionDataType extends StructureDataType
if (ordinal < 0 || ordinal >= numComponents) {
throw new IndexOutOfBoundsException(ordinal);
}
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (idx >= 0) {
return components.get(idx);
}
@ -248,11 +253,11 @@ public abstract class BiDirectionDataType extends StructureDataType
}
@Override
public DataTypeComponent getComponent(int ordinal) {
public DataTypeComponentImpl getComponent(int ordinal) {
if (ordinal < 0 || ordinal >= numComponents) {
throw new IndexOutOfBoundsException(ordinal);
}
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (idx >= 0) {
return components.get(idx);
}
@ -307,7 +312,7 @@ public abstract class BiDirectionDataType extends StructureDataType
checkAncestry(dataType);
dataType = dataType.clone(getDataTypeManager());
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int additionalShift = 0;
if (index >= 0) {
@ -443,7 +448,7 @@ public abstract class BiDirectionDataType extends StructureDataType
" within a defined component in " + getDisplayName() + ".");
}
else {
definedIndex = Collections.binarySearch(components, new Integer(dtc.getOrdinal()),
definedIndex = Collections.binarySearch(components, Integer.valueOf(dtc.getOrdinal()),
ordinalComparator);
if (definedIndex < 0) {
definedIndex = -definedIndex - 1;
@ -470,7 +475,7 @@ public abstract class BiDirectionDataType extends StructureDataType
throw new IllegalArgumentException(
"Offset " + offset + " is not in " + getDisplayName() + ".");
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int length = 1;
if (index < 0) {
@ -485,6 +490,25 @@ public abstract class BiDirectionDataType extends StructureDataType
numComponents--;
}
@Override
public void clearAtOffset(int offset) {
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
throw new IllegalArgumentException(
"Offset " + offset + " is not in " + getDisplayName() + ".");
}
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) {
DataTypeComponent dtc = components.remove(index);
dtc.getDataType().removeParent(this);
int len = dtc.getLength();
if (len > 1) {
int deltaLength = len - 1;
shiftOffsets(index, deltaLength, 0);
numComponents += deltaLength;
}
}
}
@Override
public boolean isEquivalent(DataType dataType) {
if (dataType == this) {
@ -531,19 +555,19 @@ public abstract class BiDirectionDataType extends StructureDataType
public abstract BiDirectionDataType clone(DataTypeManager dtm);
@Override
public void clearComponent(int index) {
if (index < 0 || index >= numComponents) {
throw new IndexOutOfBoundsException(index);
public void clearComponent(int ordinal) {
if (ordinal < 0 || ordinal >= numComponents) {
throw new IndexOutOfBoundsException(ordinal);
}
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator);
if (idx >= 0) {
DataTypeComponent dtc = components.remove(idx);
int index =
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (index >= 0) {
DataTypeComponent dtc = components.remove(index);
dtc.getDataType().removeParent(this);
int len = dtc.getLength();
int deltaLength = len - 1;
// int offset = dtc.getOffset();
if (len > 1) {
shiftOffsets(idx, deltaLength, 0);
int deltaLength = len - 1;
shiftOffsets(index, deltaLength, 0);
numComponents += deltaLength;
}
}
@ -644,7 +668,8 @@ public abstract class BiDirectionDataType extends StructureDataType
DataTypeComponentImpl newDtc =
new DataTypeComponentImpl(dataType, this, length, ordinal, newOffset, newName, comment);
dataType.addParent(this);
int index = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
int index =
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (index < 0) {
index = -index - 1;
}

View file

@ -79,6 +79,16 @@ class StackEditorModel extends CompositeEditorModel {
}
}
@Override
protected boolean allowsZeroLengthComponents() {
return false;
}
@Override
protected boolean allowsBitFields() {
return false;
}
void stackChangedExcternally(boolean changed) {
stackChangedExternally = changed;
}
@ -612,7 +622,7 @@ class StackEditorModel extends CompositeEditorModel {
if (currentIndex < 0 || currentIndex >= getRowCount()) {
return false;
}
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
}
catch (InvalidDataTypeException e) {
return false;
@ -720,7 +730,7 @@ class StackEditorModel extends CompositeEditorModel {
if (currentIndex < 0 || currentIndex >= getRowCount()) {
return false;
}
checkIsAllowableDataType(dataType, true);
checkIsAllowableDataType(dataType);
}
catch (InvalidDataTypeException e) {
return false;
@ -788,10 +798,9 @@ class StackEditorModel extends CompositeEditorModel {
}
@Override
public void setComponentDataTypeInstance(int index, DataTypeInstance dti) throws UsrException {
DataType dt = dti.getDataType();
checkIsAllowableDataType(dt, true);
((StackFrameDataType) viewComposite).setDataType(index, dt, dti.getLength());
public void setComponentDataTypeInstance(int index, DataType dt, int length) throws UsrException {
checkIsAllowableDataType(dt);
((StackFrameDataType) viewComposite).setDataType(index, dt, length);
}
@Override
@ -806,7 +815,7 @@ class StackEditorModel extends CompositeEditorModel {
public void setComponentName(int rowIndex, String newName)
throws InvalidInputException, InvalidNameException, DuplicateNameException {
if (newName.equals("")) {
if (newName.trim().length() == 0) {
newName = null;
}
// if (nameExistsElsewhere(newName, currentIndex)) {
@ -1330,7 +1339,7 @@ class StackEditorModel extends CompositeEditorModel {
int newLength = newDt.getLength();
checkIsAllowableDataType(newDt, true);
checkIsAllowableDataType(newDt);
newDt = DataTypeHelper.resolveDataType(newDt, viewDTM, null);
int maxLength = getMaxReplaceLength(index);
if (newLength <= 0) {

View file

@ -25,6 +25,7 @@ import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.InvalidNameException;
import ghidra.util.SystemUtilities;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.InvalidInputException;
@ -410,22 +411,22 @@ public class StackFrameDataType extends BiDirectionDataType {
*
* @param ordinal the ordinal
* @param name the new name. Null indicates the default name.
* @return true if name change was successful, else false
*/
public boolean setName(int ordinal, String name) {
validateName(ordinal, name);
DataTypeComponent comp = getComponent(ordinal);
String fieldName = comp.getFieldName();
if ((name != null) && ((name.length() == 0) || (isDefaultName(name)))) {
if (name != null) {
name = name.trim();
if (name.length() == 0 || isDefaultName(name)) {
name = null;
}
if (name == null) {
if (fieldName == null) {
return false;
}
}
else if (name.equals(fieldName)) {
}
if (SystemUtilities.isEqual(name, fieldName)) {
return false;
}
DataType dt = comp.getDataType();
int length = comp.getLength();
String comment = comp.getComment();

View file

@ -163,10 +163,16 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
// isEquiv().
// Ensure that two components in the partial struct don't map to the same
// component in the full structure.
for (DataTypeComponent partDTC : partComps) {
DataType partDT = partDTC.getDataType();
if (partDT.isZeroLength()) {
// don't try to match zero length fields, so skip
continue;
}
DataTypeComponent fullDTCAt = (partDTC.getDataType() instanceof BitFieldDataType)
? getBitfieldByOffsets(full, partDTC)
: full.getComponentAt(partDTC.getOffset());
: getBestMatchingDTC(full, partDTC);
if (fullDTCAt == null || fullDTCAt.getOffset() != partDTC.getOffset() ||
!SystemUtilities.isEqual(fullDTCAt.getFieldName(), partDTC.getFieldName())) {
return false;
@ -175,15 +181,20 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
return false;
}
}
if ( part.getFlexibleArrayComponent() != null ) {
return full.getFlexibleArrayComponent() != null &&
isMemberFieldPartiallyCompatible(full.getFlexibleArrayComponent(),
part.getFlexibleArrayComponent(), visitedDataTypes);
}
return true;
}
DataTypeComponent getBestMatchingDTC(Structure struct, DataTypeComponent matchCriteria) {
for (DataTypeComponent dtc : struct.getComponentsContaining(matchCriteria.getOffset())) {
DataType dt = dtc.getDataType();
if (dtc.getOffset() == matchCriteria.getOffset() && !dt.isZeroLength()) {
return dtc;
}
}
return null;
}
boolean isMemberFieldPartiallyCompatible(DataTypeComponent fullDTC, DataTypeComponent partDTC,
Set<Long> visitedDataTypes) {
DataType partDT = partDTC.getDataType();
@ -216,7 +227,7 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
private DataTypeComponent getBitfieldByOffsets(Structure full, DataTypeComponent partDTC) {
BitFieldDataType partBF = (BitFieldDataType) partDTC.getDataType();
DataTypeComponent fullDTC = full.getComponentAt(partDTC.getOffset());
DataTypeComponent fullDTC = full.getComponentContaining(partDTC.getOffset());
if (fullDTC == null) {
return null;
}

View file

@ -223,11 +223,6 @@ public class DWARFDataTypeImporter {
/**
* Returns true if the previously imported data type should be reused.
* <p>
* Don't re-use previously imported single-element
* Ghidra array datatypes because they may have actually been an empty array
* definition and we need the special meta-data flag DWARFDataType.isEmptyArrayType
* which is only available in a freshly created DWARFDataType.
* <p>
* Don't re-use empty structs (isNotYetDefined) to ensure that newer
* definitions of the same struct are given a chance to be resolved()
* into the DTM.
@ -236,10 +231,7 @@ public class DWARFDataTypeImporter {
* @return boolean true if its okay to reuse the data type
*/
private boolean shouldReuseAlreadyImportedDT(DataType alreadyImportedDT) {
return alreadyImportedDT != null &&
!alreadyImportedDT.isNotYetDefined() &&
!(alreadyImportedDT instanceof Array &&
((Array) alreadyImportedDT).getNumElements() == 1);
return alreadyImportedDT != null && !alreadyImportedDT.isNotYetDefined();
}
/*
@ -552,12 +544,19 @@ public class DWARFDataTypeImporter {
structSize = 0;
}
boolean isUnion = diea.getTag() == DWARFTag.DW_TAG_union_type;
boolean isDecl = diea.getBool(DWARFAttribute.DW_AT_declaration, false);
DataType struct =
isUnion ? new UnionDataType(dni.getParentCP(), dni.getName(), dataTypeManager)
: new StructureDataType(dni.getParentCP(), dni.getName(), (int) structSize,
dataTypeManager);
if (!isDecl && origStructSize == 0) {
// Enable packing on 0-byte composites so they are treated as defined
// and will not take space if used in a field in another composite.
((Composite) struct).setToDefaultPacking();
}
DWARFDataType result = new DWARFDataType(struct, dni, diea.getOffset());
result.dsi = DWARFSourceInfo.create(diea);
@ -719,6 +718,9 @@ public class DWARFDataTypeImporter {
}
if (union.getLength() < unionSize) {
// NOTE: this is likely due incorrect alignment for union or one or more of its components.
// Default alignment is 1 for non-packed unions and structures.
// if the Ghidra union data type is smaller than the DWARF union, pad it out
DataType padding = Undefined.getUndefinedDataType((int) unionSize);
try {
@ -773,11 +775,14 @@ public class DWARFDataTypeImporter {
DataTypeComponent[] definedComponents = structure.getDefinedComponents();
for (int i = 0; i < definedComponents.length; i++) {
DataTypeComponent dtc = definedComponents[i];
DataType dtcDT = dtc.getDataType();
if (dtcDT.isZeroLength()) {
continue;
}
int nextDTCOffset =
(i < definedComponents.length - 1) ? definedComponents[i + 1].getOffset()
: structure.getLength();
int emptySpaceBetween = nextDTCOffset - dtc.getEndOffset();
DataType dtcDT = dtc.getDataType();
int emptySpaceBetween = nextDTCOffset - (dtc.getEndOffset() + 1);
if (dtc.getLength() < dtcDT.getLength() && emptySpaceBetween > 0) {
DataTypeComponent newDTC = structure.replaceAtOffset(dtc.getOffset(), dtcDT,
Math.min(nextDTCOffset - dtc.getOffset(), dtc.getDataType().getLength()),
@ -802,17 +807,15 @@ public class DWARFDataTypeImporter {
DataTypeComponent[] definedComponents = structure.getDefinedComponents();
if (definedComponents.length > 0) {
DataTypeComponent lastDTC = definedComponents[definedComponents.length - 1];
return lastDTC.getOffset() + getUnpaddedDataTypeLength(lastDTC.getDataType());
return lastDTC.getOffset() + lastDTC.getLength();
}
}
return dt.getLength();
return dt.isZeroLength() ? 0 : dt.getLength();
}
private void populateStubStruct_worker(DWARFDataType ddt, StructureDataType structure,
DIEAggregate diea, int childTagType) throws IOException, DWARFExpressionException {
Set<Long> conflictingZeroLenFields = getConflictingZeroLenFields(diea, childTagType);
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
DIEAggregate childDIEA = prog.getAggregate(childEntry);
@ -870,19 +873,6 @@ public class DWARFDataTypeImporter {
}
}
if (conflictingZeroLenFields.contains(childEntry.getOffset())) {
// Skip adding this member because it is a problematic zero-length
// field
DWARFUtil.appendDescription(structure,
memberDesc("Missing member", "zero-length member", memberName, childDT,
memberOffset, -1, -1),
"\n");
continue;
}
boolean isDynamicSizedType = (childDT.dataType instanceof Dynamic ||
childDT.dataType instanceof FactoryDataType);
//if (childDT.getPathName().equals(structure.getPathName()) && childDT != structure) {
// The child we are adding has the exact same fullpath as us.
// This can happen when DWARF namespace info gets squished and two types
@ -892,33 +882,7 @@ public class DWARFDataTypeImporter {
// TODO: rename parent struct here. use .conflict or _basetype?
//}
if (childDT.isEmptyArrayType && childDT.dataType instanceof Array) {
if (memberOffset == structure.getLength() &&
structure.getFlexibleArrayComponent() == null) {
DataType arrayElementType = ((Array) childDT.dataType).getDataType();
structure.setFlexibleArrayComponent(arrayElementType, memberName, null);
}
else {
DWARFUtil.appendDescription(structure,
memberDesc("Missing member",
"Unsupported interior flex array: " + childDT.dataType.getName(),
memberName, childDT, memberOffset, -1, -1),
"\n");
}
// skip the rest of this loop as it deals with adding component children members.
continue;
}
if (isBitField) {
if (isDynamicSizedType) {
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
"dynamic length type", memberName, childDT, memberOffset, bitSize, -1),
"\n");
continue;
}
if (!BitFieldDataType.isValidBaseDataType(childDT.dataType)) {
DWARFUtil.appendDescription(structure,
memberDesc("Missing member",
@ -982,16 +946,14 @@ public class DWARFDataTypeImporter {
}
else {
String memberComment = null;
boolean isDynamicSizedType = (childDT.dataType instanceof Dynamic ||
childDT.dataType instanceof FactoryDataType);
if (isDynamicSizedType) {
memberComment = "Unsupported dynamic size data type: " + childDT.dataType;
childDT.dataType = Undefined.getUndefinedDataType(1);
}
int childLength = getUnpaddedDataTypeLength(childDT.dataType);
if (structure.isNotYetDefined() ||
(memberOffset + childLength > structure.getLength())) {
// zero len struct can't have members added, even if they are zero len, or
// member is longer than struct has storage for
if (memberOffset + childLength > structure.getLength()) {
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
"exceeds parent struct len", memberName, childDT, memberOffset, -1, -1),
"\n");
@ -999,21 +961,39 @@ public class DWARFDataTypeImporter {
continue;
}
DataTypeComponent existingDTC = structure.getComponentAt(memberOffset);
if (existingDTC != null &&
!(existingDTC.getDataType() instanceof DefaultDataType)) {
DWARFUtil.appendDescription(structure,
memberDesc("Missing member", "conflict with " + existingDTC.getFieldName(),
memberName, childDT, memberOffset, -1, -1),
"\n");
continue;
}
try {
DataTypeComponent dtc = structure.replaceAtOffset(memberOffset,
childDT.dataType, childLength, memberName, memberComment);
// struct.replaceAtOffset() clones the childDT, which will mess up our
DataTypeComponent dtc;
if (DataTypeComponent.usesZeroLengthComponent(childDT.dataType)) {
if (!isUndefinedOrZeroLenAtOffset(structure, memberOffset)) {
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
"conflicting member at same offset", memberName, childDT,
memberOffset, -1, -1), "\n");
continue;
}
// use insertAt for zero len members to allow multiple at same offset
dtc =
structure.insertAtOffset(memberOffset, childDT.dataType, 0, memberName,
memberComment);
}
else {
int ordinalToReplace = getUndefinedOrdinalAt(structure, memberOffset);
if (ordinalToReplace == -1) {
DataTypeComponent existingDTC =
structure.getComponentContaining(memberOffset);
if (existingDTC != null) {
DWARFUtil.appendDescription(structure,
memberDesc("Missing member",
"conflict with " + existingDTC.getFieldName(),
memberName, childDT, memberOffset, -1, -1),
"\n");
}
continue;
}
dtc = structure.replace(ordinalToReplace, childDT.dataType, childLength,
memberName, memberComment);
}
// struct.replaceAtOffset() and insertAtOffset() clones the childDT, which will mess up our
// identity based mapping in currentImplDataTypeToDDT.
// Update the mapping to prevent that.
updateMapping(childDT.dataType, dtc.getDataType());
@ -1030,72 +1010,29 @@ public class DWARFDataTypeImporter {
}
}
private Set<Long> getConflictingZeroLenFields(DIEAggregate diea, int childTagType)
throws IOException, DWARFExpressionException {
// Returns a set of DIE offsets of zero len fields that are fighting for
// the same offset in the parent struct
Map<Integer, Set<Long>> zeroLenMembers = new HashMap<>();
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
DIEAggregate childDIEA = prog.getAggregate(childEntry);
if (childDIEA.hasAttribute(DWARFAttribute.DW_AT_external)) {
continue;
private boolean isUndefinedOrZeroLenAtOffset(Structure struct, int offset) {
List<DataTypeComponent> compsAt = struct.getComponentsContaining(offset);
DataTypeComponent lastComp = !compsAt.isEmpty() ? compsAt.get(compsAt.size() - 1) : null;
if (lastComp == null) {
// only triggered if offset == length of struct, which is okay since we are adding
// a zero-length component to the struct
return true;
}
if (lastComp.getOffset() != offset) {
return false;
}
DataType dt = lastComp.getDataType();
return dt.isZeroLength() || dt instanceof DefaultDataType;
}
int bitSize = childDIEA.parseInt(DWARFAttribute.DW_AT_bit_size, -1);
boolean isBitField = bitSize != -1;
if (isBitField) {
continue;
private int getUndefinedOrdinalAt(Structure struct, int offset) {
List<DataTypeComponent> compsAt = struct.getComponentsContaining(offset);
DataTypeComponent lastComp = !compsAt.isEmpty() ? compsAt.get(compsAt.size() - 1) : null;
if (lastComp == null || lastComp.getOffset() != offset ||
!(lastComp.getDataType() instanceof DefaultDataType)) {
return -1;
}
DWARFDataType childDT = getDataType(childDIEA.getTypeRef(), null);
if (childDT == null) {
continue;
}
if (childDT.isZeroLenDT()) {
try {
int memberOffset =
childDIEA.parseDataMemberOffset(DWARFAttribute.DW_AT_data_member_location,
0);
zeroLenMembers.computeIfAbsent(memberOffset, k -> new HashSet<>())
.add(childEntry.getOffset());
}
catch (DWARFExpressionException e) {
continue;
}
}
}
Set<Long> conflictingZeroLenFields = new HashSet<>();
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
DIEAggregate childDIEA = prog.getAggregate(childEntry);
if (childDIEA.hasAttribute(DWARFAttribute.DW_AT_external)) {
continue;
}
int bitSize = childDIEA.parseInt(DWARFAttribute.DW_AT_bit_size, -1);
boolean isBitField = bitSize != -1;
if (isBitField) {
continue;
}
DWARFDataType childDT = getDataType(childDIEA.getTypeRef(), null);
if (childDT == null) {
continue;
}
int memberOffset = 0;
try {
memberOffset =
childDIEA.parseDataMemberOffset(DWARFAttribute.DW_AT_data_member_location, 0);
}
catch (DWARFExpressionException e) {
continue;
}
if (!childDT.isZeroLenDT() && zeroLenMembers.containsKey(memberOffset)) {
conflictingZeroLenFields.addAll(zeroLenMembers.get(memberOffset));
}
}
return conflictingZeroLenFields;
return lastComp.getOrdinal();
}
private static String memberDesc(String prefix, String errorStr, String memberName,
@ -1120,7 +1057,6 @@ public class DWARFDataTypeImporter {
throws IOException, DWARFExpressionException {
DWARFDataType elementType = getDataType(diea.getTypeRef(), voidDDT);
// do a second query to see if there was a recursive loop in the call above back
// to this datatype that resulted in this datatype being created.
// Use that instance if possible.
@ -1132,7 +1068,6 @@ public class DWARFDataTypeImporter {
// Build a list of the defined dimensions for this array type.
// The first element in the DWARF dimension list would be where a wild-card (-1 length)
// dimension would be defined.
boolean isEmptyArray = false;
List<Integer> dimensions = new ArrayList<>();
List<DebugInfoEntry> subrangeDIEs =
diea.getHeadFragment().getChildren(DWARFTag.DW_TAG_subrange_type);
@ -1146,17 +1081,14 @@ public class DWARFDataTypeImporter {
}
// Otherwise check for an upper bound
else if (subrangeAggr.hasAttribute(DWARFAttribute.DW_AT_upper_bound)) {
// TODO: Check lower bound or get the difference based on
// the language (See DWARF4 Section 5.11)
// TODO: upperbound == -1 seems to indicate zero length array
long upperBound =
subrangeAggr.parseUnsignedLong(DWARFAttribute.DW_AT_upper_bound, 0xbadbeef);
// fix special flag values used by DWARF to indicate that the array dimension
// is unknown. 64bit 0xffffff...s will already be -1, and 32bit 0xffff..s will
// be forced to -1.
// is unknown. 64bit 0xffffff...s and 32bit 0xffff..s will
// be forced to 0.
if (upperBound == 0xFF_FF_FF_FFL /* ie. max uint32 */ || upperBound == -1) {
upperBound = -1;
upperBound = 0;
}
else {
numElements = upperBound + 1;
@ -1169,28 +1101,7 @@ public class DWARFDataTypeImporter {
}
if (numElements == -1) {
// if numElements is the DWARF special flag value for unknown, set flag
// and force the value back to something that Ghidra datatypes can handle.
// The consumer of the resultant data type will get back an array with
// 1 element instead of 0 elements because of Ghidra's limitations.
// They should check the DWARFDataType.isEmptyArrayType flag (I'm looking at
// you makeDataTypeForStruct()) if they can handle unknown length arrays.
if (subRangeDIEIndex == 0) {
isEmptyArray = true;
}
else {
Msg.error(this,
"Bad undefined-length array dimension for subrange " + subRangeDIEIndex +
" for array's size in DIE: " + diea.getOffset() + ", forcing to 1");
}
numElements = 1;
}
else if (numElements == 0) {
Msg.error(this,
"Unsupported value [" + numElements + "] for array's size in DIE: " +
diea.getOffset() + ", forcing to 1");
numElements = 1;
isEmptyArray = true;
numElements = 0;
}
else if (numElements > Integer.MAX_VALUE) {
Msg.error(this, "Bad value [" + numElements + "] for array's size in DIE: " +
@ -1205,7 +1116,7 @@ public class DWARFDataTypeImporter {
for (int i = dimensions.size() - 1; i >= 0; i--) {
int numElements = dimensions.get(i);
ArrayDataType subArray =
new ArrayDataType(dt, numElements, dt.getLength(), dataTypeManager);
new ArrayDataType(dt, numElements, -1, dataTypeManager);
if (dt == elementType.dataType) {
updateMapping(dt, subArray.getDataType());
}
@ -1213,7 +1124,6 @@ public class DWARFDataTypeImporter {
}
DWARFDataType result = new DWARFDataType(dt, null, diea.getOffset());
result.isEmptyArrayType = isEmptyArray;
return result;
}
@ -1445,7 +1355,6 @@ public class DWARFDataTypeImporter {
static class DWARFDataType {
DataType dataType;
boolean isEmptyArrayType;
DWARFNameInfo dni;
DWARFSourceInfo dsi;
Set<Long> offsets = new HashSet<>();
@ -1473,12 +1382,5 @@ public class DWARFDataTypeImporter {
Collectors.joining(","));
}
boolean isZeroLenDT() {
DataType tmpDt =
(dataType instanceof TypeDef) ? ((TypeDef) dataType).getBaseDataType() : dataType;
return isEmptyArrayType || tmpDt.isNotYetDefined() ||
tmpDt.getLength() == 0 /* this can't happen right now, but never know for future */;
}
}
}

View file

@ -24,6 +24,7 @@ import ghidra.app.cmd.label.SetLabelPrimaryCmd;
import ghidra.app.util.bin.format.dwarf4.*;
import ghidra.app.util.bin.format.dwarf4.encoding.*;
import ghidra.app.util.bin.format.dwarf4.expression.*;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.database.function.OverlappingFunctionException;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
@ -258,6 +259,19 @@ public class DWARFFunctionImporter {
DWARFTag.DW_TAG_formal_parameter)) {
DIEAggregate childDIEA = prog.getAggregate(childEntry);
DataType childDT = dwarfDTM.getDataType(childDIEA.getTypeRef(), null);
if (childDT == null || DataTypeComponent.usesZeroLengthComponent(childDT)) {
String paramName =
childDIEA.getString(DWARFAttribute.DW_AT_name, "param" + formalParams.size());
Msg.warn(this, "DWARF: zero-length function parameter " + paramName +
":" + childDT.getName() + ", omitting from definition of " +
dfunc.dni.getName() + "@" + dfunc.address);
// skip this parameter because its data type is a zero-width type that typically does
// not generate code. If this varies compiler-to-compiler, setting
// skipFuncSignature=true may be a better choice
continue;
}
Parameter formalParam = createFormalParameter(childDIEA);
if (formalParam == null) {
skipFuncSignature = true;
@ -581,13 +595,33 @@ public class DWARFFunctionImporter {
}
}
else if (exprEvaluator.getLastRegister() == null) {
dvar.dni = dvar.dni.replaceType(null /*nothing matches static global var*/);
if (res != 0) {
// If the expression evaluated to a static address other than '0'
Address staticVariableAddress = toAddr(res + prog.getProgramBaseAddressFixup());
if (variablesProcesesed.contains(staticVariableAddress)) {
processStaticVar(res, dvar, diea);
return null;// Don't return the variable to be associated with the function
}
else {
Msg.error(this,
"LOCAL VAR: " + dvar.dni.getName() + " : " +
ghidra.app.util.bin.format.dwarf4.expression.DWARFExpression.exprToString(
topLocation.getLocation(), diea) +
", DWARF DIE: " + diea.getHexOffset());
return null;
}
return dvar;
}
private void processStaticVar(long address, DWARFVariable dvar, DIEAggregate diea)
throws InvalidInputException {
dvar.dni = dvar.dni.replaceType(null /*nothing matches static global var*/);
if (address != 0) {
Address staticVariableAddress = toAddr(address + prog.getProgramBaseAddressFixup());
if (isZeroByteDataType(dvar.type)) {
processZeroByteStaticVar(staticVariableAddress, dvar);
return;
}
if (variablesProcesesed.contains(staticVariableAddress)) {
return;
}
boolean external = diea.getBool(DWARFAttribute.DW_AT_external, false);
@ -602,17 +636,32 @@ public class DWARFFunctionImporter {
dvar.dni.getNamespacePath().asFormattedString() + " : " +
dvar.type.getPathName());
}
return null;// Don't return the variable to be associated with the function
}
else {
Msg.error(this,
"LOCAL VAR: " + dvar.dni.getName() + " : " +
ghidra.app.util.bin.format.dwarf4.expression.DWARFExpression.exprToString(
topLocation.getLocation(), diea) +
", DWARF DIE: " + diea.getHexOffset());
return null;
private void processZeroByteStaticVar(Address staticVariableAddress, DWARFVariable dvar)
throws InvalidInputException {
// because this is a zero-length data type (ie. array[0]),
// don't create a variable at the location since it will prevent other elements
// from occupying the same offset
Listing listing = currentProgram.getListing();
String comment =
listing.getComment(CodeUnit.PRE_COMMENT, staticVariableAddress);
comment = (comment != null) ? comment + "\n" : "";
comment += String.format("Zero length variable: %s: %s", dvar.dni.getOriginalName(),
dvar.type.getDisplayName());
listing.setComment(staticVariableAddress, CodeUnit.PRE_COMMENT, comment);
SymbolTable symbolTable = currentProgram.getSymbolTable();
symbolTable.createLabel(staticVariableAddress, dvar.dni.getName(),
dvar.dni.getParentNamespace(currentProgram),
SourceType.IMPORTED);
}
return dvar;
private boolean isZeroByteDataType(DataType dt) {
if (!dt.isZeroLength() && dt instanceof Array) {
dt = DataTypeUtilities.getArrayBaseDataType((Array) dt);
}
return dt.isZeroLength();
}
/**

View file

@ -108,9 +108,8 @@ public class PEx64UnwindInfoDataType extends DynamicDataType {
if (hasExceptionHandler(flags) || hasUnwindHandler(flags)) {
struct.add(IBO32, "ExceptionHandler", null);
if (hasUnwindHandler(flags)) {
// NOTE: Dynamic structure does not reflect flex-array
struct.setFlexibleArrayComponent(UnsignedLongDataType.dataType, "ExceptionData",
null);
struct.add(new ArrayDataType(UnsignedLongDataType.dataType, 0, -1),
"ExceptionData", null);
}
}
else if (hasChainedUnwindInfo(flags)) {
@ -132,14 +131,7 @@ public class PEx64UnwindInfoDataType extends DynamicDataType {
if (struct == null) {
return null;
}
DataTypeComponent[] components = struct.getComponents();
if (struct.hasFlexibleArrayComponent()) {
DataTypeComponent[] newArray = new DataTypeComponent[components.length + 1];
System.arraycopy(components, 0, newArray, 0, components.length);
newArray[components.length] = struct.getFlexibleArrayComponent();
components = newArray;
}
return components;
return struct.getComponents();
}
private boolean hasExceptionHandler(int flags) {

View file

@ -43,17 +43,8 @@ public class CompositeHandler {
if (dec == null || dec.getDataType() == null) {
return;
}
if (parent instanceof Structure) {
// ensure that only the last component establishes a structure's flex array
((Structure) parent).clearFlexibleArrayComponent();
}
// not a bitfield, just add the data type to composite
if (!dec.isBitField()) {
if (dec.isFlexArray() && parent instanceof Structure) {
((Structure) parent).setFlexibleArrayComponent(dec.getDataType(), dec.getName(),
dec.getComment());
return;
}
parent.add(dec.getDataType(), dec.getName(), dec.getComment());
return;
}

View file

@ -27,7 +27,6 @@ public class Declaration {
private String name;
private String comment;
private int bitSize = -1;
private boolean flexArray = false; // true if this is a zero size flex array component
public Declaration() {
super();
@ -155,11 +154,4 @@ public class Declaration {
bitSize = bits;
}
public void setFlexArray(boolean b) {
flexArray = b;
}
public boolean isFlexArray() {
return flexArray;
}
}

View file

@ -110,7 +110,11 @@ public class ArrayDataTypeHTMLRepresentation extends HTMLDataTypeRepresentation
}
private ValidatableLine buildFooterContent() {
return new TextLine("Size: " + array.getLength());
int len = array.getLength();
if (array.isZeroLength()) {
return new TextLine("Size: 0 (reported size is " + len + ")");
}
return new TextLine("Size: " + len);
}
private String buildHTMLText(ValidatableLine header, String body, ValidatableLine info,

View file

@ -100,11 +100,11 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
protected List<ValidatableLine> buildAlignmentText(Composite dataType) {
List<ValidatableLine> list = new ArrayList<>();
String alignStr = CompositeDataTypeImpl.getMinAlignmentString(dataType);
String alignStr = CompositeInternal.getMinAlignmentString(dataType);
if (alignStr != null && alignStr.length() != 0) {
list.add(new TextLine(alignStr));
}
String packStr = CompositeDataTypeImpl.getPackingString(dataType);
String packStr = CompositeInternal.getPackingString(dataType);
if (packStr != null && packStr.length() != 0) {
list.add(new TextLine(packStr));
}
@ -117,10 +117,6 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
private List<ValidatableLine> buildContent(Composite comp) {
List<ValidatableLine> list = new ArrayList<>();
if (comp.isZeroLength()) {
return list;
}
int count = 0;
DataTypeComponent[] components = comp.getComponents();
for (DataTypeComponent dataTypeComponent : components) {
@ -135,27 +131,14 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
locatableType = getLocatableDataType(dataType);
}
list.add(new DataTypeLine(fieldName, type, comment, locatableType, false));
list.add(new DataTypeLine(fieldName, type, comment, locatableType));
if (count++ >= MAX_COMPONENT_COUNT) {
// Prevent a ridiculous number of components from consuming all memory.
list.add(new DataTypeLine("", "Warning: Too many components to display...", "",
null, false));
list.add(
new DataTypeLine("", "Warning: Too many components to display...", "", null));
break;
}
}
if (comp instanceof Structure) {
Structure struct = (Structure) comp;
DataTypeComponent flexibleArrayComponent = struct.getFlexibleArrayComponent();
if (count < MAX_COMPONENT_COUNT && flexibleArrayComponent != null) {
String fieldName = flexibleArrayComponent.getFieldName();
String comment = flexibleArrayComponent.getComment();
DataType dataType = flexibleArrayComponent.getDataType();
String type = dataType.getDisplayName();
DataType locatableType = getLocatableDataType(dataType);
list.add(new DataTypeLine(fieldName, type, comment, locatableType, true));
}
}
return list;
}
@ -239,9 +222,6 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
StringBuilder lineBuffer = new StringBuilder();
DataTypeLine line = (DataTypeLine) iterator.next();
String typeName = generateTypeName(line, trim);
if (line.isFlexibleArray()) {
typeName += "[0]";
}
int fieldLength = ToolTipUtils.LINE_LENGTH / 2;
String fieldName = line.getName();

View file

@ -29,7 +29,6 @@ public class DataTypeLine implements ValidatableLine {
private String name;
private String comment;
private DataType dataType;
private boolean isFlexibleArray;
private Color typeColor;
private Color nameColor;
@ -37,9 +36,8 @@ public class DataTypeLine implements ValidatableLine {
private ValidatableLine validationLine;
DataTypeLine(String name, String type, String comment, DataType dt, boolean isFlexibleArray) {
DataTypeLine(String name, String type, String comment, DataType dt) {
this.dataType = dt;
this.isFlexibleArray = isFlexibleArray;
if (name == null) {
name = "";
}
@ -49,17 +47,9 @@ public class DataTypeLine implements ValidatableLine {
this.comment = comment == null ? "" : comment;
}
/**
* Determine if data type should be treated as flexible array
* @return true if data type should be treated as flexible array
*/
public boolean isFlexibleArray() {
return isFlexibleArray;
}
@Override
public ValidatableLine copy() {
return new DataTypeLine(name, type, comment, dataType, isFlexibleArray);
return new DataTypeLine(name, type, comment, dataType);
}
@Override

View file

@ -21,7 +21,7 @@ import ghidra.util.exception.AssertException;
public class EmptyDataTypeLine extends DataTypeLine implements PlaceHolderLine {
public EmptyDataTypeLine() {
super("", "", "", null, false);
super("", "", "", null);
}
@Override

View file

@ -20,6 +20,8 @@ import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import docking.widgets.fieldpanel.field.*;
import docking.widgets.fieldpanel.support.FieldLocation;
import docking.widgets.fieldpanel.support.FieldUtils;
@ -245,19 +247,32 @@ public class PreCommentFieldFactory extends FieldFactory {
}
private String[] getDataAutoComments(Data data) {
// Build flexible array comment
Address addr = data.getMinAddress().previous();
if (addr != null) {
return getFlexArrayComment(data, addr);
}
return null;
return getPreceedingComponentAutoComment(data);
}
private String[] getFlexArrayComment(Data data, Address addr) {
/**
* A composite which immediately preceeds the current address may contain trailing zero-length
* components which implicitly refer to this address and are not rendered by the opened composite.
* This comment is intended to convey the existence of such hidden components which correspond
* to addr.
* <br>
* NOTE: Implementation only provides comment for one trailing zero-length component. This could
* be improved to return a comment for all applicable trailing zero-length components.
* @param data data location whose pre-comment is currently be generated
* @return auto-comment or null
*/
private String[] getPreceedingComponentAutoComment(Data data) {
// NOTE: A zero-length composite has a length of 1 which may cause it to improperly consume
// the address location which actually corresponds to a trailing zero-length
// component.
int levelsToIgnore = 0;
String label = null;
Address prevDataAddr = data.getMinAddress().previous();
if (prevDataAddr == null) {
return null;
}
int[] cpath = data.getComponentPath();
if (cpath != null && cpath.length > 0) {
@ -273,46 +288,60 @@ public class PreCommentFieldFactory extends FieldFactory {
}
else {
Program p = data.getProgram();
data = p.getListing().getDefinedDataContaining(addr);
if (data == null || !(data.isStructure() || data.isDynamic())) {
data = p.getListing().getDefinedDataContaining(prevDataAddr);
if (data == null || !(data.isStructure() || data.isDynamic())) { // FIXME!! refer to DynamicDataType which has components - Union?
return null;
}
Symbol s = p.getSymbolTable().getPrimarySymbol(data.getAddress());
label = s != null ? s.getName(true) : data.getDataType().getName();
}
// locate deepest structure containing addr which will be checked for flex array
DataTypeComponent lastDtc = null;
while (true) {
int offset = (int) addr.subtract(data.getMinAddress());
Data component = data.getComponentAt(offset);
if (component == null || !component.isStructure()) {
DataType dt = data.getDataType();
if (dt instanceof Structure) {
Structure struct = (Structure) dt;
lastDtc = struct.getComponentContaining(struct.getLength());
int lastDtcOrdinal = struct.getNumComponents() - 1;
while (lastDtc != null && lastDtc.isBitFieldComponent() &&
lastDtc.getOrdinal() < lastDtcOrdinal) {
lastDtc = struct.getComponent(lastDtc.getOrdinal() + 1);
}
}
else if (dt instanceof DynamicDataType) {
DynamicDataType ddt = (DynamicDataType) dt;
lastDtc = ddt.getComponentAt(data.getLength(), data);
int lastDtcOrdinal = ddt.getNumComponents(data);
while (lastDtc != null && lastDtc.isBitFieldComponent() &&
lastDtc.getOrdinal() < lastDtcOrdinal) {
lastDtc = ddt.getComponent(lastDtc.getOrdinal() + 1, data);
}
}
if (lastDtc == null || lastDtc.getLength() == 0) {
break;
}
Data component = data.getComponent(lastDtc.getOrdinal());
if (component == null) {
return null;
}
data = component;
}
return buildFlexArrayComment(data, levelsToIgnore, label);
}
private String[] buildFlexArrayComment(Data data, int levelsToIgnore, String label) {
DataType dt = data.getBaseDataType();
DataTypeComponent flexComponent = null;
if (dt instanceof Structure) {
flexComponent = ((Structure) dt).getFlexibleArrayComponent();
}
else if (dt instanceof DynamicDataType) {
flexComponent = ((DynamicDataType) dt).getFlexibleArrayComponent(data);
}
if (flexComponent == null) {
if (lastDtc == null || lastDtc.isBitFieldComponent()) {
return null;
}
String fieldName = flexComponent.getFieldName();
if (fieldName == null) {
fieldName = flexComponent.getDefaultFieldName();
return buildZeroLengthComponentAutoComment(lastDtc, data, levelsToIgnore, label);
}
private String[] buildZeroLengthComponentAutoComment(DataTypeComponent lastZeroLengthComponent, Data data, int levelsToIgnore, String label) {
String fieldName = lastZeroLengthComponent.getFieldName();
if (StringUtils.isEmpty(fieldName)) {
fieldName = lastZeroLengthComponent.getDefaultFieldName();
}
StringBuilder flexName = new StringBuilder(fieldName);
@ -331,7 +360,7 @@ public class PreCommentFieldFactory extends FieldFactory {
flexName.insert(0, label + ".");
}
return new String[] { "Flexible Array: " + flexComponent.getDataType().getName() + "[] " +
return new String[] { "Zero-length Component: " + lastZeroLengthComponent.getDataType().getName() + " " +
flexName.toString() };
}

View file

@ -414,11 +414,11 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
}
}
}
else { // Structure
else { // Structure and DynamicDataType
List<Data> dataList = data.getComponentsContaining((int) addr.subtract(dataAddr));
if (dataList != null) { // nested flex-arrays can cause odd behavior
if (dataList != null) {
for (Data subData : dataList) {
// The only case where more than one subData exists is for bit-fields.
// The only case where more than one subData exists is for bit-fields and zero-length data.
// Depending upon the packing, bit-fields at different offsets may overlap
if (subData.getMinAddress().equals(addr)) {
list.add(subData);

View file

@ -649,7 +649,8 @@ public class DataTypesXmlMgr {
private void writerMember(XmlWriter writer, DataTypeComponent member) {
XmlAttributes attrs = new XmlAttributes();
// TODO: how should we output bitfields (packed/non-packed) and flex array
// TODO: how should we output bitfields (packed/non-packed)
// TODO: multiple components at same offset (e.g., zero-length arrays) could throw-off IDA XML import
attrs.addAttribute("OFFSET", member.getOffset(), true);
attrs.addAttribute("DATATYPE", member.getDataType().getDisplayName());
attrs.addAttribute("DATATYPE_NAMESPACE", member.getDataType().getCategoryPath().getPath());

View file

@ -1032,7 +1032,7 @@ public class CodeUnitFormat {
DataType dataType = data.getDataType();
int length = data.getLength();
if (length < dataType.getLength()) {
if ((length != 0 || !dataType.isZeroLength()) && dataType.getLength() > length) {
representationList.add("Data type \"" + dataType.getDisplayName() +
"\" is too big for available space. Size = " + dataType.getLength() +
" bytes, available = " + length + " bytes");

View file

@ -882,22 +882,6 @@ public class ProgramDiffDetails {
for (int index2 = i; index2 < compDt2.length; index2++) {
getComponentInfo(compDt2[index2], buf2, newIndent);
}
if (dt1 instanceof Structure) {
// dt2 is also Structure - check for flex array component
DataTypeComponent flexDtc1 = ((Structure) dt1).getFlexibleArrayComponent();
DataTypeComponent flexDtc2 = ((Structure) dt2).getFlexibleArrayComponent();
if (flexDtc1 != null) {
getComponentInfo(flexDtc1, buf1, newIndent);
}
if (flexDtc2 != null) {
getComponentInfo(flexDtc2, buf2, newIndent);
}
if (flexDtc1 != null && flexDtc2 != null) {
compareSubDataTypes(flexDtc1.getDataType(), flexDtc2.getDataType(), buf1, buf2,
newIndent);
}
}
}
private void compareDataCUs(Data d1, Data d2, StringBuffer buf1, StringBuffer buf2,
@ -926,22 +910,13 @@ public class ProgramDiffDetails {
if (fieldName == null) {
fieldName = dtc.getDefaultFieldName();
}
if (dtc.isFlexibleArrayComponent()) {
buf.append(indent + "Offset=" + DiffUtility.toSignedHexString(offset) + " " +
"Ordinal=" + ordinal + " " + fieldName + " " +
actualDt.getMnemonic(actualDt.getDefaultSettings()) + "[]" + " " +
getCategoryName(actualDt) + " " + "DataTypeSize=" + actualDt.getLength() +
" (flexible array) " + ((comment != null) ? comment : "") + " " + newLine);
}
else {
// TODO: how should we display bitfields?
buf.append(indent + "Offset=" + DiffUtility.toSignedHexString(offset) + " " +
"Ordinal=" + ordinal + " " + fieldName + " " +
actualDt.getMnemonic(actualDt.getDefaultSettings()) + " " +
getCategoryName(actualDt) + " " + "DataTypeSize=" + actualDt.getLength() + " " +
"ComponentSize=" + dtc.getLength() + " " + ((comment != null) ? comment : "") +
buf.append(indent + "Offset=" + DiffUtility.toSignedHexString(offset) + " " + "Ordinal=" +
ordinal + " " + fieldName + " " + actualDt.getMnemonic(actualDt.getDefaultSettings()) +
" " + getCategoryName(actualDt) + " " + "DataTypeSize=" +
(actualDt.isZeroLength() ? 0 : actualDt.getLength()) + " " + "ComponentSize=" +
dtc.getLength() + " " + ((comment != null) ? comment : "") +
" " + newLine);
}
return actualDt;
}
@ -983,18 +958,17 @@ public class ProgramDiffDetails {
Data data = (Data) cu;
DataType dt = data.getDataType();
if (dt instanceof Composite) {
DataTypeComponent[] compDt = ((Composite) dt).getComponents();
for (DataTypeComponent element : compDt) {
int offset = element.getOffset();
String comment = element.getComment();
String fieldName = element.getFieldName();
DataTypeComponent[] components = ((Composite) dt).getComponents();
for (DataTypeComponent dtc : components) {
int offset = dtc.getOffset();
String comment = dtc.getComment();
String fieldName = dtc.getFieldName();
if (fieldName == null) {
fieldName = "field" + offset;
}
buf.append(newIndent + min.add(offset) + " " + element.getFieldName() +
" " + element.getDataType().getName() + " " + "length=" +
element.getLength() + " " +
buf.append(newIndent + min.add(offset) + " " + dtc.getFieldName() + " " +
dtc.getDataType().getName() + " " + "length=" +
dtc.getLength() + " " +
((comment != null) ? comment : "") + " " + newLine);
}
}

View file

@ -573,9 +573,16 @@ public class DataTypeParser {
ArraySpecPiece(String piece) throws InvalidDataTypeException {
if (piece.startsWith("[") && piece.endsWith("]")) {
String elementCountStr = piece.substring(1, piece.length() - 1);
try {
String elementCountStr = piece.substring(1, piece.length() - 1);
if (elementCountStr.length() == 0) {
// treat empty array spec same as 0
// consumer may need to handle resulting array as a pointer (e.g., parameter)
elementCount = 0;
}
else {
elementCount = parseSize(elementCountStr);
}
return;
}
catch (NumberFormatException e) {

View file

@ -1968,15 +1968,8 @@ Declaration DirectDeclarator(Declaration dt, DataType container) : {
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Integer iSize = (Integer) iterator.next();
DataType decDt = dec.getDataType();
if (iSize == 0 && container != null) {
dec.setFlexArray(true);
break;
} else if (iSize == 0) {
dec.setDataType(dtMgr.getPointer(decDt));
} else {
dec.setDataType(new ArrayDataType(decDt, iSize, decDt.getLength()));
}
}
//System.out.println("Array expr: for " + dec.getName() + " make an array " + dt.getName() + "["+size+"]");
}
)*

View file

@ -27,7 +27,7 @@ import ghidra.program.database.ProgramModifierListener;
import ghidra.program.model.data.*;
import ghidra.util.InvalidNameException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitorAdapter;
import ghidra.util.task.TaskMonitor;
/**
* Tests for merging data types.
@ -66,12 +66,11 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
struct.insertBitFieldAt(3, 2, 6, td, 2, "bf1", null);
struct.insertBitFieldAt(3, 2, 4, td, 2, "bf2", null);
struct.add(new QWordDataType());
struct.setFlexibleArrayComponent(td, "flex", "my flex");
struct.add(new ArrayDataType(td, 0, -1), 0, "flex", "my flex");
structRef.set(struct);
c.removeCategory("Category5", TaskMonitorAdapter.DUMMY);
c.removeCategory("Category5", TaskMonitor.DUMMY);
Category c5 = c.createCategory("Category5");
c5.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
commit = true;
@ -187,7 +186,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
try {
Structure s = (Structure) c.getDataType("IntStruct");
c.remove(s, TaskMonitorAdapter.DUMMY);
c.remove(s, TaskMonitor.DUMMY);
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0, dtm);
s.add(new QWordDataType(), "f1", "my f1");
s.add(new FloatDataType());
@ -220,7 +219,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Structure s = (Structure) dt;
assertEquals("my f1", s.getComponent(0).getComment());
DataTypeComponent dtc = s.getComponentAt(17);
DataTypeComponent dtc = s.getComponentContaining(17);
assertEquals(7, dtc.getOrdinal());
assertEquals("my bf1", dtc.getComment());
}
@ -243,7 +242,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
try {
Structure s = (Structure) c.getDataType("IntStruct");
c.remove(s, TaskMonitorAdapter.DUMMY);
c.remove(s, TaskMonitor.DUMMY);
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0);
s.add(new QWordDataType());
s.add(new FloatDataType());
@ -440,7 +439,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -479,7 +478,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
try {
DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -530,7 +529,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -581,7 +580,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"FloatStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -611,7 +610,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -659,7 +658,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -715,7 +714,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -734,7 +733,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -963,7 +962,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -992,7 +991,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1050,7 +1049,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Structure s = (Structure) dt;
s.add(new ByteDataType());
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
parent.removeCategory("Category3", TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1116,7 +1115,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Structure s = (Structure) dt;
s.add(new ByteDataType());
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
parent.removeCategory("Category3", TaskMonitor.DUMMY);
commit = true;
}
finally {

View file

@ -1097,7 +1097,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
Structure s1 =
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
"Structure_1");
s1.setFlexibleArrayComponent(td, null, null);
s1.add(new ArrayDataType(td, 0, -1), 0, null, null);
}
finally {
program.endTransaction(transactionID, true);
@ -1112,7 +1112,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
Structure s1 =
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
"Structure_1");
s1.setFlexibleArrayComponent(IntegerDataType.dataType, "flex1", "cmt1");
s1.add(new ArrayDataType(IntegerDataType.dataType, 0, -1), "flex1", "cmt1");
}
finally {
program.endTransaction(transactionID, true);
@ -1134,11 +1134,15 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
assertNotNull(s1);
DataTypeComponent[] dtcs = s1.getComponents();
assertEquals(4, dtcs.length);
assertEquals(5, dtcs.length);
DataTypeComponent flexDtc = s1.getFlexibleArrayComponent();
assertNotNull(flexDtc);
assertTrue(IntegerDataType.class == flexDtc.getDataType().getClass());
DataTypeComponent flexDtc = s1.getComponent(4);
assertEquals(0, flexDtc.getLength());
DataType dt = flexDtc.getDataType();
assertTrue(dt instanceof Array);
Array a = (Array) dt;
assertEquals(0, a.getNumElements());
assertTrue(a.getDataType() instanceof IntegerDataType);
assertEquals("flex1", flexDtc.getFieldName());
assertEquals("cmt1", flexDtc.getComment());
}
@ -1159,7 +1163,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
Structure s1 =
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
"Structure_1");
s1.setFlexibleArrayComponent(IntegerDataType.dataType, null, null);
s1.add(new ArrayDataType(IntegerDataType.dataType, 0, -1), 0, null, null);
}
finally {
program.endTransaction(transactionID, true);
@ -1174,7 +1178,9 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
Structure s1 =
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
"Structure_1");
s1.setFlexibleArrayComponent(td, "flex1", "cmt1");
// last component is flex array to be replaced
s1.replace(s1.getNumComponents() - 1, new ArrayDataType(td, 0, -1), 0, "flex1",
"cmt1");
}
finally {
program.endTransaction(transactionID, true);
@ -1189,9 +1195,9 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
Structure s1 =
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
"Structure_1");
s1.deleteAtOffset(s1.getLength());
s1.insertBitFieldAt(3, 2, 6, td, 2, "bf1", "my bf1");
s1.insertBitFieldAt(3, 2, 4, td, 2, "bf2", "my bf2");
s1.clearFlexibleArrayComponent();
}
catch (InvalidDataTypeException e) {
e.printStackTrace();
@ -1217,8 +1223,9 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
assertNotNull(s1);
DataTypeComponent flexDtc = s1.getFlexibleArrayComponent();
assertNull(flexDtc);
for (DataTypeComponent dtc : s1.getComponents()) {
assertNotEquals(0, dtc.getLength());
}
DataTypeComponent[] dtcs = s1.getComponents();
assertEquals(7, dtcs.length);
@ -1260,8 +1267,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
int transactionID = program.startTransaction("test");
try {
Structure s = (Structure) dtm.getDataType("/Category5/Test");
DataType dt = dtm.getDataType("/MISC/FooTypedef");
s.setFlexibleArrayComponent(dt, "foo", "");
DataType td = dtm.getDataType("/MISC/FooTypedef");
s.replaceAtOffset(s.getLength(), new ArrayDataType(td, 0, -1), 0, "foo", null);
commit = true;
}
finally {
@ -1310,8 +1317,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
struct.insertBitFieldAt(3, 2, 4, td, 2, "bf2", null);
struct.add(new WordDataType());
struct.add(new QWordDataType());
struct.setFlexibleArrayComponent(td, "flex", "my flex");
struct.add(new ArrayDataType(td, 0, -1), 0, "flex", "my flex");
dtm.addDataType(struct, null);
commit = true;

View file

@ -55,14 +55,15 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
addDataType(ByteDataType.dataType);
addDataType(FloatDataType.dataType);
addFlexDataType(DWordDataType.dataType, null, null);
addFlexDataType((Structure) structureModel.viewComposite, DWordDataType.dataType, null,
null);
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 4, "float", FloatDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, 5, 0, "ddw[0]", DWordDataType.dataType, "", "");
checkFlexArrayRow(2, 5, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(5);
assertActualAlignment(1);
}
@ -73,16 +74,17 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
addDataType(ByteDataType.dataType);
addDataType(CharDataType.dataType);
addFlexDataType(DWordDataType.dataType, null, null);
addFlexDataType((Structure) structureModel.viewComposite, DWordDataType.dataType, null,
null);
waitForSwing();
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 1, "char", CharDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, 2, 0, "ddw[0]", DWordDataType.dataType, "", "");
checkFlexArrayRow(2, 2, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(2);
assertActualAlignment(1);
@ -90,12 +92,12 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
assertIsPackingEnabled(true);
assertDefaultPacked();
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 1, "char", CharDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, 4, 0, "ddw[0]", DWordDataType.dataType, "", "");
checkFlexArrayRow(2, 4, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(4);
assertActualAlignment(4);
}
@ -106,7 +108,8 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
addDataType(ByteDataType.dataType);
addDataType(CharDataType.dataType);
addFlexDataType(DWordDataType.dataType, null, null);
addFlexDataType((Structure) structureModel.viewComposite, DWordDataType.dataType, null,
null);
waitForSwing();
@ -117,12 +120,14 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
pressButtonByName(getPanel(), "Machine Alignment");
assertIsMachineAligned();
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 1, "char", CharDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, 8, 0, "ddw[0]", DWordDataType.dataType, "", "");
// It is important to note that a trailing flex array will align the same as any other component and
// is not guarenteed to fall at the end of the structure.
checkFlexArrayRow(2, 4, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(8);
assertActualAlignment(8);
}
@ -135,7 +140,8 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
addDataType(ByteDataType.dataType);
addDataType(CharDataType.dataType);
addFlexDataType(DWordDataType.dataType, null, null);
addFlexDataType((Structure) structureModel.viewComposite, DWordDataType.dataType, null,
null);
waitForSwing();
@ -156,51 +162,49 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
assertEquals(false, structureModel.viewComposite.isMachineAligned());
assertEquals(8, structureModel.getExplicitMinimumAlignment());
assertEquals(2, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 1, "char", CharDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, 8, 0, "ddw[0]", DWordDataType.dataType, "", "");
checkFlexArrayRow(2, 4, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(8);
assertActualAlignment(8);
}
@Test
public void testByValue1AlignedStructure() throws Exception {
checkByValueAlignedStructure(1, 4, 4);
checkByValueAlignedStructure(1, 4, 4, 4);
}
@Test
public void testByValue2AlignedStructure() throws Exception {
checkByValueAlignedStructure(2, 4, 4);
checkByValueAlignedStructure(2, 4, 4, 4);
}
@Test
public void testByValue4AlignedStructure() throws Exception {
checkByValueAlignedStructure(4, 4, 4);
checkByValueAlignedStructure(4, 4, 4, 4);
}
@Test
public void testByValue8AlignedStructure() throws Exception {
checkByValueAlignedStructure(8, 8, 8);
checkByValueAlignedStructure(8, 8, 8, 4);
}
@Test
public void testByValue16AlignedStructure() throws Exception {
checkByValueAlignedStructure(16, 16, 16);
checkByValueAlignedStructure(16, 16, 16, 4);
}
public void checkByValueAlignedStructure(int value, int alignment, int length)
public void checkByValueAlignedStructure(int value, int alignment, int length, int flexOffset)
throws Exception {
emptyStructure.setPackingEnabled(true);
emptyStructure.setExplicitMinimumAlignment(value);
emptyStructure.add(ByteDataType.dataType);
emptyStructure.add(CharDataType.dataType);
emptyStructure.setFlexibleArrayComponent(DWordDataType.dataType, null, null);
addFlexDataType(emptyStructure, DWordDataType.dataType, null, null);
init(emptyStructure, pgmRootCat, false);
CompEditorPanel editorPanel = (CompEditorPanel) getPanel();
@ -219,12 +223,13 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
assertEquals(false, structureModel.viewComposite.isMachineAligned());
assertEquals(value, structureModel.getExplicitMinimumAlignment());
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 1, "char", CharDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, length, 0, "ddw[0]", DWordDataType.dataType, "", "");
checkFlexArrayRow(2, flexOffset, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(length);
assertActualAlignment(alignment);
}
@ -240,7 +245,7 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
addDataType(ByteDataType.dataType);
addDataType(CharDataType.dataType);
addFlexDataType(DWordDataType.dataType, null, null);
addFlexDataType((Structure) structureModel.viewComposite, DWordDataType.dataType, null, null);
JRadioButton byValuePackingButton =
(JRadioButton) findComponentByName(editorPanel, "Explicit Packing");
@ -255,18 +260,24 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
assertEquals(false, structureModel.viewComposite.isMachineAligned());
assertEquals(false, structureModel.viewComposite.hasExplicitMinimumAlignment());
assertEquals(2, structureModel.getNumComponents());
assertEquals(3, structureModel.getNumComponents());
assertEquals(4, structureModel.getRowCount());
checkRow(0, 0, 1, "db", ByteDataType.dataType, "", "");
checkRow(1, 1, 1, "char", CharDataType.dataType, "", "");
checkBlankRow(2);
checkRow(3, 2, 0, "ddw[0]", DWordDataType.dataType, "", "");
checkFlexArrayRow(2, 2, "ddw", DWordDataType.dataType, "", "");
checkBlankRow(3);
assertLength(2);
assertActualAlignment(1);
}
////////////////////////////
private void checkFlexArrayRow(int rowIndex, int offset, String mnemonic, DataType dataType,
String name, String comment) {
ArrayDataType a = new ArrayDataType(dataType, 0, -1);
checkRow(rowIndex, offset, 0, mnemonic + "[0]", a, name, comment);
}
private void checkRow(int rowIndex, int offset, int length, String mnemonic, DataType dataType,
String name, String comment) {
assertTrue(dataType.isEquivalent(structureModel.getComponent(rowIndex).getDataType()));
@ -294,9 +305,9 @@ public class StructureEditorFlexAlignmentTest extends AbstractStructureEditorTes
return structureModel.viewComposite.add(dataType);
}
private DataTypeComponent addFlexDataType(DataType dataType, String name, String comment) {
return ((Structure) structureModel.viewComposite).setFlexibleArrayComponent(dataType, name,
comment);
private DataTypeComponent addFlexDataType(Structure struct, DataType dataType, String name, String comment) {
ArrayDataType a = new ArrayDataType(dataType, 0, 1);
return struct.add(a, name, comment);
}
}

View file

@ -51,7 +51,7 @@ public class StructureEditorLockedCellEditTest extends AbstractStructureEditorTe
try {
DataTypeManager dataTypeManager = cat.getDataTypeManager();
if (dt.getDataTypeManager() != dataTypeManager) {
dt = (Structure) dt.clone(dataTypeManager);
dt = dt.clone(dataTypeManager);
}
CategoryPath categoryPath = cat.getCategoryPath();

View file

@ -55,6 +55,7 @@ public class StructureEditorUnlockedActions4Test
invoke(applyAction);
assertTrue(complexStructure.isEquivalent(model.viewComposite));
assertEquals(1, complexStructure.getLength());
assertTrue(complexStructure.isNotYetDefined());
assertTrue(complexStructure.isZeroLength());
}

View file

@ -230,7 +230,10 @@ public class StructureEditorUnlockedActions5Test
triggerEnter(textField);
assertEquals(originalLength, model.getLength());
assertFalse(applyAction.isEnabled());
setErrorsExpected(true);
invoke(applyAction);
setErrorsExpected(false);
assertTrue(complexStructure.isEquivalent(model.viewComposite));
assertEquals(originalLength, complexStructure.getLength());
}
@ -590,7 +593,10 @@ public class StructureEditorUnlockedActions5Test
triggerActionKey(component, 0, KeyEvent.VK_ENTER);
assertEquals(newLength, model.getLength());
assertFalse(applyAction.isEnabled());
setErrorsExpected(true);
invoke(applyAction);
setErrorsExpected(false);
assertTrue(complexStructure.isEquivalent(model.viewComposite));
assertEquals(newLength, complexStructure.getLength());
}

View file

@ -52,6 +52,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
DataType dt = pgmRootCat.getDataType(emptyStructure.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertIsPackingEnabled(false);
@ -94,6 +95,9 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
deleteAllComponents();
assertTrue(model.viewComposite.isNotYetDefined());
assertTrue(model.viewComposite.isZeroLength());
assertEquals(0, model.getNumComponents());
assertEquals(1, model.getRowCount());
assertEquals(0, model.getLength());
@ -116,10 +120,12 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
invoke(applyAction);
assertTrue(simpleStructure.isEquivalent(model.viewComposite));
assertTrue(simpleStructure.isNotYetDefined());
assertTrue(simpleStructure.isZeroLength());
dt = pgmBbCat.getDataType(simpleStructure.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertIsPackingEnabled(false);
@ -214,6 +220,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
dt = pgmTestCat.getDataType(innerStructure.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertIsPackingEnabled(false);
@ -309,9 +316,11 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
dt = pgmTestCat.getDataType(innerStructure.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(innerStructure.isEquivalent(model.viewComposite));
assertTrue(innerStructure.isNotYetDefined());
assertTrue(innerStructure.isZeroLength());
assertIsPackingEnabled(false);
@ -350,7 +359,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
}
assertNotNull(innerStructure);
assertNotNull(innerTypedef);
assertTrue(!innerTypedef.isZeroLength());
assertFalse(innerTypedef.isZeroLength());
init(innerStructure, pgmTestCat, false);
@ -402,9 +411,11 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
dt = pgmTestCat.getDataType(innerStructure.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(innerStructure.isEquivalent(model.viewComposite));
assertTrue(innerStructure.isNotYetDefined());
assertTrue(innerStructure.isZeroLength());
assertIsPackingEnabled(false);
@ -417,6 +428,7 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
assertEquals(false, applyAction.isEnabled());
// assertStatus("/testCat/innerStructure is contained in /testCat/innerStructureTypedef and can't be changed to a zero size data type.");
assertFalse(innerTypedef.isNotYetDefined()); // Typedef is always defined even if referenced type is not
assertTrue(innerTypedef.isZeroLength());
assertEquals(1, innerTypedef.getLength());
}
@ -498,9 +510,11 @@ public class ZeroSizeStructureTest extends AbstractStructureEditorTest {
dt = pgmTestCat.getDataType(innerStructure.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(innerStructure.isEquivalent(model.viewComposite));
assertTrue(innerStructure.isNotYetDefined());
assertTrue(innerStructure.isZeroLength());
assertIsPackingEnabled(false);

View file

@ -52,6 +52,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest {
DataType dt = pgmRootCat.getDataType(emptyUnion.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertIsPackingEnabled(false);
@ -116,10 +117,12 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest {
invoke(applyAction);
assertTrue(simpleUnion.isEquivalent(model.viewComposite));
assertTrue(simpleUnion.isNotYetDefined());
assertTrue(simpleUnion.isZeroLength());
dt = pgmBbCat.getDataType(simpleUnion.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(simpleUnion.isEquivalent(model.viewComposite));
@ -214,6 +217,7 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest {
dt = pgmTestCat.getDataType(innerUnion.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertIsPackingEnabled(false);
@ -307,9 +311,11 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest {
dt = pgmTestCat.getDataType(innerUnion.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(innerUnion.isEquivalent(model.viewComposite));
assertTrue(innerUnion.isNotYetDefined());
assertTrue(innerUnion.isZeroLength());
assertIsPackingEnabled(false);
@ -397,9 +403,11 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest {
dt = pgmTestCat.getDataType(innerUnion.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(innerUnion.isEquivalent(model.viewComposite));
assertTrue(innerUnion.isNotYetDefined());
assertTrue(innerUnion.isZeroLength());
assertIsPackingEnabled(false);
@ -487,9 +495,11 @@ public class ZeroSizeUnionTest extends AbstractUnionEditorTest {
dt = pgmTestCat.getDataType(innerUnion.getName());
assertNotNull(dt);
assertTrue(dt.isNotYetDefined());
assertTrue(dt.isZeroLength());
assertTrue(innerUnion.isEquivalent(model.viewComposite));
assertTrue(innerUnion.isNotYetDefined());
assertTrue(innerUnion.isZeroLength());
assertIsPackingEnabled(false);

View file

@ -190,7 +190,8 @@ public class DataReferencesTest extends AbstractGhidraHeadedIntegrationTest {
int e = i / 24;
int f = i % 24;
assertEquals(
"dword ptr [ArrayA[" + e + "].field_0x" + Integer.toHexString(f) + "]",
"dword ptr [ArrayA[" + e + "].field" + f + "_0x" + Integer.toHexString(f) +
"]",
opStr);
}
}
@ -233,10 +234,13 @@ public class DataReferencesTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("dword ptr [StructA]", opStr);
}
else {
int f = (i / 24) * 24;
int fOrdinal = i / 24;
int fOffset = fOrdinal * 24;
int e = (i % 24) / 4;
assertEquals(
"dword ptr [StructA.field_0x" + Integer.toHexString(f) + "[" + e + "]]",
"dword ptr [StructA.field" + fOrdinal + "_0x" +
Integer.toHexString(fOffset) + "[" + e +
"]]",
opStr);
}
}
@ -327,10 +331,12 @@ public class DataReferencesTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("dword ptr [StructA]", opStr);
}
else {
int f1 = (i / 24) * 24;
int f1Ordinal = i / 24;
int f1Offset = f1Ordinal * 24;
int f2 = i % 24;
assertEquals("dword ptr [StructA.field_0x" + Integer.toHexString(f1) +
".field_0x" + Integer.toHexString(f2) + "]", opStr);
assertEquals("dword ptr [StructA.field" + f1Ordinal + "_0x" +
Integer.toHexString(f1Offset) +
".field" + f2 + "_0x" + Integer.toHexString(f2) + "]", opStr);
}
}
}

View file

@ -354,8 +354,8 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
DataType structdt2 = dataMgr.getDataType(rootCP, "mystruct.conflict");
assertEquals(100, structdt.getLength());
assertEquals("f1", structdt.getComponentAt(0).getFieldName());
assertEquals("f2", structdt.getComponentAt(10).getFieldName());
assertEquals("f1", structdt.getComponentContaining(0).getFieldName());
assertEquals("f2", structdt.getComponentContaining(10).getFieldName());
assertNull(structdt2);
}
@ -378,7 +378,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
Structure struct2dt = (Structure) dataMgr.getDataType(rootCP, "mystruct2");
assertEquals(100, structdt.getLength());
assertEquals("ptr_to_struct1", struct2dt.getComponentAt(0).getFieldName());
assertEquals("ptr_to_struct1", struct2dt.getComponentContaining(0).getFieldName());
}
@Test
@ -699,7 +699,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
DataTypeComponent dtc = structdt.getComponentAt(14);
DataTypeComponent dtc = structdt.getComponentContaining(14);
DataType anonDT = dtc.getDataType();
assertEquals("anon_struct_for_f3_f4", anonDT.getName());
}
@ -717,8 +717,13 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent());
DataTypeComponent component = structdt.getComponent(structdt.getNumComponents() - 1);
assertNotNull(component);
assertEquals(0, component.getLength());
DataType dt = component.getDataType();
assertTrue(dt instanceof Array);
Array a = (Array) dt;
assertEquals(0, a.getNumElements());
}
/*
@ -739,7 +744,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent());
assertHasFlexArray(structdt);
}
@ -761,7 +766,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent());
assertHasFlexArray(structdt);
}
@Test
@ -778,9 +783,73 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertTrue(structdt.getDescription().contains("Missing member flexarray"));
assertNull(structdt.getFlexibleArrayComponent());
DataTypeComponent component = structdt.getComponentContaining(99);
assertNotNull(component);
assertEquals(0, component.getLength());
DataType dt = component.getDataType();
assertTrue(dt.isEquivalent(new ArrayDataType(IntegerDataType.dataType, 0, -1)));
assertEquals(100, structdt.getLength());
}
@Test
public void testStructZeroLenField()
throws CancelledException, IOException, DWARFException {
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry emptyStructDIE = newStruct("emptystruct", 0).create(cu);
DebugInfoEntry structDIE = newStruct("mystruct", 10).create(cu);
newMember(structDIE, "f1", intDIE, 0).create(cu);
newMember(structDIE, "f2", emptyStructDIE, 4).create(cu);
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertEquals(2, structdt.getNumDefinedComponents());
DataTypeComponent f1 = structdt.getDefinedComponents()[0];
assertEquals(0, f1.getOffset());
assertEquals(4, f1.getLength());
DataTypeComponent f2 = structdt.getDefinedComponents()[1];
assertEquals(4, f2.getOffset());
assertTrue(f2.getDataType().isZeroLength());
assertEquals(10, structdt.getLength());
}
@Test
public void testStruct2ZeroLenField()
throws CancelledException, IOException, DWARFException {
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry emptyStructDIE = newStruct("emptystruct", 0).create(cu);
DebugInfoEntry structDIE = newStruct("mystruct", 10).create(cu);
newMember(structDIE, "f1", intDIE, 0).create(cu);
newMember(structDIE, "f2", emptyStructDIE, 4).create(cu);
newMember(structDIE, "f3", emptyStructDIE, 4).create(cu);
newMember(structDIE, "f4", intDIE, 4).create(cu);
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertEquals(4, structdt.getNumDefinedComponents());
DataTypeComponent f1 = structdt.getDefinedComponents()[0];
assertEquals(0, f1.getOffset());
assertEquals(4, f1.getLength());
DataTypeComponent f2 = structdt.getDefinedComponents()[1];
assertEquals(4, f2.getOffset());
assertTrue(f2.getDataType().isZeroLength());
DataTypeComponent f3 = structdt.getDefinedComponents()[2];
assertEquals(4, f3.getOffset());
assertTrue(f3.getDataType().isZeroLength());
DataTypeComponent f4 = structdt.getDefinedComponents()[3];
assertEquals(4, f4.getOffset());
assertEquals(4, f4.getLength());
assertEquals(10, structdt.getLength());
}
@Test
@ -862,8 +931,6 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
@Test
public void testUnionFlexArray() throws CancelledException, IOException, DWARFException {
// flex array in a union is converted to an 1 element array (if it can fit)
DebugInfoEntry intDIE = addInt(cu);
DebugInfoEntry arrayDIE = newArray(cu, intDIE, false, -1);
@ -920,10 +987,10 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
DataTypeComponent f1dtc = structdt.getComponentAt(0);
DataTypeComponent f2dtc = structdt.getComponentAt(10);
DataTypeComponent f3dtc = structdt.getComponentAt(20);
DataTypeComponent f4dtc = structdt.getComponentAt(40);
DataTypeComponent f1dtc = structdt.getComponentContaining(0);
DataTypeComponent f2dtc = structdt.getComponentContaining(10);
DataTypeComponent f3dtc = structdt.getComponentContaining(20);
DataTypeComponent f4dtc = structdt.getComponentContaining(40);
assertEquals(f1dtc.getDataType(), f2dtc.getDataType());
assertEquals(f1dtc.getDataType(), f3dtc.getDataType());

View file

@ -13,9 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*
*/
package ghidra.program.database;
import static org.junit.Assert.*;
@ -25,8 +22,6 @@ import java.util.ConcurrentModificationException;
import org.junit.Test;
import ghidra.program.database.DBObjectCache;
import ghidra.program.database.DatabaseObject;
import ghidra.program.model.address.KeyRange;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;

View file

@ -86,8 +86,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
struct.add(new ByteDataType(), "field0", "Comment1");
struct.add(new WordDataType(), null, "Comment2");
struct.add(new DWordDataType(), "field3", null);
struct.add(new ByteDataType(), "field4", "Comment4");
// struct.setFlexibleArrayComponent(CharDataType.dataType, "flex", "Flex Comment");
struct.add(new ArrayDataType(CharDataType.dataType, 0, -1), "flex", "Flex Comment");
return struct;
}
@ -117,7 +116,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
public void testStructureBitFields() throws Exception {
openStructure(addr(0x1010));
assertMnemonic("Test", addr(0x1010), 0);
assertComponents();
assertComponents("Test");
}
@Test
@ -130,10 +129,10 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
openStructure(addr(0x1010));
assertMnemonic("BitfieldDType", addr(0x1010), 0);
assertComponents();
assertComponents("BitfieldDType");
}
private void assertComponents() {
private void assertComponents(String typeName) {
assertMnemonic("int:3", addr(0x1010), 1);
assertOperand("0h", addr(0x1010), 1);
assertMnemonic("int:24", addr(0x1010), 2);
@ -152,6 +151,10 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
assertOperand("EFh", addr(0x1017), 0);
assertMnemonic("dw", addr(0x1018), 0);
assertOperand("1234h", addr(0x1018), 0);
assertMnemonic("ddw", addr(0x101c), 0);
assertOperand("89ABCDEFh", addr(0x101c), 0);
// flex-array should appear as pre-comment for next code unit
assertPreComment("Zero-length Component: char[0] " + typeName + ".flex", addr(0x1020), 0);
}
private void assertMnemonic(String expectedValue, Address addr, int occurrence) {
@ -164,6 +167,11 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
assertEquals(expectedValue, plugin.getCurrentFieldText());
}
private void assertPreComment(String expectedValue, Address addr, int occurrence) {
plugin.goToField(addr, "Pre-Comment", occurrence, 0, 0);
assertEquals(expectedValue, plugin.getCurrentFieldText());
}
private void openStructure(Address address) {
// open the structure
plugin.goToField(address, "+", 0, 0);
@ -209,14 +217,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
protected DataTypeComponent[] getAllComponents(MemBuffer buf) {
try {
Structure struct = createStructure(dataMgr);
DataTypeComponent[] components = struct.getComponents();
if (struct.hasFlexibleArrayComponent()) {
DataTypeComponent[] newArray = new DataTypeComponent[components.length + 1];
System.arraycopy(components, 0, newArray, 0, components.length);
newArray[components.length] = struct.getFlexibleArrayComponent();
components = newArray;
}
return components;
return struct.getComponents();
}
catch (InvalidDataTypeException e) {
return null; // test should fail as a result

View file

@ -128,6 +128,8 @@ public class DataTypeParserTest extends AbstractEditorTest {
checkValidDt("byte*64*32**16*8");
checkValidDt("byte*8*");
checkValidDt("byte*32*16*32");
checkValidDt("byte[]"); // treated the same as byte[0]
checkValidDt("byte[0]");
checkValidDt("byte[5]");
checkValidDt("byte[22][13]");
checkValidDt("byte*[2]");
@ -141,8 +143,6 @@ public class DataTypeParserTest extends AbstractEditorTest {
checkInvalidDt("aaa*{");
checkInvalidDt("byte*5");
checkInvalidDt("byte*16*[.]");
checkInvalidDt("byte[]");
checkInvalidDt("byte[0]");
checkInvalidDt("*byte");
checkInvalidDt("byte[7]*[12a]");
checkInvalidDt("*");

View file

@ -15,8 +15,7 @@
*/
package ghidra.util.table;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
@ -209,7 +208,7 @@ public class CodeUnitTableCellDataTest extends AbstractProgramBasedTest {
String preview = data.getDisplayString();
// this is the mnemonic and operand inside of the structure at field [2]
assertEquals("ds \"\" (TestStruct.field_0x5)", preview);
assertEquals("ds \"\" (TestStruct.field2_0x5)", preview);
}
@Test

View file

@ -15,8 +15,7 @@
*/
package ghidra.util.table;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
@ -26,27 +25,9 @@ import ghidra.app.util.viewer.field.ArrayElementFieldLocation;
import ghidra.app.util.viewer.field.BrowserCodeUnitFormat;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.CharDataType;
import ghidra.program.model.data.Integer16DataType;
import ghidra.program.model.data.StringDataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.program.model.data.TerminatedStringDataType;
import ghidra.program.model.data.UnicodeDataType;
import ghidra.program.model.listing.CodeUnitFormat;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.Variable;
import ghidra.program.util.AddressFieldLocation;
import ghidra.program.util.BytesFieldLocation;
import ghidra.program.util.FunctionNameFieldLocation;
import ghidra.program.util.LabelFieldLocation;
import ghidra.program.util.MnemonicFieldLocation;
import ghidra.program.util.OperandFieldLocation;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.RepeatableCommentFieldLocation;
import ghidra.program.util.VariableNameFieldLocation;
import ghidra.program.util.XRefFieldLocation;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.util.*;
import ghidra.test.AbstractProgramBasedTest;
import ghidra.test.ClassicSampleX86ProgramBuilder;
@ -204,7 +185,7 @@ public class PreviewTableCellDataTest extends AbstractProgramBasedTest {
String preview = data.getDisplayString();
// this is the mnemonic and operand inside of the structure at field [2]
assertEquals("ds \"\" (TestStruct.field_0x5)", preview);
assertEquals("ds \"\" (TestStruct.field2_0x5)", preview);
}
@Test

View file

@ -36,8 +36,7 @@ import ghidra.program.database.ProgramDB;
import ghidra.program.database.data.DataTypeManagerDB;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.*;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -356,4 +355,22 @@ public class DWARFTestBase extends AbstractGhidraHeadedIntegrationTest {
protected Address addr(long l) {
return space.getAddress(l);
}
protected void assertHasFlexArray(Structure struct) {
DataTypeComponent component = struct.getComponent(struct.getNumComponents() - 1);
assertNotNull(component);
assertEquals(0, component.getLength());
DataType dt = component.getDataType();
assertTrue(dt instanceof Array);
Array a = (Array) dt;
assertEquals(0, a.getNumElements());
}
protected void assertMissingFlexArray(Structure struct) {
DataTypeComponent component = struct.getComponent(struct.getNumComponents() - 1);
if (component == null) {
return;
}
assertNotEquals(0, component.getLength());
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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;
}
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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;
}
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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;
}
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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;
}
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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;
}
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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;
}
}
}

View file

@ -0,0 +1,42 @@
/* ###
* 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.Before;
/**
* This test uses the CParser to parse all datatypes defined by bitfields.h.
* The parse process entails building up the composite types using the various
* "Impl" datatypes followed by their being resolved into the associated datatype
* manager where DB datatypes will be established.
* <br>
* When fetching datatypes from the datatype manager they will naturally be
* returned as DB datatypes when applicable (see {@link #getStructure(String)} and
* {@link #getUnion(String)}). If the test class name contains "Impl" a deep copy
* will be performed on datatypes to return as an non-DB Impl datatype.
*/
public abstract class AbstractCompositeBitFieldTest extends AbstractCompositeTest {
protected static final String C_SOURCE_FILE = "ghidra/app/util/cparser/bitfields.h";
@Override
@Before
public void setUp() throws Exception {
super.setUp();
parseCHeaderFile(C_SOURCE_FILE);
}
}

View file

@ -1,77 +0,0 @@
/* ###
* 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.*;
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;
}
}

View file

@ -0,0 +1,211 @@
/* ###
* 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.*;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import generic.test.AbstractGTest;
import ghidra.app.util.cparser.C.CParser;
import ghidra.app.util.cparser.C.ParseException;
import ghidra.util.Msg;
import resources.ResourceManager;
abstract class AbstractCompositeTest extends AbstractGTest {
private HashMap<Long, DataType> copyMap = new HashMap<>();
private final boolean returnDeepCopyOnQuery;
protected AbstractCompositeTest() {
// If test class name contains "Impl" enable deep copy on query
returnDeepCopyOnQuery = getClass().getSimpleName().contains("Impl");
}
public void setUp() throws Exception {
copyMap.clear();
}
protected void parseCHeaderFile(String headerResourcePath) throws IOException, ParseException {
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 " + headerResourcePath);
CParser parser = new CParser(dataMgr, true, null);
try (InputStream is = ResourceManager.getResourceAsStream(headerResourcePath)) {
if (is == null) {
throw new FileNotFoundException("Resource not found: " + headerResourcePath);
}
// Msg.debug(this, "Parsing C headers from " + headerResourcePath);
parser.parse(is);
}
// uncomment to generate datatype archive
writeArchive(headerResourcePath);
}
private void writeArchive(String headerResourcePath) throws IOException {
URL resource = ResourceManager.getResource(headerResourcePath);
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();
Msg.debug(this, "Saved datatype archive: " + f.getAbsolutePath());
}
protected final DataTypeManager createDataTypeManager(String name, DataOrganization dataOrg) {
return new StandAloneDataTypeManager(name, dataOrg);
}
abstract DataTypeManager getDataTypeManager();
protected Structure getStructure(String name) {
DataTypeManager dtMgr = getDataTypeManager();
DataType dataType = dtMgr.getDataType("/" + name);
assertTrue("Data type not found: " + name, dataType instanceof Structure);
if (returnDeepCopyOnQuery) {
dataType = deepCopy(dataType); // TODO: need deep copy
}
return (Structure) dataType;
}
protected Union getUnion(String name) {
DataTypeManager dtMgr = getDataTypeManager();
DataType dataType = dtMgr.getDataType("/" + name);
assertTrue("Data type not found: " + name, dataType instanceof Union);
if (returnDeepCopyOnQuery) {
dataType = deepCopy(dataType);
}
return (Union) dataType;
}
private void copyCompositeSettings(Composite from, Composite to) {
to.setDescription(from.getDescription());
if (from.hasExplicitPackingValue()) {
to.setExplicitPackingValue(from.getExplicitPackingValue());
}
else if (from.hasDefaultPacking()) {
to.setToDefaultPacking();
}
if (from.hasExplicitMinimumAlignment()) {
to.setExplicitMinimumAlignment(from.getExplicitMinimumAlignment());
}
else if (from.isMachineAligned()) {
to.setToMachineAligned();
}
}
private DataType deepCopy(DataType dt) {
DataTypeManager dtMgr = dt.getDataTypeManager();
long id = dtMgr.getID(dt);
if (id > 0 && copyMap.containsKey(id)) {
return copyMap.get(id);
}
if (dt instanceof Structure) {
Structure s = (Structure) dt;
StructureDataType struct =
new StructureDataType(s.getCategoryPath(), s.getName(), s.getLength(), dtMgr);
copyMap.put(id, struct);
copyCompositeSettings(s, struct);
for (DataTypeComponent dtc : s.getDefinedComponents()) {
if (struct.isPackingEnabled()) {
struct.add(deepCopy(dtc.getDataType()), dtc.getLength(), dtc.getFieldName(),
dtc.getComment());
}
else if (dtc.isBitFieldComponent()) {
BitFieldDataType bf = (BitFieldDataType) dtc.getDataType();
try {
struct.insertBitFieldAt(dtc.getOffset(), dtc.getLength(), bf.getBitOffset(),
bf.getBaseDataType().copy(dtMgr), bf.getDeclaredBitSize(),
dtc.getFieldName(), dtc.getComment());
}
catch (InvalidDataTypeException e) {
failWithException("Unexpected exception", e);
}
}
else {
struct.insertAtOffset(dtc.getOffset(), deepCopy(dtc.getDataType()),
dtc.getLength(), dtc.getFieldName(), dtc.getComment());
}
}
return struct;
}
else if (dt instanceof Union) {
Union u = (Union) dt;
UnionDataType union = new UnionDataType(u.getCategoryPath(), u.getName(), dtMgr);
copyMap.put(id, union);
copyCompositeSettings(u, union);
for (DataTypeComponent dtc : u.getDefinedComponents()) {
union.add(deepCopy(dtc.getDataType()), dtc.getLength(), dtc.getFieldName(),
dtc.getComment());
}
return union;
}
else if (dt instanceof Array) {
Array a = (Array) dt;
a = new ArrayDataType(deepCopy(a.getDataType()), a.getNumElements(),
a.getElementLength(), dtMgr);
copyMap.put(id, a);
return a;
}
else if (dt instanceof Pointer) {
Pointer p = (Pointer) dt;
p = new PointerDataType(deepCopy(p.getDataType()),
p.hasLanguageDependantLength() ? -1 : p.getLength(), dtMgr);
copyMap.put(id, p);
return p;
}
else if (dt instanceof TypeDef) {
TypeDef t = (TypeDef) dt;
t = new TypedefDataType(t.getCategoryPath(), t.getName(), deepCopy(t.getDataType()),
dtMgr);
copyMap.put(id, t);
return t;
}
dt = dt.copy(dtMgr);
copyMap.put(id, dt);
return dt;
}
}

View file

@ -0,0 +1,41 @@
/* ###
* 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.Before;
/**
* This test uses the CParser to parse all datatypes defined by zeroarray.h.
* The parse process entails building up the composite types using the various
* "Impl" datatypes followed by their being resolved into the associated datatype
* manager where DB datatypes will be established.
* <br>
* When fetching datatypes from the datatype manager they will naturally be
* returned as DB datatypes when applicable (see {@link #getStructure(String)} and
* {@link #getUnion(String)}). If the test class name contains "Impl" a deep copy
* will be performed on datatypes to return as an non-DB Impl datatype.
*/
public abstract class AbstractCompositeZeroArrayTest extends AbstractCompositeTest {
protected static final String C_SOURCE_FILE = "ghidra/app/util/cparser/zeroarray.h";
@Override
@Before
public void setUp() throws Exception {
super.setUp();
parseCHeaderFile(C_SOURCE_FILE);
}
}

View file

@ -0,0 +1,20 @@
/* ###
* 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;
public class CompositeImplZeroArrayTest extends CompositeZeroArrayTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -0,0 +1,131 @@
/* ###
* 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 CompositeZeroArrayTest extends AbstractCompositeZeroArrayTest {
// NOTE: In the absence of bit-fields these tests are not sensitive to endianess
private static DataTypeManager dataMgr;
@Override
protected DataTypeManager getDataTypeManager() {
synchronized (CompositeZeroArrayTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testStructureZeroArrayS1() {
Structure struct = getStructure("zeroArrayStruct1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/zeroArrayStruct1\n" +
"pack()\n" +
"Structure zeroArrayStruct1 {\n" +
" 0 int 4 a \"\"\n" +
" 4 char[2] 2 a1 \"\"\n" +
" 6 char[0] 0 x \"\"\n" +
" 8 int[0] 0 y \"\"\n" +
" 8 int 4 b \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureZeroArrayS2() {
Structure struct = getStructure("zeroArrayStruct2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/zeroArrayStruct2\n" +
"pack()\n" +
"Structure zeroArrayStruct2 {\n" +
" 0 int 4 a \"\"\n" +
" 4 char[2] 2 a1 \"\"\n" +
" 6 char[0] 0 x \"\"\n" +
" 8 int[0] 0 y \"\"\n" +
"}\n" +
"Size = 8 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureZeroArrayS3() {
Structure struct = getStructure("zeroArrayStruct3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/zeroArrayStruct3\n" +
"pack()\n" +
"Structure zeroArrayStruct3 {\n" +
" 0 int 4 a \"\"\n" +
" 4 zeroArrayStruct2 8 s \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureZeroArrayU1() {
Union union = getUnion("zeroArrayUnion1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/zeroArrayUnion1\n" +
"pack()\n" +
"Union zeroArrayUnion1 {\n" +
" 0 int 4 a \"\"\n" +
" 0 char[2] 2 a1 \"\"\n" +
" 0 char[0] 0 x \"\"\n" +
" 0 int[0] 0 y \"\"\n" +
" 0 int 4 b \"\"\n" +
"}\n" +
"Size = 4 Actual Alignment = 4", union);
//@formatter:on
}
@Test
public void testStructureZeroArrayU2() {
Union union = getUnion("zeroArrayUnion2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/zeroArrayUnion2\n" +
"pack()\n" +
"Union zeroArrayUnion2 {\n" +
" 0 int 4 a \"\"\n" +
" 0 char[2] 2 a1 \"\"\n" +
" 0 char[0] 0 x \"\"\n" +
" 0 int[0] 0 y \"\"\n" +
"}\n" +
"Size = 4 Actual Alignment = 4", union);
//@formatter:on
}
@Test
public void testStructureZeroArrayU3() {
Union union = getUnion("zeroArrayUnion3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/zeroArrayUnion3\n" +
"pack()\n" +
"Union zeroArrayUnion3 {\n" +
" 0 int 4 a \"\"\n" +
" 0 zeroArrayStruct2 8 s \"\"\n" +
"}\n" +
"Size = 8 Actual Alignment = 4", union);
//@formatter:on
}
}

View file

@ -0,0 +1,829 @@
/* ###
* 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.*;
import org.junit.Test;
public class MSVCStructureBitFieldTest extends AbstractCompositeBitFieldTest {
private static DataTypeManager dataMgr;
@Override
protected DataTypeManager getDataTypeManager() {
synchronized (MSVCStructureBitFieldTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganizationWindows64BitX86(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testStructureBitFieldsA1() {
Structure struct = getStructure("A1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A1\n" +
"pack()\n" +
"Structure A1 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 8 int:3(0) 1 b \"\"\n" +
" 8 int:8(3) 2 c \"\"\n" +
" 9 int:8(3) 2 d \"\"\n" +
" 10 int:6(3) 2 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA2() {
Structure struct = getStructure("A2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A2\n" +
"pack()\n" +
"Structure A2 {\n" +
" 0 oddStruct 5 a \"\"\n" +
" 8 int:3(0) 1 b \"\"\n" +
" 8 int:8(3) 2 c \"\"\n" +
" 9 int:8(3) 2 d \"\"\n" +
" 10 int:6(3) 2 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA3() {
Structure struct = getStructure("A3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A3\n" +
"pack()\n" +
"Structure A3 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 8 int:3(0) 1 b \"\"\n" +
" 8 int:8(3) 2 c \"\"\n" +
" 12 int:85(0) 4 d \"\"\n" +
" 16 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 20 Actual Alignment = 4", struct);
//@formatter:on
DataTypeComponent c = struct.getComponent(3);
assertTrue(c.isBitFieldComponent());
BitFieldDataType bfDt = (BitFieldDataType) c.getDataType();
assertEquals(4, bfDt.getBaseTypeSize());
assertEquals(32, bfDt.getBitSize());
assertEquals(85, bfDt.getDeclaredBitSize());
}
@Test
public void testStructureBitFieldsB1() {
Structure struct = getStructure("B1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
"pack()\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 testStructureBitFieldsB1Flex() {
Structure struct = getStructure("B1flex");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" +
"pack()\n" +
"Structure B1flex {\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" +
" 12 long[0] 0 flex \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\n" +
"Structure Z1 {\n" +
" 0 char 1 a \"\"\n" +
" 2 int:0(0) 0 \"\"\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" +
"pack()\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) 0 \"\"\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" +
"pack()\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" +
" 8 longlong:0(0) 0 \"\"\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" +
"pack()\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) 0 \"\"\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" +
"pack()\n" +
"Structure Z5 {\n" +
" 0 char 1 a \"\"\n" +
" 8 int:0(0) 0 \"\"\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" +
"pack()\n" +
"Structure Z6 {\n" +
" 0 char 1 a \"\"\n" +
" 8 int:0(0) 0 \"\"\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" +
"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" +
"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" +
"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" +
"pack(1)\n" +
"Structure Z1p1 {\n" +
" 0 char 1 a \"\"\n" +
" 1 int:0(0) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
" 8 longlong:0(0) 0 \"\"\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" +
"pack()\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"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" +
"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" +
"pack(2)\n" +
"Structure Z1p2 {\n" +
" 0 char 1 a \"\"\n" +
" 2 int:0(0) 0 \"\"\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" +
"pack(2)\n" +
"Structure Z1p2x {\n" +
" 0 char 1 a \"\"\n" +
" 2 int:0(0) 0 \"\"\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) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
" 8 longlong:0(0) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"pack(2)\n" +
"Structure x3p2 {\n" +
" 0 char 1 a \"\"\n" +
" 2 short:0(0) 0 \"\"\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" +
"pack(2)\n" +
"Structure x4p2 {\n" +
" 0 char 1 a \"\"\n" +
" 2 int:27(0) 4 b \"\"\n" +
" 8 longlong:0(0) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"pack(4)\n" +
"Structure x3p4 {\n" +
" 0 char 1 a \"\"\n" +
" 4 short:0(0) 0 \"\"\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" +
"pack(4)\n" +
"Structure x4p4 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:27(0) 4 b \"\"\n" +
" 8 longlong:0(0) 0 \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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 8 z3p1 \"\"\n" +
"}\n" +
"Size = 42 Actual Alignment = 1", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsS1p2() {
Structure struct = getStructure("S1p2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/S1p2\n" +
"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" +
"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
}
}

View file

@ -15,815 +15,6 @@
*/
package ghidra.program.model.data;
import static org.junit.Assert.*;
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 testStructureBitFieldsA1() {
Structure struct = getStructure("A1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A1\n" +
"pack()\n" +
"Structure A1 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 8 int:3(0) 1 b \"\"\n" +
" 8 int:8(3) 2 c \"\"\n" +
" 9 int:8(3) 2 d \"\"\n" +
" 10 int:6(3) 2 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA2() {
Structure struct = getStructure("A2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A2\n" +
"pack()\n" +
"Structure A2 {\n" +
" 0 oddStruct 5 a \"\"\n" +
" 8 int:3(0) 1 b \"\"\n" +
" 8 int:8(3) 2 c \"\"\n" +
" 9 int:8(3) 2 d \"\"\n" +
" 10 int:6(3) 2 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA3() {
Structure struct = getStructure("A3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A3\n" +
"pack()\n" +
"Structure A3 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 8 int:3(0) 1 b \"\"\n" +
" 8 int:8(3) 2 c \"\"\n" +
" 12 int:85(0) 4 d \"\"\n" +
" 16 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 20 Actual Alignment = 4", struct);
//@formatter:on
DataTypeComponent c = struct.getComponent(3);
assertTrue(c.isBitFieldComponent());
BitFieldDataType bfDt = (BitFieldDataType) c.getDataType();
assertEquals(4, bfDt.getBaseTypeSize());
assertEquals(32, bfDt.getBitSize());
assertEquals(85, bfDt.getDeclaredBitSize());
}
@Test
public void testStructureBitFieldsB1() {
Structure struct = getStructure("B1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
"pack()\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 testStructureBitFieldsB1Flex() {
Structure struct = getStructure("B1flex");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" +
"pack()\n" +
"Structure B1flex {\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" +
" long[0] 0 flex \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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
}
public class MSVCStructureImplBitFieldTest extends MSVCStructureBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -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 MSVCUnionBitFieldTest extends AbstractCompositeBitFieldTest {
private static DataTypeManager dataMgr;
@Override
protected DataTypeManager getDataTypeManager() {
synchronized (MSVCUnionBitFieldTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganizationWindows64BitX86(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testUnionBitFieldsU1() {
Union struct = getUnion("U1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
"pack()\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" +
"pack()\n" +
"Union U1z {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 longlong:0(0) 0 \"\"\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" +
"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" +
"pack(1)\n" +
"Union U1p1z {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 longlong:0(0) 0 \"\"\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" +
"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
}
}

View file

@ -15,94 +15,6 @@
*/
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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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
}
public class MSVCUnionImplBitFieldTest extends MSVCUnionBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -0,0 +1,831 @@
/* ###
* 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.*;
import org.junit.Test;
public class StructureBigEndianBitFieldTest extends AbstractCompositeBitFieldTest {
// NOTE: verified bitfields sample built with mips-elf-gcc (GCC) 4.9.2
private static DataTypeManager dataMgr;
@Override
protected DataTypeManager getDataTypeManager() {
synchronized (StructureBigEndianBitFieldTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testStructureBitFieldsA1() {
Structure struct = getStructure("A1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A1\n" +
"pack()\n" +
"Structure A1 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(5) 1 b \"\"\n" +
" 5 int:8(5) 2 c \"\"\n" +
" 6 int:8(5) 2 d \"\"\n" +
" 8 int:6(2) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA2() {
Structure struct = getStructure("A2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A2\n" +
"pack()\n" +
"Structure A2 {\n" +
" 0 oddStruct 5 a \"\"\n" +
" 5 int:3(5) 1 b \"\"\n" +
" 5 int:8(5) 2 c \"\"\n" +
" 6 int:8(5) 2 d \"\"\n" +
" 8 int:6(2) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA3() {
Structure struct = getStructure("A3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A3\n" +
"pack()\n" +
"Structure A3 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(5) 1 b \"\"\n" +
" 5 int:8(5) 2 c \"\"\n" +
" 8 int:85(0) 4 d \"\"\n" +
" 12 int:6(2) 1 e \"\"\n" +
"}\n" +
"Size = 16 Actual Alignment = 4\n", struct);
//@formatter:on
DataTypeComponent c = struct.getComponent(3);
assertTrue(c.isBitFieldComponent());
BitFieldDataType bfDt = (BitFieldDataType) c.getDataType();
assertEquals(4, bfDt.getBaseTypeSize());
assertEquals(32, bfDt.getBitSize());
assertEquals(85, bfDt.getDeclaredBitSize());
}
@Test
public void testStructureBitFieldsB1() {
Structure struct = getStructure("B1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
"pack()\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 testStructureBitFieldsB1Flex() {
Structure struct = getStructure("B1flex");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" +
"pack()\n" +
"Structure B1flex {\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" +
" 4 long[0] 0 flex \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\n" +
"Structure Z1 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(7) 0 \"\"\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" +
"pack()\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) 0 \"\"\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" +
"pack()\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" +
" 8 longlong:0(7) 0 \"\"\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" +
"pack()\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) 0 \"\"\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" +
"pack()\n" +
"Structure Z5 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(7) 0 \"\"\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" +
"pack()\n" +
"Structure Z6 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(7) 0 \"\"\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" +
"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" +
"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" +
"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" +
"pack(1)\n" +
"Structure Z1p1 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(7) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
" 8 longlong:0(7) 0 \"\"\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" +
"pack()\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"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" +
"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" +
"pack(2)\n" +
"Structure Z1p2 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(7) 0 \"\"\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" +
"pack(2)\n" +
"Structure Z1p2x {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(7) 0 \"\"\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) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
" 8 longlong:0(7) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"pack(2)\n" +
"Structure x3p2 {\n" +
" 0 char 1 a \"\"\n" +
" 2 short:0(7) 0 \"\"\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" +
"pack(2)\n" +
"Structure x4p2 {\n" +
" 0 char 1 a \"\"\n" +
" 1 int:27(5) 4 b \"\"\n" +
" 8 longlong:0(7) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"pack(4)\n" +
"Structure x3p4 {\n" +
" 0 char 1 a \"\"\n" +
" 2 short:0(7) 0 \"\"\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" +
"pack(4)\n" +
"Structure x4p4 {\n" +
" 0 char 1 a \"\"\n" +
" 1 int:27(5) 4 b \"\"\n" +
" 8 longlong:0(7) 0 \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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
}
}

View file

@ -13,18 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*
*/
package ghidra.program.database.data;
package ghidra.program.model.data;
import static org.junit.Assert.*;
import java.util.List;
import org.apache.commons.compress.utils.Sets;
import org.junit.*;
import generic.test.AbstractGTest;
import ghidra.program.model.data.*;
/**
*
@ -45,7 +43,7 @@ public class StructureDataTypeTest extends AbstractGTest {
private void transitionToBigEndian() {
// transition default little-endian structure to big-endian
DataTypeManager beDtm = new MyBigEndianDataTypeManager();
DataTypeManager beDtm = createBigEndianDataTypeManager();
struct = struct.clone(beDtm);
}
@ -69,6 +67,24 @@ public class StructureDataTypeTest extends AbstractGTest {
return new PointerDataType(dataType, length);
}
@Test
public void testEmpty() throws Exception {
Structure s = new StructureDataType("foo", 0);
assertTrue(s.isNotYetDefined());
assertTrue(s.isZeroLength());
assertEquals(0, s.getNumComponents());
assertEquals(0, s.getNumDefinedComponents());
}
@Test
public void testSizeOne() throws Exception {
Structure s = new StructureDataType("foo", 1);
assertFalse(s.isNotYetDefined());
assertFalse(s.isZeroLength());
assertEquals(1, s.getNumComponents());
assertEquals(0, s.getNumDefinedComponents());
}
@Test
public void testAdd() throws Exception {
assertEquals(8, struct.getLength());
@ -84,7 +100,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName());
assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertEquals(null, dtc.getFieldName());
assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -123,7 +139,7 @@ public class StructureDataTypeTest extends AbstractGTest {
DataTypeComponent dtc = struct.getComponent(0);
assertEquals(0, dtc.getOffset());
assertEquals(0, dtc.getOrdinal());
assertEquals("field_0x0", dtc.getDefaultFieldName());
assertEquals("field0_0x0", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertNull(dtc.getComment());
assertEquals(DataType.DEFAULT, dtc.getDataType());
@ -131,7 +147,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName());
assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertEquals(null, dtc.getComment());
@ -147,7 +163,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(11);
assertEquals(11, dtc.getOffset());
assertEquals(11, dtc.getOrdinal());
assertEquals("field_0xb", dtc.getDefaultFieldName());
assertEquals("field11_0xb", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment());
@ -170,7 +186,7 @@ public class StructureDataTypeTest extends AbstractGTest {
DataTypeComponent dtc = struct.getComponent(0);
assertEquals(0, dtc.getOffset());
assertEquals(0, dtc.getOrdinal());
assertEquals("field_0x0", dtc.getDefaultFieldName());
assertEquals("field0_0x0", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertNull(dtc.getComment());
assertEquals(FloatDataType.class, dtc.getDataType().getClass());
@ -185,7 +201,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(2);
assertEquals(5, dtc.getOffset());
assertEquals(2, dtc.getOrdinal());
assertEquals("field_0x5", dtc.getDefaultFieldName());
assertEquals("field2_0x5", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -223,7 +239,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName());
assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -245,7 +261,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(4);
assertEquals(8, dtc.getOffset());
assertEquals(4, dtc.getOrdinal());
assertEquals("field_0x8", dtc.getDefaultFieldName());
assertEquals("field4_0x8", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertEquals(null, dtc.getComment());
assertEquals(FloatDataType.class, dtc.getDataType().getClass());
@ -269,7 +285,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName());
assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -277,7 +293,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(2);
assertEquals(3, dtc.getOffset());
assertEquals(2, dtc.getOrdinal());
assertEquals("field_0x3", dtc.getDefaultFieldName());
assertEquals("field2_0x3", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName());
assertNull(dtc.getComment());
assertEquals(FloatDataType.class, dtc.getDataType().getClass());
@ -380,7 +396,6 @@ public class StructureDataTypeTest extends AbstractGTest {
}
// test inserting at offset 1
@Test
public void testInsertAtOffset2() {
struct.insertAtOffset(2, new FloatDataType(), 4);
@ -408,12 +423,159 @@ public class StructureDataTypeTest extends AbstractGTest {
}
@Test
public void testInsertWithZeroArrayAtOffset() {
struct.insertAtOffset(2, FloatDataType.dataType, -1);
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
struct.insertAtOffset(2, zeroArray, -1);
assertEquals(13, struct.getLength());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(6, comps.length);
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertEquals(ByteDataType.class, comps[0].getDataType().getClass());
assertEquals(2, comps[1].getOffset());
assertEquals(2, comps[1].getOrdinal());
assertTrue(zeroArray.isEquivalent(comps[1].getDataType()));
assertEquals(2, comps[2].getOffset());
assertEquals(3, comps[2].getOrdinal());
assertEquals(FloatDataType.class, comps[2].getDataType().getClass());
assertEquals(6, comps[3].getOffset());
assertEquals(4, comps[3].getOrdinal());
assertEquals(WordDataType.class, comps[3].getDataType().getClass());
assertEquals(8, comps[4].getOffset());
assertEquals(5, comps[4].getOrdinal());
assertEquals(DWordDataType.class, comps[4].getDataType().getClass());
}
@Test
public void testInsertWithZeroArrayAtOffset2() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
struct.insertAtOffset(2, zeroArray, -1);
struct.insertAtOffset(2, FloatDataType.dataType, -1);
assertEquals(13, struct.getLength());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(6, comps.length);
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertEquals(ByteDataType.class, comps[0].getDataType().getClass());
assertEquals(2, comps[1].getOffset());
assertEquals(2, comps[1].getOrdinal());
assertEquals(FloatDataType.class, comps[1].getDataType().getClass());
assertEquals(6, comps[2].getOffset());
assertEquals(3, comps[2].getOrdinal());
assertTrue(zeroArray.isEquivalent(comps[2].getDataType()));
assertEquals(6, comps[3].getOffset());
assertEquals(4, comps[3].getOrdinal());
assertEquals(WordDataType.class, comps[3].getDataType().getClass());
assertEquals(8, comps[4].getOffset());
assertEquals(5, comps[4].getOrdinal());
assertEquals(DWordDataType.class, comps[4].getDataType().getClass());
}
@Test
public void testInsertAtOffsetPastEnd() {
struct.insertAtOffset(100, new FloatDataType(), 4);
assertEquals(104, struct.getLength());
}
@Test
public void testSetFlexArray() throws Exception {
struct.setPackingEnabled(true);
struct.delete(2); // remove dword to verify flex array alignment below
DataTypeComponent flexDtc =
struct.add(new ArrayDataType(CharDataType.dataType, 0, -1), "flex", "FlexComment");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
"pack()\n" +
"Structure TestStruct {\n" +
" 0 byte 1 field1 \"Comment1\"\n" +
" 2 word 2 null \"Comment2\"\n" +
" 4 byte 1 field4 \"Comment4\"\n" +
" 5 char[0] 0 flex \"FlexComment\"\n" +
"}\n" +
"Size = 6 Actual Alignment = 2", struct);
//@formatter:on
struct.replace(flexDtc.getOrdinal(), new ArrayDataType(IntegerDataType.dataType, 0, -1), 0,
"flex", "FlexComment");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
"pack()\n" +
"Structure TestStruct {\n" +
" 0 byte 1 field1 \"Comment1\"\n" +
" 2 word 2 null \"Comment2\"\n" +
" 4 byte 1 field4 \"Comment4\"\n" +
" 8 int[0] 0 flex \"FlexComment\"\n" +
"}\n" +
"Size = 8 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testZeroBitFields() throws Exception {
struct.setPackingEnabled(true);
struct.delete(2); // remove dword to verify flex array alignment below
struct.insertBitField(0, 0, 0, IntegerDataType.dataType, 3, "bf2", "bf1Comment");
struct.insertBitField(0, 0, 0, IntegerDataType.dataType, 3, "bf1", "bf1Comment");
struct.insertBitField(1, 0, 0, IntegerDataType.dataType, 0, "z1", "zero bitfield 1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
"pack()\n" +
"Structure TestStruct {\n" +
" 0 int:3(0) 1 bf1 \"bf1Comment\"\n" +
" 4 int:0(0) 0 \"zero bitfield 1\"\n" +
" 4 int:3(0) 1 bf2 \"bf1Comment\"\n" +
" 5 byte 1 field1 \"Comment1\"\n" +
" 6 word 2 null \"Comment2\"\n" +
" 8 byte 1 field4 \"Comment4\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
struct.insertBitField(2, 0, 0, IntegerDataType.dataType, 0, "z2", "zero bitfield 2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
"pack()\n" +
"Structure TestStruct {\n" +
" 0 int:3(0) 1 bf1 \"bf1Comment\"\n" +
" 4 int:0(0) 0 \"zero bitfield 1\"\n" +
" 4 int:0(0) 0 \"zero bitfield 2\"\n" +
" 4 int:3(0) 1 bf2 \"bf1Comment\"\n" +
" 5 byte 1 field1 \"Comment1\"\n" +
" 6 word 2 null \"Comment2\"\n" +
" 8 byte 1 field4 \"Comment4\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testInsertBitFieldLittleEndianAppend() throws Exception {
@ -752,16 +914,6 @@ public class StructureDataTypeTest extends AbstractGTest {
assertNull(dtc);
}
@Test
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());
@ -1116,6 +1268,46 @@ public class StructureDataTypeTest extends AbstractGTest {
assertEquals(5, comps[1].getOffset());
}
@Test
public void testClearAtOffset() {
assertEquals(8, struct.getLength());
Array zeroArray = new ArrayDataType(CharDataType.dataType, 0, -1);
struct.insertAtOffset(1, zeroArray, -1);
assertEquals(8, struct.getLength());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(5, comps.length);
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertEquals(ByteDataType.class, comps[0].getDataType().getClass());
assertEquals(1, comps[1].getOffset());
assertEquals(1, comps[1].getOrdinal());
assertTrue(zeroArray.isEquivalent(comps[1].getDataType()));
assertEquals(1, comps[2].getOffset());
assertEquals(2, comps[2].getOrdinal());
assertEquals(WordDataType.class, comps[2].getDataType().getClass());
assertEquals(3, comps[3].getOffset());
assertEquals(3, comps[3].getOrdinal());
assertEquals(DWordDataType.class, comps[3].getDataType().getClass());
struct.clearAtOffset(1);
assertEquals(8, struct.getLength());
assertEquals(5, struct.getNumComponents()); // 2 undefined components replaced word
comps = struct.getDefinedComponents();
assertEquals(DWordDataType.class, comps[1].getDataType().getClass());
assertEquals(3, comps[1].getOffset());
assertEquals(3, comps[1].getOrdinal());
}
@Test
public void testDeleteAtOffset() {
struct.deleteAtOffset(2);
@ -1126,6 +1318,41 @@ public class StructureDataTypeTest extends AbstractGTest {
assertEquals(1, comps[1].getOffset());
}
@Test
public void testDeleteAtOffset2() {
assertEquals(8, struct.getLength());
Array zeroArray = new ArrayDataType(CharDataType.dataType, 0, -1);
struct.insertAtOffset(1, zeroArray, -1);
assertEquals(8, struct.getLength());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(5, comps.length);
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertEquals(ByteDataType.class, comps[0].getDataType().getClass());
assertEquals(1, comps[1].getOffset());
assertEquals(1, comps[1].getOrdinal());
assertTrue(zeroArray.isEquivalent(comps[1].getDataType()));
assertEquals(1, comps[2].getOffset());
assertEquals(2, comps[2].getOrdinal());
assertEquals(WordDataType.class, comps[2].getDataType().getClass());
struct.deleteAtOffset(1);
assertEquals(6, struct.getLength());
assertEquals(3, struct.getNumComponents());
comps = struct.getDefinedComponents();
assertEquals(DWordDataType.class, comps[1].getDataType().getClass());
assertEquals(1, comps[1].getOffset());
}
@Test
public void testDeleteComponent() {
Structure s = new StructureDataType("test1", 0);
@ -1250,13 +1477,56 @@ public class StructureDataTypeTest extends AbstractGTest {
}
@Test
public void testGetComponentAt() {
DataTypeComponent dtc = struct.getComponentAt(4);
public void testgetComponentContaining() {
DataTypeComponent dtc = struct.getComponentContaining(4);
assertEquals(DWordDataType.class, dtc.getDataType().getClass());
assertEquals(2, dtc.getOrdinal());
assertEquals(3, dtc.getOffset());
}
@Test
public void testGetComponentsContaining() {
List<DataTypeComponent> components = struct.getComponentsContaining(4);
assertEquals("[ 2 3 dword 4 field3 null]", components.toString());
struct.add(new ArrayDataType(CharDataType.dataType, 0, -1), "zarray1", null);
struct.add(new LongDataType(), "field4", null);
struct.add(new ArrayDataType(LongDataType.dataType, 0, -1), "zarray2", null);
// force components to align
struct.setPackingEnabled(true);
struct.setPackingEnabled(false);
assertEquals(16, struct.getLength());
/**
* /Test
* pack(disabled)
* Structure Test {
* 0 byte 1 field1 "Comment1"
* 2 word 2 null "Comment2"
* 4 dword 4 field3 ""
* 8 byte 1 field4 "Comment4"
* 9 char[0] 0 zarray1 ""
* 12 long 4 field4 ""
* 16 long[0] 0 zarray2 ""
* }
* Size = 16 Actual Alignment = 1
*/
// DatatypeComponent.toString: <ordinal> <offset> <dtname> <length> <fieldname> <comment>
components = struct.getComponentsContaining(9);
assertEquals("[ 5 9 char[0] 0 zarray1 null, 6 9 undefined 1 null null]",
components.toString());
components = struct.getComponentsContaining(10);
assertEquals("[ 7 10 undefined 1 null null]", components.toString());
components = struct.getComponentsContaining(16);
assertEquals("[ 10 16 long[0] 0 zarray2 null]", components.toString());
}
@Test
public void testAddVarLengthDataTypes() {
Structure s1 = createStructure("Test1", 0);
@ -1264,7 +1534,7 @@ public class StructureDataTypeTest extends AbstractGTest {
s1.add(new StringDataType(), 10);
s1.add(new StringDataType(), 15);
DataTypeComponent dtc = s1.getComponentAt(5);
DataTypeComponent dtc = s1.getComponentContaining(5);
DataType dt = dtc.getDataType();
assertEquals(-1, dt.getLength());
assertEquals(10, dtc.getLength());
@ -1273,14 +1543,17 @@ public class StructureDataTypeTest extends AbstractGTest {
}
@Test
public void testReplaceVarLengthDataTypes() {
public void testReplaceAtVarLengthDataTypes() {
// TODO: these tests are too simple since they only replace undefined components
Structure s1 = new StructureDataType("Test1", 25);
s1.replaceAtOffset(0, new StringDataType(), 5, null, null);
s1.replaceAtOffset(5, new StringDataType(), 10, null, null);
s1.replaceAtOffset(15, new StringDataType(), 10, null, null);
DataTypeComponent dtc = s1.getComponentAt(5);
DataTypeComponent dtc = s1.getComponentContaining(5);
DataType dt = dtc.getDataType();
assertEquals(-1, dt.getLength());
assertEquals(10, dtc.getLength());
@ -1288,7 +1561,9 @@ public class StructureDataTypeTest extends AbstractGTest {
}
@Test
public void testReplaceVarLengthDataTypes2() {
public void testReplaceAtVarLengthDataTypes2() {
// TODO: these tests are too simple since they only replace undefined components
Structure s1 = new StructureDataType("Test1", 0x60);
s1.replaceAtOffset(0, new StringDataType(), 0xd, null, null);
@ -1301,17 +1576,153 @@ public class StructureDataTypeTest extends AbstractGTest {
s1.replaceAtOffset(0x48, new StringDataType(), 0xb, null, null);
s1.replaceAtOffset(0x53, new StringDataType(), 0xd, null, null);
DataTypeComponent dtc = s1.getComponentAt(0);
DataTypeComponent dtc = s1.getComponentContaining(0);
DataType dt = dtc.getDataType();
assertEquals("string", dt.getDisplayName());
assertEquals(0xd, dtc.getLength());
dtc = s1.getComponentAt(0x31);
dtc = s1.getComponentContaining(0x31);
dt = dtc.getDataType();
assertEquals("string", dt.getDisplayName());
assertEquals(0xd, dtc.getLength());
}
@Test
public void testReplaceAtPacked() {
struct.setPackingEnabled(true); // test case where there is no component
assertEquals(12, struct.getLength());
assertEquals(4, struct.getNumDefinedComponents());
struct.replaceAtOffset(0, DataType.DEFAULT, -1, "a", null);
struct.replaceAtOffset(1, ByteDataType.dataType, -1, "b", null);
struct.replaceAtOffset(2, ByteDataType.dataType, -1, "c", null);
assertEquals(12, struct.getLength());
assertEquals(5, struct.getNumDefinedComponents());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertTrue(Undefined1DataType.dataType.isEquivalent(comps[0].getDataType()));
assertEquals(1, comps[1].getOffset());
assertEquals(1, comps[1].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[1].getDataType()));
assertEquals(2, comps[2].getOffset());
assertEquals(2, comps[2].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[2].getDataType()));
assertEquals(4, comps[3].getOffset());
assertEquals(3, comps[3].getOrdinal());
assertTrue(DWordDataType.dataType.isEquivalent(comps[3].getDataType()));
assertEquals(8, comps[4].getOffset());
assertEquals(4, comps[4].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[4].getDataType()));
}
@Test
public void testReplaceAt() {
assertEquals(8, struct.getLength());
assertEquals(4, struct.getNumDefinedComponents());
struct.replaceAtOffset(0, DataType.DEFAULT, -1, "a", null);
struct.replaceAtOffset(1, ByteDataType.dataType, -1, "b", null);
struct.replaceAtOffset(2, ByteDataType.dataType, -1, "c", null);
struct.replaceAtOffset(4, CharDataType.dataType, -1, "d", null);
assertEquals(8, struct.getLength());
assertEquals(4, struct.getNumDefinedComponents());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(1, comps[0].getOffset());
assertEquals(1, comps[0].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[0].getDataType()));
assertEquals(2, comps[1].getOffset());
assertEquals(2, comps[1].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[1].getDataType()));
assertEquals(4, comps[2].getOffset());
assertEquals(4, comps[2].getOrdinal());
assertTrue(CharDataType.dataType.isEquivalent(comps[2].getDataType()));
assertEquals(7, comps[3].getOffset());
assertEquals(7, comps[3].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[3].getDataType()));
}
@Test
public void testReplaceAtWithZeroLength() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
struct.insertAtOffset(3, zeroArray, -1);
assertEquals(8, struct.getLength());
assertEquals(5, struct.getNumDefinedComponents());
// replace dword with short
struct.replaceAtOffset(3, ShortDataType.dataType, -1, "b", null);
assertEquals(8, struct.getLength());
assertEquals(5, struct.getNumDefinedComponents());
DataTypeComponent[] comps = struct.getDefinedComponents();
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[0].getDataType()));
assertEquals(1, comps[1].getOffset());
assertEquals(1, comps[1].getOrdinal());
assertTrue(WordDataType.dataType.isEquivalent(comps[1].getDataType()));
assertEquals(3, comps[2].getOffset());
assertEquals(2, comps[2].getOrdinal());
assertTrue(zeroArray.isEquivalent(comps[2].getDataType()));
assertEquals(3, comps[3].getOffset());
assertEquals(3, comps[3].getOrdinal());
assertTrue(ShortDataType.dataType.isEquivalent(comps[3].getDataType()));
assertEquals(7, comps[4].getOffset());
assertEquals(6, comps[4].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[4].getDataType()));
Array zeroArray2 = new ArrayDataType(CharDataType.dataType, 0, -1);
// replace float[0] with char[0]
struct.replaceAtOffset(3, zeroArray2, -1, "a", null);
comps = struct.getDefinedComponents();
assertEquals(0, comps[0].getOffset());
assertEquals(0, comps[0].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[0].getDataType()));
assertEquals(1, comps[1].getOffset());
assertEquals(1, comps[1].getOrdinal());
assertTrue(WordDataType.dataType.isEquivalent(comps[1].getDataType()));
assertEquals(3, comps[2].getOffset());
assertEquals(2, comps[2].getOrdinal());
assertTrue(zeroArray.isEquivalent(comps[2].getDataType()));
assertEquals(3, comps[3].getOffset());
assertEquals(3, comps[3].getOrdinal());
assertTrue(zeroArray2.isEquivalent(comps[3].getDataType()));
assertEquals(7, comps[4].getOffset());
assertEquals(8, comps[4].getOrdinal());
assertTrue(ByteDataType.dataType.isEquivalent(comps[4].getDataType()));
}
@Test
public void testSetName() throws Exception {
Structure s1 = new StructureDataType("Test1", 0);
@ -1345,7 +1756,7 @@ public class StructureDataTypeTest extends AbstractGTest {
s1.add(struct);
s1.add(new ByteDataType());
DataTypeComponent dtc = s1.getComponentAt(7);
DataTypeComponent dtc = s1.getComponentContaining(7);
assertEquals(struct, dtc.getDataType());
dtc = s1.getDataTypeAt(7);
assertEquals(DWordDataType.class, dtc.getDataType().getClass());
@ -1388,7 +1799,7 @@ public class StructureDataTypeTest extends AbstractGTest {
struct.insertBitFieldAt(9, 2, 7, td, 2, "MyBit3", "bitComment3");
struct.growStructure(1);
struct.setFlexibleArrayComponent(td, "myFlex", "flexComment");
struct.add(new ArrayDataType(td, 0, -1), "myFlex", "flexComment");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
@ -1403,12 +1814,12 @@ public class StructureDataTypeTest extends AbstractGTest {
" 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" +
" 12 Foo[0] 0 myFlex \"flexComment\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 1", struct);
//@formatter:on
DataTypeManager beDtm = new MyBigEndianDataTypeManager();
DataTypeManager beDtm = createBigEndianDataTypeManager();
Structure newStruct = new StructureDataType("bigStruct", 0, beDtm);
newStruct.replaceWith(struct);
@ -1428,7 +1839,7 @@ public class StructureDataTypeTest extends AbstractGTest {
" 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" +
" 12 Foo[0] 0 myFlex \"flexComment\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 1", newStruct);
//@formatter:on
@ -1783,13 +2194,10 @@ public class StructureDataTypeTest extends AbstractGTest {
}
}
protected class MyBigEndianDataTypeManager extends StandAloneDataTypeManager {
MyBigEndianDataTypeManager() {
super("BEdtm");
protected DataTypeManager createBigEndianDataTypeManager() {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
dataOrg.setBigEndian(true);
this.dataOrganization = dataOrg;
}
return new StandAloneDataTypeManager("BEdtm", dataOrg);
}
}

View file

@ -15,817 +15,6 @@
*/
package ghidra.program.model.data;
import static org.junit.Assert.*;
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 testStructureBitFieldsA1() {
Structure struct = getStructure("A1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A1\n" +
"pack()\n" +
"Structure A1 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(5) 1 b \"\"\n" +
" 5 int:8(5) 2 c \"\"\n" +
" 6 int:8(5) 2 d \"\"\n" +
" 8 int:6(2) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA2() {
Structure struct = getStructure("A2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A2\n" +
"pack()\n" +
"Structure A2 {\n" +
" 0 oddStruct 5 a \"\"\n" +
" 5 int:3(5) 1 b \"\"\n" +
" 5 int:8(5) 2 c \"\"\n" +
" 6 int:8(5) 2 d \"\"\n" +
" 8 int:6(2) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA3() {
Structure struct = getStructure("A3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A3\n" +
"pack()\n" +
"Structure A3 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(5) 1 b \"\"\n" +
" 5 int:8(5) 2 c \"\"\n" +
" 8 int:85(0) 4 d \"\"\n" +
" 12 int:6(2) 1 e \"\"\n" +
"}\n" +
"Size = 16 Actual Alignment = 4\n", struct);
//@formatter:on
DataTypeComponent c = struct.getComponent(3);
assertTrue(c.isBitFieldComponent());
BitFieldDataType bfDt = (BitFieldDataType) c.getDataType();
assertEquals(4, bfDt.getBaseTypeSize());
assertEquals(32, bfDt.getBitSize());
assertEquals(85, bfDt.getDeclaredBitSize());
}
@Test
public void testStructureBitFieldsB1() {
Structure struct = getStructure("B1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
"pack()\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 testStructureBitFieldsB1Flex() {
Structure struct = getStructure("B1flex");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" +
"pack()\n" +
"Structure B1flex {\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" +
" long[0] 0 flex \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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
}
public class StructureImplBigEndianBitFieldTest extends StructureBigEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -15,871 +15,6 @@
*/
package ghidra.program.model.data;
import static org.junit.Assert.*;
import org.junit.Test;
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 testStructureBitFieldsA1() {
Structure struct = getStructure("A1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A1\n" +
"pack()\n" +
"Structure A1 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(0) 1 b \"\"\n" +
" 5 int:8(3) 2 c \"\"\n" +
" 6 int:8(3) 2 d \"\"\n" +
" 8 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA2() {
Structure struct = getStructure("A2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A2\n" +
"pack()\n" +
"Structure A2 {\n" +
" 0 oddStruct 5 a \"\"\n" +
" 5 int:3(0) 1 b \"\"\n" +
" 5 int:8(3) 2 c \"\"\n" +
" 6 int:8(3) 2 d \"\"\n" +
" 8 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA3() {
Structure struct = getStructure("A3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A3\n" +
"pack()\n" +
"Structure A3 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(0) 1 b \"\"\n" +
" 5 int:8(3) 2 c \"\"\n" +
" 8 int:85(0) 4 d \"\"\n" +
" 12 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 16 Actual Alignment = 4\n", struct);
//@formatter:on
DataTypeComponent c = struct.getComponent(3);
assertTrue(c.isBitFieldComponent());
BitFieldDataType bfDt = (BitFieldDataType) c.getDataType();
assertEquals(4, bfDt.getBaseTypeSize());
assertEquals(32, bfDt.getBitSize());
assertEquals(85, bfDt.getDeclaredBitSize());
}
@Test
public void testStructureBitFieldsB1() {
Structure struct = getStructure("B1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
"pack()\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 testStructureBitFieldsB1Flex() {
Structure struct = getStructure("B1flex");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" +
"pack()\n" +
"Structure B1flex {\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" +
" long[0] 0 flex \"\"\n" +
"}\n" +
"Size = 8 Actual Alignment = 8", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsB2() {
Structure struct = getStructure("B2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B2\n" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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
// }
public class StructureImplLittleEndianBitFieldTest extends StructureLittleEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -0,0 +1,885 @@
/* ###
* 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.*;
import org.junit.Test;
public class StructureLittleEndianBitFieldTest extends AbstractCompositeBitFieldTest {
// 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 (StructureBigEndianBitFieldTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganizationGcc64BitX86(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testStructureBitFieldsA1() {
Structure struct = getStructure("A1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A1\n" +
"pack()\n" +
"Structure A1 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(0) 1 b \"\"\n" +
" 5 int:8(3) 2 c \"\"\n" +
" 6 int:8(3) 2 d \"\"\n" +
" 8 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA2() {
Structure struct = getStructure("A2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A2\n" +
"pack()\n" +
"Structure A2 {\n" +
" 0 oddStruct 5 a \"\"\n" +
" 5 int:3(0) 1 b \"\"\n" +
" 5 int:8(3) 2 c \"\"\n" +
" 6 int:8(3) 2 d \"\"\n" +
" 8 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsA3() {
Structure struct = getStructure("A3");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/A3\n" +
"pack()\n" +
"Structure A3 {\n" +
" 0 char[5] 5 a \"\"\n" +
" 5 int:3(0) 1 b \"\"\n" +
" 5 int:8(3) 2 c \"\"\n" +
" 8 int:85(0) 4 d \"\"\n" +
" 12 int:6(0) 1 e \"\"\n" +
"}\n" +
"Size = 16 Actual Alignment = 4\n", struct);
//@formatter:on
DataTypeComponent c = struct.getComponent(3);
assertTrue(c.isBitFieldComponent());
BitFieldDataType bfDt = (BitFieldDataType) c.getDataType();
assertEquals(4, bfDt.getBaseTypeSize());
assertEquals(32, bfDt.getBitSize());
assertEquals(85, bfDt.getDeclaredBitSize());
}
@Test
public void testStructureBitFieldsB1() {
Structure struct = getStructure("B1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1\n" +
"pack()\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 testStructureBitFieldsB1Flex() {
Structure struct = getStructure("B1flex");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B1flex\n" +
"pack()\n" +
"Structure B1flex {\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" +
" 8 long[0] 0 flex \"\"\n" +
"}\n" +
"Size = 8 Actual Alignment = 8", struct);
//@formatter:on
}
@Test
public void testStructureBitFieldsB2() {
Structure struct = getStructure("B2");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/B2\n" +
"pack()\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" +
"pack()\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" +
"pack()\n" +
"Structure Z1 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(0) 0 \"\"\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" +
"pack()\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) 0 \"\"\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" +
"pack()\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" +
" 8 longlong:0(0) 0 \"\"\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" +
"pack()\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) 0 \"\"\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" +
"pack()\n" +
"Structure Z5 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(0) 0 \"\"\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" +
"pack()\n" +
"Structure Z6 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(0) 0 \"\"\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" +
"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" +
"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" +
"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" +
"pack(1)\n" +
"Structure Z1p1 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(0) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
" 8 longlong:0(0) 0 \"\"\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" +
"pack()\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"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" +
"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" +
"pack(2)\n" +
"Structure Z1p2 {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(0) 0 \"\"\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" +
"pack(2)\n" +
"Structure Z1p2x {\n" +
" 0 char 1 a \"\"\n" +
" 4 int:0(0) 0 \"\"\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) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
" 8 longlong:0(0) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"pack(2)\n" +
"Structure x3p2 {\n" +
" 0 char 1 a \"\"\n" +
" 2 short:0(0) 0 \"\"\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" +
"pack(2)\n" +
"Structure x4p2 {\n" +
" 0 char 1 a \"\"\n" +
" 1 int:27(0) 4 b \"\"\n" +
" 8 longlong:0(0) 0 \"\"\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" +
"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) 0 \"\"\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" +
"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" +
"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" +
"pack(4)\n" +
"Structure x3p4 {\n" +
" 0 char 1 a \"\"\n" +
" 2 short:0(0) 0 \"\"\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" +
"pack(4)\n" +
"Structure x4p4 {\n" +
" 0 char 1 a \"\"\n" +
" 1 int:27(0) 4 b \"\"\n" +
" 8 longlong:0(0) 0 \"\"\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" +
"pack()\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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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" +
"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
// }
}

View file

@ -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 UnionBigEndianBitFieldTest extends AbstractCompositeBitFieldTest {
// NOTE: verified bitfields sample built with mips-elf-gcc (GCC) 4.9.2
private static DataTypeManager dataMgr;
@Override
protected DataTypeManager getDataTypeManager() {
synchronized (StructureBigEndianBitFieldTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganization32BitMips(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testUnionBitFieldsU1() {
Union struct = getUnion("U1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
"pack()\n" +
"Union U1 {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 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" +
"pack()\n" +
"Union U1z {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 longlong:0(7) 0 \"\"\n" + // has no impact
" 0 int:2(6) 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" +
"pack(1)\n" +
"Union U1p1 {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 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" +
"pack(1)\n" +
"Union U1p1z {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 longlong:0(7) 0 \"\"\n" + // has no impact
" 0 int:2(6) 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" +
"pack(2)\n" +
"Union U1p2 {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 2 Actual Alignment = 2", struct);
//@formatter:on
}
}

View file

@ -13,10 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*
*/
package ghidra.program.database.data;
package ghidra.program.model.data;
import static org.junit.Assert.*;
@ -25,7 +22,6 @@ import org.junit.*;
import com.google.common.collect.Sets;
import generic.test.AbstractGTest;
import ghidra.program.model.data.*;
/**
*
@ -46,8 +42,8 @@ public class UnionDataTypeTest extends AbstractGTest {
private void transitionToBigEndian() {
// transition default little-endian structure to big-endian
DataTypeManager beDtm = new MyBigEndianDataTypeManager();
union = (Union) union.clone(beDtm);
DataTypeManager beDtm = createBigEndianDataTypeManager();
union = union.clone(beDtm);
}
private Union createUnion(String name) {
@ -594,12 +590,9 @@ public class UnionDataTypeTest extends AbstractGTest {
}
}
protected class MyBigEndianDataTypeManager extends StandAloneDataTypeManager {
MyBigEndianDataTypeManager() {
super("BEdtm");
protected DataTypeManager createBigEndianDataTypeManager() {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
dataOrg.setBigEndian(true);
this.dataOrganization = dataOrg;
}
return new StandAloneDataTypeManager("BEdtm", dataOrg);
}
}

View file

@ -15,95 +15,6 @@
*/
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" +
"pack()\n" +
"Union U1 {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 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" +
"pack()\n" +
"Union U1z {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 longlong:0(7) 1 \"\"\n" + // has no impact
" 0 int:2(6) 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" +
"pack(1)\n" +
"Union U1p1 {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 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" +
"pack(1)\n" +
"Union U1p1z {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 longlong:0(7) 1 \"\"\n" + // has no impact
" 0 int:2(6) 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" +
"pack(2)\n" +
"Union U1p2 {\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 2 Actual Alignment = 2", struct);
//@formatter:on
}
public class UnionImplBigEndianBitFieldTest extends UnionBigEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -15,95 +15,6 @@
*/
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" +
"pack()\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" +
"pack()\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" +
"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" +
"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" +
"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
}
public class UnionImplLittleEndianBitFieldTest extends UnionLittleEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
}

View file

@ -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 UnionLittleEndianBitFieldTest extends AbstractCompositeBitFieldTest {
// 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 (StructureBigEndianBitFieldTest.class) {
if (dataMgr == null) {
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
DataOrganizationTestUtils.initDataOrganizationGcc64BitX86(dataOrg);
dataMgr = createDataTypeManager("test", dataOrg);
}
return dataMgr;
}
}
@Test
public void testUnionBitFieldsU1() {
Union struct = getUnion("U1");
//@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
"pack()\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" +
"pack()\n" +
"Union U1z {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 longlong:0(0) 0 \"\"\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" +
"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" +
"pack(1)\n" +
"Union U1p1z {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 longlong:0(0) 0 \"\"\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" +
"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
}
}

View file

@ -0,0 +1,60 @@
/* ###
* 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.
*/
// TEMPORARY / TESTING - Zero-length Array Components
// - how should trailing zero-length arrays be handled/defined within structure since they may have an
// offset equal to the length of the structure (current flex array only allows for 1). The last component
// may not remain the last components as components are added. In addition, multiple trailing flex-arrays
// may exist.
struct zeroArrayStruct1 {
int a;
char a1[2];
char x[0];
int y[0];
int b;
};
struct zeroArrayStruct2 {
int a;
char a1[2];
char x[0];
int y[0];
};
struct zeroArrayStruct3 {
int a;
zeroArrayStruct2 s;
};
union zeroArrayUnion1 {
int a;
char a1[2];
char x[0];
int y[0];
int b;
};
union zeroArrayUnion2 {
int a;
char a1[2];
char x[0];
int y[0];
};
union zeroArrayUnion3 {
int a;
zeroArrayStruct2 s;
};

View file

@ -261,6 +261,8 @@ public class EditStructureUtils {
int roomForData = structure.getLength() - endOfDataTypeInStruct;
// FIXME: This will not worked for structures where packing is enabled - not sure how to handle
// if structure isn't defined insert
if (structure.isNotYetDefined()) {
structure.insertAtOffset(offset, dataType, dataTypeLength, fieldName, null);

View file

@ -17,9 +17,11 @@ package ghidra.app.plugin.core.decompile.actions;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.List;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import docking.widgets.OptionDialog;
import ghidra.app.decompiler.ClangFieldToken;
import ghidra.app.decompiler.ClangToken;
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
@ -47,43 +49,6 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
setKeyBindingData(new KeyBindingData(KeyEvent.VK_L, InputEvent.CTRL_DOWN_MASK));
}
/**
* Return the index of the last component that would be overwritten by a new datatype, if we started overwriting
* with at a specific component. All components, except the first, must be undefined datatypes or we return -1
* @param struct is the structure we are testing
* @param comp is the starting component to overwrite
* @param newtype is the datatype to overwrite with
* @return the index of the last component overwritten or -1
*/
private static int getEndComponentIndex(Structure struct, DataTypeComponent comp,
DataType newtype) {
int newlen = newtype.getLength();
if (newlen <= 0) {
return -1; // Don't support variable length types
}
DataType curtype = comp.getDataType();
newlen -= curtype.getLength();
int index = comp.getOrdinal();
while (newlen > 0) {
index += 1;
if (index >= struct.getNumComponents()) {
return -1; // Not enough space in the structure
}
comp = struct.getComponent(index);
// String nm = comp.getFieldName();
// if ((nm !=null)&&(nm.length()!=0))
// return -1;
curtype = comp.getDataType();
// if (!Undefined.isUndefined(curtype))
// return -1; // Overlaps non-undefined datatype
if (curtype != DataType.DEFAULT) {
return -1; // Only allow overwrite of placeholder components
}
newlen -= curtype.getLength();
}
return index;
}
@Override
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
Function function = context.getFunction();
@ -102,6 +67,21 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
return false;
}
private DataTypeComponent getComponentContaining(Structure struct, int offset) {
DataTypeComponent comp = null;
List<DataTypeComponent> components = struct.getComponentsContaining(offset);
if (components != null) {
for (DataTypeComponent c : components) {
// skip components not supported by decompiler
if (c.getLength() != 0) {
comp = c;
break;
}
}
}
return comp;
}
@Override
protected void decompilerActionPerformed(DecompilerActionContext context) {
Program program = context.getProgram();
@ -109,7 +89,6 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
ClangToken tokenAtCursor = context.getTokenAtCursor();
DataTypeManager dataTypeManager = program.getDataTypeManager();
DataType dataType = null;
Structure struct = getStructDataType(tokenAtCursor);
int offset = ((ClangFieldToken) tokenAtCursor).getOffset();
if (struct == null) {
@ -119,64 +98,108 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
}
if (offset < 0 || offset >= struct.getLength()) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Failed to re-type structure: " + struct.getName());
"Failed to re-type structure field at offset " + offset + ": " + struct.getName());
return;
}
DataTypeComponent comp = struct.getComponentAt(offset);
if (comp == null) {
dataType = chooseDataType(tool, program, DataType.DEFAULT);
}
else {
dataType = chooseDataType(tool, program, comp.getDataType());
}
// Get original component and datatype
DataTypeComponent comp = getComponentContaining(struct, offset);
DataType originalDataType = comp != null ? comp.getDataType() : DataType.DEFAULT;
if (originalDataType instanceof BitFieldDataType) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Retype of defind bit-field is not supported.");
return;
}
DataType dataType = chooseDataType(tool, program, originalDataType);
if (dataType == null) {
return; // cancelled
}
// check for permitted datatype
if (dataType instanceof FactoryDataType || dataType.getLength() <= 0) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Retype field with \"" + dataType.getName() + "\" data type is not allowed.");
}
int transaction = program.startTransaction("Retype Structure Field");
try {
dataType = dataTypeManager.resolve(dataType, null);
int newDtLength = dataType.getLength();
if (DataTypeComponent.usesZeroLengthComponent(dataType)) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed", "Retype field with \"" +
dataType.getName() + "\" zero-length component is not allowed.");
}
if (originalDataType != DataType.DEFAULT &&
newDtLength == originalDataType.getLength()) {
// Perform simple 1-for-1 component replacement - this allows to avoid unpack in some cases - assume comp is not null
struct.replace(comp.getOrdinal(), dataType, -1);
return;
}
boolean successfulMod = false;
// check for datatype fit
String fieldName = null;
String comment = null;
int nextOffset;
if (comp == null) {
if (!struct.isNotYetDefined()) {
nextOffset = offset + 1; // assume padding offset within packed structure
}
else {
fieldName = comp.getFieldName();
comment = comp.getComment();
nextOffset = comp.getEndOffset() + 1;
}
int available = nextOffset - offset;
if (newDtLength > available) {
DataTypeComponent nextComp = struct.getDefinedComponentAtOrAfterOffset(nextOffset);
int endOffset = nextComp == null ? struct.getLength() : nextComp.getOffset();
available += endOffset - nextOffset;
if (newDtLength > available) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Could not find component of '" + struct.getName() + "' to retype");
"Failed to re-type structure '" + struct.getName() +
"': Datatype will not fit");
return;
}
// note if we reach here the offset must be zero, so assume we are inserting newtype
int transaction = program.startTransaction("Retype Structure Field");
try {
// Make sure datatype is using the program's data organization before testing fit
if (dataType.getDataTypeManager() != dataTypeManager) {
dataType = dataTypeManager.resolve(dataType, null);
}
struct.insert(0, dataType);
successfulMod = true;
if (struct.isPackingEnabled() && !isAlignmentMaintained(comp, dataType, offset)) {
int choice = OptionDialog.showOptionDialogWithCancelAsDefaultButton(null,
"Disable Structure Packing",
"Containing structure currently has packing enabled. Packing will be disabled if you continue.",
"Continue", OptionDialog.WARNING_MESSAGE);
if (choice != OptionDialog.OPTION_ONE) {
return; // cancelled
}
// alignment is maintained for struct since we do not know the extent of the impact if we change it
int alignment = struct.getAlignment();
struct.setPackingEnabled(false);
struct.setExplicitMinimumAlignment(alignment); // preserve previously computed alignment
}
// The replaceAtOffset will only replace component containing offset plus any subsequent DEFAULT
// components available. Space check is performed prior to any clearing. Zero-length components
// at offset will be ignored.
struct.replaceAtOffset(offset, dataType, -1, fieldName, comment);
}
catch (IllegalArgumentException e) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Failed to re-type structure: " + e.getMessage());
}
finally {
program.endTransaction(transaction, successfulMod);
program.endTransaction(transaction, true);
}
return;
}
int transaction = program.startTransaction("Retype Structure Field");
try {
// Make sure datatype is using the program's data organization before testing fit
if (dataType.getDataTypeManager() != dataTypeManager) {
dataType = dataTypeManager.resolve(dataType, null);
private boolean isAlignmentMaintained(DataTypeComponent comp, DataType dataType, int offset) {
if (comp == null) {
return false;
}
int startind = comp.getOrdinal();
int endind = getEndComponentIndex(struct, comp, dataType);
if (endind < 0) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Failed to re-type structure '" + struct.getName() + "': Datatype did not fit");
return;
}
for (int i = endind; i > startind; --i) { // Clear all but first field
struct.clearComponent(i);
}
struct.replaceAtOffset(comp.getOffset(), dataType, dataType.getLength(),
comp.getFieldName(), comp.getComment());
successfulMod = true;
}
finally {
program.endTransaction(transaction, successfulMod);
int align = comp.getDataType().getAlignment();
if (align != dataType.getAlignment()) {
return false;
}
return (offset % align) == 0;
}
}

View file

@ -265,9 +265,6 @@ public class DataTypeDependencyOrderer {
for (DataTypeComponent dtcomp : dtcomps) {
addDependent(entry, dtcomp.getDataType());
}
if (struct.hasFlexibleArrayComponent()) {
addDependent(entry, struct.getFlexibleArrayComponent().getDataType());
}
}
else if (dataType instanceof Composite) {
DataTypeComponent dtcomps[] = ((Composite) dataType).getComponents();

View file

@ -241,7 +241,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
// included in the length of the structure and must have a properly sized char array
// created immediately following the structure in memory.
struct.setFlexibleArrayComponent(CharDataType.dataType, "name", null);
struct.add(new ArrayDataType(CharDataType.dataType, 0, -1), "name", null);
return MSDataTypeUtils.getMatchingDataType(program, struct);
}
@ -281,8 +281,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
@Override
protected int getDataTypeLength() {
Structure struct = (Structure) getDataType();
DataTypeComponent nameComponent = struct.getFlexibleArrayComponent();
int preNameLength = nameComponent.getOffset();
int preNameLength = struct.getLength();
int totalLength = preNameLength;
// Add the length of the name string too if we can get it.
Address nameAddress = getAddress().add(preNameLength);

View file

@ -384,24 +384,24 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
protected void CheckTypeDefOnStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, null,
CheckStructureData(program, address, expectedName, expectedFieldNames, false,
expectedDtLength, true);
}
protected void CheckStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, null,
CheckStructureData(program, address, expectedName, expectedFieldNames, false,
expectedDtLength, false);
}
protected void CheckStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, String flexArrayName, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, flexArrayName,
String[] expectedFieldNames, boolean lastFieldIsFlexArray, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, lastFieldIsFlexArray,
expectedDtLength, false);
}
protected void CheckStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, String flexArrayName, int expectedDtLength,
String[] expectedFieldNames, boolean lastFieldIsFlexArray, int expectedDtLength,
boolean isTypeDefOfStructure) {
Listing listing = program.getListing();
Data data = listing.getDataAt(addr(program, address));
@ -421,24 +421,22 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
assertEquals("Mismatch in expected structure component count: " + name,
expectedFieldNames.length, structure.getNumComponents());
DataTypeComponent[] components = structure.getComponents();
boolean hasTrailingFlexArray = false;
for (int i = 0; i < components.length; i++) {
assertEquals(
"Expected component " + i + " to be named " + expectedFieldNames[i] + " but was " +
components[i].getFieldName(),
expectedFieldNames[i], components[i].getFieldName());
DataType dt = components[i].getDataType();
hasTrailingFlexArray = (dt instanceof Array) && dt.isZeroLength();
}
if (flexArrayName != null) {
DataTypeComponent flexibleArrayComponent = structure.getFlexibleArrayComponent();
assertNotNull("Structure does not contain flexible array: " + name,
flexibleArrayComponent);
assertEquals(
"Expected flexible array named " + flexArrayName + " but was " +
flexibleArrayComponent.getFieldName(),
flexArrayName, flexibleArrayComponent.getFieldName());
if (lastFieldIsFlexArray) {
assertTrue("Structure does not end with flexible array", hasTrailingFlexArray);
}
else {
assertFalse("Structure contains unexpected flexible array component: " + name,
structure.hasFlexibleArrayComponent());
assertFalse("Structure contains unexpected flexible array component",
hasTrailingFlexArray);
}
}
@ -493,8 +491,9 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
protected void checkTypeDescriptorData(ProgramDB program, long address, int structLength,
int nameArrayLength, String expectedTypeName) {
CheckStructureData(program, address, "TypeDescriptor", new String[] { "pVFTable", "spare" },
"name", structLength);
CheckStructureData(program, address, "TypeDescriptor",
new String[] { "pVFTable", "spare", "name" },
true, structLength);
checkTypeName(program, address, expectedTypeName);
}

View file

@ -234,8 +234,11 @@ public class DefaultCompositeMember extends CompositeMember {
// transform last member into flexible array
Structure struct = (Structure) memberDataType;
Array array = (Array) m.getDataType();
struct.setFlexibleArrayComponent(array.getDataType(), m.getName(), m.memberComment); // use unmodified comment
struct.delete(struct.getNumComponents() - 1);
// TODO: there may be a more direct approach since we now handle zero-length array instantiation
struct.delete(struct.getNumComponents() - 1); // delete placeholder component
struct.insertAtOffset(m.memberOffset,
new ArrayDataType(array.getDataType(), 0, 1, dataTypeManager), 0, m.getName(),
m.memberComment); // use unmodified comment
}
}
@ -286,7 +289,7 @@ public class DefaultCompositeMember extends CompositeMember {
return;
}
DataTypeComponent dtc = struct.getComponentAt(preferredSize);
DataTypeComponent dtc = struct.getComponentContaining(preferredSize);
if (dtc == null) {
return;
}
@ -1010,7 +1013,7 @@ public class DefaultCompositeMember extends CompositeMember {
}
else if (isStructureContainer()) {
Structure struct = (Structure) memberDataType;
// TODO: complicated by bitfields
// TODO: complicated by bitfields where multiple components may occupy same byte
struct.deleteAtOffset(newContainerMember.getOffset());
struct.insertAtOffset(newContainerMember.getOffset(), newContainerMember.getDataType(),
newContainerMember.getLength());

View file

@ -1285,7 +1285,7 @@ public class CppCompositeType {
}
private int getCompositeLength(Composite myComposite) {
if (!myComposite.isNotYetDefined()) {
if (!myComposite.isZeroLength()) {
return myComposite.getLength();
}
return 0;

View file

@ -331,7 +331,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
"pack()\n" +
"Structure struct {\n" +
" 0 char 1 a \"\"\n" +
" char[0] 0 e \"\"\n" +
" 1 char[0] 0 e \"\"\n" +
"}\n" +
"Size = 1 Actual Alignment = 1", struct, true);
//@formatter:on
@ -371,14 +371,14 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
" 0 int 4 a \"\"\n" +
" 4 int 4 b \"\"\n" +
" 8 int 4 c \"\"\n" +
" char[0] 0 d \"\"\n" +
" 12 char[0] 0 d \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4\n" +
"/union/union_s_1\n" +
"pack()\n" +
"Structure union_s_1 {\n" +
" 0 longlong 8 e \"\"\n" +
" char[0] 0 f \"\"\n" +
" 8 char[0] 0 f \"\"\n" +
"}\n" +
"Size = 8 Actual Alignment = 8\n", struct, true);
//@formatter:on
@ -408,7 +408,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
"pack()\n" +
"Union union {\n" +
" 0 union_s_0 12 _s_0 \"\"\n" +
" 0 union_s_1 1 _s_1 \"\"\n" +
" 0 union_s_1 0 _s_1 \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4\n" +
"/union/union_s_0\n" +
@ -417,13 +417,13 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
" 0 int 4 a \"\"\n" +
" 4 int 4 b \"\"\n" +
" 8 int 4 c \"\"\n" +
" char[0] 0 d \"\"\n" +
" 12 char[0] 0 d \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4\n" +
"/union/union_s_1\n" +
"pack()\n" +
"Structure union_s_1 {\n" +
" char[0] 0 f \"\"\n" +
" 0 char[0] 0 f \"\"\n" +
"}\n" +
"Size = 1 Actual Alignment = 1\n", struct, true);
//@formatter:on
@ -459,7 +459,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
"pack()\n" +
"Structure union_s_0 {\n" +
" 0 char 1 a \"\"\n" +
" char[0] 0 flex \"\"\n" +
" 1 char[0] 0 flex \"\"\n" +
"}\n" +
"Size = 1 Actual Alignment = 1\n" +
"/union/union_s_1\n" +
@ -767,7 +767,7 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
"pack()\n" +
"Union MoreComplicated_s_u_44 {\n" +
" 0 MoreComplicated_s_u_44_s_0 12 _s_0 \"\"\n" +
" 0 MoreComplicated_s_u_44_s_1 1 _s_1 \"\"\n" +
" 0 MoreComplicated_s_u_44_s_1 0 _s_1 \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4\n" +
"/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_0\n" +
@ -776,13 +776,13 @@ public class CompositeMemberTest extends AbstractGhidraHeadlessIntegrationTest
" 0 int 4 fromAddress \"\"\n" +
" 4 int 4 toAddress \"\"\n" +
" 8 int 4 seqNum \"\"\n" +
" char[0] 0 data \"\"\n" +
" 12 char[0] 0 data \"\"\n" +
"}\n" +
"Size = 12 Actual Alignment = 4\n" +
"/MoreComplicated_s/MoreComplicated_s_u_44/MoreComplicated_s_u_44_s_1\n" +
"pack()\n" +
"Structure MoreComplicated_s_u_44_s_1 {\n" +
" char[0] 0 buf \"\"\n" +
" 0 char[0] 0 buf \"\"\n" +
"}\n" +
"Size = 1 Actual Alignment = 1\n" +
"/MoreComplicated_s/MoreComplicated_s_u_8\n" +

Some files were not shown because too many files have changed in this diff Show more