From 4eef52216dbce2bc8cf001baa5cb0346ed081caf Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:53:40 +0000 Subject: [PATCH] GP-4960 Recursively walk implied Varnodes when building a Cover --- .../src/decompile/cpp/coreaction.cc | 12 ++------ .../Decompiler/src/decompile/cpp/cover.cc | 21 +++++++++---- .../Decompiler/src/decompile/cpp/merge.cc | 30 +++++++++---------- .../Decompiler/src/decompile/cpp/merge.hh | 6 ++-- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 2f2106dfcf..f4102c19c1 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -3402,8 +3402,7 @@ int4 ActionMarkImplied::apply(Funcdata &data) { VarnodeLocSet::const_iterator viter; list::const_iterator oiter; - Varnode *vn,*vncur,*defvn,*outvn; - PcodeOp *op; + Varnode *vn,*vncur,*outvn; vector varstack; // Depth first varnode traversal stack for(viter=data.beginLoc();viter!=data.endLoc();++viter) { @@ -3420,16 +3419,9 @@ int4 ActionMarkImplied::apply(Funcdata &data) if (!checkImpliedCover(data,vncur)) // Can this variable be implied vncur->setExplicit(); // if not, mark explicit else { - vncur->setImplied(); // Mark as implied - op = vncur->getDef(); + Merge::markImplied(vncur); // setting the implied type is now taken care of by ActionSetCasts // vn->updatetype(op->outputtype_token(),false,false); // implied must have parsed type - // Back propagate varnode's cover to inputs of defining op - for(int4 i=0;inumInput();++i) { - defvn = op->getIn(i); - if (!defvn->hasCover()) continue; - data.getMerge().inflate(defvn,vncur->getHigh()); - } } varstack.pop_back(); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/cover.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/cover.cc index 4ebca11bac..cfaed4e241 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/cover.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/cover.cc @@ -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. @@ -477,11 +477,22 @@ void Cover::merge(const Cover &op2) void Cover::rebuild(const Varnode *vn) { - list::const_iterator iter; + vector path(1,vn); + int4 pos = 0; addDefPoint(vn); - for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) - addRefPoint(*iter,vn); + do { + const Varnode *curVn = path[pos]; + pos += 1; + list::const_iterator iter; + for(iter=curVn->beginDescend();iter!=curVn->endDescend();++iter) { + const PcodeOp *op = *iter; + addRefPoint(op,vn); + const Varnode *outVn = op->getOut(); + if (outVn != (Varnode *)0 && outVn->isImplied()) + path.push_back(outVn); + } + } while(pos < path.size()); } /// Any previous cover is removed. Calling this with an diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/merge.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/merge.cc index e415365db1..4629d38155 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/merge.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/merge.cc @@ -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. @@ -1586,24 +1586,22 @@ void Merge::clear(void) stackAffectingOps.clear(); } -/// \brief Inflate the Cover of a given Varnode with a HighVariable +/// \brief Mark the given Varnode as \e implied /// -/// An expression involving a HighVariable can be propagated to all the read sites of the -/// output Varnode of the expression if the Varnode Cover can be \b inflated to include the -/// Cover of the HighVariable, even though the Varnode is not part of the HighVariable. -/// This routine performs the inflation, assuming an intersection test is already performed. -/// \param a is the given Varnode to inflate -/// \param high is the HighVariable to inflate with -void Merge::inflate(Varnode *a,HighVariable *high) +/// The covers of the immediate Varnodes involved in the expression are marked as dirty. +/// This assumes covers for the whole expression are ultimately marked because all its internal Varnodes +/// are passed to this method. +/// \param vn is the given Varnode being marked as \e implied +void Merge::markImplied(Varnode *vn) { - testCache.updateHigh(a->getHigh()); - testCache.updateHigh(high); - for(int4 i=0;inumInstances();++i) { - Varnode *b = high->getInstance(i); - a->cover->merge(*b->cover); + vn->setImplied(); // Mark as implied + PcodeOp *op = vn->getDef(); + for(int4 i=0;inumInput();++i) { + Varnode *defvn = op->getIn(i); + if (!defvn->hasCover()) continue; + defvn->setFlags(Varnode::coverdirty); } - a->getHigh()->coverDirty(); } /// \brief Test if we can inflate the Cover of the given Varnode without incurring intersections diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/merge.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/merge.hh index 9e115edd37..047a0a7845 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/merge.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/merge.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. @@ -117,8 +117,8 @@ class Merge { public: Merge(Funcdata &fd) : data(fd), stackAffectingOps(fd), testCache(stackAffectingOps) {} ///< Construct given a specific function void clear(void); + static void markImplied(Varnode *vn); bool inflateTest(Varnode *a,HighVariable *high); - void inflate(Varnode *a,HighVariable *high); bool mergeTest(HighVariable *high,vector &tmplist); void mergeOpcode(OpCode opc);