From 48f4c0b040456b99c3de84685657bed1d4a0f390 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Thu, 11 Jun 2026 20:53:01 +0000 Subject: [PATCH] GP-6957 Relative branch to next instruction is more flexible --- .../Decompiler/src/decompile/cpp/flow.cc | 9 ++++----- .../Features/Decompiler/src/decompile/cpp/op.cc | 16 ++++++++++++++++ .../Features/Decompiler/src/decompile/cpp/op.hh | 1 + 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc index 0add3cc173..16432f6d03 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc @@ -156,11 +156,10 @@ PcodeOp *FlowInfo::findRelTarget(PcodeOp *op,Address &res) const if (retop != (PcodeOp *)0) // Is this a "properly" internal branch return retop; - // Now we check if the relative branch is really to the next instruction - SeqNum seqnum1(op->getAddr(),id-1); - retop = obank.findOp(seqnum1); // We go back one sequence number - if (retop != (PcodeOp *)0) { - // If the PcodeOp exists here then branch was indeed to next instruction + // Check if the relative branch is to the next instruction + retop = obank.findLastOp(op->getAddr()); // Find the last op at this address + if (retop != (PcodeOp *)0 && retop->getTime() < id) { + // Branch is beyond the last op. Treat as branch to next instruction. map
::const_iterator miter; miter = visited.upper_bound(retop->getAddr()); if (miter != visited.begin()) { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc index dbd6ccbc3c..f1dd827b19 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/op.cc @@ -1134,6 +1134,22 @@ PcodeOp *PcodeOpBank::findOp(const SeqNum &num) const return (*iter).second; } +/// If PcodeOps exist at the address, the one with the biggest getTime() is returned. +/// \param addr is the given address +/// \return the last PcodeOp at the address (or NULL) +PcodeOp *PcodeOpBank::findLastOp(const Address &addr) const + +{ + PcodeOpTree::const_iterator iter = optree.upper_bound(SeqNum(addr,~((uintm)0))); + if (iter != optree.begin()) { + --iter; + PcodeOp *op = (*iter).second; + if (op->getAddr() == addr) + return op; + } + return (PcodeOp *)0; +} + /// The term \e fallthru in this context refers to p-code \e not assembly instructions. /// \param op is the given PcodeOp /// \return the fallthru PcodeOp diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh index c5735b1bdb..a6a793d868 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/op.hh @@ -321,6 +321,7 @@ public: bool empty(void) const { return optree.empty(); } ///< Return \b true if there are no PcodeOps in \b this container PcodeOp *target(const Address &addr) const; ///< Find the first executing PcodeOp for a target address PcodeOp *findOp(const SeqNum &num) const; ///< Find a PcodeOp by sequence number + PcodeOp *findLastOp(const Address &addr) const; ///< Find the last PcodeOp in sequence for the given address PcodeOp *fallthru(const PcodeOp *op) const; ///< Find the PcodeOp considered a \e fallthru of the given PcodeOp /// \brief Start of all PcodeOps in sequence number order