Skip to content

Commit

Permalink
Merge pull request #37 from chaoticgd/happyvtable
Browse files Browse the repository at this point in the history
Fix the existing __vtbl_ptr_type instead of creating a new one
  • Loading branch information
chaoticgd authored Sep 4, 2023
2 parents e1e6b4c + 11ec93b commit 80fd9ed
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 35 deletions.
55 changes: 25 additions & 30 deletions src/main/java/ghidra/emotionengine/symboltable/StabsImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,6 @@ public void importDataTypes(StdumpAST.ImporterState importer) {
}
}

// Create a type for the vtable pointer.
createVtablePointerType(importer);

// Create all the top-level enums, structs and unions first.
for(int i = 0; i < type_count; i++) {
StdumpAST.Node node = importer.ast.deduplicatedTypes.get(i);
Expand All @@ -248,14 +245,28 @@ public void importDataTypes(StdumpAST.ImporterState importer) {
importer.types.add(importer.programTypeManager.addDataType(type, null));
} else if(node instanceof StdumpAST.InlineStructOrUnion) {
StdumpAST.InlineStructOrUnion structOrUnion = (StdumpAST.InlineStructOrUnion) node;
DataType type = structOrUnion.createEmpty(importer);
importer.types.add(importer.programTypeManager.addDataType(type, null));
boolean isVtablePointerType = structOrUnion.name.equals("__vtbl_ptr_type");
if(isVtablePointerType) {
fixVtablePointerType(structOrUnion);
}
DataType createdType = structOrUnion.createEmpty(importer);
DataType addedType = importer.programTypeManager.addDataType(createdType, null);
if(isVtablePointerType) {
importer.vtablePointerType = addedType;
}
importer.types.add(addedType);

} else {
importer.types.add(null);
}
monitor.setProgress(i);
}


// If __vtbl_ptr_type isn't a struct, we assume it's a pointer.
if(importer.vtablePointerType == null) {
importer.vtablePointerType = PointerDataType.dataType;
}

// Fill in the structs and unions recursively.
for(int i = 0; i < type_count; i++) {
StdumpAST.Node node = importer.ast.deduplicatedTypes.get(i);
Expand All @@ -270,33 +281,17 @@ public void importDataTypes(StdumpAST.ImporterState importer) {
}
}

public void createVtablePointerType(StdumpAST.ImporterState importer) {
Integer typeIndex = importer.typeNameToDeduplicatedTypeIndex.get("__vtbl_ptr_type");
if(typeIndex == null) {
importer.vtablePointerTypeReportError = true;
importer.vtablePointerType = PointerDataType.dataType;
return;
}

StdumpAST.Node node = importer.ast.deduplicatedTypes.get(typeIndex);

public void fixVtablePointerType(StdumpAST.InlineStructOrUnion vtablePointerType) {
// For some compiler versions __vtbl_ptr_type is just a function
// pointer, for others it's a struct containing some integers and a
// function pointer. In the latter case the stab generated for that type
// is weird, so we recreate it from scratch.
if(node.sizeBits == 64) {
StructureDataType type = new StructureDataType("__vtbl_ptr_type_ccc", 8, importer.programTypeManager);
type.setDescription("Generated by the STABS importer.");
try {
type.replaceAtOffset(0, ShortDataType.dataType, 2, "__delta", null);
type.replaceAtOffset(2, ShortDataType.dataType, 2, "__index", null);
type.replaceAtOffset(4, PointerDataType.dataType, 4, "__pfn", null);
} catch(IllegalArgumentException e) {
importer.log.appendException(e);
// function pointer. In the latter case, the stab provided in the symbol
// table leads to incorrect decompilation of virtual function calls, so
// we need to fix it up here.
for(StdumpAST.Node field : vtablePointerType.fields) {
if(field.name.equals("__delta2")) {
vtablePointerType.fields.remove(field);
break;
}
importer.vtablePointerType = importer.programTypeManager.addDataType(type, null);
} else {
importer.vtablePointerType = PointerDataType.dataType;
}
}

Expand Down
5 changes: 0 additions & 5 deletions src/main/java/ghidra/emotionengine/symboltable/StdumpAST.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public static class ImporterState {
HashMap<String, StructureDataType> forwardDeclaredTypes = new HashMap<>();
ArrayList<String> prefixStack = new ArrayList<>(); // Used to name nested structs.
DataType vtablePointerType;
boolean vtablePointerTypeReportError = false;

// Ghidra objects.
TaskMonitor monitor;
Expand Down Expand Up @@ -422,10 +421,6 @@ public void fillVtable(StructureDataType dest, ImporterState importer) {
} catch(IllegalArgumentException e) {
importer.log.appendException(e);
}
if(importer.vtablePointerTypeReportError) {
importer.log.appendMsg("STABS", "Cannot find type '__vtbl_ptr_type'. Generated C++ vtables may be incorrect.");
importer.vtablePointerTypeReportError = false;
}
}
}
}
Expand Down

0 comments on commit 80fd9ed

Please sign in to comment.