astrelsky / Ghidra-Cpp-Class-Analyzer

Ghidra C++ Class and Run Time Type Information Analyzer
MIT License
633 stars 46 forks source link

Analysis failure, unable to copy some library ClassTypeInfo data to a project archive #59

Closed bpengu1n closed 1 year ago

bpengu1n commented 2 years ago

Ran analysis on a shared library in Ghidra 10.1.5 with GCC C++ Class Analyzer and GCC RTTI Analyzer enabled and their default settings set. During analysis, received the following error:

Ghidra-Cpp-Class-Analyzer> Cannot invoke "ghidra.program.model.address.Address.getAddressSpace()" because "addr" is null

Following analysis, I was able to see a large portion of class information populated under the file archive. When attempting to copy the file archive to a project archive, it failed part-way through copy (only copied a portion of the top-level classes, and non of their parent class information), with the following errors:

java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:208)
    at java.base/java.util.ImmutableCollections$Set12.<init>(ImmutableCollections.java:783)
    at java.base/java.util.Set.of(Set.java:702)
    at cppclassanalyzer.data.typeinfo.ArchivedClassTypeInfo.getVirtualParents(ArchivedClassTypeInfo.java:311)
    at cppclassanalyzer.plugin.typemgr.node.TypeInfoNode.generateChildren(TypeInfoNode.java:235)
    at docking.widgets.tree.CoreGTreeNode.children(CoreGTreeNode.java:114)
    at docking.widgets.tree.GTreeNode.getChild(GTreeNode.java:180)
    at cppclassanalyzer.plugin.typemgr.node.TypeInfoTreeNodeManager.createTypeNode(TypeInfoTreeNodeManager.java:75)
    at cppclassanalyzer.plugin.typemgr.node.AbstractSingleManagerNode.addNode(AbstractSingleManagerNode.java:23)
    at cppclassanalyzer.plugin.typemgr.TypeInfoArchiveGTree.typeAdded(TypeInfoArchiveGTree.java:63)
    at cppclassanalyzer.plugin.ClassTypeInfoManagerPlugin.managerChanged(ClassTypeInfoManagerPlugin.java:215)
    at cppclassanalyzer.data.manager.AbstractRttiRecordWorker.resolve(AbstractRttiRecordWorker.java:149)
    at cppclassanalyzer.data.manager.LibraryClassTypeInfoManager.resolve(LibraryClassTypeInfoManager.java:58)
    at cppclassanalyzer.data.manager.ProjectClassTypeInfoManager.doInsert(ProjectClassTypeInfoManager.java:351)
    at cppclassanalyzer.data.manager.ProjectClassTypeInfoManager.insert(ProjectClassTypeInfoManager.java:334)
    at cppclassanalyzer.plugin.typemgr.action.PasteArchiveAction$PasteArchiveBackgroundCommand.applyTo(PasteArchiveAction.java:73)
    at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
    at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:315)
    at java.base/java.lang.Thread.run(Thread.java:833)

---------------------------------------------------
Build Date: 2022-Aug-02 2138 UTC
Ghidra Version: 10.1.5
Java Home: /usr/lib/jvm/java-17-openjdk-amd64
JVM Version: Private Build 17.0.3
OS: Linux 5.15.0-43-generic amd64

Unspecified error occurred.
---------------------------------------------------
Build Date: 2022-Aug-02 2138 UTC
Ghidra Version: 10.1.5
Java Home: /usr/lib/jvm/java-17-openjdk-amd64
JVM Version: Private Build 17.0.3
OS: Linux 5.15.0-43-generic amd64

edit: trace of the initial analysis error from Eclipse:

java.lang.NullPointerException: Cannot invoke "ghidra.program.model.address.Address.getAddressSpace()" because "addr" is null
    at ghidra.program.database.map.AddressMapDB.encodeRelative(AddressMapDB.java:636)
    at ghidra.program.database.map.AddressMapDB.getKey(AddressMapDB.java:283)
    at ghidra.program.database.bookmark.BookmarkDBManager.getBookmark(BookmarkDBManager.java:334)
    at ghidra.program.database.bookmark.BookmarkDBManager.setBookmark(BookmarkDBManager.java:294)
    at ghidra.app.plugin.prototype.GccRttiAnalyzer.applyTypeInfo(GccRttiAnalyzer.java:341)
    at ghidra.app.plugin.prototype.GccRttiAnalyzer.added(GccRttiAnalyzer.java:123)
    at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:186)
    at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:688)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:788)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:667)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:632)
    at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:58)
    at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
    at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:319)
    at java.base/java.lang.Thread.run(Thread.java:833)
