GCC 4.8 build fixes: ensure all extern template declarations are in fact extern'ed...
[dyninst.git] / dyninstAPI / src / BPatch_memoryAccessAdapter.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
31 #include "BPatch_memoryAccessAdapter.h"
32 #include "BPatch_memoryAccess_NP.h"
33 #include "Instruction.h"
34 #include "Immediate.h"
35 #include "Register.h"
36 #include "Dereference.h"
37
38 #include "common/src/arch.h"
39
40 #include "legacy-instruction.h"
41
42 using namespace Dyninst;
43 using namespace InstructionAPI;
44
45 extern template class boost::shared_ptr<InstructionAST>;
46
47 BPatch_memoryAccess* BPatch_memoryAccessAdapter::convert(Instruction::Ptr insn,
48                                                          Address current, bool is64)
49 {
50 #if defined(arch_x86) || defined(arch_x86_64)
51     static unsigned int log2[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3 };
52     
53   // TODO 16-bit registers
54     
55   int nac = 0;
56     
57   ia32_memacc mac[3];
58   ia32_condition cnd;
59   ia32_instruction i(mac, &cnd);
60     
61   const unsigned char* addr = reinterpret_cast<const unsigned char*>(insn->ptr());
62   BPatch_memoryAccess* bmap = BPatch_memoryAccess::none;
63
64   ia32_set_mode_64(is64);
65   
66   ia32_decode(IA32_DECODE_MEMACCESS|IA32_DECODE_CONDITION, addr, i);
67   
68   bool first = true;
69
70   for(int j=0; j<3; ++j) {
71     ia32_memacc& mac = const_cast<ia32_memacc&>(i.getMac(j));
72     const ia32_condition& cond = i.getCond();
73     int bmapcond = cond.is ? cond.tttn : -1;
74     if(mac.is) {
75
76       // here, we can set the correct address for RIP-relative addressing
77       if (mac.regs[0] == mRIP) {
78         mac.imm = current + insn->size() + mac.imm;
79       }
80
81       if(first) {
82         if(mac.prefetch) {
83           if(mac.prefetchlvl > 0) // Intel
84             bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
85                                            false, false,
86                                            mac.imm, mac.regs[0], mac.regs[1], mac.scale,
87                                            0, -1, -1, 0,
88                                            bmapcond, false, mac.prefetchlvl);
89           else // AMD
90             bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
91                                            false, false,
92                                            mac.imm, mac.regs[0], mac.regs[1], mac.scale,
93                                            0, -1, -1, 0,
94                                            bmapcond, false, mac.prefetchstt + IA32AMDprefetch);
95         }
96         else switch(mac.sizehack) { // translation to pseudoregisters
97         case 0:
98           bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
99                                          mac.read, mac.write,
100                                          mac.size, mac.imm, mac.regs[0], mac.regs[1], mac.scale, 
101                                          bmapcond, mac.nt);
102           break;
103         case shREP: // use ECX register to compute final size as mac.size * ECX
104           bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
105                                          mac.read, mac.write,
106                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
107                                          0, -1, 1 , log2[mac.size],
108                                          bmapcond, false);
109           break;
110         case shREPESCAS:
111           bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
112                                          mac.read, mac.write,
113                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
114                                          0, -1, IA32_ESCAS, log2[mac.size],
115                                          bmapcond, false);
116           break;
117         case shREPNESCAS:
118           bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
119                                          mac.read, mac.write,
120                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
121                                          0, -1, IA32_NESCAS, log2[mac.size],
122                                          bmapcond, false);
123           break;
124         case shREPECMPS:
125           bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
126                                          mac.read, mac.write,
127                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
128                                          0, -1, IA32_ECMPS, log2[mac.size],
129                                          bmapcond, false);
130           break;
131         case shREPNECMPS:
132           bmap = new BPatch_memoryAccess(new internal_instruction(NULL), current,
133                                          mac.read, mac.write,
134                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
135                                          0, -1, IA32_NECMPS, log2[mac.size],
136                                          bmapcond, false);
137           break;
138         default:
139           assert(!"Unknown size hack");
140         }
141         first = false;
142       }
143       else
144         switch(mac.sizehack) { // translation to pseudoregisters
145         case 0:
146           bmap->set2nd(mac.read, mac.write, mac.size, mac.imm,
147                        mac.regs[0], mac.regs[1], mac.scale);
148           break;
149         case shREP: // use ECX register to compute final size as mac.size * ECX
150           bmap->set2nd(mac.read, mac.write,
151                        mac.imm, mac.regs[0], mac.regs[1], mac.scale,
152                        0, -1, 1 , log2[mac.size],
153                        bmapcond, false);
154           break;
155         case shREPESCAS:
156         case shREPNESCAS:
157           assert(!"Cannot happen");
158           break;
159         case shREPECMPS:
160           bmap->set2nd(mac.read, mac.write,
161                        mac.imm, mac.regs[0], mac.regs[1], mac.scale,
162                        0, -1, IA32_ECMPS, log2[mac.size],
163                        bmapcond, false);
164           break;
165         case shREPNECMPS:
166           //fprintf(stderr, "In set2nd[shREPNECMPS]!!!\n");
167           bmap->set2nd(mac.read, mac.write,
168                        mac.imm, mac.regs[0], mac.regs[1], mac.scale,
169                        0, -1, IA32_NECMPS, log2[mac.size],
170                        bmapcond, false);
171           break;
172         default:
173           assert(!"Unknown size hack");
174         }
175       ++nac;
176     }
177   }
178   assert(nac < 3);
179   return bmap;
180 #else
181     (void) is64; //Silence warnings
182     std::vector<Operand> operands;
183     insn->getOperands(operands);
184     for(std::vector<Operand>::iterator op = operands.begin();
185         op != operands.end();
186        ++op)
187     {
188         bool isLoad = op->readsMemory();
189         bool isStore = op->writesMemory();
190         if(isLoad || isStore)
191         {
192             op->getValue()->apply(this);
193             if(insn->getOperation().getID() == power_op_lmw ||
194                insn->getOperation().getID() == power_op_stmw)
195             {
196                 RegisterAST::Ptr byteOverride =
197                         boost::dynamic_pointer_cast<RegisterAST>(insn->getOperand(0).getValue());
198                 assert(byteOverride);
199                 MachRegister base = byteOverride->getID().getBaseRegister();
200                 unsigned int converted = base.val() & 0xFFFF;
201                 bytes = (32 - converted) << 2;
202             }
203             if(insn->getOperation().getID() == power_op_lswi ||
204                insn->getOperation().getID() == power_op_stswi)
205             {
206                 Immediate::Ptr byteOverride =
207                         boost::dynamic_pointer_cast<Immediate>(insn->getOperand(2).getValue());
208                 assert(byteOverride);
209                 bytes = byteOverride->eval().convert<unsigned int>();
210                 if(bytes == 0) bytes = 32;
211             }
212             if(insn->getOperation().getID() == power_op_lswx ||
213                insn->getOperation().getID() == power_op_stswx)
214             {
215                 return new BPatch_memoryAccess(new internal_instruction(NULL), current, isLoad, isStore, (long)0, ra, rb, (long)0, 9999, -1);
216             }
217             return new BPatch_memoryAccess(new internal_instruction(NULL), current, isLoad, isStore,
218                                        bytes, imm, ra, rb);
219         }
220     }
221     return NULL;
222 #endif
223 }
224
225
226 void BPatch_memoryAccessAdapter::visit(BinaryFunction* )
227 {
228     
229 }
230
231
232 void BPatch_memoryAccessAdapter::visit(Dereference* d)
233 {
234     bytes = d->size();
235 }
236
237 void BPatch_memoryAccessAdapter::visit(RegisterAST* r)
238 {
239     MachRegister base = r->getID().getBaseRegister();
240     unsigned int converted = base.val() & 0xFFFF;
241     if((ra == -1) && !setImm) {
242         ra = converted;
243         return;
244     } else if(rb == -1) {
245         rb = converted;
246         if(ra == 0) ra = -1;
247         return;
248     }
249     else
250     {
251         fprintf(stderr, "ASSERT: only two registers used in a power load/store calc!\n");
252         assert(0);
253     }        
254 }
255
256 void BPatch_memoryAccessAdapter::visit(Immediate* i)
257 {
258     imm = i->eval().convert<long>();
259     setImm = true;
260 }
261