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

View file

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

View file

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

View file

@ -85,6 +85,10 @@ public abstract class DBDomainObjectSupport extends DomainObjectAdapterDB {
} }
catch (VersionException e) { catch (VersionException e) {
versionExc = e.combine(versionExc); 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; return null;
} }
} }

View file

@ -373,28 +373,22 @@
<P><IMG alt="Note:" src="../../shared/note.png">The use of bitfield components is not <P><IMG alt="Note:" src="../../shared/note.png">The use of bitfield components is not
currently reflected in decompiler results or assembly markup. </P> currently reflected in decompiler results or assembly markup. </P>
<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 <P>A structure may be defined with zero-element array components, also referred to as a
an unsized array (e.g., char[0]). Such a component, if it exists, is always displayed as the flexible array, which correspond to an unsized array (e.g., char[0]). Such a component
last row within the structure editor with the open edit row for additional components located is created by simply specifying a zero-element array datatype as you would a sized-array component
directly above it. The <I>DataType</I> column for a flexible array always shows (see <A href="#Structure_Editor_Create_FlexArray">Create
the base type of the unsized array which can be modified similar to other components. A Zero-Element / Flexible Array Component</A>).
flexible array is added to the end of a structure by adding a last row specified by the base The resulting component will not consume any space within the structure and will report a component
<I>DataType</I> (e.g. char) size of 0. As such, it may reside at the same offset as a subsequent component and/or may have an offset
then invoking the array action and specifying an element count of 0. Attempting to specify equal to the length of the structure. When packing is enabled such a component may influence the
an element count of 0 is only permitted on the last component row when a flexible array component overall alignment of the structure and its length.
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><IMG alt="Note:" src="../../shared/note.png">The use of flexible array components is not <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 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> 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;"> <DIV style="text-align: center;">
<IMG alt="" src="images/StructureEditorWithFlexArray.png"><BR> <IMG alt="" src="images/StructureEditorWithFlexArray.png"><BR>
<BR> <BR>
@ -415,7 +409,7 @@
<BLOCKQUOTE> <BLOCKQUOTE>
<P>Within a non-packed structure <i>undefined</i> components are inserted before the current selection by clicking the <IMG src= <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 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> on inserted component).</P>
</BLOCKQUOTE> </BLOCKQUOTE>
@ -587,24 +581,14 @@
</BLOCKQUOTE> </BLOCKQUOTE>
<H3><A name="Structure_Editor_Create_FlexArray"></A> <IMG src="images/Array.png" alt="">Create <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> <BLOCKQUOTE>
<P>To create an unsized flexible array as the last structure component (assuming one <P>To create an unsized flexible array component you must use the datatype cell edit feature
is not already defined):</P> 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
<OL> you wish to modify. This may be an existing component or the empty row at the end of the table.
<LI>Add a component whose <I>DataType</I> corresponds to the base type of the unsized array.</LI> See <A href="#Structure_Editor_Editing_DataType">Editing the DataType Field</A> for more details.
<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>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3><A name="Structure_Editor_Unpackage_Component"></A> <IMG src="images/Unpackage.gif" alt=""> <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 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 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> 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= <H3><A name="Structure_Editor_Create_Structure_From_Selection"></A> <IMG src=
"images/cstruct.png" alt=""> Create Structure From Selection</H3> "images/cstruct.png" alt=""> Create Structure From Selection</H3>
@ -778,49 +761,81 @@
session top to bottom in the table.</P> session top to bottom in the table.</P>
</BLOCKQUOTE> </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 <P>To edit the data type double-click the data type cell. This will show the <A href=
type double-click the data type cell. This will show the <A href=
"help/topics/DataTypeEditors/DataTypeSelectionDialog.htm">Data Type Selection Dialog</A>, "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 which allows you to easily enter a data type or select/modify an existing one from one of the open
type, or an array.</P> 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>
<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>Examples of datatypes which may be specified, include:</P>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Basic Data Type</B></P> <P><A name="Structure_Editor_Basic_Data_Type"></A><B>Basic Data Type</B></P>
<P>This can be a built-in data type (Byte, Word, etc.), a structure, a union, or a <P>This can be any fixed-length built-in data type (e.g., byte, word, etc.), structure, union, typedef, or enum.
typedef.</P>
<P><B>Sizable Dynamic Data Type</B></P>
<P>For example, Word.</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><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 <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 with an *.</P> 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><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 <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.</P> 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><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> 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 <H4><A name="EffectOfChangingDataTypeSize"></A> <U>Effect of Changing a Component's
Size</U></H4> Size</U></H4>
<P>A non-packed union's size will always be the size of its largest component. If you <P>A non-packed union's size will always be the size of its largest component. If you
change a data type for a component and the component size changes, the union size will change a data type for a component and the component size changes, the union size will
change if necessary. A packed union is padded to make its size a multiple of the union's change if necessary. A packed union is padded to make its size a multiple of the union's
alignment.<BR> alignment.<BR>
</P> </P>

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 * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.data.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.util.CodeUnitInsertionException; 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 { public class CreateArrayCmd implements Command {
@ -37,9 +37,11 @@ public class CreateArrayCmd implements Command {
/** /**
* Constructs a new command for creating arrays. * Constructs a new command for creating arrays.
* @param addr The address at which to create an array. * @param addr The address at which to create an 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 but a minimum length will apply for all array instances.
* @param dt the dataType of the elements in the array to be created. * @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) { public CreateArrayCmd(Address addr, int numElements, DataType dt, int elementLength) {
this.addr = addr; this.addr = addr;
@ -47,69 +49,47 @@ public class CreateArrayCmd implements Command {
this.dataType = dt; this.dataType = dt;
this.elementLength = elementLength; this.elementLength = elementLength;
} }
/** @Override
*
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
*/
public boolean applyTo(DomainObject obj) { public boolean applyTo(DomainObject obj) {
Program program = (Program)obj; Program program = (Program)obj;
Listing listing = program.getListing(); 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 { try {
endAddr = addr.addNoWrap(length - 1); 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);
listing.createData(addr, adt, adt.getLength());
} catch (AddressOverflowException e1) { } catch (AddressOverflowException e1) {
msg = "Can't create data because length exceeds address space"; msg = "Can't create data because length exceeds address space";
return false; return false;
} }
AddressSet set = new AddressSet(addr, endAddr); catch (IllegalArgumentException | CodeUnitInsertionException e) {
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) {
msg = e.getMessage(); msg = e.getMessage();
return false; return false;
} }
catch (RuntimeException e) {
msg = "Unexpected error: " + e.toString();
Msg.error(this, msg, e);
return false;
}
return true; return true;
} }
@Override
/**
* @see ghidra.framework.cmd.Command#getStatusMsg()
*/
public String getStatusMsg() { public String getStatusMsg() {
return msg; return msg;
} }
/** @Override
* @see ghidra.framework.cmd.Command#getName()
*/
public String getName() { public String getName() {
return "Create Array"; return "Create Array";
} }

View file

@ -20,9 +20,11 @@ import ghidra.framework.model.DomainObject;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.*; 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 { public class CreateArrayInStructureCmd implements Command {
@ -32,14 +34,21 @@ public class CreateArrayInStructureCmd implements Command {
private DataType dataType; private DataType dataType;
private int[] compPath; 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. * 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 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 dt the dataType of the elements in the array to be created.
* @param compPath the component path within the structure at which to create * @param compPath the target component path within the structure of an existing component where
* the array. The component path is an array of integers where each integer * 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. * is a component index of the component above it.
*/ */
public CreateArrayInStructureCmd(Address addr, int numElements, DataType dt, public CreateArrayInStructureCmd(Address addr, int numElements, DataType dt,
int[] compPath) { int[] compPath) {
@ -48,42 +57,18 @@ public class CreateArrayInStructureCmd implements Command {
this.dataType = dt; this.dataType = dt;
this.compPath = compPath; this.compPath = compPath;
} }
/**
* @Override
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
*/
public boolean applyTo(DomainObject obj) { public boolean applyTo(DomainObject obj) {
Program program = (Program)obj; Program program = (Program)obj;
Listing listing = program.getListing(); 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 data = listing.getDataContaining(addr);
Data compData = data.getComponent(compPath); Data compData = data.getComponent(compPath);
if (compData == null) {
int elementLength; msg = "Invalid target component path specified";
if (dataType instanceof Dynamic) {
elementLength = compData.getLength();
}
else {
elementLength = dataType.getLength();
}
if (elementLength <=0) {
msg = "DataType must have fixed size > 0, not "+elementLength;
return false; return false;
} }
int length = numElements*elementLength;
int index = compData.getComponentIndex(); int index = compData.getComponentIndex();
int offset = compData.getParentOffset(); int offset = compData.getParentOffset();
@ -94,23 +79,34 @@ public class CreateArrayInStructureCmd implements Command {
return false; return false;
} }
Structure struct = (Structure)parentDataType; Structure struct = (Structure)parentDataType;
if (offset+length > struct.getLength()) {
msg = "Array too big for structure"; DataType baseDt = dataType;
return false; 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 { try {
ArrayDataType adt = new ArrayDataType(dataType, numElements, dataType.getLength()); 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); clearStruct(struct, compData.getParentOffset(), length);
if (struct.isPackingEnabled()) { if (struct.isPackingEnabled()) {
struct.insert(index, adt, adt.getLength()); struct.insert(index, adt, -1);
} }
else { else {
struct.replace(index, adt, adt.getLength()); struct.replace(index, adt, -1);
} }
} }
catch(Exception e) { catch (RuntimeException e) {
msg = e.getMessage(); msg = "Unexpected error: " + e.toString();
Msg.error(this, msg, e);
return false; return false;
} }
return true; return true;
@ -129,6 +125,7 @@ public class CreateArrayInStructureCmd implements Command {
/** /**
* @see ghidra.framework.cmd.Command#getStatusMsg() * @see ghidra.framework.cmd.Command#getStatusMsg()
*/ */
@Override
public String getStatusMsg() { public String getStatusMsg() {
return msg; return msg;
} }
@ -136,6 +133,7 @@ public class CreateArrayInStructureCmd implements Command {
/** /**
* @see ghidra.framework.cmd.Command#getName() * @see ghidra.framework.cmd.Command#getName()
*/ */
@Override
public String getName() { public String getName() {
return "Create Array"; 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, private void updateStructure(long sourceDtID, Structure sourceDt, Structure destStruct,
Map<Long, DataType> resolvedDataTypes) { Map<Long, DataType> resolvedDataTypes) {
@ -1332,8 +1276,6 @@ public class DataTypeMergeManager implements MergeResolver {
if (!aligned) { if (!aligned) {
adjustStructureSize(destStruct, sourceDt.getLength()); 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) { private static void adjustStructureSize(Structure struct, int preferredSize) {
DataTypeComponent dtc = struct.getComponentAt(preferredSize); DataTypeComponent dtc = struct.getComponentContaining(preferredSize);
if (dtc == null) { if (dtc == null) {
struct.growStructure(preferredSize - struct.getLength()); struct.growStructure(preferredSize - struct.getLength());
return; return;
@ -1895,16 +1837,6 @@ public class DataTypeMergeManager implements MergeResolver {
} }
checkOffsets = true; 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(); 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 info fixup info
* @param struct result structure * @param struct result structure
* @param dt component datatype * @param dt component datatype
@ -2392,35 +2324,15 @@ public class DataTypeMergeManager implements MergeResolver {
*/ */
private boolean fixUpAlignedStructureComponent(FixUpInfo info, Structure struct, DataType dt) { private boolean fixUpAlignedStructureComponent(FixUpInfo info, Structure struct, DataType dt) {
int ordinal = info.index; int ordinal = info.index;
boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE);
DataTypeComponent dtc = null; DataTypeComponent dtc = null;
if (isFlexArrayFixup) { if (ordinal >= 0 || ordinal < struct.getNumComponents()) {
dtc = struct.getFlexibleArrayComponent(); dtc = struct.getComponent(ordinal);
}
else {
if (ordinal >= 0 || ordinal < struct.getNumComponents()) {
dtc = struct.getComponent(ordinal);
}
} }
if (dtc == null) { if (dtc == null) {
return false; return false;
} }
if (isFlexArrayFixup) { if (dtc.isBitFieldComponent()) {
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 (BitFieldDataType.isValidBaseDataType(dt)) { if (BitFieldDataType.isValidBaseDataType(dt)) {
// replace bitfield base datatype - silent if updated type is not a valid base type // replace bitfield base datatype - silent if updated type is not a valid base type
BitFieldDataType bfDt = (BitFieldDataType) dtc.getDataType(); BitFieldDataType bfDt = (BitFieldDataType) dtc.getDataType();
@ -2542,13 +2454,10 @@ public class DataTypeMergeManager implements MergeResolver {
DataType compDt = resolve(info.compID, info.getDataTypeManager(), info.ht); DataType compDt = resolve(info.compID, info.getDataTypeManager(), info.ht);
boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE);
if (compDt != null) { if (compDt != null) {
if (struct.isPackingEnabled() || isFlexArrayFixup) { if (struct.isPackingEnabled()) {
if (!fixUpAlignedStructureComponent(info, struct, compDt)) { if (!fixUpAlignedStructureComponent(info, struct, compDt)) {
String msg = String msg = "component " + info.index;
isFlexArrayFixup ? "flex-array component" : ("component " + info.index);
Msg.warn(this, "Structure Merge: Couldn't get " + msg + " in " + Msg.warn(this, "Structure Merge: Couldn't get " + msg + " in " +
struct.getPathName() + " data type during fix up."); struct.getPathName() + " data type during fix up.");
return false; // Don't remove this FixUpInfo from the fixupList so the user will get notified. 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 // Datatype failed to resolved - check to see if we have a placeholder
else if (isFlexArrayFixup) {
struct.clearFlexibleArrayComponent();
}
else if (struct.isPackingEnabled()) { else if (struct.isPackingEnabled()) {
int ordinal = info.index; int ordinal = info.index;
int numComponents = struct.getNumComponents(); int numComponents = struct.getNumComponents();
@ -3291,7 +3197,7 @@ public class DataTypeMergeManager implements MergeResolver {
if (composite.isPackingEnabled() || (composite instanceof Union)) { if (composite.isPackingEnabled() || (composite instanceof Union)) {
return dtc.getOrdinal(); 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 { private class FixUpInfo {
long id; long id;
long compID; long compID;
int index; int index; // TODO: index as offset could be problematic with shared offset
Map<Long, DataType> ht; Map<Long, DataType> ht;
// bitfield info // bitfield info
@ -3315,7 +3221,6 @@ public class DataTypeMergeManager implements MergeResolver {
* @param compID id of either component or base type * @param compID id of either component or base type
* @param index offset into non-packed structure, or ordinal into union or packed * @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). * 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 * @param resolvedDataTypes hashtable used for resolving the data type
*/ */
FixUpInfo(long id, long compID, int index, FixUpInfo(long id, long compID, int index,

View file

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

View file

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

View file

@ -370,7 +370,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
void init(DataTypeComponent editDtc) { void init(DataTypeComponent editDtc) {
if (editDtc == null || editDtc.isFlexibleArrayComponent()) { if (editDtc == null) {
editMode = EditMode.NONE; editMode = EditMode.NONE;
editOrdinal = -1; editOrdinal = -1;
this.editComponent = null; this.editComponent = null;
@ -401,6 +401,12 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
return false; return false;
} }
return bitFieldAllocation.hasConflict; 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() + String conflictTip = "'" + conflict.getDataType().getDisplayName() +
(conflictName != null ? (" " + conflictName) : "") + "' at offset " + (conflictName != null ? (" " + conflictName) : "") + "' at offset " +
conflict.getOffset(); 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>"; HTMLUtilities.escapeHTML(conflictTip) + "</div>";
} }
return "<HTML><div style=\"text-align:center\">" + HTMLUtilities.escapeHTML(tip) + return "<HTML><div style=\"text-align:center\">" + HTMLUtilities.escapeHTML(tip) +
@ -842,12 +848,22 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
BitFieldPlacement(DataTypeComponent component) { BitFieldPlacement(DataTypeComponent component) {
int startOffset = component.getOffset(); int startOffset = component.getOffset();
int componentLength = component.getLength();
int offsetAdjBytes = startOffset - allocationByteOffset; int offsetAdjBytes = startOffset - allocationByteOffset;
if (!bigEndian) { if (!bigEndian) {
offsetAdjBytes = allocationByteSize - offsetAdjBytes - component.getLength(); offsetAdjBytes = allocationByteSize - offsetAdjBytes - componentLength;
} }
int leftAdj = 8 * offsetAdjBytes; 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(); BitFieldDataType bitfield = (BitFieldDataType) component.getDataType();
int storageSize = 8 * bitfield.getStorageSize(); int storageSize = 8 * bitfield.getStorageSize();
rightBit = leftAdj + storageSize - bitfield.getBitOffset() - 1; rightBit = leftAdj + storageSize - bitfield.getBitOffset() - 1;
@ -855,13 +871,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
// bits stored (NOTE: this may cause a transition from declared to effective // bits stored (NOTE: this may cause a transition from declared to effective
// bit-size when editing a bitfield where the these bit-sizes differ). // bit-size when editing a bitfield where the these bit-sizes differ).
int bitSize = bitfield.getBitSize(); int bitSize = bitfield.getBitSize();
if (bitSize == 0) { leftBit = rightBit - bitSize + 1;
zeroBitField = true;
leftBit = rightBit;
}
else {
leftBit = rightBit - bitSize + 1;
}
} }
else { else {
int componentSize = 8 * component.getLength(); int componentSize = 8 * component.getLength();
@ -1075,7 +1085,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
int allocationEndOffset = offset + allocationBytes - 1; int allocationEndOffset = offset + allocationBytes - 1;
int numComponents = struct.getNumComponents(); int numComponents = struct.getNumComponents();
DataTypeComponent component = struct.getComponentAt(offset); DataTypeComponent component = struct.getDefinedComponentAtOrAfterOffset(offset);
while (component != null) { while (component != null) {
if (component.getOffset() > allocationEndOffset) { if (component.getOffset() > allocationEndOffset) {
break; break;
@ -1149,7 +1159,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
// determine placement attribute index within allocationBytes which // determine placement attribute index within allocationBytes which
// may have been reduced from allocationByteSize based upon visibility. // 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) { if (index >= 0 && index < bitAttributes.length) {
bitAttributes[index] = new BitAttributes(dtc, bitAttributes[index]); bitAttributes[index] = new BitAttributes(dtc, bitAttributes[index]);
} }
@ -1245,11 +1255,11 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
private DataTypeComponent getConflict() { private DataTypeComponent getConflict() {
BitAttributes c = conflict; BitAttributes c = conflict;
while (c != null && c.dtc.isZeroBitFieldComponent()) { while (c != null && c.dtc.getLength() == 0 && c.conflict != null) {
// TODO: improve conflict detection // 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) // offcut with another component (currently ignored)
c = conflict.conflict; c = c.conflict;
} }
// NOTE: DEFAULT undefined datatype can be ignored as conflict // NOTE: DEFAULT undefined datatype can be ignored as conflict
return c != null && c.dtc.getDataType() != DataType.DEFAULT ? c.dtc : null; return c != null && c.dtc.getDataType() != DataType.DEFAULT ? c.dtc : null;
@ -1301,7 +1311,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
} }
else { else {
g.fillRect(rectangle.x, rectangle.y, bitWidth, CELL_HEIGHT); 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); conflict.paint(g, null, false);
} }
} }

View file

@ -536,7 +536,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
if (isEditingField()) { if (isEditingField()) {
endFieldEditing(); endFieldEditing();
} }
checkIsAllowableDataType(datatype, true); checkIsAllowableDataType(datatype);
if (length < 1) { if (length < 1) {
DataTypeInstance dti = DataTypeHelper.getSizedDataType(getProvider(), datatype, DataTypeInstance dti = DataTypeHelper.getSizedDataType(getProvider(), datatype,
lastNumBytes, Integer.MAX_VALUE); lastNumBytes, Integer.MAX_VALUE);
@ -575,7 +575,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
endFieldEditing(); endFieldEditing();
} }
checkIsAllowableDataType(dataType, true); checkIsAllowableDataType(dataType);
insertMultiple(rowIndex, dataType, dtLen, multiple, monitor); insertMultiple(rowIndex, dataType, dtLen, multiple, monitor);
fixSelection(); fixSelection();
componentEdited(); componentEdited();
@ -741,29 +741,23 @@ public abstract class CompEditorModel extends CompositeEditorModel {
return null; return null;
} }
checkIsAllowableDataType(datatype, !oldDtc.isFlexibleArrayComponent()); checkIsAllowableDataType(datatype);
DataTypeComponent dtc; int oldCompSize = oldDtc.getLength();
if (oldDtc.isFlexibleArrayComponent()) { int newCompSize = length;
// flexible array only supports fixed-length types int sizeDiff = newCompSize - oldCompSize;
dtc = replace(rowIndex, datatype);
}
else {
int oldCompSize = oldDtc.getLength();
int newCompSize = length;
int sizeDiff = newCompSize - oldCompSize;
// New one is larger so check to make sure it will fit. // New one is larger so check to make sure it will fit.
if (sizeDiff > 0) { if (sizeDiff > 0) {
if (!checkForReplace(rowIndex, datatype)) { if (!checkForReplace(rowIndex, datatype)) {
throw new InvalidDataTypeException(datatype.getDisplayName() + " doesn't fit."); throw new InvalidDataTypeException(datatype.getDisplayName() + " doesn't fit.");
}
} }
// Replace the component at index.
dtc = replace(rowIndex, datatype, newCompSize, oldDtc.getFieldName(),
oldDtc.getComment());
} }
// Replace the component at index.
DataTypeComponent dtc =
replace(rowIndex, datatype, newCompSize, oldDtc.getFieldName(), oldDtc.getComment());
fixSelection(); fixSelection();
componentEdited(); componentEdited();
selectionChanged(); selectionChanged();
@ -793,11 +787,11 @@ public abstract class CompEditorModel extends CompositeEditorModel {
} }
DataTypeComponent oldDtc = getComponent(startRowIndex); DataTypeComponent oldDtc = getComponent(startRowIndex);
if (oldDtc == null || oldDtc.isFlexibleArrayComponent()) { if (oldDtc == null) {
throw new AssertException(); 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 // 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) { if (dtc == null) {
return false; return false;
} }
if (!isShowingUndefinedBytes() || dtc.isFlexibleArrayComponent()) { if (!isShowingUndefinedBytes()) {
return true; return true;
} }
// Does the new data type fit by replacing the component at index. // 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(); protected abstract void replaceOriginalComponents();
@Override @Override
protected void checkIsAllowableDataType(DataType datatype, boolean dynamicSizingAllowed) protected void checkIsAllowableDataType(DataType datatype)
throws InvalidDataTypeException { throws InvalidDataTypeException {
super.checkIsAllowableDataType(datatype, dynamicSizingAllowed); super.checkIsAllowableDataType(datatype);
// Verify that we aren't adding this structure or anything that it is // Verify that we aren't adding this structure or anything that it is
// part of to this editable structure. // part of to this editable structure.
@ -1021,12 +1015,6 @@ public abstract class CompEditorModel extends CompositeEditorModel {
// Get data type to make into array. // Get data type to make into array.
DataType dt = comp.getDataType(); 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); ArrayDataType array = new ArrayDataType(dt, numElements, comp.getLength(), viewDTM);
if (getNumSelectedComponentRows() > 1) { if (getNumSelectedComponentRows() > 1) {
@ -1244,17 +1232,17 @@ public abstract class CompEditorModel extends CompositeEditorModel {
} }
@Override @Override
public void setComponentDataTypeInstance(int rowIndex, DataTypeInstance dti) public void setComponentDataTypeInstance(int rowIndex, DataType dt, int length)
throws UsrException { throws UsrException {
if (getComponent(rowIndex) == null) { if (getComponent(rowIndex) == null) {
// Replacing data type in unlocked mode replaces only // Replacing data type in unlocked mode replaces only
// that data type and structure size may change. // that data type and structure size may change.
insert(rowIndex, dti.getDataType(), dti.getLength()); insert(rowIndex, dt, length);
} }
else { else {
// Replacing data type in unlocked mode replaces only // Replacing data type in unlocked mode replaces only
// that data type and structure size may change. // 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 @Override
public void setComponentName(int rowIndex, String name) public void setComponentName(int rowIndex, String name)
throws InvalidInputException, InvalidNameException, DuplicateNameException { throws InvalidInputException, InvalidNameException, DuplicateNameException {
if (name.equals("")) {
name = null;
}
if (nameExistsElsewhere(name, rowIndex)) { if (nameExistsElsewhere(name, rowIndex)) {
throw new InvalidNameException("Name \"" + name + "\" already exists."); throw new InvalidNameException("Name \"" + name + "\" already exists.");
} }
try { try {
getComponent(rowIndex).setFieldName(name); getComponent(rowIndex).setFieldName(name); // setFieldName handles trimming
} }
catch (DuplicateNameException exc) { catch (DuplicateNameException exc) {
throw new InvalidNameException(exc.getMessage()); throw new InvalidNameException(exc.getMessage());
@ -1552,9 +1537,6 @@ public abstract class CompEditorModel extends CompositeEditorModel {
if (!isContiguousSelection()) { if (!isContiguousSelection()) {
return 0; return 0;
} }
if (isFlexibleArraySelection()) {
return Integer.MAX_VALUE;
}
int rowIndex = selection.getFieldRange(0).getStart().getIndex().intValue(); int rowIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
if (rowIndex < getNumComponents()) { if (rowIndex < getNumComponents()) {

View file

@ -177,7 +177,13 @@ public class CompEditorPanel extends CompositeEditorPanel {
validate(); validate();
} }
bitViewComponent.init(dtc); 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); sizeTextField.setEditable(editable);
if (editable) { if (editable) {
// editable - use same background as category field // editable - use same background as category field
sizeTextField.setBackground(categoryStatusTextField.getBackground()); sizeTextField.setBackground(descriptionTextField.getBackground());
} }
else { else {
// not editable - use same background as panel // 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(); rowIndex = range.getStart().getIndex().intValue();
} }
boolean dynamicSizingAllowed = true;
DataType currentDt = null; DataType currentDt = null;
DataTypeComponent dtc = getComponent(rowIndex); DataTypeComponent dtc = getComponent(rowIndex);
if (dtc != null) { if (dtc != null) {
dynamicSizingAllowed = !dtc.isFlexibleArrayComponent();
currentDt = dtc.getDataType(); currentDt = dtc.getDataType();
} }
if (!(currentDt instanceof Pointer)) { if (!(currentDt instanceof Pointer)) {
// stacking on pointer allows any data type // stacking on pointer allows any data type
checkIsAllowableDataType(dt, dynamicSizingAllowed); checkIsAllowableDataType(dt);
} }
DataType resultDt = DataUtilities.reconcileAppliedDataType(currentDt, dt, true); DataType resultDt = DataUtilities.reconcileAppliedDataType(currentDt, dt, true);
@ -358,7 +355,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
dtName = previousDt.getDisplayName(); dtName = previousDt.getDisplayName();
} }
DataType newDt = null; DataType newDt = null;
int newLength = 0; int newLength = -1;
if (dataTypeObject instanceof DataTypeInstance) { if (dataTypeObject instanceof DataTypeInstance) {
DataTypeInstance dti = (DataTypeInstance) dataTypeObject; DataTypeInstance dti = (DataTypeInstance) dataTypeObject;
newDt = dti.getDataType(); newDt = dti.getDataType();
@ -381,10 +378,15 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
if (newDt == null) { if (newDt == null) {
return; // Was nothing and is nothing. return; // Was nothing and is nothing.
} }
if (DataTypeComponent.usesZeroLengthComponent(newDt)) {
newLength = 0;
}
checkIsAllowableDataType(newDt, element == null || !element.isFlexibleArrayComponent()); checkIsAllowableDataType(newDt);
newDt = resolveDataType(newDt, viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER); newDt = resolveDataType(newDt, viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
if (newLength < 0) { if (newLength < 0) {
// prefer previous size first // prefer previous size first
int suggestedLength = (previousLength <= 0) ? lastNumBytes : previousLength; int suggestedLength = (previousLength <= 0) ? lastNumBytes : previousLength;
@ -393,22 +395,22 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
if (sizedDataType == null) { if (sizedDataType == null) {
return; return;
} }
newDt = resolveDataType(sizedDataType.getDataType(), viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
newLength = sizedDataType.getLength(); newLength = sizedDataType.getLength();
if (newLength <= 0) {
throw new UsrException("Can't currently add this data type.");
}
} }
if ((previousDt != null) && newDt.isEquivalent(previousDt) && newLength == previousLength) { if ((previousDt != null) && newDt.isEquivalent(previousDt) && newLength == previousLength) {
return; return;
} }
int maxLength = getMaxReplaceLength(rowIndex); int maxLength = getMaxReplaceLength(rowIndex);
if (newLength <= 0) {
throw new UsrException("Can't currently add this data type.");
}
if (maxLength > 0 && newLength > maxLength) { if (maxLength > 0 && newLength > maxLength) {
throw new UsrException(newDt.getDisplayName() + " doesn't fit within " + maxLength + throw new UsrException(newDt.getDisplayName() + " doesn't fit within " + maxLength +
" bytes, need " + newLength + " bytes"); " bytes, need " + newLength + " bytes");
} }
setComponentDataTypeInstance(rowIndex, setComponentDataTypeInstance(rowIndex, newDt, newLength);
DataTypeInstance.getDataTypeInstance(newDt, newLength));
notifyCompositeChanged(); notifyCompositeChanged();
} }
@ -458,10 +460,6 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
int max = getMaxElements(); int max = getMaxElements();
if (isSingleRowSelection()) { if (isSingleRowSelection()) {
if (max != 0) { if (max != 0) {
int currentIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
if (canConvertToFlexibleArray(currentIndex)) {
min = 0; // allow flexible array
}
int initial = getLastNumElements(); int initial = getLastNumElements();
NumberInputDialog numberInputDialog = NumberInputDialog numberInputDialog =
new NumberInputDialog("elements", ((initial > 0) ? initial : 1), min, max); 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) protected void createArray(int numElements)
throws InvalidDataTypeException, DataTypeConflictException, UsrException { throws InvalidDataTypeException, DataTypeConflictException, UsrException {
if (selection.getNumRanges() != 1) { if (selection.getNumRanges() != 1) {
@ -777,6 +761,10 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
*/ */
protected boolean nameExistsElsewhere(String name, int rowIndex) { protected boolean nameExistsElsewhere(String name, int rowIndex) {
if (name != null) { if (name != null) {
name = name.trim();
if (name.length() == 0) {
return false;
}
int numComponents = getNumComponents(); int numComponents = getNumComponents();
for (int i = 0; i < rowIndex && i < numComponents; i++) { for (int i = 0; i < rowIndex && i < numComponents; i++) {
if (name.equals(getComponent(i).getFieldName())) { if (name.equals(getComponent(i).getFieldName())) {
@ -797,12 +785,18 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
* If invalid, an exception will be thrown. * If invalid, an exception will be thrown.
* *
* @param datatype the data type * @param datatype the data type
* @param dynamicSizingAllowed true signals to allow dynamic types
* @throws InvalidDataTypeException if the structure being edited is part * @throws InvalidDataTypeException if the structure being edited is part
* of the data type being inserted or doesn't have a valid size. * 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 { 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) { if (datatype instanceof TypeDef) {
datatype = ((TypeDef) datatype).getBaseDataType(); 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."); "Factory data types are not " + "allowed in a composite data type.");
} }
else if (datatype instanceof Dynamic) { else if (datatype instanceof Dynamic) {
if (!dynamicSizingAllowed) { if (!((Dynamic) datatype).canSpecifyLength()) {
throw new InvalidDataTypeException(
"Dynamic data type is not permitted in current context");
}
else if (!((Dynamic) datatype).canSpecifyLength()) {
throw new InvalidDataTypeException("Non-sizable Dynamic data types are not " + throw new InvalidDataTypeException("Non-sizable Dynamic data types are not " +
"allowed in a composite data type."); "allowed in a composite data type.");
} }
} }
} }
protected boolean allowsZeroLengthComponents() {
return true;
}
protected boolean allowsBitFields() {
return true;
}
@Override @Override
public boolean isAddAllowed(int currentIndex, DataType datatype) { public boolean isAddAllowed(int currentIndex, DataType datatype) {
return false; return false;
@ -1114,7 +1112,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
throw new AssertException("Can't set data type to null."); throw new AssertException("Can't set data type to null.");
} }
checkIsAllowableDataType(newDt, element == null || !element.isFlexibleArrayComponent()); checkIsAllowableDataType(newDt);
newLength = newDt.getLength(); newLength = newDt.getLength();
if (newLength < 0) { 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). * @param composite the composite data type that is being edited. (cannot be null).
*/ */
public CompositeViewerDataTypeManager(String rootName, Composite composite) { public CompositeViewerDataTypeManager(String rootName, Composite composite) {
super(rootName); super(rootName, composite.getDataTypeManager().getDataOrganization());
transactionID = startTransaction(""); transactionID = startTransaction("");
originalDTM = composite.getDataTypeManager(); originalDTM = composite.getDataTypeManager();
universalID = originalDTM.getUniversalID(); // mimic original DTM universalID = originalDTM.getUniversalID(); // mimic original DTM
@ -50,10 +50,4 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
return originalDTM.getType(); 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 * 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 * blank row at the end for selecting. Therefore this number can be
* different than the actual number of components currently in the * different than the actual number of components currently in the
* structure being viewed. In addition, if a flexible array component * structure being viewed.
* 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) ).
* *
* @return the number of rows in the model * @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. * 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 * @return the number of components in the model
*/ */
public int getNumComponents() { public int getNumComponents() {
if (viewComposite == null) { return (viewComposite != null) ? viewComposite.getNumComponents() : 0;
return 0;
}
return viewComposite.getNumComponents();
} }
/** /**
* Return the nth component for the structure being viewed. Since the number of rows * Return the nth component for the structure being viewed. Since the number of rows
* can exceed the number of components defined within the composite * can exceed the number of components defined within the composite
* ({@link Composite#getNumComponents()}) this method will return null for a blank * ({@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 * row.
* structures.
* @param rowIndex the index of the component to return. First component is index of 0. * @param rowIndex the index of the component to return. First component is index of 0.
* @return the component * @return the component
*/ */
@ -588,37 +579,34 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
return ""; return "";
} }
String value; String value;
DataType dt; DataTypeComponent dtc = viewComposite.getComponent(rowIndex);
int dtLen;
if (columnIndex == getOffsetColumn()) { if (columnIndex == getOffsetColumn()) {
int offset = viewComposite.getComponent(rowIndex).getOffset(); int offset = dtc.getOffset();
value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset); value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset);
} }
else if (columnIndex == getLengthColumn()) { else if (columnIndex == getLengthColumn()) {
int length = viewComposite.getComponent(rowIndex).getLength(); int compLen = dtc.getLength();
value = showHexNumbers ? getHexString(length, true) : Integer.toString(length); value = showHexNumbers ? getHexString(compLen, true) : Integer.toString(compLen);
} }
else if (columnIndex == getMnemonicColumn()) { else if (columnIndex == getMnemonicColumn()) {
DataTypeComponent comp = viewComposite.getComponent(rowIndex); DataType dt = dtc.getDataType();
dt = comp.getDataType();
value = dt.getMnemonic(new SettingsImpl()); value = dt.getMnemonic(new SettingsImpl());
int compLen = comp.getLength(); int compLen = dtc.getLength();
dtLen = comp.getDataType().getLength(); int dtLen = dt.isZeroLength() ? 0 : dt.getLength();
if (dtLen > compLen) { if (dtLen > compLen) {
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen; value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
} }
} }
else if (columnIndex == getDataTypeColumn()) { else if (columnIndex == getDataTypeColumn()) {
DataTypeComponent dtc = viewComposite.getComponent(rowIndex); DataType dt = dtc.getDataType();
dt = dtc.getDataType(); int dtLen = dt.getLength();
dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength()); return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength());
} }
else if (columnIndex == getNameColumn()) { else if (columnIndex == getNameColumn()) {
value = viewComposite.getComponent(rowIndex).getFieldName(); value = dtc.getFieldName();
} }
else if (columnIndex == getCommentColumn()) { else if (columnIndex == getCommentColumn()) {
value = viewComposite.getComponent(rowIndex).getComment(); value = dtc.getComment();
} }
else { else {
value = "UNKNOWN"; value = "UNKNOWN";
@ -1173,20 +1161,6 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
return (selection.getNumRanges() == 1); 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 * Returns true if the component list selection is a single component
* @return 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) { if (newDt == null) {
throw new InvalidDataTypeException("valid data-type not specified"); throw new InvalidDataTypeException("valid data-type not specified");
} }
DataTypeComponent element = editModel.getComponent(index); editModel.checkIsAllowableDataType(newDt);
editModel.checkIsAllowableDataType(newDt,
element == null || !element.isFlexibleArrayComponent());
int mrl = editModel.getMaxReplaceLength(index); int mrl = editModel.getMaxReplaceLength(index);
if ((mrl != -1) && (newDt.getLength() > mrl)) { if ((mrl != -1) && (newDt.getLength() > mrl)) {
throw new InvalidDataTypeException(newDt.getDisplayName() + " doesn't fit within " + 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. * Sets the data type for the component at the indicated row index.
* @param rowIndex the row index of the component * @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; throws UsrException;
/** /**

View file

@ -102,10 +102,6 @@ class StructureEditorModel extends CompEditorModel {
public int getRowCount() { public int getRowCount() {
int componentCount = getNumComponents(); int componentCount = getNumComponents();
int rowCount = componentCount + 1; // add blank edit row int rowCount = componentCount + 1; // add blank edit row
Structure viewStruct = (Structure) viewComposite;
if (viewStruct != null && viewStruct.hasFlexibleArrayComponent()) {
++rowCount;
}
return rowCount; return rowCount;
} }
@ -129,7 +125,6 @@ class StructureEditorModel extends CompEditorModel {
} }
DataTypeComponent dtc = getComponent(rowIndex); DataTypeComponent dtc = getComponent(rowIndex);
if (dtc == null) { if (dtc == null) {
if (columnIndex == getDataTypeColumn()) { if (columnIndex == getDataTypeColumn()) {
return null; return null;
@ -137,42 +132,34 @@ class StructureEditorModel extends CompEditorModel {
return ""; return "";
} }
boolean isFlexArrayComponent = dtc.isFlexibleArrayComponent();
String value = null; String value = null;
DataType dt;
int dtLen;
if (columnIndex == getOffsetColumn()) { if (columnIndex == getOffsetColumn()) {
int offset = dtc.getOffset(); int offset = dtc.getOffset();
value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset); value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset);
} }
else if (columnIndex == getLengthColumn()) { else if (columnIndex == getLengthColumn()) {
int length = dtc.getLength(); int compLen = dtc.getLength();
value = showHexNumbers ? getHexString(length, true) : Integer.toString(length); value = showHexNumbers ? getHexString(compLen, true) : Integer.toString(compLen);
} }
else if (columnIndex == getMnemonicColumn()) { else if (columnIndex == getMnemonicColumn()) {
dt = dtc.getDataType(); DataType dt = dtc.getDataType();
value = dt.getMnemonic(new SettingsImpl()); value = dt.getMnemonic(new SettingsImpl());
if (isFlexArrayComponent) { int compLen = dtc.getLength();
value += "[0]"; int dtLen = dt.isZeroLength() ? 0 : dt.getLength();
} if (dtLen > compLen) {
else { value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
int compLen = dtc.getLength();
dtLen = dtc.getDataType().getLength();
if (dtLen > compLen) {
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
}
} }
} }
else if (columnIndex == getDataTypeColumn()) { else if (columnIndex == getDataTypeColumn()) {
dt = dtc.getDataType(); DataType dt = dtc.getDataType();
dtLen = dt.getLength(); int dtLen = dt.getLength();
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength()); return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength());
} }
else if (columnIndex == getNameColumn()) { else if (columnIndex == getNameColumn()) {
value = getComponent(rowIndex).getFieldName(); value = dtc.getFieldName();
} }
else if (columnIndex == getCommentColumn()) { else if (columnIndex == getCommentColumn()) {
value = getComponent(rowIndex).getComment(); value = dtc.getComment();
} }
return (value == null) ? "" : value; return (value == null) ? "" : value;
@ -185,9 +172,6 @@ class StructureEditorModel extends CompEditorModel {
return null; return null;
} }
Structure viewStruct = (Structure) viewComposite; Structure viewStruct = (Structure) viewComposite;
if (rowIndex == (numComponents + 1)) {
return viewStruct.getFlexibleArrayComponent();
}
if (rowIndex > numComponents) { if (rowIndex > numComponents) {
return null; return null;
} }
@ -203,73 +187,48 @@ class StructureEditorModel extends CompEditorModel {
return viewComposite == null ? 0 : viewComposite.getNumComponents(); 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 @Override
protected boolean isSizeEditable() { protected boolean isSizeEditable() {
return !isPackingEnabled(); return !isPackingEnabled();
} }
void setStructureSize(int size) { void setStructureSize(int size) {
if (viewComposite == null) { if (viewComposite == null || viewComposite.isPackingEnabled()) {
return; return;
} }
int currentLength = viewComposite.isZeroLength() ? 0 : viewComposite.getLength(); int currentLength = (viewComposite.isZeroLength()) ? 0 : viewComposite.getLength();
if (currentLength == size) { if (currentLength == size) {
return; return;
} }
Structure structure = (Structure) viewComposite; 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) { if (currentLength < size) {
// Increasing structure length. // Increasing structure length.
structure.growStructure(size - currentLength); 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(); updateAndCheckChangeState();
fireTableDataChanged(); fireTableDataChanged();
} }
@ -292,9 +251,6 @@ class StructureEditorModel extends CompEditorModel {
if (dtc == null) { if (dtc == null) {
return false; return false;
} }
if (dtc.isFlexibleArrayComponent()) {
return true;
}
DataType dt = dtc.getDataType(); DataType dt = dtc.getDataType();
if (dt == DataType.DEFAULT) { if (dt == DataType.DEFAULT) {
return false; return false;
@ -398,12 +354,12 @@ class StructureEditorModel extends CompEditorModel {
} }
DataTypeComponent originalComp = getComponent(index); DataTypeComponent originalComp = getComponent(index);
if (originalComp == null || originalComp.isFlexibleArrayComponent()) { if (originalComp == null) {
throw new IllegalArgumentException("Invalid component index specified"); throw new IllegalArgumentException("Invalid component index specified");
} }
DataType dt = originalComp.getDataType(); DataType dt = originalComp.getDataType();
int dtLen = dt.getLength(); int dtLen = dt.getLength();
checkIsAllowableDataType(dt, true); checkIsAllowableDataType(dt);
int startIndex = index + 1; int startIndex = index + 1;
if (isShowingUndefinedBytes() && (dt != DataType.DEFAULT)) { if (isShowingUndefinedBytes() && (dt != DataType.DEFAULT)) {
@ -570,7 +526,7 @@ class StructureEditorModel extends CompEditorModel {
@Override @Override
public boolean isBitFieldAllowed() { public boolean isBitFieldAllowed() {
return isSingleRowSelection() && !isFlexibleArraySelection(); return isSingleRowSelection();
} }
/** /**
@ -587,7 +543,7 @@ class StructureEditorModel extends CompEditorModel {
FieldRange range = selection.getFieldRange(0); FieldRange range = selection.getFieldRange(0);
DataTypeComponent comp = getComponent(range.getStart().getIndex().intValue()); DataTypeComponent comp = getComponent(range.getStart().getIndex().intValue());
if (comp == null || comp.isFlexibleArrayComponent() || comp.isBitFieldComponent()) { if (comp == null || comp.isBitFieldComponent()) {
return false; return false;
} }
@ -615,29 +571,6 @@ class StructureEditorModel extends CompEditorModel {
return getComponent(rowIndex) != null; 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 @Override
public boolean isDuplicateAllowed() { public boolean isDuplicateAllowed() {
@ -813,7 +746,7 @@ class StructureEditorModel extends CompEditorModel {
} }
try { try {
checkIsAllowableDataType(dataType, !dtc.isFlexibleArrayComponent()); checkIsAllowableDataType(dataType);
} }
catch (InvalidDataTypeException e) { catch (InvalidDataTypeException e) {
return false; return false;
@ -898,9 +831,7 @@ class StructureEditorModel extends CompEditorModel {
else if (comp == null) { else if (comp == null) {
return 0; // No such component. Not at valid edit index. 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. // Otherwise, get size of component and number of Undefined bytes after it.
FieldRange range = getSelectedRangeContaining(currentIndex); FieldRange range = getSelectedRangeContaining(currentIndex);
if (range == null || if (range == null ||
@ -936,28 +867,20 @@ class StructureEditorModel extends CompEditorModel {
@Override @Override
protected DataTypeComponent insert(int rowIndex, DataType dataType, int length, String name, protected DataTypeComponent insert(int rowIndex, DataType dataType, int length, String name,
String comment) throws InvalidDataTypeException { String comment) throws InvalidDataTypeException {
checkIsAllowableDataType(dataType, true); checkIsAllowableDataType(dataType);
try { try {
DataTypeComponent dtc = getComponent(rowIndex); DataTypeComponent dtc;
if (dtc != null && dtc.isFlexibleArrayComponent()) { if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) {
Structure struct = (Structure) viewComposite; dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name, comment);
dtc = struct.setFlexibleArrayComponent(dataType, dtc.getFieldName(),
dtc.getComment());
} }
else { else {
if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) { BitFieldDataType bitfield = (BitFieldDataType) dataType;
dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name, dtc = ((Structure) viewComposite).insertBitField(rowIndex, length,
comment); bitfield.getBitOffset(), bitfield.getBaseDataType(),
} bitfield.getDeclaredBitSize(), name, comment);
else { }
BitFieldDataType bitfield = (BitFieldDataType) dataType; if (rowIndex <= row) {
dtc = ((Structure) viewComposite).insertBitField(rowIndex, length, row++;
bitfield.getBitOffset(), bitfield.getBaseDataType(),
bitfield.getDeclaredBitSize(), name, comment);
}
if (rowIndex <= row) {
row++;
}
} }
adjustSelection(rowIndex, 1); adjustSelection(rowIndex, 1);
// Consume undefined bytes that may have been added, if needed. // Consume undefined bytes that may have been added, if needed.
@ -973,7 +896,7 @@ class StructureEditorModel extends CompEditorModel {
protected void insert(int rowIndex, DataType dataType, int length, int numCopies, protected void insert(int rowIndex, DataType dataType, int length, int numCopies,
TaskMonitor monitor) throws InvalidDataTypeException, CancelledException { TaskMonitor monitor) throws InvalidDataTypeException, CancelledException {
checkIsAllowableDataType(dataType, true); checkIsAllowableDataType(dataType);
int componentOrdinal = convertRowToOrdinal(rowIndex); int componentOrdinal = convertRowToOrdinal(rowIndex);
monitor.initialize(numCopies); monitor.initialize(numCopies);
try { 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 @Override
protected DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name, protected DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name,
String comment) throws InvalidDataTypeException { String comment) throws InvalidDataTypeException {
// It is assumed that the replaced component is not a flexible array checkIsAllowableDataType(dataType);
checkIsAllowableDataType(dataType, true);
try { try {
DataTypeComponent dtc = null; DataTypeComponent dtc = null;
boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex)); boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex));

View file

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

View file

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

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; 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 @Override
public int getAlignment() { public int getAlignment() {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
@ -91,18 +103,11 @@ public abstract class BiDirectionDataType extends StructureDataType
// ignore // ignore
} }
@Override
public DataTypeComponent setFlexibleArrayComponent(DataType flexType, String name,
String comment) {
throw new UnsupportedOperationException(
"BiDirectionDataType.setFlexibleArrayComponent() not implemented.");
}
protected DataTypeComponent getDefinedComponentAt(int offset) { protected DataTypeComponent getDefinedComponentAt(int offset) {
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) { if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
return null; return null;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) { if (index >= 0) {
return components.get(index); return components.get(index);
} }
@ -114,7 +119,7 @@ public abstract class BiDirectionDataType extends StructureDataType
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) { if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
return null; return null;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) { if (index >= 0) {
return components.get(index); return components.get(index);
} }
@ -240,7 +245,7 @@ public abstract class BiDirectionDataType extends StructureDataType
if (ordinal < 0 || ordinal >= numComponents) { if (ordinal < 0 || ordinal >= numComponents) {
throw new IndexOutOfBoundsException(ordinal); 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) { if (idx >= 0) {
return components.get(idx); return components.get(idx);
} }
@ -248,11 +253,11 @@ public abstract class BiDirectionDataType extends StructureDataType
} }
@Override @Override
public DataTypeComponent getComponent(int ordinal) { public DataTypeComponentImpl getComponent(int ordinal) {
if (ordinal < 0 || ordinal >= numComponents) { if (ordinal < 0 || ordinal >= numComponents) {
throw new IndexOutOfBoundsException(ordinal); 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) { if (idx >= 0) {
return components.get(idx); return components.get(idx);
} }
@ -307,7 +312,7 @@ public abstract class BiDirectionDataType extends StructureDataType
checkAncestry(dataType); checkAncestry(dataType);
dataType = dataType.clone(getDataTypeManager()); 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; int additionalShift = 0;
if (index >= 0) { if (index >= 0) {
@ -443,7 +448,7 @@ public abstract class BiDirectionDataType extends StructureDataType
" within a defined component in " + getDisplayName() + "."); " within a defined component in " + getDisplayName() + ".");
} }
else { else {
definedIndex = Collections.binarySearch(components, new Integer(dtc.getOrdinal()), definedIndex = Collections.binarySearch(components, Integer.valueOf(dtc.getOrdinal()),
ordinalComparator); ordinalComparator);
if (definedIndex < 0) { if (definedIndex < 0) {
definedIndex = -definedIndex - 1; definedIndex = -definedIndex - 1;
@ -470,7 +475,7 @@ public abstract class BiDirectionDataType extends StructureDataType
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Offset " + offset + " is not in " + getDisplayName() + "."); "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; int length = 1;
if (index < 0) { if (index < 0) {
@ -485,6 +490,25 @@ public abstract class BiDirectionDataType extends StructureDataType
numComponents--; 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 @Override
public boolean isEquivalent(DataType dataType) { public boolean isEquivalent(DataType dataType) {
if (dataType == this) { if (dataType == this) {
@ -531,19 +555,19 @@ public abstract class BiDirectionDataType extends StructureDataType
public abstract BiDirectionDataType clone(DataTypeManager dtm); public abstract BiDirectionDataType clone(DataTypeManager dtm);
@Override @Override
public void clearComponent(int index) { public void clearComponent(int ordinal) {
if (index < 0 || index >= numComponents) { if (ordinal < 0 || ordinal >= numComponents) {
throw new IndexOutOfBoundsException(index); throw new IndexOutOfBoundsException(ordinal);
} }
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator); int index =
if (idx >= 0) { Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
DataTypeComponent dtc = components.remove(idx); if (index >= 0) {
DataTypeComponent dtc = components.remove(index);
dtc.getDataType().removeParent(this); dtc.getDataType().removeParent(this);
int len = dtc.getLength(); int len = dtc.getLength();
int deltaLength = len - 1;
// int offset = dtc.getOffset();
if (len > 1) { if (len > 1) {
shiftOffsets(idx, deltaLength, 0); int deltaLength = len - 1;
shiftOffsets(index, deltaLength, 0);
numComponents += deltaLength; numComponents += deltaLength;
} }
} }
@ -644,7 +668,8 @@ public abstract class BiDirectionDataType extends StructureDataType
DataTypeComponentImpl newDtc = DataTypeComponentImpl newDtc =
new DataTypeComponentImpl(dataType, this, length, ordinal, newOffset, newName, comment); new DataTypeComponentImpl(dataType, this, length, ordinal, newOffset, newName, comment);
dataType.addParent(this); dataType.addParent(this);
int index = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); int index =
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (index < 0) { if (index < 0) {
index = -index - 1; 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) { void stackChangedExcternally(boolean changed) {
stackChangedExternally = changed; stackChangedExternally = changed;
} }
@ -612,7 +622,7 @@ class StackEditorModel extends CompositeEditorModel {
if (currentIndex < 0 || currentIndex >= getRowCount()) { if (currentIndex < 0 || currentIndex >= getRowCount()) {
return false; return false;
} }
checkIsAllowableDataType(dataType, true); checkIsAllowableDataType(dataType);
} }
catch (InvalidDataTypeException e) { catch (InvalidDataTypeException e) {
return false; return false;
@ -720,7 +730,7 @@ class StackEditorModel extends CompositeEditorModel {
if (currentIndex < 0 || currentIndex >= getRowCount()) { if (currentIndex < 0 || currentIndex >= getRowCount()) {
return false; return false;
} }
checkIsAllowableDataType(dataType, true); checkIsAllowableDataType(dataType);
} }
catch (InvalidDataTypeException e) { catch (InvalidDataTypeException e) {
return false; return false;
@ -788,10 +798,9 @@ class StackEditorModel extends CompositeEditorModel {
} }
@Override @Override
public void setComponentDataTypeInstance(int index, DataTypeInstance dti) throws UsrException { public void setComponentDataTypeInstance(int index, DataType dt, int length) throws UsrException {
DataType dt = dti.getDataType(); checkIsAllowableDataType(dt);
checkIsAllowableDataType(dt, true); ((StackFrameDataType) viewComposite).setDataType(index, dt, length);
((StackFrameDataType) viewComposite).setDataType(index, dt, dti.getLength());
} }
@Override @Override
@ -806,7 +815,7 @@ class StackEditorModel extends CompositeEditorModel {
public void setComponentName(int rowIndex, String newName) public void setComponentName(int rowIndex, String newName)
throws InvalidInputException, InvalidNameException, DuplicateNameException { throws InvalidInputException, InvalidNameException, DuplicateNameException {
if (newName.equals("")) { if (newName.trim().length() == 0) {
newName = null; newName = null;
} }
// if (nameExistsElsewhere(newName, currentIndex)) { // if (nameExistsElsewhere(newName, currentIndex)) {
@ -1330,7 +1339,7 @@ class StackEditorModel extends CompositeEditorModel {
int newLength = newDt.getLength(); int newLength = newDt.getLength();
checkIsAllowableDataType(newDt, true); checkIsAllowableDataType(newDt);
newDt = DataTypeHelper.resolveDataType(newDt, viewDTM, null); newDt = DataTypeHelper.resolveDataType(newDt, viewDTM, null);
int maxLength = getMaxReplaceLength(index); int maxLength = getMaxReplaceLength(index);
if (newLength <= 0) { 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.pcode.Varnode;
import ghidra.program.model.symbol.SymbolUtilities; import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.InvalidNameException; import ghidra.util.InvalidNameException;
import ghidra.util.SystemUtilities;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
@ -410,22 +411,22 @@ public class StackFrameDataType extends BiDirectionDataType {
* *
* @param ordinal the ordinal * @param ordinal the ordinal
* @param name the new name. Null indicates the default name. * @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) { public boolean setName(int ordinal, String name) {
validateName(ordinal, name); validateName(ordinal, name);
DataTypeComponent comp = getComponent(ordinal); DataTypeComponent comp = getComponent(ordinal);
String fieldName = comp.getFieldName(); String fieldName = comp.getFieldName();
if ((name != null) && ((name.length() == 0) || (isDefaultName(name)))) { if (name != null) {
name = null; name = name.trim();
} if (name.length() == 0 || isDefaultName(name)) {
if (name == null) { name = null;
if (fieldName == null) {
return false;
} }
} }
else if (name.equals(fieldName)) { if (SystemUtilities.isEqual(name, fieldName)) {
return false; return false;
} }
DataType dt = comp.getDataType(); DataType dt = comp.getDataType();
int length = comp.getLength(); int length = comp.getLength();
String comment = comp.getComment(); String comment = comp.getComment();

View file

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

View file

@ -223,11 +223,6 @@ public class DWARFDataTypeImporter {
/** /**
* Returns true if the previously imported data type should be reused. * Returns true if the previously imported data type should be reused.
* <p> * <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 * Don't re-use empty structs (isNotYetDefined) to ensure that newer
* definitions of the same struct are given a chance to be resolved() * definitions of the same struct are given a chance to be resolved()
* into the DTM. * into the DTM.
@ -236,10 +231,7 @@ public class DWARFDataTypeImporter {
* @return boolean true if its okay to reuse the data type * @return boolean true if its okay to reuse the data type
*/ */
private boolean shouldReuseAlreadyImportedDT(DataType alreadyImportedDT) { private boolean shouldReuseAlreadyImportedDT(DataType alreadyImportedDT) {
return alreadyImportedDT != null && return alreadyImportedDT != null && !alreadyImportedDT.isNotYetDefined();
!alreadyImportedDT.isNotYetDefined() &&
!(alreadyImportedDT instanceof Array &&
((Array) alreadyImportedDT).getNumElements() == 1);
} }
/* /*
@ -552,12 +544,19 @@ public class DWARFDataTypeImporter {
structSize = 0; structSize = 0;
} }
boolean isUnion = diea.getTag() == DWARFTag.DW_TAG_union_type; boolean isUnion = diea.getTag() == DWARFTag.DW_TAG_union_type;
boolean isDecl = diea.getBool(DWARFAttribute.DW_AT_declaration, false);
DataType struct = DataType struct =
isUnion ? new UnionDataType(dni.getParentCP(), dni.getName(), dataTypeManager) isUnion ? new UnionDataType(dni.getParentCP(), dni.getName(), dataTypeManager)
: new StructureDataType(dni.getParentCP(), dni.getName(), (int) structSize, : new StructureDataType(dni.getParentCP(), dni.getName(), (int) structSize,
dataTypeManager); 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()); DWARFDataType result = new DWARFDataType(struct, dni, diea.getOffset());
result.dsi = DWARFSourceInfo.create(diea); result.dsi = DWARFSourceInfo.create(diea);
@ -719,6 +718,9 @@ public class DWARFDataTypeImporter {
} }
if (union.getLength() < unionSize) { 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 // if the Ghidra union data type is smaller than the DWARF union, pad it out
DataType padding = Undefined.getUndefinedDataType((int) unionSize); DataType padding = Undefined.getUndefinedDataType((int) unionSize);
try { try {
@ -773,11 +775,14 @@ public class DWARFDataTypeImporter {
DataTypeComponent[] definedComponents = structure.getDefinedComponents(); DataTypeComponent[] definedComponents = structure.getDefinedComponents();
for (int i = 0; i < definedComponents.length; i++) { for (int i = 0; i < definedComponents.length; i++) {
DataTypeComponent dtc = definedComponents[i]; DataTypeComponent dtc = definedComponents[i];
DataType dtcDT = dtc.getDataType();
if (dtcDT.isZeroLength()) {
continue;
}
int nextDTCOffset = int nextDTCOffset =
(i < definedComponents.length - 1) ? definedComponents[i + 1].getOffset() (i < definedComponents.length - 1) ? definedComponents[i + 1].getOffset()
: structure.getLength(); : structure.getLength();
int emptySpaceBetween = nextDTCOffset - dtc.getEndOffset(); int emptySpaceBetween = nextDTCOffset - (dtc.getEndOffset() + 1);
DataType dtcDT = dtc.getDataType();
if (dtc.getLength() < dtcDT.getLength() && emptySpaceBetween > 0) { if (dtc.getLength() < dtcDT.getLength() && emptySpaceBetween > 0) {
DataTypeComponent newDTC = structure.replaceAtOffset(dtc.getOffset(), dtcDT, DataTypeComponent newDTC = structure.replaceAtOffset(dtc.getOffset(), dtcDT,
Math.min(nextDTCOffset - dtc.getOffset(), dtc.getDataType().getLength()), Math.min(nextDTCOffset - dtc.getOffset(), dtc.getDataType().getLength()),
@ -802,17 +807,15 @@ public class DWARFDataTypeImporter {
DataTypeComponent[] definedComponents = structure.getDefinedComponents(); DataTypeComponent[] definedComponents = structure.getDefinedComponents();
if (definedComponents.length > 0) { if (definedComponents.length > 0) {
DataTypeComponent lastDTC = definedComponents[definedComponents.length - 1]; 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, private void populateStubStruct_worker(DWARFDataType ddt, StructureDataType structure,
DIEAggregate diea, int childTagType) throws IOException, DWARFExpressionException { DIEAggregate diea, int childTagType) throws IOException, DWARFExpressionException {
Set<Long> conflictingZeroLenFields = getConflictingZeroLenFields(diea, childTagType);
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) { for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
DIEAggregate childDIEA = prog.getAggregate(childEntry); 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) { //if (childDT.getPathName().equals(structure.getPathName()) && childDT != structure) {
// The child we are adding has the exact same fullpath as us. // The child we are adding has the exact same fullpath as us.
// This can happen when DWARF namespace info gets squished and two types // 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? // 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 (isBitField) {
if (isDynamicSizedType) {
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
"dynamic length type", memberName, childDT, memberOffset, bitSize, -1),
"\n");
continue;
}
if (!BitFieldDataType.isValidBaseDataType(childDT.dataType)) { if (!BitFieldDataType.isValidBaseDataType(childDT.dataType)) {
DWARFUtil.appendDescription(structure, DWARFUtil.appendDescription(structure,
memberDesc("Missing member", memberDesc("Missing member",
@ -982,16 +946,14 @@ public class DWARFDataTypeImporter {
} }
else { else {
String memberComment = null; String memberComment = null;
boolean isDynamicSizedType = (childDT.dataType instanceof Dynamic ||
childDT.dataType instanceof FactoryDataType);
if (isDynamicSizedType) { if (isDynamicSizedType) {
memberComment = "Unsupported dynamic size data type: " + childDT.dataType; memberComment = "Unsupported dynamic size data type: " + childDT.dataType;
childDT.dataType = Undefined.getUndefinedDataType(1); childDT.dataType = Undefined.getUndefinedDataType(1);
} }
int childLength = getUnpaddedDataTypeLength(childDT.dataType); int childLength = getUnpaddedDataTypeLength(childDT.dataType);
if (structure.isNotYetDefined() || if (memberOffset + childLength > structure.getLength()) {
(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
DWARFUtil.appendDescription(structure, memberDesc("Missing member", DWARFUtil.appendDescription(structure, memberDesc("Missing member",
"exceeds parent struct len", memberName, childDT, memberOffset, -1, -1), "exceeds parent struct len", memberName, childDT, memberOffset, -1, -1),
"\n"); "\n");
@ -999,21 +961,39 @@ public class DWARFDataTypeImporter {
continue; 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 { try {
DataTypeComponent dtc = structure.replaceAtOffset(memberOffset, DataTypeComponent dtc;
childDT.dataType, childLength, memberName, memberComment); if (DataTypeComponent.usesZeroLengthComponent(childDT.dataType)) {
if (!isUndefinedOrZeroLenAtOffset(structure, memberOffset)) {
// struct.replaceAtOffset() clones the childDT, which will mess up our 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. // identity based mapping in currentImplDataTypeToDDT.
// Update the mapping to prevent that. // Update the mapping to prevent that.
updateMapping(childDT.dataType, dtc.getDataType()); updateMapping(childDT.dataType, dtc.getDataType());
@ -1030,72 +1010,29 @@ public class DWARFDataTypeImporter {
} }
} }
private Set<Long> getConflictingZeroLenFields(DIEAggregate diea, int childTagType) private boolean isUndefinedOrZeroLenAtOffset(Structure struct, int offset) {
throws IOException, DWARFExpressionException { List<DataTypeComponent> compsAt = struct.getComponentsContaining(offset);
// Returns a set of DIE offsets of zero len fields that are fighting for DataTypeComponent lastComp = !compsAt.isEmpty() ? compsAt.get(compsAt.size() - 1) : null;
// the same offset in the parent struct if (lastComp == null) {
Map<Integer, Set<Long>> zeroLenMembers = new HashMap<>(); // only triggered if offset == length of struct, which is okay since we are adding
// a zero-length component to the struct
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) { return true;
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;
}
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;
}
}
} }
if (lastComp.getOffset() != offset) {
Set<Long> conflictingZeroLenFields = new HashSet<>(); return false;
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; DataType dt = lastComp.getDataType();
return dt.isZeroLength() || dt instanceof DefaultDataType;
}
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;
}
return lastComp.getOrdinal();
} }
private static String memberDesc(String prefix, String errorStr, String memberName, private static String memberDesc(String prefix, String errorStr, String memberName,
@ -1120,7 +1057,6 @@ public class DWARFDataTypeImporter {
throws IOException, DWARFExpressionException { throws IOException, DWARFExpressionException {
DWARFDataType elementType = getDataType(diea.getTypeRef(), voidDDT); DWARFDataType elementType = getDataType(diea.getTypeRef(), voidDDT);
// do a second query to see if there was a recursive loop in the call above back // 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. // to this datatype that resulted in this datatype being created.
// Use that instance if possible. // Use that instance if possible.
@ -1132,7 +1068,6 @@ public class DWARFDataTypeImporter {
// Build a list of the defined dimensions for this array type. // 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) // The first element in the DWARF dimension list would be where a wild-card (-1 length)
// dimension would be defined. // dimension would be defined.
boolean isEmptyArray = false;
List<Integer> dimensions = new ArrayList<>(); List<Integer> dimensions = new ArrayList<>();
List<DebugInfoEntry> subrangeDIEs = List<DebugInfoEntry> subrangeDIEs =
diea.getHeadFragment().getChildren(DWARFTag.DW_TAG_subrange_type); diea.getHeadFragment().getChildren(DWARFTag.DW_TAG_subrange_type);
@ -1146,17 +1081,14 @@ public class DWARFDataTypeImporter {
} }
// Otherwise check for an upper bound // Otherwise check for an upper bound
else if (subrangeAggr.hasAttribute(DWARFAttribute.DW_AT_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 = long upperBound =
subrangeAggr.parseUnsignedLong(DWARFAttribute.DW_AT_upper_bound, 0xbadbeef); subrangeAggr.parseUnsignedLong(DWARFAttribute.DW_AT_upper_bound, 0xbadbeef);
// fix special flag values used by DWARF to indicate that the array dimension // 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 // is unknown. 64bit 0xffffff...s and 32bit 0xffff..s will
// be forced to -1. // be forced to 0.
if (upperBound == 0xFF_FF_FF_FFL /* ie. max uint32 */ || upperBound == -1) { if (upperBound == 0xFF_FF_FF_FFL /* ie. max uint32 */ || upperBound == -1) {
upperBound = -1; upperBound = 0;
} }
else { else {
numElements = upperBound + 1; numElements = upperBound + 1;
@ -1169,28 +1101,7 @@ public class DWARFDataTypeImporter {
} }
if (numElements == -1) { if (numElements == -1) {
// if numElements is the DWARF special flag value for unknown, set flag numElements = 0;
// 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;
} }
else if (numElements > Integer.MAX_VALUE) { else if (numElements > Integer.MAX_VALUE) {
Msg.error(this, "Bad value [" + numElements + "] for array's size in DIE: " + 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--) { for (int i = dimensions.size() - 1; i >= 0; i--) {
int numElements = dimensions.get(i); int numElements = dimensions.get(i);
ArrayDataType subArray = ArrayDataType subArray =
new ArrayDataType(dt, numElements, dt.getLength(), dataTypeManager); new ArrayDataType(dt, numElements, -1, dataTypeManager);
if (dt == elementType.dataType) { if (dt == elementType.dataType) {
updateMapping(dt, subArray.getDataType()); updateMapping(dt, subArray.getDataType());
} }
@ -1213,7 +1124,6 @@ public class DWARFDataTypeImporter {
} }
DWARFDataType result = new DWARFDataType(dt, null, diea.getOffset()); DWARFDataType result = new DWARFDataType(dt, null, diea.getOffset());
result.isEmptyArrayType = isEmptyArray;
return result; return result;
} }
@ -1445,7 +1355,6 @@ public class DWARFDataTypeImporter {
static class DWARFDataType { static class DWARFDataType {
DataType dataType; DataType dataType;
boolean isEmptyArrayType;
DWARFNameInfo dni; DWARFNameInfo dni;
DWARFSourceInfo dsi; DWARFSourceInfo dsi;
Set<Long> offsets = new HashSet<>(); Set<Long> offsets = new HashSet<>();
@ -1473,12 +1382,5 @@ public class DWARFDataTypeImporter {
Collectors.joining(",")); 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.*;
import ghidra.app.util.bin.format.dwarf4.encoding.*; import ghidra.app.util.bin.format.dwarf4.encoding.*;
import ghidra.app.util.bin.format.dwarf4.expression.*; import ghidra.app.util.bin.format.dwarf4.expression.*;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.database.function.OverlappingFunctionException; import ghidra.program.database.function.OverlappingFunctionException;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet; import ghidra.program.model.address.AddressSet;
@ -258,6 +259,19 @@ public class DWARFFunctionImporter {
DWARFTag.DW_TAG_formal_parameter)) { DWARFTag.DW_TAG_formal_parameter)) {
DIEAggregate childDIEA = prog.getAggregate(childEntry); 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); Parameter formalParam = createFormalParameter(childDIEA);
if (formalParam == null) { if (formalParam == null) {
skipFuncSignature = true; skipFuncSignature = true;
@ -581,27 +595,7 @@ public class DWARFFunctionImporter {
} }
} }
else if (exprEvaluator.getLastRegister() == null) { else if (exprEvaluator.getLastRegister() == null) {
dvar.dni = dvar.dni.replaceType(null /*nothing matches static global var*/); processStaticVar(res, dvar, diea);
if (res != 0) {
// If the expression evaluated to a static address other than '0'
Address staticVariableAddress = toAddr(res + prog.getProgramBaseAddressFixup());
if (variablesProcesesed.contains(staticVariableAddress)) {
return null;
}
boolean external = diea.getBool(DWARFAttribute.DW_AT_external, false);
outputGlobal(staticVariableAddress, dvar.type, external,
DWARFSourceInfo.create(diea), dvar.dni);
}
else {
// If the expression evaluated to a static address of '0'.
// This case is probably caused by relocation fixups not being applied to the
// .debug_info section.
importSummary.relocationErrorVarDefs.add(
dvar.dni.getNamespacePath().asFormattedString() + " : " +
dvar.type.getPathName());
}
return null;// Don't return the variable to be associated with the function return null;// Don't return the variable to be associated with the function
} }
else { else {
@ -615,6 +609,61 @@ public class DWARFFunctionImporter {
return dvar; 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);
outputGlobal(staticVariableAddress, dvar.type, external,
DWARFSourceInfo.create(diea), dvar.dni);
}
else {
// If the expression evaluated to a static address of '0'.
// This case is probably caused by relocation fixups not being applied to the
// .debug_info section.
importSummary.relocationErrorVarDefs.add(
dvar.dni.getNamespacePath().asFormattedString() + " : " +
dvar.type.getPathName());
}
}
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);
}
private boolean isZeroByteDataType(DataType dt) {
if (!dt.isZeroLength() && dt instanceof Array) {
dt = DataTypeUtilities.getArrayBaseDataType((Array) dt);
}
return dt.isZeroLength();
}
/** /**
* Process lexical block entries. * Process lexical block entries.
* *

View file

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

View file

@ -43,17 +43,8 @@ public class CompositeHandler {
if (dec == null || dec.getDataType() == null) { if (dec == null || dec.getDataType() == null) {
return; 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 // not a bitfield, just add the data type to composite
if (!dec.isBitField()) { 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()); parent.add(dec.getDataType(), dec.getName(), dec.getComment());
return; return;
} }

View file

@ -27,7 +27,6 @@ public class Declaration {
private String name; private String name;
private String comment; private String comment;
private int bitSize = -1; private int bitSize = -1;
private boolean flexArray = false; // true if this is a zero size flex array component
public Declaration() { public Declaration() {
super(); super();
@ -155,11 +154,4 @@ public class Declaration {
bitSize = bits; 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() { 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, 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) { protected List<ValidatableLine> buildAlignmentText(Composite dataType) {
List<ValidatableLine> list = new ArrayList<>(); List<ValidatableLine> list = new ArrayList<>();
String alignStr = CompositeDataTypeImpl.getMinAlignmentString(dataType); String alignStr = CompositeInternal.getMinAlignmentString(dataType);
if (alignStr != null && alignStr.length() != 0) { if (alignStr != null && alignStr.length() != 0) {
list.add(new TextLine(alignStr)); list.add(new TextLine(alignStr));
} }
String packStr = CompositeDataTypeImpl.getPackingString(dataType); String packStr = CompositeInternal.getPackingString(dataType);
if (packStr != null && packStr.length() != 0) { if (packStr != null && packStr.length() != 0) {
list.add(new TextLine(packStr)); list.add(new TextLine(packStr));
} }
@ -117,10 +117,6 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
private List<ValidatableLine> buildContent(Composite comp) { private List<ValidatableLine> buildContent(Composite comp) {
List<ValidatableLine> list = new ArrayList<>(); List<ValidatableLine> list = new ArrayList<>();
if (comp.isZeroLength()) {
return list;
}
int count = 0; int count = 0;
DataTypeComponent[] components = comp.getComponents(); DataTypeComponent[] components = comp.getComponents();
for (DataTypeComponent dataTypeComponent : components) { for (DataTypeComponent dataTypeComponent : components) {
@ -135,27 +131,14 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
locatableType = getLocatableDataType(dataType); 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) { if (count++ >= MAX_COMPONENT_COUNT) {
// Prevent a ridiculous number of components from consuming all memory. // Prevent a ridiculous number of components from consuming all memory.
list.add(new DataTypeLine("", "Warning: Too many components to display...", "", list.add(
null, false)); new DataTypeLine("", "Warning: Too many components to display...", "", null));
break; 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; return list;
} }
@ -239,9 +222,6 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
StringBuilder lineBuffer = new StringBuilder(); StringBuilder lineBuffer = new StringBuilder();
DataTypeLine line = (DataTypeLine) iterator.next(); DataTypeLine line = (DataTypeLine) iterator.next();
String typeName = generateTypeName(line, trim); String typeName = generateTypeName(line, trim);
if (line.isFlexibleArray()) {
typeName += "[0]";
}
int fieldLength = ToolTipUtils.LINE_LENGTH / 2; int fieldLength = ToolTipUtils.LINE_LENGTH / 2;
String fieldName = line.getName(); String fieldName = line.getName();

View file

@ -29,7 +29,6 @@ public class DataTypeLine implements ValidatableLine {
private String name; private String name;
private String comment; private String comment;
private DataType dataType; private DataType dataType;
private boolean isFlexibleArray;
private Color typeColor; private Color typeColor;
private Color nameColor; private Color nameColor;
@ -37,9 +36,8 @@ public class DataTypeLine implements ValidatableLine {
private ValidatableLine validationLine; 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.dataType = dt;
this.isFlexibleArray = isFlexibleArray;
if (name == null) { if (name == null) {
name = ""; name = "";
} }
@ -49,17 +47,9 @@ public class DataTypeLine implements ValidatableLine {
this.comment = comment == null ? "" : comment; 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 @Override
public ValidatableLine copy() { public ValidatableLine copy() {
return new DataTypeLine(name, type, comment, dataType, isFlexibleArray); return new DataTypeLine(name, type, comment, dataType);
} }
@Override @Override

View file

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

View file

@ -20,6 +20,8 @@ import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils;
import docking.widgets.fieldpanel.field.*; import docking.widgets.fieldpanel.field.*;
import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.FieldLocation;
import docking.widgets.fieldpanel.support.FieldUtils; import docking.widgets.fieldpanel.support.FieldUtils;
@ -245,19 +247,32 @@ public class PreCommentFieldFactory extends FieldFactory {
} }
private String[] getDataAutoComments(Data data) { private String[] getDataAutoComments(Data data) {
return getPreceedingComponentAutoComment(data);
// Build flexible array comment
Address addr = data.getMinAddress().previous();
if (addr != null) {
return getFlexArrayComment(data, addr);
}
return null;
} }
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; int levelsToIgnore = 0;
String label = null; String label = null;
Address prevDataAddr = data.getMinAddress().previous();
if (prevDataAddr == null) {
return null;
}
int[] cpath = data.getComponentPath(); int[] cpath = data.getComponentPath();
if (cpath != null && cpath.length > 0) { if (cpath != null && cpath.length > 0) {
@ -273,46 +288,60 @@ public class PreCommentFieldFactory extends FieldFactory {
} }
else { else {
Program p = data.getProgram(); Program p = data.getProgram();
data = p.getListing().getDefinedDataContaining(addr); data = p.getListing().getDefinedDataContaining(prevDataAddr);
if (data == null || !(data.isStructure() || data.isDynamic())) { if (data == null || !(data.isStructure() || data.isDynamic())) { // FIXME!! refer to DynamicDataType which has components - Union?
return null; return null;
} }
Symbol s = p.getSymbolTable().getPrimarySymbol(data.getAddress()); Symbol s = p.getSymbolTable().getPrimarySymbol(data.getAddress());
label = s != null ? s.getName(true) : data.getDataType().getName(); 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) { while (true) {
int offset = (int) addr.subtract(data.getMinAddress()); DataType dt = data.getDataType();
Data component = data.getComponentAt(offset);
if (component == null || !component.isStructure()) { 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; break;
} }
Data component = data.getComponent(lastDtc.getOrdinal());
if (component == null) {
return null;
}
data = component; data = component;
} }
return buildFlexArrayComment(data, levelsToIgnore, label); if (lastDtc == null || lastDtc.isBitFieldComponent()) {
}
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) {
return null; return null;
} }
return buildZeroLengthComponentAutoComment(lastDtc, data, levelsToIgnore, label);
}
String fieldName = flexComponent.getFieldName(); private String[] buildZeroLengthComponentAutoComment(DataTypeComponent lastZeroLengthComponent, Data data, int levelsToIgnore, String label) {
if (fieldName == null) {
fieldName = flexComponent.getDefaultFieldName(); String fieldName = lastZeroLengthComponent.getFieldName();
if (StringUtils.isEmpty(fieldName)) {
fieldName = lastZeroLengthComponent.getDefaultFieldName();
} }
StringBuilder flexName = new StringBuilder(fieldName); StringBuilder flexName = new StringBuilder(fieldName);
@ -331,8 +360,8 @@ public class PreCommentFieldFactory extends FieldFactory {
flexName.insert(0, label + "."); flexName.insert(0, label + ".");
} }
return new String[] { "Flexible Array: " + flexComponent.getDataType().getName() + "[] " + return new String[] { "Zero-length Component: " + lastZeroLengthComponent.getDataType().getName() + " " +
flexName.toString() }; flexName.toString() };
} }
private ListingTextField getTextField(String[] comments, String[] autoComment, private ListingTextField getTextField(String[] comments, String[] autoComment,

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)); 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) { 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 // Depending upon the packing, bit-fields at different offsets may overlap
if (subData.getMinAddress().equals(addr)) { if (subData.getMinAddress().equals(addr)) {
list.add(subData); list.add(subData);

View file

@ -649,7 +649,8 @@ public class DataTypesXmlMgr {
private void writerMember(XmlWriter writer, DataTypeComponent member) { private void writerMember(XmlWriter writer, DataTypeComponent member) {
XmlAttributes attrs = new XmlAttributes(); 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("OFFSET", member.getOffset(), true);
attrs.addAttribute("DATATYPE", member.getDataType().getDisplayName()); attrs.addAttribute("DATATYPE", member.getDataType().getDisplayName());
attrs.addAttribute("DATATYPE_NAMESPACE", member.getDataType().getCategoryPath().getPath()); attrs.addAttribute("DATATYPE_NAMESPACE", member.getDataType().getCategoryPath().getPath());

View file

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

View file

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

View file

@ -573,9 +573,16 @@ public class DataTypeParser {
ArraySpecPiece(String piece) throws InvalidDataTypeException { ArraySpecPiece(String piece) throws InvalidDataTypeException {
if (piece.startsWith("[") && piece.endsWith("]")) { if (piece.startsWith("[") && piece.endsWith("]")) {
String elementCountStr = piece.substring(1, piece.length() - 1);
try { try {
elementCount = parseSize(elementCountStr); 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; return;
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {

View file

@ -1968,14 +1968,7 @@ Declaration DirectDeclarator(Declaration dt, DataType container) : {
for (Iterator iterator = list.iterator(); iterator.hasNext();) { for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Integer iSize = (Integer) iterator.next(); Integer iSize = (Integer) iterator.next();
DataType decDt = dec.getDataType(); DataType decDt = dec.getDataType();
if (iSize == 0 && container != null) { dec.setDataType(new ArrayDataType(decDt, iSize, decDt.getLength()));
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+"]"); //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.program.model.data.*;
import ghidra.util.InvalidNameException; import ghidra.util.InvalidNameException;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitorAdapter; import ghidra.util.task.TaskMonitor;
/** /**
* Tests for merging data types. * 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, 6, td, 2, "bf1", null);
struct.insertBitFieldAt(3, 2, 4, td, 2, "bf2", null); struct.insertBitFieldAt(3, 2, 4, td, 2, "bf2", null);
struct.add(new QWordDataType()); struct.add(new QWordDataType());
struct.add(new ArrayDataType(td, 0, -1), 0, "flex", "my flex");
struct.setFlexibleArrayComponent(td, "flex", "my flex");
structRef.set(struct); structRef.set(struct);
c.removeCategory("Category5", TaskMonitorAdapter.DUMMY); c.removeCategory("Category5", TaskMonitor.DUMMY);
Category c5 = c.createCategory("Category5"); Category c5 = c.createCategory("Category5");
c5.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER); c5.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
commit = true; commit = true;
@ -187,7 +186,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3")); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
try { try {
Structure s = (Structure) c.getDataType("IntStruct"); 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 = new StructureDataType(c.getCategoryPath(), "IntStruct", 0, dtm);
s.add(new QWordDataType(), "f1", "my f1"); s.add(new QWordDataType(), "f1", "my f1");
s.add(new FloatDataType()); s.add(new FloatDataType());
@ -220,7 +219,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Structure s = (Structure) dt; Structure s = (Structure) dt;
assertEquals("my f1", s.getComponent(0).getComment()); assertEquals("my f1", s.getComponent(0).getComment());
DataTypeComponent dtc = s.getComponentAt(17); DataTypeComponent dtc = s.getComponentContaining(17);
assertEquals(7, dtc.getOrdinal()); assertEquals(7, dtc.getOrdinal());
assertEquals("my bf1", dtc.getComment()); assertEquals("my bf1", dtc.getComment());
} }
@ -243,7 +242,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3")); Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
try { try {
Structure s = (Structure) c.getDataType("IntStruct"); Structure s = (Structure) c.getDataType("IntStruct");
c.remove(s, TaskMonitorAdapter.DUMMY); c.remove(s, TaskMonitor.DUMMY);
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0); s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0);
s.add(new QWordDataType()); s.add(new QWordDataType());
s.add(new FloatDataType()); s.add(new FloatDataType());
@ -440,7 +439,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -479,7 +478,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
try { try {
DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER); DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -530,7 +529,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -581,7 +580,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"FloatStruct"); "FloatStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -611,7 +610,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -659,7 +658,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -715,7 +714,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -734,7 +733,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -963,7 +962,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -992,7 +991,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
"IntStruct"); "IntStruct");
try { try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY); dtm.remove(dt, TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -1050,7 +1049,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Structure s = (Structure) dt; Structure s = (Structure) dt;
s.add(new ByteDataType()); s.add(new ByteDataType());
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2")); Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY); parent.removeCategory("Category3", TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {
@ -1116,7 +1115,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
Structure s = (Structure) dt; Structure s = (Structure) dt;
s.add(new ByteDataType()); s.add(new ByteDataType());
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2")); Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY); parent.removeCategory("Category3", TaskMonitor.DUMMY);
commit = true; commit = true;
} }
finally { finally {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -190,7 +190,8 @@ public class DataReferencesTest extends AbstractGhidraHeadedIntegrationTest {
int e = i / 24; int e = i / 24;
int f = i % 24; int f = i % 24;
assertEquals( assertEquals(
"dword ptr [ArrayA[" + e + "].field_0x" + Integer.toHexString(f) + "]", "dword ptr [ArrayA[" + e + "].field" + f + "_0x" + Integer.toHexString(f) +
"]",
opStr); opStr);
} }
} }
@ -233,10 +234,13 @@ public class DataReferencesTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("dword ptr [StructA]", opStr); assertEquals("dword ptr [StructA]", opStr);
} }
else { else {
int f = (i / 24) * 24; int fOrdinal = i / 24;
int fOffset = fOrdinal * 24;
int e = (i % 24) / 4; int e = (i % 24) / 4;
assertEquals( assertEquals(
"dword ptr [StructA.field_0x" + Integer.toHexString(f) + "[" + e + "]]", "dword ptr [StructA.field" + fOrdinal + "_0x" +
Integer.toHexString(fOffset) + "[" + e +
"]]",
opStr); opStr);
} }
} }
@ -327,10 +331,12 @@ public class DataReferencesTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("dword ptr [StructA]", opStr); assertEquals("dword ptr [StructA]", opStr);
} }
else { else {
int f1 = (i / 24) * 24; int f1Ordinal = i / 24;
int f1Offset = f1Ordinal * 24;
int f2 = i % 24; int f2 = i % 24;
assertEquals("dword ptr [StructA.field_0x" + Integer.toHexString(f1) + assertEquals("dword ptr [StructA.field" + f1Ordinal + "_0x" +
".field_0x" + Integer.toHexString(f2) + "]", opStr); 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"); DataType structdt2 = dataMgr.getDataType(rootCP, "mystruct.conflict");
assertEquals(100, structdt.getLength()); assertEquals(100, structdt.getLength());
assertEquals("f1", structdt.getComponentAt(0).getFieldName()); assertEquals("f1", structdt.getComponentContaining(0).getFieldName());
assertEquals("f2", structdt.getComponentAt(10).getFieldName()); assertEquals("f2", structdt.getComponentContaining(10).getFieldName());
assertNull(structdt2); assertNull(structdt2);
} }
@ -378,7 +378,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
Structure struct2dt = (Structure) dataMgr.getDataType(rootCP, "mystruct2"); Structure struct2dt = (Structure) dataMgr.getDataType(rootCP, "mystruct2");
assertEquals(100, structdt.getLength()); assertEquals(100, structdt.getLength());
assertEquals("ptr_to_struct1", struct2dt.getComponentAt(0).getFieldName()); assertEquals("ptr_to_struct1", struct2dt.getComponentContaining(0).getFieldName());
} }
@Test @Test
@ -699,7 +699,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes(); importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct"); Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
DataTypeComponent dtc = structdt.getComponentAt(14); DataTypeComponent dtc = structdt.getComponentContaining(14);
DataType anonDT = dtc.getDataType(); DataType anonDT = dtc.getDataType();
assertEquals("anon_struct_for_f3_f4", anonDT.getName()); assertEquals("anon_struct_for_f3_f4", anonDT.getName());
} }
@ -717,8 +717,13 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes(); importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct"); 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(); importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct"); Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent()); assertHasFlexArray(structdt);
} }
@ -761,7 +766,7 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes(); importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct"); Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
assertNotNull(structdt.getFlexibleArrayComponent()); assertHasFlexArray(structdt);
} }
@Test @Test
@ -778,9 +783,73 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes(); importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct"); 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 @Test
@ -862,8 +931,6 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
@Test @Test
public void testUnionFlexArray() throws CancelledException, IOException, DWARFException { 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 intDIE = addInt(cu);
DebugInfoEntry arrayDIE = newArray(cu, intDIE, false, -1); DebugInfoEntry arrayDIE = newArray(cu, intDIE, false, -1);
@ -920,10 +987,10 @@ public class DWARFDataTypeImporterTest extends DWARFTestBase {
importAllDataTypes(); importAllDataTypes();
Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct"); Structure structdt = (Structure) dataMgr.getDataType(rootCP, "mystruct");
DataTypeComponent f1dtc = structdt.getComponentAt(0); DataTypeComponent f1dtc = structdt.getComponentContaining(0);
DataTypeComponent f2dtc = structdt.getComponentAt(10); DataTypeComponent f2dtc = structdt.getComponentContaining(10);
DataTypeComponent f3dtc = structdt.getComponentAt(20); DataTypeComponent f3dtc = structdt.getComponentContaining(20);
DataTypeComponent f4dtc = structdt.getComponentAt(40); DataTypeComponent f4dtc = structdt.getComponentContaining(40);
assertEquals(f1dtc.getDataType(), f2dtc.getDataType()); assertEquals(f1dtc.getDataType(), f2dtc.getDataType());
assertEquals(f1dtc.getDataType(), f3dtc.getDataType()); assertEquals(f1dtc.getDataType(), f3dtc.getDataType());

View file

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

View file

@ -86,8 +86,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
struct.add(new ByteDataType(), "field0", "Comment1"); struct.add(new ByteDataType(), "field0", "Comment1");
struct.add(new WordDataType(), null, "Comment2"); struct.add(new WordDataType(), null, "Comment2");
struct.add(new DWordDataType(), "field3", null); struct.add(new DWordDataType(), "field3", null);
struct.add(new ByteDataType(), "field4", "Comment4"); struct.add(new ArrayDataType(CharDataType.dataType, 0, -1), "flex", "Flex Comment");
// struct.setFlexibleArrayComponent(CharDataType.dataType, "flex", "Flex Comment");
return struct; return struct;
} }
@ -117,7 +116,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
public void testStructureBitFields() throws Exception { public void testStructureBitFields() throws Exception {
openStructure(addr(0x1010)); openStructure(addr(0x1010));
assertMnemonic("Test", addr(0x1010), 0); assertMnemonic("Test", addr(0x1010), 0);
assertComponents(); assertComponents("Test");
} }
@Test @Test
@ -130,10 +129,10 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
openStructure(addr(0x1010)); openStructure(addr(0x1010));
assertMnemonic("BitfieldDType", addr(0x1010), 0); assertMnemonic("BitfieldDType", addr(0x1010), 0);
assertComponents(); assertComponents("BitfieldDType");
} }
private void assertComponents() { private void assertComponents(String typeName) {
assertMnemonic("int:3", addr(0x1010), 1); assertMnemonic("int:3", addr(0x1010), 1);
assertOperand("0h", addr(0x1010), 1); assertOperand("0h", addr(0x1010), 1);
assertMnemonic("int:24", addr(0x1010), 2); assertMnemonic("int:24", addr(0x1010), 2);
@ -152,6 +151,10 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
assertOperand("EFh", addr(0x1017), 0); assertOperand("EFh", addr(0x1017), 0);
assertMnemonic("dw", addr(0x1018), 0); assertMnemonic("dw", addr(0x1018), 0);
assertOperand("1234h", 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) { private void assertMnemonic(String expectedValue, Address addr, int occurrence) {
@ -164,6 +167,11 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
assertEquals(expectedValue, plugin.getCurrentFieldText()); 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) { private void openStructure(Address address) {
// open the structure // open the structure
plugin.goToField(address, "+", 0, 0); plugin.goToField(address, "+", 0, 0);
@ -209,14 +217,7 @@ public class BitFieldListingDisplayTest extends AbstractGhidraHeadedIntegrationT
protected DataTypeComponent[] getAllComponents(MemBuffer buf) { protected DataTypeComponent[] getAllComponents(MemBuffer buf) {
try { try {
Structure struct = createStructure(dataMgr); Structure struct = createStructure(dataMgr);
DataTypeComponent[] components = struct.getComponents(); return 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;
} }
catch (InvalidDataTypeException e) { catch (InvalidDataTypeException e) {
return null; // test should fail as a result 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*64*32**16*8");
checkValidDt("byte*8*"); checkValidDt("byte*8*");
checkValidDt("byte*32*16*32"); checkValidDt("byte*32*16*32");
checkValidDt("byte[]"); // treated the same as byte[0]
checkValidDt("byte[0]");
checkValidDt("byte[5]"); checkValidDt("byte[5]");
checkValidDt("byte[22][13]"); checkValidDt("byte[22][13]");
checkValidDt("byte*[2]"); checkValidDt("byte*[2]");
@ -141,8 +143,6 @@ public class DataTypeParserTest extends AbstractEditorTest {
checkInvalidDt("aaa*{"); checkInvalidDt("aaa*{");
checkInvalidDt("byte*5"); checkInvalidDt("byte*5");
checkInvalidDt("byte*16*[.]"); checkInvalidDt("byte*16*[.]");
checkInvalidDt("byte[]");
checkInvalidDt("byte[0]");
checkInvalidDt("*byte"); checkInvalidDt("*byte");
checkInvalidDt("byte[7]*[12a]"); checkInvalidDt("byte[7]*[12a]");
checkInvalidDt("*"); checkInvalidDt("*");

View file

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

View file

@ -15,8 +15,7 @@
*/ */
package ghidra.util.table; package ghidra.util.table;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -26,27 +25,9 @@ import ghidra.app.util.viewer.field.ArrayElementFieldLocation;
import ghidra.app.util.viewer.field.BrowserCodeUnitFormat; import ghidra.app.util.viewer.field.BrowserCodeUnitFormat;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.ArrayDataType; import ghidra.program.model.data.*;
import ghidra.program.model.data.CharDataType; import ghidra.program.model.listing.*;
import ghidra.program.model.data.Integer16DataType; import ghidra.program.util.*;
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.test.AbstractProgramBasedTest; import ghidra.test.AbstractProgramBasedTest;
import ghidra.test.ClassicSampleX86ProgramBuilder; import ghidra.test.ClassicSampleX86ProgramBuilder;
@ -204,7 +185,7 @@ public class PreviewTableCellDataTest extends AbstractProgramBasedTest {
String preview = data.getDisplayString(); String preview = data.getDisplayString();
// this is the mnemonic and operand inside of the structure at field [2] // 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 @Test

View file

@ -36,8 +36,7 @@ import ghidra.program.database.ProgramDB;
import ghidra.program.database.data.DataTypeManagerDB; import ghidra.program.database.data.DataTypeManagerDB;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.CategoryPath; import ghidra.program.model.data.*;
import ghidra.program.model.data.DataTypeManager;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -356,4 +355,22 @@ public class DWARFTestBase extends AbstractGhidraHeadedIntegrationTest {
protected Address addr(long l) { protected Address addr(long l) {
return space.getAddress(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; package ghidra.program.model.data;
import static org.junit.Assert.*; public class MSVCStructureImplBitFieldTest extends MSVCStructureBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
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
}
} }

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; package ghidra.program.model.data;
import org.junit.Test; public class MSVCUnionImplBitFieldTest extends MSVCUnionBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
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
}
} }

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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* package ghidra.program.model.data;
*
*/
package ghidra.program.database.data;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.util.List;
import org.apache.commons.compress.utils.Sets; import org.apache.commons.compress.utils.Sets;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGTest; import generic.test.AbstractGTest;
import ghidra.program.model.data.*;
/** /**
* *
@ -45,7 +43,7 @@ public class StructureDataTypeTest extends AbstractGTest {
private void transitionToBigEndian() { private void transitionToBigEndian() {
// transition default little-endian structure to big-endian // transition default little-endian structure to big-endian
DataTypeManager beDtm = new MyBigEndianDataTypeManager(); DataTypeManager beDtm = createBigEndianDataTypeManager();
struct = struct.clone(beDtm); struct = struct.clone(beDtm);
} }
@ -68,6 +66,24 @@ public class StructureDataTypeTest extends AbstractGTest {
private Pointer createPointer(DataType dataType, int length) { private Pointer createPointer(DataType dataType, int length) {
return new PointerDataType(dataType, length); 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 @Test
public void testAdd() throws Exception { public void testAdd() throws Exception {
@ -84,7 +100,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1); dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset()); assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal()); assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName()); assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertEquals(null, dtc.getFieldName()); assertEquals(null, dtc.getFieldName());
assertEquals("Comment2", dtc.getComment()); assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass()); assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -123,7 +139,7 @@ public class StructureDataTypeTest extends AbstractGTest {
DataTypeComponent dtc = struct.getComponent(0); DataTypeComponent dtc = struct.getComponent(0);
assertEquals(0, dtc.getOffset()); assertEquals(0, dtc.getOffset());
assertEquals(0, dtc.getOrdinal()); assertEquals(0, dtc.getOrdinal());
assertEquals("field_0x0", dtc.getDefaultFieldName()); assertEquals("field0_0x0", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertNull(dtc.getComment()); assertNull(dtc.getComment());
assertEquals(DataType.DEFAULT, dtc.getDataType()); assertEquals(DataType.DEFAULT, dtc.getDataType());
@ -131,7 +147,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1); dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset()); assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal()); assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName()); assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertEquals(null, dtc.getComment()); assertEquals(null, dtc.getComment());
@ -147,7 +163,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(11); dtc = struct.getComponent(11);
assertEquals(11, dtc.getOffset()); assertEquals(11, dtc.getOffset());
assertEquals(11, dtc.getOrdinal()); assertEquals(11, dtc.getOrdinal());
assertEquals("field_0xb", dtc.getDefaultFieldName()); assertEquals("field11_0xb", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment()); assertEquals("Comment2", dtc.getComment());
@ -170,7 +186,7 @@ public class StructureDataTypeTest extends AbstractGTest {
DataTypeComponent dtc = struct.getComponent(0); DataTypeComponent dtc = struct.getComponent(0);
assertEquals(0, dtc.getOffset()); assertEquals(0, dtc.getOffset());
assertEquals(0, dtc.getOrdinal()); assertEquals(0, dtc.getOrdinal());
assertEquals("field_0x0", dtc.getDefaultFieldName()); assertEquals("field0_0x0", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertNull(dtc.getComment()); assertNull(dtc.getComment());
assertEquals(FloatDataType.class, dtc.getDataType().getClass()); assertEquals(FloatDataType.class, dtc.getDataType().getClass());
@ -185,7 +201,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(2); dtc = struct.getComponent(2);
assertEquals(5, dtc.getOffset()); assertEquals(5, dtc.getOffset());
assertEquals(2, dtc.getOrdinal()); assertEquals(2, dtc.getOrdinal());
assertEquals("field_0x5", dtc.getDefaultFieldName()); assertEquals("field2_0x5", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment()); assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass()); assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -223,7 +239,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1); dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset()); assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal()); assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName()); assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment()); assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass()); assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -245,7 +261,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(4); dtc = struct.getComponent(4);
assertEquals(8, dtc.getOffset()); assertEquals(8, dtc.getOffset());
assertEquals(4, dtc.getOrdinal()); assertEquals(4, dtc.getOrdinal());
assertEquals("field_0x8", dtc.getDefaultFieldName()); assertEquals("field4_0x8", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertEquals(null, dtc.getComment()); assertEquals(null, dtc.getComment());
assertEquals(FloatDataType.class, dtc.getDataType().getClass()); assertEquals(FloatDataType.class, dtc.getDataType().getClass());
@ -269,7 +285,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(1); dtc = struct.getComponent(1);
assertEquals(1, dtc.getOffset()); assertEquals(1, dtc.getOffset());
assertEquals(1, dtc.getOrdinal()); assertEquals(1, dtc.getOrdinal());
assertEquals("field_0x1", dtc.getDefaultFieldName()); assertEquals("field1_0x1", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertEquals("Comment2", dtc.getComment()); assertEquals("Comment2", dtc.getComment());
assertEquals(WordDataType.class, dtc.getDataType().getClass()); assertEquals(WordDataType.class, dtc.getDataType().getClass());
@ -277,7 +293,7 @@ public class StructureDataTypeTest extends AbstractGTest {
dtc = struct.getComponent(2); dtc = struct.getComponent(2);
assertEquals(3, dtc.getOffset()); assertEquals(3, dtc.getOffset());
assertEquals(2, dtc.getOrdinal()); assertEquals(2, dtc.getOrdinal());
assertEquals("field_0x3", dtc.getDefaultFieldName()); assertEquals("field2_0x3", dtc.getDefaultFieldName());
assertNull(dtc.getFieldName()); assertNull(dtc.getFieldName());
assertNull(dtc.getComment()); assertNull(dtc.getComment());
assertEquals(FloatDataType.class, dtc.getDataType().getClass()); assertEquals(FloatDataType.class, dtc.getDataType().getClass());
@ -380,7 +396,6 @@ public class StructureDataTypeTest extends AbstractGTest {
} }
// test inserting at offset 1
@Test @Test
public void testInsertAtOffset2() { public void testInsertAtOffset2() {
struct.insertAtOffset(2, new FloatDataType(), 4); struct.insertAtOffset(2, new FloatDataType(), 4);
@ -407,12 +422,159 @@ public class StructureDataTypeTest extends AbstractGTest {
assertEquals(DWordDataType.class, comps[3].getDataType().getClass()); assertEquals(DWordDataType.class, comps[3].getDataType().getClass());
} }
@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 @Test
public void testInsertAtOffsetPastEnd() { public void testInsertAtOffsetPastEnd() {
struct.insertAtOffset(100, new FloatDataType(), 4); struct.insertAtOffset(100, new FloatDataType(), 4);
assertEquals(104, struct.getLength()); 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 @Test
public void testInsertBitFieldLittleEndianAppend() throws Exception { public void testInsertBitFieldLittleEndianAppend() throws Exception {
@ -752,16 +914,6 @@ public class StructureDataTypeTest extends AbstractGTest {
assertNull(dtc); assertNull(dtc);
} }
@Test
public void testReplace() { // bigger, no space below
try {
struct.replace(0, new QWordDataType(), 8);
Assert.fail();
}
catch (Exception e) {
}
}
@Test @Test
public void testReplace1() { // bigger, space below public void testReplace1() { // bigger, space below
struct.insert(1, new QWordDataType()); struct.insert(1, new QWordDataType());
@ -1116,6 +1268,46 @@ public class StructureDataTypeTest extends AbstractGTest {
assertEquals(5, comps[1].getOffset()); 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 @Test
public void testDeleteAtOffset() { public void testDeleteAtOffset() {
struct.deleteAtOffset(2); struct.deleteAtOffset(2);
@ -1125,6 +1317,41 @@ public class StructureDataTypeTest extends AbstractGTest {
assertEquals(DWordDataType.class, comps[1].getDataType().getClass()); assertEquals(DWordDataType.class, comps[1].getDataType().getClass());
assertEquals(1, comps[1].getOffset()); 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 @Test
public void testDeleteComponent() { public void testDeleteComponent() {
@ -1250,13 +1477,56 @@ public class StructureDataTypeTest extends AbstractGTest {
} }
@Test @Test
public void testGetComponentAt() { public void testgetComponentContaining() {
DataTypeComponent dtc = struct.getComponentAt(4); DataTypeComponent dtc = struct.getComponentContaining(4);
assertEquals(DWordDataType.class, dtc.getDataType().getClass()); assertEquals(DWordDataType.class, dtc.getDataType().getClass());
assertEquals(2, dtc.getOrdinal()); assertEquals(2, dtc.getOrdinal());
assertEquals(3, dtc.getOffset()); 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 @Test
public void testAddVarLengthDataTypes() { public void testAddVarLengthDataTypes() {
Structure s1 = createStructure("Test1", 0); Structure s1 = createStructure("Test1", 0);
@ -1264,7 +1534,7 @@ public class StructureDataTypeTest extends AbstractGTest {
s1.add(new StringDataType(), 10); s1.add(new StringDataType(), 10);
s1.add(new StringDataType(), 15); s1.add(new StringDataType(), 15);
DataTypeComponent dtc = s1.getComponentAt(5); DataTypeComponent dtc = s1.getComponentContaining(5);
DataType dt = dtc.getDataType(); DataType dt = dtc.getDataType();
assertEquals(-1, dt.getLength()); assertEquals(-1, dt.getLength());
assertEquals(10, dtc.getLength()); assertEquals(10, dtc.getLength());
@ -1273,14 +1543,17 @@ public class StructureDataTypeTest extends AbstractGTest {
} }
@Test @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); Structure s1 = new StructureDataType("Test1", 25);
s1.replaceAtOffset(0, new StringDataType(), 5, null, null); s1.replaceAtOffset(0, new StringDataType(), 5, null, null);
s1.replaceAtOffset(5, new StringDataType(), 10, null, null); s1.replaceAtOffset(5, new StringDataType(), 10, null, null);
s1.replaceAtOffset(15, 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(); DataType dt = dtc.getDataType();
assertEquals(-1, dt.getLength()); assertEquals(-1, dt.getLength());
assertEquals(10, dtc.getLength()); assertEquals(10, dtc.getLength());
@ -1288,7 +1561,9 @@ public class StructureDataTypeTest extends AbstractGTest {
} }
@Test @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); Structure s1 = new StructureDataType("Test1", 0x60);
s1.replaceAtOffset(0, new StringDataType(), 0xd, null, null); s1.replaceAtOffset(0, new StringDataType(), 0xd, null, null);
@ -1301,16 +1576,152 @@ public class StructureDataTypeTest extends AbstractGTest {
s1.replaceAtOffset(0x48, new StringDataType(), 0xb, null, null); s1.replaceAtOffset(0x48, new StringDataType(), 0xb, null, null);
s1.replaceAtOffset(0x53, new StringDataType(), 0xd, null, null); s1.replaceAtOffset(0x53, new StringDataType(), 0xd, null, null);
DataTypeComponent dtc = s1.getComponentAt(0); DataTypeComponent dtc = s1.getComponentContaining(0);
DataType dt = dtc.getDataType(); DataType dt = dtc.getDataType();
assertEquals("string", dt.getDisplayName()); assertEquals("string", dt.getDisplayName());
assertEquals(0xd, dtc.getLength()); assertEquals(0xd, dtc.getLength());
dtc = s1.getComponentAt(0x31); dtc = s1.getComponentContaining(0x31);
dt = dtc.getDataType(); dt = dtc.getDataType();
assertEquals("string", dt.getDisplayName()); assertEquals("string", dt.getDisplayName());
assertEquals(0xd, dtc.getLength()); 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 @Test
public void testSetName() throws Exception { public void testSetName() throws Exception {
@ -1345,7 +1756,7 @@ public class StructureDataTypeTest extends AbstractGTest {
s1.add(struct); s1.add(struct);
s1.add(new ByteDataType()); s1.add(new ByteDataType());
DataTypeComponent dtc = s1.getComponentAt(7); DataTypeComponent dtc = s1.getComponentContaining(7);
assertEquals(struct, dtc.getDataType()); assertEquals(struct, dtc.getDataType());
dtc = s1.getDataTypeAt(7); dtc = s1.getDataTypeAt(7);
assertEquals(DWordDataType.class, dtc.getDataType().getClass()); 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.insertBitFieldAt(9, 2, 7, td, 2, "MyBit3", "bitComment3");
struct.growStructure(1); struct.growStructure(1);
struct.setFlexibleArrayComponent(td, "myFlex", "flexComment"); struct.add(new ArrayDataType(td, 0, -1), "myFlex", "flexComment");
//@formatter:off //@formatter:off
CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" + CompositeTestUtils.assertExpectedComposite(this, "/TestStruct\n" +
@ -1403,12 +1814,12 @@ public class StructureDataTypeTest extends AbstractGTest {
" 9 Foo:3(4) 1 MyBit2 \"bitComment2\"\n" + " 9 Foo:3(4) 1 MyBit2 \"bitComment2\"\n" +
" 9 Foo:2(7) 2 MyBit3 \"bitComment3\"\n" + " 9 Foo:2(7) 2 MyBit3 \"bitComment3\"\n" +
// " 11 undefined 1 null \"\"\n" + // " 11 undefined 1 null \"\"\n" +
" Foo[0] 0 myFlex \"flexComment\"\n" + " 12 Foo[0] 0 myFlex \"flexComment\"\n" +
"}\n" + "}\n" +
"Size = 12 Actual Alignment = 1", struct); "Size = 12 Actual Alignment = 1", struct);
//@formatter:on //@formatter:on
DataTypeManager beDtm = new MyBigEndianDataTypeManager(); DataTypeManager beDtm = createBigEndianDataTypeManager();
Structure newStruct = new StructureDataType("bigStruct", 0, beDtm); Structure newStruct = new StructureDataType("bigStruct", 0, beDtm);
newStruct.replaceWith(struct); newStruct.replaceWith(struct);
@ -1428,7 +1839,7 @@ public class StructureDataTypeTest extends AbstractGTest {
" 9 Foo:3(4) 1 MyBit2 \"bitComment2\"\n" + " 9 Foo:3(4) 1 MyBit2 \"bitComment2\"\n" +
" 9 Foo:2(7) 2 MyBit3 \"bitComment3\"\n" + " 9 Foo:2(7) 2 MyBit3 \"bitComment3\"\n" +
// " 11 undefined 1 null \"\"\n" + // " 11 undefined 1 null \"\"\n" +
" Foo[0] 0 myFlex \"flexComment\"\n" + " 12 Foo[0] 0 myFlex \"flexComment\"\n" +
"}\n" + "}\n" +
"Size = 12 Actual Alignment = 1", newStruct); "Size = 12 Actual Alignment = 1", newStruct);
//@formatter:on //@formatter:on
@ -1783,13 +2194,10 @@ public class StructureDataTypeTest extends AbstractGTest {
} }
} }
protected class MyBigEndianDataTypeManager extends StandAloneDataTypeManager { protected DataTypeManager createBigEndianDataTypeManager() {
MyBigEndianDataTypeManager() { DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null);
super("BEdtm"); dataOrg.setBigEndian(true);
DataOrganizationImpl dataOrg = DataOrganizationImpl.getDefaultOrganization(null); return new StandAloneDataTypeManager("BEdtm", dataOrg);
dataOrg.setBigEndian(true);
this.dataOrganization = dataOrg;
}
} }
} }

View file

@ -15,817 +15,6 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import static org.junit.Assert.*; public class StructureImplBigEndianBitFieldTest extends StructureBigEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
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
}
} }

View file

@ -15,871 +15,6 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import static org.junit.Assert.*; public class StructureImplLittleEndianBitFieldTest extends StructureLittleEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
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
// }
} }

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

View file

@ -15,95 +15,6 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import org.junit.Test; public class UnionImplBigEndianBitFieldTest extends UnionBigEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
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
}
} }

View file

@ -15,95 +15,6 @@
*/ */
package ghidra.program.model.data; package ghidra.program.model.data;
import org.junit.Test; public class UnionImplLittleEndianBitFieldTest extends UnionLittleEndianBitFieldTest {
// "Impl" in class names forces StructureDB to be copied to Impl types for verification
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
}
} }

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

@ -260,6 +260,8 @@ public class EditStructureUtils {
int endOfDataTypeInStruct = offset + dataTypeLength; int endOfDataTypeInStruct = offset + dataTypeLength;
int roomForData = structure.getLength() - endOfDataTypeInStruct; 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 isn't defined insert
if (structure.isNotYetDefined()) { if (structure.isNotYetDefined()) {

View file

@ -17,9 +17,11 @@ package ghidra.app.plugin.core.decompile.actions;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.List;
import docking.action.KeyBindingData; import docking.action.KeyBindingData;
import docking.action.MenuData; import docking.action.MenuData;
import docking.widgets.OptionDialog;
import ghidra.app.decompiler.ClangFieldToken; import ghidra.app.decompiler.ClangFieldToken;
import ghidra.app.decompiler.ClangToken; import ghidra.app.decompiler.ClangToken;
import ghidra.app.plugin.core.decompile.DecompilerActionContext; 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)); 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 @Override
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) { protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
Function function = context.getFunction(); Function function = context.getFunction();
@ -102,6 +67,21 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
return false; 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 @Override
protected void decompilerActionPerformed(DecompilerActionContext context) { protected void decompilerActionPerformed(DecompilerActionContext context) {
Program program = context.getProgram(); Program program = context.getProgram();
@ -109,7 +89,6 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
ClangToken tokenAtCursor = context.getTokenAtCursor(); ClangToken tokenAtCursor = context.getTokenAtCursor();
DataTypeManager dataTypeManager = program.getDataTypeManager(); DataTypeManager dataTypeManager = program.getDataTypeManager();
DataType dataType = null;
Structure struct = getStructDataType(tokenAtCursor); Structure struct = getStructDataType(tokenAtCursor);
int offset = ((ClangFieldToken) tokenAtCursor).getOffset(); int offset = ((ClangFieldToken) tokenAtCursor).getOffset();
if (struct == null) { if (struct == null) {
@ -119,64 +98,108 @@ public class RetypeFieldAction extends AbstractDecompilerAction {
} }
if (offset < 0 || offset >= struct.getLength()) { if (offset < 0 || offset >= struct.getLength()) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed", 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; 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) { if (dataType == null) {
return; return; // cancelled
} }
boolean successfulMod = false;
if (comp == null) { // check for permitted datatype
if (!struct.isNotYetDefined()) { if (dataType instanceof FactoryDataType || dataType.getLength() <= 0) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed", Msg.showError(this, tool.getToolFrame(), "Retype Failed",
"Could not find component of '" + struct.getName() + "' to retype"); "Retype field with \"" + dataType.getName() + "\" data type is not allowed.");
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;
}
finally {
program.endTransaction(transaction, successfulMod);
}
return;
} }
int transaction = program.startTransaction("Retype Structure Field"); int transaction = program.startTransaction("Retype Structure Field");
try { try {
// Make sure datatype is using the program's data organization before testing fit dataType = dataTypeManager.resolve(dataType, null);
if (dataType.getDataTypeManager() != dataTypeManager) { int newDtLength = dataType.getLength();
dataType = dataTypeManager.resolve(dataType, null);
if (DataTypeComponent.usesZeroLengthComponent(dataType)) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed", "Retype field with \"" +
dataType.getName() + "\" zero-length component is not allowed.");
} }
int startind = comp.getOrdinal();
int endind = getEndComponentIndex(struct, comp, dataType); if (originalDataType != DataType.DEFAULT &&
if (endind < 0) { newDtLength == originalDataType.getLength()) {
Msg.showError(this, tool.getToolFrame(), "Retype Failed", // Perform simple 1-for-1 component replacement - this allows to avoid unpack in some cases - assume comp is not null
"Failed to re-type structure '" + struct.getName() + "': Datatype did not fit"); struct.replace(comp.getOrdinal(), dataType, -1);
return; return;
} }
for (int i = endind; i > startind; --i) { // Clear all but first field
struct.clearComponent(i); // check for datatype fit
String fieldName = null;
String comment = null;
int nextOffset;
if (comp == null) {
nextOffset = offset + 1; // assume padding offset within packed structure
} }
struct.replaceAtOffset(comp.getOffset(), dataType, dataType.getLength(), else {
comp.getFieldName(), comp.getComment()); fieldName = comp.getFieldName();
successfulMod = true; 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",
"Failed to re-type structure '" + struct.getName() +
"': Datatype will not fit");
return;
}
}
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 { finally {
program.endTransaction(transaction, successfulMod); program.endTransaction(transaction, true);
} }
} }
private boolean isAlignmentMaintained(DataTypeComponent comp, DataType dataType, int offset) {
if (comp == null) {
return false;
}
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) { for (DataTypeComponent dtcomp : dtcomps) {
addDependent(entry, dtcomp.getDataType()); addDependent(entry, dtcomp.getDataType());
} }
if (struct.hasFlexibleArrayComponent()) {
addDependent(entry, struct.getFlexibleArrayComponent().getDataType());
}
} }
else if (dataType instanceof Composite) { else if (dataType instanceof Composite) {
DataTypeComponent dtcomps[] = ((Composite) dataType).getComponents(); 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 // included in the length of the structure and must have a properly sized char array
// created immediately following the structure in memory. // 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); return MSDataTypeUtils.getMatchingDataType(program, struct);
} }
@ -281,8 +281,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
@Override @Override
protected int getDataTypeLength() { protected int getDataTypeLength() {
Structure struct = (Structure) getDataType(); Structure struct = (Structure) getDataType();
DataTypeComponent nameComponent = struct.getFlexibleArrayComponent(); int preNameLength = struct.getLength();
int preNameLength = nameComponent.getOffset();
int totalLength = preNameLength; int totalLength = preNameLength;
// Add the length of the name string too if we can get it. // Add the length of the name string too if we can get it.
Address nameAddress = getAddress().add(preNameLength); 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, protected void CheckTypeDefOnStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, int expectedDtLength) { String[] expectedFieldNames, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, null, CheckStructureData(program, address, expectedName, expectedFieldNames, false,
expectedDtLength, true); expectedDtLength, true);
} }
protected void CheckStructureData(ProgramDB program, long address, String expectedName, protected void CheckStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, int expectedDtLength) { String[] expectedFieldNames, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, null, CheckStructureData(program, address, expectedName, expectedFieldNames, false,
expectedDtLength, false); expectedDtLength, false);
} }
protected void CheckStructureData(ProgramDB program, long address, String expectedName, protected void CheckStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, String flexArrayName, int expectedDtLength) { String[] expectedFieldNames, boolean lastFieldIsFlexArray, int expectedDtLength) {
CheckStructureData(program, address, expectedName, expectedFieldNames, flexArrayName, CheckStructureData(program, address, expectedName, expectedFieldNames, lastFieldIsFlexArray,
expectedDtLength, false); expectedDtLength, false);
} }
protected void CheckStructureData(ProgramDB program, long address, String expectedName, protected void CheckStructureData(ProgramDB program, long address, String expectedName,
String[] expectedFieldNames, String flexArrayName, int expectedDtLength, String[] expectedFieldNames, boolean lastFieldIsFlexArray, int expectedDtLength,
boolean isTypeDefOfStructure) { boolean isTypeDefOfStructure) {
Listing listing = program.getListing(); Listing listing = program.getListing();
Data data = listing.getDataAt(addr(program, address)); Data data = listing.getDataAt(addr(program, address));
@ -421,24 +421,22 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
assertEquals("Mismatch in expected structure component count: " + name, assertEquals("Mismatch in expected structure component count: " + name,
expectedFieldNames.length, structure.getNumComponents()); expectedFieldNames.length, structure.getNumComponents());
DataTypeComponent[] components = structure.getComponents(); DataTypeComponent[] components = structure.getComponents();
boolean hasTrailingFlexArray = false;
for (int i = 0; i < components.length; i++) { for (int i = 0; i < components.length; i++) {
assertEquals( assertEquals(
"Expected component " + i + " to be named " + expectedFieldNames[i] + " but was " + "Expected component " + i + " to be named " + expectedFieldNames[i] + " but was " +
components[i].getFieldName(), components[i].getFieldName(),
expectedFieldNames[i], 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(); if (lastFieldIsFlexArray) {
assertNotNull("Structure does not contain flexible array: " + name, assertTrue("Structure does not end with flexible array", hasTrailingFlexArray);
flexibleArrayComponent);
assertEquals(
"Expected flexible array named " + flexArrayName + " but was " +
flexibleArrayComponent.getFieldName(),
flexArrayName, flexibleArrayComponent.getFieldName());
} }
else { else {
assertFalse("Structure contains unexpected flexible array component: " + name, assertFalse("Structure contains unexpected flexible array component",
structure.hasFlexibleArrayComponent()); hasTrailingFlexArray);
} }
} }
@ -493,8 +491,9 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
protected void checkTypeDescriptorData(ProgramDB program, long address, int structLength, protected void checkTypeDescriptorData(ProgramDB program, long address, int structLength,
int nameArrayLength, String expectedTypeName) { int nameArrayLength, String expectedTypeName) {
CheckStructureData(program, address, "TypeDescriptor", new String[] { "pVFTable", "spare" }, CheckStructureData(program, address, "TypeDescriptor",
"name", structLength); new String[] { "pVFTable", "spare", "name" },
true, structLength);
checkTypeName(program, address, expectedTypeName); checkTypeName(program, address, expectedTypeName);
} }

View file

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

View file

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

View file

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

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