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