Fixes for non-returning functions and tail calls:
[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/src/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, set<Address>()))
124         {
125             return UNKNOWN;
126         }
127         if(!parsedJumpTable)
128         {
129             return UNSET;
130         }
131         else if(!successfullyParsedJumpTable)
132         {
133             return UNKNOWN;
134         }
135             
136     }
137     if(isReturn(context, _curBlk))
138     {
139         return RETURN;
140     }
141     return UNSET;
142 }
143
144 /* Returns true for indirect calls and unresolved indirect branches 
145  */
146 bool InstructionAdapter::hasUnresolvedControlFlow(Function* context, unsigned int num_insns) const
147 {
148     if(isDynamicCall())
149     {
150         return true;
151     }
152     if(getReturnStatus(context, num_insns) == UNKNOWN)
153     { // true for indirect branches
154         return true;
155     }
156     return false;
157 }
158
159 InstrumentableLevel InstructionAdapter::getInstLevel(Function * context, unsigned int num_insns) const
160 {
161    bool valid; Address target;
162    boost::tie(valid, target) = getCFT();
163    if(isBranch() && !valid)
164     {
165         if(num_insns == 2)
166         {
167             return UNINSTRUMENTABLE;
168         }
169         else if(isTailCall(context, INDIRECT, num_insns, set<Address>()))
170         {
171             return NORMAL;
172         }
173         else if(!parsedJumpTable)
174         {
175             fprintf(stderr, "expected jump table parsing attempt for insn at 0x%lx\n", current);
176             assert(0);
177             // check for unparseable
178             return HAS_BR_INDIR;
179         }
180         else if(!successfullyParsedJumpTable)
181         {
182             return HAS_BR_INDIR;
183         }
184     }
185     return NORMAL;
186 }