ROSE 0.11.145.147
Variables.h
1#ifndef ROSE_BinaryAnalysis_Variables_H
2#define ROSE_BinaryAnalysis_Variables_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5
6#include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics/BasicTypes.h>
7#include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics/MemoryCellState.h>
8#include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
9#include <Rose/BinaryAnalysis/SymbolicExpression.h>
10
11#include <Sawyer/IntervalMap.h>
12#include <Sawyer/Message.h>
13#include <Sawyer/Optional.h>
14#include <Sawyer/Set.h>
15
16#include <boost/serialization/access.hpp>
17#include <boost/serialization/split_member.hpp>
18
19#include <chrono>
20#include <map>
21#include <ostream>
22#include <set>
23#include <string>
24#include <vector>
25
26namespace Rose {
27namespace BinaryAnalysis {
28
30namespace Variables {
31
33// Basic types
35
38
40typedef std::map<int64_t /*offset*/, AddressSet> OffsetToAddresses;
41
43typedef std::map<rose_addr_t /*globalVa*/, AddressSet /*insns*/> AddressToAddresses;
44
47
49// Global variables
51
54
56// Global utilities
58
61
63std::string offsetStr(int64_t offset);
64
66std::string sizeStr(uint64_t size);
67
69// Base class for variable descriptors
71
74 rose_addr_t maxSizeBytes_ = 0; // maximum possible size of this variable in bytes
75 AddressSet insnVas_; // instructions where the variable was detected that reference the variable
77 std::string name_; // optional variable name
78
79#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
80private:
81 friend class boost::serialization::access;
82
83 template<class S>
84 void serialize(S &s, const unsigned /*version*/) {
85 s & BOOST_SERIALIZATION_NVP(maxSizeBytes_);
86 s & BOOST_SERIALIZATION_NVP(insnVas_);
87 s & BOOST_SERIALIZATION_NVP(ioProperties_);
88 s & BOOST_SERIALIZATION_NVP(name_);
89 }
90#endif
91
92protected:
97
99 BaseVariable(size_t maxSizeBytes, const AddressSet &definingInstructionVas, const std::string &name);
100
101public:
104
105public:
112 rose_addr_t maxSizeBytes() const;
113 void maxSizeBytes(rose_addr_t size);
143 const std::string& name() const;
144 void name(const std::string &s);
146};
147
149// Local variable descriptors
151
154public:
156 enum class Purpose {
159 SPILL_AREA,
160 NORMAL,
161 UNKNOWN,
162 OTHER
163 };
164
174
176 using Boundaries = std::vector<Boundary>;
177
178private:
179 Partitioner2::FunctionPtr function_; // function in which local variable exists
180 int64_t frameOffset_ = 0; // offset where variable is located in the function's stack frame
181 Purpose purpose_ = Purpose::UNKNOWN;
182
183#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
184private:
185 friend class boost::serialization::access;
186
187 template<class S>
188 void serialize(S &s, const unsigned version) {
189 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(BaseVariable);
190 s & BOOST_SERIALIZATION_NVP(function_);
191 s & BOOST_SERIALIZATION_NVP(frameOffset_);
192 if (version >= 1)
193 s & BOOST_SERIALIZATION_NVP(purpose_);
194 }
195#endif
196
197public:
202
205 const AddressSet &definingInstructionVas = AddressSet(), const std::string &name = "");
206
209
226 int64_t frameOffset() const;
227 void frameOffset(int64_t offset);
242 const std::string& setDefaultName();
243
250 bool operator==(const StackVariable &other) const;
251 bool operator!=(const StackVariable &other) const;
256
260 static Boundary& insertBoundary(Boundaries& /*in,out*/, int64_t frameOffset, rose_addr_t insnVa);
261
265 void print(std::ostream&) const;
266 std::string toString() const;
273 explicit operator bool() const {
274 return !interval().isEmpty();
275 }
276
280 bool operator!() const {
281 return interval().isEmpty();
282 }
283
285 friend std::ostream& operator<<(std::ostream&, const Rose::BinaryAnalysis::Variables::StackVariable&);
286};
287
290
295void print(const StackVariables&, const Partitioner2::PartitionerConstPtr&, std::ostream &out, const std::string &prefix = "");
296
298// Global variable descriptors
300
303 rose_addr_t address_ = 0; // starting (lowest) virtual address
304
305#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
306private:
307 friend class boost::serialization::access;
308
309 template<class S>
310 void serialize(S &s, const unsigned /*version*/) {
311 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(BaseVariable);
312 s & BOOST_SERIALIZATION_NVP(address_);
313 }
314#endif
315
316public:
321
327 GlobalVariable(rose_addr_t startingAddress, rose_addr_t maxSizeBytes,
328 const AddressSet &definingInstructionVas = AddressSet(), const std::string &name = "");
329
331
337 rose_addr_t address() const;
338 void address(rose_addr_t va);
344 const std::string& setDefaultName();
345
351 bool operator==(const GlobalVariable &other) const;
352 bool operator!=(const GlobalVariable &other) const;
357
361 void print(std::ostream&) const;
362 std::string toString() const;
369 explicit operator bool() const {
370 return !interval().isEmpty();
371 }
372
376 bool operator!() const {
377 return interval().isEmpty();
378 }
379
381 friend std::ostream& operator<<(std::ostream&, const Rose::BinaryAnalysis::Variables::GlobalVariable&);
382};
383
390
396void erase(GlobalVariables&, const AddressInterval &toErase);
397
402void print(const GlobalVariables&,const Partitioner2::PartitionerConstPtr&, std::ostream &out, const std::string &prefix = "");
403
413
415// StackFrame
417
455
457// Analyzer
459
462public:
464 struct Settings {
466 std::chrono::seconds gvarMethod1MaxTimePerFunction;
467
468 Settings()
470 };
471
474
475private:
476 Settings settings_;
477
478protected:
479 explicit VariableFinder(const Settings&);
480public:
482
483public:
486
490 const Settings& settings() const { return settings_; }
491 Settings& settings() { return settings_; }
528
544
547
555 StackVariable::Boundaries &boundaries /*in,out*/);
556
557#if 0 // [Robb Matzke 2021-10-27]
563 OffsetInterval referencedFrameArea(const Partitioner2::Partitioner&,
565 const SymbolicExpression::Ptr &address, size_t nBytes);
566#endif
567
573
579
616
620 std::set<rose_addr_t> findConstants(const SymbolicExpression::Ptr&);
621
623 std::set<rose_addr_t> findConstants(SgAsmInstruction*);
624
629
634
635#if 0 // [Robb Matzke 2021-10-27]
639 InstructionSemantics::BaseSemantics::SValuePtr
640 symbolicAddress(const Partitioner2::Partitioner&, const StackVariable&,
642#endif
643
652 StackVariable::Boundaries &sortedBoundaries /*in,out*/);
653
656
659
662
663private:
664 // Searches for global variables using a per-function data-flow analysis and distinguishing between global variable
665 // addresses based on which instructions wrote to those addresses. The data-flow is inter-procedural only for calls to
666 // certain functions (such as the x86 get_pc_thunk variety of functions).
667 //
668 // The return value is a list of global variable addresses and the instructions at which each global variable address
669 // was detected.
670 AddressToAddresses findGlobalVariableVasMethod1(const Partitioner2::PartitionerConstPtr&);
671
672 // Searches for global variables by running each instruction individually in symbolic semantics and then searching
673 // the memory state addresses. All constants found in address expressions are gathered together.
674 //
675 // The return value is a list of global variable addresses and the instructions at which each global address was detected.
676 AddressToAddresses findGlobalVariableVasMethod2(const Partitioner2::PartitionerConstPtr&);
677
678 // Searches for global variables by looking for constants in instruction ASTs.
679 //
680 // The retun value is the list of constants and the instructions in which each constant appeared.
681 AddressToAddresses findGlobalVariableVasMethod3(const Partitioner2::PartitionerConstPtr&);
682
683 // Merge one set of addresses and their defining instructions into another.
684 static void merge(AddressToAddresses&, const AddressToAddresses&);
685};
686
687} // namespace
688} // namespace
689} // namespace
690
691// Class versions must be at global scope
693
694#endif
695#endif
Partitions instructions into basic blocks and functions.
Describes (part of) a physical CPU register.
Describes a local or global variable.
Definition Variables.h:73
AddressSet & definingInstructionVas()
Property: Addresses of instructions related to this variable.
void maxSizeBytes(rose_addr_t size)
Property: Maximum variable size in bytes.
InstructionSemantics::BaseSemantics::InputOutputPropertySet & ioProperties()
Property: I/O properties.
BaseVariable(size_t maxSizeBytes, const AddressSet &definingInstructionVas, const std::string &name)
Construct a variable with a given maximum size.
void ioProperties(const InstructionSemantics::BaseSemantics::InputOutputPropertySet &set)
Property: I/O properties.
void name(const std::string &s)
Property: Optional variable name.
rose_addr_t maxSizeBytes() const
Property: Maximum variable size in bytes.
const AddressSet & definingInstructionVas() const
Property: Addresses of instructions related to this variable.
const InstructionSemantics::BaseSemantics::InputOutputPropertySet & ioProperties() const
Property: I/O properties.
void definingInstructionVas(const AddressSet &vas)
Property: Addresses of instructions related to this variable.
const std::string & name() const
Property: Optional variable name.
Description of a global variable.
Definition Variables.h:302
bool operator!=(const GlobalVariable &other) const
Compare two global variable descriptors.
GlobalVariable(rose_addr_t startingAddress, rose_addr_t maxSizeBytes, const AddressSet &definingInstructionVas=AddressSet(), const std::string &name="")
Constructor.
bool operator==(const GlobalVariable &other) const
Compare two global variable descriptors.
std::string toString() const
Printing global variable.
const std::string & setDefaultName()
Give variable a defult name.
void address(rose_addr_t va)
Property: Starting address.
AddressInterval interval() const
Location of variable in memory.
bool operator!() const
Predicate to test whether variable is invalid.
Definition Variables.h:376
void print(std::ostream &) const
Printing global variable.
friend std::ostream & operator<<(std::ostream &, const Rose::BinaryAnalysis::Variables::GlobalVariable &)
Print global variable descriptor.
rose_addr_t address() const
Property: Starting address.
Information about a stack frame.
Definition Variables.h:441
Sawyer::Optional< int64_t > maxOffset
Maximum frame offset w.r.t.
Definition Variables.h:450
RegisterDescriptor framePointerRegister
Optional descriptor for register pointing to latest frame.
Definition Variables.h:449
Sawyer::Optional< uint64_t > size
Size of the frame in bytes if known.
Definition Variables.h:452
Sawyer::Optional< int64_t > minOffset
Minimum frame offset w.r.t.
Definition Variables.h:451
std::string rule
Informal rule name used to detect frame characteristics.
Definition Variables.h:453
@ GROWS_UP
New frames are added at higher addresses than old frames.
Definition Variables.h:444
@ GROWS_DOWN
New frames are added at lower addresses than old frames.
Definition Variables.h:445
Direction growthDirection
Direction that the stack grows when pushing a new frame.
Definition Variables.h:448
Description of a local stack variable within a function.
Definition Variables.h:153
std::string toString() const
Printing local variable.
OffsetInterval interval() const
Location within the function stack frame.
const std::string & setDefaultName()
Give variable a defult name.
friend std::ostream & operator<<(std::ostream &, const Rose::BinaryAnalysis::Variables::StackVariable &)
Print local variable descriptor.
bool operator==(const StackVariable &other) const
Compare two local variables.
bool operator!=(const StackVariable &other) const
Compare two local variables.
static Boundary & insertBoundary(Boundaries &, int64_t frameOffset, rose_addr_t insnVa)
Insert a new boundary or adjust an existing boundary.
std::vector< Boundary > Boundaries
List of boundaries.
Definition Variables.h:176
Purpose purpose() const
Property: Purpose.
void print(std::ostream &) const
Printing local variable.
@ NORMAL
Normal source code level variable.
@ RETURN_ADDRESS
Possible or known return address.
@ FRAME_POINTER
Pointer to previous stack frame.
void frameOffset(int64_t offset)
Property: Frame offset.
StackVariable(const Partitioner2::FunctionPtr &, int64_t frameOffset, rose_addr_t maxSizeBytes, Purpose, const AddressSet &definingInstructionVas=AddressSet(), const std::string &name="")
Construct a variable descriptor.
void purpose(Purpose p)
Property: Purpose.
void function(const Partitioner2::FunctionPtr &)
Property: Function owning the variable.
int64_t frameOffset() const
Property: Frame offset.
bool operator!() const
Predicate to test whether variable is invalid.
Definition Variables.h:280
Partitioner2::FunctionPtr function() const
Property: Function owning the variable.
Analysis to find variable locations.
Definition Variables.h:461
static bool regionIsFullyReadWrite(const Partitioner2::PartitionerConstPtr &, const AddressInterval &)
True if memory region is fully mapped with read and write access.
std::set< rose_addr_t > findAddressConstants(const InstructionSemantics::BaseSemantics::MemoryCellStatePtr &)
Find constants in memory.
StackFrame detectFrameAttributes(const Partitioner2::PartitionerConstPtr &, const Partitioner2::FunctionPtr &)
Figure out attributes describing the stack frame for the specified function.
std::set< int64_t > findFrameOffsets(const StackFrame &, const Partitioner2::PartitionerConstPtr &, SgAsmInstruction *)
Find stack variable addresses.
void evict(const Partitioner2::PartitionerConstPtr &)
Removed cached information.
void removeOutliers(const StackFrame &, const Partitioner2::PartitionerConstPtr &, const Partitioner2::FunctionPtr &, StackVariable::Boundaries &sortedBoundaries)
Remove boundaries that are outside a stack frame.
StackVariables findStackVariables(const Partitioner2::PartitionerConstPtr &, SgAsmInstruction *)
Find local variables in a function.
const Settings & settings() const
Settings for this analysis.
Definition Variables.h:490
Settings & settings()
Settings for this analysis.
Definition Variables.h:491
void initializeFrameBoundaries(const StackFrame &, const Partitioner2::PartitionerConstPtr &, const Partitioner2::FunctionPtr &, StackVariable::Boundaries &boundaries)
Initilialize offsets for function prologue.
std::set< SymbolicExpression::Ptr > getMemoryAddresses(const InstructionSemantics::BaseSemantics::MemoryCellStatePtr &)
Find addresses in memory state.
static Ptr instance(const Settings &settings=Settings())
Allocating constructor.
static bool regionContainsInstructions(const Partitioner2::PartitionerConstPtr &, const AddressInterval &)
True if memory region contains any decoded instructions.
GlobalVariables findGlobalVariables(const Partitioner2::PartitionerConstPtr &)
Find global variables.
std::set< rose_addr_t > findConstants(SgAsmInstruction *)
Find constants syntactically in an instruction.
bool isCached(const Partitioner2::FunctionPtr &)
Test whether local variable information is cached.
void evict(const Partitioner2::FunctionPtr &)
Removed cached information.
std::set< rose_addr_t > findConstants(const SymbolicExpression::Ptr &)
Find address constants in an expression.
StackVariables findStackVariables(const Partitioner2::PartitionerConstPtr &, const Partitioner2::FunctionPtr &)
Find local variables in a function.
AddressToAddresses findGlobalVariableVas(const Partitioner2::PartitionerConstPtr &)
Find global variable addresses.
Partitioner2::FunctionPtr functionForInstruction(const Partitioner2::PartitionerConstPtr &, SgAsmInstruction *)
Function that owns an instruction.
static bool regionIsFullyMapped(const Partitioner2::PartitionerConstPtr &, const AddressInterval &)
True if memory region is fully mapped.
Range of values delimited by endpoints.
Definition Interval.h:31
bool isEmpty() const
True if interval is empty.
Definition Interval.h:230
Ordered set of values.
Definition Set.h:56
Collection of streams.
Definition Message.h:1606
Converts text to messages.
Definition Message.h:1396
Holds a value or nothing.
Definition Optional.h:56
Base class for reference counted objects.
Base class for machine instructions.
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
boost::shared_ptr< class MemoryCellState > MemoryCellStatePtr
Shared-ownership pointer to a cell-based memory state.
Sawyer::Container::Set< rose_addr_t > AddressSet
Set of addresses.
Definition Variables.h:37
void initDiagnostics()
Initialize diagnostic output.
std::map< rose_addr_t, AddressSet > AddressToAddresses
Mapping from addresses to address sets.
Definition Variables.h:43
std::string offsetStr(int64_t offset)
Format a stack offset as a string.
Sawyer::Container::IntervalMap< AddressInterval, GlobalVariable > GlobalVariables
Maps virtual addresses to global variables.
Definition Variables.h:389
std::map< int64_t, AddressSet > OffsetToAddresses
Mapping from stack offsets to address sets.
Definition Variables.h:40
void print(const StackVariables &, const Partitioner2::PartitionerConstPtr &, std::ostream &out, const std::string &prefix="")
Print info about multiple local variables.
void erase(GlobalVariables &, const AddressInterval &toErase)
Erase some global variables.
Sawyer::Message::Facility mlog
Diagnostic facility.
std::string sizeStr(uint64_t size)
Format size as a string.
Sawyer::SharedPointer< VariableFinder > VariableFinderPtr
Reference counting pointer.
AddressInterval isInconsistent(const GlobalVariables &, Sawyer::Message::Stream &)
Check that the map is consistent.
Sawyer::Container::Interval< int64_t > OffsetInterval
Interval of signed offsets.
Definition Variables.h:46
The ROSE library.
Purpose purpose
Purpose of addresses above this boundary.
Definition Variables.h:172
int64_t frameOffset
Address of boundary with respect to frame pointer.
Definition Variables.h:170
AddressSet definingInsns
Instructions that define this boundary.
Definition Variables.h:171
std::chrono::seconds gvarMethod1MaxTimePerFunction
Max time to spend in Method 1 global variable analysis per function.
Definition Variables.h:466