MRPT  2.0.5
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/demangle.h>
13 #include <mrpt/core/format.h>
14 #include <mrpt/system/backtrace.h>
15 
16 #include <iostream>
17 #include <sstream>
18 
19 #ifdef _WIN32
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 //
23 #include <DbgHelp.h>
24 #else
25 #include <dlfcn.h> // dladdr()
26 #include <execinfo.h>
27 
28 #include <cstdlib>
29 #include <iostream>
30 #include <sstream>
31 #include <string>
32 #endif
33 
35 {
36  out_bt.backtrace_levels.clear();
37  // skip *this* function from the backtrace
38  const unsigned int framesToSkip = 1;
39  const unsigned int framesToCapture = 64;
40 
41 #ifdef _WIN32
42  void* backTrace[framesToCapture]{};
43 
44  SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
45  const HANDLE hProcess = GetCurrentProcess();
46  if (!SymInitialize(
47  hProcess, nullptr /* UserSearchPath */, TRUE /*fInvadeProcess*/))
48  {
49  std::cerr
50  << "[mrpt::system::getCallStackBackTrace] Error in SymInitialize()!"
51  << std::endl;
52  return;
53  }
54 
55  char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
56  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
57  pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
58  pSymbol->MaxNameLen = MAX_SYM_NAME;
59 
60  const USHORT nFrames = CaptureStackBackTrace(
61  framesToSkip, framesToCapture, backTrace, nullptr);
62  for (unsigned int i = 0; i < nFrames; i++)
63  {
64  TCallStackEntry cse;
65  cse.address = backTrace[i];
66 
67  if (!SymFromAddr(hProcess, (DWORD64)cse.address, nullptr, pSymbol))
68  {
69  cse.symbolName = "???";
70  cse.symbolNameOriginal = "???";
71  out_bt.backtrace_levels.emplace_back(cse);
72  continue;
73  }
74  SYMBOL_INFO& si = *pSymbol;
75 
76  cse.symbolNameOriginal = si.Name;
77  cse.symbolName = mrpt::demangle(si.Name);
78 
79  out_bt.backtrace_levels.emplace_back(cse);
80  }
81 #else
82  // Based on: https://gist.github.com/fmela/591333
83  void* callstack[framesToCapture];
84  const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
85  int nFrames = ::backtrace(callstack, nMaxFrames);
86  char** symbols = ::backtrace_symbols(callstack, nFrames);
87 
88  for (int i = (int)framesToSkip; i < nFrames; i++)
89  {
90  TCallStackEntry cse;
91  cse.address = callstack[i];
92 
93  Dl_info info;
94  if (dladdr(callstack[i], &info) && info.dli_sname)
95  {
96  cse.symbolNameOriginal =
97  info.dli_sname == nullptr ? symbols[i] : info.dli_sname;
99  }
100  out_bt.backtrace_levels.emplace_back(cse);
101  }
102  free(symbols);
103 #endif
104 }
105 
108 {
109  std::ostringstream trace_buf;
110  trace_buf << "Callstack backtrace:" << std::endl;
111  for (std::size_t i = 0; i < this->backtrace_levels.size(); i++)
112  {
113  trace_buf << mrpt::format(
114  "[%-2d] %*p %s", static_cast<int>(i),
115  int(2 + sizeof(void*) * 2),
116  backtrace_levels[i].address,
117  backtrace_levels[i].symbolName.c_str())
118  << std::endl;
119  }
120  return trace_buf.str();
121 }
Used in getCallStackBackTrace()
Definition: backtrace.h:17
std::string std::string format(std::string_view fmt, ARGS &&... args)
Definition: format.h:26
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
std::string demangle(const std::string &symbolName)
Demangle a C++ symbol name (works on both Windows and Unices)
Definition: demangle.cpp:30
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:107
void getCallStackBackTrace(TCallStackBackTrace &out_bt)
Returns a list of strings representing the current call stack backtrace.
Definition: backtrace.cpp:34



Page generated by Doxygen 1.8.14 for MRPT 2.0.5 Git: ecc95703f Thu Jul 2 07:56:41 2020 +0200 at jue jul 2 08:00:14 CEST 2020