Skip to content

Commit 9cae6dc

Browse files
committed
Merge remote-tracking branch 'origin/patch'
2 parents 42719e9 + 9837384 commit 9cae6dc

3 files changed

Lines changed: 73 additions & 12 deletions

File tree

Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,33 @@ private DataType parseUnion(XmlPullParser parser, XmlMessageLog log) {
226226
return unionDT;
227227
}
228228

229-
while (parser.peek().getName().equals("field")) {
230-
XmlElement fieldElement = parser.start("field");
231-
DataType fieldDT = parseDataTypeTag(parser, log);
232-
unionDT.add(fieldDT, fieldDT.getLength(), key.name(), "");
233-
parser.end(fieldElement);
229+
while (parser.peek().getName().contains("field")) {
230+
String fieldType = parser.peek().getName();
231+
if (fieldType.equals("field")) {
232+
XmlElement fieldElement = parser.start("field");
233+
DataType fieldDT = parseDataTypeTag(parser, log);
234+
unionDT.add(fieldDT, fieldDT.getLength(), key.name(), "");
235+
parser.end(fieldElement);
236+
}
237+
else if (fieldType.equals("bitfield")) {
238+
XmlElement bitFieldElement = parser.start("bitfield");
239+
int bitFieldSize =
240+
SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_SIZE.name()));
241+
String componentName = bitFieldElement.getAttribute(ATTRIB_NAME.name());
242+
DataType fieldDT = parseDataTypeTag(parser, log);
243+
244+
try {
245+
unionDT.addBitField(fieldDT, bitFieldSize, componentName, null);
246+
}
247+
catch (InvalidDataTypeException e) {
248+
log.appendException(e);
249+
}
250+
parser.end(bitFieldElement);
251+
}
234252
}
235253
parser.end(unionElement);
236254
return unionDT;
255+
237256
}
238257

239258
/**
@@ -295,8 +314,9 @@ private DataType parsePointerRelative(XmlPullParser parser, XmlMessageLog log) {
295314
DataType baseType = parseDataTypeTag(parser, log);
296315
PointerTypedef relPointerDT =
297316
new PointerTypedef(baseType.getName(), baseType, size, programDataManager, offset);
298-
299-
DataType resolved = resolveAndMapDataType(new DataTypeKey(baseType.getName()+"relptr", idHolder), relPointerDT);
317+
318+
DataType resolved = resolveAndMapDataType(
319+
new DataTypeKey(baseType.getName() + "relptr", idHolder), relPointerDT);
300320
parser.end(pointerRelElement);
301321

302322
return resolved;
@@ -331,7 +351,25 @@ private DataType parseStruct(XmlPullParser parser, XmlMessageLog log) {
331351
return createdStruct;
332352
}
333353

334-
while (parser.peek().getName().equals("field")) {
354+
while (parser.peek().getName().contains("field")) {
355+
handleStructFieldType(parser, createdStruct, log);
356+
}
357+
parser.end(structElement);
358+
359+
return createdStruct;
360+
361+
}
362+
363+
/**
364+
* Parse and populate field and bit field types for created structs.
365+
*
366+
* @param parser XmlPullParser
367+
* @param createdStruct Structure
368+
* @param log XmlMessageLog
369+
*/
370+
private void handleStructFieldType(XmlPullParser parser, Structure createdStruct,
371+
XmlMessageLog log) {
372+
if (parser.peek().getName().equals("field")) {
335373
XmlElement fieldElement = parser.start("field");
336374
int fieldOffset =
337375
SpecXmlUtils.decodeInt(fieldElement.getAttribute(ATTRIB_OFFSET.name()));
@@ -341,10 +379,27 @@ private DataType parseStruct(XmlPullParser parser, XmlMessageLog log) {
341379
fieldElement.getAttribute(ATTRIB_NAME.name()), "");
342380
parser.end(fieldElement);
343381
}
344-
parser.end(structElement);
345-
346-
return createdStruct;
382+
else if (parser.peek().getName().equals("bitfield")) {
383+
XmlElement bitFieldElement = parser.start("bitfield");
384+
int bitFieldSize =
385+
SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_SIZE.name()));
386+
String componentName = bitFieldElement.getAttribute(ATTRIB_NAME.name());
387+
int byteOffset =
388+
SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_OFFSET.name()));
389+
int bitOffset =
390+
SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_FIRST.name()));
391+
int byteWidth = Math.ceilDiv((bitOffset + bitFieldSize), 8);
392+
DataType fieldDT = parseDataTypeTag(parser, log);
347393

394+
try {
395+
createdStruct.insertBitFieldAt(byteOffset, byteWidth, bitOffset, fieldDT,
396+
bitFieldSize, componentName, null);
397+
}
398+
catch (InvalidDataTypeException e) {
399+
log.appendException(e);
400+
}
401+
parser.end(bitFieldElement);
402+
}
348403
}
349404

350405
/**

Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,14 @@ public void testVerifyLoadedProgramDataTypes() throws Exception {
123123

124124
Iterator<Structure> structures = dtm.getAllStructures();
125125
Structure struct = structures.next(); // there is only 1 struct in the example XML dump
126-
assertEquals("Component count didn't match.", 20, struct.getNumComponents());
126+
assertEquals("Component count didn't match.", 22, struct.getNumComponents());
127127
assertEquals("Struct name is incorrect", "IMAGE_DOS_HEADER", struct.getName());
128128
DataTypeComponent array = struct.getComponentAt(0); // the first component is an array
129129
assertEquals("Array component name doesn't match", "e_magic", array.getFieldName());
130130
assertEquals("Array wasn't sized right", 2, array.getLength());
131+
DataTypeComponent bitField = struct.getComponentAt(65); // last component is a bitfield
132+
assertEquals("Bitfield name doesn't match", "low_nibble", bitField.getFieldName());
133+
assertEquals("Bitfield length doesn't match", "1", bitField.getLength() + "");
131134
}
132135
finally {
133136
program.release(this);

Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ c4305fc3b907000000e8be03000090b9
167167
<type name="byte" id="0xc00000000000007f" metatype="uint" size="1"/>
168168
</type>
169169
</field>
170+
<bitfield name="low_nibble" id="0" offset="65" first="0" size="4">
171+
<type name="byte" id="0xc00000000000007a" metatype="uint" size="1"/>
172+
</bitfield>
170173
</type>
171174
</typegrp><db scopeidbyname="false">
172175
<scope name="" id="0x0">

0 commit comments

Comments
 (0)