diff --git a/Ghidra/Features/Decompiler/certification.manifest b/Ghidra/Features/Decompiler/certification.manifest index ccb91abf11..e3219bfa2b 100644 --- a/Ghidra/Features/Decompiler/certification.manifest +++ b/Ghidra/Features/Decompiler/certification.manifest @@ -43,6 +43,7 @@ src/decompile/datatests/impliedfield.xml||GHIDRA||||END| src/decompile/datatests/indproto.xml||GHIDRA||||END| src/decompile/datatests/injectoverride.xml||GHIDRA||||END| src/decompile/datatests/inline.xml||GHIDRA||||END| +src/decompile/datatests/inlinetarget.xml||GHIDRA||||END| src/decompile/datatests/longdouble.xml||GHIDRA||||END| src/decompile/datatests/loopcomment.xml||GHIDRA||||END| src/decompile/datatests/lzcount.xml||GHIDRA||||END| diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc index 61f484f738..bbe3028bf2 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc @@ -198,6 +198,19 @@ PcodeOp *FlowInfo::branchTarget(PcodeOp *op) const return target(addr); // Otherwise a normal address target } +/// Replace any reference to the op being inlined with the first op of the inlined sequence. +/// \param oldOp is the p-code op being inlined +/// \param newOp is the first p-code op in the inlined sequence +void FlowInfo::updateTarget(PcodeOp *oldOp,PcodeOp *newOp) + +{ + map
::iterator viter = visited.find(oldOp->getAddr()); + if (viter != visited.end()) { // Check if -oldOp- is a possible branch target + if ((*viter).second.seqnum == oldOp->getSeqNum()) // (if injection op is the first op for its address) + (*viter).second.seqnum = newOp->getSeqNum(); // change the seqnum to the newOp + } +} + /// Check to see if the new target has been seen before. Otherwise /// add it to the list of addresses that need to be processed. /// Also check range bounds and update basic block information. @@ -1189,11 +1202,7 @@ void FlowInfo::doInjection(InjectPayload *payload,InjectContext &icontext,PcodeO obank.markIncidentalCopy(firstop, lastop); obank.moveSequenceDead(firstop,lastop,op); // Move the injection to right after the call - map::iterator viter = visited.find(op->getAddr()); - if (viter != visited.end()) { // Check if -op- is a possible branch target - if ((*viter).second.seqnum == op->getSeqNum()) // (if injection op is the first op for its address) - (*viter).second.seqnum = firstop->getSeqNum(); // change the seqnum to the first injected op - } + updateTarget(op,firstop); // Replace -op- with -firstop- in the target map // Get rid of the original call data.opDestroyRaw(op); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.hh index 4bd5743b0c..8f7bd48c75 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.hh @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -148,6 +148,7 @@ public: void clearFlags(uint4 val) { flags &= ~val; } ///< Disable a specific option PcodeOp *target(const Address &addr) const; ///< Return first p-code op for instruction at given address PcodeOp *branchTarget(PcodeOp *op) const; ///< Find the target referred to by a given BRANCH or CBRANCH + void updateTarget(PcodeOp *oldOp,PcodeOp *newOp); ///< Update the branch target for an inlined p-code op void generateOps(void); ///< Generate raw control-flow from the function's base address void generateBlocks(void); ///< Generate basic blocks from the raw control-flow bool testHardInlineRestrictions(Funcdata *inlinefd,PcodeOp *op,Address &retaddr); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc index 24363d34b5..14ee7313ed 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc @@ -880,8 +880,10 @@ int4 Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop) --oiter; PcodeOp *lastop = *oiter; obank.moveSequenceDead(firstop,lastop,callop); // Move cloned sequence to right after callop - if (callop->isBlockStart()) + if (callop->isBlockStart()) { firstop->setFlag(PcodeOp::startbasic); // First op of inline inherits callop's startbasic flag + flow.updateTarget(callop, firstop); + } else firstop->clearFlag(PcodeOp::startbasic); } diff --git a/Ghidra/Features/Decompiler/src/decompile/datatests/inlinetarget.xml b/Ghidra/Features/Decompiler/src/decompile/datatests/inlinetarget.xml new file mode 100644 index 0000000000..7d0b71bc13 --- /dev/null +++ b/Ghidra/Features/Decompiler/src/decompile/datatests/inlinetarget.xml @@ -0,0 +1,35 @@ +