Update copyright to LGPL on all files
[dyninst.git] / instructionAPI / src / Instruction.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include <stdio.h>
33 #include <string>
34 #include "../h/InstructionCategories.h"
35 #include "../h/Instruction.h"
36 #include "../h/Register.h"
37 #include "../h/Operation.h"
38 #include "InstructionDecoder.h"
39 #include "Dereference.h"
40 #include <boost/iterator/indirect_iterator.hpp>
41 #include <iostream>
42 #include "arch-x86.h"
43 using namespace std;
44
45 #include <boost/pool/pool.hpp>
46
47 namespace Dyninst
48 {
49   namespace InstructionAPI
50   {
51
52     bool readsOperand(unsigned int opsema, unsigned int i)
53     {
54       switch(opsema) {
55       case s1R2R:
56         return (i == 0 || i == 1);
57       case s1R:
58       case s1RW:
59         return i == 0;
60       case s1W:
61         return false;
62       case s1W2RW:
63       case s1W2R:   // second operand read, first operand written (e.g. mov)
64         return i == 1;
65       case s1RW2R:  // two operands read, first written (e.g. add)
66       case s1RW2RW: // e.g. xchg
67       case s1R2RW:
68         return i == 0 || i == 1;
69       case s1W2R3R: // e.g. imul
70       case s1W2RW3R: // some mul
71       case s1W2R3RW: // (stack) push & pop
72         return i == 1 || i == 2;
73       case s1W2W3R: // e.g. les
74         return i == 2;
75       case s1RW2R3R: // shld/shrd
76       case s1RW2RW3R: // [i]div, cmpxch8b
77         return i == 0 || i == 1 || i == 2;
78         break;
79       case sNONE:
80       default:
81         return false;
82       }
83       
84     }
85       
86     bool writesOperand(unsigned int opsema, unsigned int i)
87     {
88       switch(opsema) {
89       case s1R2R:
90       case s1R:
91         return false;
92       case s1RW:
93       case s1W:
94       case s1W2R:   // second operand read, first operand written (e.g. mov)
95       case s1RW2R:  // two operands read, first written (e.g. add)
96       case s1W2R3R: // e.g. imul
97       case s1RW2R3R: // shld/shrd
98         return i == 0;
99       case s1R2RW:
100         return i == 1;
101       case s1W2RW:
102       case s1RW2RW: // e.g. xchg
103       case s1W2RW3R: // some mul
104       case s1W2W3R: // e.g. les
105       case s1RW2RW3R: // [i]div, cmpxch8b
106         return i == 0 || i == 1;
107       case s1W2R3RW: // (stack) push & pop
108         return i == 0 || i == 2;
109       case sNONE:
110       default:
111         return false;
112       }
113     }    
114
115     INSTRUCTION_EXPORT Instruction::Instruction(Operation::Ptr what, 
116                              size_t size, const unsigned char* raw)
117       : m_InsnOp(what), m_Valid(true)
118     {
119       copyRaw(size, raw);
120       
121     }
122
123     void Instruction::copyRaw(size_t size, const unsigned char* raw)
124     {
125       
126       if(raw)
127       {
128         m_size = size;
129         m_RawInsn.small_insn = 0;
130         if(size <= sizeof(unsigned int))
131         {
132           memcpy(&m_RawInsn, raw, size);
133         }
134         else
135         {
136           m_RawInsn.large_insn = new unsigned char[size];
137           memcpy(m_RawInsn.large_insn, raw, size);
138         }
139       }
140       else
141       {
142         m_size = 0;
143         m_RawInsn.small_insn = 0;
144       }
145     }
146     
147     void Instruction::decodeOperands() const
148     {
149       static InstructionDecoder d;
150       const unsigned char* buffer = reinterpret_cast<const unsigned char*>(&(m_RawInsn.small_insn));
151       if(m_size > sizeof(unsigned int)) {
152         buffer = m_RawInsn.large_insn;
153       }
154       std::vector<Expression::Ptr> opSrc;
155       d.resetBuffer(buffer, size());
156       d.doIA32Decode();
157       d.decodeOperands(opSrc);
158       m_Operands.reserve(opSrc.size());
159       unsigned int opsema = d.decodedInstruction->getEntry()->opsema & 0xFF;
160       
161       for(unsigned int i = 0;
162           i < opSrc.size();
163           ++i)
164       {
165         m_Operands.push_back(Operand(opSrc[i], readsOperand(opsema, i), writesOperand(opsema, i)));
166       }
167     }
168     
169     INSTRUCTION_EXPORT Instruction::Instruction(Operation::Ptr what, 
170                              const std::vector<Expression::Ptr>& operandSource,
171                              size_t size, const unsigned char* raw, unsigned int opsema)
172       : m_InsnOp(what), m_Valid(true)
173     {
174       std::vector<Expression::Ptr>::const_iterator curVC;
175       m_Operands.reserve(operandSource.size());
176       
177       for(unsigned int i = 0;
178           i < operandSource.size();
179           ++i)
180       {
181         m_Operands.push_back(Operand(operandSource[i], readsOperand(opsema, i), writesOperand(opsema, i)));
182       }
183       copyRaw(size, raw);
184       
185     }
186     INSTRUCTION_EXPORT Instruction::Instruction() :
187       m_Valid(false), m_size(0)
188     {
189     }
190     
191     INSTRUCTION_EXPORT Instruction::~Instruction()
192     {
193       if(m_size > sizeof(unsigned int))
194       {
195         delete[] m_RawInsn.large_insn;
196       }
197       
198     }
199
200     INSTRUCTION_EXPORT Instruction::Instruction(const Instruction& o)
201     {
202       m_Operands.clear();
203       //m_Operands.reserve(o.m_Operands.size());
204       //std::copy(o.m_Operands.begin(), o.m_Operands.end(), std::back_inserter(m_Operands));
205       if(m_size > sizeof(unsigned int)) 
206       {
207         delete[] m_RawInsn.large_insn;
208       }
209       
210       m_size = o.m_size;
211       if(o.m_size > sizeof(unsigned int))
212       {
213         m_RawInsn.large_insn = new unsigned char[o.m_size];
214         memcpy(m_RawInsn.large_insn, o.m_RawInsn.large_insn, m_size);
215       }
216       else
217       {
218         m_RawInsn.small_insn = o.m_RawInsn.small_insn;
219       }
220
221       m_InsnOp = o.m_InsnOp;
222       m_Valid = o.m_Valid;
223     }
224
225     INSTRUCTION_EXPORT const Instruction& Instruction::operator=(const Instruction& rhs)
226     {
227       m_Operands.clear();
228       //m_Operands.reserve(rhs.m_Operands.size());
229       //std::copy(rhs.m_Operands.begin(), rhs.m_Operands.end(), std::back_inserter(m_Operands));
230       if(m_size > sizeof(unsigned int)) 
231       {
232         delete[] m_RawInsn.large_insn;
233       }
234       
235       m_size = rhs.m_size;
236       if(rhs.m_size > sizeof(unsigned int))
237       {
238         m_RawInsn.large_insn = new unsigned char[rhs.m_size];
239         memcpy(m_RawInsn.large_insn, rhs.m_RawInsn.large_insn, m_size);
240       }
241       else
242       {
243         m_RawInsn.small_insn = rhs.m_RawInsn.small_insn;
244       }
245
246
247       m_InsnOp = rhs.m_InsnOp;
248       m_Valid = rhs.m_Valid;
249       return *this;
250     }    
251     
252     INSTRUCTION_EXPORT bool Instruction::isValid() const
253     {
254       return m_Valid;
255     }
256     
257     INSTRUCTION_EXPORT const Operation& Instruction::getOperation() const
258     {
259       return *m_InsnOp;
260     }
261     
262     INSTRUCTION_EXPORT void Instruction::getOperands(std::vector<Operand>& operands) const
263     {
264       if(m_Operands.empty())
265       {
266         decodeOperands();
267       }
268       
269       std::copy(m_Operands.begin(), m_Operands.end(), std::back_inserter(operands));
270     }
271     
272     INSTRUCTION_EXPORT Operand Instruction::getOperand(int index) const
273      {
274       if(m_Operands.empty())
275       {
276         decodeOperands();
277       }
278
279         if(index < 0 || index >= (int)(m_Operands.size()))
280         {
281           // Out of range = empty operand
282            return Operand(Expression::Ptr(), false, false);
283         }
284         return m_Operands[index];
285      }
286
287      INSTRUCTION_EXPORT const void* Instruction::ptr() const
288      {
289          if(m_size > sizeof(unsigned int))
290          {
291              return m_RawInsn.large_insn;
292          }
293          else
294          {
295              return reinterpret_cast<const void*>(&m_RawInsn.small_insn);
296          }
297      }
298     INSTRUCTION_EXPORT unsigned char Instruction::rawByte(unsigned int index) const
299     {
300       if(index > m_size) return 0;
301       if(m_size > sizeof(unsigned int)) 
302       {
303         return m_RawInsn.large_insn[index];
304       }
305       else
306       {
307         return reinterpret_cast<const unsigned char*>(&m_RawInsn.small_insn)[index];
308       }
309     }
310     
311     INSTRUCTION_EXPORT size_t Instruction::size() const
312     {
313       return m_size;
314       
315     }
316     
317     INSTRUCTION_EXPORT void Instruction::getReadSet(std::set<RegisterAST::Ptr>& regsRead) const
318     {
319       if(m_Operands.empty())
320       {
321         decodeOperands();
322       }
323       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
324           curOperand != m_Operands.end();
325           ++curOperand)
326       {
327         curOperand->getReadSet(regsRead);
328       }
329       std::copy(m_InsnOp->implicitReads().begin(), m_InsnOp->implicitReads().end(), std::inserter(regsRead, regsRead.begin()));
330       
331     }
332     
333     INSTRUCTION_EXPORT void Instruction::getWriteSet(std::set<RegisterAST::Ptr>& regsWritten) const
334     { 
335       if(m_Operands.empty())
336       {
337         decodeOperands();
338       }
339       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
340           curOperand != m_Operands.end();
341           ++curOperand)
342       {
343         curOperand->getWriteSet(regsWritten);
344       }
345       std::copy(m_InsnOp->implicitWrites().begin(), m_InsnOp->implicitWrites().end(), std::inserter(regsWritten, regsWritten.begin()));
346       
347     }
348     
349     INSTRUCTION_EXPORT bool Instruction::isRead(Expression::Ptr candidate) const
350     {
351       if(m_Operands.empty())
352       {
353         decodeOperands();
354       }
355       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
356           curOperand != m_Operands.end();
357           ++curOperand)
358       {
359         if(curOperand->isRead(candidate))
360         {
361           return true;
362         }
363       }
364       return m_InsnOp->isRead(candidate);
365     }
366
367     INSTRUCTION_EXPORT bool Instruction::isWritten(Expression::Ptr candidate) const
368     {
369       if(m_Operands.empty())
370       {
371         decodeOperands();
372       }
373       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
374           curOperand != m_Operands.end();
375           ++curOperand)
376       {
377         if(curOperand->isWritten(candidate))
378         {
379           return true;
380         }
381       }
382       return m_InsnOp->isWritten(candidate);
383     }
384     
385     INSTRUCTION_EXPORT bool Instruction::readsMemory() const
386     {
387       if(m_Operands.empty())
388       {
389         decodeOperands();
390       }
391       if(getCategory() == c_PrefetchInsn)
392       {
393           return false;
394       }
395       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
396           curOperand != m_Operands.end();
397           ++curOperand)
398       {
399         if(curOperand->readsMemory())
400         {
401           return true;
402         }
403       }
404       return !m_InsnOp->getImplicitMemReads().empty();
405     }
406     
407     INSTRUCTION_EXPORT bool Instruction::writesMemory() const
408     {
409       if(m_Operands.empty())
410       {
411         decodeOperands();
412       }
413       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
414           curOperand != m_Operands.end();
415           ++curOperand)
416       {
417         if(curOperand->writesMemory())
418         {
419           return true;
420         }
421       }
422       return !m_InsnOp->getImplicitMemWrites().empty();
423     }
424     
425     INSTRUCTION_EXPORT void Instruction::getMemoryReadOperands(std::set<Expression::Ptr>& memAccessors) const
426     {
427       if(m_Operands.empty())
428       {
429         decodeOperands();
430       }
431       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
432           curOperand != m_Operands.end();
433           ++curOperand)
434       {
435         curOperand->addEffectiveReadAddresses(memAccessors);
436       }  
437       std::copy(m_InsnOp->getImplicitMemReads().begin(), m_InsnOp->getImplicitMemReads().end(), std::inserter(memAccessors, memAccessors.begin()));
438     }
439     
440     INSTRUCTION_EXPORT void Instruction::getMemoryWriteOperands(std::set<Expression::Ptr>& memAccessors) const
441     {
442       if(m_Operands.empty())
443       {
444         decodeOperands();
445       }
446       for(std::vector<Operand>::const_iterator curOperand = m_Operands.begin();
447           curOperand != m_Operands.end();
448           ++curOperand)
449       {
450         curOperand->addEffectiveWriteAddresses(memAccessors);
451       }  
452       std::copy(m_InsnOp->getImplicitMemWrites().begin(), m_InsnOp->getImplicitMemWrites().end(), std::inserter(memAccessors, memAccessors.begin()));
453     }
454     
455     INSTRUCTION_EXPORT Expression::Ptr Instruction::getControlFlowTarget() const
456     {
457         // We assume control flow transfer instructions have the PC as
458         // an implicit write, and that we have decoded the control flow
459         // target's full location as the first and only operand.
460         // If this is not the case, we'll squawk for the time being...
461         static Expression::Ptr thePC(new RegisterAST(RegisterAST::makePC()));
462         if(getCategory() == c_NoCategory)
463         {
464             return Expression::Ptr();
465         }
466         if(getCategory() == c_ReturnInsn)
467         {
468             return makeReturnExpression();
469         }
470         if(m_Operands.empty())
471         {
472             decodeOperands();
473         }
474     #if defined(DEBUG_LOG)      
475         if(!(m_Operands[0].isRead(thePC) || m_Operands.size() == 1))
476         {
477             fprintf(stderr, "WARNING: control flow target for instruction %s may be incorrect\n", format().c_str());
478         }
479     #endif      
480         if(getCategory() == c_BranchInsn ||
481         getCategory() == c_CallInsn)
482         {
483 #if defined(NO_OPT_FLAG)            
484             assert(m_InsnOp->isWritten(thePC));
485 #endif //defined(NO_OPT_FLAG)
486             return m_Operands[0].getValue();
487         }
488         return Expression::Ptr();
489     }
490     
491     INSTRUCTION_EXPORT std::string Instruction::format() const
492     {
493       if(m_Operands.empty())
494       {
495         decodeOperands();
496       }
497       std::string retVal = m_InsnOp->format();
498       retVal += " ";
499       std::vector<Operand>::const_iterator curOperand;
500       for(curOperand = m_Operands.begin();
501           curOperand != m_Operands.end();
502           ++curOperand)
503       {
504         retVal += curOperand->format();
505         retVal += ", ";
506       }
507       if(!m_Operands.empty())
508       {
509         // trim trailing ", "
510         retVal.erase(retVal.size() - 2, retVal.size());
511       }
512       
513       return retVal;
514     }
515     INSTRUCTION_EXPORT bool Instruction::allowsFallThrough() const
516     {
517       switch(m_InsnOp->getID())
518       {
519       case e_ret_far:
520       case e_ret_near:
521       case e_iret:
522       case e_jmp:
523       case e_hlt:
524       case e_sysret:
525       case e_sysexit:
526         return false;
527       default:
528         return true;
529       }
530       
531     }
532     INSTRUCTION_EXPORT bool Instruction::isLegalInsn() const
533     {
534       return (m_InsnOp->getID() != e_No_Entry);
535     }
536     Expression::Ptr Instruction::makeReturnExpression() const
537     {
538       Expression::Ptr stackPtr = Expression::Ptr(new RegisterAST(r_rSP));
539       Expression::Ptr retLoc = Expression::Ptr(new Dereference(stackPtr, u32));
540       return retLoc;
541     }
542     INSTRUCTION_EXPORT InsnCategory Instruction::getCategory() const
543     {
544       return entryToCategory(m_InsnOp->getID());
545     }
546   };
547 };
548