ROSE  0.11.145.0
CallingConvention.h
1 #ifndef ROSE_BinaryAnalysis_CallingConvention_H
2 #define ROSE_BinaryAnalysis_CallingConvention_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
5 
6 #include <Rose/BinaryAnalysis/BasicTypes.h>
7 #include <Rose/BinaryAnalysis/ConcreteLocation.h>
8 #include <Rose/BinaryAnalysis/Disassembler/BasicTypes.h>
9 #include <Rose/BinaryAnalysis/InstructionSemantics/BaseSemantics.h>
10 #include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
11 #include <Rose/BinaryAnalysis/RegisterParts.h>
12 #include <Rose/BinaryAnalysis/Variables.h>
13 
14 #include <boost/serialization/access.hpp>
15 #include <boost/serialization/set.hpp>
16 #include <boost/serialization/string.hpp>
17 #include <boost/serialization/vector.hpp>
18 #include <boost/serialization/version.hpp>
19 #include <Sawyer/SharedObject.h>
20 #include <Sawyer/SharedPointer.h>
21 
22 // Clean up global namespace pollution
23 #undef ABSOLUTE
24 
25 namespace Rose {
26 namespace BinaryAnalysis {
27 
28 // Forwards
29 namespace Disassembler {
30 class Base;
31 } // namespace
32 
43 namespace CallingConvention {
44 
48 void initDiagnostics();
49 
54 
56 // Miscellaneous small types
58 
60 enum class StackParameterOrder {
63  UNSPECIFIED,
64 };
65 
67 enum class StackDirection {
68  GROWS_UP,
69  GROWS_DOWN,
70 };
71 
73 enum class StackCleanup {
74  BY_CALLER,
75  BY_CALLEE,
76  UNSPECIFIED,
77 };
78 
80 // Definition
82 
87 public:
89  using Ptr = DefinitionPtr;
90 
91 private:
92  std::string name_; // Official short name of the convention, like "stdcall".
93  std::string comment_; // Long name, like "Windows Borland x86-32 fastcall"
94  size_t wordWidth_ = 0; // Natural width word size in bits
95  RegisterDictionaryPtr regDict_; // Register dictionary used when this definition was created
96  std::vector<ConcreteLocation> nonParameterInputs_; // Inputs that are not considered normal function parameters
97  std::vector<ConcreteLocation> inputParameters_; // Input (inc. in-out) parameters; additional stack-based are implied
98  std::vector<ConcreteLocation> outputParameters_; // Return values and output parameters.
99  StackParameterOrder stackParameterOrder_ = StackParameterOrder::UNSPECIFIED; // Order of arguments on the stack
100  RegisterDescriptor stackPointerRegister_; // Base pointer for implied stack parameters
101  size_t nonParameterStackSize_ = 0; // Size in bytes of non-parameter stack area
102  size_t stackAlignment_ = 0; // Stack alignment in bytes (zero means unknown)
103  StackDirection stackDirection_ = StackDirection::GROWS_DOWN; // Direction that stack grows from a PUSH operation
104  StackCleanup stackCleanup_ = StackCleanup::UNSPECIFIED; // Who cleans up stack parameters?
105  ConcreteLocation thisParameter_; // Object pointer for calling conventions that are object methods
106  std::set<RegisterDescriptor> calleeSavedRegisters_; // Register that the callee must restore before returning
107  std::set<RegisterDescriptor> scratchRegisters_; // Caller-saved registers
108  ConcreteLocation returnAddressLocation_; // Where is the function return address stored at function entry?
109  RegisterDescriptor instructionPointerRegister_; // Where is the next instruction address stored?
110 
111 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
112 private:
113  friend class boost::serialization::access;
114 
115  template<class S>
116  void serialize(S &s, const unsigned version) {
117  s & BOOST_SERIALIZATION_NVP(name_);
118  s & BOOST_SERIALIZATION_NVP(comment_);
119  s & BOOST_SERIALIZATION_NVP(wordWidth_);
120  s & BOOST_SERIALIZATION_NVP(regDict_);
121  s & BOOST_SERIALIZATION_NVP(inputParameters_);
122  s & BOOST_SERIALIZATION_NVP(outputParameters_);
123  s & BOOST_SERIALIZATION_NVP(stackParameterOrder_);
124  s & BOOST_SERIALIZATION_NVP(stackPointerRegister_);
125  s & BOOST_SERIALIZATION_NVP(nonParameterStackSize_);
126  s & BOOST_SERIALIZATION_NVP(stackAlignment_);
127  s & BOOST_SERIALIZATION_NVP(stackDirection_);
128  s & BOOST_SERIALIZATION_NVP(stackCleanup_);
129  s & BOOST_SERIALIZATION_NVP(thisParameter_);
130  s & BOOST_SERIALIZATION_NVP(calleeSavedRegisters_);
131  s & BOOST_SERIALIZATION_NVP(scratchRegisters_);
132  if (version >= 1) {
133  s & BOOST_SERIALIZATION_NVP(returnAddressLocation_);
134  s & BOOST_SERIALIZATION_NVP(instructionPointerRegister_);
135  }
136  }
137 #endif
138 
139 protected:
143  Definition();
144 
150  Definition(size_t wordWidth, const std::string &name, const std::string &comment, const RegisterDictionaryPtr&);
151 
152 public:
153  ~Definition();
154 
155 public:
157  static Ptr instance(size_t wordWidth, const std::string &name, const std::string &comment, const RegisterDictionaryPtr &regs) {
158  return Ptr(new Definition(wordWidth, name, comment, regs));
159  }
160 
161 public:
165  static Ptr x86_32bit_cdecl();
166  static Ptr x86_64bit_cdecl();
167  static Ptr x86_32bit_stdcall();
168  static Ptr x86_64bit_stdcall();
169  static Ptr x86_32bit_fastcall();
170  static Ptr x86_64bit_sysv();
171  static Ptr ppc_32bit_ibm();
177  static Ptr x86_cdecl(const RegisterDictionaryPtr&);
178  static Ptr x86_stdcall(const RegisterDictionaryPtr&);
179  static Ptr x86_fastcall(const RegisterDictionaryPtr&);
180  static Ptr ppc_ibm(const RegisterDictionaryPtr&);
200  const std::string& name() const { return name_; }
201  void name(const std::string &s) { name_ = s; }
211  const std::string& comment() const { return comment_; }
212  void comment(const std::string &s) { comment_ = s; }
224  size_t wordWidth() const { return wordWidth_; }
225  void wordWidth(size_t nBits) {
226  ASSERT_require2(nBits > 0 && 0 == (nBits & 7), "word size must be a positive multiple of eight");
227  wordWidth_ = nBits;
228  }
238  const std::vector<ConcreteLocation>& nonParameterInputs() const { return nonParameterInputs_; }
239  std::vector<ConcreteLocation>& nonParameterInputs() { return nonParameterInputs_; }
246  nonParameterInputs_.clear();
249  thisParameter_ = ConcreteLocation();
250  }
251 
256  const std::vector<ConcreteLocation>& inputParameters() const { return inputParameters_; }
257 
263 
268  void clearInputParameters() { inputParameters_.clear(); }
269 
279  }
280  void appendInputParameter(RegisterDescriptor reg, int64_t offset) {
282  }
283  void appendInputParameter(rose_addr_t va) {
285  }
292  const std::vector<ConcreteLocation>& outputParameters() const { return outputParameters_; }
293 
296 
301  void clearOutputParameters() { outputParameters_.clear(); }
302 
314  }
315  void appendOutputParameter(RegisterDescriptor reg, int64_t offset) {
317  }
318  void appendOutputParameter(rose_addr_t va) {
320  }
333  StackParameterOrder stackParameterOrder() const { return stackParameterOrder_; }
334  void stackParameterOrder(StackParameterOrder x) { stackParameterOrder_ = x; }
344  const RegisterDescriptor stackPointerRegister() const { return stackPointerRegister_; }
345  void stackPointerRegister(RegisterDescriptor r) { stackPointerRegister_ = r; }
355  size_t nonParameterStackSize() const {
356  return nonParameterStackSize_;
357  }
358  void nonParameterStackSize(size_t nBytes) {
359  nonParameterStackSize_ = nBytes;
360  }
370  StackDirection stackDirection() const { return stackDirection_; }
371  void stackDirection(StackDirection x) { stackDirection_ = x; }
381  StackCleanup stackCleanup() const { return stackCleanup_; }
382  void stackCleanup(StackCleanup x) { stackCleanup_ = x; }
391  size_t stackAlignment() const { return stackAlignment_; }
392  void stackAlignment(size_t nBytes) { stackAlignment_ = nBytes; }
409  const ConcreteLocation& thisParameter() const { return thisParameter_; }
410  void thisParameter(const ConcreteLocation &x) { thisParameter_ = x; }
413  }
414  void thisParameter(RegisterDescriptor reg, int64_t offset) {
415  thisParameter(ConcreteLocation(reg, offset));
416  }
417  void thisParameter(rose_addr_t va) {
419  }
428  const ConcreteLocation& returnAddressLocation() const { return returnAddressLocation_; }
429  void returnAddressLocation(const ConcreteLocation &x) { returnAddressLocation_ = x; }
435  RegisterDescriptor instructionPointerRegister() const { return instructionPointerRegister_; }
436  void instructionPointerRegister(RegisterDescriptor x) { instructionPointerRegister_ = x; }
450  const std::set<RegisterDescriptor>& calleeSavedRegisters() const { return calleeSavedRegisters_; }
451  std::set<RegisterDescriptor>& calleeSavedRegisters() { return calleeSavedRegisters_; }
456 
464  const std::set<RegisterDescriptor>& scratchRegisters() const { return scratchRegisters_; }
465  std::set<RegisterDescriptor>& scratchRegisters() { return scratchRegisters_; }
470 
481 
488  void print(std::ostream&) const;
489  void print(std::ostream&, const RegisterDictionaryPtr &regDict) const;
491 };
492 
493 
495 // Dictionary
497 
499 typedef std::vector<Definition::Ptr> Dictionary;
500 
502 const Dictionary& dictionaryAmd64();
503 
505 const Dictionary& dictionaryAarch32();
506 
508 const Dictionary& dictionaryAarch64();
509 
511 const Dictionary& dictionaryM68k();
512 
514 const Dictionary& dictionaryMips();
515 
517 const Dictionary& dictionaryPowerpc32();
518 
520 const Dictionary& dictionaryPowerpc64();
521 
523 const Dictionary& dictionaryX86();
524 
525 
527 // Analysis
529 
533 class Analysis {
534 private:
536  RegisterDictionaryPtr regDict_; // Names for the register parts
537  Definition::Ptr defaultCc_; // Default calling convention for called functions
538 
539  bool hasResults_; // Are the following data members initialized?
540  bool didConverge_; // Are the following data members valid (else only approximations)?
541  RegisterParts restoredRegisters_; // Registers accessed but restored
542  RegisterParts inputRegisters_; // Registers that serve as possible input parameters
543  RegisterParts outputRegisters_; // Registers that hold possible return values
544  Variables::StackVariables inputStackParameters_; // Stack variables serving as function inputs
545  Variables::StackVariables outputStackParameters_; // Stack variables serving as possible return values
546  Sawyer::Optional<int64_t> stackDelta_; // Change in stack across entire function
547  // Don't forget to update clearResults() and serialize() if you add more.
548 
549 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
550 private:
551  friend class boost::serialization::access;
552 
553  template<class S>
554  void serialize(S &s, const unsigned /*version*/) {
555  s & BOOST_SERIALIZATION_NVP(cpu_);
556  s & BOOST_SERIALIZATION_NVP(regDict_);
557  s & BOOST_SERIALIZATION_NVP(defaultCc_);
558  s & BOOST_SERIALIZATION_NVP(hasResults_);
559  s & BOOST_SERIALIZATION_NVP(didConverge_);
560  s & BOOST_SERIALIZATION_NVP(restoredRegisters_);
561  s & BOOST_SERIALIZATION_NVP(inputRegisters_);
562  s & BOOST_SERIALIZATION_NVP(outputRegisters_);
563  s & BOOST_SERIALIZATION_NVP(inputStackParameters_);
564  s & BOOST_SERIALIZATION_NVP(outputStackParameters_);
565  s & BOOST_SERIALIZATION_NVP(stackDelta_);
566  }
567 #endif
568 
569 public:
575  Analysis();
576  ~Analysis();
577 
581  explicit Analysis(const Disassembler::BasePtr&);
582 
590 
598  Definition::Ptr defaultCallingConvention() const { return defaultCc_; }
599  void defaultCallingConvention(const Definition::Ptr &x) { defaultCc_ = x; }
608 
613  bool hasResults() const { return hasResults_; }
614 
619  bool didConverge() const { return didConverge_; }
620 
625  void clearResults();
626 
631  void clearNonResults();
632 
648  const RegisterParts& calleeSavedRegisters() const { return restoredRegisters_; }
649 
654  const RegisterParts& inputRegisters() const { return inputRegisters_; }
655 
660  const RegisterParts& outputRegisters() const { return outputRegisters_; }
661 
665  const Variables::StackVariables& inputStackParameters() const { return inputStackParameters_; }
666 
670  const Variables::StackVariables& outputStackParameters() const { return outputStackParameters_; }
671 
676  Sawyer::Optional<int64_t> stackDelta() const { return stackDelta_; }
677 
681  bool match(const Definition::Ptr&) const;
682 
688  Dictionary match(const Dictionary&) const;
689 
694  void print(std::ostream&, bool multiLine=false) const;
695 
696 private:
697  // Finish constructing
698  void init(const Disassembler::BasePtr&);
699 
700  // Recompute the restoredRegisters_ data member.
701  void updateRestoredRegisters(const InstructionSemantics::BaseSemantics::StatePtr &initialState,
703 
704  // Recompute the inputRegisters_ data member after updateRestoredRegisters is computed.
705  void updateInputRegisters(const InstructionSemantics::BaseSemantics::StatePtr &state);
706 
707  // Recompute the outputRegisters_ data member after updateRestoredRegisters is computed.
708  void updateOutputRegisters(const InstructionSemantics::BaseSemantics::StatePtr &state);
709 
710  // Recompute the input and output stack variables
711  void updateStackParameters(const Partitioner2::FunctionPtr &function,
714 
715  // Recomputes the stack delta
716  void updateStackDelta(const InstructionSemantics::BaseSemantics::StatePtr &initialState,
718 };
719 
721 // Free functions
723 
727 
730  size_t argNumber, const InstructionSemantics::BaseSemantics::SValuePtr &value);
731 
735 
739 
744 
746 std::ostream& operator<<(std::ostream&, const Definition&);
747 
749 std::ostream& operator<<(std::ostream&, const Analysis&);
750 
751 } // namespace
752 } // namespace
753 } // namespace
754 
755 // Class versions must be at global scope
757 
758 #endif
759 #endif
void thisParameter(rose_addr_t va)
Property: Object pointer parameter.
size_t wordWidth() const
Property: Word size in bits.
const Dictionary & dictionaryX86()
Common calling conventions for 32-bit x86.
The called function pops all stack parameters.
Stack parameter order is unknown or unspecified.
void analyzeFunction(const Partitioner2::PartitionerConstPtr &, const Sawyer::SharedPointer< Partitioner2::Function > &)
Analyze one function.
StackParameterOrder stackParameterOrder() const
Property: Stack parameter order.
size_t stackAlignment() const
Property: Stack alignment.
void writeArgument(const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &, const Definition::Ptr &, size_t argNumber, const InstructionSemantics::BaseSemantics::SValuePtr &value)
Write a function argument to a semantic state.
const Dictionary & dictionaryM68k()
Common calling conventions for m68k.
static Ptr x86_fastcall(const RegisterDictionaryPtr &)
Constructs a new pre-defined calling convention based on a register dictionary.
static Ptr x86_cdecl(const RegisterDictionaryPtr &)
Constructs a new pre-defined calling convention based on a register dictionary.
StackDirection stackDirection() const
Property: Direction that stack grows for a push operation.
std::vector< ConcreteLocation > & nonParameterInputs()
Non-parameter inputs.
const Variables::StackVariables & outputStackParameters() const
Output stack parameters.
void wordWidth(size_t nBits)
Property: Word size in bits.
void stackDirection(StackDirection x)
Property: Direction that stack grows for a push operation.
static Ptr x86_32bit_cdecl()
Returns a predefined, cached calling convention.
void appendOutputParameter(rose_addr_t va)
Append output parameter.
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
const Dictionary & dictionaryAarch64()
Common calling conventions for ARM AArch64.
Collection of streams.
Definition: Message.h:1606
static Ptr x86_32bit_stdcall()
Allocating constructor.
static Ptr ppc_32bit_ibm()
Allocating constructor.
void thisParameter(RegisterDescriptor reg, int64_t offset)
Property: Object pointer parameter.
const Dictionary & dictionaryPowerpc64()
Common calling conventions for PowerPC-64.
const std::vector< ConcreteLocation > & inputParameters() const
Property: Enumerated input parameters.
Stack parameters pushed left to right (Pascal order).
StackDirection
The direction in which the stack grows.
const Dictionary & dictionaryAmd64()
Common calling conventions for amd64 (x86-64).
void appendInputParameter(rose_addr_t va)
Append input parameter.
Definition::Ptr defaultCallingConvention() const
Property: Default calling convention.
void thisParameter(RegisterDescriptor reg)
Property: Object pointer parameter.
void stackCleanup(StackCleanup x)
Property: Who pops stack parameters.
Main namespace for the ROSE library.
RegisterParts inputRegisterParts() const
Compute the set of input registers.
RegisterParts scratchRegisterParts() const
Computes the set of scratch registers.
Holds a set of registers without regard for register boundaries.
Definition: RegisterParts.h:28
StackCleanup stackCleanup() const
Property: Who pops stack parameters.
Sawyer::Optional< int64_t > stackDelta() const
Concrete stack delta.
void print(std::ostream &) const
Print detailed information about this calling convention.
RegisterDictionaryPtr registerDictionary() const
Property: Register dictionary.
boost::shared_ptr< State > StatePtr
Shared-ownership pointer to a semantic state.
bool hasResults() const
Whether a function has been analyzed.
boost::shared_ptr< Dispatcher > DispatcherPtr
Shared-ownership pointer to a semantics instruction dispatcher.
Sawyer::SharedPointer< Definition > DefinitionPtr
Reference counting pointer.
const std::vector< ConcreteLocation > & outputParameters() const
Property: List of output parameters.
void comment(const std::string &s)
Property: Full name of calling convention.
const RegisterParts & calleeSavedRegisters() const
Callee-saved registers.
void stackParameterOrder(StackParameterOrder x)
Property: Stack parameter order.
const RegisterParts & inputRegisters() const
Input registers.
void print(std::ostream &, bool multiLine=false) const
Print information about the analysis results.
const ConcreteLocation & returnAddressLocation() const
Property: Location of return address.
void instructionPointerRegister(RegisterDescriptor x)
Property: Register that points to next instruction to execute.
const Dictionary & dictionaryPowerpc32()
Common calling conventions for PowerPC-32.
std::vector< Definition::Ptr > Dictionary
A ordered collection of calling convention definitions.
const Dictionary & dictionaryMips()
Common calling conventions for MIPS.
Stack parameter cleanup is unknown or unspecified.
const Variables::StackVariables & inputStackParameters() const
Input stack parameters.
const std::set< RegisterDescriptor > & calleeSavedRegisters() const
Property: Callee-saved registers.
Describes (part of) a physical CPU register.
void appendInputParameter(RegisterDescriptor reg)
Append input parameter.
DefinitionPtr Ptr
Reference counting pointer to calling convention definition.
void nonParameterStackSize(size_t nBytes)
Property: Size of non-parameter stack area.
StackParameterOrder
The order that arguments are pushed onto the stack.
bool didConverge() const
Whether the analysis results are valid.
Information about calling conventions.
std::set< RegisterDescriptor > & scratchRegisters()
Property: Scratch registers.
Sawyer::Message::Facility mlog
Facility for diagnostic output.
void clearOutputParameters()
Erase output parameters.
void appendInputParameter(RegisterDescriptor reg, int64_t offset)
Append input parameter.
size_t nonParameterStackSize() const
Property: Size of non-parameter stack area.
RegisterDictionaryPtr registerDictionary() const
Property: Register dictionary.
RegisterParts outputRegisterParts() const
Computes the set of output registers.
bool match(const Definition::Ptr &) const
Determine whether a definition matches.
void appendOutputParameter(const ConcreteLocation &)
Append output parameter.
const RegisterDescriptor stackPointerRegister() const
Property: Register for implied stack parameters.
RegisterParts getUsedRegisterParts() const
Returns all registers mentioned in this definition.
const RegisterParts & outputRegisters() const
Output registers.
InstructionSemantics::BaseSemantics::SValuePtr readReturnValue(const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &, const Definition::Ptr &)
Read the return value that a function is returning.
static Ptr x86_64bit_cdecl()
Allocating constructor.
void name(const std::string &s)
Property: Short name of calling convention.
InstructionSemantics::BaseSemantics::SValuePtr readArgument(const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &, const Definition::Ptr &, size_t argNumber)
Read a function argument from a semantic state.
StackCleanup
Who is responsible for popping stack parameters.
static Ptr x86_stdcall(const RegisterDictionaryPtr &)
Constructs a new pre-defined calling convention based on a register dictionary.
Base class for reference counted objects.
Definition: SharedObject.h:64
void clearNonResults()
Clears everything but results.
void initDiagnostics()
Initialize diagnostics.
void simulateFunctionReturn(const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &, const Definition::Ptr &)
Simulate a function return.
void clearResults()
Clear analysis results.
static Ptr instance(size_t wordWidth, const std::string &name, const std::string &comment, const RegisterDictionaryPtr &regs)
Allocating constructor.
void writeReturnValue(const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &, const Definition::Ptr &, const InstructionSemantics::BaseSemantics::SValuePtr &returnValue)
Write a value to a function return semantic state.
const ConcreteLocation & thisParameter() const
Property: Object pointer parameter.
void clearInputParameters()
Erase enumerated input parameters.
void appendOutputParameter(RegisterDescriptor reg)
Append output parameter.
const std::string & name() const
Property: Short name of calling convention.
void stackAlignment(size_t nBytes)
Property: Stack alignment.
RegisterDescriptor instructionPointerRegister() const
Property: Register that points to next instruction to execute.
const Dictionary & dictionaryAarch32()
Common calling conventions for ARM AArch32.
const std::vector< ConcreteLocation > & nonParameterInputs() const
Non-parameter inputs.
RegisterParts calleeSavedRegisterParts() const
Compute the set of callee-saved registers.
void defaultCallingConvention(const Definition::Ptr &x)
Property: Default calling convention.
const std::string & comment() const
Property: Full name of calling convention.
const std::set< RegisterDescriptor > & scratchRegisters() const
Property: Scratch registers.
static Ptr x86_32bit_fastcall()
Allocating constructor.
void thisParameter(const ConcreteLocation &x)
Property: Object pointer parameter.
static Ptr x86_64bit_sysv()
Allocating constructor.
static Ptr x86_64bit_stdcall()
Allocating constructor.
void returnAddressLocation(const ConcreteLocation &x)
Property: Location of return address.
std::ostream & operator<<(std::ostream &, const Definition &)
Print a definition.
static Ptr ppc_ibm(const RegisterDictionaryPtr &)
Constructs a new pre-defined calling convention based on a register dictionary.
std::set< RegisterDescriptor > & calleeSavedRegisters()
Property: Callee-saved registers.
Virtual base class for instruction disassemblers.
void appendInputParameter(const ConcreteLocation &)
Append input parameter.
void stackPointerRegister(RegisterDescriptor r)
Property: Register for implied stack parameters.
void appendOutputParameter(RegisterDescriptor reg, int64_t offset)
Append output parameter.