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



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at miƩ 12 jul 2023 10:03:34 CEST