Fix bug in decoding far calls.
[dyninst.git] / dataflowAPI / src / ExpressionConversionVisitor.C
1 #include "ExpressionConversionVisitor.h"
2
3 #include "Register.h"
4 #include "Immediate.h"
5 #include "BinaryFunction.h"
6 #include "Dereference.h"
7
8 #include <list>
9
10 #include "../rose/SgAsmExpression.h"
11
12 using namespace Dyninst;
13 using namespace Dyninst::InstructionAPI;
14
15 //#include "../rose/x86InstructionSemantics.h"
16 //#include "../rose/powerpcInstructionSemantics.h"
17
18 using namespace Dyninst;
19 using namespace DataflowAPI;
20
21 void ExpressionConversionVisitor::visit(InstructionAPI::Immediate* immed) {
22   // no children
23   
24   const Result &value = immed->eval();
25   
26   // TODO rose doesn't distinguish signed/unsigned within the value itself,
27   // only at operations?
28   
29   // TODO rose doesn't handle large values (XMM?)
30   
31   // build different kind of rose value object based on type
32   switch (value.type) {
33   case s8:
34   case u8:
35     roseExpression = new SgAsmByteValueExpression(value.val.u8val);
36     break;
37   case s16:
38   case u16:
39     roseExpression = new SgAsmWordValueExpression(value.val.u16val);
40     break;
41   case s32:
42   case u32:
43     roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
44     break;
45   case s48:
46   case u48:
47           // This only happens with far calls. ROSE appears to be set up to
48           // expect a 32-bit absolute destination (or doesn't handle far call at 
49           // all), so give it what it wants. 
50         roseExpression = new SgAsmDoubleWordValueExpression(value.val.u32val);
51         break;
52   case s64:
53   case u64:
54     roseExpression = new SgAsmQuadWordValueExpression(value.val.u64val);
55     break;
56   case sp_float:
57     roseExpression = new SgAsmSingleFloatValueExpression(value.val.floatval);
58     break;
59   case dp_float:
60     roseExpression = new SgAsmDoubleFloatValueExpression(value.val.dblval);
61     break;
62   default:
63     roseExpression = NULL;
64         assert(0);
65     // error!
66   }
67   m_stack.push_front(roseExpression);
68 }
69
70
71 void ExpressionConversionVisitor::visit(RegisterAST* regast) {
72   // has no children
73   
74   m_stack.push_front(archSpecificRegisterProc(regast, addr));
75   roseExpression = m_stack.front();
76   return;
77 }
78
79 void ExpressionConversionVisitor::visit(Dereference* deref) {
80   // get child
81   assert(m_stack.size());
82   SgAsmExpression *toderef = m_stack.front();
83   m_stack.pop_front();
84   if(toderef == NULL) {
85     roseExpression = NULL;
86     return;
87   }
88   SgAsmType *type;
89
90   // TODO fix some mismatched types?
91   // pick correct type
92   switch (deref->eval().type)
93     {
94     case s8:
95     case u8:
96       type = new SgAsmTypeByte();
97       break;
98     case s16:
99     case u16:
100       type = new SgAsmTypeWord();
101       break;
102     case s32:
103     case u32:
104       type = new SgAsmTypeDoubleWord();
105       break;
106     case s64:
107     case u64:
108       type = new SgAsmTypeQuadWord();
109       break;
110     case sp_float:
111       type = new SgAsmTypeSingleFloat();
112       break;
113     case dp_float:
114       type = new SgAsmTypeDoubleFloat();
115       break;
116     default:
117       type = NULL;
118       // error
119     }
120
121
122   SgAsmExpression *segReg = makeSegRegExpr();
123   SgAsmMemoryReferenceExpression* result = new SgAsmMemoryReferenceExpression(toderef, segReg);
124   result->set_type(type);
125   roseExpression = result;
126 }
127
128 SgAsmExpression* ExpressionConversionVisitor::archSpecificRegisterProc(InstructionAPI::RegisterAST* regast, uint64_t addr)
129 {
130   MachRegister machReg = regast->getID();
131   if(machReg.isPC()) return NULL;
132
133   switch(arch) {
134   case Arch_x86: {
135     int regClass;
136     int regNum;
137     int regPos;
138    
139     MachRegister machReg = regast->getID();
140     if(machReg.isPC()) {
141       // ideally this would be symbolic
142       SgAsmExpression *constAddrExpr = new SgAsmDoubleWordValueExpression(addr);
143       return constAddrExpr;
144     } 
145     machReg.getROSERegister(regClass, regNum, regPos);
146     
147     return new SgAsmx86RegisterReferenceExpression((X86RegisterClass) regClass,
148                                                    regNum, 
149                                                    (X86PositionInRegister) regPos);
150     break;
151   }
152   case Arch_ppc32: {
153     int regClass;
154     int regNum;
155     int regGran = powerpc_condreggranularity_whole;
156
157     machReg.getROSERegister(regClass, regNum, regGran);
158
159     return new SgAsmPowerpcRegisterReferenceExpression((PowerpcRegisterClass) regClass, 
160                                                        regNum, 
161                                                        (PowerpcConditionRegisterAccessGranularity) regGran);
162     break;
163   }
164   default:
165     return NULL;
166     break;
167   }
168 }
169
170 SgAsmExpression* ExpressionConversionVisitor::makeSegRegExpr()
171 {
172   if (arch == Arch_x86) {
173     return new SgAsmx86RegisterReferenceExpression(x86_regclass_segment,
174                                                    x86_segreg_none, x86_regpos_all);
175   }
176   else {
177     return NULL;
178   }
179 }
180
181 /////////////// Visitor class /////////////////
182
183 void ExpressionConversionVisitor::visit(BinaryFunction* binfunc) {
184   assert(m_stack.size() >= 2);
185   SgAsmExpression *rhs = m_stack.front();
186   m_stack.pop_front();
187   SgAsmExpression *lhs = m_stack.front();
188   m_stack.pop_front();
189   // If the RHS didn't convert, that means it should disappear
190   // And we are just left with the LHS
191   if(!rhs && !lhs) {
192     roseExpression = NULL;
193   }
194   else if (!rhs) {
195     roseExpression = lhs;
196   }
197   else if(!lhs) {
198     roseExpression = rhs;
199   }
200   else {
201     // now build either add or multiply
202     if (binfunc->isAdd())
203       roseExpression = new SgAsmBinaryAdd(lhs, rhs);
204     else if (binfunc->isMultiply())
205       roseExpression = new SgAsmBinaryMultiply(lhs, rhs);
206     else roseExpression = NULL; // error
207   }
208   m_stack.push_front(roseExpression);
209 }