Skip to content

Commit

Permalink
Refactor type import code
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalh committed Mar 21, 2021
1 parent eca2077 commit 6a9ff87
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

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

Expand Down Expand Up @@ -33,8 +34,8 @@ public DataTypeManager getDataTypeManager() {
return program.getDataTypeManager();
}

public DebugInfoEntry getDebugInfoEntry(long ref) {
return dieMap.get(ref);
public Optional<DebugInfoEntry> getDebugInfoEntry(long ref) {
return Optional.ofNullable(dieMap.get(ref));
}

public void addEntry(DebugInfoEntry die) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public DWARF1TypeImporter(DWARF1Program program, MessageLog log, DWARF1TypeManag
this.categoryPath = new CategoryPath("/DWARF");
}

Optional<DataType> processTypeDebugInfoEntry(DebugInfoEntry die) {
DataType processTypeDebugInfoEntry(DebugInfoEntry die) {
try {
switch (die.getTag()) {
case CLASS_TYPE:
Expand All @@ -75,19 +75,17 @@ Optional<DataType> processTypeDebugInfoEntry(DebugInfoEntry die) {
case SET_TYPE:
case SUBRANGE_TYPE:
// TODO
log.appendMsg("Skipping type: " + die);
return Optional.empty();
throw new IllegalArgumentException("Unsupported debug info entry tag: " + die.getTag());
default:
// skip other tags
log.appendMsg("Expected type tag in " + die);
return Optional.empty();
throw new IllegalArgumentException("Expected type tag, got " + die.getTag());
}
} catch (Exception e) {
throw new RuntimeException("Failed to process type debug info entry " + die, e);
}
}

private Optional<DataType> processSubrountineType(DebugInfoEntry die) {
private DataType processSubrountineType(DebugInfoEntry die) {
// Note: this is a function type, not a pointer to function type
DataType returnDt = typeExtractor.extractDataType(die);
List<ParameterDefinition> params = new ArrayList<>();
Expand Down Expand Up @@ -115,10 +113,10 @@ private Optional<DataType> processSubrountineType(DebugInfoEntry die) {
funDt = dtMgr.addDataType(funDefDt, DataTypeConflictHandler.DEFAULT_HANDLER);
}
dwarfTypeManager.registerType(die.getRef(), funDt);
return Optional.of(funDt);
return funDt;
}

private Optional<DataType> processArrayType(DebugInfoEntry die) throws IOException {
private DataType processArrayType(DebugInfoEntry die) throws IOException {
byte[] subscrData = die.<BlockAttributeValue>getAttribute(AttributeName.SUBSCR_DATA)
.map(av -> av.get())
.orElseThrow(() -> new IllegalArgumentException("array type without subscr_data " + die));
Expand Down Expand Up @@ -146,15 +144,13 @@ private Optional<DataType> processArrayType(DebugInfoEntry die) throws IOExcepti
}
}
if (baseDt == null) {
log.appendMsg("Missing array element type information in " + die);
return Optional.empty();
throw new IllegalArgumentException("Missing array element type information");
}
DataType dt = baseDt;
Collections.reverse(dims);
for (int dim : dims) {
if (dim < 0) {
log.appendMsg("Bad array dimension " + dim + " in " + die);
return Optional.empty();
throw new IllegalArgumentException("Bad array dimension: " + dim);
}
if (dim == 0) {
// Ghidra does not support array data type with length 0 so return it as void type, which has zero size
Expand All @@ -164,14 +160,13 @@ private Optional<DataType> processArrayType(DebugInfoEntry die) throws IOExcepti
dt = new ArrayDataType(dt, dim, -1, program.getDataTypeManager());
}
dwarfTypeManager.registerType(die.getRef(), dt);
return Optional.of(dt);
return dt;
}

private Optional<DataType> processClassType(DebugInfoEntry die) {
private DataType processClassType(DebugInfoEntry die) {
Optional<Number> byteSizeOpt = die.<ConstAttributeValue>getAttribute(AttributeName.BYTE_SIZE).map(av -> av.get());
if (byteSizeOpt.isEmpty()) {
log.appendMsg("Skipping structure without size " + die);
return Optional.empty();
throw new IllegalArgumentException("class type is missing byte size attribute");
}
String name = DWARF1ImportUtils.extractName(die)
// FIXME: anonymous class?
Expand All @@ -183,10 +178,11 @@ private Optional<DataType> processClassType(DebugInfoEntry die) {
if (existingDt != null) {
// already imported
dwarfTypeManager.registerType(die.getRef(), existingDt);
return Optional.of(existingDt);
return existingDt;
}
StructureDataType sdt = new StructureDataType(categoryPath, name, size, dataTypeManager);
Structure newDt = (Structure) dataTypeManager.addDataType(sdt, DataTypeConflictHandler.DEFAULT_HANDLER);
StructureDataType tempDt = new StructureDataType(categoryPath, name, size, dataTypeManager);
// Register the type before importing fields because field can reference parent type
Structure newDt = (Structure) dataTypeManager.addDataType(tempDt, DataTypeConflictHandler.DEFAULT_HANDLER);
dwarfTypeManager.registerType(die.getRef(), newDt);
//log.appendMsg("Struct " + name);
for (DebugInfoEntry childDie : die.getChildren()) {
Expand All @@ -201,7 +197,7 @@ private Optional<DataType> processClassType(DebugInfoEntry die) {
log.appendMsg("Unexpected child of class type: " + childDie.getTag());
}
}
return Optional.of(newDt);
return newDt;
}

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

private Optional<DataType> processUnionType(DebugInfoEntry die) {
private DataType processUnionType(DebugInfoEntry die) {
String name = DWARF1ImportUtils.extractName(die).orElseGet(() -> "anon_" + die.getRef());
DataTypeManager dataTypeManager = program.getDataTypeManager();
DataType existingDt = dataTypeManager.getDataType(categoryPath, name);
if (existingDt != null) {
// already imported
dwarfTypeManager.registerType(die.getRef(), existingDt);
return Optional.of(existingDt);
return existingDt;
}
UnionDataType udt = new UnionDataType(categoryPath, name, dataTypeManager);
Union newDt = (Union) dataTypeManager.addDataType(udt, DataTypeConflictHandler.DEFAULT_HANDLER);
dwarfTypeManager.registerType(die.getRef(), newDt);
UnionDataType tempUnionDt = new UnionDataType(categoryPath, name, dataTypeManager);
Union newUnionDt = (Union) dataTypeManager.addDataType(tempUnionDt, DataTypeConflictHandler.DEFAULT_HANDLER);
dwarfTypeManager.registerType(die.getRef(), newUnionDt);
//log.appendMsg("Struct " + name);
for (DebugInfoEntry childDie : die.getChildren()) {
switch (childDie.getTag()) {
case MEMBER:
processUnionTypeMember(newDt, childDie);
processUnionTypeMember(newUnionDt, childDie);
break;
default:
log.appendMsg("Unexpected child of union type: " + childDie.getTag());
}
}
return Optional.of(newDt);
return newUnionDt;
}

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

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

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

int size = byteSizeOpt.orElse(4).intValue();
var edt = new EnumDataType(categoryPath, name, size, dataTypeManager);
var tempEnumDt = new EnumDataType(categoryPath, name, size, dataTypeManager);
if (elementListOpt.isPresent()) {
processEnumElementList(edt, elementListOpt.get(), size);
processEnumElementList(tempEnumDt, elementListOpt.get(), size);
}

DataType newDt = dataTypeManager.addDataType(edt, DataTypeConflictHandler.DEFAULT_HANDLER);
dwarfTypeManager.registerType(die.getRef(), newDt);
return Optional.of(newDt);
DataType enumDt = dataTypeManager.addDataType(tempEnumDt, DataTypeConflictHandler.DEFAULT_HANDLER);
dwarfTypeManager.registerType(die.getRef(), enumDt);
return enumDt;
}

private void processEnumElementList(EnumDataType edt, byte[] encodedElementList, int size) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Map;
import java.util.Optional;

import com.github.rafalh.ghidra.dwarfone.model.DebugInfoEntry;
import com.github.rafalh.ghidra.dwarfone.model.FundamentalType;

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

DataType getUserDataType(long ref) {
var dtOpt = Optional.ofNullable(userDataTypeMap.get(ref));
if (dtOpt.isEmpty()) {
dtOpt = Optional.ofNullable(program.getDebugInfoEntry(ref))
.flatMap(dwarfTypeImporter::processTypeDebugInfoEntry);
public DataType getUserDataType(long ref) {
var cachedDtOpt = Optional.ofNullable(userDataTypeMap.get(ref));
if (cachedDtOpt.isPresent()) {
return cachedDtOpt.get();
}
if (dtOpt.isEmpty()) {
log.appendMsg("Cannot find user type " + Long.toHexString(ref));
try {
DebugInfoEntry die = program.getDebugInfoEntry(ref)
.orElseThrow(() -> new IllegalArgumentException("Cannot find DIE for reference " + ref));
return dwarfTypeImporter.processTypeDebugInfoEntry(die);
} catch (Exception e) {
log.appendMsg("Failed to resolve type reference: " + ref);
log.appendException(e);
return DataType.DEFAULT;
}
return dtOpt.orElse(DataType.DEFAULT);
}

DataType convertFundamentalTypeToDataType(FundamentalType ft) {
public DataType convertFundamentalTypeToDataType(FundamentalType ft) {
DataTypeManager dataTypeManager = BuiltInDataTypeManager.getDataTypeManager();
switch (ft) {
case CHAR:
Expand Down Expand Up @@ -74,6 +79,7 @@ DataType convertFundamentalTypeToDataType(FundamentalType ft) {
case BOOLEAN:
return dataTypeManager.getDataType(CategoryPath.ROOT, "bool");
default:
log.appendMsg("Unknown fundamental type: " + ft);
return DataType.DEFAULT;
}
}
Expand All @@ -85,5 +91,4 @@ public void registerType(long ref, DataType dt) {
public void setTypeImporter(DWARF1TypeImporter dwarfTypeImporter) {
this.dwarfTypeImporter = dwarfTypeImporter;
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.rafalh.ghidra.dwarfone.model;

import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -32,10 +33,7 @@ public static TypeModifier fromValue(int value) {
if (value >= LO_USER && value <= HI_USER) {
return USER;
}
TypeModifier mod = VALUE_MAP.get(value);
if (mod == null) {
throw new IllegalArgumentException("invalid mod value " + value);
}
return mod;
return Optional.ofNullable(VALUE_MAP.get(value))
.orElseThrow(() -> new IllegalArgumentException("invalid mod value " + value));
}
}

0 comments on commit 6a9ff87

Please sign in to comment.