mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-13 07:11:30 +08:00
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:
+25
-20
@@ -116,8 +116,14 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
default DBTraceDefinedDataAdapter getComponentAt(int offset) {
|
||||
return getComponentContaining(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
default DBTraceDefinedDataAdapter getComponentContaining(int offset) {
|
||||
// We may write to the cache
|
||||
try (LockHold hold = LockHold.lock(getTrace().getReadWriteLock().writeLock())) {
|
||||
if (offset < 0 || offset >= getLength()) {
|
||||
@@ -133,7 +139,7 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
}
|
||||
if (baseDataType instanceof Structure) {
|
||||
Structure structure = (Structure) baseDataType;
|
||||
DataTypeComponent dtc = structure.getComponentAt(offset);
|
||||
DataTypeComponent dtc = structure.getComponentContaining(offset);
|
||||
return dtc == null ? null : getComponent(dtc.getOrdinal());
|
||||
}
|
||||
if (baseDataType instanceof Union) {
|
||||
@@ -155,7 +161,6 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
if (offset < 0 || offset >= getLength()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DataType baseDataType = getBaseDataType();
|
||||
if (baseDataType instanceof Array) {
|
||||
Array array = (Array) baseDataType;
|
||||
@@ -163,24 +168,30 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
int index = offset / elementLength;
|
||||
return Collections.singletonList(getComponent(index));
|
||||
}
|
||||
if (baseDataType instanceof Structure) {
|
||||
Structure structure = (Structure) baseDataType;
|
||||
DataTypeComponent dtc = structure.getComponentAt(offset);
|
||||
else if (baseDataType instanceof Structure) {
|
||||
Structure struct = (Structure) baseDataType;
|
||||
List<Data> result = new ArrayList<>();
|
||||
// Logic handles overlapping bit fields
|
||||
for (DataTypeComponent dtc : struct.getComponentsContaining(offset)) {
|
||||
result.add(getComponent(dtc.getOrdinal()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (baseDataType instanceof DynamicDataType) {
|
||||
DynamicDataType ddt = (DynamicDataType) baseDataType;
|
||||
DataTypeComponent dtc = ddt.getComponentAt(offset, this);
|
||||
List<Data> result = new ArrayList<>();
|
||||
// Logic handles overlapping bit-fields
|
||||
// Include if offset is contained within bounds of component
|
||||
while (dtc != null && offset >= dtc.getOffset() &&
|
||||
offset <= dtc.getOffset() + dtc.getLength() - 1) {
|
||||
int ordinal = dtc.getOrdinal(); // TODO: Seems I could move this before while
|
||||
result.add(getComponent(ordinal));
|
||||
ordinal++;
|
||||
dtc = ordinal < structure.getNumComponents() ? structure.getComponent(ordinal)
|
||||
while (dtc != null && (offset >= dtc.getOffset()) &&
|
||||
(offset < (dtc.getOffset() + dtc.getLength()))) {
|
||||
int ordinal = dtc.getOrdinal();
|
||||
result.add(getComponent(ordinal++));
|
||||
dtc = ordinal < ddt.getNumComponents(this) ? ddt.getComponent(ordinal, this)
|
||||
: null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (baseDataType instanceof Union) {
|
||||
/** NOTE: The {@link DataDB} implementation seems hasty */
|
||||
else if (baseDataType instanceof Union) {
|
||||
Union union = (Union) baseDataType;
|
||||
List<Data> result = new ArrayList<>();
|
||||
for (DataTypeComponent dtc : union.getComponents()) {
|
||||
@@ -190,12 +201,6 @@ public interface DBTraceDefinedDataAdapter extends DBTraceDataAdapter {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (baseDataType instanceof DynamicDataType) {
|
||||
DynamicDataType dynamic = (DynamicDataType) baseDataType;
|
||||
DataTypeComponent dtc = dynamic.getComponentAt(offset, this);
|
||||
return dtc == null ? Collections.emptyList()
|
||||
: Collections.singletonList(getComponent(dtc.getOrdinal()));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -237,6 +237,11 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Data getComponentContaining(int offset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Data> getComponentsContaining(int offset) {
|
||||
if (offset < 0 || offset >= getLength()) {
|
||||
|
||||
+2
-2
@@ -1414,8 +1414,8 @@ public class DBTraceCodeUnitTest extends AbstractGhidraHeadlessIntegrationTest
|
||||
assertNull(u3fff.getFieldName());
|
||||
assertNull(s4000.getFieldName());
|
||||
assertEquals("nuD", s4000nuD.getFieldName());
|
||||
assertEquals("field_0x4", s4000lE.getFieldName());
|
||||
assertEquals("field_0x8", s4000pF.getFieldName());
|
||||
assertEquals("field2_0x4", s4000lE.getFieldName());
|
||||
assertEquals("field3_0x8", s4000pF.getFieldName());
|
||||
|
||||
// TODO: DAT... may change when proper symbols are implemented
|
||||
assertEquals("DAT_00003fff", u3fff.getPathName());
|
||||
|
||||
+4
@@ -85,6 +85,10 @@ public abstract class DBDomainObjectSupport extends DomainObjectAdapterDB {
|
||||
}
|
||||
catch (VersionException e) {
|
||||
versionExc = e.combine(versionExc);
|
||||
|
||||
// TODO: (see GP-1238) Consider properly supporting VersionException and upgrades.
|
||||
// Returning a null manager will likely induce an NPE down the line.
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+71
-56
@@ -373,28 +373,22 @@
|
||||
<P><IMG alt="Note:" src="../../shared/note.png">The use of bitfield components is not
|
||||
currently reflected in decompiler results or assembly markup. </P>
|
||||
|
||||
<H2><A name="Structure_Editor_Flex_Array"></A>Flexible Array Component</H2>
|
||||
<H2><A name="Structure_Editor_Flex_Array"></A>Zero-Element / Flexible Array Components</H2>
|
||||
|
||||
<P>A structure may be defined with a trailing flexible array component which corresponds to
|
||||
an unsized array (e.g., char[0]). Such a component, if it exists, is always displayed as the
|
||||
last row within the structure editor with the open edit row for additional components located
|
||||
directly above it. The <I>DataType</I> column for a flexible array always shows
|
||||
the base type of the unsized array which can be modified similar to other components. A
|
||||
flexible array is added to the end of a structure by adding a last row specified by the base
|
||||
<I>DataType</I> (e.g. char)
|
||||
then invoking the array action and specifying an element count of 0. Attempting to specify
|
||||
an element count of 0 is only permitted on the last component row when a flexible array component
|
||||
does not already exist. The presence of a flexible array component does not affect the size of a
|
||||
structure and will not appear within the structure when applied to Data within memory as it
|
||||
corresponds to the memory location which immediately follows the end of the structure.</P>
|
||||
|
||||
<P>A structure may be defined with zero-element array components, also referred to as a
|
||||
flexible array, which correspond to an unsized array (e.g., char[0]). Such a component
|
||||
is created by simply specifying a zero-element array datatype as you would a sized-array component
|
||||
(see <A href="#Structure_Editor_Create_FlexArray">Create
|
||||
Zero-Element / Flexible Array Component</A>).
|
||||
The resulting component will not consume any space within the structure and will report a component
|
||||
size of 0. As such, it may reside at the same offset as a subsequent component and/or may have an offset
|
||||
equal to the length of the structure. When packing is enabled such a component may influence the
|
||||
overall alignment of the structure and its length.
|
||||
|
||||
<P><IMG alt="Note:" src="../../shared/note.png">The use of flexible array components is not
|
||||
currently reflected in decompiler results or listing reference markup. Its primary purpose
|
||||
if to reflect the C/C++ source definition of a structure with correct alignment and structure sizing.</P>
|
||||
|
||||
<P><IMG alt="Note:" src="../../shared/note.png">While C/C++ support flexible arrays anywhere
|
||||
within a structure, Ghidra only supports the case where it is the last structure component.</P>
|
||||
|
||||
<DIV style="text-align: center;">
|
||||
<IMG alt="" src="images/StructureEditorWithFlexArray.png"><BR>
|
||||
<BR>
|
||||
@@ -415,7 +409,7 @@
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>Within a non-packed structure <i>undefined</i> components are inserted before the current selection by clicking the <IMG src=
|
||||
"images/Plus.png" alt=""> <B>Insert Undefined Byte</B> button. Within a packed structure an <i>undefined1<i> datatype component
|
||||
"images/Plus.png" alt=""> <B>Insert Undefined Byte</B> button. Within a packed structure an <i>undefined1</i> datatype component
|
||||
is inserted in a similar fashion, although in packed structures it is more appropriate to use a properly sized datatype (e.g., modify datatype
|
||||
on inserted component).</P>
|
||||
</BLOCKQUOTE>
|
||||
@@ -587,24 +581,14 @@
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Structure_Editor_Create_FlexArray"></A> <IMG src="images/Array.png" alt="">Create
|
||||
Flexible Array</H3>
|
||||
Zero-Element / Flexible Array Component</H3>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>To create an unsized flexible array as the last structure component (assuming one
|
||||
is not already defined):</P>
|
||||
|
||||
<OL>
|
||||
<LI>Add a component whose <I>DataType</I> corresponds to the base type of the unsized array.</LI>
|
||||
|
||||
<LI>Select this last structure component in the table.</LI>
|
||||
|
||||
<LI>Press the <IMG src="images/Array.png" alt=""> <B>Create Array</B> button or the '['
|
||||
action key binding.</LI>
|
||||
|
||||
<LI>A dialog pops up to request
|
||||
the number of elements in the array. Specify 0 as the number of elements in the popup
|
||||
dialog and click OK.</LI>
|
||||
</OL>
|
||||
<P>To create an unsized flexible array component you must use the datatype cell edit feature
|
||||
to select/enter the datatype by name including the array-sizing-specification (e.g., char[0]).
|
||||
To initiate edit mode for a component datatype you must double-click the datatype cell for the component
|
||||
you wish to modify. This may be an existing component or the empty row at the end of the table.
|
||||
See <A href="#Structure_Editor_Editing_DataType">Editing the DataType Field</A> for more details.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Structure_Editor_Unpackage_Component"></A> <IMG src="images/Unpackage.gif" alt="">
|
||||
@@ -617,8 +601,7 @@
|
||||
button. For example, the array component Word[4] would become four Word components. If the
|
||||
structure struct_1 was composed of a Float and a DWord, then unpackaging it would replace the
|
||||
struct_1 component with a Float component and a DWord component.</P>
|
||||
</BLOCKQUOTE><BR>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Structure_Editor_Create_Structure_From_Selection"></A> <IMG src=
|
||||
"images/cstruct.png" alt=""> Create Structure From Selection</H3>
|
||||
@@ -778,49 +761,81 @@
|
||||
session top to bottom in the table.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Editing the <I>DataType</I> Field</H3>
|
||||
<H3><A name="Structure_Editor_Editing_DataType"></A>Editing the <I>DataType</I> Field</H3>
|
||||
|
||||
<P>This can be any data type that is available in the data type manager. To edit the data
|
||||
type double-click the data type cell. This will show the <A href=
|
||||
<P>To edit the data type double-click the data type cell. This will show the <A href=
|
||||
"help/topics/DataTypeEditors/DataTypeSelectionDialog.htm">Data Type Selection Dialog</A>,
|
||||
which allows you to easily enter a data type. It can also be Undefined, a pointer to a data
|
||||
type, or an array.</P>
|
||||
which allows you to easily enter a data type or select/modify an existing one from one of the open
|
||||
datatype managers. It can also be Undefined, a pointer to a datatype, or an array.</P>
|
||||
|
||||
<P><IMG alt="Note:" src="../../shared/note.png"> Certain restrictions may apply when specifying
|
||||
or modifying a component's datatype which could cause a modification to fail. Some common restrictions include
|
||||
but are not limited to:</P>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<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>
|
||||
<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
|
||||
typedef.</P>
|
||||
|
||||
<P>For example, Word.</P>
|
||||
<P>This can be any fixed-length built-in data type (e.g., byte, word, etc.), structure, union, typedef, or enum.
|
||||
|
||||
<P><B>Sizable Dynamic Data Type</B></P>
|
||||
|
||||
<P>A sizable built-in Dynamic data type such as <i>string</i> may be specified in which case the user
|
||||
will be prompted to specify the component size.</P>
|
||||
|
||||
<P><B>Pointer Data Type</B></P>
|
||||
|
||||
<P>This can be the basic Pointer data type or a pointer to a data type. A pointer to a data
|
||||
type is indicated by following the data type with an *.</P>
|
||||
<P>This can be a named Pointer data type (e.g., <i>pointer</i>, <i>pointer16</i>, etc.) or a pointer to a specific data type. A pointer to a data
|
||||
type is indicated by following the data type name with an * (i.e., asterisk symbol). It is also possible to stipulate a specific pointer-size, although it should be
|
||||
only done when the default pointer size is inappropriate. A stipulated pointer size may be specified by following the * with its bit-size
|
||||
(16,24,32..64). The pointer * designation may also be stacked for a pointer-to-pointer type.</P>
|
||||
|
||||
<P>For example, Word * is a pointer to a Word.</P>
|
||||
<P>For example, <i>word*</i> is a pointer to a Word using the default pointer size. If a non-default size is needed <i>word*16</i> would force
|
||||
the use of a 16-bit pointer.</P>
|
||||
|
||||
<P><B>Array</B></P>
|
||||
|
||||
<P>This can be a multidimensional array of any data type.</P>
|
||||
<P>A single or multidimensional array of any <A href="#Structure_Editor_Basic_Data_Type">basic data type</A> may be specified.</P>
|
||||
|
||||
<P>For example, DWord[2][4] is an array with 2 elements, where each element is an array
|
||||
with 4 elements that are DWords.</P>
|
||||
<P>For example, <i>dword[2][4]</i> is an array with 2 elements, where each element is an array
|
||||
with 4 elements that are DWords; In a similar fashion a zero-element character array may be specified
|
||||
as <i>char[0]</i>.</P>
|
||||
|
||||
<P><B>Array of Pointers</B></P>
|
||||
|
||||
<P>Arrays of pointers can also be specified.</P>
|
||||
<P>Arrays of pointers may also be specified.</P>
|
||||
|
||||
<P>For example, Float*[5] is an array with five elements where each element is a pointer to
|
||||
<P>For example, <i>float*[5]</i> is an array with five elements where each element is a pointer to
|
||||
a Float.</P>
|
||||
|
||||
|
||||
<P><B>Bitfields</B></P>
|
||||
|
||||
<P>A bitfield may be specified by appending <b>:<bitsize></b> to the end of a valid base datatype. Valid base datatypes include
|
||||
all integer types (e.g., byte, char, int, etc.), a defined enum, or a typedef which corresponds to an integer-type or enum.
|
||||
It is important to note that specifying a bitfield in this manner works well for packed structures, however for non-packed
|
||||
structures it may be neccessary to use the <A href="#Structure_Editor_Bitfield_Actions">Bitfield Actions</A> to properly define a bitfield.</P>
|
||||
|
||||
<P>For example, <i>int:4</i> defines a signed integer bitfield which is 4-bits in length.
|
||||
|
||||
<H4><A name="EffectOfChangingDataTypeSize"></A> <U>Effect of Changing a Component's
|
||||
Size</U></H4>
|
||||
|
||||
<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 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>
|
||||
</P>
|
||||
|
||||
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,9 +21,10 @@ import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* Command to create an array.
|
||||
* Command to create an array. All conflicting data will be cleared.
|
||||
*
|
||||
*/
|
||||
public class CreateArrayCmd implements Command {
|
||||
@@ -37,9 +37,11 @@ public class CreateArrayCmd implements Command {
|
||||
/**
|
||||
* Constructs a new command for creating arrays.
|
||||
* @param addr The address at which to create an array.
|
||||
* @param numElements the number of elements in the array to be created.
|
||||
* @param numElements the number of elements in the array to be created.
|
||||
* A 0 element count is permitted but a minimum length will apply for all array instances.
|
||||
* @param dt the dataType of the elements in the array to be created.
|
||||
* @param elementLength the size of an element in the array.
|
||||
* @param elementLength the size of an element in the array. Only used for Dynamic
|
||||
* datatype <code>dt</code> when {@link Dynamic#canSpecifyLength()} returns true.
|
||||
*/
|
||||
public CreateArrayCmd(Address addr, int numElements, DataType dt, int elementLength) {
|
||||
this.addr = addr;
|
||||
@@ -47,69 +49,47 @@ public class CreateArrayCmd implements Command {
|
||||
this.dataType = dt;
|
||||
this.elementLength = elementLength;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean applyTo(DomainObject obj) {
|
||||
Program program = (Program)obj;
|
||||
Listing listing = program.getListing();
|
||||
|
||||
if (dataType instanceof FactoryDataType) {
|
||||
msg = "Array not allowed on a Factory data-type: " + dataType.getName();
|
||||
return false;
|
||||
}
|
||||
if (dataType instanceof Dynamic && !((Dynamic)dataType).canSpecifyLength()) {
|
||||
msg = "Array not allowed on a non-sizable Dynamic data-type: " + dataType.getName();
|
||||
return false;
|
||||
}
|
||||
if (elementLength <=0) {
|
||||
msg = "DataType must have fixed size > 0, not "+dataType.getLength();
|
||||
return false;
|
||||
}
|
||||
if (numElements <= 0) {
|
||||
msg = "Number of elements must be positive, not "+numElements;
|
||||
return false;
|
||||
}
|
||||
|
||||
int length = numElements*elementLength;
|
||||
Address endAddr;
|
||||
try {
|
||||
endAddr = addr.addNoWrap(length - 1);
|
||||
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) {
|
||||
msg = "Can't create data because length exceeds address space";
|
||||
return false;
|
||||
}
|
||||
AddressSet set = new AddressSet(addr, endAddr);
|
||||
InstructionIterator iter = listing.getInstructions(set, true);
|
||||
if (iter.hasNext()) {
|
||||
msg = "Can't create data because the current selection contains instructions";
|
||||
return false;
|
||||
}
|
||||
|
||||
listing.clearCodeUnits(addr, endAddr, false);
|
||||
ArrayDataType adt = new ArrayDataType(dataType, numElements, elementLength);
|
||||
try {
|
||||
listing.createData(addr, adt, adt.getLength());
|
||||
} catch(CodeUnitInsertionException e) {
|
||||
catch (IllegalArgumentException | CodeUnitInsertionException e) {
|
||||
msg = e.getMessage();
|
||||
return false;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
msg = "Unexpected error: " + e.toString();
|
||||
Msg.error(this, msg, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||
*/
|
||||
@Override
|
||||
public String getStatusMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.framework.cmd.Command#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Create Array";
|
||||
}
|
||||
|
||||
+39
-41
@@ -20,9 +20,11 @@ import ghidra.framework.model.DomainObject;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* Command to create an array inside of a structure.
|
||||
* Command to create an array inside of a structure. All conflicting components
|
||||
* within the targeted structure will be replaced with the new array component.
|
||||
*
|
||||
*/
|
||||
public class CreateArrayInStructureCmd implements Command {
|
||||
@@ -32,14 +34,21 @@ public class CreateArrayInStructureCmd implements Command {
|
||||
private DataType dataType;
|
||||
private int[] compPath;
|
||||
|
||||
// NOTE: This command does not currently handle Dynamic types whose length may
|
||||
// be specified since no elementLength parameter exists.
|
||||
|
||||
/**
|
||||
* Constructs a new command for creating arrays inside of structures.
|
||||
* The specified component will be replaced as will subsequent components within
|
||||
* the structure required to make room for the new array component.
|
||||
* NOTE: This is intended for replacing existing components and not for
|
||||
* simply inserting an array component.
|
||||
* @param addr The address of the structure that will contain the new array.
|
||||
* @param numElements the number of elements in the array to be created.
|
||||
* @param numElements the number of elements in the array to be created. A 0 element count is permitted.
|
||||
* @param dt the dataType of the elements in the array to be created.
|
||||
* @param compPath the component path within the structure at which to create
|
||||
* the array. The component path is an array of integers where each integer
|
||||
* is a component index of the component above it.
|
||||
* @param compPath the target component path within the structure of an existing component where
|
||||
* the array should be created. The component path is an array of integers where each integer
|
||||
* is a component index of the component above it.
|
||||
*/
|
||||
public CreateArrayInStructureCmd(Address addr, int numElements, DataType dt,
|
||||
int[] compPath) {
|
||||
@@ -48,42 +57,18 @@ public class CreateArrayInStructureCmd implements Command {
|
||||
this.dataType = dt;
|
||||
this.compPath = compPath;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean applyTo(DomainObject obj) {
|
||||
Program program = (Program)obj;
|
||||
Listing listing = program.getListing();
|
||||
|
||||
if (dataType instanceof FactoryDataType) {
|
||||
msg = "Array not allowed on a Factory data-type: " + dataType.getName();
|
||||
return false;
|
||||
}
|
||||
if (dataType instanceof Dynamic && !((Dynamic)dataType).canSpecifyLength()) {
|
||||
msg = "Array not allowed on a non-sizable Dynamic data-type: " + dataType.getName();
|
||||
return false;
|
||||
}
|
||||
if (numElements <= 0) {
|
||||
msg = "Number of elements must be positive, not "+numElements;
|
||||
return false;
|
||||
}
|
||||
|
||||
Data data = listing.getDataContaining(addr);
|
||||
Data compData = data.getComponent(compPath);
|
||||
|
||||
int elementLength;
|
||||
if (dataType instanceof Dynamic) {
|
||||
elementLength = compData.getLength();
|
||||
}
|
||||
else {
|
||||
elementLength = dataType.getLength();
|
||||
}
|
||||
if (elementLength <=0) {
|
||||
msg = "DataType must have fixed size > 0, not "+elementLength;
|
||||
if (compData == null) {
|
||||
msg = "Invalid target component path specified";
|
||||
return false;
|
||||
}
|
||||
int length = numElements*elementLength;
|
||||
|
||||
int index = compData.getComponentIndex();
|
||||
int offset = compData.getParentOffset();
|
||||
@@ -94,23 +79,34 @@ public class CreateArrayInStructureCmd implements Command {
|
||||
return false;
|
||||
}
|
||||
Structure struct = (Structure)parentDataType;
|
||||
if (offset+length > struct.getLength()) {
|
||||
msg = "Array too big for structure";
|
||||
return false;
|
||||
}
|
||||
|
||||
DataType baseDt = dataType;
|
||||
if (dataType instanceof TypeDef) {
|
||||
baseDt = ((TypeDef) dataType).getBaseDataType();
|
||||
}
|
||||
if (baseDt instanceof Dynamic) {
|
||||
msg = "Dynamic data-type may not be specified: " + dataType.getName();
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
ArrayDataType adt = new ArrayDataType(dataType, numElements, dataType.getLength());
|
||||
int length = adt.isZeroLength() ? 0 : adt.getLength();
|
||||
if (!struct.isPackingEnabled() && (offset + length) > struct.getLength()) {
|
||||
msg = "Array too big for structure";
|
||||
return false;
|
||||
}
|
||||
clearStruct(struct, compData.getParentOffset(), length);
|
||||
if (struct.isPackingEnabled()) {
|
||||
struct.insert(index, adt, adt.getLength());
|
||||
struct.insert(index, adt, -1);
|
||||
}
|
||||
else {
|
||||
struct.replace(index, adt, adt.getLength());
|
||||
struct.replace(index, adt, -1);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
msg = e.getMessage();
|
||||
catch (RuntimeException e) {
|
||||
msg = "Unexpected error: " + e.toString();
|
||||
Msg.error(this, msg, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -129,6 +125,7 @@ public class CreateArrayInStructureCmd implements Command {
|
||||
/**
|
||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||
*/
|
||||
@Override
|
||||
public String getStatusMsg() {
|
||||
return msg;
|
||||
}
|
||||
@@ -136,6 +133,7 @@ public class CreateArrayInStructureCmd implements Command {
|
||||
/**
|
||||
* @see ghidra.framework.cmd.Command#getName()
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Create Array";
|
||||
}
|
||||
|
||||
+9
-104
@@ -1094,62 +1094,6 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFlexArray(long sourceDtID, Structure sourceDt, Structure destStruct,
|
||||
Map<Long, DataType> resolvedDataTypes) {
|
||||
|
||||
DataTypeComponent flexDtc = sourceDt.getFlexibleArrayComponent();
|
||||
if (flexDtc == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DataTypeManager sourceDTM = sourceDt.getDataTypeManager();
|
||||
|
||||
DataType sourceCompDt = flexDtc.getDataType();
|
||||
String comment = flexDtc.getComment();
|
||||
long sourceComponentID = sourceDTM.getID(sourceCompDt);
|
||||
|
||||
// Try to get a mapping of the source data type to a result data type.
|
||||
DataType resultCompDt = getResolvedComponent(sourceComponentID, resolvedDataTypes);
|
||||
|
||||
if (resultCompDt == null) {
|
||||
// We didn't have a map entry for the data type.
|
||||
|
||||
if (!myDtAddedList.contains(Long.valueOf(sourceComponentID))) {
|
||||
// Not added so should be in result if it wasn't deleted there.
|
||||
DataType rDt = dtms[RESULT].getDataType(sourceComponentID);
|
||||
if (rDt != null) {
|
||||
resultCompDt = rDt;
|
||||
}
|
||||
}
|
||||
if (resultCompDt == null) {
|
||||
// Not added/resolved yet
|
||||
// put an entry in the fixup list
|
||||
fixUpList.add(new FixUpInfo(sourceDtID, sourceComponentID, Integer.MAX_VALUE,
|
||||
resolvedDataTypes));
|
||||
fixUpIDSet.add(sourceDtID);
|
||||
|
||||
// substitute datatype to preserve component name for subsequent fixup
|
||||
resultCompDt = Undefined1DataType.dataType;
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Apply resultCompDt as flex array
|
||||
try {
|
||||
destStruct.setFlexibleArrayComponent(resultCompDt, flexDtc.getFieldName(), comment);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
displayError(destStruct, e);
|
||||
DataType badDt = Undefined1DataType.dataType;
|
||||
comment = "Couldn't add " + resultCompDt.getDisplayName() + " here. " +
|
||||
e.getMessage() + " " + ((comment != null) ? (" " + comment) : "");
|
||||
destStruct.setFlexibleArrayComponent(badDt, flexDtc.getFieldName(), comment);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
displayError(destStruct, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStructure(long sourceDtID, Structure sourceDt, Structure destStruct,
|
||||
Map<Long, DataType> resolvedDataTypes) {
|
||||
|
||||
@@ -1332,8 +1276,6 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
if (!aligned) {
|
||||
adjustStructureSize(destStruct, sourceDt.getLength());
|
||||
}
|
||||
|
||||
updateFlexArray(sourceDtID, sourceDt, destStruct, resolvedDataTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1343,7 +1285,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
*/
|
||||
private static void adjustStructureSize(Structure struct, int preferredSize) {
|
||||
|
||||
DataTypeComponent dtc = struct.getComponentAt(preferredSize);
|
||||
DataTypeComponent dtc = struct.getComponentContaining(preferredSize);
|
||||
if (dtc == null) {
|
||||
struct.growStructure(preferredSize - struct.getLength());
|
||||
return;
|
||||
@@ -1895,16 +1837,6 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
}
|
||||
checkOffsets = true;
|
||||
}
|
||||
DataTypeComponent flexDtc1 = ((Structure) c1).getFlexibleArrayComponent();
|
||||
DataTypeComponent flexDtc2 = ((Structure) c2).getFlexibleArrayComponent();
|
||||
if (flexDtc1 != null && flexDtc2 != null) {
|
||||
if (isChangedComponent(flexDtc1, flexDtc2, dtm1, dtm2, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (flexDtc1 != null || flexDtc2 != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DataTypeComponent[] c1Components = c1.getDefinedComponents();
|
||||
@@ -2384,7 +2316,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process fixup for aligned structure component or trailing flexible array
|
||||
* Process fixup for aligned structure component
|
||||
* @param info fixup info
|
||||
* @param struct result structure
|
||||
* @param dt component datatype
|
||||
@@ -2392,35 +2324,15 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
*/
|
||||
private boolean fixUpAlignedStructureComponent(FixUpInfo info, Structure struct, DataType dt) {
|
||||
int ordinal = info.index;
|
||||
boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE);
|
||||
|
||||
DataTypeComponent dtc = null;
|
||||
if (isFlexArrayFixup) {
|
||||
dtc = struct.getFlexibleArrayComponent();
|
||||
}
|
||||
else {
|
||||
if (ordinal >= 0 || ordinal < struct.getNumComponents()) {
|
||||
dtc = struct.getComponent(ordinal);
|
||||
}
|
||||
if (ordinal >= 0 || ordinal < struct.getNumComponents()) {
|
||||
dtc = struct.getComponent(ordinal);
|
||||
}
|
||||
if (dtc == null) {
|
||||
return false;
|
||||
}
|
||||
if (isFlexArrayFixup) {
|
||||
try {
|
||||
struct.setFlexibleArrayComponent(dt, dtc.getFieldName(), dtc.getComment());
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
displayError(struct, e);
|
||||
DataType badDt = Undefined1DataType.dataType;
|
||||
String comment = dtc.getComment();
|
||||
comment = "Couldn't add " + dt.getDisplayName() + "[ ] here. " + e.getMessage() +
|
||||
" " + ((comment != null) ? (" " + comment) : "");
|
||||
struct.replace(ordinal, badDt, dtc.getLength(), dtc.getFieldName(), comment);
|
||||
struct.setFlexibleArrayComponent(badDt, dtc.getFieldName(), comment);
|
||||
}
|
||||
}
|
||||
else if (dtc.isBitFieldComponent()) {
|
||||
if (dtc.isBitFieldComponent()) {
|
||||
if (BitFieldDataType.isValidBaseDataType(dt)) {
|
||||
// replace bitfield base datatype - silent if updated type is not a valid base type
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dtc.getDataType();
|
||||
@@ -2542,13 +2454,10 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
|
||||
DataType compDt = resolve(info.compID, info.getDataTypeManager(), info.ht);
|
||||
|
||||
boolean isFlexArrayFixup = (info.index == Integer.MAX_VALUE);
|
||||
|
||||
if (compDt != null) {
|
||||
if (struct.isPackingEnabled() || isFlexArrayFixup) {
|
||||
if (struct.isPackingEnabled()) {
|
||||
if (!fixUpAlignedStructureComponent(info, struct, compDt)) {
|
||||
String msg =
|
||||
isFlexArrayFixup ? "flex-array component" : ("component " + info.index);
|
||||
String msg = "component " + info.index;
|
||||
Msg.warn(this, "Structure Merge: Couldn't get " + msg + " in " +
|
||||
struct.getPathName() + " data type during fix up.");
|
||||
return false; // Don't remove this FixUpInfo from the fixupList so the user will get notified.
|
||||
@@ -2565,9 +2474,6 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
}
|
||||
|
||||
// Datatype failed to resolved - check to see if we have a placeholder
|
||||
else if (isFlexArrayFixup) {
|
||||
struct.clearFlexibleArrayComponent();
|
||||
}
|
||||
else if (struct.isPackingEnabled()) {
|
||||
int ordinal = info.index;
|
||||
int numComponents = struct.getNumComponents();
|
||||
@@ -3291,7 +3197,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
if (composite.isPackingEnabled() || (composite instanceof Union)) {
|
||||
return dtc.getOrdinal();
|
||||
}
|
||||
return dtc.getOffset();
|
||||
return dtc.getOffset(); // TODO: use of offset could be problematic with shared offset
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3301,7 +3207,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
private class FixUpInfo {
|
||||
long id;
|
||||
long compID;
|
||||
int index;
|
||||
int index; // TODO: index as offset could be problematic with shared offset
|
||||
Map<Long, DataType> ht;
|
||||
|
||||
// bitfield info
|
||||
@@ -3315,7 +3221,6 @@ public class DataTypeMergeManager implements MergeResolver {
|
||||
* @param compID id of either component or base type
|
||||
* @param index offset into non-packed structure, or ordinal into union or packed
|
||||
* structure; or parameter/return ordinal; for other data types index is not used (specify -1).
|
||||
* For structure trailing flex-array specify {@link Integer#MAX_VALUE}.
|
||||
* @param resolvedDataTypes hashtable used for resolving the data type
|
||||
*/
|
||||
FixUpInfo(long id, long compID, int index,
|
||||
|
||||
@@ -87,44 +87,44 @@ class DataTypePanel extends JPanel {
|
||||
|
||||
pathAttrSet = new SimpleAttributeSet();
|
||||
pathAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
|
||||
pathAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11));
|
||||
pathAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
|
||||
pathAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
|
||||
pathAttrSet.addAttribute(StyleConstants.Foreground, MergeConstants.CONFLICT_COLOR);
|
||||
|
||||
nameAttrSet = new SimpleAttributeSet();
|
||||
nameAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
|
||||
nameAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11));
|
||||
nameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
|
||||
nameAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
|
||||
|
||||
sourceAttrSet = new SimpleAttributeSet();
|
||||
sourceAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
|
||||
sourceAttrSet.addAttribute(StyleConstants.FontSize, new Integer(11));
|
||||
sourceAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
|
||||
sourceAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
|
||||
sourceAttrSet.addAttribute(StyleConstants.Foreground, SOURCE_COLOR);
|
||||
|
||||
offsetAttrSet = new SimpleAttributeSet();
|
||||
offsetAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
|
||||
offsetAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
|
||||
offsetAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
|
||||
offsetAttrSet.addAttribute(StyleConstants.Foreground, Color.BLACK);
|
||||
|
||||
contentAttrSet = new SimpleAttributeSet();
|
||||
contentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
|
||||
contentAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
|
||||
contentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
|
||||
contentAttrSet.addAttribute(StyleConstants.Foreground, Color.BLUE);
|
||||
|
||||
fieldNameAttrSet = new SimpleAttributeSet();
|
||||
fieldNameAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
|
||||
fieldNameAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
|
||||
fieldNameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
|
||||
fieldNameAttrSet.addAttribute(StyleConstants.Foreground, new Color(204, 0, 204));
|
||||
|
||||
commentAttrSet = new SimpleAttributeSet();
|
||||
commentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
|
||||
commentAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
|
||||
commentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
|
||||
commentAttrSet.addAttribute(StyleConstants.Foreground, new Color(0, 204, 51));
|
||||
|
||||
deletedAttrSet = new SimpleAttributeSet();
|
||||
deletedAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
|
||||
deletedAttrSet.addAttribute(StyleConstants.FontSize, new Integer(12));
|
||||
deletedAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
|
||||
deletedAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
|
||||
deletedAttrSet.addAttribute(StyleConstants.Foreground, Color.RED);
|
||||
|
||||
@@ -149,7 +149,7 @@ class DataTypePanel extends JPanel {
|
||||
}
|
||||
|
||||
private void formatAlignment(Composite composite) {
|
||||
String str = CompositeDataTypeImpl.getAlignmentAndPackingString(composite);
|
||||
String str = CompositeInternal.getAlignmentAndPackingString(composite);
|
||||
insertString(str + "\n\n", sourceAttrSet);
|
||||
}
|
||||
|
||||
@@ -178,10 +178,7 @@ class DataTypePanel extends JPanel {
|
||||
DataType dt = dtc.getDataType();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(dt.getName());
|
||||
if (dtc.isFlexibleArrayComponent()) {
|
||||
buffer.append("[0]");
|
||||
}
|
||||
else if (dt instanceof BitFieldDataType &&
|
||||
if (dt instanceof BitFieldDataType &&
|
||||
!((Composite) dtc.getParent()).isPackingEnabled()) {
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dt;
|
||||
buffer.append("(");
|
||||
@@ -204,14 +201,9 @@ class DataTypePanel extends JPanel {
|
||||
offsetWidth += 2; // factor in 0x prefix
|
||||
String offsetStr = "";
|
||||
if (offsetWidth > 0) {
|
||||
if (!dtc.isFlexibleArrayComponent()) {
|
||||
offsetStr = "0x" + Integer.toHexString(dtc.getOffset());
|
||||
offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth - offsetStr.length());
|
||||
offsetStr += ": ";
|
||||
}
|
||||
else {
|
||||
offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth + 2);
|
||||
}
|
||||
offsetStr = "0x" + Integer.toHexString(dtc.getOffset());
|
||||
offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth - offsetStr.length());
|
||||
offsetStr += ": ";
|
||||
insertString(" " + offsetStr + " ", offsetAttrSet);
|
||||
}
|
||||
fieldName = pad(fieldName, fieldNameWidth);
|
||||
@@ -233,10 +225,8 @@ class DataTypePanel extends JPanel {
|
||||
boolean showComponentOffset = false;
|
||||
|
||||
DataTypeComponent[] components = comp.getDefinedComponents();
|
||||
DataTypeComponent flexDtc = null;
|
||||
if (comp instanceof Structure) {
|
||||
showComponentOffset = !comp.isPackingEnabled();
|
||||
flexDtc = ((Structure) comp).getFlexibleArrayComponent();
|
||||
}
|
||||
|
||||
int offsetLength = showComponentOffset ? Integer.toHexString(comp.getLength()).length() : 0;
|
||||
@@ -246,17 +236,10 @@ class DataTypePanel extends JPanel {
|
||||
maxDtNameLength = max(getDataTypeName(component), maxDtNameLength);
|
||||
maxFieldNameLength = max(component.getFieldName(), maxFieldNameLength);
|
||||
}
|
||||
if (flexDtc != null) {
|
||||
maxDtNameLength = max(getDataTypeName(flexDtc), maxDtNameLength);
|
||||
maxFieldNameLength = max(flexDtc.getFieldName(), maxFieldNameLength);
|
||||
}
|
||||
|
||||
for (DataTypeComponent component : components) {
|
||||
renderComponent(component, maxDtNameLength, maxFieldNameLength, offsetLength);
|
||||
}
|
||||
if (flexDtc != null) {
|
||||
renderComponent(flexDtc, maxDtNameLength, maxFieldNameLength, offsetLength);
|
||||
}
|
||||
|
||||
insertString("}\n\n", contentAttrSet);
|
||||
insertAlignment(comp);
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
|
||||
public void actionPerformed(ActionContext context) {
|
||||
|
||||
CompEditorModel editorModel = (CompEditorModel) model;
|
||||
if (editorModel.getNumSelectedRows() != 1 || editorModel.isFlexibleArraySelection()) {
|
||||
if (editorModel.getNumSelectedRows() != 1) {
|
||||
return;
|
||||
}
|
||||
int rowIndex = model.getSelectedRows()[0];
|
||||
@@ -71,7 +71,7 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
|
||||
CompEditorModel editorModel = (CompEditorModel) model;
|
||||
// Union do not support non-packed placement of bitfields
|
||||
if (!(editorModel.viewComposite instanceof Structure) || editorModel.isPackingEnabled() ||
|
||||
editorModel.getNumSelectedRows() != 1 || editorModel.isFlexibleArraySelection()) {
|
||||
editorModel.getNumSelectedRows() != 1) {
|
||||
enabled = false;
|
||||
}
|
||||
setEnabled(enabled);
|
||||
|
||||
+27
-17
@@ -370,7 +370,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
|
||||
void init(DataTypeComponent editDtc) {
|
||||
|
||||
if (editDtc == null || editDtc.isFlexibleArrayComponent()) {
|
||||
if (editDtc == null) {
|
||||
editMode = EditMode.NONE;
|
||||
editOrdinal = -1;
|
||||
this.editComponent = null;
|
||||
@@ -401,6 +401,12 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
return false;
|
||||
}
|
||||
return bitFieldAllocation.hasConflict;
|
||||
|
||||
// TODO: Improve conflict detection with zero-length components.
|
||||
// Zero-length components can share common offset, although
|
||||
// zero-length components should have a lower ordinal than a
|
||||
// sized component at the same offset.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,7 +609,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
String conflictTip = "'" + conflict.getDataType().getDisplayName() +
|
||||
(conflictName != null ? (" " + conflictName) : "") + "' at offset " +
|
||||
conflict.getOffset();
|
||||
conflictMsg += "<div style=\"color: red;font-style: italic\">conflict with " +
|
||||
conflictMsg += "<div style=\"color: red;font-style: italic\">overlaps " +
|
||||
HTMLUtilities.escapeHTML(conflictTip) + "</div>";
|
||||
}
|
||||
return "<HTML><div style=\"text-align:center\">" + HTMLUtilities.escapeHTML(tip) +
|
||||
@@ -842,12 +848,22 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
|
||||
BitFieldPlacement(DataTypeComponent component) {
|
||||
int startOffset = component.getOffset();
|
||||
int componentLength = component.getLength();
|
||||
int offsetAdjBytes = startOffset - allocationByteOffset;
|
||||
if (!bigEndian) {
|
||||
offsetAdjBytes = allocationByteSize - offsetAdjBytes - component.getLength();
|
||||
offsetAdjBytes = allocationByteSize - offsetAdjBytes - componentLength;
|
||||
}
|
||||
int leftAdj = 8 * offsetAdjBytes;
|
||||
if (component.isBitFieldComponent()) {
|
||||
if (componentLength == 0) {
|
||||
// treat all zero-length fields the same
|
||||
zeroBitField = true;
|
||||
rightBit = leftAdj - 8;
|
||||
if (!isBigEndian()) {
|
||||
rightBit += 7;
|
||||
}
|
||||
leftBit = rightBit;
|
||||
}
|
||||
else if (component.isBitFieldComponent()) {
|
||||
BitFieldDataType bitfield = (BitFieldDataType) component.getDataType();
|
||||
int storageSize = 8 * bitfield.getStorageSize();
|
||||
rightBit = leftAdj + storageSize - bitfield.getBitOffset() - 1;
|
||||
@@ -855,13 +871,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
// bits stored (NOTE: this may cause a transition from declared to effective
|
||||
// bit-size when editing a bitfield where the these bit-sizes differ).
|
||||
int bitSize = bitfield.getBitSize();
|
||||
if (bitSize == 0) {
|
||||
zeroBitField = true;
|
||||
leftBit = rightBit;
|
||||
}
|
||||
else {
|
||||
leftBit = rightBit - bitSize + 1;
|
||||
}
|
||||
leftBit = rightBit - bitSize + 1;
|
||||
}
|
||||
else {
|
||||
int componentSize = 8 * component.getLength();
|
||||
@@ -1075,7 +1085,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
int allocationEndOffset = offset + allocationBytes - 1;
|
||||
|
||||
int numComponents = struct.getNumComponents();
|
||||
DataTypeComponent component = struct.getComponentAt(offset);
|
||||
DataTypeComponent component = struct.getDefinedComponentAtOrAfterOffset(offset);
|
||||
while (component != null) {
|
||||
if (component.getOffset() > allocationEndOffset) {
|
||||
break;
|
||||
@@ -1149,7 +1159,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
// determine placement attribute index within allocationBytes which
|
||||
// may have been reduced from allocationByteSize based upon visibility.
|
||||
|
||||
int index = bitIndex - (8 * rightChopBytes);
|
||||
int index = bitIndex - (8 * leftChopBytes);
|
||||
if (index >= 0 && index < bitAttributes.length) {
|
||||
bitAttributes[index] = new BitAttributes(dtc, bitAttributes[index]);
|
||||
}
|
||||
@@ -1245,11 +1255,11 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
|
||||
private DataTypeComponent getConflict() {
|
||||
BitAttributes c = conflict;
|
||||
while (c != null && c.dtc.isZeroBitFieldComponent()) {
|
||||
while (c != null && c.dtc.getLength() == 0 && c.conflict != null) {
|
||||
// TODO: improve conflict detection
|
||||
// Zero-length bitfield could be conflict if placement is
|
||||
// Zero-length components could be conflict if placement is
|
||||
// offcut with another component (currently ignored)
|
||||
c = conflict.conflict;
|
||||
c = c.conflict;
|
||||
}
|
||||
// NOTE: DEFAULT undefined datatype can be ignored as conflict
|
||||
return c != null && c.dtc.getDataType() != DataType.DEFAULT ? c.dtc : null;
|
||||
@@ -1301,7 +1311,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
||||
}
|
||||
else {
|
||||
g.fillRect(rectangle.x, rectangle.y, bitWidth, CELL_HEIGHT);
|
||||
if (conflict != null && conflict.dtc.isZeroBitFieldComponent()) {
|
||||
if (conflict != null && conflict.dtc.getLength() == 0) {
|
||||
conflict.paint(g, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-42
@@ -536,7 +536,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
if (isEditingField()) {
|
||||
endFieldEditing();
|
||||
}
|
||||
checkIsAllowableDataType(datatype, true);
|
||||
checkIsAllowableDataType(datatype);
|
||||
if (length < 1) {
|
||||
DataTypeInstance dti = DataTypeHelper.getSizedDataType(getProvider(), datatype,
|
||||
lastNumBytes, Integer.MAX_VALUE);
|
||||
@@ -575,7 +575,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
endFieldEditing();
|
||||
}
|
||||
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
insertMultiple(rowIndex, dataType, dtLen, multiple, monitor);
|
||||
fixSelection();
|
||||
componentEdited();
|
||||
@@ -741,29 +741,23 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
checkIsAllowableDataType(datatype, !oldDtc.isFlexibleArrayComponent());
|
||||
checkIsAllowableDataType(datatype);
|
||||
|
||||
DataTypeComponent dtc;
|
||||
if (oldDtc.isFlexibleArrayComponent()) {
|
||||
// flexible array only supports fixed-length types
|
||||
dtc = replace(rowIndex, datatype);
|
||||
}
|
||||
else {
|
||||
int oldCompSize = oldDtc.getLength();
|
||||
int newCompSize = length;
|
||||
int sizeDiff = newCompSize - oldCompSize;
|
||||
int oldCompSize = oldDtc.getLength();
|
||||
int newCompSize = length;
|
||||
int sizeDiff = newCompSize - oldCompSize;
|
||||
|
||||
// New one is larger so check to make sure it will fit.
|
||||
if (sizeDiff > 0) {
|
||||
if (!checkForReplace(rowIndex, datatype)) {
|
||||
throw new InvalidDataTypeException(datatype.getDisplayName() + " doesn't fit.");
|
||||
}
|
||||
// New one is larger so check to make sure it will fit.
|
||||
if (sizeDiff > 0) {
|
||||
if (!checkForReplace(rowIndex, datatype)) {
|
||||
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();
|
||||
componentEdited();
|
||||
selectionChanged();
|
||||
@@ -793,11 +787,11 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
}
|
||||
|
||||
DataTypeComponent oldDtc = getComponent(startRowIndex);
|
||||
if (oldDtc == null || oldDtc.isFlexibleArrayComponent()) {
|
||||
if (oldDtc == null) {
|
||||
throw new AssertException();
|
||||
}
|
||||
|
||||
checkIsAllowableDataType(datatype, true);
|
||||
checkIsAllowableDataType(datatype);
|
||||
|
||||
//
|
||||
// Note: if the range being replaced is large enough, then the UI could lock-up. If we
|
||||
@@ -839,7 +833,7 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
if (dtc == null) {
|
||||
return false;
|
||||
}
|
||||
if (!isShowingUndefinedBytes() || dtc.isFlexibleArrayComponent()) {
|
||||
if (!isShowingUndefinedBytes()) {
|
||||
return true;
|
||||
}
|
||||
// Does the new data type fit by replacing the component at index.
|
||||
@@ -869,10 +863,10 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
protected abstract void replaceOriginalComponents();
|
||||
|
||||
@Override
|
||||
protected void checkIsAllowableDataType(DataType datatype, boolean dynamicSizingAllowed)
|
||||
protected void checkIsAllowableDataType(DataType datatype)
|
||||
throws InvalidDataTypeException {
|
||||
|
||||
super.checkIsAllowableDataType(datatype, dynamicSizingAllowed);
|
||||
super.checkIsAllowableDataType(datatype);
|
||||
|
||||
// Verify that we aren't adding this structure or anything that it is
|
||||
// part of to this editable structure.
|
||||
@@ -1021,12 +1015,6 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
// Get data type to make into array.
|
||||
DataType dt = comp.getDataType();
|
||||
|
||||
if (numElements == 0) {
|
||||
// assume if 0 was permitted flexible array support has been provided
|
||||
convertToFlexibleArray(rowIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayDataType array = new ArrayDataType(dt, numElements, comp.getLength(), viewDTM);
|
||||
|
||||
if (getNumSelectedComponentRows() > 1) {
|
||||
@@ -1244,17 +1232,17 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComponentDataTypeInstance(int rowIndex, DataTypeInstance dti)
|
||||
public void setComponentDataTypeInstance(int rowIndex, DataType dt, int length)
|
||||
throws UsrException {
|
||||
if (getComponent(rowIndex) == null) {
|
||||
// Replacing data type in unlocked mode replaces only
|
||||
// that data type and structure size may change.
|
||||
insert(rowIndex, dti.getDataType(), dti.getLength());
|
||||
insert(rowIndex, dt, length);
|
||||
}
|
||||
else {
|
||||
// Replacing data type in unlocked mode replaces only
|
||||
// that data type and structure size may change.
|
||||
replace(rowIndex, dti.getDataType(), dti.getLength());
|
||||
replace(rowIndex, dt, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1268,14 +1256,11 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
@Override
|
||||
public void setComponentName(int rowIndex, String name)
|
||||
throws InvalidInputException, InvalidNameException, DuplicateNameException {
|
||||
if (name.equals("")) {
|
||||
name = null;
|
||||
}
|
||||
if (nameExistsElsewhere(name, rowIndex)) {
|
||||
throw new InvalidNameException("Name \"" + name + "\" already exists.");
|
||||
}
|
||||
try {
|
||||
getComponent(rowIndex).setFieldName(name);
|
||||
getComponent(rowIndex).setFieldName(name); // setFieldName handles trimming
|
||||
}
|
||||
catch (DuplicateNameException exc) {
|
||||
throw new InvalidNameException(exc.getMessage());
|
||||
@@ -1552,9 +1537,6 @@ public abstract class CompEditorModel extends CompositeEditorModel {
|
||||
if (!isContiguousSelection()) {
|
||||
return 0;
|
||||
}
|
||||
if (isFlexibleArraySelection()) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
int rowIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
|
||||
if (rowIndex < getNumComponents()) {
|
||||
|
||||
+8
-2
@@ -177,7 +177,13 @@ public class CompEditorPanel extends CompositeEditorPanel {
|
||||
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);
|
||||
if (editable) {
|
||||
// editable - use same background as category field
|
||||
sizeTextField.setBackground(categoryStatusTextField.getBackground());
|
||||
sizeTextField.setBackground(descriptionTextField.getBackground());
|
||||
}
|
||||
else {
|
||||
// not editable - use same background as panel
|
||||
|
||||
+35
-37
@@ -177,17 +177,14 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
rowIndex = range.getStart().getIndex().intValue();
|
||||
}
|
||||
|
||||
boolean dynamicSizingAllowed = true;
|
||||
|
||||
DataType currentDt = null;
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
if (dtc != null) {
|
||||
dynamicSizingAllowed = !dtc.isFlexibleArrayComponent();
|
||||
currentDt = dtc.getDataType();
|
||||
}
|
||||
if (!(currentDt instanceof Pointer)) {
|
||||
// stacking on pointer allows any data type
|
||||
checkIsAllowableDataType(dt, dynamicSizingAllowed);
|
||||
checkIsAllowableDataType(dt);
|
||||
}
|
||||
|
||||
DataType resultDt = DataUtilities.reconcileAppliedDataType(currentDt, dt, true);
|
||||
@@ -358,7 +355,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
dtName = previousDt.getDisplayName();
|
||||
}
|
||||
DataType newDt = null;
|
||||
int newLength = 0;
|
||||
int newLength = -1;
|
||||
if (dataTypeObject instanceof DataTypeInstance) {
|
||||
DataTypeInstance dti = (DataTypeInstance) dataTypeObject;
|
||||
newDt = dti.getDataType();
|
||||
@@ -381,10 +378,15 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
if (newDt == null) {
|
||||
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);
|
||||
|
||||
if (newLength < 0) {
|
||||
// prefer previous size first
|
||||
int suggestedLength = (previousLength <= 0) ? lastNumBytes : previousLength;
|
||||
@@ -393,22 +395,22 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
if (sizedDataType == null) {
|
||||
return;
|
||||
}
|
||||
newDt = resolveDataType(sizedDataType.getDataType(), viewDTM, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
newLength = sizedDataType.getLength();
|
||||
if (newLength <= 0) {
|
||||
throw new UsrException("Can't currently add this data type.");
|
||||
}
|
||||
}
|
||||
if ((previousDt != null) && newDt.isEquivalent(previousDt) && newLength == previousLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxLength = getMaxReplaceLength(rowIndex);
|
||||
if (newLength <= 0) {
|
||||
throw new UsrException("Can't currently add this data type.");
|
||||
}
|
||||
if (maxLength > 0 && newLength > maxLength) {
|
||||
throw new UsrException(newDt.getDisplayName() + " doesn't fit within " + maxLength +
|
||||
" bytes, need " + newLength + " bytes");
|
||||
}
|
||||
setComponentDataTypeInstance(rowIndex,
|
||||
DataTypeInstance.getDataTypeInstance(newDt, newLength));
|
||||
setComponentDataTypeInstance(rowIndex, newDt, newLength);
|
||||
notifyCompositeChanged();
|
||||
}
|
||||
|
||||
@@ -458,10 +460,6 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
int max = getMaxElements();
|
||||
if (isSingleRowSelection()) {
|
||||
if (max != 0) {
|
||||
int currentIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
|
||||
if (canConvertToFlexibleArray(currentIndex)) {
|
||||
min = 0; // allow flexible array
|
||||
}
|
||||
int initial = getLastNumElements();
|
||||
NumberInputDialog numberInputDialog =
|
||||
new NumberInputDialog("elements", ((initial > 0) ? initial : 1), min, max);
|
||||
@@ -492,20 +490,6 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the existing composite component identified by its rowIndex can
|
||||
* be converted to a flexible array (i.e., unsized array).
|
||||
* @param rowIndex existing component index
|
||||
* @return true if conversion to flexible array permitted.
|
||||
*/
|
||||
protected boolean canConvertToFlexibleArray(int rowIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void convertToFlexibleArray(int rowIndex) throws UsrException {
|
||||
throw new UsrException("Flexible array not permitted");
|
||||
}
|
||||
|
||||
protected void createArray(int numElements)
|
||||
throws InvalidDataTypeException, DataTypeConflictException, UsrException {
|
||||
if (selection.getNumRanges() != 1) {
|
||||
@@ -777,6 +761,10 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
*/
|
||||
protected boolean nameExistsElsewhere(String name, int rowIndex) {
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
if (name.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
int numComponents = getNumComponents();
|
||||
for (int i = 0; i < rowIndex && i < numComponents; i++) {
|
||||
if (name.equals(getComponent(i).getFieldName())) {
|
||||
@@ -797,12 +785,18 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
* If invalid, an exception will be thrown.
|
||||
*
|
||||
* @param datatype the data type
|
||||
* @param dynamicSizingAllowed true signals to allow dynamic types
|
||||
* @throws InvalidDataTypeException if the structure being edited is part
|
||||
* of the data type being inserted or doesn't have a valid size.
|
||||
*/
|
||||
protected void checkIsAllowableDataType(DataType datatype, boolean dynamicSizingAllowed)
|
||||
protected void checkIsAllowableDataType(DataType datatype)
|
||||
throws InvalidDataTypeException {
|
||||
if (!allowsZeroLengthComponents() && DataTypeComponent.usesZeroLengthComponent(datatype)) {
|
||||
throw new InvalidDataTypeException(
|
||||
"Zero-length datatype not permitted: " + datatype.getName());
|
||||
}
|
||||
if (!allowsBitFields() && (datatype instanceof BitFieldDataType)) {
|
||||
throw new InvalidDataTypeException("Bitfield not permitted: " + datatype.getName());
|
||||
}
|
||||
if (datatype instanceof TypeDef) {
|
||||
datatype = ((TypeDef) datatype).getBaseDataType();
|
||||
}
|
||||
@@ -811,17 +805,21 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
"Factory data types are not " + "allowed in a composite data type.");
|
||||
}
|
||||
else if (datatype instanceof Dynamic) {
|
||||
if (!dynamicSizingAllowed) {
|
||||
throw new InvalidDataTypeException(
|
||||
"Dynamic data type is not permitted in current context");
|
||||
}
|
||||
else if (!((Dynamic) datatype).canSpecifyLength()) {
|
||||
if (!((Dynamic) datatype).canSpecifyLength()) {
|
||||
throw new InvalidDataTypeException("Non-sizable Dynamic data types are not " +
|
||||
"allowed in a composite data type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean allowsZeroLengthComponents() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean allowsBitFields() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddAllowed(int currentIndex, DataType datatype) {
|
||||
return false;
|
||||
@@ -1114,7 +1112,7 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
|
||||
throw new AssertException("Can't set data type to null.");
|
||||
}
|
||||
|
||||
checkIsAllowableDataType(newDt, element == null || !element.isFlexibleArrayComponent());
|
||||
checkIsAllowableDataType(newDt);
|
||||
|
||||
newLength = newDt.getLength();
|
||||
if (newLength < 0) {
|
||||
|
||||
+1
-7
@@ -32,7 +32,7 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
|
||||
* @param composite the composite data type that is being edited. (cannot be null).
|
||||
*/
|
||||
public CompositeViewerDataTypeManager(String rootName, Composite composite) {
|
||||
super(rootName);
|
||||
super(rootName, composite.getDataTypeManager().getDataOrganization());
|
||||
transactionID = startTransaction("");
|
||||
originalDTM = composite.getDataTypeManager();
|
||||
universalID = originalDTM.getUniversalID(); // mimic original DTM
|
||||
@@ -50,10 +50,4 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
|
||||
return originalDTM.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
// get the alignment from the original data type manager.
|
||||
return originalDTM.getDataOrganization();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-40
@@ -516,10 +516,7 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
|
||||
* Returns the number of component rows in the viewer. There may be a
|
||||
* blank row at the end for selecting. Therefore this number can be
|
||||
* different than the actual number of components currently in the
|
||||
* structure being viewed. In addition, if a flexible array component
|
||||
* exists which is not included in {@link #getNumComponents()} it
|
||||
* will be included in this count and would appear after the blank row
|
||||
* (e.g., getComponent(getNumComponents()+1) ).
|
||||
* structure being viewed.
|
||||
*
|
||||
* @return the number of rows in the model
|
||||
*/
|
||||
@@ -530,23 +527,17 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
|
||||
|
||||
/**
|
||||
* Returns the number of components in this structure or union.
|
||||
* NOTE: This number does not include the flexible array component which may exist
|
||||
* within a structure.
|
||||
* @return the number of components in the model
|
||||
*/
|
||||
public int getNumComponents() {
|
||||
if (viewComposite == null) {
|
||||
return 0;
|
||||
}
|
||||
return viewComposite.getNumComponents();
|
||||
return (viewComposite != null) ? viewComposite.getNumComponents() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nth component for the structure being viewed. Since the number of rows
|
||||
* can exceed the number of components defined within the composite
|
||||
* ({@link Composite#getNumComponents()}) this method will return null for a blank
|
||||
* row or a flexible array component which may appear as an additional rows for
|
||||
* structures.
|
||||
* row.
|
||||
* @param rowIndex the index of the component to return. First component is index of 0.
|
||||
* @return the component
|
||||
*/
|
||||
@@ -588,37 +579,34 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
|
||||
return "";
|
||||
}
|
||||
String value;
|
||||
DataType dt;
|
||||
int dtLen;
|
||||
DataTypeComponent dtc = viewComposite.getComponent(rowIndex);
|
||||
if (columnIndex == getOffsetColumn()) {
|
||||
int offset = viewComposite.getComponent(rowIndex).getOffset();
|
||||
int offset = dtc.getOffset();
|
||||
value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset);
|
||||
}
|
||||
else if (columnIndex == getLengthColumn()) {
|
||||
int length = viewComposite.getComponent(rowIndex).getLength();
|
||||
value = showHexNumbers ? getHexString(length, true) : Integer.toString(length);
|
||||
int compLen = dtc.getLength();
|
||||
value = showHexNumbers ? getHexString(compLen, true) : Integer.toString(compLen);
|
||||
}
|
||||
else if (columnIndex == getMnemonicColumn()) {
|
||||
DataTypeComponent comp = viewComposite.getComponent(rowIndex);
|
||||
dt = comp.getDataType();
|
||||
DataType dt = dtc.getDataType();
|
||||
value = dt.getMnemonic(new SettingsImpl());
|
||||
int compLen = comp.getLength();
|
||||
dtLen = comp.getDataType().getLength();
|
||||
int compLen = dtc.getLength();
|
||||
int dtLen = dt.isZeroLength() ? 0 : dt.getLength();
|
||||
if (dtLen > compLen) {
|
||||
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
|
||||
}
|
||||
}
|
||||
else if (columnIndex == getDataTypeColumn()) {
|
||||
DataTypeComponent dtc = viewComposite.getComponent(rowIndex);
|
||||
dt = dtc.getDataType();
|
||||
dtLen = dt.getLength();
|
||||
DataType dt = dtc.getDataType();
|
||||
int dtLen = dt.getLength();
|
||||
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength());
|
||||
}
|
||||
else if (columnIndex == getNameColumn()) {
|
||||
value = viewComposite.getComponent(rowIndex).getFieldName();
|
||||
value = dtc.getFieldName();
|
||||
}
|
||||
else if (columnIndex == getCommentColumn()) {
|
||||
value = viewComposite.getComponent(rowIndex).getComment();
|
||||
value = dtc.getComment();
|
||||
}
|
||||
else {
|
||||
value = "UNKNOWN";
|
||||
@@ -1173,20 +1161,6 @@ class CompositeViewerModel extends AbstractTableModel implements DataTypeManager
|
||||
return (selection.getNumRanges() == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current single row selection corresponds to a flexible array component
|
||||
* @return true if the current single row selection corresponds to a flexible array component
|
||||
*/
|
||||
public boolean isFlexibleArraySelection() {
|
||||
if (!isSingleRowSelection()) {
|
||||
return false;
|
||||
}
|
||||
FieldRange range = selection.getFieldRange(0);
|
||||
int rowIndex = range.getStart().getIndex().intValue();
|
||||
DataTypeComponent component = getComponent(rowIndex);
|
||||
return component != null && component.isFlexibleArrayComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component list selection is a single component
|
||||
* @return true if the component list selection is a single component
|
||||
|
||||
+1
-3
@@ -102,9 +102,7 @@ public class DataTypeHelper {
|
||||
if (newDt == null) {
|
||||
throw new InvalidDataTypeException("valid data-type not specified");
|
||||
}
|
||||
DataTypeComponent element = editModel.getComponent(index);
|
||||
editModel.checkIsAllowableDataType(newDt,
|
||||
element == null || !element.isFlexibleArrayComponent());
|
||||
editModel.checkIsAllowableDataType(newDt);
|
||||
int mrl = editModel.getMaxReplaceLength(index);
|
||||
if ((mrl != -1) && (newDt.getLength() > mrl)) {
|
||||
throw new InvalidDataTypeException(newDt.getDisplayName() + " doesn't fit within " +
|
||||
|
||||
+4
-2
@@ -214,9 +214,11 @@ public interface EditorModel {
|
||||
/**
|
||||
* Sets the data type for the component at the indicated row index.
|
||||
* @param rowIndex the row index of the component
|
||||
* @param dataTypeInstance
|
||||
* @param dt component datatype
|
||||
* @param length component length
|
||||
* @throws UsrException if invalid datatype or length specified
|
||||
*/
|
||||
public void setComponentDataTypeInstance(int rowIndex, DataTypeInstance dataTypeInstance)
|
||||
public void setComponentDataTypeInstance(int rowIndex, DataType dt, int length)
|
||||
throws UsrException;
|
||||
|
||||
/**
|
||||
|
||||
+56
-144
@@ -102,10 +102,6 @@ class StructureEditorModel extends CompEditorModel {
|
||||
public int getRowCount() {
|
||||
int componentCount = getNumComponents();
|
||||
int rowCount = componentCount + 1; // add blank edit row
|
||||
Structure viewStruct = (Structure) viewComposite;
|
||||
if (viewStruct != null && viewStruct.hasFlexibleArrayComponent()) {
|
||||
++rowCount;
|
||||
}
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
@@ -129,7 +125,6 @@ class StructureEditorModel extends CompEditorModel {
|
||||
}
|
||||
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
|
||||
if (dtc == null) {
|
||||
if (columnIndex == getDataTypeColumn()) {
|
||||
return null;
|
||||
@@ -137,42 +132,34 @@ class StructureEditorModel extends CompEditorModel {
|
||||
return "";
|
||||
}
|
||||
|
||||
boolean isFlexArrayComponent = dtc.isFlexibleArrayComponent();
|
||||
String value = null;
|
||||
DataType dt;
|
||||
int dtLen;
|
||||
if (columnIndex == getOffsetColumn()) {
|
||||
int offset = dtc.getOffset();
|
||||
value = showHexNumbers ? getHexString(offset, true) : Integer.toString(offset);
|
||||
}
|
||||
else if (columnIndex == getLengthColumn()) {
|
||||
int length = dtc.getLength();
|
||||
value = showHexNumbers ? getHexString(length, true) : Integer.toString(length);
|
||||
int compLen = dtc.getLength();
|
||||
value = showHexNumbers ? getHexString(compLen, true) : Integer.toString(compLen);
|
||||
}
|
||||
else if (columnIndex == getMnemonicColumn()) {
|
||||
dt = dtc.getDataType();
|
||||
DataType dt = dtc.getDataType();
|
||||
value = dt.getMnemonic(new SettingsImpl());
|
||||
if (isFlexArrayComponent) {
|
||||
value += "[0]";
|
||||
}
|
||||
else {
|
||||
int compLen = dtc.getLength();
|
||||
dtLen = dtc.getDataType().getLength();
|
||||
if (dtLen > compLen) {
|
||||
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
|
||||
}
|
||||
int compLen = dtc.getLength();
|
||||
int dtLen = dt.isZeroLength() ? 0 : dt.getLength();
|
||||
if (dtLen > compLen) {
|
||||
value = "TooBig: " + value + " needs " + dtLen + " has " + compLen;
|
||||
}
|
||||
}
|
||||
else if (columnIndex == getDataTypeColumn()) {
|
||||
dt = dtc.getDataType();
|
||||
dtLen = dt.getLength();
|
||||
DataType dt = dtc.getDataType();
|
||||
int dtLen = dt.getLength();
|
||||
return DataTypeInstance.getDataTypeInstance(dt, (dtLen > 0) ? dtLen : dtc.getLength());
|
||||
}
|
||||
else if (columnIndex == getNameColumn()) {
|
||||
value = getComponent(rowIndex).getFieldName();
|
||||
value = dtc.getFieldName();
|
||||
}
|
||||
else if (columnIndex == getCommentColumn()) {
|
||||
value = getComponent(rowIndex).getComment();
|
||||
value = dtc.getComment();
|
||||
}
|
||||
|
||||
return (value == null) ? "" : value;
|
||||
@@ -185,9 +172,6 @@ class StructureEditorModel extends CompEditorModel {
|
||||
return null;
|
||||
}
|
||||
Structure viewStruct = (Structure) viewComposite;
|
||||
if (rowIndex == (numComponents + 1)) {
|
||||
return viewStruct.getFlexibleArrayComponent();
|
||||
}
|
||||
if (rowIndex > numComponents) {
|
||||
return null;
|
||||
}
|
||||
@@ -203,73 +187,48 @@ class StructureEditorModel extends CompEditorModel {
|
||||
return viewComposite == null ? 0 : viewComposite.getNumComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canConvertToFlexibleArray(int rowIndex) {
|
||||
if (!(viewComposite instanceof Structure)) {
|
||||
return false;
|
||||
}
|
||||
if (((Structure) viewComposite).hasFlexibleArrayComponent()) {
|
||||
return false;
|
||||
}
|
||||
if (rowIndex != (getNumComponents() - 1)) {
|
||||
return false;
|
||||
}
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
DataType dt = dtc.getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
if (dt instanceof Dynamic || dt instanceof FactoryDataType) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void convertToFlexibleArray(int rowIndex) throws UsrException {
|
||||
if (!canConvertToFlexibleArray(rowIndex)) {
|
||||
// should be avoided by constraining minimum array size and data type
|
||||
throw new UsrException("Flexible array not permitted");
|
||||
}
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
Structure struct = (Structure) viewComposite;
|
||||
struct.setFlexibleArrayComponent(dtc.getDataType(), dtc.getFieldName(), dtc.getComment());
|
||||
delete(rowIndex);
|
||||
selection.addRange(rowIndex + 1, rowIndex + 2); // select flex component
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSizeEditable() {
|
||||
return !isPackingEnabled();
|
||||
}
|
||||
|
||||
void setStructureSize(int size) {
|
||||
if (viewComposite == null) {
|
||||
if (viewComposite == null || viewComposite.isPackingEnabled()) {
|
||||
return;
|
||||
}
|
||||
int currentLength = viewComposite.isZeroLength() ? 0 : viewComposite.getLength();
|
||||
int currentLength = (viewComposite.isZeroLength()) ? 0 : viewComposite.getLength();
|
||||
if (currentLength == size) {
|
||||
return;
|
||||
}
|
||||
Structure structure = (Structure) viewComposite;
|
||||
if (currentLength > size) {
|
||||
int numComponents = structure.getNumComponents();
|
||||
|
||||
DataTypeComponent dtc = structure.getComponentContaining(size);
|
||||
int ordinal = dtc.getOrdinal();
|
||||
|
||||
// retain any zero-length components which have an offset equal the new size
|
||||
while (dtc.getOffset() == size && dtc.getLength() == 0 &&
|
||||
(ordinal + 1) < numComponents) {
|
||||
dtc = structure.getComponent(++ordinal);
|
||||
}
|
||||
|
||||
// remove trailing components outside of new size
|
||||
for (int index = numComponents - 1; index >= ordinal; index--) {
|
||||
structure.delete(index);
|
||||
int bitFieldResidualBytes = structure.getNumComponents() - index;
|
||||
for (int i = 0; i < bitFieldResidualBytes; i++) {
|
||||
// bitfield removal may cause injection of undefined bytes - remove them
|
||||
structure.delete(index);
|
||||
}
|
||||
}
|
||||
// structure may shrink too much from component removal - may need to grow
|
||||
currentLength = (viewComposite.isZeroLength()) ? 0 : viewComposite.getLength();
|
||||
}
|
||||
if (currentLength < size) {
|
||||
// Increasing structure length.
|
||||
structure.growStructure(size - currentLength);
|
||||
}
|
||||
else {
|
||||
DataTypeComponent dtc = structure.getComponentAt(size);
|
||||
int ordinal = dtc.getOrdinal();
|
||||
if (dtc.getOffset() != size) {
|
||||
structure.clearComponent(ordinal);
|
||||
dtc = structure.getComponentAt(size);
|
||||
ordinal = dtc.getOrdinal();
|
||||
}
|
||||
int numComponents = structure.getNumComponents();
|
||||
for (int index = numComponents - 1; index >= ordinal; index--) {
|
||||
structure.delete(index);
|
||||
}
|
||||
}
|
||||
updateAndCheckChangeState();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
@@ -292,9 +251,6 @@ class StructureEditorModel extends CompEditorModel {
|
||||
if (dtc == null) {
|
||||
return false;
|
||||
}
|
||||
if (dtc.isFlexibleArrayComponent()) {
|
||||
return true;
|
||||
}
|
||||
DataType dt = dtc.getDataType();
|
||||
if (dt == DataType.DEFAULT) {
|
||||
return false;
|
||||
@@ -398,12 +354,12 @@ class StructureEditorModel extends CompEditorModel {
|
||||
}
|
||||
|
||||
DataTypeComponent originalComp = getComponent(index);
|
||||
if (originalComp == null || originalComp.isFlexibleArrayComponent()) {
|
||||
if (originalComp == null) {
|
||||
throw new IllegalArgumentException("Invalid component index specified");
|
||||
}
|
||||
DataType dt = originalComp.getDataType();
|
||||
int dtLen = dt.getLength();
|
||||
checkIsAllowableDataType(dt, true);
|
||||
checkIsAllowableDataType(dt);
|
||||
|
||||
int startIndex = index + 1;
|
||||
if (isShowingUndefinedBytes() && (dt != DataType.DEFAULT)) {
|
||||
@@ -570,7 +526,7 @@ class StructureEditorModel extends CompEditorModel {
|
||||
|
||||
@Override
|
||||
public boolean isBitFieldAllowed() {
|
||||
return isSingleRowSelection() && !isFlexibleArraySelection();
|
||||
return isSingleRowSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -587,7 +543,7 @@ class StructureEditorModel extends CompEditorModel {
|
||||
FieldRange range = selection.getFieldRange(0);
|
||||
|
||||
DataTypeComponent comp = getComponent(range.getStart().getIndex().intValue());
|
||||
if (comp == null || comp.isFlexibleArrayComponent() || comp.isBitFieldComponent()) {
|
||||
if (comp == null || comp.isBitFieldComponent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -615,29 +571,6 @@ class StructureEditorModel extends CompEditorModel {
|
||||
return getComponent(rowIndex) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSelectedComponents() throws UsrException {
|
||||
if (!isDeleteAllowed()) {
|
||||
throw new UsrException("Deleting is not allowed.");
|
||||
}
|
||||
if (isEditingField()) {
|
||||
endFieldEditing();
|
||||
}
|
||||
|
||||
int rowIndex = selection.getFieldRange(0).getStart().getIndex().intValue();
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
if (dtc.isFlexibleArrayComponent()) {
|
||||
// Remove flexible array component
|
||||
((Structure) viewComposite).clearFlexibleArrayComponent();
|
||||
componentEdited();
|
||||
selection.addRange(rowIndex - 1, rowIndex);
|
||||
fixSelection();
|
||||
selectionChanged();
|
||||
return;
|
||||
}
|
||||
super.deleteSelectedComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDuplicateAllowed() {
|
||||
|
||||
@@ -813,7 +746,7 @@ class StructureEditorModel extends CompEditorModel {
|
||||
}
|
||||
|
||||
try {
|
||||
checkIsAllowableDataType(dataType, !dtc.isFlexibleArrayComponent());
|
||||
checkIsAllowableDataType(dataType);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
return false;
|
||||
@@ -898,9 +831,7 @@ class StructureEditorModel extends CompEditorModel {
|
||||
else if (comp == null) {
|
||||
return 0; // No such component. Not at valid edit index.
|
||||
}
|
||||
else if (comp.isFlexibleArrayComponent()) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
// Otherwise, get size of component and number of Undefined bytes after it.
|
||||
FieldRange range = getSelectedRangeContaining(currentIndex);
|
||||
if (range == null ||
|
||||
@@ -936,28 +867,20 @@ class StructureEditorModel extends CompEditorModel {
|
||||
@Override
|
||||
protected DataTypeComponent insert(int rowIndex, DataType dataType, int length, String name,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
try {
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
if (dtc != null && dtc.isFlexibleArrayComponent()) {
|
||||
Structure struct = (Structure) viewComposite;
|
||||
dtc = struct.setFlexibleArrayComponent(dataType, dtc.getFieldName(),
|
||||
dtc.getComment());
|
||||
DataTypeComponent dtc;
|
||||
if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) {
|
||||
dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name, comment);
|
||||
}
|
||||
else {
|
||||
if (isPackingEnabled() || !(dataType instanceof BitFieldDataType)) {
|
||||
dtc = ((Structure) viewComposite).insert(rowIndex, dataType, length, name,
|
||||
comment);
|
||||
}
|
||||
else {
|
||||
BitFieldDataType bitfield = (BitFieldDataType) dataType;
|
||||
dtc = ((Structure) viewComposite).insertBitField(rowIndex, length,
|
||||
bitfield.getBitOffset(), bitfield.getBaseDataType(),
|
||||
bitfield.getDeclaredBitSize(), name, comment);
|
||||
}
|
||||
if (rowIndex <= row) {
|
||||
row++;
|
||||
}
|
||||
BitFieldDataType bitfield = (BitFieldDataType) dataType;
|
||||
dtc = ((Structure) viewComposite).insertBitField(rowIndex, length,
|
||||
bitfield.getBitOffset(), bitfield.getBaseDataType(),
|
||||
bitfield.getDeclaredBitSize(), name, comment);
|
||||
}
|
||||
if (rowIndex <= row) {
|
||||
row++;
|
||||
}
|
||||
adjustSelection(rowIndex, 1);
|
||||
// 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,
|
||||
TaskMonitor monitor) throws InvalidDataTypeException, CancelledException {
|
||||
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
int componentOrdinal = convertRowToOrdinal(rowIndex);
|
||||
monitor.initialize(numCopies);
|
||||
try {
|
||||
@@ -997,21 +920,10 @@ class StructureEditorModel extends CompEditorModel {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent replace(int rowIndex, DataType dt) throws UsrException {
|
||||
DataTypeComponent dtc = getComponent(rowIndex);
|
||||
if (dtc == null || !dtc.isFlexibleArrayComponent()) {
|
||||
return super.replace(rowIndex, dt);
|
||||
}
|
||||
Structure struct = (Structure) viewComposite;
|
||||
return struct.setFlexibleArrayComponent(dt, dtc.getFieldName(), dtc.getComment());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
// It is assumed that the replaced component is not a flexible array
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
try {
|
||||
DataTypeComponent dtc = null;
|
||||
boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex));
|
||||
|
||||
+3
-3
@@ -294,7 +294,7 @@ class UnionEditorModel extends CompEditorModel {
|
||||
if (currentIndex < 0 || currentIndex > getNumComponents()) {
|
||||
return false;
|
||||
}
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
return false;
|
||||
@@ -378,7 +378,7 @@ class UnionEditorModel extends CompEditorModel {
|
||||
@Override
|
||||
public DataTypeComponent insert(int rowIndex, DataType dataType, int length, String name,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
try {
|
||||
DataTypeComponent dtc =
|
||||
((Union) viewComposite).insert(rowIndex, dataType, length, name, comment);
|
||||
@@ -409,7 +409,7 @@ class UnionEditorModel extends CompEditorModel {
|
||||
@Override
|
||||
public DataTypeComponent replace(int rowIndex, DataType dataType, int length, String name,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
try {
|
||||
boolean isSelected = selection.containsEntirely(BigInteger.valueOf(rowIndex));
|
||||
((Union) viewComposite).delete(rowIndex);
|
||||
|
||||
+11
-22
@@ -63,6 +63,8 @@ import util.CollectionUtils;
|
||||
//@formatter:on
|
||||
public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
|
||||
private static final String ROOT_NAME = "DataTypePreviewer";
|
||||
|
||||
private DTPPComponentProvider provider;
|
||||
private DTPPTableModel model;
|
||||
private DTPPTable table;
|
||||
@@ -71,7 +73,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
private GoToService goToService;
|
||||
private DockingAction addAction;
|
||||
private DockingAction deleteAction;
|
||||
private LayeredDataTypeManager dataTypeManager;
|
||||
private DataTypeManager dataTypeManager;
|
||||
private Program activeProgram;
|
||||
|
||||
private SwingUpdateManager updateManager = new SwingUpdateManager(650, () -> updatePreview());
|
||||
@@ -101,7 +103,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
model = new DTPPTableModel();
|
||||
table = new DTPPTable(model);
|
||||
component = new DTPPScrollPane(table);
|
||||
dataTypeManager = new LayeredDataTypeManager(activeProgram);
|
||||
dataTypeManager = createLayeredDataTypeManager();
|
||||
|
||||
addDataType(new ByteDataType());
|
||||
addDataType(new WordDataType());
|
||||
@@ -177,7 +179,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
|
||||
private void updateModel() {
|
||||
|
||||
LayeredDataTypeManager newDtm = new LayeredDataTypeManager(activeProgram);
|
||||
DataTypeManager newDtm = createLayeredDataTypeManager();
|
||||
|
||||
int transactionId = newDtm.startTransaction("add datatypes");
|
||||
try {
|
||||
@@ -197,7 +199,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
List<DataTypePath> dtPaths = getModelDataTypePaths();
|
||||
model.removeAll();
|
||||
|
||||
LayeredDataTypeManager oldDtm = dataTypeManager;
|
||||
DataTypeManager oldDtm = dataTypeManager;
|
||||
dataTypeManager = newDtm;
|
||||
oldDtm.close();
|
||||
|
||||
@@ -711,24 +713,11 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private class LayeredDataTypeManager extends StandAloneDataTypeManager {
|
||||
|
||||
DataOrganization layeredDataOrganization1;
|
||||
|
||||
public LayeredDataTypeManager(Program program) {
|
||||
super("DataTypePreviewer");
|
||||
this.layeredDataOrganization1 =
|
||||
program != null ? program.getDataTypeManager().getDataOrganization() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
if (layeredDataOrganization1 == null) {
|
||||
return super.getDataOrganization();
|
||||
}
|
||||
return layeredDataOrganization1;
|
||||
}
|
||||
|
||||
private DataTypeManager createLayeredDataTypeManager() {
|
||||
DataOrganization dataOrg =
|
||||
(activeProgram != null) ? activeProgram.getCompilerSpec().getDataOrganization()
|
||||
: DataOrganizationImpl.getDefaultOrganization();
|
||||
return new StandAloneDataTypeManager(ROOT_NAME, dataOrg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-62
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+50
-25
@@ -55,6 +55,18 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
this.splitOffset = splitOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataType validateDataType(DataType dataType) {
|
||||
if (DataTypeComponent.usesZeroLengthComponent(dataType)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Zero-length datatype not permitted: " + dataType.getName());
|
||||
}
|
||||
if (dataType instanceof BitFieldDataType) {
|
||||
throw new IllegalArgumentException("Bitfield not permitted: " + dataType.getName());
|
||||
}
|
||||
return super.validateDataType(dataType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlignment() {
|
||||
throw new UnsupportedOperationException(
|
||||
@@ -91,18 +103,11 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent setFlexibleArrayComponent(DataType flexType, String name,
|
||||
String comment) {
|
||||
throw new UnsupportedOperationException(
|
||||
"BiDirectionDataType.setFlexibleArrayComponent() not implemented.");
|
||||
}
|
||||
|
||||
protected DataTypeComponent getDefinedComponentAt(int offset) {
|
||||
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
|
||||
return null;
|
||||
}
|
||||
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
|
||||
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
|
||||
if (index >= 0) {
|
||||
return components.get(index);
|
||||
}
|
||||
@@ -114,7 +119,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
|
||||
return null;
|
||||
}
|
||||
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
|
||||
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
|
||||
if (index >= 0) {
|
||||
return components.get(index);
|
||||
}
|
||||
@@ -240,7 +245,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
if (ordinal < 0 || ordinal >= numComponents) {
|
||||
throw new IndexOutOfBoundsException(ordinal);
|
||||
}
|
||||
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
|
||||
int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
|
||||
if (idx >= 0) {
|
||||
return components.get(idx);
|
||||
}
|
||||
@@ -248,11 +253,11 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent getComponent(int ordinal) {
|
||||
public DataTypeComponentImpl getComponent(int ordinal) {
|
||||
if (ordinal < 0 || ordinal >= numComponents) {
|
||||
throw new IndexOutOfBoundsException(ordinal);
|
||||
}
|
||||
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
|
||||
int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
|
||||
if (idx >= 0) {
|
||||
return components.get(idx);
|
||||
}
|
||||
@@ -307,7 +312,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
checkAncestry(dataType);
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
|
||||
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
|
||||
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
|
||||
|
||||
int additionalShift = 0;
|
||||
if (index >= 0) {
|
||||
@@ -443,7 +448,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
" within a defined component in " + getDisplayName() + ".");
|
||||
}
|
||||
else {
|
||||
definedIndex = Collections.binarySearch(components, new Integer(dtc.getOrdinal()),
|
||||
definedIndex = Collections.binarySearch(components, Integer.valueOf(dtc.getOrdinal()),
|
||||
ordinalComparator);
|
||||
if (definedIndex < 0) {
|
||||
definedIndex = -definedIndex - 1;
|
||||
@@ -470,7 +475,7 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
throw new IllegalArgumentException(
|
||||
"Offset " + offset + " is not in " + getDisplayName() + ".");
|
||||
}
|
||||
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
|
||||
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
|
||||
|
||||
int length = 1;
|
||||
if (index < 0) {
|
||||
@@ -485,6 +490,25 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
numComponents--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAtOffset(int offset) {
|
||||
if (offset < splitOffset - negativeLength || offset >= splitOffset + positiveLength) {
|
||||
throw new IllegalArgumentException(
|
||||
"Offset " + offset + " is not in " + getDisplayName() + ".");
|
||||
}
|
||||
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
|
||||
if (index >= 0) {
|
||||
DataTypeComponent dtc = components.remove(index);
|
||||
dtc.getDataType().removeParent(this);
|
||||
int len = dtc.getLength();
|
||||
if (len > 1) {
|
||||
int deltaLength = len - 1;
|
||||
shiftOffsets(index, deltaLength, 0);
|
||||
numComponents += deltaLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalent(DataType dataType) {
|
||||
if (dataType == this) {
|
||||
@@ -531,19 +555,19 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
public abstract BiDirectionDataType clone(DataTypeManager dtm);
|
||||
|
||||
@Override
|
||||
public void clearComponent(int index) {
|
||||
if (index < 0 || index >= numComponents) {
|
||||
throw new IndexOutOfBoundsException(index);
|
||||
public void clearComponent(int ordinal) {
|
||||
if (ordinal < 0 || ordinal >= numComponents) {
|
||||
throw new IndexOutOfBoundsException(ordinal);
|
||||
}
|
||||
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator);
|
||||
if (idx >= 0) {
|
||||
DataTypeComponent dtc = components.remove(idx);
|
||||
int index =
|
||||
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
|
||||
if (index >= 0) {
|
||||
DataTypeComponent dtc = components.remove(index);
|
||||
dtc.getDataType().removeParent(this);
|
||||
int len = dtc.getLength();
|
||||
int deltaLength = len - 1;
|
||||
// int offset = dtc.getOffset();
|
||||
if (len > 1) {
|
||||
shiftOffsets(idx, deltaLength, 0);
|
||||
int deltaLength = len - 1;
|
||||
shiftOffsets(index, deltaLength, 0);
|
||||
numComponents += deltaLength;
|
||||
}
|
||||
}
|
||||
@@ -644,7 +668,8 @@ public abstract class BiDirectionDataType extends StructureDataType
|
||||
DataTypeComponentImpl newDtc =
|
||||
new DataTypeComponentImpl(dataType, this, length, ordinal, newOffset, newName, comment);
|
||||
dataType.addParent(this);
|
||||
int index = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
|
||||
int index =
|
||||
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
|
||||
if (index < 0) {
|
||||
index = -index - 1;
|
||||
}
|
||||
|
||||
+17
-8
@@ -79,6 +79,16 @@ class StackEditorModel extends CompositeEditorModel {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowsZeroLengthComponents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowsBitFields() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void stackChangedExcternally(boolean changed) {
|
||||
stackChangedExternally = changed;
|
||||
}
|
||||
@@ -612,7 +622,7 @@ class StackEditorModel extends CompositeEditorModel {
|
||||
if (currentIndex < 0 || currentIndex >= getRowCount()) {
|
||||
return false;
|
||||
}
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
return false;
|
||||
@@ -720,7 +730,7 @@ class StackEditorModel extends CompositeEditorModel {
|
||||
if (currentIndex < 0 || currentIndex >= getRowCount()) {
|
||||
return false;
|
||||
}
|
||||
checkIsAllowableDataType(dataType, true);
|
||||
checkIsAllowableDataType(dataType);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
return false;
|
||||
@@ -788,10 +798,9 @@ class StackEditorModel extends CompositeEditorModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComponentDataTypeInstance(int index, DataTypeInstance dti) throws UsrException {
|
||||
DataType dt = dti.getDataType();
|
||||
checkIsAllowableDataType(dt, true);
|
||||
((StackFrameDataType) viewComposite).setDataType(index, dt, dti.getLength());
|
||||
public void setComponentDataTypeInstance(int index, DataType dt, int length) throws UsrException {
|
||||
checkIsAllowableDataType(dt);
|
||||
((StackFrameDataType) viewComposite).setDataType(index, dt, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -806,7 +815,7 @@ class StackEditorModel extends CompositeEditorModel {
|
||||
public void setComponentName(int rowIndex, String newName)
|
||||
throws InvalidInputException, InvalidNameException, DuplicateNameException {
|
||||
|
||||
if (newName.equals("")) {
|
||||
if (newName.trim().length() == 0) {
|
||||
newName = null;
|
||||
}
|
||||
// if (nameExistsElsewhere(newName, currentIndex)) {
|
||||
@@ -1330,7 +1339,7 @@ class StackEditorModel extends CompositeEditorModel {
|
||||
|
||||
int newLength = newDt.getLength();
|
||||
|
||||
checkIsAllowableDataType(newDt, true);
|
||||
checkIsAllowableDataType(newDt);
|
||||
newDt = DataTypeHelper.resolveDataType(newDt, viewDTM, null);
|
||||
int maxLength = getMaxReplaceLength(index);
|
||||
if (newLength <= 0) {
|
||||
|
||||
+8
-7
@@ -25,6 +25,7 @@ import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.symbol.SymbolUtilities;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
@@ -410,22 +411,22 @@ public class StackFrameDataType extends BiDirectionDataType {
|
||||
*
|
||||
* @param ordinal the ordinal
|
||||
* @param name the new name. Null indicates the default name.
|
||||
* @return true if name change was successful, else false
|
||||
*/
|
||||
public boolean setName(int ordinal, String name) {
|
||||
validateName(ordinal, name);
|
||||
DataTypeComponent comp = getComponent(ordinal);
|
||||
String fieldName = comp.getFieldName();
|
||||
if ((name != null) && ((name.length() == 0) || (isDefaultName(name)))) {
|
||||
name = null;
|
||||
}
|
||||
if (name == null) {
|
||||
if (fieldName == null) {
|
||||
return false;
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
if (name.length() == 0 || isDefaultName(name)) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
else if (name.equals(fieldName)) {
|
||||
if (SystemUtilities.isEqual(name, fieldName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DataType dt = comp.getDataType();
|
||||
int length = comp.getLength();
|
||||
String comment = comp.getComment();
|
||||
|
||||
+18
-7
@@ -163,10 +163,16 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
|
||||
// isEquiv().
|
||||
// Ensure that two components in the partial struct don't map to the same
|
||||
// component in the full structure.
|
||||
|
||||
for (DataTypeComponent partDTC : partComps) {
|
||||
DataType partDT = partDTC.getDataType();
|
||||
if (partDT.isZeroLength()) {
|
||||
// don't try to match zero length fields, so skip
|
||||
continue;
|
||||
}
|
||||
DataTypeComponent fullDTCAt = (partDTC.getDataType() instanceof BitFieldDataType)
|
||||
? getBitfieldByOffsets(full, partDTC)
|
||||
: full.getComponentAt(partDTC.getOffset());
|
||||
: getBestMatchingDTC(full, partDTC);
|
||||
if (fullDTCAt == null || fullDTCAt.getOffset() != partDTC.getOffset() ||
|
||||
!SystemUtilities.isEqual(fullDTCAt.getFieldName(), partDTC.getFieldName())) {
|
||||
return false;
|
||||
@@ -175,15 +181,20 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( part.getFlexibleArrayComponent() != null ) {
|
||||
return full.getFlexibleArrayComponent() != null &&
|
||||
isMemberFieldPartiallyCompatible(full.getFlexibleArrayComponent(),
|
||||
part.getFlexibleArrayComponent(), visitedDataTypes);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DataTypeComponent getBestMatchingDTC(Structure struct, DataTypeComponent matchCriteria) {
|
||||
for (DataTypeComponent dtc : struct.getComponentsContaining(matchCriteria.getOffset())) {
|
||||
DataType dt = dtc.getDataType();
|
||||
if (dtc.getOffset() == matchCriteria.getOffset() && !dt.isZeroLength()) {
|
||||
return dtc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isMemberFieldPartiallyCompatible(DataTypeComponent fullDTC, DataTypeComponent partDTC,
|
||||
Set<Long> visitedDataTypes) {
|
||||
DataType partDT = partDTC.getDataType();
|
||||
@@ -216,7 +227,7 @@ class DWARFDataTypeConflictHandler extends DataTypeConflictHandler {
|
||||
private DataTypeComponent getBitfieldByOffsets(Structure full, DataTypeComponent partDTC) {
|
||||
BitFieldDataType partBF = (BitFieldDataType) partDTC.getDataType();
|
||||
|
||||
DataTypeComponent fullDTC = full.getComponentAt(partDTC.getOffset());
|
||||
DataTypeComponent fullDTC = full.getComponentContaining(partDTC.getOffset());
|
||||
if (fullDTC == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+78
-176
@@ -223,11 +223,6 @@ public class DWARFDataTypeImporter {
|
||||
/**
|
||||
* Returns true if the previously imported data type should be reused.
|
||||
* <p>
|
||||
* Don't re-use previously imported single-element
|
||||
* Ghidra array datatypes because they may have actually been an empty array
|
||||
* definition and we need the special meta-data flag DWARFDataType.isEmptyArrayType
|
||||
* which is only available in a freshly created DWARFDataType.
|
||||
* <p>
|
||||
* Don't re-use empty structs (isNotYetDefined) to ensure that newer
|
||||
* definitions of the same struct are given a chance to be resolved()
|
||||
* into the DTM.
|
||||
@@ -236,10 +231,7 @@ public class DWARFDataTypeImporter {
|
||||
* @return boolean true if its okay to reuse the data type
|
||||
*/
|
||||
private boolean shouldReuseAlreadyImportedDT(DataType alreadyImportedDT) {
|
||||
return alreadyImportedDT != null &&
|
||||
!alreadyImportedDT.isNotYetDefined() &&
|
||||
!(alreadyImportedDT instanceof Array &&
|
||||
((Array) alreadyImportedDT).getNumElements() == 1);
|
||||
return alreadyImportedDT != null && !alreadyImportedDT.isNotYetDefined();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -552,12 +544,19 @@ public class DWARFDataTypeImporter {
|
||||
structSize = 0;
|
||||
}
|
||||
boolean isUnion = diea.getTag() == DWARFTag.DW_TAG_union_type;
|
||||
boolean isDecl = diea.getBool(DWARFAttribute.DW_AT_declaration, false);
|
||||
|
||||
DataType struct =
|
||||
isUnion ? new UnionDataType(dni.getParentCP(), dni.getName(), dataTypeManager)
|
||||
: new StructureDataType(dni.getParentCP(), dni.getName(), (int) structSize,
|
||||
dataTypeManager);
|
||||
|
||||
if (!isDecl && origStructSize == 0) {
|
||||
// Enable packing on 0-byte composites so they are treated as defined
|
||||
// and will not take space if used in a field in another composite.
|
||||
((Composite) struct).setToDefaultPacking();
|
||||
}
|
||||
|
||||
DWARFDataType result = new DWARFDataType(struct, dni, diea.getOffset());
|
||||
result.dsi = DWARFSourceInfo.create(diea);
|
||||
|
||||
@@ -719,6 +718,9 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
|
||||
if (union.getLength() < unionSize) {
|
||||
// NOTE: this is likely due incorrect alignment for union or one or more of its components.
|
||||
// Default alignment is 1 for non-packed unions and structures.
|
||||
|
||||
// if the Ghidra union data type is smaller than the DWARF union, pad it out
|
||||
DataType padding = Undefined.getUndefinedDataType((int) unionSize);
|
||||
try {
|
||||
@@ -773,11 +775,14 @@ public class DWARFDataTypeImporter {
|
||||
DataTypeComponent[] definedComponents = structure.getDefinedComponents();
|
||||
for (int i = 0; i < definedComponents.length; i++) {
|
||||
DataTypeComponent dtc = definedComponents[i];
|
||||
DataType dtcDT = dtc.getDataType();
|
||||
if (dtcDT.isZeroLength()) {
|
||||
continue;
|
||||
}
|
||||
int nextDTCOffset =
|
||||
(i < definedComponents.length - 1) ? definedComponents[i + 1].getOffset()
|
||||
: structure.getLength();
|
||||
int emptySpaceBetween = nextDTCOffset - dtc.getEndOffset();
|
||||
DataType dtcDT = dtc.getDataType();
|
||||
int emptySpaceBetween = nextDTCOffset - (dtc.getEndOffset() + 1);
|
||||
if (dtc.getLength() < dtcDT.getLength() && emptySpaceBetween > 0) {
|
||||
DataTypeComponent newDTC = structure.replaceAtOffset(dtc.getOffset(), dtcDT,
|
||||
Math.min(nextDTCOffset - dtc.getOffset(), dtc.getDataType().getLength()),
|
||||
@@ -802,17 +807,15 @@ public class DWARFDataTypeImporter {
|
||||
DataTypeComponent[] definedComponents = structure.getDefinedComponents();
|
||||
if (definedComponents.length > 0) {
|
||||
DataTypeComponent lastDTC = definedComponents[definedComponents.length - 1];
|
||||
return lastDTC.getOffset() + getUnpaddedDataTypeLength(lastDTC.getDataType());
|
||||
return lastDTC.getOffset() + lastDTC.getLength();
|
||||
}
|
||||
}
|
||||
return dt.getLength();
|
||||
return dt.isZeroLength() ? 0 : dt.getLength();
|
||||
}
|
||||
|
||||
private void populateStubStruct_worker(DWARFDataType ddt, StructureDataType structure,
|
||||
DIEAggregate diea, int childTagType) throws IOException, DWARFExpressionException {
|
||||
|
||||
Set<Long> conflictingZeroLenFields = getConflictingZeroLenFields(diea, childTagType);
|
||||
|
||||
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
|
||||
|
||||
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
||||
@@ -870,19 +873,6 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
}
|
||||
|
||||
if (conflictingZeroLenFields.contains(childEntry.getOffset())) {
|
||||
// Skip adding this member because it is a problematic zero-length
|
||||
// field
|
||||
DWARFUtil.appendDescription(structure,
|
||||
memberDesc("Missing member", "zero-length member", memberName, childDT,
|
||||
memberOffset, -1, -1),
|
||||
"\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean isDynamicSizedType = (childDT.dataType instanceof Dynamic ||
|
||||
childDT.dataType instanceof FactoryDataType);
|
||||
|
||||
//if (childDT.getPathName().equals(structure.getPathName()) && childDT != structure) {
|
||||
// The child we are adding has the exact same fullpath as us.
|
||||
// This can happen when DWARF namespace info gets squished and two types
|
||||
@@ -892,33 +882,7 @@ public class DWARFDataTypeImporter {
|
||||
// TODO: rename parent struct here. use .conflict or _basetype?
|
||||
//}
|
||||
|
||||
if (childDT.isEmptyArrayType && childDT.dataType instanceof Array) {
|
||||
|
||||
if (memberOffset == structure.getLength() &&
|
||||
structure.getFlexibleArrayComponent() == null) {
|
||||
DataType arrayElementType = ((Array) childDT.dataType).getDataType();
|
||||
structure.setFlexibleArrayComponent(arrayElementType, memberName, null);
|
||||
}
|
||||
else {
|
||||
DWARFUtil.appendDescription(structure,
|
||||
memberDesc("Missing member",
|
||||
"Unsupported interior flex array: " + childDT.dataType.getName(),
|
||||
memberName, childDT, memberOffset, -1, -1),
|
||||
"\n");
|
||||
|
||||
}
|
||||
|
||||
// skip the rest of this loop as it deals with adding component children members.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isBitField) {
|
||||
if (isDynamicSizedType) {
|
||||
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
|
||||
"dynamic length type", memberName, childDT, memberOffset, bitSize, -1),
|
||||
"\n");
|
||||
continue;
|
||||
}
|
||||
if (!BitFieldDataType.isValidBaseDataType(childDT.dataType)) {
|
||||
DWARFUtil.appendDescription(structure,
|
||||
memberDesc("Missing member",
|
||||
@@ -982,16 +946,14 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
else {
|
||||
String memberComment = null;
|
||||
boolean isDynamicSizedType = (childDT.dataType instanceof Dynamic ||
|
||||
childDT.dataType instanceof FactoryDataType);
|
||||
if (isDynamicSizedType) {
|
||||
memberComment = "Unsupported dynamic size data type: " + childDT.dataType;
|
||||
childDT.dataType = Undefined.getUndefinedDataType(1);
|
||||
}
|
||||
|
||||
int childLength = getUnpaddedDataTypeLength(childDT.dataType);
|
||||
if (structure.isNotYetDefined() ||
|
||||
(memberOffset + childLength > structure.getLength())) {
|
||||
// zero len struct can't have members added, even if they are zero len, or
|
||||
// member is longer than struct has storage for
|
||||
if (memberOffset + childLength > structure.getLength()) {
|
||||
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
|
||||
"exceeds parent struct len", memberName, childDT, memberOffset, -1, -1),
|
||||
"\n");
|
||||
@@ -999,21 +961,39 @@ public class DWARFDataTypeImporter {
|
||||
continue;
|
||||
}
|
||||
|
||||
DataTypeComponent existingDTC = structure.getComponentAt(memberOffset);
|
||||
if (existingDTC != null &&
|
||||
!(existingDTC.getDataType() instanceof DefaultDataType)) {
|
||||
DWARFUtil.appendDescription(structure,
|
||||
memberDesc("Missing member", "conflict with " + existingDTC.getFieldName(),
|
||||
memberName, childDT, memberOffset, -1, -1),
|
||||
"\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
DataTypeComponent dtc = structure.replaceAtOffset(memberOffset,
|
||||
childDT.dataType, childLength, memberName, memberComment);
|
||||
|
||||
// struct.replaceAtOffset() clones the childDT, which will mess up our
|
||||
DataTypeComponent dtc;
|
||||
if (DataTypeComponent.usesZeroLengthComponent(childDT.dataType)) {
|
||||
if (!isUndefinedOrZeroLenAtOffset(structure, memberOffset)) {
|
||||
DWARFUtil.appendDescription(structure, memberDesc("Missing member",
|
||||
"conflicting member at same offset", memberName, childDT,
|
||||
memberOffset, -1, -1), "\n");
|
||||
continue;
|
||||
}
|
||||
// use insertAt for zero len members to allow multiple at same offset
|
||||
dtc =
|
||||
structure.insertAtOffset(memberOffset, childDT.dataType, 0, memberName,
|
||||
memberComment);
|
||||
}
|
||||
else {
|
||||
int ordinalToReplace = getUndefinedOrdinalAt(structure, memberOffset);
|
||||
if (ordinalToReplace == -1) {
|
||||
DataTypeComponent existingDTC =
|
||||
structure.getComponentContaining(memberOffset);
|
||||
if (existingDTC != null) {
|
||||
DWARFUtil.appendDescription(structure,
|
||||
memberDesc("Missing member",
|
||||
"conflict with " + existingDTC.getFieldName(),
|
||||
memberName, childDT, memberOffset, -1, -1),
|
||||
"\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
dtc = structure.replace(ordinalToReplace, childDT.dataType, childLength,
|
||||
memberName, memberComment);
|
||||
}
|
||||
// struct.replaceAtOffset() and insertAtOffset() clones the childDT, which will mess up our
|
||||
// identity based mapping in currentImplDataTypeToDDT.
|
||||
// Update the mapping to prevent that.
|
||||
updateMapping(childDT.dataType, dtc.getDataType());
|
||||
@@ -1030,72 +1010,29 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Long> getConflictingZeroLenFields(DIEAggregate diea, int childTagType)
|
||||
throws IOException, DWARFExpressionException {
|
||||
// Returns a set of DIE offsets of zero len fields that are fighting for
|
||||
// the same offset in the parent struct
|
||||
Map<Integer, Set<Long>> zeroLenMembers = new HashMap<>();
|
||||
|
||||
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
|
||||
|
||||
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
||||
if (childDIEA.hasAttribute(DWARFAttribute.DW_AT_external)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private boolean isUndefinedOrZeroLenAtOffset(Structure struct, int offset) {
|
||||
List<DataTypeComponent> compsAt = struct.getComponentsContaining(offset);
|
||||
DataTypeComponent lastComp = !compsAt.isEmpty() ? compsAt.get(compsAt.size() - 1) : null;
|
||||
if (lastComp == null) {
|
||||
// only triggered if offset == length of struct, which is okay since we are adding
|
||||
// a zero-length component to the struct
|
||||
return true;
|
||||
}
|
||||
|
||||
Set<Long> conflictingZeroLenFields = new HashSet<>();
|
||||
for (DebugInfoEntry childEntry : diea.getHeadFragment().getChildren(childTagType)) {
|
||||
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
||||
if (childDIEA.hasAttribute(DWARFAttribute.DW_AT_external)) {
|
||||
continue;
|
||||
}
|
||||
int bitSize = childDIEA.parseInt(DWARFAttribute.DW_AT_bit_size, -1);
|
||||
boolean isBitField = bitSize != -1;
|
||||
if (isBitField) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DWARFDataType childDT = getDataType(childDIEA.getTypeRef(), null);
|
||||
if (childDT == null) {
|
||||
continue;
|
||||
}
|
||||
int memberOffset = 0;
|
||||
try {
|
||||
memberOffset =
|
||||
childDIEA.parseDataMemberOffset(DWARFAttribute.DW_AT_data_member_location, 0);
|
||||
}
|
||||
catch (DWARFExpressionException e) {
|
||||
continue;
|
||||
}
|
||||
if (!childDT.isZeroLenDT() && zeroLenMembers.containsKey(memberOffset)) {
|
||||
conflictingZeroLenFields.addAll(zeroLenMembers.get(memberOffset));
|
||||
}
|
||||
if (lastComp.getOffset() != offset) {
|
||||
return false;
|
||||
}
|
||||
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,
|
||||
@@ -1120,7 +1057,6 @@ public class DWARFDataTypeImporter {
|
||||
throws IOException, DWARFExpressionException {
|
||||
|
||||
DWARFDataType elementType = getDataType(diea.getTypeRef(), voidDDT);
|
||||
|
||||
// do a second query to see if there was a recursive loop in the call above back
|
||||
// to this datatype that resulted in this datatype being created.
|
||||
// Use that instance if possible.
|
||||
@@ -1132,7 +1068,6 @@ public class DWARFDataTypeImporter {
|
||||
// Build a list of the defined dimensions for this array type.
|
||||
// The first element in the DWARF dimension list would be where a wild-card (-1 length)
|
||||
// dimension would be defined.
|
||||
boolean isEmptyArray = false;
|
||||
List<Integer> dimensions = new ArrayList<>();
|
||||
List<DebugInfoEntry> subrangeDIEs =
|
||||
diea.getHeadFragment().getChildren(DWARFTag.DW_TAG_subrange_type);
|
||||
@@ -1146,17 +1081,14 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
// Otherwise check for an upper bound
|
||||
else if (subrangeAggr.hasAttribute(DWARFAttribute.DW_AT_upper_bound)) {
|
||||
// TODO: Check lower bound or get the difference based on
|
||||
// the language (See DWARF4 Section 5.11)
|
||||
// TODO: upperbound == -1 seems to indicate zero length array
|
||||
long upperBound =
|
||||
subrangeAggr.parseUnsignedLong(DWARFAttribute.DW_AT_upper_bound, 0xbadbeef);
|
||||
|
||||
// fix special flag values used by DWARF to indicate that the array dimension
|
||||
// is unknown. 64bit 0xffffff...s will already be -1, and 32bit 0xffff..s will
|
||||
// be forced to -1.
|
||||
// is unknown. 64bit 0xffffff...s and 32bit 0xffff..s will
|
||||
// be forced to 0.
|
||||
if (upperBound == 0xFF_FF_FF_FFL /* ie. max uint32 */ || upperBound == -1) {
|
||||
upperBound = -1;
|
||||
upperBound = 0;
|
||||
}
|
||||
else {
|
||||
numElements = upperBound + 1;
|
||||
@@ -1169,28 +1101,7 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
|
||||
if (numElements == -1) {
|
||||
// if numElements is the DWARF special flag value for unknown, set flag
|
||||
// and force the value back to something that Ghidra datatypes can handle.
|
||||
// The consumer of the resultant data type will get back an array with
|
||||
// 1 element instead of 0 elements because of Ghidra's limitations.
|
||||
// They should check the DWARFDataType.isEmptyArrayType flag (I'm looking at
|
||||
// you makeDataTypeForStruct()) if they can handle unknown length arrays.
|
||||
if (subRangeDIEIndex == 0) {
|
||||
isEmptyArray = true;
|
||||
}
|
||||
else {
|
||||
Msg.error(this,
|
||||
"Bad undefined-length array dimension for subrange " + subRangeDIEIndex +
|
||||
" for array's size in DIE: " + diea.getOffset() + ", forcing to 1");
|
||||
}
|
||||
numElements = 1;
|
||||
}
|
||||
else if (numElements == 0) {
|
||||
Msg.error(this,
|
||||
"Unsupported value [" + numElements + "] for array's size in DIE: " +
|
||||
diea.getOffset() + ", forcing to 1");
|
||||
numElements = 1;
|
||||
isEmptyArray = true;
|
||||
numElements = 0;
|
||||
}
|
||||
else if (numElements > Integer.MAX_VALUE) {
|
||||
Msg.error(this, "Bad value [" + numElements + "] for array's size in DIE: " +
|
||||
@@ -1205,7 +1116,7 @@ public class DWARFDataTypeImporter {
|
||||
for (int i = dimensions.size() - 1; i >= 0; i--) {
|
||||
int numElements = dimensions.get(i);
|
||||
ArrayDataType subArray =
|
||||
new ArrayDataType(dt, numElements, dt.getLength(), dataTypeManager);
|
||||
new ArrayDataType(dt, numElements, -1, dataTypeManager);
|
||||
if (dt == elementType.dataType) {
|
||||
updateMapping(dt, subArray.getDataType());
|
||||
}
|
||||
@@ -1213,7 +1124,6 @@ public class DWARFDataTypeImporter {
|
||||
}
|
||||
|
||||
DWARFDataType result = new DWARFDataType(dt, null, diea.getOffset());
|
||||
result.isEmptyArrayType = isEmptyArray;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1445,7 +1355,6 @@ public class DWARFDataTypeImporter {
|
||||
|
||||
static class DWARFDataType {
|
||||
DataType dataType;
|
||||
boolean isEmptyArrayType;
|
||||
DWARFNameInfo dni;
|
||||
DWARFSourceInfo dsi;
|
||||
Set<Long> offsets = new HashSet<>();
|
||||
@@ -1473,12 +1382,5 @@ public class DWARFDataTypeImporter {
|
||||
Collectors.joining(","));
|
||||
}
|
||||
|
||||
boolean isZeroLenDT() {
|
||||
DataType tmpDt =
|
||||
(dataType instanceof TypeDef) ? ((TypeDef) dataType).getBaseDataType() : dataType;
|
||||
return isEmptyArrayType || tmpDt.isNotYetDefined() ||
|
||||
tmpDt.getLength() == 0 /* this can't happen right now, but never know for future */;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+70
-21
@@ -24,6 +24,7 @@ import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||
import ghidra.app.util.bin.format.dwarf4.*;
|
||||
import ghidra.app.util.bin.format.dwarf4.encoding.*;
|
||||
import ghidra.app.util.bin.format.dwarf4.expression.*;
|
||||
import ghidra.program.database.data.DataTypeUtilities;
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
@@ -258,6 +259,19 @@ public class DWARFFunctionImporter {
|
||||
DWARFTag.DW_TAG_formal_parameter)) {
|
||||
DIEAggregate childDIEA = prog.getAggregate(childEntry);
|
||||
|
||||
DataType childDT = dwarfDTM.getDataType(childDIEA.getTypeRef(), null);
|
||||
if (childDT == null || DataTypeComponent.usesZeroLengthComponent(childDT)) {
|
||||
String paramName =
|
||||
childDIEA.getString(DWARFAttribute.DW_AT_name, "param" + formalParams.size());
|
||||
Msg.warn(this, "DWARF: zero-length function parameter " + paramName +
|
||||
":" + childDT.getName() + ", omitting from definition of " +
|
||||
dfunc.dni.getName() + "@" + dfunc.address);
|
||||
// skip this parameter because its data type is a zero-width type that typically does
|
||||
// not generate code. If this varies compiler-to-compiler, setting
|
||||
// skipFuncSignature=true may be a better choice
|
||||
continue;
|
||||
}
|
||||
|
||||
Parameter formalParam = createFormalParameter(childDIEA);
|
||||
if (formalParam == null) {
|
||||
skipFuncSignature = true;
|
||||
@@ -581,27 +595,7 @@ public class DWARFFunctionImporter {
|
||||
}
|
||||
}
|
||||
else if (exprEvaluator.getLastRegister() == null) {
|
||||
dvar.dni = dvar.dni.replaceType(null /*nothing matches static global var*/);
|
||||
if (res != 0) {
|
||||
// If the expression evaluated to a static address other than '0'
|
||||
Address staticVariableAddress = toAddr(res + prog.getProgramBaseAddressFixup());
|
||||
if (variablesProcesesed.contains(staticVariableAddress)) {
|
||||
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());
|
||||
}
|
||||
processStaticVar(res, dvar, diea);
|
||||
return null;// Don't return the variable to be associated with the function
|
||||
}
|
||||
else {
|
||||
@@ -615,6 +609,61 @@ public class DWARFFunctionImporter {
|
||||
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.
|
||||
*
|
||||
|
||||
+3
-11
@@ -108,9 +108,8 @@ public class PEx64UnwindInfoDataType extends DynamicDataType {
|
||||
if (hasExceptionHandler(flags) || hasUnwindHandler(flags)) {
|
||||
struct.add(IBO32, "ExceptionHandler", null);
|
||||
if (hasUnwindHandler(flags)) {
|
||||
// NOTE: Dynamic structure does not reflect flex-array
|
||||
struct.setFlexibleArrayComponent(UnsignedLongDataType.dataType, "ExceptionData",
|
||||
null);
|
||||
struct.add(new ArrayDataType(UnsignedLongDataType.dataType, 0, -1),
|
||||
"ExceptionData", null);
|
||||
}
|
||||
}
|
||||
else if (hasChainedUnwindInfo(flags)) {
|
||||
@@ -132,14 +131,7 @@ public class PEx64UnwindInfoDataType extends DynamicDataType {
|
||||
if (struct == null) {
|
||||
return null;
|
||||
}
|
||||
DataTypeComponent[] components = struct.getComponents();
|
||||
if (struct.hasFlexibleArrayComponent()) {
|
||||
DataTypeComponent[] newArray = new DataTypeComponent[components.length + 1];
|
||||
System.arraycopy(components, 0, newArray, 0, components.length);
|
||||
newArray[components.length] = struct.getFlexibleArrayComponent();
|
||||
components = newArray;
|
||||
}
|
||||
return components;
|
||||
return struct.getComponents();
|
||||
}
|
||||
|
||||
private boolean hasExceptionHandler(int flags) {
|
||||
|
||||
@@ -43,17 +43,8 @@ public class CompositeHandler {
|
||||
if (dec == null || dec.getDataType() == null) {
|
||||
return;
|
||||
}
|
||||
if (parent instanceof Structure) {
|
||||
// ensure that only the last component establishes a structure's flex array
|
||||
((Structure) parent).clearFlexibleArrayComponent();
|
||||
}
|
||||
// not a bitfield, just add the data type to composite
|
||||
if (!dec.isBitField()) {
|
||||
if (dec.isFlexArray() && parent instanceof Structure) {
|
||||
((Structure) parent).setFlexibleArrayComponent(dec.getDataType(), dec.getName(),
|
||||
dec.getComment());
|
||||
return;
|
||||
}
|
||||
parent.add(dec.getDataType(), dec.getName(), dec.getComment());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ public class Declaration {
|
||||
private String name;
|
||||
private String comment;
|
||||
private int bitSize = -1;
|
||||
private boolean flexArray = false; // true if this is a zero size flex array component
|
||||
|
||||
public Declaration() {
|
||||
super();
|
||||
@@ -155,11 +154,4 @@ public class Declaration {
|
||||
bitSize = bits;
|
||||
}
|
||||
|
||||
public void setFlexArray(boolean b) {
|
||||
flexArray = b;
|
||||
}
|
||||
|
||||
public boolean isFlexArray() {
|
||||
return flexArray;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -110,7 +110,11 @@ public class ArrayDataTypeHTMLRepresentation extends HTMLDataTypeRepresentation
|
||||
}
|
||||
|
||||
private ValidatableLine buildFooterContent() {
|
||||
return new TextLine("Size: " + array.getLength());
|
||||
int len = array.getLength();
|
||||
if (array.isZeroLength()) {
|
||||
return new TextLine("Size: 0 (reported size is " + len + ")");
|
||||
}
|
||||
return new TextLine("Size: " + len);
|
||||
}
|
||||
|
||||
private String buildHTMLText(ValidatableLine header, String body, ValidatableLine info,
|
||||
|
||||
+5
-25
@@ -100,11 +100,11 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
|
||||
|
||||
protected List<ValidatableLine> buildAlignmentText(Composite dataType) {
|
||||
List<ValidatableLine> list = new ArrayList<>();
|
||||
String alignStr = CompositeDataTypeImpl.getMinAlignmentString(dataType);
|
||||
String alignStr = CompositeInternal.getMinAlignmentString(dataType);
|
||||
if (alignStr != null && alignStr.length() != 0) {
|
||||
list.add(new TextLine(alignStr));
|
||||
}
|
||||
String packStr = CompositeDataTypeImpl.getPackingString(dataType);
|
||||
String packStr = CompositeInternal.getPackingString(dataType);
|
||||
if (packStr != null && packStr.length() != 0) {
|
||||
list.add(new TextLine(packStr));
|
||||
}
|
||||
@@ -117,10 +117,6 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
|
||||
|
||||
private List<ValidatableLine> buildContent(Composite comp) {
|
||||
List<ValidatableLine> list = new ArrayList<>();
|
||||
if (comp.isZeroLength()) {
|
||||
return list;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
DataTypeComponent[] components = comp.getComponents();
|
||||
for (DataTypeComponent dataTypeComponent : components) {
|
||||
@@ -135,27 +131,14 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
|
||||
locatableType = getLocatableDataType(dataType);
|
||||
}
|
||||
|
||||
list.add(new DataTypeLine(fieldName, type, comment, locatableType, false));
|
||||
list.add(new DataTypeLine(fieldName, type, comment, locatableType));
|
||||
if (count++ >= MAX_COMPONENT_COUNT) {
|
||||
// Prevent a ridiculous number of components from consuming all memory.
|
||||
list.add(new DataTypeLine("", "Warning: Too many components to display...", "",
|
||||
null, false));
|
||||
list.add(
|
||||
new DataTypeLine("", "Warning: Too many components to display...", "", null));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (comp instanceof Structure) {
|
||||
Structure struct = (Structure) comp;
|
||||
DataTypeComponent flexibleArrayComponent = struct.getFlexibleArrayComponent();
|
||||
if (count < MAX_COMPONENT_COUNT && flexibleArrayComponent != null) {
|
||||
String fieldName = flexibleArrayComponent.getFieldName();
|
||||
String comment = flexibleArrayComponent.getComment();
|
||||
DataType dataType = flexibleArrayComponent.getDataType();
|
||||
String type = dataType.getDisplayName();
|
||||
DataType locatableType = getLocatableDataType(dataType);
|
||||
list.add(new DataTypeLine(fieldName, type, comment, locatableType, true));
|
||||
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -239,9 +222,6 @@ public class CompositeDataTypeHTMLRepresentation extends HTMLDataTypeRepresentat
|
||||
StringBuilder lineBuffer = new StringBuilder();
|
||||
DataTypeLine line = (DataTypeLine) iterator.next();
|
||||
String typeName = generateTypeName(line, trim);
|
||||
if (line.isFlexibleArray()) {
|
||||
typeName += "[0]";
|
||||
}
|
||||
|
||||
int fieldLength = ToolTipUtils.LINE_LENGTH / 2;
|
||||
String fieldName = line.getName();
|
||||
|
||||
@@ -29,7 +29,6 @@ public class DataTypeLine implements ValidatableLine {
|
||||
private String name;
|
||||
private String comment;
|
||||
private DataType dataType;
|
||||
private boolean isFlexibleArray;
|
||||
|
||||
private Color typeColor;
|
||||
private Color nameColor;
|
||||
@@ -37,9 +36,8 @@ public class DataTypeLine implements ValidatableLine {
|
||||
|
||||
private ValidatableLine validationLine;
|
||||
|
||||
DataTypeLine(String name, String type, String comment, DataType dt, boolean isFlexibleArray) {
|
||||
DataTypeLine(String name, String type, String comment, DataType dt) {
|
||||
this.dataType = dt;
|
||||
this.isFlexibleArray = isFlexibleArray;
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
@@ -49,17 +47,9 @@ public class DataTypeLine implements ValidatableLine {
|
||||
this.comment = comment == null ? "" : comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if data type should be treated as flexible array
|
||||
* @return true if data type should be treated as flexible array
|
||||
*/
|
||||
public boolean isFlexibleArray() {
|
||||
return isFlexibleArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidatableLine copy() {
|
||||
return new DataTypeLine(name, type, comment, dataType, isFlexibleArray);
|
||||
return new DataTypeLine(name, type, comment, dataType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,7 @@ import ghidra.util.exception.AssertException;
|
||||
|
||||
public class EmptyDataTypeLine extends DataTypeLine implements PlaceHolderLine {
|
||||
public EmptyDataTypeLine() {
|
||||
super("", "", "", null, false);
|
||||
super("", "", "", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+64
-35
@@ -20,6 +20,8 @@ import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.widgets.fieldpanel.field.*;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
import docking.widgets.fieldpanel.support.FieldUtils;
|
||||
@@ -245,19 +247,32 @@ public class PreCommentFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
private String[] getDataAutoComments(Data data) {
|
||||
|
||||
// Build flexible array comment
|
||||
Address addr = data.getMinAddress().previous();
|
||||
if (addr != null) {
|
||||
return getFlexArrayComment(data, addr);
|
||||
}
|
||||
return null;
|
||||
return getPreceedingComponentAutoComment(data);
|
||||
}
|
||||
|
||||
private String[] getFlexArrayComment(Data data, Address addr) {
|
||||
/**
|
||||
* A composite which immediately preceeds the current address may contain trailing zero-length
|
||||
* components which implicitly refer to this address and are not rendered by the opened composite.
|
||||
* This comment is intended to convey the existence of such hidden components which correspond
|
||||
* to addr.
|
||||
* <br>
|
||||
* NOTE: Implementation only provides comment for one trailing zero-length component. This could
|
||||
* be improved to return a comment for all applicable trailing zero-length components.
|
||||
* @param data data location whose pre-comment is currently be generated
|
||||
* @return auto-comment or null
|
||||
*/
|
||||
private String[] getPreceedingComponentAutoComment(Data data) {
|
||||
|
||||
// NOTE: A zero-length composite has a length of 1 which may cause it to improperly consume
|
||||
// the address location which actually corresponds to a trailing zero-length
|
||||
// component.
|
||||
|
||||
int levelsToIgnore = 0;
|
||||
String label = null;
|
||||
Address prevDataAddr = data.getMinAddress().previous();
|
||||
if (prevDataAddr == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int[] cpath = data.getComponentPath();
|
||||
if (cpath != null && cpath.length > 0) {
|
||||
@@ -273,46 +288,60 @@ public class PreCommentFieldFactory extends FieldFactory {
|
||||
}
|
||||
else {
|
||||
Program p = data.getProgram();
|
||||
data = p.getListing().getDefinedDataContaining(addr);
|
||||
if (data == null || !(data.isStructure() || data.isDynamic())) {
|
||||
data = p.getListing().getDefinedDataContaining(prevDataAddr);
|
||||
if (data == null || !(data.isStructure() || data.isDynamic())) { // FIXME!! refer to DynamicDataType which has components - Union?
|
||||
return null;
|
||||
}
|
||||
Symbol s = p.getSymbolTable().getPrimarySymbol(data.getAddress());
|
||||
label = s != null ? s.getName(true) : data.getDataType().getName();
|
||||
}
|
||||
|
||||
// locate deepest structure containing addr which will be checked for flex array
|
||||
DataTypeComponent lastDtc = null;
|
||||
while (true) {
|
||||
int offset = (int) addr.subtract(data.getMinAddress());
|
||||
Data component = data.getComponentAt(offset);
|
||||
if (component == null || !component.isStructure()) {
|
||||
DataType dt = data.getDataType();
|
||||
|
||||
if (dt instanceof Structure) {
|
||||
Structure struct = (Structure) dt;
|
||||
lastDtc = struct.getComponentContaining(struct.getLength());
|
||||
int lastDtcOrdinal = struct.getNumComponents() - 1;
|
||||
while (lastDtc != null && lastDtc.isBitFieldComponent() &&
|
||||
lastDtc.getOrdinal() < lastDtcOrdinal) {
|
||||
lastDtc = struct.getComponent(lastDtc.getOrdinal() + 1);
|
||||
}
|
||||
}
|
||||
else if (dt instanceof DynamicDataType) {
|
||||
DynamicDataType ddt = (DynamicDataType) dt;
|
||||
lastDtc = ddt.getComponentAt(data.getLength(), data);
|
||||
int lastDtcOrdinal = ddt.getNumComponents(data);
|
||||
while (lastDtc != null && lastDtc.isBitFieldComponent() &&
|
||||
lastDtc.getOrdinal() < lastDtcOrdinal) {
|
||||
lastDtc = ddt.getComponent(lastDtc.getOrdinal() + 1, data);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDtc == null || lastDtc.getLength() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Data component = data.getComponent(lastDtc.getOrdinal());
|
||||
if (component == null) {
|
||||
return null;
|
||||
}
|
||||
data = component;
|
||||
}
|
||||
|
||||
return buildFlexArrayComment(data, levelsToIgnore, label);
|
||||
}
|
||||
|
||||
private String[] buildFlexArrayComment(Data data, int levelsToIgnore, String label) {
|
||||
|
||||
DataType dt = data.getBaseDataType();
|
||||
|
||||
DataTypeComponent flexComponent = null;
|
||||
if (dt instanceof Structure) {
|
||||
flexComponent = ((Structure) dt).getFlexibleArrayComponent();
|
||||
}
|
||||
else if (dt instanceof DynamicDataType) {
|
||||
flexComponent = ((DynamicDataType) dt).getFlexibleArrayComponent(data);
|
||||
}
|
||||
|
||||
if (flexComponent == null) {
|
||||
if (lastDtc == null || lastDtc.isBitFieldComponent()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return buildZeroLengthComponentAutoComment(lastDtc, data, levelsToIgnore, label);
|
||||
}
|
||||
|
||||
String fieldName = flexComponent.getFieldName();
|
||||
if (fieldName == null) {
|
||||
fieldName = flexComponent.getDefaultFieldName();
|
||||
private String[] buildZeroLengthComponentAutoComment(DataTypeComponent lastZeroLengthComponent, Data data, int levelsToIgnore, String label) {
|
||||
|
||||
String fieldName = lastZeroLengthComponent.getFieldName();
|
||||
if (StringUtils.isEmpty(fieldName)) {
|
||||
fieldName = lastZeroLengthComponent.getDefaultFieldName();
|
||||
}
|
||||
|
||||
StringBuilder flexName = new StringBuilder(fieldName);
|
||||
@@ -331,8 +360,8 @@ public class PreCommentFieldFactory extends FieldFactory {
|
||||
flexName.insert(0, label + ".");
|
||||
}
|
||||
|
||||
return new String[] { "Flexible Array: " + flexComponent.getDataType().getName() + "[] " +
|
||||
flexName.toString() };
|
||||
return new String[] { "Zero-length Component: " + lastZeroLengthComponent.getDataType().getName() + " " +
|
||||
flexName.toString() };
|
||||
}
|
||||
|
||||
private ListingTextField getTextField(String[] comments, String[] autoComment,
|
||||
|
||||
+3
-3
@@ -414,11 +414,11 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // Structure
|
||||
else { // Structure and DynamicDataType
|
||||
List<Data> dataList = data.getComponentsContaining((int) addr.subtract(dataAddr));
|
||||
if (dataList != null) { // nested flex-arrays can cause odd behavior
|
||||
if (dataList != null) {
|
||||
for (Data subData : dataList) {
|
||||
// The only case where more than one subData exists is for bit-fields.
|
||||
// The only case where more than one subData exists is for bit-fields and zero-length data.
|
||||
// Depending upon the packing, bit-fields at different offsets may overlap
|
||||
if (subData.getMinAddress().equals(addr)) {
|
||||
list.add(subData);
|
||||
|
||||
@@ -649,7 +649,8 @@ public class DataTypesXmlMgr {
|
||||
|
||||
private void writerMember(XmlWriter writer, DataTypeComponent member) {
|
||||
XmlAttributes attrs = new XmlAttributes();
|
||||
// TODO: how should we output bitfields (packed/non-packed) and flex array
|
||||
// TODO: how should we output bitfields (packed/non-packed)
|
||||
// TODO: multiple components at same offset (e.g., zero-length arrays) could throw-off IDA XML import
|
||||
attrs.addAttribute("OFFSET", member.getOffset(), true);
|
||||
attrs.addAttribute("DATATYPE", member.getDataType().getDisplayName());
|
||||
attrs.addAttribute("DATATYPE_NAMESPACE", member.getDataType().getCategoryPath().getPath());
|
||||
|
||||
@@ -1032,7 +1032,7 @@ public class CodeUnitFormat {
|
||||
DataType dataType = data.getDataType();
|
||||
int length = data.getLength();
|
||||
|
||||
if (length < dataType.getLength()) {
|
||||
if ((length != 0 || !dataType.isZeroLength()) && dataType.getLength() > length) {
|
||||
representationList.add("Data type \"" + dataType.getDisplayName() +
|
||||
"\" is too big for available space. Size = " + dataType.getLength() +
|
||||
" bytes, available = " + length + " bytes");
|
||||
|
||||
@@ -882,22 +882,6 @@ public class ProgramDiffDetails {
|
||||
for (int index2 = i; index2 < compDt2.length; index2++) {
|
||||
getComponentInfo(compDt2[index2], buf2, newIndent);
|
||||
}
|
||||
|
||||
if (dt1 instanceof Structure) {
|
||||
// dt2 is also Structure - check for flex array component
|
||||
DataTypeComponent flexDtc1 = ((Structure) dt1).getFlexibleArrayComponent();
|
||||
DataTypeComponent flexDtc2 = ((Structure) dt2).getFlexibleArrayComponent();
|
||||
if (flexDtc1 != null) {
|
||||
getComponentInfo(flexDtc1, buf1, newIndent);
|
||||
}
|
||||
if (flexDtc2 != null) {
|
||||
getComponentInfo(flexDtc2, buf2, newIndent);
|
||||
}
|
||||
if (flexDtc1 != null && flexDtc2 != null) {
|
||||
compareSubDataTypes(flexDtc1.getDataType(), flexDtc2.getDataType(), buf1, buf2,
|
||||
newIndent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void compareDataCUs(Data d1, Data d2, StringBuffer buf1, StringBuffer buf2,
|
||||
@@ -926,22 +910,13 @@ public class ProgramDiffDetails {
|
||||
if (fieldName == null) {
|
||||
fieldName = dtc.getDefaultFieldName();
|
||||
}
|
||||
if (dtc.isFlexibleArrayComponent()) {
|
||||
buf.append(indent + "Offset=" + DiffUtility.toSignedHexString(offset) + " " +
|
||||
"Ordinal=" + ordinal + " " + fieldName + " " +
|
||||
actualDt.getMnemonic(actualDt.getDefaultSettings()) + "[]" + " " +
|
||||
getCategoryName(actualDt) + " " + "DataTypeSize=" + actualDt.getLength() +
|
||||
" (flexible array) " + ((comment != null) ? comment : "") + " " + newLine);
|
||||
}
|
||||
else {
|
||||
// TODO: how should we display bitfields?
|
||||
buf.append(indent + "Offset=" + DiffUtility.toSignedHexString(offset) + " " +
|
||||
"Ordinal=" + ordinal + " " + fieldName + " " +
|
||||
actualDt.getMnemonic(actualDt.getDefaultSettings()) + " " +
|
||||
getCategoryName(actualDt) + " " + "DataTypeSize=" + actualDt.getLength() + " " +
|
||||
"ComponentSize=" + dtc.getLength() + " " + ((comment != null) ? comment : "") +
|
||||
" " + newLine);
|
||||
}
|
||||
// TODO: how should we display bitfields?
|
||||
buf.append(indent + "Offset=" + DiffUtility.toSignedHexString(offset) + " " + "Ordinal=" +
|
||||
ordinal + " " + fieldName + " " + actualDt.getMnemonic(actualDt.getDefaultSettings()) +
|
||||
" " + getCategoryName(actualDt) + " " + "DataTypeSize=" +
|
||||
(actualDt.isZeroLength() ? 0 : actualDt.getLength()) + " " + "ComponentSize=" +
|
||||
dtc.getLength() + " " + ((comment != null) ? comment : "") +
|
||||
" " + newLine);
|
||||
return actualDt;
|
||||
}
|
||||
|
||||
@@ -983,18 +958,17 @@ public class ProgramDiffDetails {
|
||||
Data data = (Data) cu;
|
||||
DataType dt = data.getDataType();
|
||||
if (dt instanceof Composite) {
|
||||
DataTypeComponent[] compDt = ((Composite) dt).getComponents();
|
||||
for (DataTypeComponent element : compDt) {
|
||||
int offset = element.getOffset();
|
||||
String comment = element.getComment();
|
||||
String fieldName = element.getFieldName();
|
||||
DataTypeComponent[] components = ((Composite) dt).getComponents();
|
||||
for (DataTypeComponent dtc : components) {
|
||||
int offset = dtc.getOffset();
|
||||
String comment = dtc.getComment();
|
||||
String fieldName = dtc.getFieldName();
|
||||
if (fieldName == null) {
|
||||
fieldName = "field" + offset;
|
||||
}
|
||||
buf.append(newIndent + min.add(offset) + " " + element.getFieldName() +
|
||||
" " + element.getDataType().getName() + " " + "length=" +
|
||||
element.getLength() + " " +
|
||||
|
||||
buf.append(newIndent + min.add(offset) + " " + dtc.getFieldName() + " " +
|
||||
dtc.getDataType().getName() + " " + "length=" +
|
||||
dtc.getLength() + " " +
|
||||
((comment != null) ? comment : "") + " " + newLine);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,9 +573,16 @@ public class DataTypeParser {
|
||||
|
||||
ArraySpecPiece(String piece) throws InvalidDataTypeException {
|
||||
if (piece.startsWith("[") && piece.endsWith("]")) {
|
||||
String elementCountStr = piece.substring(1, piece.length() - 1);
|
||||
try {
|
||||
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;
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
|
||||
@@ -1968,14 +1968,7 @@ Declaration DirectDeclarator(Declaration dt, DataType container) : {
|
||||
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
|
||||
Integer iSize = (Integer) iterator.next();
|
||||
DataType decDt = dec.getDataType();
|
||||
if (iSize == 0 && container != null) {
|
||||
dec.setFlexArray(true);
|
||||
break;
|
||||
} else if (iSize == 0) {
|
||||
dec.setDataType(dtMgr.getPointer(decDt));
|
||||
} else {
|
||||
dec.setDataType(new ArrayDataType(decDt, iSize, decDt.getLength()));
|
||||
}
|
||||
dec.setDataType(new ArrayDataType(decDt, iSize, decDt.getLength()));
|
||||
}
|
||||
//System.out.println("Array expr: for " + dec.getName() + " make an array " + dt.getName() + "["+size+"]");
|
||||
}
|
||||
|
||||
+18
-19
@@ -27,7 +27,7 @@ import ghidra.program.database.ProgramModifierListener;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Tests for merging data types.
|
||||
@@ -66,12 +66,11 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
struct.insertBitFieldAt(3, 2, 6, td, 2, "bf1", null);
|
||||
struct.insertBitFieldAt(3, 2, 4, td, 2, "bf2", null);
|
||||
struct.add(new QWordDataType());
|
||||
|
||||
struct.setFlexibleArrayComponent(td, "flex", "my flex");
|
||||
struct.add(new ArrayDataType(td, 0, -1), 0, "flex", "my flex");
|
||||
|
||||
structRef.set(struct);
|
||||
|
||||
c.removeCategory("Category5", TaskMonitorAdapter.DUMMY);
|
||||
c.removeCategory("Category5", TaskMonitor.DUMMY);
|
||||
Category c5 = c.createCategory("Category5");
|
||||
c5.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
commit = true;
|
||||
@@ -187,7 +186,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||
try {
|
||||
Structure s = (Structure) c.getDataType("IntStruct");
|
||||
c.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
c.remove(s, TaskMonitor.DUMMY);
|
||||
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0, dtm);
|
||||
s.add(new QWordDataType(), "f1", "my f1");
|
||||
s.add(new FloatDataType());
|
||||
@@ -220,7 +219,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
|
||||
Structure s = (Structure) dt;
|
||||
assertEquals("my f1", s.getComponent(0).getComment());
|
||||
DataTypeComponent dtc = s.getComponentAt(17);
|
||||
DataTypeComponent dtc = s.getComponentContaining(17);
|
||||
assertEquals(7, dtc.getOrdinal());
|
||||
assertEquals("my bf1", dtc.getComment());
|
||||
}
|
||||
@@ -243,7 +242,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||
try {
|
||||
Structure s = (Structure) c.getDataType("IntStruct");
|
||||
c.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
c.remove(s, TaskMonitor.DUMMY);
|
||||
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0);
|
||||
s.add(new QWordDataType());
|
||||
s.add(new FloatDataType());
|
||||
@@ -440,7 +439,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -479,7 +478,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
|
||||
try {
|
||||
DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -530,7 +529,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -581,7 +580,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"FloatStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -611,7 +610,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -659,7 +658,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -715,7 +714,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -734,7 +733,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -963,7 +962,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -992,7 +991,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
dtm.remove(dt, TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -1050,7 +1049,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
Structure s = (Structure) dt;
|
||||
s.add(new ByteDataType());
|
||||
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
|
||||
parent.removeCategory("Category3", TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
@@ -1116,7 +1115,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||
Structure s = (Structure) dt;
|
||||
s.add(new ByteDataType());
|
||||
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
|
||||
parent.removeCategory("Category3", TaskMonitor.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user