ROSE  0.11.51.0
DispatcherAarch32.h
1 #ifndef ROSE_BinaryAnalysis_InstructionSemantics2_DispatcherAarch32_H
2 #define ROSE_BinaryAnalysis_InstructionSemantics2_DispatcherAarch32_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_ASM_AARCH32
5 
6 #include <Rose/BinaryAnalysis/InstructionSemantics2/BaseSemantics.h>
7 
8 #include <boost/serialization/access.hpp>
9 #include <boost/serialization/base_object.hpp>
10 #include <boost/serialization/export.hpp>
11 #include <boost/serialization/split_member.hpp>
12 
13 namespace Rose {
14 namespace BinaryAnalysis {
15 namespace InstructionSemantics2 {
16 
18 using DispatcherAarch32Ptr = boost::shared_ptr<class DispatcherAarch32>;
19 
20 class DispatcherAarch32: public BaseSemantics::Dispatcher {
21 public:
23  using Super = BaseSemantics::Dispatcher;
24 
26  using Ptr = DispatcherAarch32Ptr;
27 
28 public:
35  RegisterDescriptor REG_PC, REG_SP, REG_LR;
36  RegisterDescriptor REG_PSTATE_N, REG_PSTATE_Z, REG_PSTATE_C, REG_PSTATE_V, REG_PSTATE_T; // parts of CPSR
37  RegisterDescriptor REG_PSTATE_E, REG_PSTATE_Q, REG_PSTATE_GE;
38  RegisterDescriptor REG_PSTATE_NZCV; // the CPSR N, Z, C, and V bits
39  RegisterDescriptor REG_SPSR, REG_CPSR;
40  RegisterDescriptor REG_DTRTX; // debug registers
41  RegisterDescriptor REG_UNKNOWN; // special ROSE register
44 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
45 private:
46  friend class boost::serialization::access;
47 
48  template<class S>
49  void save(S &s, const unsigned /*version*/) const {
50  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
51  }
52 
53  template<class S>
54  void load(S &s, const unsigned /*version*/) {
55  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
56  initializeRegisterDescriptors();
57  initializeInsnDispatchTable();
58  initializeMemory();
59  }
60 
61  BOOST_SERIALIZATION_SPLIT_MEMBER();
62 #endif
63 
64 protected:
65  // prototypical constructor
66  DispatcherAarch32()
67  :BaseSemantics::Dispatcher(32, RegisterDictionary::dictionary_aarch32()) {}
68 
69  DispatcherAarch32(const BaseSemantics::RiscOperatorsPtr &ops, const RegisterDictionary *regs)
70  : BaseSemantics::Dispatcher(ops, 32, regs ? regs : RegisterDictionary::dictionary_aarch32()) {
71  initializeRegisterDescriptors();
72  initializeInsnDispatchTable();
73  initializeMemory();
74  initializeState(ops->currentState());
75  }
76 
77 public:
81  static DispatcherAarch32Ptr instance() {
82  return DispatcherAarch32Ptr(new DispatcherAarch32);
83  }
84 
86  static DispatcherAarch32Ptr instance(const BaseSemantics::RiscOperatorsPtr &ops, const RegisterDictionary *regs = nullptr) {
87  return DispatcherAarch32Ptr(new DispatcherAarch32(ops, regs));
88  }
89 
91  virtual BaseSemantics::DispatcherPtr create(const BaseSemantics::RiscOperatorsPtr &ops, size_t addrWidth = 0,
92  const RegisterDictionary *regs = nullptr) const override {
93  ASSERT_require(0 == addrWidth || 32 == addrWidth);
94  return instance(ops, regs);
95  }
96 
98  static DispatcherAarch32Ptr promote(const BaseSemantics::DispatcherPtr &d) {
99  DispatcherAarch32Ptr retval = boost::dynamic_pointer_cast<DispatcherAarch32>(d);
100  ASSERT_not_null(retval);
101  return retval;
102  }
103 
104 protected:
106  void initializeRegisterDescriptors();
107 
111  void initializeInsnDispatchTable();
112 
114  void initializeMemory();
115 
116 protected:
117  int iprocKey(SgAsmInstruction*) const override;
118  RegisterDescriptor instructionPointerRegister() const override;
119  RegisterDescriptor stackPointerRegister() const override;
120  RegisterDescriptor stackFrameRegister() const override;
121  RegisterDescriptor callReturnRegister() const override;
122  void set_register_dictionary(const RegisterDictionary*) override;
123 
124 public:
125  BaseSemantics::SValuePtr read(SgAsmExpression*, size_t value_nbits=0, size_t addr_nbits=0) override;
126  void write(SgAsmExpression*, const BaseSemantics::SValuePtr&, size_t addr_nbits=0) override;
127 
128  // Instruction condition
129  BaseSemantics::SValuePtr conditionHolds(Aarch32InstructionCondition);
130 
131  // True if the expression is the program counter register
132  bool isIpRegister(SgAsmExpression*);
133 
134  // Read the instruction pointer (PC) register, which is handled in a special way.
136 
137  // Is the processor in T32 mode? This is based just on the instruction being executed.
138  BaseSemantics::SValuePtr isT32Mode();
139 
140  // Is the processor in A32 mode? This is based just on the instruction being executed.
141  BaseSemantics::SValuePtr isA32Mode();
142 
143  // Set T32 mode on or off.
144  void setThumbMode(SgAsmAarch32Instruction*); // on if instructions is 2 bytes; off otherwise
145  void setThumbMode(const BaseSemantics::SValuePtr &state);
146  void setThumbMode(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &state);
147 
148  // Conditionally write a value to a register
149  void maybeWriteRegister(const BaseSemantics::SValuePtr &enabled, RegisterDescriptor, const BaseSemantics::SValuePtr &value);
150 
151  // Conditionally write a value to memory
152  void maybeWriteMemory(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &address,
153  const BaseSemantics::SValuePtr &value);
154 
155  // Conditionally write the the destination described the by ROSE expression, which must also be readable.
156  void maybeWrite(const BaseSemantics::SValuePtr &enabled, SgAsmExpression *destination, const BaseSemantics::SValuePtr &value);
157 
158  // Returns the most significant bit.
160 
161  // Return the register that's being directly read or written.
162  RegisterDescriptor accessedRegister(SgAsmExpression*);
163 
164  // Returns true if the specified value is a constant true, false in all other cases
165  bool mustBeSet(const BaseSemantics::SValuePtr&);
166 
167  //----------------------------------------------------------------------------------------------------------------
168  // The following functions are more or less from ARM documentation and named similarly. They are generally not
169  // further documented here or by ARM.
170  //----------------------------------------------------------------------------------------------------------------
171  using TwoValues = std::tuple<BaseSemantics::SValuePtr, BaseSemantics::SValuePtr>;
172 
173  enum class SrType { LSL, LSR, ASR, ROR, RRX }; // SRType
174  enum class BranchType { // BranchType
175  DIRCALL, // direct branch with link
176  DIR, // undocumented but used by B instruction (maybe the same as DIRCALL?)
177  INDCALL, // indirect branch with link
178  ERET, // exception return (indirect)
179  DBGEXIT, // exit from debug state
180  RET, // indirect branch with function return hint
181  INDIR, // indicrect branch
182  EXCEPTION, // exception entry
183  RESET, // reset
184  UNKNOWN // other
185  };
186 
187  BaseSemantics::SValuePtr part(const BaseSemantics::SValuePtr&, size_t maxBit, size_t minBit); // X<m,n>
188  BaseSemantics::SValuePtr part(const BaseSemantics::SValuePtr&, size_t bitNumber); // X<n>
189  BaseSemantics::SValuePtr join(const BaseSemantics::SValuePtr &highBits, const BaseSemantics::SValuePtr &lowBits); // X:Y
190  BaseSemantics::SValuePtr zeroExtend(const BaseSemantics::SValuePtr&, size_t); // ZeroExtend
191  BaseSemantics::SValuePtr makeZeros(size_t); // Zeros
192  TwoValues a32ExpandImmC(const BaseSemantics::SValuePtr&); // A32ExpandImm_C
193  TwoValues shiftC(const BaseSemantics::SValuePtr&, SrType, int amount, const BaseSemantics::SValuePtr &carry); // Shift_C
194  TwoValues lslC(const BaseSemantics::SValuePtr&, size_t shift); // LSL_C
195  TwoValues lsrC(const BaseSemantics::SValuePtr&, size_t shift); // LSR_C
196  TwoValues asrC(const BaseSemantics::SValuePtr&, size_t shift); // ASR_C
197  TwoValues rorC(const BaseSemantics::SValuePtr&, int shift); // ROR_C
198  TwoValues rrxC(const BaseSemantics::SValuePtr&, const BaseSemantics::SValuePtr &carry); // RRX_C
199  BaseSemantics::SValuePtr lsr(const BaseSemantics::SValuePtr&, size_t shift); // LSR
200  BaseSemantics::SValuePtr lsl(const BaseSemantics::SValuePtr&, size_t shift); // LSL
201  BaseSemantics::SValuePtr signExtend(const BaseSemantics::SValuePtr&, size_t); // SignExtend
202  void aluExceptionReturn(const BaseSemantics::SValuePtr &enabled,
203  const BaseSemantics::SValuePtr &address); // ALUExceptionReturn
204  void aluWritePc(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &address); // ALUWritePC
205  void bxWritePc(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &address, BranchType); // BXWritePC
206  void branchWritePc(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &address,
207  BranchType branchType); // BranchWritePC
208  void branchTo(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &alignedAddress,
209  BranchType); // BranchTo
210  BaseSemantics::SValuePtr align(const BaseSemantics::SValuePtr&, unsigned); // Align
211  BaseSemantics::SValuePtr pc(); // PC. Returns address of current instruction plus eight (not sure why).
212  BaseSemantics::SValuePtr pcStoreValue(); // PCStoreValue (which doesn't store anything at all)
213  void loadWritePc(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &address); // LoadWritePC
214  TwoValues addWithCarry(const BaseSemantics::SValuePtr&, const BaseSemantics::SValuePtr&,
215  const BaseSemantics::SValuePtr&); // AddWithCarry
216  BaseSemantics::SValuePtr spsr(); // SPSR
217  void aarch32ExceptionReturn(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &address,
218  const BaseSemantics::SValuePtr &spsr); // AArch32.ExceptionReturn
219  void dbgdtrEl0(const BaseSemantics::SValuePtr &enabled, const BaseSemantics::SValuePtr &value); // DBGDTR_EL0
220  BaseSemantics::SValuePtr dbgdtrEl0(); // DBGDTR_EL0
221  BaseSemantics::SValuePtr bigEndian(); // BigEndian
222  BaseSemantics::SValuePtr signedSat(const BaseSemantics::SValuePtr&, size_t); // SignedSat
223  TwoValues signedSatQ(const BaseSemantics::SValuePtr&, size_t); // SignedSatQ
224  BaseSemantics::SValuePtr unsignedSat(const BaseSemantics::SValuePtr&, size_t); // UnsignedSat
225  TwoValues unsignedSatQ(const BaseSemantics::SValuePtr&, size_t); // UnsignedSatQ
227  BaseSemantics::SValuePtr countLeadingZeroBits(const BaseSemantics::SValuePtr&); // CountLeadingZeroBits
228  void aarch32CallHypervisor(const BaseSemantics::SValuePtr&, const BaseSemantics::SValuePtr&); // AArch32.CallHypervisor
229 };
230 
231 } // namespace
232 } // namespace
233 } // namespace
234 
235 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
236 BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::InstructionSemantics2::DispatcherAarch32);
237 #endif
238 
239 #endif
240 #endif
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
Sawyer::SharedPointer< Node > Ptr
Shared-ownership pointer to an expression Node.
Definition: SymbolicExpr.h:156
Base class for machine instructions.
Unsigned signExtend(Unsigned src, size_t n)
Sign extend part of a value to the full width of the src type.
Definition: Rose/BitOps.h:272
bool signBit(T value)
Returns true if the sign bit is set, false if clear.
Definition: integerOps.h:72
Main namespace for the ROSE library.
boost::shared_ptr< Dispatcher > DispatcherPtr
Shared-ownership pointer to a semantics instruction dispatcher.
Base classes for instruction semantics.
Definition: Dispatcher.h:18
Base class for expressions.
Dispatches instructions through the RISC layer.
Definition: Dispatcher.h:44
std::string join(const std::string &separator, const Container &container)
Join individual items to form a single string.