diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/action.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/action.cc index adcee171fc..9157c6fde0 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/action.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/action.cc @@ -955,13 +955,26 @@ ActionDatabase::~ActionDatabase(void) delete (*iter).second; } -/// This provides the database with the single Action from which all other -/// \e root Actions are derived. The Action has a reserved name "universal" -/// \param act is the universal Action -void ActionDatabase::registerUniversal(Action *act) +/// Clear out (possibly altered) root Actions. Reset the default groups. +/// Set the default root action "decompile" +void ActionDatabase::resetDefaults(void) { - registerAction(universalname,act); + Action *universalAction = (Action *)0; + map::iterator iter; + iter = actionmap.find(universalname); + if (iter != actionmap.end()) + universalAction = (*iter).second; + for(iter = actionmap.begin();iter!=actionmap.end();++iter) { + Action *curAction = (*iter).second; + if (curAction != universalAction) + delete curAction; // Clear out any old (modified) root actions + } + actionmap.clear(); + registerAction(universalname, universalAction); + + buildDefaultGroups(); + setCurrent("decompile"); // The default root action } const ActionGroupList &ActionDatabase::getGroup(const string &grp) const @@ -1019,13 +1032,15 @@ Action *ActionDatabase::toggleAction(const string &grp, const string &basegrp,bo /// \param argv is a list of static char pointers, which must end with a NULL pointer, or a zero length string. void ActionDatabase::setGroup(const string &grp,const char **argv) -{ ActionGroupList &curgrp( groupmap[ grp ] ); +{ + ActionGroupList &curgrp( groupmap[ grp ] ); curgrp.list.clear(); // Clear out any old members for(int4 i=0;;++i) { if (argv[i] == (char *)0) break; if (argv[i][0] == '\0') break; curgrp.list.insert( argv[i] ); } + isDefaultGroups = false; } /// Copy an existing \e root Action by copying its grouplist, giving it a new name. @@ -1038,6 +1053,7 @@ void ActionDatabase::cloneGroup(const string &oldname,const string &newname) { const ActionGroupList &curgrp(getGroup(oldname)); // Should already exist groupmap[ newname ] = curgrp; // Copy the group + isDefaultGroups = false; } /// Add a group to the grouplist for a particular \e root Action. @@ -1046,7 +1062,9 @@ void ActionDatabase::cloneGroup(const string &oldname,const string &newname) /// \param basegroup is the group to add /// \return \b true for a new addition, \b false is the group was already present bool ActionDatabase::addToGroup(const string &grp, const string &basegroup) + { + isDefaultGroups = false; ActionGroupList &curgrp( groupmap[ grp ] ); return curgrp.list.insert( basegroup ).second; } @@ -1057,7 +1075,9 @@ bool ActionDatabase::addToGroup(const string &grp, const string &basegroup) /// \param basegrp is the group to remove /// \return \b true if the group existed and was removed bool ActionDatabase::removeFromGroup(const string &grp, const string &basegrp) + { + isDefaultGroups = false; ActionGroupList &curgrp( groupmap[ grp ] ); return (curgrp.list.erase(basegrp) > 0); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/action.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/action.hh index 14df7561dc..bb562e5591 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/action.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/action.hh @@ -296,14 +296,16 @@ class ActionDatabase { string currentactname; ///< The name associated with the current root Action map groupmap; ///< Map from root Action name to the grouplist it uses map actionmap; ///< Map from name to root Action + bool isDefaultGroups; ///< \b true if only the default groups are set static const char universalname[]; ///< The name of the \e universal root Action void registerAction(const string &nm,Action *act); ///< Register a \e root Action + void buildDefaultGroups(void); ///< Set up descriptions of preconfigured root Actions Action *getAction(const string &nm) const; ///< Look up a \e root Action by name Action *deriveAction(const string &baseaction,const string &grp); ///< Derive a \e root Action public: - ActionDatabase(void) { currentact = (Action *)0; } ///< Constructor + ActionDatabase(void) { currentact = (Action *)0; isDefaultGroups = false; } ///< Constructor ~ActionDatabase(void); ///< Destructor - void registerUniversal(Action *act); ///< Register the \e universal root Action + void resetDefaults(void); ///< (Re)set the default configuration Action *getCurrent(void) const { return currentact; } ///< Get the current \e root Action const string &getCurrentName(void) const { return currentactname; } ///< Get the name of the current \e root Action const ActionGroupList &getGroup(const string &grp) const; ///< Get a specific grouplist by name @@ -314,6 +316,7 @@ public: void cloneGroup(const string &oldname,const string &newname); ///< Clone a \e root Action bool addToGroup(const string &grp,const string &basegroup); ///< Add a group to a \e root Action bool removeFromGroup(const string &grp,const string &basegroup); ///< Remove a group from a \e root Action + void universalAction(Architecture *glb); ///< Build the universal action }; #endif diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc index 875078ec31..9116284df4 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc @@ -86,17 +86,10 @@ Architecture::Architecture(void) { // endian = -1; - trim_recurse_max = 5; // Reasonable default value - max_implied_ref = 2; // 2 is best, in specific cases a higher number might be good - max_term_duplication = 2; // 2 and 3 (4) are pretty reasonable - max_basetype_size = 10; // Needs to be 8 or bigger + resetDefaultsInternal(); min_funcsymbol_size = 1; aggressive_ext_trim = false; - readonlypropagate = false; - infer_pointers = true; funcptr_align = 0; - flowoptions = 0; - alias_block_level = 2; // Block structs and arrays by default defaultfp = (ProtoModel *)0; defaultReturnAddr.space = (AddrSpace *)0; evalfp_current = (ProtoModel *)0; @@ -508,8 +501,8 @@ void Architecture::buildAction(DocumentStorage &store) { parseExtraRules(store); // Look for any additional rules - universal_action(this); - allacts.setCurrent("decompile"); + allacts.universalAction(this); + allacts.resetDefaults(); } /// This builds the database which holds the status registers setings and other @@ -1253,6 +1246,30 @@ void Architecture::init(DocumentStorage &store) fillinReadOnlyFromLoader(); } +void Architecture::resetDefaultsInternal(void) + +{ + trim_recurse_max = 5; + max_implied_ref = 2; // 2 is best, in specific cases a higher number might be good + max_term_duplication = 2; // 2 and 3 (4) are reasonable + max_basetype_size = 10; // Needs to be 8 or bigger + flowoptions = 0; + infer_pointers = true; + readonlypropagate = false; + alias_block_level = 2; // Block structs and arrays by default +} + +/// Reset options that can be modified by the OptionDatabase. This includes +/// options specific to this class and options under PrintLanguage and ActionDatabase +void Architecture::resetDefaults(void) + +{ + resetDefaultsInternal(); + allacts.resetDefaults(); + for(int4 i=0;iresetDefaults(); +} + Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point,uintb &fullEncoding) { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh index 0a67163fbd..87de413e95 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh @@ -164,6 +164,8 @@ public: #endif Architecture(void); ///< Construct an uninitialized Architecture void init(DocumentStorage &store); ///< Load the image and configure architecture + void resetDefaultsInternal(void); ///< Reset default values for options specific to Architecture + void resetDefaults(void); ///< Reset defaults values for options owned by \b this ProtoModel *getModel(const string &nm) const; ///< Get a specific PrototypeModel bool hasModel(const string &nm) const; ///< Does this Architecture have a specific PrototypeModel bool highPtrPossible(const Address &loc,int4 size) const; ///< Are pointers possible to the given location? diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 75114edf14..0cb2ddc1f3 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -4703,11 +4703,12 @@ void TermOrder::sortTerms(void) sort(sorter.begin(),sorter.end(),additiveCompare); } -/// Build the default \e root Actions: decompile, jumptable, normalize, paramid, register, firstpass -/// \param allacts is the database that will hold the \e root Actions -void build_defaultactions(ActionDatabase &allacts) +/// (Re)build the default \e root Actions: decompile, jumptable, normalize, paramid, register, firstpass +void ActionDatabase::buildDefaultGroups(void) { + if (isDefaultGroups) return; + groupmap.clear(); const char *members[] = { "base", "protorecovery", "protorecovery_a", "deindirect", "localrecovery", "deadcode", "typerecovery", "stackptrflow", "blockrecovery", "stackvars", "deadcontrolflow", "switchnorm", @@ -4716,36 +4717,37 @@ void build_defaultactions(ActionDatabase &allacts) "segment", "returnsplit", "nodejoin", "doubleload", "doubleprecis", "unreachable", "subvar", "floatprecision", "conditionalexe", "" }; - allacts.setGroup("decompile",members); + setGroup("decompile",members); const char *jumptab[] = { "base", "noproto", "localrecovery", "deadcode", "stackptrflow", "stackvars", "analysis", "segment", "subvar", "conditionalexe", "" }; - allacts.setGroup("jumptable",jumptab); + setGroup("jumptable",jumptab); const char *normali[] = { "base", "protorecovery", "protorecovery_b", "deindirect", "localrecovery", "deadcode", "stackptrflow", "normalanalysis", "stackvars", "deadcontrolflow", "analysis", "fixateproto", "nodejoin", "unreachable", "subvar", "floatprecision", "normalizebranches", "conditionalexe", "" }; - allacts.setGroup("normalize",normali); + setGroup("normalize",normali); const char *paramid[] = { "base", "protorecovery", "protorecovery_b", "deindirect", "localrecovery", "deadcode", "typerecovery", "stackptrflow", "siganalysis", "stackvars", "deadcontrolflow", "analysis", "fixateproto", "unreachable", "subvar", "floatprecision", "conditionalexe", "" }; - allacts.setGroup("paramid",paramid); + setGroup("paramid",paramid); const char *regmemb[] = { "base", "analysis", "subvar", "" }; - allacts.setGroup("register",regmemb); + setGroup("register",regmemb); const char *firstmem[] = { "base", "" }; - allacts.setGroup("firstpass",firstmem); + setGroup("firstpass",firstmem); + isDefaultGroups = true; } /// Construct the \b universal Action that contains all possible components /// \param conf is the Architecture that will use the Action -void universal_action(Architecture *conf) +void ActionDatabase::universalAction(Architecture *conf) { vector::iterator iter; @@ -4757,9 +4759,8 @@ void universal_action(Architecture *conf) ActionGroup *actstackstall; AddrSpace *stackspace = conf->getStackSpace(); - build_defaultactions(conf->allacts); act = new ActionRestartGroup(Action::rule_onceperfunc,"universal",1); - conf->allacts.registerUniversal(act); + registerAction(universalname,act); act->addAction( new ActionStart("base")); act->addAction( new ActionConstbase("base")); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc index 231a12dd42..c6b60c15ee 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_process.cc @@ -433,6 +433,7 @@ void SetOptions::rawAction(void) { res = false; + ghidra->resetDefaults(); ghidra->options->restoreXml(doc->getRoot()); delete doc; doc = (Document *)0; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc index 21ded50c81..009d5bbb64 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.cc @@ -344,6 +344,12 @@ void EmitXml::spaces(int4 num,int4 bump) } } +void EmitXml::resetDefaults(void) + +{ + resetDefaultsInternal(); +} + int4 TokenSplit::countbase = 0; /// Emit markup or content corresponding to \b this token on a low-level emitter. @@ -536,15 +542,15 @@ void TokenSplit::printDebug(ostream &s) const } #endif -EmitPrettyPrint::EmitPrettyPrint(int4 mls) - : EmitXml(), scanqueue( 3*mls ), tokqueue( 3*mls ) +EmitPrettyPrint::EmitPrettyPrint(void) + : EmitXml(), scanqueue( 3*100 ), tokqueue( 3*100 ) { lowlevel = new EmitNoXml(); // Do not emit xml by default - maxlinesize = mls; spaceremain = maxlinesize; needbreak = false; commentmode = false; + resetDefaultsPrettyPrint(); } EmitPrettyPrint::~EmitPrettyPrint(void) @@ -1213,3 +1219,11 @@ void EmitPrettyPrint::setMaxLineSize(int4 val) spaceremain = maxlinesize; clear(); } + +void EmitPrettyPrint::resetDefaults(void) + +{ + lowlevel->resetDefaults(); + resetDefaultsInternal(); + resetDefaultsPrettyPrint(); +} diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh index ff4230fd35..5de1739874 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/prettyprint.hh @@ -80,8 +80,9 @@ protected: int4 indentlevel; ///< Current indent level (in fixed width characters) int4 parenlevel; ///< Current depth of parentheses int4 indentincrement; ///< Change in indentlevel per level of nesting + void resetDefaultsInternal(void) { indentincrement = 2; } ///< Set options to default values for EmitXml public: - EmitXml(void) { s = (ostream *)0; indentlevel=0; parenlevel=0; indentincrement=2; } ///< Constructor + EmitXml(void) { s = (ostream *)0; indentlevel=0; parenlevel=0; resetDefaultsInternal(); } ///< Constructor /// \brief Possible types of syntax highlighting enum syntax_highlight { @@ -196,6 +197,9 @@ public: /// \return \b true if \b this produces an XML markup of its emitted source code virtual bool emitsXml(void) const { return true; } + /// \brief (Re)set the default emitting options + virtual void resetDefaults(void); + /// \brief Get the current parentheses depth /// /// \return the current number of open parenthetical groups @@ -649,9 +653,11 @@ template void circularqueue<_type>::setMax(int4 sz) { - delete [] cache; - max = sz; - cache = new _type [ sz ]; + if (max != sz) { + delete [] cache; + max = sz; + cache = new _type [ sz ]; + } left = 1; // This operation empties queue right = 0; } @@ -721,8 +727,9 @@ class EmitPrettyPrint : public EmitXml { void print(const TokenSplit &tok); ///< Output the given token to the low-level emitter void advanceleft(void); ///< Emit tokens that have been fully committed void scan(void); ///< Process a new token + void resetDefaultsPrettyPrint(void) { setMaxLineSize(100); } public: - EmitPrettyPrint(int4 mls); ///< Construct with an initial maximum line size + EmitPrettyPrint(void); ///< Construct with an initial maximum line size virtual ~EmitPrettyPrint(void); virtual int4 beginDocument(void); virtual void endDocument(int4 id); @@ -768,6 +775,7 @@ public: virtual int4 getMaxLineSize(void) const { return maxlinesize; } virtual void setCommentFill(const string &fill) { commentfill = fill; } virtual bool emitsXml(void) const { return lowlevel->emitsXml(); } + virtual void resetDefaults(void); void setXML(bool val); ///< Toggle whether the low-level emitter emits XML markup or not }; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc index dbad39fe1e..535ca1d922 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc @@ -94,12 +94,6 @@ PrintLanguage *PrintCCapability::buildLanguage(Architecture *glb) PrintC::PrintC(Architecture *g,const string &nm) : PrintLanguage(g,nm) { - option_NULL = false; - option_inplace_ops = false; - option_convention = true; - option_nocasts = false; - option_unplaced = false; - option_hide_exts = true; nullToken = "NULL"; // Set the flip tokens @@ -111,7 +105,7 @@ PrintC::PrintC(Architecture *g,const string &nm) : PrintLanguage(g,nm) not_equal.negate = &equal; castStrategy = new CastStrategyC(); - setCStyleComments(); + resetDefaultsPrintC(); } /// Push nested components of a data-type declaration onto a stack, so we can access it bottom up @@ -1282,6 +1276,18 @@ bool PrintC::printCharacterConstant(ostream &s,const Address &addr,int4 charsize return res; } +void PrintC::resetDefaultsPrintC(void) + +{ + option_convention = true; + option_hide_exts = true; + option_inplace_ops = false; + option_nocasts = false; + option_NULL = false; + option_unplaced = false; + setCStyleComments(); +} + /// \brief Push a single character constant to the RPN stack /// /// For C, a character constant is usually emitted as the character in single quotes. @@ -1931,6 +1937,13 @@ void PrintC::emitGotoStatement(const FlowBlock *bl,const FlowBlock *exp_bl, emit->endStatement(id); } +void PrintC::resetDefaults(void) + +{ + PrintLanguage::resetDefaults(); + resetDefaultsPrintC(); +} + void PrintC::adjustTypeOperators(void) { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh index ebc15f0693..fd9a0aafc5 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh @@ -159,6 +159,7 @@ protected: void opHiddenFunc(const PcodeOp *op); ///< Push the given p-code op as a hidden token static bool hasCharTerminator(uint1 *buffer,int4 size,int4 charsize); bool printCharacterConstant(ostream &s,const Address &addr,int4 charsize) const; + void resetDefaultsPrintC(void); ///< Set default values for options specific to PrintC virtual void pushConstant(uintb val,const Datatype *ct, const Varnode *vn,const PcodeOp *op); virtual bool pushEquate(uintb val,int4 sz,const EquateSymbol *sym, @@ -200,6 +201,7 @@ public: void setDisplayUnplaced(bool val) { option_unplaced = val; } ///< Toggle whether \e unplaced comments are displayed in the header void setHideImpliedExts(bool val) { option_hide_exts = val; } ///< Toggle whether implied extensions are hidden virtual ~PrintC(void) {} + virtual void resetDefaults(void); virtual void adjustTypeOperators(void); virtual void setCommentStyle(const string &nm); virtual bool isCharacterConstant(const uint1 *buf,int4 size,int4 charsize) const; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc index b614c37595..151cdac141 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.cc @@ -61,13 +61,10 @@ PrintLanguage::PrintLanguage(Architecture *g,const string &nm) castStrategy = (CastStrategy *)0; name = nm; curscope = (Scope *)0; - emit = new EmitPrettyPrint(100); + emit = new EmitPrettyPrint(); - mods = 0; pending = 0; - line_commentindent = 20; - instr_comment_type = Comment::user2 | Comment::warning; - head_comment_type = Comment::header | Comment::warningheader; + resetDefaultsInternal(); } PrintLanguage::~PrintLanguage(void) @@ -692,6 +689,15 @@ void PrintLanguage::opUnary(const OpToken *tok,const PcodeOp *op) pushVnImplied(op->getIn(0),op,mods); } +void PrintLanguage::resetDefaultsInternal(void) + +{ + mods = 0; + head_comment_type = Comment::header | Comment::warningheader; + line_commentindent = 20; + instr_comment_type = Comment::user2 | Comment::warning; +} + /// The comment will get emitted as a single line using the high-level language's /// delimiters with the given indent level /// \param indent is the number of characters to indent @@ -767,6 +773,13 @@ void PrintLanguage::setFlat(bool val) mods &= ~flat; } +void PrintLanguage::resetDefaults(void) + +{ + emit->resetDefaults(); + resetDefaultsInternal(); +} + void PrintLanguage::clear(void) { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh index 5681ca1e69..412a4a5773 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printlanguage.hh @@ -275,6 +275,8 @@ protected: void opBinary(const OpToken *tok,const PcodeOp *op); ///< Push a binary operator onto the RPN stack void opUnary(const OpToken *tok,const PcodeOp *op); ///< Push a unary operator onto the RPN stack int4 getPending(void) const { return pending; } ///< Get the number of pending nodes yet to be put on the RPN stack + void resetDefaultsInternal(void); ///< Reset options to default for PrintLanguage + /// \brief Print a single unicode character as a \e character \e constant for the high-level language /// @@ -421,6 +423,7 @@ public: void setFlat(bool val); ///< Set whether nesting code structure should be emitted virtual void adjustTypeOperators(void)=0; ///< Set basic data-type information for p-code operators + virtual void resetDefaults(void); ///< Set printing options to their default value virtual void clear(void); ///< Clear the RPN stack and the low-level emitter virtual void setIntegerFormat(const string &nm); ///< Set the default integer format