diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc index 0bbdc35c52..82c1cab05c 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc @@ -362,6 +362,8 @@ void Symbol::saveXmlHeader(ostream &s) const a_v_b(s,"hiddenretparm",true); if ((dispflags&isolate)!=0) a_v_b(s,"merge",false); + if ((dispflags&is_this_ptr)!=0) + a_v_b(s,"thisptr",true); int4 format = getDisplayFormat(); if (format != 0) { s << " format=\""; @@ -461,6 +463,10 @@ void Symbol::restoreXmlHeader(const Element *el) if (xml_readbool(el->getAttributeValue(i))) flags |= Varnode::typelock; } + else if (attName == "thisptr") { + if (xml_readbool(el->getAttributeValue(i))) + dispflags |= is_this_ptr; + } break; case 'v': if (attName == "volatile") { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/database.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/database.hh index 10b2c0f547..1bd6731fdd 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/database.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/database.hh @@ -183,7 +183,8 @@ public: force_char = 5, ///< Force integer to be printed as a character constant size_typelock = 8, ///< Only the size of the symbol is typelocked isolate = 16, ///< Symbol should not speculatively merge automatically - merge_problems = 32 ///< Set if some SymbolEntrys did not get merged + merge_problems = 32, ///< Set if some SymbolEntrys did not get merged + is_this_ptr = 64 ///< We are the "this" symbol for a class method }; Symbol(Scope *sc,const string &nm,Datatype *ct); ///< Construct given a name and data-type @@ -198,6 +199,7 @@ public: bool isTypeLocked(void) const { return ((flags&Varnode::typelock)!=0); } ///< Is the Symbol type-locked bool isNameLocked(void) const { return ((flags&Varnode::namelock)!=0); } ///< Is the Symbol name-locked bool isSizeTypeLocked(void) const { return ((dispflags & size_typelock)!=0); } ///< Is the Symbol size type-locked + bool isThisPointer(void) const { return ((dispflags & is_this_ptr)!=0); } ///< Is \b this the "this" pointer bool isIndirectStorage(void) const { return ((flags&Varnode::indirectstorage)!=0); } ///< Is storage really a pointer to the true Symbol bool isHiddenReturn(void) const { return ((flags&Varnode::hiddenretparm)!=0); } ///< Is this a reference to the function return value bool isNameUndefined(void) const; ///< Does \b this have an undefined name diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java index 2a3c2b3fd3..ecbf29f663 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java @@ -17,10 +17,11 @@ package ghidra.program.model.pcode; import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; -import ghidra.program.model.listing.Program; -import ghidra.program.model.listing.VariableStorage; +import ghidra.program.model.lang.DynamicVariableStorage; +import ghidra.program.model.listing.*; import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.Symbol; +import ghidra.util.exception.InvalidInputException; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.XmlElement; import ghidra.xml.XmlPullParser; @@ -40,6 +41,8 @@ public class HighSymbol { protected int categoryIndex; // Numbering within the sub-class private boolean namelock; // Is this variable's name locked private boolean typelock; // Is this variable's datatype locked + private boolean isThis; // True if we are "this" symbol for function method call + private boolean isHidden; // True if we are hidden symbol containing pointer to where return value is stored private long id; // Unique id of this symbol protected SymbolEntry[] entryList; // List of mappings for this symbol @@ -53,6 +56,8 @@ public class HighSymbol { protected HighSymbol(HighFunction func) { function = func; dtmanage = function.getDataTypeManager(); + isThis = false; + isHidden = false; } /** @@ -69,6 +74,8 @@ public class HighSymbol { type = tp; namelock = false; typelock = false; + isThis = false; + isHidden = false; id = uniqueId; category = -1; categoryIndex = -1; @@ -92,6 +99,8 @@ public class HighSymbol { type = tp; namelock = nlock; typelock = tlock; + isThis = false; + isHidden = false; id = uniqueId; category = -1; categoryIndex = -1; @@ -101,6 +110,15 @@ public class HighSymbol { if (entryList == null) { entryList = new SymbolEntry[1]; entryList[0] = entry; + if (entry.getStorage().isAutoStorage()) { + AutoParameterType autoType = entry.getStorage().getAutoParameterType(); + if (autoType == AutoParameterType.THIS) { + isThis = true; + } + else if (autoType == AutoParameterType.RETURN_STORAGE_PTR) { + isHidden = true; + } + } } else { SymbolEntry[] newList = new SymbolEntry[entryList.length + 1]; @@ -316,6 +334,20 @@ public class HighSymbol { return false; } + /** + * @return true if symbol is a "this" pointer for a class method + */ + public boolean isThisPointer() { + return isThis; + } + + /** + * @return true is symbol holds a pointer to where a function's return value should be stored + */ + public boolean isHiddenReturn() { + return isHidden; + } + /** * @return the first mapping object attached to this symbol */ @@ -349,6 +381,12 @@ public class HighSymbol { if (isIsolated()) { SpecXmlUtils.encodeBooleanAttribute(buf, "merge", false); } + if (isThis) { + SpecXmlUtils.encodeBooleanAttribute(buf, "thisptr", true); + } + if (isHidden) { + SpecXmlUtils.encodeBooleanAttribute(buf, "hiddenretparm", true); + } SpecXmlUtils.encodeSignedIntegerAttribute(buf, "cat", category); if (categoryIndex >= 0) { SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", categoryIndex); @@ -382,6 +420,16 @@ public class HighSymbol { if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) { namelock = true; } + isThis = false; + String thisstring = symel.getAttribute("thisptr"); + if ((thisstring != null) && (SpecXmlUtils.decodeBoolean(thisstring))) { + isThis = true; + } + isHidden = false; + String hiddenstring = symel.getAttribute("hiddenretparm"); + if ((hiddenstring != null) && (SpecXmlUtils.decodeBoolean(hiddenstring))) { + isHidden = true; + } // isolate = false; // String isolatestr = symel.getAttribute("merge"); // if ((isolatestr != null) && !SpecXmlUtils.decodeBoolean(isolatestr)) { @@ -431,6 +479,20 @@ public class HighSymbol { entry.restoreXML(parser); addMapEntry(entry); } + if ((isThis || isHidden) && entryList != null) { + SymbolEntry entry = entryList[0]; + VariableStorage storage = entry.getStorage(); + AutoParameterType autoType = + isThis ? AutoParameterType.THIS : AutoParameterType.RETURN_STORAGE_PTR; + try { + VariableStorage newStorage = new DynamicVariableStorage(storage.getProgram(), + autoType, storage.getFirstVarnode()); + entryList[0] = new MappedEntry(this, newStorage, entry.getPCAdress()); + } + catch (InvalidInputException e) { + throw new PcodeXMLException("Unable to parse auto-parameter"); + } + } } /**