ReFRACtor
backtrace.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2010 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #define BOOST_SOURCE
9 
10 #include <boost/backtrace.hpp>
11 
12 #if defined(__linux) || defined(__APPLE__) || defined(__sun)
13 #define BOOST_HAVE_EXECINFO
14 #define BOOST_HAVE_DLADDR
15 #endif
16 
17 #if defined(__GNUC__)
18 #define BOOST_HAVE_ABI_CXA_DEMANGLE
19 #endif
20 
21 #ifdef BOOST_HAVE_EXECINFO
22 #include <execinfo.h>
23 #endif
24 
25 #ifdef BOOST_HAVE_ABI_CXA_DEMANGLE
26 #include <cxxabi.h>
27 #endif
28 
29 #ifdef BOOST_HAVE_DLADDR
30 #include <dlfcn.h>
31 #endif
32 #include <string.h>
33 #include <stdlib.h>
34 #include <ostream>
35 #include <sstream>
36 #include <iomanip>
37 
38 #if defined(BOOST_MSVC)
39 #include <windows.h>
40 #include <stdlib.h>
41 #include <dbghelp.h>
42 #endif
43 
44 
45 namespace boost {
46 
47  namespace stack_trace {
48  #if defined(BOOST_HAVE_EXECINFO)
49 
50  int trace(void **array,int n)
51  {
52  return :: backtrace(array,n);
53  }
54 
55  #elif defined(BOOST_MSVC)
56 
57  int trace(void **array,int n)
58  {
59  if(n>=63)
60  n=62;
61  return RtlCaptureStackBackTrace(0,n,array,0);
62  }
63 
64  #else
65 
66  int trace(void ** /*array*/,int /*n*/)
67  {
68  return 0;
69  }
70 
71  #endif
72 
73  #if defined(BOOST_HAVE_DLADDR) && defined(BOOST_HAVE_ABI_CXA_DEMANGLE)
74 
75  std::string get_symbol(void *ptr)
76  {
77  if(!ptr)
78  return std::string();
79  std::ostringstream res;
80  res.imbue(std::locale::classic());
81  res << ptr<<": ";
82  Dl_info info = {0};
83  if(dladdr(ptr,&info) == 0) {
84  res << "???";
85  }
86  else {
87  if(info.dli_sname) {
88  int status = 0;
89  char *demangled = abi::__cxa_demangle(info.dli_sname,0,0,&status);
90  if(demangled) {
91  res << demangled;
92  free(demangled);
93  }
94  else {
95  res << info.dli_sname;
96  }
97  }
98  else {
99  res << "???";
100  }
101 
102  unsigned offset = (char *)ptr - (char *)info.dli_saddr;
103  res << std::hex <<" + 0x" << offset ;
104 
105  if(info.dli_fname)
106  res << " in " << info.dli_fname;
107  }
108  return res.str();
109  }
110 
111  std::string get_symbols(void *const *addresses,int size)
112  {
113  std::string res;
114  for(int i=0;i<size;i++) {
115  std::string tmp = get_symbol(addresses[i]);
116  if(!tmp.empty()) {
117  res+=tmp;
118  res+='\n';
119  }
120  }
121  return res;
122  }
123  void write_symbols(void *const *addresses,int size,std::ostream &out)
124  {
125  for(int i=0;i<size;i++) {
126  std::string tmp = get_symbol(addresses[i]);
127  if(!tmp.empty()) {
128  out << tmp << '\n';
129  }
130  }
131  out << std::flush;
132  }
133 
134  #elif defined(BOOST_HAVE_EXECINFO)
135  std::string get_symbol(void *address)
136  {
137  char ** ptr = backtrace_symbols(&address,1);
138  try {
139  if(ptr == 0)
140  return std::string();
141  std::string res = ptr[0];
142  free(ptr);
143  ptr = 0;
144  return res;
145  }
146  catch(...) {
147  free(ptr);
148  throw;
149  }
150  }
151 
152  std::string get_symbols(void * const *address,int size)
153  {
154  char ** ptr = backtrace_symbols(address,size);
155  try {
156  if(ptr==0)
157  return std::string();
158  std::string res;
159  for(int i=0;i<size;i++) {
160  res+=ptr[i];
161  res+='\n';
162  }
163  free(ptr);
164  ptr = 0;
165  return res;
166  }
167  catch(...) {
168  free(ptr);
169  throw;
170  }
171  }
172 
173 
174  void write_symbols(void *const *addresses,int size,std::ostream &out)
175  {
176  char ** ptr = backtrace_symbols(addresses,size);
177  try {
178  if(ptr==0)
179  return;
180  for(int i=0;i<size;i++)
181  out << ptr[i] << '\n';
182  free(ptr);
183  ptr = 0;
184  out << std::flush;
185  }
186  catch(...) {
187  free(ptr);
188  throw;
189  }
190  }
191 
192  #elif defined(BOOST_MSVC)
193 
194  namespace {
195  HANDLE hProcess = 0;
196  bool syms_ready = false;
197 
198  void init()
199  {
200  if(hProcess == 0) {
201  hProcess = GetCurrentProcess();
202  SymSetOptions(SYMOPT_DEFERRED_LOADS);
203 
204  if (SymInitialize(hProcess, NULL, TRUE))
205  {
206  syms_ready = true;
207  }
208  }
209  }
210  }
211 
212  std::string get_symbol(void *ptr)
213  {
214  if(ptr==0)
215  return std::string();
216  init();
217  std::ostringstream ss;
218  ss << ptr;
219  if(syms_ready) {
220  DWORD64 dwDisplacement = 0;
221  DWORD64 dwAddress = (DWORD64)ptr;
222 
223  std::vector<char> buffer(sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
224  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)&buffer.front();
225 
226  pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
227  pSymbol->MaxNameLen = MAX_SYM_NAME;
228 
229  if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
230  {
231  ss <<": " << pSymbol->Name << std::hex << " +0x" << dwDisplacement;
232  }
233  else
234  {
235  ss << ": ???";
236  }
237  }
238  return ss.str();
239  }
240 
241  std::string get_symbols(void *const *addresses,int size)
242  {
243  std::string res;
244  for(int i=0;i<size;i++) {
245  std::string tmp = get_symbol(addresses[i]);
246  if(!tmp.empty()) {
247  res+=tmp;
248  res+='\n';
249  }
250  }
251  return res;
252  }
253  void write_symbols(void *const *addresses,int size,std::ostream &out)
254  {
255  for(int i=0;i<size;i++) {
256  std::string tmp = get_symbol(addresses[i]);
257  if(!tmp.empty()) {
258  out << tmp << '\n';
259  }
260  }
261  out << std::flush;
262  }
263 
264  #else
265 
266  std::string get_symbol(void *ptr)
267  {
268  if(!ptr)
269  return std::string();
270  std::ostringstream res;
271  res.imbue(std::locale::classic());
272  res << ptr;
273  return res.str();
274  }
275 
276  std::string get_symbols(void *const *ptrs,int size)
277  {
278  if(!ptrs)
279  return std::string();
280  std::ostringstream res;
281  res.imbue(std::locale::classic());
282  write_symbols(ptrs,size,res);
283  return res.str();
284  }
285 
286  void write_symbols(void *const *addresses,int size,std::ostream &out)
287  {
288  for(int i=0;i<size;i++) {
289  if(addresses[i]!=0)
290  out << addresses[i]<<'\n';
291  }
292  out << std::flush;
293  }
294 
295  #endif
296 
297  } // stack_trace
298 
299 } // boost
300 
301 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
302 
Definition: doxygen.h:52
std::string get_symbols(void *const *ptrs, int size)
Definition: backtrace.cpp:276
void write_symbols(void *const *addresses, int size, std::ostream &out)
Definition: backtrace.cpp:286
int trace(void **, int)
Definition: backtrace.cpp:66
std::string get_symbol(void *ptr)
Definition: backtrace.cpp:266

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:11