Merge branch 'master' of https://github.com/dyninst/dyninst
[dyninst.git] / dataflowAPI / src / RoseInsnFactory.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 "RoseInsnFactory.h"
31 //#include "../rose/x86InstructionSemantics.h"
32 //#include "../rose/powerpcInstructionSemantics.h"
33
34 #include "Instruction.h"
35 #include "Dereference.h"
36 #include "Immediate.h"
37
38 #include "../rose/SgAsmInstruction.h"
39 #include "../rose/SgAsmPowerpcInstruction.h"
40 #include "../rose/SgAsmArmv8Instruction.h"
41 #include "../rose/SgAsmx86Instruction.h"
42 #include "../rose/SgAsmExpression.h"
43
44 #include "ExpressionConversionVisitor.h"
45
46 // Assume Windows/MSVC is little-endian
47
48 #if defined(_MSC_VER)
49 #define htobe _byteswap_ulong
50 #endif
51
52 using namespace Dyninst;
53 using namespace InstructionAPI;
54 using namespace DataflowAPI;
55
56 SgAsmInstruction *RoseInsnFactory::convert(const InstructionAPI::Instruction::Ptr &insn, uint64_t addr) {
57   SgAsmInstruction *rinsn = createInsn();
58   
59   rinsn->set_address(addr);
60   rinsn->set_mnemonic(insn->format());
61   setOpcode(rinsn, insn->getOperation().getID(), insn->getOperation().getPrefixID(), insn->getOperation().format());
62
63   // semantics don't support 64-bit code
64   setSizes(rinsn);
65
66   //rinsn->set_operandSize(x86_insnsize_32);
67   //rinsn->set_addressSize(x86_insnsize_32);
68   
69   std::vector<unsigned char> rawBytes;
70   for (unsigned i = 0; i < insn->size(); ++i) rawBytes.push_back(insn->rawByte(i));
71   rinsn->set_raw_bytes(rawBytes);
72   
73   // operand list
74   SgAsmOperandList *roperands = new SgAsmOperandList;
75   
76 //   std::cerr << "Converting " << insn->format(addr) << " @" << std::hex << addr << std::dec << std::endl;
77   
78 //   std::cerr << "checking instruction: " << insn->format(addr) << " for special handling" << std::endl;
79   if (handleSpecialCases(insn->getOperation().getID(), rinsn, roperands)) {
80       rinsn->set_operandList(roperands);
81       return rinsn;
82   }
83
84 //   std::cerr << "no special handling by opcode, checking if we should mangle operands..." << std::endl;
85   std::vector<InstructionAPI::Operand> operands;
86   insn->getOperands(operands);
87 //   std::cerr << "\t " << operands.size() << " operands" << std::endl;
88   massageOperands(insn, operands);
89   int i = 0;
90 //   std::cerr << "converting insn " << insn->format(addr) << std::endl;
91   for (std::vector<InstructionAPI::Operand>::iterator opi = operands.begin();
92        opi != operands.end();
93        ++opi, ++i) {
94       InstructionAPI::Operand &currOperand = *opi;
95 //       std::cerr << "Converting operand " << currOperand.format(arch(), addr) << std::endl;
96       roperands->append_operand(convertOperand(currOperand.getValue(), addr, insn->size()));
97   }  
98   rinsn->set_operandList(roperands);
99   return rinsn;
100 }
101
102 SgAsmExpression *RoseInsnFactory::convertOperand(const Expression::Ptr expression, int64_t addr, size_t insnSize) {
103   if(!expression) return NULL;
104   ExpressionConversionVisitor visitor(arch(), addr, insnSize);
105   expression->apply(&visitor);
106   return visitor.getRoseExpression();
107 }
108
109 ///////////// X86 //////////////////
110
111 SgAsmInstruction *RoseInsnX86Factory::createInsn() {
112   return new SgAsmx86Instruction;
113 }
114
115 // Note: convertKind is defined in convertOpcodes.C
116
117 void RoseInsnX86Factory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID prefix, std::string) {
118   SgAsmx86Instruction *tmp = static_cast<SgAsmx86Instruction *>(insn);
119   
120   tmp->set_kind(convertKind(opcode, prefix));
121 }
122
123 void RoseInsnX86Factory::setSizes(SgAsmInstruction *insn) {
124   SgAsmx86Instruction *tmp = static_cast<SgAsmx86Instruction *>(insn);
125   if (a == Arch_x86_64) {
126       tmp->set_operandSize(x86_insnsize_64);
127       tmp->set_addressSize(x86_insnsize_64);
128   } else {
129       tmp->set_operandSize(x86_insnsize_32);
130       tmp->set_addressSize(x86_insnsize_32);
131   }
132 }
133
134 bool RoseInsnX86Factory::handleSpecialCases(entryID, SgAsmInstruction *, SgAsmOperandList *) {
135   // Does nothing?
136
137   return false;
138 }
139
140 void RoseInsnX86Factory::massageOperands(const InstructionAPI::Instruction::Ptr &insn, 
141                                          std::vector<InstructionAPI::Operand> &operands) {
142   switch (insn->getOperation().getID()) {
143   case e_lea: {
144     // ROSE expects there to be a "memory reference" statement wrapping the
145     // address calculation. It then unwraps it. 
146     Dereference::Ptr tmp = Dereference::Ptr(new Dereference(operands[1].getValue(), u32));
147     operands[1] = Operand(tmp, operands[1].isRead(), operands[1].isWritten());
148     operands.resize(2);
149     break;  
150   }
151   case e_push:
152   case e_pop:
153     operands.resize(1);
154     break;
155   case e_cmpxch:
156     operands.resize(2);
157     break;
158   case e_movsb:
159   case e_movsd:
160   case e_movsw:
161     // No operands
162     operands.clear();
163     break;
164   case e_cmpsb:
165   case e_cmpsw:
166   case e_cmpsd:
167     // No operands
168     operands.clear();
169     break;
170   case e_scasb:
171   case e_scasd:
172   case e_scasw:
173     // Same here
174     operands.clear();
175     break;
176   case e_stosb:
177   case e_stosd:
178   case e_stosw:
179     // Also, no operands
180     operands.clear();
181     break;
182   case e_jcxz_jec:
183     operands.resize(1);
184     break;
185   case e_cbw:
186   case e_cwde:
187   case e_cdq:
188     // Nada
189     operands.clear();
190     break;
191   case e_popad:
192   case e_pushfd:
193     operands.clear();
194     break;
195   case e_lodsd:
196   case e_lodsb:
197   case e_lodsw:
198       operands.clear();
199       break;
200   case e_pushad:
201       operands.clear();
202       break;
203   case e_loop:
204   case e_loope:
205   case e_loopn:
206       operands.resize(1);
207       break;
208   case e_ret_far:
209   case e_ret_near:
210           if (operands.size() == 2) {
211                   operands[0]=operands[1];
212           }
213           operands.resize(1);
214           break;
215   case e_aaa:
216   case e_aas: 
217           // ROSE does not expect implicit operand rax/eax to be treated as an operand
218           operands.clear();
219           break;
220   case e_aad:
221   case e_aam: {
222           // ROSE does not expect implicit operand rax/eax to be treated as an operand
223           std::set<RegisterAST::Ptr> regs;
224           operands[0].getReadSet(regs);
225           operands[0].getWriteSet(regs);                  
226           if (!regs.empty()) {        
227                       operands[0] = operands[1];
228           }
229           operands.resize(1);
230           break;
231   }
232   case e_div:
233   case e_idiv:
234   case e_imul:
235   case e_mul:
236     // remove implicit operands.
237     if (operands.size() == 3) {
238       operands[0] = operands[2];
239       operands.resize(1);
240     }
241     break;
242   default:
243     break;
244   }
245 }
246
247
248 //////////// PPC ///////////////////
249 // Note: convertKind is defined in convertOpcodes.C
250
251 SgAsmInstruction *RoseInsnPPCFactory::createInsn() {
252   return new SgAsmPowerpcInstruction;
253 }
254
255 void RoseInsnPPCFactory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID /*prefix*/, std::string mnem) {
256   SgAsmPowerpcInstruction *tmp = static_cast<SgAsmPowerpcInstruction *>(insn);
257   kind = convertKind(opcode, mnem);
258   tmp->set_kind(kind);
259 }
260
261
262 void RoseInsnPPCFactory::setSizes(SgAsmInstruction *) {
263 }
264
265 bool RoseInsnPPCFactory::handleSpecialCases(entryID iapi_opcode,
266                                             SgAsmInstruction *insn,
267                                             SgAsmOperandList *rose_operands) {
268   SgAsmPowerpcInstruction *rose_insn = static_cast<SgAsmPowerpcInstruction *>(insn);
269
270   switch(iapi_opcode) {
271   case power_op_b:
272   case power_op_bc:
273   case power_op_bcctr:
274   case power_op_bclr: {
275     unsigned int raw = 0;
276     int branch_target = 0;
277     unsigned int bo = 0, bi = 0;
278     std::vector<unsigned char> bytes = rose_insn->get_raw_bytes();
279     for(unsigned i = 0; i < bytes.size(); i++) {
280       raw = raw << 8;
281       raw |= bytes[i];
282     }
283 #ifdef os_windows
284     // Visual Studio doensn't define htobe32, so we assume that Windows is always little endian.
285     raw = _byteswap_ulong(raw);
286 #else
287     raw = htobe32(raw);
288 #endif
289     bool isAbsolute = (bool)(raw & 0x00000002);
290     bool isLink = (bool)(raw & 0x00000001);
291     rose_insn->set_kind(makeRoseBranchOpcode(iapi_opcode, isAbsolute, isLink));
292     if(power_op_b == iapi_opcode) {
293       branch_target = ((raw >> 2) & 0x00FFFFFF) << 2;
294       branch_target = (branch_target << 8) >> 8;
295     } else {
296       if(power_op_bc == iapi_opcode) {
297         branch_target = ((raw >> 2) & 0x00003FFF) << 2;
298         branch_target = (branch_target << 18) >> 18;
299         //cerr << "14-bit branch target: " << branch_target << endl;
300       }
301       bo = ((raw >> 21) & 0x0000001F);
302       bi = ((raw >> 16) & 0x0000001F);
303       rose_operands->append_operand(new SgAsmByteValueExpression(bo));
304       rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_cr, bi,
305                                                                                 powerpc_condreggranularity_bit));
306     }
307     if(branch_target) {
308       rose_operands->append_operand(new SgAsmDoubleWordValueExpression(branch_target));
309     } else if(power_op_bcctr == iapi_opcode) {
310       rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_spr, powerpc_spr_ctr));
311     } else {
312       assert(power_op_bclr == iapi_opcode);
313       rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_spr, powerpc_spr_lr));
314     }
315     return true;
316   }
317     break;
318   case power_op_sc:
319   case power_op_svcs: {
320     //cerr << "special-casing syscall insn" << endl;
321     unsigned int raw = 0;
322     std::vector<unsigned char> bytes = rose_insn->get_raw_bytes();
323     for(unsigned i = 0; i < bytes.size(); i++) {
324       raw = raw << 8;
325       raw |= bytes[i];
326     }
327     unsigned int lev = (raw >> 5) & 0x7F;
328     rose_operands->append_operand(new SgAsmByteValueExpression(lev));
329     //cerr << "LEV = " << lev << endl;
330     return true;
331   }
332   default:
333     return false;
334   }
335   
336 }  
337
338 void RoseInsnPPCFactory::massageOperands(const InstructionAPI::Instruction::Ptr &insn, 
339                                          std::vector<InstructionAPI::Operand> &operands) {
340   /*
341   if(insn->writesMemory())
342     std::swap(operands[0], operands[1]);
343   */
344   entryID opcode = insn->getOperation().getID();
345   // Anything that's writing RA, ROSE expects in RA, RS, RB/immediates form.
346   // Any store, however, ROSE expects in RS, RA, RB/displacement form.  Very confusing,
347   // but we handle it cleanly here.
348   if(!operands[0].isWritten() && operands.size() >= 2 &&
349      operands[1].isWritten() && !operands[1].writesMemory()) {
350     //std::cerr << "swapping RS and RA in " << insn->format() << std::endl;
351     std::swap(operands[0], operands[1]);
352   }
353   if(opcode == power_op_cmp ||
354      opcode == power_op_cmpl ||
355      opcode == power_op_cmpi ||
356      opcode == power_op_cmpli) {
357     operands.push_back(Operand(Immediate::makeImmediate(Result(u8, 1)), false, false));
358     std::swap(operands[2], operands[3]);
359     std::swap(operands[1], operands[2]);
360   }
361   if(insn->getOperation().format().find(".") != std::string::npos &&
362      insn->getOperation().getID() != power_op_stwcx_rc) {
363     operands.pop_back();
364   }
365
366   // Convert to ROSE so we can use numeric greater than/less than
367
368   if(kind >= powerpc_lbz && kind <= powerpc_lwzx) {
369     operands.resize(2);
370   }
371   if(kind >= powerpc_stb && kind <= powerpc_stwx) {
372     operands.resize(2);
373   }
374
375   return;
376 }
377
378 SgAsmInstruction *RoseInsnArmv8Factory::createInsn() {
379   return new SgAsmArmv8Instruction;
380 }
381
382 void RoseInsnArmv8Factory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID, std::string) {
383   SgAsmArmv8Instruction *tmp = static_cast<SgAsmArmv8Instruction *>(insn);
384   tmp->set_kind(convertKind(opcode));
385 }
386
387 bool RoseInsnArmv8Factory::handleSpecialCases(entryID, SgAsmInstruction *, SgAsmOperandList *) {
388   return false;
389 }
390
391 void RoseInsnArmv8Factory::massageOperands(const InstructionAPI::Instruction::Ptr &,
392                                            std::vector <InstructionAPI::Operand> &) {
393   return;
394 }