diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java index e91fdb9ddf..46c779fc27 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java @@ -226,14 +226,33 @@ public class DecompileDebugDataTypeManager { return unionDT; } - while (parser.peek().getName().equals("field")) { - XmlElement fieldElement = parser.start("field"); - DataType fieldDT = parseDataTypeTag(parser, log); - unionDT.add(fieldDT, fieldDT.getLength(), key.name(), ""); - parser.end(fieldElement); + while (parser.peek().getName().contains("field")) { + String fieldType = parser.peek().getName(); + if (fieldType.equals("field")) { + XmlElement fieldElement = parser.start("field"); + DataType fieldDT = parseDataTypeTag(parser, log); + unionDT.add(fieldDT, fieldDT.getLength(), key.name(), ""); + parser.end(fieldElement); + } + else if (fieldType.equals("bitfield")) { + XmlElement bitFieldElement = parser.start("bitfield"); + int bitFieldSize = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_SIZE.name())); + String componentName = bitFieldElement.getAttribute(ATTRIB_NAME.name()); + DataType fieldDT = parseDataTypeTag(parser, log); + + try { + unionDT.addBitField(fieldDT, bitFieldSize, componentName, null); + } + catch (InvalidDataTypeException e) { + log.appendException(e); + } + parser.end(bitFieldElement); + } } parser.end(unionElement); return unionDT; + } /** @@ -295,8 +314,9 @@ public class DecompileDebugDataTypeManager { DataType baseType = parseDataTypeTag(parser, log); PointerTypedef relPointerDT = new PointerTypedef(baseType.getName(), baseType, size, programDataManager, offset); - - DataType resolved = resolveAndMapDataType(new DataTypeKey(baseType.getName()+"relptr", idHolder), relPointerDT); + + DataType resolved = resolveAndMapDataType( + new DataTypeKey(baseType.getName() + "relptr", idHolder), relPointerDT); parser.end(pointerRelElement); return resolved; @@ -331,7 +351,25 @@ public class DecompileDebugDataTypeManager { return createdStruct; } - while (parser.peek().getName().equals("field")) { + while (parser.peek().getName().contains("field")) { + handleStructFieldType(parser, createdStruct, log); + } + parser.end(structElement); + + return createdStruct; + + } + + /** + * Parse and populate field and bit field types for created structs. + * + * @param parser XmlPullParser + * @param createdStruct Structure + * @param log XmlMessageLog + */ + private void handleStructFieldType(XmlPullParser parser, Structure createdStruct, + XmlMessageLog log) { + if (parser.peek().getName().equals("field")) { XmlElement fieldElement = parser.start("field"); int fieldOffset = SpecXmlUtils.decodeInt(fieldElement.getAttribute(ATTRIB_OFFSET.name())); @@ -341,10 +379,27 @@ public class DecompileDebugDataTypeManager { fieldElement.getAttribute(ATTRIB_NAME.name()), ""); parser.end(fieldElement); } - parser.end(structElement); - - return createdStruct; + else if (parser.peek().getName().equals("bitfield")) { + XmlElement bitFieldElement = parser.start("bitfield"); + int bitFieldSize = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_SIZE.name())); + String componentName = bitFieldElement.getAttribute(ATTRIB_NAME.name()); + int byteOffset = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_OFFSET.name())); + int bitOffset = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_FIRST.name())); + int byteWidth = Math.ceilDiv((bitOffset + bitFieldSize), 8); + DataType fieldDT = parseDataTypeTag(parser, log); + try { + createdStruct.insertBitFieldAt(byteOffset, byteWidth, bitOffset, fieldDT, + bitFieldSize, componentName, null); + } + catch (InvalidDataTypeException e) { + log.appendException(e); + } + parser.end(bitFieldElement); + } } /** diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java index 6a9290b0e7..8c11d8a3b2 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java @@ -123,11 +123,14 @@ public class DecompileDebugXmlLoaderTest extends AbstractGhidraHeadedIntegration Iterator structures = dtm.getAllStructures(); Structure struct = structures.next(); // there is only 1 struct in the example XML dump - assertEquals("Component count didn't match.", 20, struct.getNumComponents()); + assertEquals("Component count didn't match.", 22, struct.getNumComponents()); assertEquals("Struct name is incorrect", "IMAGE_DOS_HEADER", struct.getName()); DataTypeComponent array = struct.getComponentAt(0); // the first component is an array assertEquals("Array component name doesn't match", "e_magic", array.getFieldName()); assertEquals("Array wasn't sized right", 2, array.getLength()); + DataTypeComponent bitField = struct.getComponentAt(65); // last component is a bitfield + assertEquals("Bitfield name doesn't match", "low_nibble", bitField.getFieldName()); + assertEquals("Bitfield length doesn't match", "1", bitField.getLength() + ""); } finally { program.release(this); diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml index ac6ce65036..61b0f0f892 100644 --- a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml +++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml @@ -167,6 +167,9 @@ c4305fc3b907000000e8be03000090b9 + + +