/* * See the dyninst/COPYRIGHT file for copyright information. * * We provide the Paradyn Tools (below described as "Paradyn") * on an AS IS basis, and do not warrant its validity or performance. * We reserve the right to update, modify, or discontinue this * software at any time. We shall have no obligation to supply such * updates or modifications or any other form of support to you. * * By your use of Paradyn, you understand and agree that we (or any * other person or entity with proprietary rights in Paradyn) are * under no obligation to provide either maintenance services, * update services, notices of latent defects, or correction of * defects for Paradyn. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined(DEREFERENCE_H) #define DEREFERENCE_H #include "Operand.h" #include "Expression.h" #include "BinaryFunction.h" #include "Immediate.h" #include "Register.h" #include "Visitor.h" #include "ArchSpecificFormatters.h" #include #include namespace Dyninst { namespace InstructionAPI { using std::vector; /// A %Dereference object is a %Expression that dereferences another %ValueComputation. /// /// A %Dereference contains an %Expression representing an effective address computation. /// Its use set is the same as the use set of the /// %Expression being dereferenced. /// /// It is not possible, given the information in a single instruction, to evaluate /// the result of a dereference. \c eval may still be called on a %Expression /// that includes dereferences, but the expected use case is as follows: /// - Determine the address being used in a dereference via the \c eval mechanism /// - Perform analysis to determine the contents of that address /// - If necessary, fill in the %Dereference node with the contents of that addresss, using \c setValue /// /// The type associated with a %Dereference node will be the type of the value \em read \em from \em memory, /// not the type used for the address computation. Two %Dereferences that access the same address but interpret /// the contents of that memory as different types will produce different values. The children of a %Dereference at /// a given address are identical, regardless of the type of dereference being performed at that address. /// For example, the %Expression shown in Figure 6 could have its root %Dereference, which interprets the memory being dereferenced /// as a unsigned 16-bit integer, replaced with a %Dereference that /// interprets the memory being dereferenced as any other type. The remainder of the %Expression tree would, however, remain unchanged. class INSTRUCTION_EXPORT Dereference : public Expression { public: /// A %Dereference is constructed from a %Expression pointer (raw or shared) representing the address /// to be dereferenced and a type /// indicating how the memory at the address in question is to be interpreted. Dereference(Expression::Ptr addr, Result_Type result_type) : Expression(result_type), addressToDereference(addr) { } virtual ~Dereference() { } /// A %Dereference has one child, which represents the address being dereferenced. /// \param children Appends the child of this %Dereference to \c children. virtual void getChildren(vector& children) const { children.push_back(addressToDereference); return; } virtual void getChildren(vector& children) const { children.push_back(addressToDereference); return; } /// The use set of a %Dereference is the same as the use set of its children. /// \param uses The use set of this %Dereference is inserted into \c uses. virtual void getUses(set& uses) { addressToDereference->getUses(uses); return; } /// An %InstructionAST is used by a %Dereference if it is equivalent to the /// %Dereference or it is used by the lone child of the %Dereference virtual bool isUsed(InstructionAST::Ptr findMe) const { return addressToDereference->isUsed(findMe) || *findMe == *this; } virtual std::string format(formatStyle) const { std::string retVal; #if defined(DEBUG_MEMORY_ACCESS_WIDTH) switch(Expression::userSetValue.type) { case u8: retVal += "u8 @ "; break; case s8: retVal += "s8 @ "; break; case u16: retVal += "u16 @ "; break; case s16: retVal += "s16 @ "; break; case u32: retVal += "u32 @ "; break; case s32: retVal += "s32 @ "; break; case u64: retVal += "u64 @ "; break; case s64: retVal += "s64 @ "; break; case sp_float: retVal += "float @ "; break; case dp_float: retVal += "double @ "; break; case dbl128: retVal += "packed double @ "; break; default: retVal += "UNKNOWN SIZE @ "; break; } #endif retVal += "[" + addressToDereference->format() + "]"; return retVal; } virtual std::string format(Architecture arch, formatStyle) const { #if defined(DEBUG_MEMORY_ACCESS_WIDTH) switch(Expression::userSetValue.type) { case u8: retVal << "u8 @ "; break; case s8: retVal << "s8 @ "; break; case u16: retVal << "u16 @ "; break; case s16: retVal << "s16 @ "; break; case u32: retVal << "u32 @ "; break; case s32: retVal << "s32 @ "; break; case u64: retVal << "u64 @ "; break; case s64: retVal << "s64 @ "; break; case sp_float: retVal << "float @ "; break; case dp_float: retVal << "double @ "; break; case dbl128: retVal << "packed double @ "; break; default: retVal << "UNKNOWN SIZE @ "; break; } #endif #if 0 /* Which parts of the operand are available? */ if(list.base) std::cout << "\tBase: " << list.base << std::endl; if(list.offset) std::cout << "\tOffset: " << list.offset << std::endl; if(list.segment) std::cout << "\tSegment: " << list.segment << std::endl; if(list.scale) std::cout << "\tScale: " << list.scale << std::endl; if(list.displacement) std::cout << "\tDisplacement: " << list.displacement << std::endl; #endif return ArchSpecificFormatter::getFormatter(arch).formatDeref(addressToDereference->format(arch)); } virtual bool bind(Expression* expr, const Result& value) { if(Expression::bind(expr, value)) { return true; } return addressToDereference->bind(expr, value); } virtual void apply(Visitor* v) { addressToDereference->apply(v); v->visit(this); } protected: virtual bool isSameType(const InstructionAST& rhs) const { return dynamic_cast(&rhs) != NULL; } virtual bool isStrictEqual(const InstructionAST& rhs) const { const Dereference& other(dynamic_cast(rhs)); return *(other.addressToDereference) == *addressToDereference; } private: Expression::Ptr addressToDereference; }; } } #endif // !defined(DEREFERENCE_H)