mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-5073 Fix for inlining infinite loop
This commit is contained in:
parent
aaa19420e9
commit
dde9fed837
5 changed files with 95 additions and 27 deletions
|
@ -1120,12 +1120,6 @@ void FlowInfo::inlineEZClone(const FlowInfo &inlineflow,const Address &calladdr)
|
|||
bool FlowInfo::testHardInlineRestrictions(Funcdata *inlinefd,PcodeOp *op,Address &retaddr)
|
||||
|
||||
{
|
||||
if (inline_recursion->find( inlinefd->getAddress() ) != inline_recursion->end()) {
|
||||
// This function has already been included with current inlining
|
||||
inline_head->warning("Could not inline here",op->getAddr());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!inlinefd->getFuncProto().isNoReturn()) {
|
||||
list<PcodeOp *>::iterator iter = op->getInsertIter();
|
||||
++iter;
|
||||
|
@ -1142,8 +1136,6 @@ bool FlowInfo::testHardInlineRestrictions(Funcdata *inlinefd,PcodeOp *op,Address
|
|||
// If the inlining "jumps back" this starts a new basic block
|
||||
data.opMarkStartBasic(nextop);
|
||||
}
|
||||
|
||||
inline_recursion->insert(inlinefd->getAddress());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1243,11 +1235,31 @@ bool FlowInfo::inlineSubFunction(FuncCallSpecs *fc)
|
|||
{
|
||||
Funcdata *fd = fc->getFuncdata();
|
||||
if (fd == (Funcdata *)0) return false;
|
||||
PcodeOp *op = fc->getOp();
|
||||
Address retaddr;
|
||||
|
||||
if (!data.inlineFlow( fd, *this, op))
|
||||
if (inline_head == (Funcdata *)0) {
|
||||
// This is the top level of inlining
|
||||
inline_head = &data; // Set up head of inlining
|
||||
inline_recursion = &inline_base;
|
||||
}
|
||||
inline_recursion->insert(data.getAddress()); // Insert current function
|
||||
if (inline_recursion->find( fd->getAddress() ) != inline_recursion->end()) {
|
||||
// This function has already been included with current inlining
|
||||
inline_head->warning("Could not inline here",fc->getOp()->getAddr());
|
||||
return false;
|
||||
}
|
||||
|
||||
int4 res = data.inlineFlow( fd, *this, fc->getOp());
|
||||
if (res < 0)
|
||||
return false;
|
||||
else if (res == 0) { // easy model
|
||||
// Remove inlined function from list so it can be inlined again, even if it also inlines
|
||||
inline_recursion->erase(fd->getAddress());
|
||||
}
|
||||
else if (res == 1) { // hard model
|
||||
// Add inlined function to recursion list, even if it contains no inlined calls,
|
||||
// to prevent parent from inlining it twice
|
||||
inline_recursion->insert(fd->getAddress());
|
||||
}
|
||||
|
||||
// Changing CALL to JUMP may make some original code unreachable
|
||||
setPossibleUnreachable();
|
||||
|
@ -1306,17 +1318,6 @@ void FlowInfo::deleteCallSpec(FuncCallSpecs *fc)
|
|||
void FlowInfo::injectPcode(void)
|
||||
|
||||
{
|
||||
if (inline_head == (Funcdata *)0) {
|
||||
// This is the top level of inlining
|
||||
inline_head = &data; // Set up head of inlining
|
||||
inline_recursion = &inline_base;
|
||||
inline_recursion->insert(data.getAddress()); // Insert ourselves
|
||||
// inline_head = (Funcdata *)0;
|
||||
}
|
||||
else {
|
||||
inline_recursion->insert(data.getAddress()); // Insert ourselves
|
||||
}
|
||||
|
||||
for(int4 i=0;i<injectlist.size();++i) {
|
||||
PcodeOp *op = injectlist[i];
|
||||
if (op == (PcodeOp *)0) continue;
|
||||
|
|
|
@ -192,7 +192,7 @@ public:
|
|||
|
||||
void followFlow(const Address &baddr,const Address &eadddr);
|
||||
void truncatedFlow(const Funcdata *fd,const FlowInfo *flow);
|
||||
bool inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop);
|
||||
int4 inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop);
|
||||
void overrideFlow(const Address &addr,uint4 type);
|
||||
void doLiveInject(InjectPayload *payload,const Address &addr,BlockBasic *bl,list<PcodeOp *>::iterator pos);
|
||||
|
||||
|
|
|
@ -804,8 +804,8 @@ void Funcdata::truncatedFlow(const Funcdata *fd,const FlowInfo *flow)
|
|||
/// \param inlinefd is the function to in-line
|
||||
/// \param flow is the flow object being injected
|
||||
/// \param callop is the site of the injection
|
||||
/// \return \b true if the injection was successful
|
||||
bool Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop)
|
||||
/// \return 0 for a successful inlining with the easy model, 1 for the hard model, -1 if inlining was not successful
|
||||
int4 Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop)
|
||||
|
||||
{
|
||||
inlinefd->getArch()->clearAnalysis(inlinefd);
|
||||
|
@ -821,7 +821,9 @@ bool Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop)
|
|||
inlineflow.forwardRecursion(flow);
|
||||
inlineflow.generateOps();
|
||||
|
||||
int4 res;
|
||||
if (inlineflow.checkEZModel()) {
|
||||
res = 0;
|
||||
// With an EZ clone there are no jumptables to clone
|
||||
list<PcodeOp *>::const_iterator oiter = obank.endDead();
|
||||
--oiter; // There is at least one op
|
||||
|
@ -843,7 +845,8 @@ bool Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop)
|
|||
else {
|
||||
Address retaddr;
|
||||
if (!flow.testHardInlineRestrictions(inlinefd,callop,retaddr))
|
||||
return false;
|
||||
return -1;
|
||||
res = 1;
|
||||
vector<JumpTable *>::const_iterator jiter; // Clone any jumptables from inline piece
|
||||
for(jiter=inlinefd->jumpvec.begin();jiter!=inlinefd->jumpvec.end();++jiter) {
|
||||
JumpTable *jtclone = new JumpTable(*jiter);
|
||||
|
@ -862,7 +865,7 @@ bool Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop)
|
|||
|
||||
obank.setUniqId( inlinefd->obank.getUniqId() );
|
||||
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Find the primary branch operation for an instruction
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue