From 8aa5ac7c477c10ae88c50100365c5c77617414d5 Mon Sep 17 00:00:00 2001 From: ghidra007 Date: Tue, 9 May 2023 13:41:26 -0400 Subject: [PATCH] GP-3406 RTTI script - added check that mingw analyzer fixed relocations correctly. --- .../RecoverClassesFromRTTIScript.java | 86 ++++++++++++------- .../classrecovery/RTTIGccClassRecoverer.java | 8 -- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java b/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java index 2a5b8e24ee9..1148d082324 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java @@ -56,18 +56,10 @@ import java.io.PrintWriter; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; -import classrecovery.DecompilerScriptUtils; -import classrecovery.RTTIClassRecoverer; -import classrecovery.RTTIGccClassRecoverer; -import classrecovery.RTTIWindowsClassRecoverer; -import classrecovery.RecoveredClass; -import classrecovery.RecoveredClassHelper; +import classrecovery.*; import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.decompiler.DecompInterface; import ghidra.app.plugin.core.analysis.AutoAnalysisManager; @@ -75,6 +67,7 @@ import ghidra.app.script.GhidraScript; import ghidra.app.services.Analyzer; import ghidra.app.services.GraphDisplayBroker; +import ghidra.app.util.NamespaceUtils; import ghidra.app.util.bin.format.dwarf4.next.DWARFFunctionImporter; import ghidra.app.util.bin.format.dwarf4.next.DWARFProgram; import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.DWARFSectionProvider; @@ -84,29 +77,14 @@ import ghidra.app.util.opinion.PeLoader; import ghidra.framework.options.Options; import ghidra.framework.plugintool.PluginTool; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressSet; -import ghidra.program.model.address.AddressSetView; -import ghidra.program.model.data.CategoryPath; -import ghidra.program.model.data.DataType; -import ghidra.program.model.data.DataTypeComponent; -import ghidra.program.model.data.DataTypeManager; -import ghidra.program.model.data.Structure; -import ghidra.program.model.listing.Function; -import ghidra.program.model.listing.Parameter; -import ghidra.program.model.listing.Program; +import ghidra.program.model.address.*; +import ghidra.program.model.data.*; +import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryBlock; +import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.SymbolIterator; import ghidra.program.util.GhidraProgramUtilities; -import ghidra.service.graph.AttributedEdge; -import ghidra.service.graph.AttributedGraph; -import ghidra.service.graph.AttributedVertex; -import ghidra.service.graph.GraphDisplay; -import ghidra.service.graph.GraphDisplayOptions; -import ghidra.service.graph.GraphDisplayOptionsBuilder; -import ghidra.service.graph.GraphDisplayProvider; -import ghidra.service.graph.GraphType; -import ghidra.service.graph.GraphTypeBuilder; -import ghidra.service.graph.VertexShape; +import ghidra.service.graph.*; import ghidra.util.exception.CancelledException; import ghidra.util.exception.GraphException; import ghidra.util.task.TaskMonitor; @@ -391,7 +369,7 @@ private boolean isDwarfLoadedInProgram() { DWARFProgram.DWARF_ROOT_NAME) || options.getBoolean("DWARF Loaded", false)); } - public String validate() { + public String validate() throws CancelledException { if (currentProgram == null) { return ("There is no open program"); @@ -425,6 +403,25 @@ public String validate() { if (defaultPointerSize != 4 && defaultPointerSize != 8) { return ("This script only works on 32 or 64 bit programs"); } + + // check that gcc loader or mingw analyzer has fixed the relocations correctly + if(isGcc()) { + + // first check that there is even rtti by searching the special string in memory + if (!isStringInProgramMemory("class_type_info")) { + return ("This program does not contain RTTI."); + } + + // then check to see if the special typeinfo namespace is in external space + // if so then relocations are present and have not been fixed up because when fixed up + // the namespace gets moved to inside program space + if(isExternalNamespace("__cxxabiv1::__class_type_info")) { + return ("This program's relocations were not correctly fixed so the script cannot " + + "continue. If this program is mingw this is a known issue and " + + "will be fixed in a later release. For all other gcc programs please " + + "contact the Ghidra team so this issue can be fixed."); + } + } return new String(); } @@ -1549,6 +1546,31 @@ private void printTime() { LocalDateTime now = LocalDateTime.now(); println(dtf.format(now)); } + + private boolean isStringInProgramMemory(String string) { + + byte[] byteArrray = string.getBytes(); + + Address findBytes = currentProgram.getMemory() + .findBytes(currentProgram.getMinAddress(), byteArrray, null, true, monitor); + if (findBytes != null) { + return true; + } + return false; + } + + private boolean isExternalNamespace(String path) throws CancelledException { + + List symbols = NamespaceUtils.getSymbols(path, currentProgram, true); + for(Symbol symbol : symbols) { + monitor.checkCancelled(); + if(symbol.isExternal() && symbol.getSymbolType().isNamespace()) { + return true; + } + } + + return false; + } } diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java index f75fecc4ec7..27a945b9e84 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java @@ -698,8 +698,6 @@ private List processVtables(List typeinfos) for (GccTypeinfo typeinfo : typeinfos) { monitor.checkCancelled(); - Msg.debug(this, typeinfo.getNamespace().getName()); - Address typeinfoAddress = typeinfo.getAddress(); Structure typeinfoStructure = getTypeinfoStructure(typeinfoAddress); @@ -2638,10 +2636,6 @@ private Structure getOrCreateVmiTypeinfoStructure(Address typeinfoAddress, return null; } - Msg.debug(this, "numBases for typeinfo: " + typeinfoAddress.toString() + " at address " - + typeinfoAddress.add(offsetOfNumBases) + " numbases: " + numBases); - ; - // get or create the vmiClassTypeInfoStruct Structure vmiClassTypeinfoStructure = (Structure) dataTypeManager.getDataType(classDataTypesCategoryPath, VMI_CLASS_TYPE_INFO_STRUCTURE + numBases); @@ -2718,8 +2712,6 @@ private Symbol createDemangledTypeinfoSymbol(Address typeinfoAddress) Namespace classNamespace = typeinfoNameSymbol.getParentNamespace(); - Msg.debug(this, typeinfoAddress.toString() + " " + classNamespace.getName()); - if (classNamespace.isGlobal()) { Msg.debug(this, typeinfoAddress.toString() + "Could not create a class namespace for demangled namespace string ");