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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: c7a3bec24 Sun Mar 29 18:33:13 2020 +0200 at dom mar 29 18:50:38 CEST 2020