bpengu1n commented 2 years ago

Also of note, I was initially using the latest from the master branch as of two days ago. Just re-attempted with release 2.1.1. I still get the first error (re: AddressSpace); I don't get the second error when copying the data to a project archive. However, most of the class data is flattened, i.e. class hierarchies are no longer displayed for most classes, and instead the parent classes are displayed as separate classes in the namespace. This behavior also happens sometimes in master. It always seems to be linked back to an error being thrown during analysis, either the above AddressSpace error, or one that simply says "null".

bpengu1n commented 2 years ago

One more comment - I noticed when the last case I mentioned occurs, the application log outputs messages such as:

2022-08-04 16:44:43 WARN  (ClassTypeInfoUtils) Variable Utils returned wrong class structure! IInterface
astrelsky commented 2 years ago

Uh oh, I'll investigate this weekend and see if I can figure out where the problem is.

One more comment - I noticed when the last case I mentioned occurs, the application log outputs messages such as:

2022-08-04 16:44:43 WARN  (ClassTypeInfoUtils) Variable Utils returned wrong class structure! IInterface

Unfortunately this is normal and out of my control. If you decompile one of IInterface's methods the decompiler may decide to use some other struct named IInterface because it has the same name and the VariableUtils class just takes the first Structure it finds with the correct name.

The initial analysis error seems really weird. Unless I'm trying to create a bookmark at null.

bpengu1n commented 2 years ago

Sounds good, if I find anything out as well I'll be sure to update.

bpengu1n commented 2 years ago

Disabled bookmark creation, and this is the error I get:

ghidra.util.exception.AssertException: Unexpected Error: ghidra.program.model.mem.MemoryAccessException
    at ghidra.app.cmd.data.rtti.gcc.typeinfo.VmiClassTypeInfoModel.getBaseArrayDataType(VmiClassTypeInfoModel.java:269)
    at ghidra.app.cmd.data.rtti.gcc.CreateTypeInfoBackgroundCmd.doApplyTo(CreateTypeInfoBackgroundCmd.java:66)
    at ghidra.app.cmd.data.rtti.gcc.CreateTypeInfoBackgroundCmd.applyTo(CreateTypeInfoBackgroundCmd.java:54)
    at ghidra.app.plugin.prototype.GccRttiAnalyzer.applyTypeInfo(GccRttiAnalyzer.java:333)
    at ghidra.app.plugin.prototype.GccRttiAnalyzer.added(GccRttiAnalyzer.java:123)
    at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:186)
    at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:688)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:788)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:667)
    at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:632)
    at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:58)
    at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
    at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:319)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: ghidra.program.model.mem.MemoryAccessException
    at ghidra.util.GhidraLittleEndianDataConverter.getInt(GhidraLittleEndianDataConverter.java:42)
    at ghidra.program.database.code.CodeUnitDB.getInt(CodeUnitDB.java:191)
    at ghidra.app.cmd.data.rtti.gcc.typeinfo.VmiClassTypeInfoModel.getBaseArrayDataType(VmiClassTypeInfoModel.java:264)
    ... 14 more
INFO  Analysis Log Messages
Ghidra-Cpp-Class-Analyzer> Unexpected Error: ghidra.program.model.mem.MemoryAccessException
astrelsky commented 2 years ago

I'm currently under the impression that it is attempting to create a typeinfo which isn't valid. I just pushed a4aeeabcb5094205dc61a289dff70e39fa4915bc to try and prevent this and log it's occurrence with some information.

bpengu1n commented 2 years ago

@astrelsky Good news! Looks like that did it - analysis completes without frontend failure, and I do see the logged outputs you added. Including them below in case it's useful:

