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