Fixes for non-returning functions and tail calls:
[dyninst.git] / parseAPI / src / CodeSource.C
1 /*
2  * Copyright (c) 1996-2011 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 #include <vector>
32 #include <map>
33
34 #include <boost/assign/list_of.hpp>
35
36 #include "dyntypes.h"
37
38 #include "CodeSource.h"
39 #include "debug_parse.h"
40 #include "util.h"
41
42 using namespace std;
43 using namespace Dyninst;
44 using namespace Dyninst::ParseAPI;
45
46 /** CodeSource **/
47 void
48 CodeSource::addRegion(CodeRegion * cr)
49 {
50     _regions.push_back(cr);
51
52     // check for overlapping regions
53     if(!_regions_overlap) {
54         set<CodeRegion *> exist;
55         _region_tree.find(cr,exist);
56         if(!exist.empty())
57             _regions_overlap = true;
58     }
59
60     _region_tree.insert(cr);
61 }
62
63 int
64 CodeSource::findRegions(Address addr, set<CodeRegion *> & ret) const
65 {
66     return _region_tree.find(addr,ret);
67 }
68
69 dyn_hash_map<std::string, bool>
70 CodeSource::non_returning_funcs =
71     boost::assign::map_list_of
72         ("exit",true)
73         ("abort",true)
74         ("__f90_stop",true)
75         ("fancy_abort",true)
76         ("__stack_chk_fail",true)
77         ("__assert_fail",true)
78         ("ExitProcess",true)
79         ("_ZSt17__throw_bad_allocv",true)
80         ("_ZSt20__throw_length_errorPKc",true)
81         ("_Unwind_Resume",true)
82         ("longjmp",true)
83         ("__longjmp",true)
84         ("siglongjmp",true)
85         ("_ZSt16__throw_bad_castv",true)
86         ("_ZSt19__throw_logic_errorPKc",true)
87         ("_ZSt20__throw_out_of_rangePKc",true)
88         ("__cxa_rethrow",true)
89         ("__cxa_throw",true)
90         ("_ZSt21__throw_runtime_errorPKc",true)
91         ("_ZSt9terminatev",true)
92         ("_gfortran_os_error",true)
93         ("_gfortran_runtime_error",true)
94         ("_gfortran_stop_numeric", true)
95         ("_gfortran_runtime_error_at", true)
96         ("_gfortran_stop_string", true)
97         ("_gfortran_abort", true)
98         ("_gfortran_exit_i8", true)
99         ("_gfortran_exit_i4", true)
100         ("for_stop_core", true)
101         ("__sys_exit", true);
102
103 dyn_hash_map<int, bool>
104 CodeSource::non_returning_syscalls_x86 =
105     boost::assign::map_list_of
106         (1 /*exit*/,true)
107         (119 /*sigreturn*/, true);
108
109 dyn_hash_map<int, bool>
110 CodeSource::non_returning_syscalls_x86_64 =
111     boost::assign::map_list_of
112         (60 /*exit*/,true)
113         (15 /*sigreturn*/, true);
114
115 bool
116 CodeSource::nonReturning(string name)
117 {
118 #if defined(os_windows)
119         // We see MSVCR<N>.exit
120         // Of course, it's often reached via indirect call, but hope never fails.
121         if ((name.compare(0, strlen("MSVCR"), "MSVCR") == 0) &&
122                 (name.find("exit") != name.npos)) return true;
123 #endif
124         parsing_printf("Checking non-returning for %s\n", name.c_str());
125     return non_returning_funcs.find(name) != non_returning_funcs.end();
126 }
127