names = new ArrayList<>();
for (DataTypeComponent dataTypeComponent : components) {
+ if (dataTypeComponent.isBitFieldComponent()) {
+ continue;
+ }
String fieldName = dataTypeComponent.getFieldName();
if (StringUtils.isBlank(fieldName)) {
continue;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java
index d46bb45c28..f9f330949c 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ToolTipUtils.java
@@ -92,6 +92,9 @@ public class ToolTipUtils {
else if (dataType instanceof Array) {
return new ArrayDataTypeHTMLRepresentation((Array) dataType);
}
+ else if (dataType instanceof BitFieldDataType) {
+ return new BitFieldDataTypeHTMLRepresentation((BitFieldDataType) dataType);
+ }
else {
return new DefaultDataTypeHTMLRepresentation(dataType);
}
@@ -203,8 +206,9 @@ public class ToolTipUtils {
buf.append("");
buf.append(colorString(Color.BLACK, friendlyEncodeHTML(param.getDataType().getName())));
buf.append(" | ");
- Color paramColor = param.getFunction().hasCustomVariableStorage()
- ? PARAM_CUSTOM_STORAGE_COLOR : PARAM_DYNAMIC_STORAGE_COLOR;
+ Color paramColor =
+ param.getFunction().hasCustomVariableStorage() ? PARAM_CUSTOM_STORAGE_COLOR
+ : PARAM_DYNAMIC_STORAGE_COLOR;
buf.append(
colorString(paramColor, friendlyEncodeHTML(param.getVariableStorage().toString())));
buf.append(" | ");
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/BitFieldDataTypeHTMLRepresentation.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/BitFieldDataTypeHTMLRepresentation.java
new file mode 100644
index 0000000000..ca25ffbe37
--- /dev/null
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/BitFieldDataTypeHTMLRepresentation.java
@@ -0,0 +1,63 @@
+/* ###
+ * 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.util.html;
+
+import ghidra.app.util.ToolTipUtils;
+import ghidra.program.model.data.BitFieldDataType;
+import ghidra.program.model.data.DataType;
+import ghidra.util.HTMLUtilities;
+import ghidra.util.exception.AssertException;
+
+public class BitFieldDataTypeHTMLRepresentation extends HTMLDataTypeRepresentation {
+
+ public BitFieldDataTypeHTMLRepresentation(BitFieldDataType bitFieldDt) {
+ super(buildHTMLText(bitFieldDt));
+ }
+
+ private static String buildHTMLText(BitFieldDataType bitFieldDt) {
+ StringBuffer buffer = new StringBuffer();
+ String description = bitFieldDt.getDescription();
+
+ if (description == null || description.length() == 0) {
+ description = bitFieldDt.getDisplayName();
+ }
+ description = HTMLUtilities.friendlyEncodeHTML(description);
+ buffer.append(description);
+
+ DataType baseDataType = bitFieldDt.getBaseDataType();
+
+ buffer.append(BR).append(BR);
+ buffer.append("Bitfield Base Data Type: ").append(BR);
+
+ buffer.append(INDENT_OPEN);
+ HTMLDataTypeRepresentation representation =
+ ToolTipUtils.getHTMLRepresentation(baseDataType);
+ String baseHTML = representation.getHTMLContentString();
+ buffer.append(baseHTML);
+ if (baseHTML.indexOf(LENGTH_PREFIX) < 0) {
+ addDataTypeLength(baseDataType, buffer);
+ }
+ buffer.append(INDENT_CLOSE);
+
+ return buffer.toString();
+ }
+
+ @Override
+ public HTMLDataTypeRepresentation[] diff(HTMLDataTypeRepresentation otherRepresentation) {
+ throw new AssertException("Bitfield types are not diffable at this time");
+ }
+
+}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java
index c3014dfbd4..45232d0c92 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/html/TypeDefDataTypeHTMLRepresentation.java
@@ -138,7 +138,7 @@ public class TypeDefDataTypeHTMLRepresentation extends HTMLDataTypeRepresentatio
// body
buffy.append(BR);
- buffy.append("TypeDef Base Data Type: ").append(BR).append(BR);
+ buffy.append("TypeDef Base Data Type: ").append(BR);
iterator = bodyLines.iterator();
for (; iterator.hasNext();) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java
index 942551e787..d79a4ef20c 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/DataTypesXmlMgr.java
@@ -648,6 +648,7 @@ public class DataTypesXmlMgr {
private void writerMember(XmlWriter writer, DataTypeComponent member) {
XmlAttributes attrs = new XmlAttributes();
+ // TODO: how should we output bitfields (aligned/unaligned) and flex array
attrs.addAttribute("OFFSET", member.getOffset(), true);
attrs.addAttribute("DATATYPE", member.getDataType().getDisplayName());
attrs.addAttribute("DATATYPE_NAMESPACE", member.getDataType().getCategoryPath().getPath());
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java
index 162d24caaf..a19a196853 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java
@@ -935,6 +935,7 @@ public class ProgramDiffDetails {
" (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()) + " " +
@@ -1505,8 +1506,8 @@ public class ProgramDiffDetails {
private boolean addSpecificCommentDetails(int commentType, String commentName) {
boolean hasCommentDiff = false;
try {
- for (Address p1Address = minP1Address; p1Address
- .compareTo(maxP1Address) <= 0; p1Address = p1Address.add(1L)) {
+ for (Address p1Address = minP1Address; p1Address.compareTo(
+ maxP1Address) <= 0; p1Address = p1Address.add(1L)) {
Address p2Address = SimpleDiffUtility.getCompatibleAddress(p1, p1Address, p2);
String noComment = "No " + commentName + ".";
String cmt1 = l1.getComment(commentType, p1Address);
@@ -2209,9 +2210,8 @@ public class ProgramDiffDetails {
for (String propertyName : names1) {
if (cu.hasProperty(propertyName)) {
// Handle case where the class for a Saveable property is missing (unsupported).
- if (cu.getProgram()
- .getListing()
- .getPropertyMap(propertyName) instanceof UnsupportedMapDB) {
+ if (cu.getProgram().getListing().getPropertyMap(
+ propertyName) instanceof UnsupportedMapDB) {
buf.append(
indent2 + propertyName + " is an unsupported property." + newLine);
continue;
@@ -2282,8 +2282,8 @@ public class ProgramDiffDetails {
BookmarkManager bmm1 = p1.getBookmarkManager();
BookmarkManager bmm2 = p2.getBookmarkManager();
try {
- for (Address p1Address = minP1Address; p1Address
- .compareTo(maxP1Address) <= 0; p1Address = p1Address.add(1)) {
+ for (Address p1Address = minP1Address; p1Address.compareTo(
+ maxP1Address) <= 0; p1Address = p1Address.add(1)) {
Address p2Address = SimpleDiffUtility.getCompatibleAddress(p1, p1Address, p2);
Bookmark[] marks1 = bmm1.getBookmarks(p1Address);
Arrays.sort(marks1, BOOKMARK_COMPARATOR);
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/util/DataTypeDependencyOrderer.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/util/DataTypeDependencyOrderer.java
index dab59a5dd6..565c90ce7c 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/util/DataTypeDependencyOrderer.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/util/DataTypeDependencyOrderer.java
@@ -46,16 +46,16 @@ public class DataTypeDependencyOrderer {
private DataTypeManager dtManager;
// A HashSet is chosen so that we have no duplicates.
- private HashSet inputSet = new HashSet();
+ private HashSet inputSet = new HashSet<>();
- private HashSet procSet = new HashSet();
- private HashSet doneSet = new HashSet();
- private ArrayList structList = new ArrayList();
- private ArrayList orderedDependentsList = new ArrayList();
+ private HashSet procSet = new HashSet<>();
+ private HashSet doneSet = new HashSet<>();
+ private ArrayList structList = new ArrayList<>();
+ private ArrayList orderedDependentsList = new ArrayList<>();
- private HashMap> whoIDependOn = new HashMap>();
- private HashMap> whoDependsOnMe = new HashMap>();
- private LinkedList noDependentsQueue = new LinkedList();
+ private HashMap> whoIDependOn = new HashMap<>();
+ private HashMap> whoDependsOnMe = new HashMap<>();
+ private LinkedList noDependentsQueue = new LinkedList<>();
/**
* Associate a DataType with its ID (relative to the DataTypeManager) in an Entry
@@ -152,7 +152,7 @@ public class DataTypeDependencyOrderer {
if (processed == false) {
processDependencyLists();
}
- return new Pair, ArrayList>(structList, orderedDependentsList);
+ return new Pair<>(structList, orderedDependentsList);
}
/**
@@ -189,8 +189,8 @@ public class DataTypeDependencyOrderer {
whoDependsOnMe.size() + "\n\n");
if (!orderedDependentsList.isEmpty()) {
for (DataType dt : orderedDependentsList) {
- res.append("Ordered Dependents: " + dt.getName() + " " + dt.getClass().getName() +
- "\n");
+ res.append(
+ "Ordered Dependents: " + dt.getName() + " " + dt.getClass().getName() + "\n");
}
}
res.append("\n");
@@ -260,10 +260,14 @@ public class DataTypeDependencyOrderer {
addDependent(entry, ((TypeDef) dataType).getDataType());
}
else if (dataType instanceof Structure) {
- DataTypeComponent dtcomps[] = ((Structure) dataType).getComponents();
+ Structure struct = (Structure) dataType;
+ DataTypeComponent dtcomps[] = struct.getComponents();
for (DataTypeComponent dtcomp : dtcomps) {
addDependent(entry, dtcomp.getDataType());
}
+ if (struct.hasFlexibleArrayComponent()) {
+ addDependent(entry, struct.getFlexibleArrayComponent().getDataType());
+ }
}
else if (dataType instanceof Composite) {
DataTypeComponent dtcomps[] = ((Composite) dataType).getComponents();
@@ -331,6 +335,9 @@ public class DataTypeDependencyOrderer {
if ((entry == null) || (subType == null)) {
return;
}
+ if (subType instanceof BitFieldDataType) {
+ subType = ((BitFieldDataType) subType).getBaseDataType();
+ }
Entry subEntry = createEntry(subType);
if (!doneSet.contains(subEntry)) {
procSet.add(subEntry);
@@ -343,13 +350,13 @@ public class DataTypeDependencyOrderer {
}
Set dependents = whoDependsOnMe.get(subEntry);
if (dependents == null) {
- dependents = new HashSet();
+ dependents = new HashSet<>();
whoDependsOnMe.put(subEntry, dependents);
}
dependents.add(entry); //ignores duplicates
Set support = whoIDependOn.get(entry);
if (support == null) {
- support = new HashSet();
+ support = new HashSet<>();
whoIDependOn.put(entry, support);
}
support.add(subEntry); //ignores duplicates
@@ -361,10 +368,10 @@ public class DataTypeDependencyOrderer {
}
Set dependents = whoDependsOnMe.get(entry);
if (dependents == null) {
- dependents = new HashSet();
+ dependents = new HashSet<>();
whoDependsOnMe.put(entry, dependents);
}
- Set support = new HashSet();
+ Set support = new HashSet<>();
whoIDependOn.put(entry, support);
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java
index 29614610a2..c176346152 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java
@@ -2151,7 +2151,7 @@ public class CodeManager implements ErrorHandler, ManagerDB {
}
private void createReference(Data data, Address toAddr, List longSegmentAddressList) {
- if (toAddr == null) {
+ if (toAddr == null || !toAddr.isLoadedMemoryAddress()) {
return;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java
index 7d28efc84e..1e8006a3a1 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java
@@ -421,6 +421,12 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
for (DataTypeComponent comp : comps) {
comp.getDataType().addParent(dt);
}
+ if (dt instanceof Structure) {
+ Structure struct = (Structure) dt;
+ if (struct.hasFlexibleArrayComponent()) {
+ struct.getFlexibleArrayComponent().getDataType().addParent(dt);
+ }
+ }
}
else if (dt instanceof FunctionDefinition) {
FunctionDefinition funDef = (FunctionDefinition) dt;
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java
index 9939f0952e..efb1da1e02 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java
@@ -649,6 +649,7 @@ class StructureDB extends CompositeDB implements Structure {
return 1; // Unaligned
}
if (alignment <= 0) {
+ // just in case - alignment should have been previously determined and stored
StructurePackResult packResult = AlignedStructureInspector.packComponents(this);
alignment = packResult.alignment;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java
index fd1b776826..9b9a11f04b 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AlignedStructureInspector.java
@@ -23,6 +23,11 @@ import javax.help.UnsupportedOperationException;
import ghidra.docking.settings.Settings;
import ghidra.util.exception.DuplicateNameException;
+/**
+ * AlignedStructureInspector provides a simple instance of a structure
+ * member container used to perform alignment operations without forcing modification
+ * of the actual structure.
+ */
public class AlignedStructureInspector extends AlignedStructurePacker {
private AlignedStructureInspector(Structure structure) {
@@ -34,6 +39,9 @@ public class AlignedStructureInspector extends AlignedStructurePacker {
for (DataTypeComponent c : structure.getComponents()) {
list.add(new ReadOnlyComponentWrapper(c));
}
+ if (structure.hasFlexibleArrayComponent()) {
+ list.add(new ReadOnlyComponentWrapper(structure.getFlexibleArrayComponent()));
+ }
return list;
}
@@ -55,10 +63,10 @@ public class AlignedStructureInspector extends AlignedStructurePacker {
}
@Override
- public void update(int ordinal, int offset, int length) {
- this.ordinal = ordinal;
- this.offset = offset;
- this.length = length;
+ public void update(int ord, int off, int len) {
+ this.ordinal = ord;
+ this.offset = off;
+ this.length = len;
}
@Override
@@ -73,7 +81,7 @@ public class AlignedStructureInspector extends AlignedStructurePacker {
@Override
public boolean isFlexibleArrayComponent() {
- return false;
+ return component.isFlexibleArrayComponent();
}
@Override
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java
index cab42075a3..12ced56f50 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java
@@ -340,7 +340,18 @@ public class BitFieldDataType extends AbstractDataType {
@Override
public String getDescription() {
- return getName() + " BitField";
+ StringBuffer sbuf = new StringBuffer();
+ sbuf.append(Integer.toString(effectiveBitSize));
+ sbuf.append("-bit ");
+ DataType dt = getBaseDataType();
+ sbuf.append(dt.getDisplayName());
+ sbuf.append(" bitfield");
+ if (effectiveBitSize != bitSize) {
+ sbuf.append(" (declared as ");
+ sbuf.append(Integer.toString(bitSize));
+ sbuf.append("-bits)");
+ }
+ return sbuf.toString();
}
@Override
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeWriter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeWriter.java
index 63cbc66427..92279f5ad6 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeWriter.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeWriter.java
@@ -242,7 +242,7 @@ public class DataTypeWriter {
}
Msg.error(this, "Factory data types may not be written - type: " + dt, iae);
}
- if (dt instanceof Pointer || dt instanceof Array) {
+ if (dt instanceof Pointer || dt instanceof Array || dt instanceof BitFieldDataType) {
write(getBaseDataType(dt), monitor);
return;
}
@@ -308,6 +308,9 @@ public class DataTypeWriter {
else if (dt instanceof BuiltInDataType) {
writeBuiltIn((BuiltInDataType) dt, monitor);
}
+ else if (dt instanceof BitFieldDataType) {
+ // skip
+ }
else {
writer.write(EOL);
writer.write(EOL);
@@ -540,7 +543,12 @@ public class DataTypeWriter {
if (componentString == null) {
- if (dataType instanceof Array) {
+ if (dataType instanceof BitFieldDataType) {
+ BitFieldDataType bfDt = (BitFieldDataType) dataType;
+ name += ":" + bfDt.getDeclaredBitSize();
+ dataType = bfDt.getBaseDataType();
+ }
+ else if (dataType instanceof Array) {
Array array = (Array) dataType;
name += getArrayDimensions(array);
dataType = getArrayBaseType(array);
@@ -637,6 +645,7 @@ public class DataTypeWriter {
return;
}
}
+ // TODO: A comment explaining the special 'P' case would be helpful!! Smells like fish.
else if (baseType instanceof Pointer && typedefName.startsWith("P")) {
DataType dt = ((Pointer) baseType).getDataType();
if (dt instanceof TypeDef) {
@@ -765,6 +774,10 @@ public class DataTypeWriter {
Pointer pointer = (Pointer) dt;
dt = pointer.getDataType();
}
+ else if (dt instanceof BitFieldDataType) {
+ BitFieldDataType bitfieldDt = (BitFieldDataType) dt;
+ dt = bitfieldDt.getBaseDataType();
+ }
else {
break;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/InternalDataTypeComponent.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/InternalDataTypeComponent.java
index f21897737b..32175bd83d 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/InternalDataTypeComponent.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/InternalDataTypeComponent.java
@@ -25,9 +25,9 @@ public interface InternalDataTypeComponent extends DataTypeComponent {
/**
* Update component ordinal, offset and length during alignment
- * @param ordinal
- * @param offset
- * @param length
+ * @param ordinal updated ordinal
+ * @param offset updated offset
+ * @param length updated byte length
*/
void update(int ordinal, int offset, int length);
|