SymEval: Use MachRegister interface
[dyninst.git] / symEval / src / SymEval.C
1 /*
2  * Copyright (c) 1996-2007 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 #include <string>
33
34 #include "SymEval.h"
35 #include "SymEvalPolicy.h"
36
37 #include "AST.h"
38
39 #include "../rose/x86InstructionSemantics.h"
40
41 using namespace Dyninst;
42 using namespace Dyninst::InstructionAPI;
43 using namespace Dyninst::SymbolicEvaluation;
44
45 AST::Ptr SymEval::expand(const Assignment::Ptr &assignment) {
46   // This is a shortcut version for when we only want a 
47   // single assignment
48
49   SymEval::Result res;
50   // Fill it in to mark it as existing
51   res[assignment] = AST::Ptr();
52   expand(res);
53   return res[assignment];
54 }
55
56 void SymEval::expand(Result &res) {
57   // Symbolic evaluation works off an Instruction
58   // so we have something to hand to ROSE. 
59   // Let's assume (and, in fact, assert) that
60   // all of the Assignments we've been handed are for
61   // the same instruction.
62
63   Result::iterator i = res.begin();
64   if (i == res.end()) return;
65
66   Assignment::Ptr ptr = i->first;
67   expandInsn(ptr->insn(),
68              ptr->addr(),
69              res);
70 }
71
72
73 void SymEval::expandInsn(const InstructionAPI::Instruction::Ptr insn,
74                          const uint64_t addr,
75                          Result &res) {
76   SgAsmx86Instruction roseInsn = convert(insn, addr);
77   SymEvalPolicy policy(res, insn->getArch());
78   X86InstructionSemantics<SymEvalPolicy, Handle> t(policy);
79   t.processInstruction(&roseInsn);
80   return;
81 }
82
83 SgAsmx86Instruction SymEval::convert(const InstructionAPI::Instruction::Ptr &insn, uint64_t addr) {
84     SgAsmx86Instruction rinsn;
85
86     rinsn.set_address(addr);
87     rinsn.set_mnemonic(insn->format());
88     rinsn.set_kind(convert(insn->getOperation().getID()));
89     // semantics don't support 64-bit code
90     rinsn.set_operandSize(x86_insnsize_32);
91     rinsn.set_addressSize(x86_insnsize_32);
92
93     std::vector<unsigned char> rawBytes;
94     for (unsigned i = 0; i < insn->size(); ++i) rawBytes.push_back(insn->rawByte(i));
95     rinsn.set_raw_bytes(rawBytes);
96
97     // operand list
98     SgAsmOperandList *roperands = new SgAsmOperandList;
99     std::vector<InstructionAPI::Operand> operands;
100     insn->getOperands(operands);
101
102     // Override for LEA conversion
103     if (rinsn.get_kind() == x86_lea) {
104         assert(operands.size() == 2);
105         roperands->append_operand(convert(operands[0]));
106         
107         SgAsmExpression *o1 = convert(operands[1]);
108         // We need to wrap o1 in a memory dereference...
109         SgAsmMemoryReferenceExpression *expr = new SgAsmMemoryReferenceExpression(o1);
110         roperands->append_operand(expr);
111         
112     }
113     else if (rinsn.get_kind() == x86_push) {
114       assert(operands.size() == 2); 
115       roperands->append_operand(convert(operands[0]));
116     }
117     else if (rinsn.get_kind() == x86_pop) {
118       assert(operands.size() == 2);
119       roperands->append_operand(convert(operands[0]));
120     }
121     else {
122         for (std::vector<InstructionAPI::Operand>::iterator opi = operands.begin(),
123                  ope = operands.end();
124              opi != ope;
125              ++opi) {
126             InstructionAPI::Operand &currOperand = *opi;
127             roperands->append_operand(convert(currOperand));   
128         }
129     }
130     rinsn.set_operandList(roperands);
131
132     return rinsn;
133 }
134
135 SgAsmExpression *SymEval::convert(const InstructionAPI::Operand &operand) {
136     return convert(operand.getValue());
137 }
138
139 SgAsmExpression *SymEval::convert(const Expression::Ptr expression) {
140     ExpressionConversionVisitor visitor;
141     expression->apply(&visitor);
142     return visitor.getRoseExpression();
143 }
144
145 void ExpressionConversionVisitor::visit(BinaryFunction* binfunc) {
146     // get two children
147     vector<InstructionAST::Ptr> children;
148     binfunc->getChildren(children);
149     // convert each InstAST::Ptr to SgAsmExpression*
150     // these casts will not fail
151     SgAsmExpression *lhs = 
152       SymEval::convert(dyn_detail::boost::dynamic_pointer_cast<Expression>(children[0]));
153     SgAsmExpression *rhs =
154       SymEval::convert(dyn_detail::boost::dynamic_pointer_cast<Expression>(children[1]));
155
156     // now build either add or multiply
157     if (binfunc->isAdd())
158         roseExpression = new SgAsmBinaryAdd(lhs, rhs);
159     else if (binfunc->isMultiply())
160         roseExpression = new SgAsmBinaryMultiply(lhs, rhs);
161     else roseExpression = NULL; // error
162 }
163
164 void ExpressionConversionVisitor::visit(Immediate* immed) {
165     // no children
166
167     const Result &value = immed->eval();
168     
169     // TODO rose doesn't distinguish signed/unsigned within the value itself,
170     // only at operations?
171
172     // TODO rose doesn't handle large values (XMM?)
173
174     // build different kind of rose value object based on type
175     switch (value.type) {
176         case s8:
177         case u8:
178             roseExpression = new SgAsmByteValueExpression(value.val.u8val);
179             break;
180         case s16:
181         case u16:
182             roseExpression = new SgAsmWordValueExpression(value.val.u16val);
183             break;
184         case s32:
185         case u32:
186             roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
187             break;
188         case s64:
189         case u64:
190             roseExpression = new SgAsmQuadWordValueExpression(value.val.u64val);
191             break;
192         case sp_float:
193             roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
194             break;
195         case dp_float:
196             roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
197             break;
198         default:
199             roseExpression = NULL;
200             // error!
201     }
202 }
203
204 void ExpressionConversionVisitor::visit(RegisterAST* regast) {
205     // has no children
206
207     int rreg_class;
208     int rreg_num;
209     int rreg_pos;
210
211     unsigned int machRegID = regast->getID();
212     MachRegister machReg(machRegID);
213     machReg.getROSERegister(rreg_class, rreg_num, rreg_pos);
214
215     roseExpression = new SgAsmx86RegisterReferenceExpression((X86RegisterClass)rreg_class, 
216                                                              rreg_num, 
217                                                              (X86PositionInRegister)rreg_pos);
218 }
219
220 void ExpressionConversionVisitor::visit(Dereference* deref) {
221     // get child
222     vector<InstructionAST::Ptr> children;
223     deref->getChildren(children);
224     SgAsmExpression *toderef = 
225       SymEval::convert(dyn_detail::boost::dynamic_pointer_cast<Expression>(children[0]));
226     
227     SgAsmType *type;
228
229     // TODO fix some mismatched types?
230     // pick correct type
231     switch (deref->eval().type)
232     {
233         case s8:
234         case u8:
235             type = new SgAsmTypeByte();
236             break;
237         case s16:
238         case u16:
239             type = new SgAsmTypeWord();
240             break;
241         case s32:
242         case u32:
243             type = new SgAsmTypeDoubleWord();
244             break;
245         case s64:
246         case u64:
247             type = new SgAsmTypeQuadWord();
248             break;
249         case sp_float:
250             type = new SgAsmTypeSingleFloat();
251             break;
252         case dp_float:
253             type = new SgAsmTypeDoubleFloat();
254             break;
255         default:
256             type = NULL;
257             // error
258     }
259
260     SgAsmx86RegisterReferenceExpression *segReg = new SgAsmx86RegisterReferenceExpression(x86_regclass_segment, x86_segreg_none, x86_regpos_all);
261
262     SgAsmMemoryReferenceExpression *result = new SgAsmMemoryReferenceExpression(toderef, segReg);
263     result->set_type(type);
264     roseExpression = result;
265 }
266