Merge branch 'master' into NewInstpoint
[dyninst.git] / parseAPI / src / InstructionAdapter.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 "common/h/Types.h"
33 //#include "arch.h"
34 #include "InstructionAdapter.h"
35 #include "debug_parse.h"
36
37 #include "parseAPI/h/CodeObject.h"
38 #include "external/boost/tuple/tuple.hpp"
39
40 using namespace Dyninst;
41 using namespace Dyninst::InsnAdapter;
42 using namespace Dyninst::ParseAPI;
43
44 InstructionAdapter::InstructionAdapter(Address start, CodeObject *o, CodeRegion * r, InstructionSource * isrc, Block * curBlk)
45     : current(start), previous((Address)-1), parsedJumpTable(false), successfullyParsedJumpTable(false),
46     isDynamicCall_(false), checkedDynamicCall_(false),
47     isInvalidCallTarget_(false), checkedInvalidCallTarget_(false),
48     //context(NULL), 
49     _obj(o), _cr(r), _isrc(isrc), _curBlk(curBlk)
50 {
51 }
52
53 void
54 InstructionAdapter::reset(
55     Address start,
56     CodeObject *o,
57     CodeRegion *r,
58     InstructionSource *isrc,
59     Block *curBlk)
60 {
61     current = start;
62     previous = (Address)-1;    
63     parsedJumpTable = false;
64     successfullyParsedJumpTable = false;
65     isDynamicCall_ = false;
66     checkedDynamicCall_ = false;
67     isInvalidCallTarget_ = false;
68     checkedInvalidCallTarget_ = false;
69     _obj = o;
70     _cr = r;
71     _isrc = isrc;
72     _curBlk = curBlk;
73 }
74
75 InstructionAdapter::~InstructionAdapter()
76 {
77 }
78
79
80 void InstructionAdapter::advance()
81 {
82     previous = current;
83     parsedJumpTable = false;
84     successfullyParsedJumpTable = false;
85     checkedDynamicCall_ = false;
86     checkedInvalidCallTarget_ = false;
87
88 }
89
90 bool InstructionAdapter::retreat()
91 {
92     // anything? FIXME
93     return false;
94 }
95
96 Address InstructionAdapter::getAddr() const
97 {
98     return current;
99 }
100
101 Address InstructionAdapter::getPrevAddr() const
102 {
103     return previous;
104 }
105
106 Address InstructionAdapter::getNextAddr() const
107 {
108     return current + getSize();
109 }
110
111 FuncReturnStatus InstructionAdapter::getReturnStatus(Function * context ,
112         unsigned int num_insns) const
113 {
114     // Branch that's not resolvable by binding IP,
115     // therefore indirect...
116    bool valid; Address addr;
117    boost::tie(valid, addr) = getCFT();
118    if(isBranch() && !valid)
119     {
120         if(num_insns == 2)
121         {
122             return UNKNOWN;
123         }
124         if(isTailCall(context,num_insns))
125         {
126             return UNKNOWN;
127         }
128         if(!parsedJumpTable)
129         {
130 #if !defined(os_vxworks)
131             assert(0);
132 #endif
133             return UNSET;
134         }
135         else if(!successfullyParsedJumpTable)
136         {
137             return UNKNOWN;
138         }
139             
140     }
141     if(isReturn(context, _curBlk))
142     {
143         return RETURN;
144     }
145     return UNSET;
146 }
147
148 /* Returns true for indirect calls and unresolved indirect branches 
149  */
150 bool InstructionAdapter::hasUnresolvedControlFlow(Function* context, unsigned int num_insns) const
151 {
152     if(isDynamicCall())
153     {
154         return true;
155     }
156     if(getReturnStatus(context, num_insns) == UNKNOWN)
157     { // true for indirect branches
158         return true;
159     }
160     return false;
161 }
162
163 InstrumentableLevel InstructionAdapter::getInstLevel(Function * context, unsigned int num_insns) const
164 {
165    bool valid; Address target;
166    boost::tie(valid, target) = getCFT();
167    if(isBranch() && !valid)
168     {
169         if(num_insns == 2)
170         {
171             return UNINSTRUMENTABLE;
172         }
173         else if(isTailCall(context,num_insns))
174         {
175             return NORMAL;
176         }
177         else if(!parsedJumpTable)
178         {
179             fprintf(stderr, "expected jump table parsing attempt for insn at 0x%lx\n", current);
180             assert(0);
181             // check for unparseable
182             return HAS_BR_INDIR;
183         }
184         else if(!successfullyParsedJumpTable)
185         {
186             return HAS_BR_INDIR;
187         }
188     }
189     return NORMAL;
190 }