GP-5073 Fix for inlining infinite loop

This commit is contained in:
caheckman 2024-10-29 22:26:18 +00:00
parent aaa19420e9
commit dde9fed837
5 changed files with 95 additions and 27 deletions

View file

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

View file

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

View file

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