Skip to content

Commit 6a9ff87

Browse files
committed
Refactor type import code
1 parent eca2077 commit 6a9ff87

File tree

4 files changed

+51
-51
lines changed

4 files changed

+51
-51
lines changed

src/main/java/com/github/rafalh/ghidra/dwarfone/DWARF1Program.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5+
import java.util.Optional;
56

67
import com.github.rafalh.ghidra.dwarfone.model.DebugInfoEntry;
78

@@ -33,8 +34,8 @@ public DataTypeManager getDataTypeManager() {
3334
return program.getDataTypeManager();
3435
}
3536

36-
public DebugInfoEntry getDebugInfoEntry(long ref) {
37-
return dieMap.get(ref);
37+
public Optional<DebugInfoEntry> getDebugInfoEntry(long ref) {
38+
return Optional.ofNullable(dieMap.get(ref));
3839
}
3940

4041
public void addEntry(DebugInfoEntry die) {

src/main/java/com/github/rafalh/ghidra/dwarfone/DWARF1TypeImporter.java

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public DWARF1TypeImporter(DWARF1Program program, MessageLog log, DWARF1TypeManag
5454
this.categoryPath = new CategoryPath("/DWARF");
5555
}
5656

57-
Optional<DataType> processTypeDebugInfoEntry(DebugInfoEntry die) {
57+
DataType processTypeDebugInfoEntry(DebugInfoEntry die) {
5858
try {
5959
switch (die.getTag()) {
6060
case CLASS_TYPE:
@@ -75,19 +75,17 @@ Optional<DataType> processTypeDebugInfoEntry(DebugInfoEntry die) {
7575
case SET_TYPE:
7676
case SUBRANGE_TYPE:
7777
// TODO
78-
log.appendMsg("Skipping type: " + die);
79-
return Optional.empty();
78+
throw new IllegalArgumentException("Unsupported debug info entry tag: " + die.getTag());
8079
default:
8180
// skip other tags
82-
log.appendMsg("Expected type tag in " + die);
83-
return Optional.empty();
81+
throw new IllegalArgumentException("Expected type tag, got " + die.getTag());
8482
}
8583
} catch (Exception e) {
8684
throw new RuntimeException("Failed to process type debug info entry " + die, e);
8785
}
8886
}
8987

90-
private Optional<DataType> processSubrountineType(DebugInfoEntry die) {
88+
private DataType processSubrountineType(DebugInfoEntry die) {
9189
// Note: this is a function type, not a pointer to function type
9290
DataType returnDt = typeExtractor.extractDataType(die);
9391
List<ParameterDefinition> params = new ArrayList<>();
@@ -115,10 +113,10 @@ private Optional<DataType> processSubrountineType(DebugInfoEntry die) {
115113
funDt = dtMgr.addDataType(funDefDt, DataTypeConflictHandler.DEFAULT_HANDLER);
116114
}
117115
dwarfTypeManager.registerType(die.getRef(), funDt);
118-
return Optional.of(funDt);
116+
return funDt;
119117
}
120118

121-
private Optional<DataType> processArrayType(DebugInfoEntry die) throws IOException {
119+
private DataType processArrayType(DebugInfoEntry die) throws IOException {
122120
byte[] subscrData = die.<BlockAttributeValue>getAttribute(AttributeName.SUBSCR_DATA)
123121
.map(av -> av.get())
124122
.orElseThrow(() -> new IllegalArgumentException("array type without subscr_data " + die));
@@ -146,15 +144,13 @@ private Optional<DataType> processArrayType(DebugInfoEntry die) throws IOExcepti
146144
}
147145
}
148146
if (baseDt == null) {
149-
log.appendMsg("Missing array element type information in " + die);
150-
return Optional.empty();
147+
throw new IllegalArgumentException("Missing array element type information");
151148
}
152149
DataType dt = baseDt;
153150
Collections.reverse(dims);
154151
for (int dim : dims) {
155152
if (dim < 0) {
156-
log.appendMsg("Bad array dimension " + dim + " in " + die);
157-
return Optional.empty();
153+
throw new IllegalArgumentException("Bad array dimension: " + dim);
158154
}
159155
if (dim == 0) {
160156
// Ghidra does not support array data type with length 0 so return it as void type, which has zero size
@@ -164,14 +160,13 @@ private Optional<DataType> processArrayType(DebugInfoEntry die) throws IOExcepti
164160
dt = new ArrayDataType(dt, dim, -1, program.getDataTypeManager());
165161
}
166162
dwarfTypeManager.registerType(die.getRef(), dt);
167-
return Optional.of(dt);
163+
return dt;
168164
}
169165

170-
private Optional<DataType> processClassType(DebugInfoEntry die) {
166+
private DataType processClassType(DebugInfoEntry die) {
171167
Optional<Number> byteSizeOpt = die.<ConstAttributeValue>getAttribute(AttributeName.BYTE_SIZE).map(av -> av.get());
172168
if (byteSizeOpt.isEmpty()) {
173-
log.appendMsg("Skipping structure without size " + die);
174-
return Optional.empty();
169+
throw new IllegalArgumentException("class type is missing byte size attribute");
175170
}
176171
String name = DWARF1ImportUtils.extractName(die)
177172
// FIXME: anonymous class?
@@ -183,10 +178,11 @@ private Optional<DataType> processClassType(DebugInfoEntry die) {
183178
if (existingDt != null) {
184179
// already imported
185180
dwarfTypeManager.registerType(die.getRef(), existingDt);
186-
return Optional.of(existingDt);
181+
return existingDt;
187182
}
188-
StructureDataType sdt = new StructureDataType(categoryPath, name, size, dataTypeManager);
189-
Structure newDt = (Structure) dataTypeManager.addDataType(sdt, DataTypeConflictHandler.DEFAULT_HANDLER);
183+
StructureDataType tempDt = new StructureDataType(categoryPath, name, size, dataTypeManager);
184+
// Register the type before importing fields because field can reference parent type
185+
Structure newDt = (Structure) dataTypeManager.addDataType(tempDt, DataTypeConflictHandler.DEFAULT_HANDLER);
190186
dwarfTypeManager.registerType(die.getRef(), newDt);
191187
//log.appendMsg("Struct " + name);
192188
for (DebugInfoEntry childDie : die.getChildren()) {
@@ -201,7 +197,7 @@ private Optional<DataType> processClassType(DebugInfoEntry die) {
201197
log.appendMsg("Unexpected child of class type: " + childDie.getTag());
202198
}
203199
}
204-
return Optional.of(newDt);
200+
return newDt;
205201
}
206202

207203
private void processClassTypeInheritance(Structure sdt, DebugInfoEntry die) {
@@ -222,29 +218,29 @@ private void processClassTypeMember(Structure sdt, DebugInfoEntry die) {
222218
sdt.replaceAtOffset(memberOffset, memberDt, -1, memberName, null);
223219
}
224220

225-
private Optional<DataType> processUnionType(DebugInfoEntry die) {
221+
private DataType processUnionType(DebugInfoEntry die) {
226222
String name = DWARF1ImportUtils.extractName(die).orElseGet(() -> "anon_" + die.getRef());
227223
DataTypeManager dataTypeManager = program.getDataTypeManager();
228224
DataType existingDt = dataTypeManager.getDataType(categoryPath, name);
229225
if (existingDt != null) {
230226
// already imported
231227
dwarfTypeManager.registerType(die.getRef(), existingDt);
232-
return Optional.of(existingDt);
228+
return existingDt;
233229
}
234-
UnionDataType udt = new UnionDataType(categoryPath, name, dataTypeManager);
235-
Union newDt = (Union) dataTypeManager.addDataType(udt, DataTypeConflictHandler.DEFAULT_HANDLER);
236-
dwarfTypeManager.registerType(die.getRef(), newDt);
230+
UnionDataType tempUnionDt = new UnionDataType(categoryPath, name, dataTypeManager);
231+
Union newUnionDt = (Union) dataTypeManager.addDataType(tempUnionDt, DataTypeConflictHandler.DEFAULT_HANDLER);
232+
dwarfTypeManager.registerType(die.getRef(), newUnionDt);
237233
//log.appendMsg("Struct " + name);
238234
for (DebugInfoEntry childDie : die.getChildren()) {
239235
switch (childDie.getTag()) {
240236
case MEMBER:
241-
processUnionTypeMember(newDt, childDie);
237+
processUnionTypeMember(newUnionDt, childDie);
242238
break;
243239
default:
244240
log.appendMsg("Unexpected child of union type: " + childDie.getTag());
245241
}
246242
}
247-
return Optional.of(newDt);
243+
return newUnionDt;
248244
}
249245

250246
private void processUnionTypeMember(Union union, DebugInfoEntry die) {
@@ -254,7 +250,7 @@ private void processUnionTypeMember(Union union, DebugInfoEntry die) {
254250
union.add(memberDt, memberName, null);
255251
}
256252

257-
private Optional<DataType> processEnumType(DebugInfoEntry die) throws IOException {
253+
private DataType processEnumType(DebugInfoEntry die) throws IOException {
258254
Optional<Number> byteSizeOpt = die.<ConstAttributeValue>getAttribute(AttributeName.BYTE_SIZE).map(av -> av.get());
259255
Optional<byte[]> elementListOpt = die.<BlockAttributeValue>getAttribute(AttributeName.ELEMENT_LIST).map(av -> av.get());
260256

@@ -264,18 +260,18 @@ private Optional<DataType> processEnumType(DebugInfoEntry die) throws IOExceptio
264260
if (existingDt != null) {
265261
// already imported?
266262
dwarfTypeManager.registerType(die.getRef(), existingDt);
267-
return Optional.of(existingDt);
263+
return existingDt;
268264
}
269265

270266
int size = byteSizeOpt.orElse(4).intValue();
271-
var edt = new EnumDataType(categoryPath, name, size, dataTypeManager);
267+
var tempEnumDt = new EnumDataType(categoryPath, name, size, dataTypeManager);
272268
if (elementListOpt.isPresent()) {
273-
processEnumElementList(edt, elementListOpt.get(), size);
269+
processEnumElementList(tempEnumDt, elementListOpt.get(), size);
274270
}
275271

276-
DataType newDt = dataTypeManager.addDataType(edt, DataTypeConflictHandler.DEFAULT_HANDLER);
277-
dwarfTypeManager.registerType(die.getRef(), newDt);
278-
return Optional.of(newDt);
272+
DataType enumDt = dataTypeManager.addDataType(tempEnumDt, DataTypeConflictHandler.DEFAULT_HANDLER);
273+
dwarfTypeManager.registerType(die.getRef(), enumDt);
274+
return enumDt;
279275
}
280276

281277
private void processEnumElementList(EnumDataType edt, byte[] encodedElementList, int size) throws IOException {

src/main/java/com/github/rafalh/ghidra/dwarfone/DWARF1TypeManager.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Map;
55
import java.util.Optional;
66

7+
import com.github.rafalh.ghidra.dwarfone.model.DebugInfoEntry;
78
import com.github.rafalh.ghidra.dwarfone.model.FundamentalType;
89

910
import ghidra.app.util.importer.MessageLog;
@@ -25,19 +26,23 @@ public DWARF1TypeManager(DWARF1Program program, MessageLog log) {
2526
this.log = log;
2627
}
2728

28-
DataType getUserDataType(long ref) {
29-
var dtOpt = Optional.ofNullable(userDataTypeMap.get(ref));
30-
if (dtOpt.isEmpty()) {
31-
dtOpt = Optional.ofNullable(program.getDebugInfoEntry(ref))
32-
.flatMap(dwarfTypeImporter::processTypeDebugInfoEntry);
29+
public DataType getUserDataType(long ref) {
30+
var cachedDtOpt = Optional.ofNullable(userDataTypeMap.get(ref));
31+
if (cachedDtOpt.isPresent()) {
32+
return cachedDtOpt.get();
3333
}
34-
if (dtOpt.isEmpty()) {
35-
log.appendMsg("Cannot find user type " + Long.toHexString(ref));
34+
try {
35+
DebugInfoEntry die = program.getDebugInfoEntry(ref)
36+
.orElseThrow(() -> new IllegalArgumentException("Cannot find DIE for reference " + ref));
37+
return dwarfTypeImporter.processTypeDebugInfoEntry(die);
38+
} catch (Exception e) {
39+
log.appendMsg("Failed to resolve type reference: " + ref);
40+
log.appendException(e);
41+
return DataType.DEFAULT;
3642
}
37-
return dtOpt.orElse(DataType.DEFAULT);
3843
}
3944

40-
DataType convertFundamentalTypeToDataType(FundamentalType ft) {
45+
public DataType convertFundamentalTypeToDataType(FundamentalType ft) {
4146
DataTypeManager dataTypeManager = BuiltInDataTypeManager.getDataTypeManager();
4247
switch (ft) {
4348
case CHAR:
@@ -74,6 +79,7 @@ DataType convertFundamentalTypeToDataType(FundamentalType ft) {
7479
case BOOLEAN:
7580
return dataTypeManager.getDataType(CategoryPath.ROOT, "bool");
7681
default:
82+
log.appendMsg("Unknown fundamental type: " + ft);
7783
return DataType.DEFAULT;
7884
}
7985
}
@@ -85,5 +91,4 @@ public void registerType(long ref, DataType dt) {
8591
public void setTypeImporter(DWARF1TypeImporter dwarfTypeImporter) {
8692
this.dwarfTypeImporter = dwarfTypeImporter;
8793
}
88-
8994
}

src/main/java/com/github/rafalh/ghidra/dwarfone/model/TypeModifier.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.rafalh.ghidra.dwarfone.model;
22

33
import java.util.Map;
4+
import java.util.Optional;
45
import java.util.function.Function;
56
import java.util.stream.Collectors;
67
import java.util.stream.Stream;
@@ -32,10 +33,7 @@ public static TypeModifier fromValue(int value) {
3233
if (value >= LO_USER && value <= HI_USER) {
3334
return USER;
3435
}
35-
TypeModifier mod = VALUE_MAP.get(value);
36-
if (mod == null) {
37-
throw new IllegalArgumentException("invalid mod value " + value);
38-
}
39-
return mod;
36+
return Optional.ofNullable(VALUE_MAP.get(value))
37+
.orElseThrow(() -> new IllegalArgumentException("invalid mod value " + value));
4038
}
4139
}

0 commit comments

Comments
 (0)