Fix vpadd decoding. Clean up control flow target logic and shared pointer constructio...
[dyninst.git] / instructionAPI / src / Instruction.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 // Needs to be the first include.
32 #include "common/src/Types.h"
33
34 #include <stdio.h>
35 #include <string>
36 #include "../h/InstructionCategories.h"
37 #include "../h/Instruction.h"
38 #include "../h/Register.h"
39 #include "../h/Operation.h"
40 #include "InstructionDecoder.h"
41 #include "Dereference.h"
42 #include <boost/iterator/indirect_iterator.hpp>
43 #include <iostream>
44 #include <sstream>
45 #include <iomanip>
46 #include <set>
47 #include <functional>
48
49 #define INSIDE_INSTRUCTION_API
50 #include "common/src/arch-x86.h"
51
52 using namespace std;
53 using namespace NS_x86;
54
55 #include "../../common/src/singleton_object_pool.h"
56
57 namespace Dyninst
58 {
59   namespace InstructionAPI
60   {
61
62       static const int IAPI_major_version = 8;
63       static const int IAPI_minor_version = 2;
64       static const int IAPI_maintenance_version = 0;
65
66       void Instruction::version(int& major, int& minor, int& maintenance)
67       {
68           major = IAPI_major_version;
69           minor = IAPI_minor_version;
70           maintenance = IAPI_maintenance_version;
71       }
72
73       int Instruction::numInsnsAllocated = 0;
74     INSTRUCTION_EXPORT Instruction::Instruction(Operation::Ptr what,
75                              size_t size, const unsigned char* raw,
76                              Dyninst::Architecture arch)
77       : m_InsnOp(what), m_Valid(true), arch_decoded_from(arch)
78     {
79
80         copyRaw(size, raw);
81
82 #if defined(DEBUG_INSN_ALLOCATIONS)
83         numInsnsAllocated++;
84         if((numInsnsAllocated % 1000) == 0)
85         {
86             fprintf(stderr, "Instruction CTOR, %d insns allocated\n", numInsnsAllocated);
87         }
88 #endif    
89     }
90
91     void Instruction::copyRaw(size_t size, const unsigned char* raw)
92     {
93       
94       if(raw)
95       {
96         m_size = size;
97         m_RawInsn.small_insn = 0;
98         if(size <= sizeof(m_RawInsn.small_insn))
99         {
100           memcpy(&m_RawInsn.small_insn, raw, size);
101         }
102         else
103         {
104           m_RawInsn.large_insn = new unsigned char[size];
105           memcpy(m_RawInsn.large_insn, raw, size);
106         }
107       }
108       else
109       {
110         m_size = 0;
111         m_RawInsn.small_insn = 0;
112       }
113     }
114
115     void Instruction::decodeOperands() const
116     {
117         //m_Operands.reserve(5);
118         InstructionDecoder dec(ptr(), size(), arch_decoded_from);
119         dec.doDelayedDecode(this);
120     }
121     
122     INSTRUCTION_EXPORT Instruction::Instruction() :
123       m_Valid(false), m_size(0), arch_decoded_from(Arch_none)
124     {
125
126 #if defined(DEBUG_INSN_ALLOCATIONS)
127         numInsnsAllocated++;
128         if((numInsnsAllocated % 1000) == 0)
129         {
130             fprintf(stderr, "Instruction CTOR, %d insns allocated\n", numInsnsAllocated);
131         }
132 #endif
133     }
134     
135     INSTRUCTION_EXPORT Instruction::~Instruction()
136     {
137
138       if(m_size > sizeof(m_RawInsn.small_insn))
139       {
140         delete[] m_RawInsn.large_insn;
141       }
142 #if defined(DEBUG_INSN_ALLOCATIONS)
143       numInsnsAllocated--;
144       if((numInsnsAllocated % 1000) == 0)
145       {
146           fprintf(stderr, "Instruction DTOR, %d insns allocated\n", numInsnsAllocated);
147       }
148 #endif      
149     }
150
151     INSTRUCTION_EXPORT Instruction::Instruction(const Instruction& o) :
152       arch_decoded_from(o.arch_decoded_from)
153     {
154         m_Operands = o.m_Operands;
155       m_size = o.m_size;
156       if(o.m_size > sizeof(m_RawInsn.small_insn))
157       {
158         m_RawInsn.large_insn = new unsigned char[o.m_size];
159         memcpy(m_RawInsn.large_insn, o.m_RawInsn.large_insn, m_size);
160       }
161       else
162       {
163         m_RawInsn.small_insn = o.m_RawInsn.small_insn;
164       }
165
166       m_InsnOp = o.m_InsnOp;
167       m_Valid = o.m_Valid;
168 #if defined(DEBUG_INSN_ALLOCATIONS)
169       numInsnsAllocated++;
170       if((numInsnsAllocated % 1000) == 0)
171       {
172           fprintf(stderr, "Instruction COPY CTOR, %d insns allocated\n", numInsnsAllocated);
173       }
174 #endif
175     }
176
177     INSTRUCTION_EXPORT const Instruction& Instruction::operator=(const Instruction& rhs)
178     {
179       m_Operands = rhs.m_Operands;
180       //m_Operands.reserve(rhs.m_Operands.size());
181       //std::copy(rhs.m_Operands.begin(), rhs.m_Operands.end(), std::back_inserter(m_Operands));
182       if(m_size > sizeof(m_RawInsn.small_insn))
183       {
184         delete[] m_RawInsn.large_insn;
185       }
186       
187       m_size = rhs.m_size;
188       if(rhs.m_size > sizeof(m_RawInsn.small_insn))
189       {
190         m_RawInsn.large_insn = new unsigned char[rhs.m_size];
191         memcpy(m_RawInsn.large_insn, rhs.m_RawInsn.large_insn, m_size);
192       }
193       else
194       {
195         m_RawInsn.small_insn = rhs.m_RawInsn.small_insn;
196       }
197
198
199       m_InsnOp = rhs.m_InsnOp;
200       m_Valid = rhs.m_Valid;
201       arch_decoded_from = rhs.arch_decoded_from;
202       return *this;
203     }    
204     
205     INSTRUCTION_EXPORT bool Instruction::isValid() const
206     {
207       return m_Valid;
208     }
209     
210     INSTRUCTION_EXPORT const Operation& Instruction::getOperation() const
211     {
212       return *m_InsnOp;
213     }
214     
215     INSTRUCTION_EXPORT void Instruction::getOperands(std::vector<Operand>& operands) const
216     {
217       if(m_Operands.empty())
218       {
219         decodeOperands();
220       }
221       
222       std::copy(m_Operands.begin(), m_Operands.end(), std::back_inserter(operands));
223     }
224     
225     INSTRUCTION_EXPORT Operand Instruction::getOperand(int index) const
226      {
227       if(m_Operands.empty())
228       {
229         decodeOperands();
230       }
231
232         if(index < 0 || index >= (int)(m_Operands.size()))
233         {
234           // Out of range = empty operand
235             return Operand(Expression::Ptr(), false, false);
236         }
237         std::list<Operand>::const_iterator found = m_Operands.begin();
238         std::advance(found, index);
239         return *found;
240      }
241
242      INSTRUCTION_EXPORT const void* Instruction::ptr() const
243      {
244          if(m_size > sizeof(m_RawInsn.small_insn))
245          {
246              return m_RawInsn.large_insn;
247          }
248          else
249          {
250              return reinterpret_cast<const void*>(&m_RawInsn.small_insn);
251          }
252      }
253     INSTRUCTION_EXPORT unsigned char Instruction::rawByte(unsigned int index) const
254     {
255       if(index >= m_size) return 0;
256       if(m_size > sizeof(m_RawInsn.small_insn))
257       {
258         return m_RawInsn.large_insn[index];
259       }
260       else
261       {
262         return reinterpret_cast<const unsigned char*>(&m_RawInsn.small_insn)[index];
263       }
264     }
265     
266     INSTRUCTION_EXPORT size_t Instruction::size() const
267     {
268       return m_size;
269       
270     }
271     
272     INSTRUCTION_EXPORT void Instruction::getReadSet(std::set<RegisterAST::Ptr>& regsRead) const
273     {
274       if(m_Operands.empty())
275       {
276         decodeOperands();
277       }
278       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
279           curOperand != m_Operands.end();
280           ++curOperand)
281       {
282           curOperand->getReadSet(regsRead);
283       }
284       std::copy(m_InsnOp->implicitReads().begin(), m_InsnOp->implicitReads().end(), std::inserter(regsRead, regsRead.begin()));
285       
286     }
287     
288     INSTRUCTION_EXPORT void Instruction::getWriteSet(std::set<RegisterAST::Ptr>& regsWritten) const
289     { 
290       if(m_Operands.empty())
291       {
292         decodeOperands();
293       }
294       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
295           curOperand != m_Operands.end();
296           ++curOperand)
297       {
298           curOperand->getWriteSet(regsWritten);
299       }
300       std::copy(m_InsnOp->implicitWrites().begin(), m_InsnOp->implicitWrites().end(), std::inserter(regsWritten,
301 regsWritten.begin()));
302       
303     }
304     
305     INSTRUCTION_EXPORT bool Instruction::isRead(Expression::Ptr candidate) const
306     {
307       if(m_Operands.empty())
308       {
309         decodeOperands();
310       }
311       for(std::list<Operand >::const_iterator curOperand = m_Operands.begin();
312           curOperand != m_Operands.end();
313           ++curOperand)
314       {
315           if(curOperand->isRead(candidate))
316         {
317           return true;
318         }
319       }
320       return m_InsnOp->isRead(candidate);
321     }
322
323     INSTRUCTION_EXPORT bool Instruction::isWritten(Expression::Ptr candidate) const
324     {
325       if(m_Operands.empty())
326       {
327         decodeOperands();
328       }
329       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
330           curOperand != m_Operands.end();
331           ++curOperand)
332       {
333           if(curOperand->isWritten(candidate))
334         {
335           return true;
336         }
337       }
338       return m_InsnOp->isWritten(candidate);
339     }
340     
341     INSTRUCTION_EXPORT bool Instruction::readsMemory() const
342     {
343       if(m_Operands.empty())
344       {
345         decodeOperands();
346       }
347       if(getCategory() == c_PrefetchInsn)
348       {
349           return false;
350       }
351       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
352           curOperand != m_Operands.end();
353           ++curOperand)
354       {
355           if(curOperand->readsMemory())
356         {
357           return true;
358         }
359       }
360       return !m_InsnOp->getImplicitMemReads().empty();
361     }
362     
363     INSTRUCTION_EXPORT bool Instruction::writesMemory() const
364     {
365       if(m_Operands.empty())
366       {
367         decodeOperands();
368       }
369       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
370           curOperand != m_Operands.end();
371           ++curOperand)
372       {
373           if(curOperand->writesMemory())
374         {
375           return true;
376         }
377       }
378       return !m_InsnOp->getImplicitMemWrites().empty();
379     }
380     
381     INSTRUCTION_EXPORT void Instruction::getMemoryReadOperands(std::set<Expression::Ptr>& memAccessors) const
382     {
383       if(m_Operands.empty())
384       {
385         decodeOperands();
386       }
387       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
388           curOperand != m_Operands.end();
389           ++curOperand)
390       {
391           curOperand->addEffectiveReadAddresses(memAccessors);
392       }  
393       std::copy(m_InsnOp->getImplicitMemReads().begin(), m_InsnOp->getImplicitMemReads().end(), std::inserter(memAccessors,
394 memAccessors.begin()));
395     }
396     
397     INSTRUCTION_EXPORT void Instruction::getMemoryWriteOperands(std::set<Expression::Ptr>& memAccessors) const
398     {
399       if(m_Operands.empty())
400       {
401         decodeOperands();
402       }
403       for(std::list<Operand>::const_iterator curOperand = m_Operands.begin();
404           curOperand != m_Operands.end();
405           ++curOperand)
406       {
407           curOperand->addEffectiveWriteAddresses(memAccessors);
408       }  
409       std::copy(m_InsnOp->getImplicitMemWrites().begin(), m_InsnOp->getImplicitMemWrites().end(), std::inserter(memAccessors,
410 memAccessors.begin()));
411     }
412     
413     INSTRUCTION_EXPORT Expression::Ptr Instruction::getControlFlowTarget() const
414     {
415         // We assume control flow transfer instructions have the PC as
416         // an implicit write, and that we have decoded the control flow
417         // target's full location as the first and only operand.
418         // If this is not the case, we'll squawk for the time being...
419         if(getCategory() == c_NoCategory ||
420                 getCategory() == c_CompareInsn ||
421                 getCategory() == c_PrefetchInsn)
422         {
423             return Expression::Ptr();
424         }
425         if(getCategory() == c_ReturnInsn)
426         {
427             return makeReturnExpression();
428         }
429         if(m_Operands.empty())
430         {
431             decodeOperands();
432         }
433         if(m_Successors.empty())
434         {
435             return Expression::Ptr();
436         }
437         return m_Successors.front().target;
438     }
439     
440     INSTRUCTION_EXPORT std::string Instruction::format(Address addr) const
441     {
442       if(m_Operands.empty())
443       {
444         decodeOperands();
445       }
446
447       std::string retVal = m_InsnOp->format();
448       retVal += " ";
449       std::list<Operand>::const_iterator curOperand;
450       for(curOperand = m_Operands.begin();
451           curOperand != m_Operands.end();
452           ++curOperand)
453       {
454           retVal += curOperand->format(getArch(), addr);
455         retVal += ", ";
456       }
457       if(!m_Operands.empty())
458       {
459         // trim trailing ", "
460         retVal.erase(retVal.size() - 2, retVal.size());
461       }
462 #if defined(DEBUG_READ_WRITE)      
463       std::set<RegisterAST::Ptr> tmp;
464       getReadSet(tmp);
465       cout << "Read set:" << endl;
466       for(std::set<RegisterAST::Ptr>::iterator i = tmp.begin();
467           i != tmp.end();
468          ++i)
469       {
470           cout << (*i)->format() << " ";
471       }
472       cout << endl;
473       tmp.clear();
474       getWriteSet(tmp);
475       cout << "Write set:" << endl;
476       for(std::set<RegisterAST::Ptr>::iterator i = tmp.begin();
477           i != tmp.end();
478           ++i)
479       {
480           cout << (*i)->format() << " ";
481       }
482       cout << endl;
483       std::set<Expression::Ptr> mem;
484       getMemoryReadOperands(mem);
485       cout << "Read mem:" << endl;
486       for(std::set<Expression::Ptr>::iterator i = mem.begin();
487           i != mem.end();
488           ++i)
489       {
490           cout << (*i)->format() << " ";
491       }
492       cout << endl;
493       mem.clear();
494       getMemoryWriteOperands(mem);
495       cout << "Write mem:" << endl;
496       for(std::set<Expression::Ptr>::iterator i = mem.begin();
497           i != mem.end();
498           ++i)
499       {
500           cout << (*i)->format() << " ";
501       }
502       cout << endl;
503 #endif // defined(DEBUG_READ_WRITE)
504       return retVal;
505     }
506     INSTRUCTION_EXPORT bool Instruction::allowsFallThrough() const
507     {
508       switch(m_InsnOp->getID())
509       {
510       case e_ret_far:
511       case e_ret_near:
512       case e_iret:
513       case e_jmp:
514       case e_hlt:
515       case e_sysret:
516       case e_sysexit:
517       case e_call:
518       case e_syscall:
519         return false;
520           case e_jnb:
521           case e_jb:
522           case e_jb_jnaej_j:
523           case e_jbe:
524           case e_jcxz_jec:
525           case e_jl:
526           case e_jle:
527           case e_jnb_jae_j:
528           case e_jnbe:
529           case e_jnl:
530           case e_jnle:
531           case e_jno:
532           case e_jnp:
533           case e_jns:
534           case e_jnz:
535           case e_jo:
536           case e_jp:
537           case e_js:
538           case e_jz:
539               return true;
540       default:
541       {
542         decodeOperands();
543           for(cftConstIter targ = m_Successors.begin();
544               targ != m_Successors.end();
545               ++targ)
546           {
547             if(targ->isFallthrough) return true;
548           }
549           return m_Successors.empty();
550       }
551       }
552       
553     }
554     INSTRUCTION_EXPORT bool Instruction::isLegalInsn() const
555     {
556       return (m_InsnOp->getID() != e_No_Entry);
557     }
558
559     INSTRUCTION_EXPORT Architecture Instruction::getArch() const {
560       return arch_decoded_from;
561     }
562
563     Expression::Ptr Instruction::makeReturnExpression() const
564     {
565         Expression::Ptr stackPtr = Expression::Ptr(new RegisterAST(MachRegister::getStackPointer(arch_decoded_from),
566                 0, MachRegister::getStackPointer(arch_decoded_from).size()));
567         Expression::Ptr retLoc = Expression::Ptr(new Dereference(stackPtr, u32));
568         return retLoc;
569     }
570     INSTRUCTION_EXPORT InsnCategory Instruction::getCategory() const
571     {
572        InsnCategory c = entryToCategory(m_InsnOp->getID());
573        if(c == c_BranchInsn && (arch_decoded_from == Arch_ppc32 || arch_decoded_from == Arch_ppc64))
574        {
575           if(m_Operands.empty()) decodeOperands();
576           for(cftConstIter cft = cft_begin();
577               cft != cft_end();
578               ++cft)
579           {
580              if(cft->isCall)
581              {
582                 return c_CallInsn;
583              }
584           }
585           if(m_InsnOp->getID() == power_op_bclr)
586           {
587              return c_ReturnInsn;
588           }
589        }
590       return c;
591     }
592     void Instruction::addSuccessor(Expression::Ptr e, 
593                                    bool isCall, 
594                                    bool isIndirect, 
595                                    bool isConditional, 
596                                    bool isFallthrough) const
597     {
598         CFT c(e, isCall, isIndirect, isConditional, isFallthrough);
599         m_Successors.push_back(c);
600         if (!isFallthrough) appendOperand(e, true, false);
601     }
602     void Instruction::appendOperand(Expression::Ptr e, bool isRead, bool isWritten) const
603     {
604         m_Operands.push_back(Operand(e, isRead, isWritten));
605     }
606   
607
608   };
609 };
610