Skip to content

Commit

Permalink
stabs: Improve conflict resolution for built-ins and anonymous types
Browse files Browse the repository at this point in the history
  • Loading branch information
chaoticgd committed Oct 20, 2023
1 parent f175eca commit 1dd51a3
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## v2.1.11

- stabs: Built-ins and typedefs are now imported and used instead of their underlying type.
- stabs: Anonymous return types, parameter types, local variable types and global variable types are now given more useful names.

## v2.1.10

- Added support for Ghidra 10.4.
Expand Down
48 changes: 43 additions & 5 deletions src/main/java/ghidra/emotionengine/symboltable/StabsImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@
import ghidra.app.util.exporter.ExporterException;
import ghidra.app.util.exporter.OriginalFileExporter;
import ghidra.app.util.importer.MessageLog;
import ghidra.emotionengine.symboltable.StdumpAST.ImporterState;
import ghidra.emotionengine.symboltable.StdumpAST.StorageClass;
import ghidra.framework.Application;
import ghidra.framework.Platform;
import ghidra.program.flatapi.FlatProgramAPI;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.BuiltInDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeConflictHandler;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.DataUtilities;
import ghidra.program.model.data.DataUtilities.ClearDataMode;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.TypedefDataType;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.LocalVariable;
import ghidra.program.model.listing.LocalVariableImpl;
Expand Down Expand Up @@ -245,15 +249,15 @@ public void importDataTypes(StdumpAST.ImporterState importer) {
if(node instanceof StdumpAST.InlineEnum) {
StdumpAST.InlineEnum inlineEnum = (StdumpAST.InlineEnum) node;
DataType type = inlineEnum.createType(importer);
importer.types.add(importer.programTypeManager.addDataType(type, null));
importer.types.add(importer.programTypeManager.addDataType(type, STABS_DATA_TYPE_CONFLICT_HANDLER));
} else if(node instanceof StdumpAST.InlineStructOrUnion) {
StdumpAST.InlineStructOrUnion structOrUnion = (StdumpAST.InlineStructOrUnion) node;
boolean isVtablePointerType = structOrUnion.name.equals("__vtbl_ptr_type");
if(isVtablePointerType) {
fixVtablePointerType(structOrUnion);
}
DataType createdType = structOrUnion.createEmpty(importer);
DataType addedType = importer.programTypeManager.addDataType(createdType, null);
DataType addedType = importer.programTypeManager.addDataType(createdType, STABS_DATA_TYPE_CONFLICT_HANDLER);
if(isVtablePointerType) {
importer.vtablePointerType = addedType;
}
Expand All @@ -277,14 +281,14 @@ public void importDataTypes(StdumpAST.ImporterState importer) {
boolean isBuiltIn = node instanceof StdumpAST.BuiltIn;
if(isBuiltIn) {
if(!importer.eraseBuiltins) {
importer.typedefs.add(node.createTypedef(importer));
importer.typedefs.add(createTypedef(node, importer));
continue;
}
} else {
boolean isEnum = node instanceof StdumpAST.InlineEnum;
boolean isStructOrUnion = node instanceof StdumpAST.InlineStructOrUnion;
if(!importer.eraseTypedefs && !isEnum && !isStructOrUnion) {
importer.typedefs.add(node.createTypedef(importer));
importer.typedefs.add(createTypedef(node, importer));
continue;
}
}
Expand Down Expand Up @@ -320,6 +324,11 @@ public void fixVtablePointerType(StdumpAST.InlineStructOrUnion vtablePointerType
}
}

public DataType createTypedef(StdumpAST.Node node, ImporterState importer) {
DataType createdType = new TypedefDataType(node.name, node.createType(importer));
return importer.programTypeManager.addDataType(createdType, STABS_DATA_TYPE_CONFLICT_HANDLER);
}

public void importFunctions(StdumpAST.ImporterState importer, Program program) {
monitor.setMessage("STABS - Importing functions...");
monitor.setMaximum(importer.ast.files.size());
Expand All @@ -340,6 +349,7 @@ public void importFunctions(StdumpAST.ImporterState importer, Program program) {
Function function = findOrCreateFunction(def, low, high, range);
setFunctionName(function, def);
function.setComment(sourceFile.path);
importer.currentFuncOrGlobalName = def.name;
if(type.returnType != null) {
try {
importer.stage = StdumpAST.ImportStage.RETURN_TYPE;
Expand Down Expand Up @@ -416,6 +426,7 @@ private HashSet<String> fillInParameters(Function function, StdumpAST.ImporterSt
ArrayList<Variable> parameters = new ArrayList<>();
for(int i = 0; i < type.parameters.size(); i++) {
StdumpAST.Variable variable = (StdumpAST.Variable) type.parameters.get(i);
importer.currentVariableName = variable.name;
DataType parameterType = StdumpAST.replaceVoidWithUndefined1(variable.type.createType(importer));
if(variable.storage.isByReference) {
parameterType = new PointerDataType(parameterType);
Expand Down Expand Up @@ -470,6 +481,7 @@ private void fillInLocalVariables(Function function, StdumpAST.ImporterState imp
}
for(Map.Entry<String, StdumpAST.Variable> local : stackLocals.entrySet()) {
StdumpAST.Variable var = local.getValue();
importer.currentVariableName = var.name;
DataType localType = StdumpAST.replaceVoidWithUndefined1(var.type.createType(importer));
LocalVariable dest;
try {
Expand All @@ -494,8 +506,9 @@ public void importGlobalVariables(StdumpAST.ImporterState importer) {
for(StdumpAST.Node global_node : file.globals) {
StdumpAST.Variable global = (StdumpAST.Variable) global_node;
if(global.storage.globalAddress > -1) {
Address address = space.getAddress(global.storage.globalAddress);
importer.currentFuncOrGlobalName = global.name;
DataType type = StdumpAST.replaceVoidWithUndefined1(global.type.createType(importer));
Address address = space.getAddress(global.storage.globalAddress);
try {
DataUtilities.createData(currentProgram, address, type, type.getLength(), false, ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
} catch (CodeUnitInsertionException e) {
Expand Down Expand Up @@ -553,5 +566,30 @@ public static String stripColourCodes(String input) {
}
return output.toString();
}

public final static DataTypeConflictHandler STABS_DATA_TYPE_CONFLICT_HANDLER = new DataTypeConflictHandler() {
@Override
public ConflictResult resolveConflict(DataType addedDataType, DataType existingDataType) {
// If we're trying to make a typedef to built-in with the same name
// as said built-in, just use the built-in itself instead so we
// don't create a ".conflict" type.
if(addedDataType instanceof TypedefDataType && existingDataType instanceof BuiltInDataType) {
TypedefDataType typedef = (TypedefDataType) addedDataType;
if(typedef.getBaseDataType().isEquivalent(existingDataType)) {
return ConflictResult.USE_EXISTING;
}
}
return ConflictResult.RENAME_AND_ADD;
}

@Override
public boolean shouldUpdate(DataType sourceDataType, DataType localDataType) {
return true;
}

@Override
public DataTypeConflictHandler getSubsequentHandler() {
return DataTypeConflictHandler.DEFAULT_HANDLER;
}
};
}
23 changes: 10 additions & 13 deletions src/main/java/ghidra/emotionengine/symboltable/StdumpAST.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import ghidra.program.model.data.ShortDataType;
import ghidra.program.model.data.Structure;
import ghidra.program.model.data.StructureDataType;
import ghidra.program.model.data.TypedefDataType;
import ghidra.program.model.data.Undefined1DataType;
import ghidra.program.model.data.Undefined4DataType;
import ghidra.program.model.data.Union;
Expand Down Expand Up @@ -59,6 +58,8 @@ public static class ImporterState {

// Internal state.
ImportStage stage; // Used to name types defined inline in global/local variable declarations.
String currentFuncOrGlobalName; // Used to name anonymous inline types.
String currentVariableName; // Also used to name anonymous inline types.
ArrayList<DataType> types = new ArrayList<>();
ArrayList<HashMap<Integer, Integer>> stabsTypeNumberToDeduplicatedTypeIndex = new ArrayList<>();
HashMap<String, Integer> typeNameToDeduplicatedTypeIndex = new HashMap<>();
Expand Down Expand Up @@ -126,11 +127,6 @@ public DataType createTypeImpl(ImporterState importer) {
return Undefined1DataType.dataType;
}

public DataType createTypedef(ImporterState importer) {
DataType createdType = new TypedefDataType(name, createType(importer));
return importer.programTypeManager.addDataType(createdType, null);
}

void setupConflictResolutionPostfix(ImporterState importer) {
if(conflict) {
importer.conflictResolutionPostfix = "__" + Integer.toString(firstFile) + "_" + Integer.toString(stabsTypeNumber);
Expand All @@ -151,15 +147,16 @@ String generateName(ImporterState importer, boolean addPrefix) {
}
}
if(name == null || name.isEmpty()) {
String dummyName = "unnamed_";
switch(importer.stage) {
case TYPES: dummyName = "unnamed_"; break;
case RETURN_TYPE: dummyName = "anonymousreturntype_"; break;
case PARAMETERS: dummyName = "anonymousparametertype_"; break;
case LOCAL_VARIABLES: dummyName = "anonymouslocaltype_"; break;
case GLOBAL_VARIABLES: dummyName = "anonymousglobaltype_"; break;
case TYPES: {
String fullPostfix = Integer.toString(absoluteOffsetBytes) + importer.conflictResolutionPostfix;
return prefixString + "unnamed_" + fullPostfix;
}
case RETURN_TYPE: return importer.currentFuncOrGlobalName + "__anonymousreturntype";
case PARAMETERS: return importer.currentFuncOrGlobalName + "__anonymousparameter__" + importer.currentVariableName;
case LOCAL_VARIABLES: return importer.currentFuncOrGlobalName + "__anonymouslocal__" + importer.currentVariableName;
case GLOBAL_VARIABLES: return importer.currentFuncOrGlobalName + "__anonymousglobal";
}
return prefixString + dummyName + Integer.toString(absoluteOffsetBytes) + importer.conflictResolutionPostfix;
}
return prefixString + name + importer.conflictResolutionPostfix;
}
Expand Down

0 comments on commit 1dd51a3

Please sign in to comment.