diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc index 9116284df4..b6c7273a8b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc @@ -16,6 +16,7 @@ // Set up decompiler for specific architectures #include "coreaction.hh" +#include "flow.hh" #ifdef CPUI_RULECOMPILE #include "rulecompile.hh" #endif @@ -1253,7 +1254,8 @@ void Architecture::resetDefaultsInternal(void) 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; + flowoptions = FlowInfo::error_toomanyinstructions; + max_instructions = 100000; infer_pointers = true; readonlypropagate = false; alias_block_level = 2; // Block structs and arrays by default diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh index 87de413e95..065966282a 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh @@ -130,6 +130,7 @@ public: vector inferPtrSpaces; ///< Set of address spaces in which a pointer constant is inferable int4 funcptr_align; ///< How many bits of alignment a function ptr has uint4 flowoptions; ///< options passed to flow following engine + uint4 max_instructions; ///< Maximum instructions that can be processed in one function int4 alias_block_level; ///< Aliases blocked by 0=none, 1=struct, 2=array, 3=all vector extra_pool_rules; ///< Extra rules that go in the main pool (cpu specific, experimental) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc index 18d1e43e2d..0e340dd1bb 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc @@ -136,7 +136,7 @@ void Funcdata::startProcessing(void) warningHeader("This is an inlined function"); Address baddr(baseaddr.getSpace(),0); Address eaddr(baseaddr.getSpace(),~((uintb)0)); - followFlow(baddr,eaddr,0); + followFlow(baddr,eaddr); structureReset(); sortCallSpecs(); // Must come after structure reset heritage.buildInfoList(); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh index 37c802f9c8..5a173256a8 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.hh @@ -160,7 +160,7 @@ public: void startCleanUp(void) { clean_up_index = vbank.getCreateIndex(); } ///< Start \e clean-up phase uint4 getCleanUpIndex(void) const { return clean_up_index; } ///< Get creation index at the start of \b clean-up phase - void followFlow(const Address &baddr,const Address &eadddr,uint4 insn_max); + void followFlow(const Address &baddr,const Address &eadddr); void truncatedFlow(const Funcdata *fd,const FlowInfo *flow); bool inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop); void overrideFlow(const Address &addr,uint4 type); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc index 8ee82d6798..001e0a9309 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc @@ -700,12 +700,10 @@ void Funcdata::markIndirectCreation(PcodeOp *indop,bool possibleOutput) /// \brief Generate raw p-code for the function /// /// Follow flow from the entry point generating PcodeOps for each instruction encountered. -/// The caller can provide a bounding range that constrains where control can flow to -/// and can also provide a maximum number of instructions that will be followed. +/// The caller can provide a bounding range that constrains where control can flow to. /// \param baddr is the beginning of the constraining range /// \param eaddr is the end of the constraining range -/// \param insn_max is the maximum number of instructions to follow -void Funcdata::followFlow(const Address &baddr,const Address &eaddr,uint4 insn_max) +void Funcdata::followFlow(const Address &baddr,const Address &eaddr) { if (!obank.empty()) { @@ -719,8 +717,7 @@ void Funcdata::followFlow(const Address &baddr,const Address &eaddr,uint4 insn_m FlowInfo flow(*this,obank,bblocks,qlst); flow.setRange(baddr,eaddr); flow.setFlags(fl); - if (insn_max != 0) - flow.setMaximumInstructions(insn_max); + flow.setMaximumInstructions(glb->max_instructions); flow.generateOps(); size = flow.getSize(); // Cannot keep track of function sizes in general because of non-contiguous functions diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc index 8aaa776ee4..a37afdc4bd 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc @@ -360,10 +360,10 @@ static void IfcFollowFlow(ostream &s,IfaceDecompData *dcp,const Address &offset, if (size==0) { Address baddr(dcp->fd->getAddress().getSpace(),0); Address eaddr(dcp->fd->getAddress().getSpace(),dcp->fd->getAddress().getSpace()->getHighest()); - dcp->fd->followFlow(baddr,eaddr,0); + dcp->fd->followFlow(baddr,eaddr); } else - dcp->fd->followFlow(offset,offset+size,0); + dcp->fd->followFlow(offset,offset+size); s << "Function " << dcp->fd->getName() << ": "; dcp->fd->getAddress().printRaw(s); s << endl; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc index 0fde37bed8..32ea9769fa 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/options.cc @@ -80,6 +80,7 @@ OptionDatabase::OptionDatabase(Architecture *g) registerOption(new OptionJumpLoad()); registerOption(new OptionToggleRule()); registerOption(new OptionAliasBlock()); + registerOption(new OptionMaxInstruction()); } OptionDatabase::~OptionDatabase(void) @@ -816,3 +817,19 @@ string OptionAliasBlock::apply(Architecture *glb,const string &p1,const string & return "Alias block level unchanged"; return "Alias block level set to " + p1; } + +string OptionMaxInstruction::apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const + +{ + if (p1.size() == 0) + throw ParseError("Must specify number of instructions"); + + int4 newMax = -1; + istringstream s1(p1); + s1.unsetf(ios::dec | ios::hex | ios::oct); // Let user specify base + s1 >> newMax; + if (newMax < 0) + throw ParseError("Bad maxinstruction parameter"); + glb->max_instructions = newMax; + return "Maximum instructions per function set"; +} diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh index d9f0cf62f4..5cd7674407 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/options.hh @@ -264,4 +264,10 @@ public: virtual string apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const; }; +class OptionMaxInstruction : public ArchOption { +public: + OptionMaxInstruction(void) { name="maxinstruction"; } ///< Constructor + virtual string apply(Architecture *glb,const string &p1,const string &p2,const string &p3) const; +}; + #endif