Enable symbolic evaluation on x86 64-bit binaries
[dyninst.git] / dataflowAPI / src / ExpressionConversionVisitor.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "ExpressionConversionVisitor.h"
31
32 #include "Register.h"
33 #include "Immediate.h"
34 #include "BinaryFunction.h"
35 #include "Dereference.h"
36
37 #include <list>
38
39 #include "../rose/SgAsmExpression.h"
40
41 using namespace Dyninst;
42 using namespace Dyninst::InstructionAPI;
43
44 //#include "../rose/x86InstructionSemantics.h"
45 //#include "../rose/powerpcInstructionSemantics.h"
46
47 using namespace Dyninst;
48 using namespace DataflowAPI;
49
50 void ExpressionConversionVisitor::visit(InstructionAPI::Immediate* immed) {
51   // no children
52   
53   const Result &value = immed->eval();
54   
55   // TODO rose doesn't distinguish signed/unsigned within the value itself,
56   // only at operations?
57   
58   // TODO rose doesn't handle large values (XMM?)
59   
60   // build different kind of rose value object based on type
61   switch (value.type) {
62   case s8:
63   case u8:
64     roseExpression = new SgAsmByteValueExpression(value.val.u8val);
65     break;
66   case s16:
67   case u16:
68     roseExpression = new SgAsmWordValueExpression(value.val.u16val);
69     break;
70   case s32:
71   case u32:
72     roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
73     break;
74   case s48:
75   case u48:
76           // This only happens with far calls. ROSE appears to be set up to
77           // expect a 32-bit absolute destination (or doesn't handle far call at 
78           // all), so give it what it wants. 
79         roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
80         break;
81   case s64:
82   case u64:
83     roseExpression = new SgAsmQuadWordValueExpression(value.val.u64val);
84     break;
85   case sp_float:
86     roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
87     break;
88   case dp_float:
89     roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
90     break;
91   default:
92     roseExpression = NULL;
93         assert(0);
94     // error!
95   }
96   m_stack.push_front(roseExpression);
97 }
98
99
100 void ExpressionConversionVisitor::visit(RegisterAST* regast) {
101   // has no children
102   
103   m_stack.push_front(archSpecificRegisterProc(regast, addr));
104   roseExpression = m_stack.front();
105   return;
106 }
107
108 void ExpressionConversionVisitor::visit(Dereference* deref) {
109   // get child
110   assert(m_stack.size());
111   SgAsmExpression *toderef = m_stack.front();
112   m_stack.pop_front();
113   if(toderef == NULL) {
114     roseExpression = NULL;
115     return;
116   }
117   SgAsmType *type;
118
119   // TODO fix some mismatched types?
120   // pick correct type
121   switch (deref->eval().type)
122     {
123     case s8:
124     case u8:
125       type = new SgAsmTypeByte();
126       break;
127     case s16:
128     case u16:
129       type = new SgAsmTypeWord();
130       break;
131     case s32:
132     case u32:
133       type = new SgAsmTypeDoubleWord();
134       break;
135     case s64:
136     case u64:
137       type = new SgAsmTypeQuadWord();
138       break;
139     case sp_float:
140       type = new SgAsmTypeSingleFloat();
141       break;
142     case dp_float:
143       type = new SgAsmTypeDoubleFloat();
144       break;
145     default:
146       type = NULL;
147       // error
148     }
149
150
151   SgAsmExpression *segReg = makeSegRegExpr();
152   SgAsmMemoryReferenceExpression* result = new SgAsmMemoryReferenceExpression(toderef, segReg);
153   result->set_type(type);
154   roseExpression = result;
155 }
156
157 SgAsmExpression* ExpressionConversionVisitor::archSpecificRegisterProc(InstructionAPI::RegisterAST* regast, uint64_t addr)
158 {
159
160   MachRegister machReg = regast->getID();  
161
162   switch(arch) {
163   case Arch_x86:
164   case Arch_x86_64: {
165     int regClass;
166     int regNum;
167     int regPos;
168    
169     MachRegister machReg = regast->getID();
170     if(machReg.isPC()) {
171       // ideally this would be symbolic
172       SgAsmExpression *constAddrExpr;
173       if (arch == Arch_x86) 
174           constAddrExpr = new SgAsmDoubleWordValueExpression(addr);
175       else
176           constAddrExpr = new SgAsmQuadWordValueExpression(addr);
177
178       return constAddrExpr;
179     } 
180     machReg.getROSERegister(regClass, regNum, regPos);
181     
182     return new SgAsmx86RegisterReferenceExpression((X86RegisterClass) regClass,
183                                                    regNum, 
184                                                    (X86PositionInRegister) regPos);
185     break;
186   }
187   case Arch_ppc32: {
188     int regClass;
189     int regNum;
190     int regGran = powerpc_condreggranularity_whole;
191
192     machReg.getROSERegister(regClass, regNum, regGran);
193
194     return new SgAsmPowerpcRegisterReferenceExpression((PowerpcRegisterClass) regClass, 
195                                                        regNum, 
196                                                        (PowerpcConditionRegisterAccessGranularity) regGran);
197     break;
198   }
199   default:
200     return NULL;
201     break;
202   }
203 }
204
205 SgAsmExpression* ExpressionConversionVisitor::makeSegRegExpr()
206 {
207   if (arch == Arch_x86 || arch == Arch_x86_64) {
208     return new SgAsmx86RegisterReferenceExpression(x86_regclass_segment,
209                                                    x86_segreg_none, x86_regpos_all);
210   }
211   else {
212     return NULL;
213   }
214 }
215
216 /////////////// Visitor class /////////////////
217
218 void ExpressionConversionVisitor::visit(BinaryFunction* binfunc) {
219   assert(m_stack.size() >= 2);
220   SgAsmExpression *rhs = m_stack.front();
221   m_stack.pop_front();
222   SgAsmExpression *lhs = m_stack.front();
223   m_stack.pop_front();
224   // If the RHS didn't convert, that means it should disappear
225   // And we are just left with the LHS
226   if(!rhs && !lhs) {
227     roseExpression = NULL;
228   }
229   else if (!rhs) {
230     roseExpression = lhs;
231   }
232   else if(!lhs) {
233     roseExpression = rhs;
234   }
235   else {
236     // now build either add or multiply
237     if (binfunc->isAdd())
238       roseExpression = new SgAsmBinaryAdd(lhs, rhs);
239     else if (binfunc->isMultiply())
240       roseExpression = new SgAsmBinaryMultiply(lhs, rhs);
241     else roseExpression = NULL; // error
242   }
243   m_stack.push_front(roseExpression);
244 }