New resetDefaults support

This commit is contained in:
caheckman 2020-03-27 15:03:24 -04:00
parent 791f16101e
commit d9bd93c36b
12 changed files with 147 additions and 50 deletions

View file

@ -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<string,Action *>::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);
}

View file

@ -296,14 +296,16 @@ class ActionDatabase {
string currentactname; ///< The name associated with the current root Action
map<string,ActionGroupList> groupmap; ///< Map from root Action name to the grouplist it uses
map<string,Action *> 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

View file

@ -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;i<printlist.size();++i)
printlist[i]->resetDefaults();
}
Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point,uintb &fullEncoding)
{

View file

@ -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?

View file

@ -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<Rule *>::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"));

View file

@ -433,6 +433,7 @@ void SetOptions::rawAction(void)
{
res = false;
ghidra->resetDefaults();
ghidra->options->restoreXml(doc->getRoot());
delete doc;
doc = (Document *)0;

View file

@ -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();
}

View file

@ -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<typename _type>
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
};

View file

@ -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)
{

View file

@ -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;

View file

@ -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)
{

View file

@ -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