Fix register conversion between Dyninst and ROSE
[dyninst.git] / dataflowAPI / rose / semantics / SymEvalSemantics.C
1 //
2 // Created by ssunny on 7/1/16.
3 //
4
5 #include <Register.h>
6 #include "SymEvalSemantics.h"
7
8 using namespace rose::BinaryAnalysis::InstructionSemantics2;
9
10 ///////////////////////////////////////////////////////
11 //                                           StateARM64
12 ///////////////////////////////////////////////////////
13
14 BaseSemantics::SValuePtr SymEvalSemantics::StateARM64::readRegister(const RegisterDescriptor &desc,
15                                                                     const BaseSemantics::SValuePtr &/*dflt*/, BaseSemantics::RiscOperators */*ops*/) {
16     ASSERT_require(desc.is_valid());
17     SymEvalSemantics::RegisterStateARM64Ptr registers = SymEvalSemantics::RegisterStateARM64::promote(registerState());
18     return registers->readRegister(desc, addr);
19 }
20
21 void SymEvalSemantics::StateARM64::writeRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &value,
22                                                  BaseSemantics::RiscOperators */*ops*/) {
23     ASSERT_require(reg.is_valid());
24     ASSERT_not_null(value);
25     SymEvalSemantics::RegisterStateARM64Ptr registers = SymEvalSemantics::RegisterStateARM64::promote(registerState());
26     registers->writeRegister(reg, value, res, aaMap);
27 }
28
29 void SymEvalSemantics::StateARM64::writeMemory(const BaseSemantics::SValuePtr &addr,
30                                                const BaseSemantics::SValuePtr &value,
31                                                BaseSemantics::RiscOperators */*addrOps*/,
32                                                BaseSemantics::RiscOperators */*valOps*/) {
33     ASSERT_not_null(addr);
34     ASSERT_not_null(value);
35     SymEvalSemantics::MemoryStateARM64Ptr memory = SymEvalSemantics::MemoryStateARM64::promote(memoryState());
36     memory->writeMemory(addr, value, res, aaMap);
37 }
38
39 ///////////////////////////////////////////////////////
40 //                                   RegisterStateARM64
41 ///////////////////////////////////////////////////////
42
43 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
44                                                                             Dyninst::Address addr) {
45     if(reg.get_major() != armv8_regclass_simd_fpr) {
46         ARMv8GeneralPurposeRegister r = static_cast<ARMv8GeneralPurposeRegister>(reg.get_minor());
47         unsigned int size = reg.get_nbits();
48         return SymEvalSemantics::SValue::instance(wrap(convert(reg), addr));
49     } else {
50         ASSERT_not_implemented("readRegister not yet implemented for categories other than GPR");
51     }
52 }
53
54 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
55                                                                             const BaseSemantics::SValuePtr &/*dflt*/,
56                                                                             BaseSemantics::RiscOperators */*ops*/) {
57     ASSERT_always_forbid("overridden RegisterState::readRegister() should never be called for ARM64, always use the non-virtual readRegister that takes Dyninst::Address as an argument.");
58 }
59
60 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &reg,
61                                                          const BaseSemantics::SValuePtr &value,
62                                                          Dyninst::DataflowAPI::Result_t &res,
63                                                          std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
64     if(reg.get_major() != armv8_regclass_simd_fpr) {
65         std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(convert(reg));
66         if (i != aaMap.end()) {
67             SymEvalSemantics::SValuePtr value_ = SymEvalSemantics::SValue::promote(value);
68             res[i->second] = value_->get_expression();
69         }
70     } else {
71         ASSERT_not_implemented("writeRegister not yet implemented for categories other than GPR");
72     }
73 }
74
75 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &/*reg*/,
76                                                          const BaseSemantics::SValuePtr &/*value*/,
77                                                          BaseSemantics::RiscOperators */*ops*/) {
78     ASSERT_always_forbid("overridden RegisterState::writeRegister() should never be called for ARM64, always use the non-virtual writeRegister that also takes additional parameters.");
79 }
80
81 Dyninst::Absloc SymEvalSemantics::RegisterStateARM64::convert(const RegisterDescriptor &reg) {
82     Dyninst::MachRegister mreg;
83
84     unsigned int major = reg.get_major();
85     unsigned int size = reg.get_nbits();
86
87     switch (major) {
88         case armv8_regclass_gpr: {
89             unsigned int minor = reg.get_minor();
90
91             if (minor == armv8_gpr_zr) {
92                 mreg = Dyninst::MachRegister((size == 32) ? Dyninst::aarch64::wzr : Dyninst::aarch64::zr);
93             } else {
94                 Dyninst::MachRegister base = (size == 32) ? Dyninst::aarch64::w0 : Dyninst::aarch64::x0;
95                 mreg = Dyninst::MachRegister(base.val() + (minor - armv8_gpr_r0));
96             }
97         }
98             break;
99         case armv8_regclass_pc:
100             mreg = Dyninst::MachRegister(Dyninst::aarch64::pc);
101             break;
102         case armv8_regclass_sp:
103             mreg = Dyninst::MachRegister((size == 32) ? Dyninst::aarch64::wsp : Dyninst::aarch64::sp);
104             break;
105         case armv8_regclass_pstate: {
106             unsigned int offset = reg.get_offset();
107             if (offset == armv8_pstatefield_nzcv) {
108                 mreg = Dyninst::MachRegister(Dyninst::aarch64::pstate);
109             } else {
110                 ASSERT_always_forbid("No part of the PSTATE register other than NZCV should be used.");
111             }
112         }
113             break;
114         default:
115             ASSERT_always_forbid("Unexpected register major type.");
116     }
117
118     return Dyninst::Absloc(mreg);
119 }
120
121 ///////////////////////////////////////////////////////
122 //                                     MemoryStateARM64
123 ///////////////////////////////////////////////////////
124
125 //TODO: what is Len in this case?
126
127 BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateARM64::readMemory(const BaseSemantics::SValuePtr &address,
128                                                                         const BaseSemantics::SValuePtr &/*dflt*/,
129                                                                         BaseSemantics::RiscOperators */*addrOps*/,
130                                                                         BaseSemantics::RiscOperators */*valOps*/) {
131     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
132     return SymEvalSemantics::SValue::instance(Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(Dyninst::DataflowAPI::ROSEOperation::derefOp),
133                                                  addr->get_expression(),
134                                                  Dyninst::DataflowAPI::ConstantAST::create(Dyninst::DataflowAPI::Constant(1, 1))));
135 }
136
137 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &address,
138                                                      const BaseSemantics::SValuePtr &value,
139                                                      Dyninst::DataflowAPI::Result_t &res,
140                                                      std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
141     std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(Dyninst::Absloc(0));
142     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
143
144     if (i != aaMap.end()) {
145         i->second->out().setGenerator(addr->get_expression());
146         //i->second->out().setSize(Len);
147
148         SymEvalSemantics::SValuePtr data = SymEvalSemantics::SValue::promote(value);
149         res[i->second] = data->get_expression();
150     }
151 }
152
153 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &/*addr*/,
154                                                      const BaseSemantics::SValuePtr &/*value*/,
155                                                      BaseSemantics::RiscOperators */*addrOps*/,
156                                                      BaseSemantics::RiscOperators */*valOps*/) {
157     ASSERT_always_forbid("overridden MemoryState::writeMemory() should never be called for ARM64, always use the non-virtual writeRegister that also takes additional parameters.");
158 }
159
160 ///////////////////////////////////////////////////////
161 //                                        RiscOperators
162 ///////////////////////////////////////////////////////
163
164 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::and_(const BaseSemantics::SValuePtr &a_,
165                                                                const BaseSemantics::SValuePtr &b_) {
166     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::andOp, a_, b_);
167 }
168
169 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::or_(const BaseSemantics::SValuePtr &a_,
170                                                               const BaseSemantics::SValuePtr &b_) {
171     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::orOp, a_, b_);
172 }
173
174 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::xor_(const BaseSemantics::SValuePtr &a_,
175                                                                const BaseSemantics::SValuePtr &b_) {
176     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, a_, b_);
177 }
178
179 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::invert(const BaseSemantics::SValuePtr &a_) {
180     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::invertOp, a_);
181 }
182
183 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::extract(const BaseSemantics::SValuePtr &a_, size_t begin,
184                                                                   size_t end) {
185     BaseSemantics::SValuePtr begin_ = SymEvalSemantics::SValue::instance(64, begin);
186     BaseSemantics::SValuePtr end_ = SymEvalSemantics::SValue::instance(64, end);
187
188     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::extractOp, a_, begin_, end_, end - begin);
189 }
190
191 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::ite(const BaseSemantics::SValuePtr &sel_,
192                                                               const BaseSemantics::SValuePtr &a_,
193                                                               const BaseSemantics::SValuePtr &b_) {
194     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::ifOp, sel_, a_, b_);
195 }
196
197 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::concat(const BaseSemantics::SValuePtr &a_,
198                                                                  const BaseSemantics::SValuePtr &b_) {
199     //TODO: should be able to specify number of bits to concat for each expression
200     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::concatOp, a_, b_);
201 }
202
203 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::leastSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
204     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::LSBSetOp, a_);
205 }
206
207 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::mostSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
208     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::MSBSetOp, a_);
209 }
210
211 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateLeft(const BaseSemantics::SValuePtr &a_,
212                                                                      const BaseSemantics::SValuePtr &b_) {
213     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateLOp, a_, b_);
214 }
215
216 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateRight(const BaseSemantics::SValuePtr &a_,
217                                                                       const BaseSemantics::SValuePtr &b_) {
218     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateROp, a_, b_);
219 }
220
221 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftLeft(const BaseSemantics::SValuePtr &a_,
222                                                                     const BaseSemantics::SValuePtr &b_) {
223     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftLOp, a_, b_);
224 }
225
226 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRight(const BaseSemantics::SValuePtr &a_,
227                                                                      const BaseSemantics::SValuePtr &b_) {
228     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftROp, a_, b_);
229 }
230
231 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRightArithmetic(const BaseSemantics::SValuePtr &a_,
232                                                                                const BaseSemantics::SValuePtr &b_) {
233     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftRArithOp, a_, b_);
234 }
235
236 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::equalToZero(const BaseSemantics::SValuePtr &a_) {
237     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::equalToZeroOp, a_);
238 }
239
240 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signExtend(const BaseSemantics::SValuePtr &a_,
241                                                                      size_t newwidth) {
242     BaseSemantics::SValuePtr width_ = SymEvalSemantics::SValue::instance(64, newwidth);
243
244     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::signExtendOp, a_, width_);
245 }
246
247 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::add(const BaseSemantics::SValuePtr &a_,
248                                                               const BaseSemantics::SValuePtr &b_) {
249     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, a_, b_);
250 }
251
252 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::addWithCarries(const BaseSemantics::SValuePtr &a_,
253                                                                          const BaseSemantics::SValuePtr &b_,
254                                                                          const BaseSemantics::SValuePtr &c_,
255                                                                          BaseSemantics::SValuePtr &carry_out) {
256     BaseSemantics::SValuePtr aa_ = unsignedExtend(a_, a_->get_width() + 1);
257     BaseSemantics::SValuePtr bb_ = unsignedExtend(a_, b_->get_width() + 1);
258     BaseSemantics::SValuePtr sum_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, aa_,
259                                                     createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, bb_, c_));
260
261     BaseSemantics::SValuePtr cc_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, aa_,
262                                                    createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, bb_, sum_));
263     carry_out = extract(cc_, 1, a_->get_width() + 1);
264
265     return extract(sum_, 0, a_->get_width());
266 }
267
268 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::negate(const BaseSemantics::SValuePtr &a_) {
269     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::negateOp, a_);
270 }
271
272 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedDivide(const BaseSemantics::SValuePtr &a_,
273                                                                        const BaseSemantics::SValuePtr &b_) {
274     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sDivOp, a_, b_);
275 }
276
277 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedModulo(const BaseSemantics::SValuePtr &a_,
278                                                                        const BaseSemantics::SValuePtr &b_) {
279     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sModOp, a_, b_);
280 }
281
282 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedMultiply(const BaseSemantics::SValuePtr &a_,
283                                                                          const BaseSemantics::SValuePtr &b_) {
284     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sMultOp, a_, b_);
285 }
286
287 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedDivide(const BaseSemantics::SValuePtr &a_,
288                                                                        const BaseSemantics::SValuePtr &b_) {
289     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uDivOp, a_, b_);
290 }
291
292 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedModulo(const BaseSemantics::SValuePtr &a_,
293                                                                        const BaseSemantics::SValuePtr &b_) {
294     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uModOp, a_, b_);
295 }
296
297 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedMultiply(const BaseSemantics::SValuePtr &a_,
298                                                                          const BaseSemantics::SValuePtr &b_) {
299     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uMultOp, a_, b_);
300 }
301
302 //TODO: do we deal with byte ordering?
303 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::readMemory(const RegisterDescriptor &/*segreg*/,
304                                                                      const BaseSemantics::SValuePtr &addr,
305                                                                      const BaseSemantics::SValuePtr &dflt,
306                                                                      const BaseSemantics::SValuePtr &/*cond*/) {
307     return currentState()->readMemory(addr, dflt, this, this);
308 }
309
310 void SymEvalSemantics::RiscOperatorsARM64::writeMemory(const RegisterDescriptor &/*segreg*/,
311                                                   const BaseSemantics::SValuePtr &addr,
312                                                   const BaseSemantics::SValuePtr &data,
313                                                   const BaseSemantics::SValuePtr &/*cond*/) {
314     currentState()->writeMemory(addr, data, this, this);
315 }