Main MRPT website > C++ reference for MRPT 1.9.9
backtrace.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "base-precomp.h" // Precompiled headers
11 
12 #include <mrpt/utils/bits.h>
13 #include <mrpt/system/backtrace.h>
14 
15 #ifdef MRPT_OS_WINDOWS
16 #define WIN32_LEAN_AND_MEAN
17 #include <windows.h>
18 #include <DbgHelp.h>
19 #else
20 #include <execinfo.h>
21 #include <dlfcn.h> // dladdr()
22 #include <cxxabi.h> // __cxa_demangle()
23 #include <cstdlib>
24 #include <string>
25 #include <sstream>
26 #include <iostream>
27 #endif
28 
30 {
31  out_bt.backtrace_levels.clear();
32  const unsigned int framesToSkip =
33  1; // skip *this* function from the backtrace
34  const unsigned int framesToCapture = 64;
35 
36 #ifdef MRPT_OS_WINDOWS
37  void* backTrace[framesToCapture]{};
38 
39  SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
40  const HANDLE hProcess = GetCurrentProcess();
41  if (!SymInitialize(
42  hProcess, nullptr /* UserSearchPath */, TRUE /*fInvadeProcess*/))
43  {
44  std::cerr
45  << "[mrpt::system::getCallStackBackTrace] Error in SymInitialize()!"
46  << std::endl;
47  return;
48  }
49 
50  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
51  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
52  pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
53  pSymbol->MaxNameLen = MAX_SYM_NAME;
54 
55  const USHORT nFrames = CaptureStackBackTrace(
56  framesToSkip, framesToCapture, backTrace, nullptr);
57  for (unsigned int i = 0; i < nFrames; i++)
58  {
59  TCallStackEntry cse;
60  cse.address = backTrace[i];
61 
62  if (!SymFromAddr(hProcess, (DWORD64)cse.address, nullptr, pSymbol))
63  {
64  cse.symbolName = "???";
65  cse.symbolNameOriginal = "???";
66  out_bt.backtrace_levels.emplace_back(cse);
67  continue;
68  }
69  SYMBOL_INFO& si = *pSymbol;
70 
71  cse.symbolNameOriginal = si.Name;
72  char undecorated_name[1024];
73  if (!UnDecorateSymbolName(
74  si.Name, undecorated_name, sizeof(undecorated_name),
75  UNDNAME_COMPLETE))
76  {
78  }
79  else
80  {
81  cse.symbolName = std::string(undecorated_name);
82  }
83 
84  out_bt.backtrace_levels.emplace_back(cse);
85  }
86 #else
87  // Based on: https://gist.github.com/fmela/591333
88  void* callstack[framesToCapture];
89  const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
90  int nFrames = ::backtrace(callstack, nMaxFrames);
91  char** symbols = ::backtrace_symbols(callstack, nFrames);
92 
93  for (int i = (int)framesToSkip; i < nFrames; i++)
94  {
95  TCallStackEntry cse;
96  cse.address = callstack[i];
97 
98  Dl_info info;
99  if (dladdr(callstack[i], &info) && info.dli_sname)
100  {
101  char* demangled = NULL;
102  int status = -1;
103  if (info.dli_sname[0] == '_')
104  {
105  demangled =
106  abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
107  }
108  cse.symbolNameOriginal =
109  info.dli_sname == 0 ? symbols[i] : info.dli_sname;
110  cse.symbolName =
111  status == 0 ? std::string(demangled) : cse.symbolNameOriginal;
112  free(demangled);
113  }
114  out_bt.backtrace_levels.emplace_back(cse);
115  }
116  free(symbols);
117 #endif
118 }
119 
122 {
123  std::ostringstream trace_buf;
124  trace_buf << "Callstack backtrace:" << std::endl;
125  for (unsigned int i = 0; i < this->backtrace_levels.size(); i++)
126  {
127  trace_buf << mrpt::format(
128  "[%-2d] %*p %s", i, int(2 + sizeof(void*) * 2),
129  backtrace_levels[i].address,
130  backtrace_levels[i].symbolName.c_str())
131  << std::endl;
132  }
133  return trace_buf.str();
134 }
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Used in getCallStackBackTrace()
Definition: backtrace.h:20
GLuint buffer
Definition: glext.h:3917
void getCallStackBackTrace(TCallStackBackTrace &out_bt)
Returns a list of strings representing the current call stack backtrace.
Definition: backtrace.cpp:29
void * address
Address of the calling point.
Definition: backtrace.h:24
std::string symbolName
Demangled symbol name.
Definition: backtrace.h:26
std::vector< TCallStackEntry > backtrace_levels
Definition: backtrace.h:39
GLsizei const GLchar ** string
Definition: glext.h:4101
#define TRUE
Definition: jmorecfg.h:219
std::string symbolNameOriginal
Original (before demangle) symbol name.
Definition: backtrace.h:28
See: getCallStackBackTrace()
Definition: backtrace.h:36
_u8 status
Definition: rplidar_cmd.h:20
GLuint address
Definition: glext.h:6947
std::string asString() const
Prints all backtrace entries, one per line in a human-readable format.
Definition: backtrace.cpp:121



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019