2022-08-06 21:34:45 ERROR (CreateTypeInfoBackgroundCmd) Failed to apply typeinfo at 0002d298 ghidra.program.model.mem.MemoryAccessException
        at ghidra.util.GhidraLittleEndianDataConverter.getInt(GhidraLittleEndianDataConverter.java:42)
        at ghidra.program.database.code.CodeUnitDB.getInt(CodeUnitDB.java:191)
        at ghidra.app.cmd.data.rtti.gcc.typeinfo.VmiClassTypeInfoModel.getBaseArrayDataType(VmiClassTypeInfoModel.java:263)
        at ghidra.app.cmd.data.rtti.gcc.CreateTypeInfoBackgroundCmd.doApplyTo(CreateTypeInfoBackgroundCmd.java:67)
        at ghidra.app.cmd.data.rtti.gcc.CreateTypeInfoBackgroundCmd.applyTo(CreateTypeInfoBackgroundCmd.java:55)
        at ghidra.app.plugin.prototype.GccRttiAnalyzer.applyTypeInfo(GccRttiAnalyzer.java:344)
        at ghidra.app.plugin.prototype.GccRttiAnalyzer.added(GccRttiAnalyzer.java:129)
        at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:186)
        at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:688)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:788)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:667)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:632)
        at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:58)
        at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
        at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:319)
        at java.base/java.lang.Thread.run(Thread.java:833)

2022-08-06 21:34:45 ERROR (CreateTypeInfoBackgroundCmd) ghidra.program.model.util.CodeUnitInsertionException: Insufficent memory at address EXTERNAL:000000ba (length: 8 bytes)  
2022-08-06 21:34:45 ERROR (CreateTypeInfoBackgroundCmd) ghidra.program.model.util.CodeUnitInsertionException: Insufficent memory at address EXTERNAL:000000bb (length: 8 bytes)
astrelsky commented 2 years ago

@astrelsky Good news! Looks like that did it - analysis completes without frontend failure, and I do see the logged outputs you added. Including them below in case it's useful:

2022-08-06 21:34:45 ERROR (CreateTypeInfoBackgroundCmd) Failed to apply typeinfo at 0002d298 ghidra.program.model.mem.MemoryAccessException
        at ghidra.util.GhidraLittleEndianDataConverter.getInt(GhidraLittleEndianDataConverter.java:42)
        at ghidra.program.database.code.CodeUnitDB.getInt(CodeUnitDB.java:191)
        at ghidra.app.cmd.data.rtti.gcc.typeinfo.VmiClassTypeInfoModel.getBaseArrayDataType(VmiClassTypeInfoModel.java:263)
        at ghidra.app.cmd.data.rtti.gcc.CreateTypeInfoBackgroundCmd.doApplyTo(CreateTypeInfoBackgroundCmd.java:67)
        at ghidra.app.cmd.data.rtti.gcc.CreateTypeInfoBackgroundCmd.applyTo(CreateTypeInfoBackgroundCmd.java:55)
        at ghidra.app.plugin.prototype.GccRttiAnalyzer.applyTypeInfo(GccRttiAnalyzer.java:344)
        at ghidra.app.plugin.prototype.GccRttiAnalyzer.added(GccRttiAnalyzer.java:129)
        at ghidra.app.plugin.core.analysis.AnalysisScheduler.runAnalyzer(AnalysisScheduler.java:186)
        at ghidra.app.plugin.core.analysis.AnalysisTask.applyTo(AnalysisTask.java:39)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager$AnalysisTaskWrapper.run(AutoAnalysisManager.java:688)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:788)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:667)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.startAnalysis(AutoAnalysisManager.java:632)
        at ghidra.app.plugin.core.analysis.AnalysisBackgroundCommand.applyTo(AnalysisBackgroundCommand.java:58)
        at ghidra.framework.plugintool.mgr.BackgroundCommandTask.run(BackgroundCommandTask.java:102)
        at ghidra.framework.plugintool.mgr.ToolTaskManager.run(ToolTaskManager.java:319)
        at java.base/java.lang.Thread.run(Thread.java:833)

2022-08-06 21:34:45 ERROR (CreateTypeInfoBackgroundCmd) ghidra.program.model.util.CodeUnitInsertionException: Insufficent memory at address EXTERNAL:000000ba (length: 8 bytes)  
2022-08-06 21:34:45 ERROR (CreateTypeInfoBackgroundCmd) ghidra.program.model.util.CodeUnitInsertionException: Insufficent memory at address EXTERNAL:000000bb (length: 8 bytes)

Excellent. Seeing the EXTERNAL address spaces in the logs is a bit worrying though. May you show what the data 0x2d298 looks like?