File indexing completed on 2025-03-09 05:09:08
0001 /* 0002 * backward.hpp 0003 * Copyright 2013 Google Inc. All Rights Reserved. 0004 * 0005 * Permission is hereby granted, free of charge, to any person obtaining a copy 0006 * of this software and associated documentation files (the "Software"), to deal 0007 * in the Software without restriction, including without limitation the rights 0008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0009 * copies of the Software, and to permit persons to whom the Software is 0010 * furnished to do so, subject to the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included in 0013 * all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 0021 * SOFTWARE. 0022 */ 0023 0024 #ifndef H_6B9572DA_A64B_49E6_B234_051480991C89 0025 #define H_6B9572DA_A64B_49E6_B234_051480991C89 0026 0027 #ifndef __cplusplus 0028 #error "It's not going to compile without a C++ compiler..." 0029 #endif 0030 0031 #if defined(BACKWARD_CXX11) 0032 #elif defined(BACKWARD_CXX98) 0033 #else 0034 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) 0035 #define BACKWARD_CXX11 0036 #define BACKWARD_ATLEAST_CXX11 0037 #define BACKWARD_ATLEAST_CXX98 0038 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 0039 #define BACKWARD_ATLEAST_CXX17 0040 #endif 0041 #else 0042 #define BACKWARD_CXX98 0043 #define BACKWARD_ATLEAST_CXX98 0044 #endif 0045 #endif 0046 0047 // You can define one of the following (or leave it to the auto-detection): 0048 // 0049 // #define BACKWARD_SYSTEM_LINUX 0050 // - specialization for linux 0051 // 0052 // #define BACKWARD_SYSTEM_DARWIN 0053 // - specialization for Mac OS X 10.5 and later. 0054 // 0055 // #define BACKWARD_SYSTEM_WINDOWS 0056 // - specialization for Windows (Clang 9 and MSVC2017) 0057 // 0058 // #define BACKWARD_SYSTEM_UNKNOWN 0059 // - placebo implementation, does nothing. 0060 // 0061 #if defined(BACKWARD_SYSTEM_LINUX) 0062 #elif defined(BACKWARD_SYSTEM_DARWIN) 0063 #elif defined(BACKWARD_SYSTEM_UNKNOWN) 0064 #elif defined(BACKWARD_SYSTEM_WINDOWS) 0065 #else 0066 #if defined(__linux) || defined(__linux__) 0067 #define BACKWARD_SYSTEM_LINUX 0068 #elif defined(__APPLE__) 0069 #define BACKWARD_SYSTEM_DARWIN 0070 #elif defined(_WIN32) 0071 #define BACKWARD_SYSTEM_WINDOWS 0072 #else 0073 #define BACKWARD_SYSTEM_UNKNOWN 0074 #endif 0075 #endif 0076 0077 #define NOINLINE __attribute__((noinline)) 0078 0079 #include <algorithm> 0080 #include <cctype> 0081 #include <cstdio> 0082 #include <cstdlib> 0083 #include <cstring> 0084 #include <fstream> 0085 #include <iomanip> 0086 #include <iostream> 0087 #include <limits> 0088 #include <new> 0089 #include <sstream> 0090 #include <streambuf> 0091 #include <string> 0092 #include <vector> 0093 #include <exception> 0094 #include <iterator> 0095 #include <filesystem> 0096 0097 #if defined(BACKWARD_SYSTEM_LINUX) 0098 0099 // On linux, backtrace can back-trace or "walk" the stack using the following 0100 // libraries: 0101 // 0102 // #define BACKWARD_HAS_UNWIND 1 0103 // - unwind comes from libgcc, but I saw an equivalent inside clang itself. 0104 // - with unwind, the stacktrace is as accurate as it can possibly be, since 0105 // this is used by the C++ runtime in gcc/clang for stack unwinding on 0106 // exception. 0107 // - normally libgcc is already linked to your program by default. 0108 // 0109 // #define BACKWARD_HAS_LIBUNWIND 1 0110 // - libunwind provides, in some cases, a more accurate stacktrace as it knows 0111 // to decode signal handler frames and lets us edit the context registers when 0112 // unwinding, allowing stack traces over bad function references. 0113 // 0114 // #define BACKWARD_HAS_BACKTRACE == 1 0115 // - backtrace seems to be a little bit more portable than libunwind, but on 0116 // linux, it uses unwind anyway, but abstract away a tiny information that is 0117 // sadly really important in order to get perfectly accurate stack traces. 0118 // - backtrace is part of the (e)glib library. 0119 // 0120 // The default is: 0121 // #define BACKWARD_HAS_UNWIND == 1 0122 // 0123 // Note that only one of the define should be set to 1 at a time. 0124 // 0125 #if BACKWARD_HAS_UNWIND == 1 0126 #elif BACKWARD_HAS_LIBUNWIND == 1 0127 #elif BACKWARD_HAS_BACKTRACE == 1 0128 #else 0129 #undef BACKWARD_HAS_UNWIND 0130 #define BACKWARD_HAS_UNWIND 1 0131 #undef BACKWARD_HAS_LIBUNWIND 0132 #define BACKWARD_HAS_LIBUNWIND 0 0133 #undef BACKWARD_HAS_BACKTRACE 0134 #define BACKWARD_HAS_BACKTRACE 0 0135 #endif 0136 0137 // On linux, backward can extract detailed information about a stack trace 0138 // using one of the following libraries: 0139 // 0140 // #define BACKWARD_HAS_DW 1 0141 // - libdw gives you the most juicy details out of your stack traces: 0142 // - object filename 0143 // - function name 0144 // - source filename 0145 // - line and column numbers 0146 // - source code snippet (assuming the file is accessible) 0147 // - variable names (if not optimized out) 0148 // - variable values (not supported by backward-cpp) 0149 // - You need to link with the lib "dw": 0150 // - apt-get install libdw-dev 0151 // - g++/clang++ -ldw ... 0152 // 0153 // #define BACKWARD_HAS_BFD 1 0154 // - With libbfd, you get a fair amount of details: 0155 // - object filename 0156 // - function name 0157 // - source filename 0158 // - line numbers 0159 // - source code snippet (assuming the file is accessible) 0160 // - You need to link with the lib "bfd": 0161 // - apt-get install binutils-dev 0162 // - g++/clang++ -lbfd ... 0163 // 0164 // #define BACKWARD_HAS_DWARF 1 0165 // - libdwarf gives you the most juicy details out of your stack traces: 0166 // - object filename 0167 // - function name 0168 // - source filename 0169 // - line and column numbers 0170 // - source code snippet (assuming the file is accessible) 0171 // - variable names (if not optimized out) 0172 // - variable values (not supported by backward-cpp) 0173 // - You need to link with the lib "dwarf": 0174 // - apt-get install libdwarf-dev 0175 // - g++/clang++ -ldwarf ... 0176 // 0177 // #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 0178 // - backtrace provides minimal details for a stack trace: 0179 // - object filename 0180 // - function name 0181 // - backtrace is part of the (e)glib library. 0182 // 0183 // The default is: 0184 // #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1 0185 // 0186 // Note that only one of the define should be set to 1 at a time. 0187 // 0188 #if BACKWARD_HAS_DW == 1 0189 #elif BACKWARD_HAS_BFD == 1 0190 #elif BACKWARD_HAS_DWARF == 1 0191 #elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 0192 #else 0193 #undef BACKWARD_HAS_DW 0194 #define BACKWARD_HAS_DW 0 0195 #undef BACKWARD_HAS_BFD 0196 #define BACKWARD_HAS_BFD 0 0197 #undef BACKWARD_HAS_DWARF 0198 #define BACKWARD_HAS_DWARF 0 0199 #undef BACKWARD_HAS_BACKTRACE_SYMBOL 0200 #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 0201 #endif 0202 0203 #include <cxxabi.h> 0204 #include <fcntl.h> 0205 #ifdef __ANDROID__ 0206 // Old Android API levels define _Unwind_Ptr in both link.h and 0207 // unwind.h Rename the one in link.h as we are not going to be using 0208 // it 0209 #define _Unwind_Ptr _Unwind_Ptr_Custom 0210 #include <link.h> 0211 #undef _Unwind_Ptr 0212 #else 0213 #include <link.h> 0214 #endif 0215 #if defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \ 0216 defined(__POWERPC__) 0217 // Linux kernel header required for the struct pt_regs definition 0218 // to access the NIP (Next Instruction Pointer) register value 0219 #include <asm/ptrace.h> 0220 #endif 0221 #include <signal.h> 0222 #include <sys/stat.h> 0223 #include <syscall.h> 0224 #include <unistd.h> 0225 #ifndef _GNU_SOURCE 0226 #define _GNU_SOURCE 0227 #include <dlfcn.h> 0228 #undef _GNU_SOURCE 0229 #else 0230 #include <dlfcn.h> 0231 #endif 0232 0233 #if BACKWARD_HAS_BFD == 1 0234 // NOTE: defining PACKAGE{,_VERSION} is required before including 0235 // bfd.h on some platforms, see also: 0236 // https://sourceware.org/bugzilla/show_bug.cgi?id=14243 0237 #ifndef PACKAGE 0238 #define PACKAGE 0239 #endif 0240 #ifndef PACKAGE_VERSION 0241 #define PACKAGE_VERSION 0242 #endif 0243 #include <bfd.h> 0244 #endif 0245 0246 #if BACKWARD_HAS_DW == 1 0247 #include <dwarf.h> 0248 #include <elfutils/libdw.h> 0249 #include <elfutils/libdwfl.h> 0250 #endif 0251 0252 #if BACKWARD_HAS_DWARF == 1 0253 #include <algorithm> 0254 #include <dwarf.h> 0255 #include <libdwarf.h> 0256 #include <libelf.h> 0257 #include <map> 0258 #endif 0259 0260 #if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) 0261 // then we shall rely on backtrace 0262 #include <execinfo.h> 0263 #endif 0264 0265 #endif // defined(BACKWARD_SYSTEM_LINUX) 0266 0267 #if defined(BACKWARD_SYSTEM_DARWIN) 0268 // On Darwin, backtrace can back-trace or "walk" the stack using the following 0269 // libraries: 0270 // 0271 // #define BACKWARD_HAS_UNWIND 1 0272 // - unwind comes from libgcc, but I saw an equivalent inside clang itself. 0273 // - with unwind, the stacktrace is as accurate as it can possibly be, since 0274 // this is used by the C++ runtime in gcc/clang for stack unwinding on 0275 // exception. 0276 // - normally libgcc is already linked to your program by default. 0277 // 0278 // #define BACKWARD_HAS_LIBUNWIND 1 0279 // - libunwind comes from clang, which implements an API compatible version. 0280 // - libunwind provides, in some cases, a more accurate stacktrace as it knows 0281 // to decode signal handler frames and lets us edit the context registers when 0282 // unwinding, allowing stack traces over bad function references. 0283 // 0284 // #define BACKWARD_HAS_BACKTRACE == 1 0285 // - backtrace is available by default, though it does not produce as much 0286 // information as another library might. 0287 // 0288 // The default is: 0289 // #define BACKWARD_HAS_UNWIND == 1 0290 // 0291 // Note that only one of the define should be set to 1 at a time. 0292 // 0293 #if BACKWARD_HAS_UNWIND == 1 0294 #elif BACKWARD_HAS_BACKTRACE == 1 0295 #elif BACKWARD_HAS_LIBUNWIND == 1 0296 #else 0297 #undef BACKWARD_HAS_UNWIND 0298 #define BACKWARD_HAS_UNWIND 1 0299 #undef BACKWARD_HAS_BACKTRACE 0300 #define BACKWARD_HAS_BACKTRACE 0 0301 #undef BACKWARD_HAS_LIBUNWIND 0302 #define BACKWARD_HAS_LIBUNWIND 0 0303 #endif 0304 0305 // On Darwin, backward can extract detailed information about a stack trace 0306 // using one of the following libraries: 0307 // 0308 // #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 0309 // - backtrace provides minimal details for a stack trace: 0310 // - object filename 0311 // - function name 0312 // 0313 // The default is: 0314 // #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1 0315 // 0316 #if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 0317 #else 0318 #undef BACKWARD_HAS_BACKTRACE_SYMBOL 0319 #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 0320 #endif 0321 0322 #include <cxxabi.h> 0323 #include <fcntl.h> 0324 #include <pthread.h> 0325 #include <signal.h> 0326 #include <sys/stat.h> 0327 #include <unistd.h> 0328 0329 #if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) 0330 #include <execinfo.h> 0331 #endif 0332 #endif // defined(BACKWARD_SYSTEM_DARWIN) 0333 0334 #if defined(BACKWARD_SYSTEM_WINDOWS) 0335 0336 #include <condition_variable> 0337 #include <mutex> 0338 #include <thread> 0339 0340 #include <basetsd.h> 0341 0342 #ifdef _WIN64 0343 typedef SSIZE_T ssize_t; 0344 #else 0345 typedef int ssize_t; 0346 #endif 0347 0348 #ifndef NOMINMAX 0349 #define NOMINMAX 0350 #endif 0351 #include <windows.h> 0352 #include <winnt.h> 0353 0354 #include <psapi.h> 0355 #include <signal.h> 0356 0357 #ifndef __clang__ 0358 #undef NOINLINE 0359 #define NOINLINE __declspec(noinline) 0360 #endif 0361 0362 #ifdef _MSC_VER 0363 #pragma comment(lib, "psapi.lib") 0364 #pragma comment(lib, "dbghelp.lib") 0365 #endif 0366 0367 // Comment / packing is from stackoverflow: 0368 // https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227 0369 // Some versions of imagehlp.dll lack the proper packing directives themselves 0370 // so we need to do it. 0371 #pragma pack(push, before_imagehlp, 8) 0372 #include <imagehlp.h> 0373 #pragma pack(pop, before_imagehlp) 0374 0375 // TODO maybe these should be undefined somewhere else? 0376 #undef BACKWARD_HAS_UNWIND 0377 #undef BACKWARD_HAS_BACKTRACE 0378 #if BACKWARD_HAS_PDB_SYMBOL == 1 0379 #else 0380 #undef BACKWARD_HAS_PDB_SYMBOL 0381 #define BACKWARD_HAS_PDB_SYMBOL 1 0382 #endif 0383 0384 #endif 0385 0386 #if BACKWARD_HAS_UNWIND == 1 0387 0388 #include <unwind.h> 0389 // while gcc's unwind.h defines something like that: 0390 // extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); 0391 // extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *); 0392 // 0393 // clang's unwind.h defines something like this: 0394 // uintptr_t _Unwind_GetIP(struct _Unwind_Context* __context); 0395 // 0396 // Even if the _Unwind_GetIPInfo can be linked to, it is not declared, worse we 0397 // cannot just redeclare it because clang's unwind.h doesn't define _Unwind_Ptr 0398 // anyway. 0399 // 0400 // Luckily we can play on the fact that the guard macros have a different name: 0401 #ifdef __CLANG_UNWIND_H 0402 // In fact, this function still comes from libgcc (on my different linux boxes, 0403 // clang links against libgcc). 0404 #include <inttypes.h> 0405 extern "C" uintptr_t _Unwind_GetIPInfo(_Unwind_Context *, int *); 0406 #endif 0407 0408 #endif // BACKWARD_HAS_UNWIND == 1 0409 0410 #if BACKWARD_HAS_LIBUNWIND == 1 0411 #define UNW_LOCAL_ONLY 0412 #include <libunwind.h> 0413 #endif // BACKWARD_HAS_LIBUNWIND == 1 0414 0415 #ifdef BACKWARD_ATLEAST_CXX11 0416 #include <unordered_map> 0417 #include <utility> // for std::swap 0418 namespace backward { 0419 namespace details { 0420 template <typename K, typename V> struct hashtable { 0421 typedef std::unordered_map<K, V> type; 0422 }; 0423 using std::move; 0424 } // namespace details 0425 } // namespace backward 0426 #else // NOT BACKWARD_ATLEAST_CXX11 0427 #define nullptr NULL 0428 #define override 0429 #include <map> 0430 namespace backward { 0431 namespace details { 0432 template <typename K, typename V> struct hashtable { 0433 typedef std::map<K, V> type; 0434 }; 0435 template <typename T> const T &move(const T &v) { return v; } 0436 template <typename T> T &move(T &v) { return v; } 0437 } // namespace details 0438 } // namespace backward 0439 #endif // BACKWARD_ATLEAST_CXX11 0440 0441 namespace backward { 0442 namespace details { 0443 #if defined(BACKWARD_SYSTEM_WINDOWS) 0444 const char kBackwardPathDelimiter[] = ";"; 0445 #else 0446 const char kBackwardPathDelimiter[] = ":"; 0447 #endif 0448 } // namespace details 0449 } // namespace backward 0450 0451 namespace backward { 0452 0453 namespace system_tag { 0454 struct linux_tag; // seems that I cannot call that "linux" because the name 0455 // is already defined... so I am adding _tag everywhere. 0456 struct darwin_tag; 0457 struct windows_tag; 0458 struct unknown_tag; 0459 0460 #if defined(BACKWARD_SYSTEM_LINUX) 0461 typedef linux_tag current_tag; 0462 #elif defined(BACKWARD_SYSTEM_DARWIN) 0463 typedef darwin_tag current_tag; 0464 #elif defined(BACKWARD_SYSTEM_WINDOWS) 0465 typedef windows_tag current_tag; 0466 #elif defined(BACKWARD_SYSTEM_UNKNOWN) 0467 typedef unknown_tag current_tag; 0468 #else 0469 #error "May I please get my system defines?" 0470 #endif 0471 } // namespace system_tag 0472 0473 namespace trace_resolver_tag { 0474 #if defined(BACKWARD_SYSTEM_LINUX) 0475 struct libdw; 0476 struct libbfd; 0477 struct libdwarf; 0478 struct backtrace_symbol; 0479 0480 #if BACKWARD_HAS_DW == 1 0481 typedef libdw current; 0482 #elif BACKWARD_HAS_BFD == 1 0483 typedef libbfd current; 0484 #elif BACKWARD_HAS_DWARF == 1 0485 typedef libdwarf current; 0486 #elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 0487 typedef backtrace_symbol current; 0488 #else 0489 #error "You shall not pass, until you know what you want." 0490 #endif 0491 #elif defined(BACKWARD_SYSTEM_DARWIN) 0492 struct backtrace_symbol; 0493 0494 #if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 0495 typedef backtrace_symbol current; 0496 #else 0497 #error "You shall not pass, until you know what you want." 0498 #endif 0499 #elif defined(BACKWARD_SYSTEM_WINDOWS) 0500 struct pdb_symbol; 0501 #if BACKWARD_HAS_PDB_SYMBOL == 1 0502 typedef pdb_symbol current; 0503 #else 0504 #error "You shall not pass, until you know what you want." 0505 #endif 0506 #endif 0507 } // namespace trace_resolver_tag 0508 0509 namespace details { 0510 0511 template <typename T> struct rm_ptr { typedef T type; }; 0512 0513 template <typename T> struct rm_ptr<T *> { typedef T type; }; 0514 0515 template <typename T> struct rm_ptr<const T *> { typedef const T type; }; 0516 0517 template <typename R, typename T, R (*F)(T)> struct deleter { 0518 template <typename U> void operator()(U &ptr) const { (*F)(ptr); } 0519 }; 0520 0521 template <typename T> struct default_delete { 0522 void operator()(T &ptr) const { delete ptr; } 0523 }; 0524 0525 template <typename T, typename Deleter = deleter<void, void *, &::free> > 0526 class handle { 0527 struct dummy; 0528 T _val; 0529 bool _empty; 0530 0531 #ifdef BACKWARD_ATLEAST_CXX11 0532 handle(const handle &) = delete; 0533 handle &operator=(const handle &) = delete; 0534 #endif 0535 0536 public: 0537 ~handle() { 0538 if (!_empty) { 0539 Deleter()(_val); 0540 } 0541 } 0542 0543 explicit handle() : _val(), _empty(true) {} 0544 explicit handle(T val) : _val(val), _empty(false) { 0545 if (!_val) 0546 _empty = true; 0547 } 0548 0549 #ifdef BACKWARD_ATLEAST_CXX11 0550 handle(handle &&from) : _empty(true) { swap(from); } 0551 handle &operator=(handle &&from) { 0552 swap(from); 0553 return *this; 0554 } 0555 #else 0556 explicit handle(const handle &from) : _empty(true) { 0557 // some sort of poor man's move semantic. 0558 swap(const_cast<handle &>(from)); 0559 } 0560 handle &operator=(const handle &from) { 0561 // some sort of poor man's move semantic. 0562 swap(const_cast<handle &>(from)); 0563 return *this; 0564 } 0565 #endif 0566 0567 void reset(T new_val) { 0568 handle tmp(new_val); 0569 swap(tmp); 0570 } 0571 0572 void update(T new_val) { 0573 _val = new_val; 0574 _empty = !static_cast<bool>(new_val); 0575 } 0576 0577 operator const dummy *() const { 0578 if (_empty) { 0579 return nullptr; 0580 } 0581 return reinterpret_cast<const dummy *>(_val); 0582 } 0583 T get() { return _val; } 0584 T release() { 0585 _empty = true; 0586 return _val; 0587 } 0588 void swap(handle &b) { 0589 using std::swap; 0590 swap(b._val, _val); // can throw, we are safe here. 0591 swap(b._empty, _empty); // should not throw: if you cannot swap two 0592 // bools without throwing... It's a lost cause anyway! 0593 } 0594 0595 T &operator->() { return _val; } 0596 const T &operator->() const { return _val; } 0597 0598 typedef typename rm_ptr<T>::type &ref_t; 0599 typedef const typename rm_ptr<T>::type &const_ref_t; 0600 ref_t operator*() { return *_val; } 0601 const_ref_t operator*() const { return *_val; } 0602 ref_t operator[](size_t idx) { return _val[idx]; } 0603 0604 // Watch out, we've got a badass over here 0605 T *operator&() { 0606 _empty = false; 0607 return &_val; 0608 } 0609 }; 0610 0611 // Default demangler implementation (do nothing). 0612 template <typename TAG> struct demangler_impl { 0613 static std::string demangle(const char *funcname) { return funcname; } 0614 }; 0615 0616 #if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN) 0617 0618 template <> struct demangler_impl<system_tag::current_tag> { 0619 demangler_impl() : _demangle_buffer_length(0) {} 0620 0621 std::string demangle(const char *funcname) { 0622 using namespace details; 0623 char *result = abi::__cxa_demangle(funcname, _demangle_buffer.get(), 0624 &_demangle_buffer_length, nullptr); 0625 if (result) { 0626 _demangle_buffer.update(result); 0627 return result; 0628 } 0629 return funcname; 0630 } 0631 0632 private: 0633 details::handle<char *> _demangle_buffer; 0634 size_t _demangle_buffer_length; 0635 }; 0636 0637 #endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN 0638 0639 struct demangler : public demangler_impl<system_tag::current_tag> {}; 0640 0641 // Split a string on the platform's PATH delimiter. Example: if delimiter 0642 // is ":" then: 0643 // "" --> [] 0644 // ":" --> ["",""] 0645 // "::" --> ["","",""] 0646 // "/a/b/c" --> ["/a/b/c"] 0647 // "/a/b/c:/d/e/f" --> ["/a/b/c","/d/e/f"] 0648 // etc. 0649 inline std::vector<std::string> split_source_prefixes(const std::string &s) { 0650 std::vector<std::string> out; 0651 size_t last = 0; 0652 size_t next = 0; 0653 size_t delimiter_size = sizeof(kBackwardPathDelimiter) - 1; 0654 while ((next = s.find(kBackwardPathDelimiter, last)) != std::string::npos) { 0655 out.push_back(s.substr(last, next - last)); 0656 last = next + delimiter_size; 0657 } 0658 if (last <= s.length()) { 0659 out.push_back(s.substr(last)); 0660 } 0661 return out; 0662 } 0663 0664 } // namespace details 0665 0666 /*************** A TRACE ***************/ 0667 0668 struct Trace { 0669 void *addr; 0670 size_t idx; 0671 0672 Trace() : addr(nullptr), idx(0) {} 0673 0674 explicit Trace(void *_addr, size_t _idx) : addr(_addr), idx(_idx) {} 0675 }; 0676 0677 struct ResolvedTrace : public Trace { 0678 0679 struct SourceLoc { 0680 std::string function; 0681 std::string filename; 0682 unsigned line; 0683 unsigned col; 0684 0685 SourceLoc() : line(0), col(0) {} 0686 0687 bool operator==(const SourceLoc &b) const { 0688 return function == b.function && filename == b.filename && 0689 line == b.line && col == b.col; 0690 } 0691 0692 bool operator!=(const SourceLoc &b) const { return !(*this == b); } 0693 }; 0694 0695 // In which binary object this trace is located. 0696 std::string object_filename; 0697 0698 // The function in the object that contain the trace. This is not the same 0699 // as source.function which can be an function inlined in object_function. 0700 std::string object_function; 0701 0702 // The source location of this trace. It is possible for filename to be 0703 // empty and for line/col to be invalid (value 0) if this information 0704 // couldn't be deduced, for example if there is no debug information in the 0705 // binary object. 0706 SourceLoc source; 0707 0708 // An optionals list of "inliners". All the successive sources location 0709 // from where the source location of the trace (the attribute right above) 0710 // is inlined. It is especially useful when you compiled with optimization. 0711 typedef std::vector<SourceLoc> source_locs_t; 0712 source_locs_t inliners; 0713 0714 ResolvedTrace() : Trace() {} 0715 ResolvedTrace(const Trace &mini_trace) : Trace(mini_trace) {} 0716 }; 0717 0718 /*************** STACK TRACE ***************/ 0719 0720 // default implemention. 0721 template <typename TAG> class StackTraceImpl { 0722 public: 0723 size_t size() const { return 0; } 0724 Trace operator[](size_t) const { return Trace(); } 0725 size_t load_here(size_t = 0) { return 0; } 0726 size_t load_from(void *, size_t = 0, void * = nullptr, void * = nullptr) { 0727 return 0; 0728 } 0729 size_t thread_id() const { return 0; } 0730 void skip_n_firsts(size_t) {} 0731 }; 0732 0733 class StackTraceImplBase { 0734 public: 0735 StackTraceImplBase() 0736 : _thread_id(0), _skip(0), _context(nullptr), _error_addr(nullptr) {} 0737 0738 size_t thread_id() const { return _thread_id; } 0739 0740 void skip_n_firsts(size_t n) { _skip = n; } 0741 0742 protected: 0743 void load_thread_info() { 0744 #ifdef BACKWARD_SYSTEM_LINUX 0745 #ifndef __ANDROID__ 0746 _thread_id = static_cast<size_t>(syscall(SYS_gettid)); 0747 #else 0748 _thread_id = static_cast<size_t>(gettid()); 0749 #endif 0750 if (_thread_id == static_cast<size_t>(getpid())) { 0751 // If the thread is the main one, let's hide that. 0752 // I like to keep little secret sometimes. 0753 _thread_id = 0; 0754 } 0755 #elif defined(BACKWARD_SYSTEM_DARWIN) 0756 _thread_id = reinterpret_cast<size_t>(pthread_self()); 0757 if (pthread_main_np() == 1) { 0758 // If the thread is the main one, let's hide that. 0759 _thread_id = 0; 0760 } 0761 #endif 0762 } 0763 0764 void set_context(void *context) { _context = context; } 0765 void *context() const { return _context; } 0766 0767 void set_error_addr(void *error_addr) { _error_addr = error_addr; } 0768 void *error_addr() const { return _error_addr; } 0769 0770 size_t skip_n_firsts() const { return _skip; } 0771 0772 private: 0773 size_t _thread_id; 0774 size_t _skip; 0775 void *_context; 0776 void *_error_addr; 0777 }; 0778 0779 class StackTraceImplHolder : public StackTraceImplBase { 0780 public: 0781 size_t size() const { 0782 return (_stacktrace.size() >= skip_n_firsts()) 0783 ? _stacktrace.size() - skip_n_firsts() 0784 : 0; 0785 } 0786 Trace operator[](size_t idx) const { 0787 if (idx >= size()) { 0788 return Trace(); 0789 } 0790 return Trace(_stacktrace[idx + skip_n_firsts()], idx); 0791 } 0792 void *const *begin() const { 0793 if (size()) { 0794 return &_stacktrace[skip_n_firsts()]; 0795 } 0796 return nullptr; 0797 } 0798 0799 protected: 0800 std::vector<void *> _stacktrace; 0801 }; 0802 0803 #if BACKWARD_HAS_UNWIND == 1 0804 0805 namespace details { 0806 0807 template <typename F> class Unwinder { 0808 public: 0809 size_t operator()(F &f, size_t depth) { 0810 _f = &f; 0811 _index = -1; 0812 _depth = depth; 0813 _Unwind_Backtrace(&this->backtrace_trampoline, this); 0814 if (_index == -1) { 0815 // _Unwind_Backtrace has failed to obtain any backtraces 0816 return 0; 0817 } else { 0818 return static_cast<size_t>(_index); 0819 } 0820 } 0821 0822 private: 0823 F *_f; 0824 ssize_t _index; 0825 size_t _depth; 0826 0827 static _Unwind_Reason_Code backtrace_trampoline(_Unwind_Context *ctx, 0828 void *self) { 0829 return (static_cast<Unwinder *>(self))->backtrace(ctx); 0830 } 0831 0832 _Unwind_Reason_Code backtrace(_Unwind_Context *ctx) { 0833 if (_index >= 0 && static_cast<size_t>(_index) >= _depth) 0834 return _URC_END_OF_STACK; 0835 0836 int ip_before_instruction = 0; 0837 uintptr_t ip = _Unwind_GetIPInfo(ctx, &ip_before_instruction); 0838 0839 if (!ip_before_instruction) { 0840 // calculating 0-1 for unsigned, looks like a possible bug to sanitizers, 0841 // so let's do it explicitly: 0842 if (ip == 0) { 0843 ip = std::numeric_limits<uintptr_t>::max(); // set it to 0xffff... (as 0844 // from casting 0-1) 0845 } else { 0846 ip -= 1; // else just normally decrement it (no overflow/underflow will 0847 // happen) 0848 } 0849 } 0850 0851 if (_index >= 0) { // ignore first frame. 0852 (*_f)(static_cast<size_t>(_index), reinterpret_cast<void *>(ip)); 0853 } 0854 _index += 1; 0855 return _URC_NO_REASON; 0856 } 0857 }; 0858 0859 template <typename F> size_t unwind(F f, size_t depth) { 0860 Unwinder<F> unwinder; 0861 return unwinder(f, depth); 0862 } 0863 0864 } // namespace details 0865 0866 template <> 0867 class StackTraceImpl<system_tag::current_tag> : public StackTraceImplHolder { 0868 public: 0869 NOINLINE 0870 size_t load_here(size_t depth = 32, void *context = nullptr, 0871 void *error_addr = nullptr) { 0872 load_thread_info(); 0873 set_context(context); 0874 set_error_addr(error_addr); 0875 if (depth == 0) { 0876 return 0; 0877 } 0878 _stacktrace.resize(depth); 0879 size_t trace_cnt = details::unwind(callback(*this), depth); 0880 _stacktrace.resize(trace_cnt); 0881 skip_n_firsts(0); 0882 return size(); 0883 } 0884 size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, 0885 void *error_addr = nullptr) { 0886 load_here(depth + 8, context, error_addr); 0887 0888 for (size_t i = 0; i < _stacktrace.size(); ++i) { 0889 if (_stacktrace[i] == addr) { 0890 skip_n_firsts(i); 0891 break; 0892 } 0893 } 0894 0895 _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); 0896 return size(); 0897 } 0898 0899 private: 0900 struct callback { 0901 StackTraceImpl &self; 0902 callback(StackTraceImpl &_self) : self(_self) {} 0903 0904 void operator()(size_t idx, void *addr) { self._stacktrace[idx] = addr; } 0905 }; 0906 }; 0907 0908 #elif BACKWARD_HAS_LIBUNWIND == 1 0909 0910 template <> 0911 class StackTraceImpl<system_tag::current_tag> : public StackTraceImplHolder { 0912 public: 0913 __attribute__((noinline)) size_t load_here(size_t depth = 32, 0914 void *_context = nullptr, 0915 void *_error_addr = nullptr) { 0916 set_context(_context); 0917 set_error_addr(_error_addr); 0918 load_thread_info(); 0919 if (depth == 0) { 0920 return 0; 0921 } 0922 _stacktrace.resize(depth + 1); 0923 0924 int result = 0; 0925 0926 unw_context_t ctx; 0927 size_t index = 0; 0928 0929 // Add the tail call. If the Instruction Pointer is the crash address it 0930 // means we got a bad function pointer dereference, so we "unwind" the 0931 // bad pointer manually by using the return address pointed to by the 0932 // Stack Pointer as the Instruction Pointer and letting libunwind do 0933 // the rest 0934 0935 if (context()) { 0936 ucontext_t *uctx = reinterpret_cast<ucontext_t *>(context()); 0937 #ifdef REG_RIP // x86_64 0938 if (uctx->uc_mcontext.gregs[REG_RIP] == 0939 reinterpret_cast<greg_t>(error_addr())) { 0940 uctx->uc_mcontext.gregs[REG_RIP] = 0941 *reinterpret_cast<size_t *>(uctx->uc_mcontext.gregs[REG_RSP]); 0942 } 0943 _stacktrace[index] = 0944 reinterpret_cast<void *>(uctx->uc_mcontext.gregs[REG_RIP]); 0945 ++index; 0946 ctx = *reinterpret_cast<unw_context_t *>(uctx); 0947 #elif defined(REG_EIP) // x86_32 0948 if (uctx->uc_mcontext.gregs[REG_EIP] == 0949 reinterpret_cast<greg_t>(error_addr())) { 0950 uctx->uc_mcontext.gregs[REG_EIP] = 0951 *reinterpret_cast<size_t *>(uctx->uc_mcontext.gregs[REG_ESP]); 0952 } 0953 _stacktrace[index] = 0954 reinterpret_cast<void *>(uctx->uc_mcontext.gregs[REG_EIP]); 0955 ++index; 0956 ctx = *reinterpret_cast<unw_context_t *>(uctx); 0957 #elif defined(__arm__) 0958 // libunwind uses its own context type for ARM unwinding. 0959 // Copy the registers from the signal handler's context so we can 0960 // unwind 0961 unw_getcontext(&ctx); 0962 ctx.regs[UNW_ARM_R0] = uctx->uc_mcontext.arm_r0; 0963 ctx.regs[UNW_ARM_R1] = uctx->uc_mcontext.arm_r1; 0964 ctx.regs[UNW_ARM_R2] = uctx->uc_mcontext.arm_r2; 0965 ctx.regs[UNW_ARM_R3] = uctx->uc_mcontext.arm_r3; 0966 ctx.regs[UNW_ARM_R4] = uctx->uc_mcontext.arm_r4; 0967 ctx.regs[UNW_ARM_R5] = uctx->uc_mcontext.arm_r5; 0968 ctx.regs[UNW_ARM_R6] = uctx->uc_mcontext.arm_r6; 0969 ctx.regs[UNW_ARM_R7] = uctx->uc_mcontext.arm_r7; 0970 ctx.regs[UNW_ARM_R8] = uctx->uc_mcontext.arm_r8; 0971 ctx.regs[UNW_ARM_R9] = uctx->uc_mcontext.arm_r9; 0972 ctx.regs[UNW_ARM_R10] = uctx->uc_mcontext.arm_r10; 0973 ctx.regs[UNW_ARM_R11] = uctx->uc_mcontext.arm_fp; 0974 ctx.regs[UNW_ARM_R12] = uctx->uc_mcontext.arm_ip; 0975 ctx.regs[UNW_ARM_R13] = uctx->uc_mcontext.arm_sp; 0976 ctx.regs[UNW_ARM_R14] = uctx->uc_mcontext.arm_lr; 0977 ctx.regs[UNW_ARM_R15] = uctx->uc_mcontext.arm_pc; 0978 0979 // If we have crashed in the PC use the LR instead, as this was 0980 // a bad function dereference 0981 if (reinterpret_cast<unsigned long>(error_addr()) == 0982 uctx->uc_mcontext.arm_pc) { 0983 ctx.regs[UNW_ARM_R15] = 0984 uctx->uc_mcontext.arm_lr - sizeof(unsigned long); 0985 } 0986 _stacktrace[index] = reinterpret_cast<void *>(ctx.regs[UNW_ARM_R15]); 0987 ++index; 0988 #elif defined(__APPLE__) && defined(__x86_64__) 0989 unw_getcontext(&ctx); 0990 // OS X's implementation of libunwind uses its own context object 0991 // so we need to convert the passed context to libunwind's format 0992 // (information about the data layout taken from unw_getcontext.s 0993 // in Apple's libunwind source 0994 ctx.data[0] = uctx->uc_mcontext->__ss.__rax; 0995 ctx.data[1] = uctx->uc_mcontext->__ss.__rbx; 0996 ctx.data[2] = uctx->uc_mcontext->__ss.__rcx; 0997 ctx.data[3] = uctx->uc_mcontext->__ss.__rdx; 0998 ctx.data[4] = uctx->uc_mcontext->__ss.__rdi; 0999 ctx.data[5] = uctx->uc_mcontext->__ss.__rsi; 1000 ctx.data[6] = uctx->uc_mcontext->__ss.__rbp; 1001 ctx.data[7] = uctx->uc_mcontext->__ss.__rsp; 1002 ctx.data[8] = uctx->uc_mcontext->__ss.__r8; 1003 ctx.data[9] = uctx->uc_mcontext->__ss.__r9; 1004 ctx.data[10] = uctx->uc_mcontext->__ss.__r10; 1005 ctx.data[11] = uctx->uc_mcontext->__ss.__r11; 1006 ctx.data[12] = uctx->uc_mcontext->__ss.__r12; 1007 ctx.data[13] = uctx->uc_mcontext->__ss.__r13; 1008 ctx.data[14] = uctx->uc_mcontext->__ss.__r14; 1009 ctx.data[15] = uctx->uc_mcontext->__ss.__r15; 1010 ctx.data[16] = uctx->uc_mcontext->__ss.__rip; 1011 1012 // If the IP is the same as the crash address we have a bad function 1013 // dereference The caller's address is pointed to by %rsp, so we 1014 // dereference that value and set it to be the next frame's IP. 1015 if (uctx->uc_mcontext->__ss.__rip == 1016 reinterpret_cast<__uint64_t>(error_addr())) { 1017 ctx.data[16] = 1018 *reinterpret_cast<__uint64_t *>(uctx->uc_mcontext->__ss.__rsp); 1019 } 1020 _stacktrace[index] = reinterpret_cast<void *>(ctx.data[16]); 1021 ++index; 1022 #elif defined(__APPLE__) 1023 unw_getcontext(&ctx) 1024 // TODO: Convert the ucontext_t to libunwind's unw_context_t like 1025 // we do in 64 bits 1026 if (ctx.uc_mcontext->__ss.__eip == 1027 reinterpret_cast<greg_t>(error_addr())) { 1028 ctx.uc_mcontext->__ss.__eip = ctx.uc_mcontext->__ss.__esp; 1029 } 1030 _stacktrace[index] = 1031 reinterpret_cast<void *>(ctx.uc_mcontext->__ss.__eip); 1032 ++index; 1033 #endif 1034 } 1035 1036 unw_cursor_t cursor; 1037 if (context()) { 1038 #if defined(UNW_INIT_SIGNAL_FRAME) 1039 result = unw_init_local2(&cursor, &ctx, UNW_INIT_SIGNAL_FRAME); 1040 #else 1041 result = unw_init_local(&cursor, &ctx); 1042 #endif 1043 } else { 1044 unw_getcontext(&ctx); 1045 ; 1046 result = unw_init_local(&cursor, &ctx); 1047 } 1048 1049 if (result != 0) 1050 return 1; 1051 1052 unw_word_t ip = 0; 1053 1054 while (index <= depth && unw_step(&cursor) > 0) { 1055 result = unw_get_reg(&cursor, UNW_REG_IP, &ip); 1056 if (result == 0) { 1057 _stacktrace[index] = reinterpret_cast<void *>(--ip); 1058 ++index; 1059 } 1060 } 1061 --index; 1062 1063 _stacktrace.resize(index + 1); 1064 skip_n_firsts(0); 1065 return size(); 1066 } 1067 1068 size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, 1069 void *error_addr = nullptr) { 1070 load_here(depth + 8, context, error_addr); 1071 1072 for (size_t i = 0; i < _stacktrace.size(); ++i) { 1073 if (_stacktrace[i] == addr) { 1074 skip_n_firsts(i); 1075 _stacktrace[i] = (void *)((uintptr_t)_stacktrace[i]); 1076 break; 1077 } 1078 } 1079 1080 _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); 1081 return size(); 1082 } 1083 }; 1084 1085 #elif defined(BACKWARD_HAS_BACKTRACE) 1086 1087 template <> 1088 class StackTraceImpl<system_tag::current_tag> : public StackTraceImplHolder { 1089 public: 1090 NOINLINE 1091 size_t load_here(size_t depth = 32, void *context = nullptr, 1092 void *error_addr = nullptr) { 1093 set_context(context); 1094 set_error_addr(error_addr); 1095 load_thread_info(); 1096 if (depth == 0) { 1097 return 0; 1098 } 1099 _stacktrace.resize(depth + 1); 1100 size_t trace_cnt = backtrace(&_stacktrace[0], _stacktrace.size()); 1101 _stacktrace.resize(trace_cnt); 1102 skip_n_firsts(1); 1103 return size(); 1104 } 1105 1106 size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, 1107 void *error_addr = nullptr) { 1108 load_here(depth + 8, context, error_addr); 1109 1110 for (size_t i = 0; i < _stacktrace.size(); ++i) { 1111 if (_stacktrace[i] == addr) { 1112 skip_n_firsts(i); 1113 _stacktrace[i] = (void *)((uintptr_t)_stacktrace[i] + 1); 1114 break; 1115 } 1116 } 1117 1118 _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); 1119 return size(); 1120 } 1121 }; 1122 1123 #elif defined(BACKWARD_SYSTEM_WINDOWS) 1124 1125 template <> 1126 class StackTraceImpl<system_tag::current_tag> : public StackTraceImplHolder { 1127 public: 1128 // We have to load the machine type from the image info 1129 // So we first initialize the resolver, and it tells us this info 1130 void set_machine_type(DWORD machine_type) { machine_type_ = machine_type; } 1131 void set_context(CONTEXT *ctx) { ctx_ = ctx; } 1132 void set_thread_handle(HANDLE handle) { thd_ = handle; } 1133 1134 NOINLINE 1135 size_t load_here(size_t depth = 32, void *context = nullptr, 1136 void *error_addr = nullptr) { 1137 set_context(static_cast<CONTEXT*>(context)); 1138 set_error_addr(error_addr); 1139 CONTEXT localCtx; // used when no context is provided 1140 1141 if (depth == 0) { 1142 return 0; 1143 } 1144 1145 if (!ctx_) { 1146 ctx_ = &localCtx; 1147 RtlCaptureContext(ctx_); 1148 } 1149 1150 if (!thd_) { 1151 thd_ = GetCurrentThread(); 1152 } 1153 1154 HANDLE process = GetCurrentProcess(); 1155 1156 STACKFRAME64 s; 1157 memset(&s, 0, sizeof(STACKFRAME64)); 1158 1159 // TODO: 32 bit context capture 1160 s.AddrStack.Mode = AddrModeFlat; 1161 s.AddrFrame.Mode = AddrModeFlat; 1162 s.AddrPC.Mode = AddrModeFlat; 1163 #ifdef _M_X64 1164 s.AddrPC.Offset = ctx_->Rip; 1165 s.AddrStack.Offset = ctx_->Rsp; 1166 s.AddrFrame.Offset = ctx_->Rbp; 1167 #else 1168 s.AddrPC.Offset = ctx_->Eip; 1169 s.AddrStack.Offset = ctx_->Esp; 1170 s.AddrFrame.Offset = ctx_->Ebp; 1171 #endif 1172 1173 if (!machine_type_) { 1174 #ifdef _M_X64 1175 machine_type_ = IMAGE_FILE_MACHINE_AMD64; 1176 #else 1177 machine_type_ = IMAGE_FILE_MACHINE_I386; 1178 #endif 1179 } 1180 1181 for (;;) { 1182 // NOTE: this only works if PDBs are already loaded! 1183 SetLastError(0); 1184 if (!StackWalk64(machine_type_, process, thd_, &s, ctx_, NULL, 1185 SymFunctionTableAccess64, SymGetModuleBase64, NULL)) 1186 break; 1187 1188 if (s.AddrReturn.Offset == 0) 1189 break; 1190 1191 _stacktrace.push_back(reinterpret_cast<void *>(s.AddrPC.Offset)); 1192 1193 if (size() >= depth) 1194 break; 1195 } 1196 1197 return size(); 1198 } 1199 1200 size_t load_from(void *addr, size_t depth = 32, void *context = nullptr, 1201 void *error_addr = nullptr) { 1202 load_here(depth + 8, context, error_addr); 1203 1204 for (size_t i = 0; i < _stacktrace.size(); ++i) { 1205 if (_stacktrace[i] == addr) { 1206 skip_n_firsts(i); 1207 break; 1208 } 1209 } 1210 1211 _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth)); 1212 return size(); 1213 } 1214 1215 private: 1216 DWORD machine_type_ = 0; 1217 HANDLE thd_ = 0; 1218 CONTEXT *ctx_ = nullptr; 1219 }; 1220 1221 #endif 1222 1223 class StackTrace : public StackTraceImpl<system_tag::current_tag> {}; 1224 1225 /*************** TRACE RESOLVER ***************/ 1226 1227 class TraceResolverImplBase { 1228 public: 1229 virtual ~TraceResolverImplBase() {} 1230 1231 virtual void load_addresses(void *const*addresses, int address_count) { 1232 (void)addresses; 1233 (void)address_count; 1234 } 1235 1236 template <class ST> void load_stacktrace(ST &st) { 1237 load_addresses(st.begin(), static_cast<int>(st.size())); 1238 } 1239 1240 virtual ResolvedTrace resolve(ResolvedTrace t) { return t; } 1241 1242 protected: 1243 std::string demangle(const char *funcname) { 1244 return _demangler.demangle(funcname); 1245 } 1246 1247 private: 1248 details::demangler _demangler; 1249 }; 1250 1251 template <typename TAG> class TraceResolverImpl; 1252 1253 #ifdef BACKWARD_SYSTEM_UNKNOWN 1254 1255 template <> class TraceResolverImpl<system_tag::unknown_tag> 1256 : public TraceResolverImplBase {}; 1257 1258 #endif 1259 1260 #ifdef BACKWARD_SYSTEM_LINUX 1261 1262 class TraceResolverLinuxBase : public TraceResolverImplBase { 1263 public: 1264 TraceResolverLinuxBase() 1265 : argv0_(get_argv0()), exec_path_(read_symlink("/proc/self/exe")) {} 1266 std::string resolve_exec_path(Dl_info &symbol_info) const { 1267 // mutates symbol_info.dli_fname to be filename to open and returns filename 1268 // to display 1269 if (symbol_info.dli_fname == argv0_) { 1270 // dladdr returns argv[0] in dli_fname for symbols contained in 1271 // the main executable, which is not a valid path if the 1272 // executable was found by a search of the PATH environment 1273 // variable; In that case, we actually open /proc/self/exe, which 1274 // is always the actual executable (even if it was deleted/replaced!) 1275 // but display the path that /proc/self/exe links to. 1276 // However, this right away reduces probability of successful symbol 1277 // resolution, because libbfd may try to find *.debug files in the 1278 // same dir, in case symbols are stripped. As a result, it may try 1279 // to find a file /proc/self/<exe_name>.debug, which obviously does 1280 // not exist. /proc/self/exe is a last resort. First load attempt 1281 // should go for the original executable file path. 1282 symbol_info.dli_fname = "/proc/self/exe"; 1283 return exec_path_; 1284 } else { 1285 return symbol_info.dli_fname; 1286 } 1287 } 1288 1289 private: 1290 std::string argv0_; 1291 std::string exec_path_; 1292 1293 static std::string get_argv0() { 1294 std::string argv0; 1295 std::ifstream ifs("/proc/self/cmdline"); 1296 std::getline(ifs, argv0, '\0'); 1297 return argv0; 1298 } 1299 1300 static std::string read_symlink(std::string const &symlink_path) { 1301 std::string path; 1302 path.resize(100); 1303 1304 while (true) { 1305 ssize_t len = 1306 ::readlink(symlink_path.c_str(), &*path.begin(), path.size()); 1307 if (len < 0) { 1308 return ""; 1309 } 1310 if (static_cast<size_t>(len) == path.size()) { 1311 path.resize(path.size() * 2); 1312 } else { 1313 path.resize(static_cast<std::string::size_type>(len)); 1314 break; 1315 } 1316 } 1317 1318 return path; 1319 } 1320 }; 1321 1322 template <typename STACKTRACE_TAG> class TraceResolverLinuxImpl; 1323 1324 #if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 1325 1326 template <> 1327 class TraceResolverLinuxImpl<trace_resolver_tag::backtrace_symbol> 1328 : public TraceResolverLinuxBase { 1329 public: 1330 void load_addresses(void *const*addresses, int address_count) override { 1331 if (address_count == 0) { 1332 return; 1333 } 1334 _symbols.reset(backtrace_symbols(addresses, address_count)); 1335 } 1336 1337 ResolvedTrace resolve(ResolvedTrace trace) override { 1338 char *filename = _symbols[trace.idx]; 1339 char *funcname = filename; 1340 while (*funcname && *funcname != '(') { 1341 funcname += 1; 1342 } 1343 trace.object_filename.assign(filename, 1344 funcname); // ok even if funcname is the ending 1345 // \0 (then we assign entire string) 1346 1347 if (*funcname) { // if it's not end of string (e.g. from last frame ip==0) 1348 funcname += 1; 1349 char *funcname_end = funcname; 1350 while (*funcname_end && *funcname_end != ')' && *funcname_end != '+') { 1351 funcname_end += 1; 1352 } 1353 *funcname_end = '\0'; 1354 trace.object_function = this->demangle(funcname); 1355 trace.source.function = trace.object_function; // we cannot do better. 1356 } 1357 return trace; 1358 } 1359 1360 private: 1361 details::handle<char **> _symbols; 1362 }; 1363 1364 #endif // BACKWARD_HAS_BACKTRACE_SYMBOL == 1 1365 1366 #if BACKWARD_HAS_BFD == 1 1367 1368 template <> 1369 class TraceResolverLinuxImpl<trace_resolver_tag::libbfd> 1370 : public TraceResolverLinuxBase { 1371 public: 1372 TraceResolverLinuxImpl() : _bfd_loaded(false) {} 1373 1374 ResolvedTrace resolve(ResolvedTrace trace) override { 1375 Dl_info symbol_info; 1376 1377 // trace.addr is a virtual address in memory pointing to some code. 1378 // Let's try to find from which loaded object it comes from. 1379 // The loaded object can be yourself btw. 1380 if (!dladdr(trace.addr, &symbol_info)) { 1381 return trace; // dat broken trace... 1382 } 1383 1384 // Now we get in symbol_info: 1385 // .dli_fname: 1386 // pathname of the shared object that contains the address. 1387 // .dli_fbase: 1388 // where the object is loaded in memory. 1389 // .dli_sname: 1390 // the name of the nearest symbol to trace.addr, we expect a 1391 // function name. 1392 // .dli_saddr: 1393 // the exact address corresponding to .dli_sname. 1394 1395 if (symbol_info.dli_sname) { 1396 trace.object_function = demangle(symbol_info.dli_sname); 1397 } 1398 1399 if (!symbol_info.dli_fname) { 1400 return trace; 1401 } 1402 1403 trace.object_filename = resolve_exec_path(symbol_info); 1404 bfd_fileobject *fobj; 1405 // Before rushing to resolution need to ensure the executable 1406 // file still can be used. For that compare inode numbers of 1407 // what is stored by the executable's file path, and in the 1408 // dli_fname, which not necessarily equals to the executable. 1409 // It can be a shared library, or /proc/self/exe, and in the 1410 // latter case has drawbacks. See the exec path resolution for 1411 // details. In short - the dli object should be used only as 1412 // the last resort. 1413 // If inode numbers are equal, it is known dli_fname and the 1414 // executable file are the same. This is guaranteed by Linux, 1415 // because if the executable file is changed/deleted, it will 1416 // be done in a new inode. The old file will be preserved in 1417 // /proc/self/exe, and may even have inode 0. The latter can 1418 // happen if the inode was actually reused, and the file was 1419 // kept only in the main memory. 1420 // 1421 struct stat obj_stat; 1422 struct stat dli_stat; 1423 if (stat(trace.object_filename.c_str(), &obj_stat) == 0 && 1424 stat(symbol_info.dli_fname, &dli_stat) == 0 && 1425 obj_stat.st_ino == dli_stat.st_ino) { 1426 // The executable file, and the shared object containing the 1427 // address are the same file. Safe to use the original path. 1428 // this is preferable. Libbfd will search for stripped debug 1429 // symbols in the same directory. 1430 fobj = load_object_with_bfd(trace.object_filename); 1431 } else{ 1432 // The original object file was *deleted*! The only hope is 1433 // that the debug symbols are either inside the shared 1434 // object file, or are in the same directory, and this is 1435 // not /proc/self/exe. 1436 fobj = nullptr; 1437 } 1438 if (fobj == nullptr || !fobj->handle) { 1439 fobj = load_object_with_bfd(symbol_info.dli_fname); 1440 if (!fobj->handle) { 1441 return trace; 1442 } 1443 } 1444 1445 find_sym_result *details_selected; // to be filled. 1446 1447 // trace.addr is the next instruction to be executed after returning 1448 // from the nested stack frame. In C++ this usually relate to the next 1449 // statement right after the function call that leaded to a new stack 1450 // frame. This is not usually what you want to see when printing out a 1451 // stacktrace... 1452 find_sym_result details_call_site = 1453 find_symbol_details(fobj, trace.addr, symbol_info.dli_fbase); 1454 details_selected = &details_call_site; 1455 1456 #if BACKWARD_HAS_UNWIND == 0 1457 // ...this is why we also try to resolve the symbol that is right 1458 // before the return address. If we are lucky enough, we will get the 1459 // line of the function that was called. But if the code is optimized, 1460 // we might get something absolutely not related since the compiler 1461 // can reschedule the return address with inline functions and 1462 // tail-call optimization (among other things that I don't even know 1463 // or cannot even dream about with my tiny limited brain). 1464 find_sym_result details_adjusted_call_site = find_symbol_details( 1465 fobj, (void *)(uintptr_t(trace.addr) - 1), symbol_info.dli_fbase); 1466 1467 // In debug mode, we should always get the right thing(TM). 1468 if (details_call_site.found && details_adjusted_call_site.found) { 1469 // Ok, we assume that details_adjusted_call_site is a better estimation. 1470 details_selected = &details_adjusted_call_site; 1471 trace.addr = (void *)(uintptr_t(trace.addr) - 1); 1472 } 1473 1474 if (details_selected == &details_call_site && details_call_site.found) { 1475 // we have to re-resolve the symbol in order to reset some 1476 // internal state in BFD... so we can call backtrace_inliners 1477 // thereafter... 1478 details_call_site = 1479 find_symbol_details(fobj, trace.addr, symbol_info.dli_fbase); 1480 } 1481 #endif // BACKWARD_HAS_UNWIND 1482 1483 if (details_selected->found) { 1484 if (details_selected->filename) { 1485 trace.source.filename = details_selected->filename; 1486 } 1487 trace.source.line = details_selected->line; 1488 1489 if (details_selected->funcname) { 1490 // this time we get the name of the function where the code is 1491 // located, instead of the function were the address is 1492 // located. In short, if the code was inlined, we get the 1493 // function corresponding to the code. Else we already got in 1494 // trace.function. 1495 trace.source.function = demangle(details_selected->funcname); 1496 1497 if (!symbol_info.dli_sname) { 1498 // for the case dladdr failed to find the symbol name of 1499 // the function, we might as well try to put something 1500 // here. 1501 trace.object_function = trace.source.function; 1502 } 1503 } 1504 1505 // Maybe the source of the trace got inlined inside the function 1506 // (trace.source.function). Let's see if we can get all the inlined 1507 // calls along the way up to the initial call site. 1508 trace.inliners = backtrace_inliners(fobj, *details_selected); 1509 1510 #if 0 1511 if (trace.inliners.size() == 0) { 1512 // Maybe the trace was not inlined... or maybe it was and we 1513 // are lacking the debug information. Let's try to make the 1514 // world better and see if we can get the line number of the 1515 // function (trace.source.function) now. 1516 // 1517 // We will get the location of where the function start (to be 1518 // exact: the first instruction that really start the 1519 // function), not where the name of the function is defined. 1520 // This can be quite far away from the name of the function 1521 // btw. 1522 // 1523 // If the source of the function is the same as the source of 1524 // the trace, we cannot say if the trace was really inlined or 1525 // not. However, if the filename of the source is different 1526 // between the function and the trace... we can declare it as 1527 // an inliner. This is not 100% accurate, but better than 1528 // nothing. 1529 1530 if (symbol_info.dli_saddr) { 1531 find_sym_result details = find_symbol_details(fobj, 1532 symbol_info.dli_saddr, 1533 symbol_info.dli_fbase); 1534 1535 if (details.found) { 1536 ResolvedTrace::SourceLoc diy_inliner; 1537 diy_inliner.line = details.line; 1538 if (details.filename) { 1539 diy_inliner.filename = details.filename; 1540 } 1541 if (details.funcname) { 1542 diy_inliner.function = demangle(details.funcname); 1543 } else { 1544 diy_inliner.function = trace.source.function; 1545 } 1546 if (diy_inliner != trace.source) { 1547 trace.inliners.push_back(diy_inliner); 1548 } 1549 } 1550 } 1551 } 1552 #endif 1553 } 1554 1555 return trace; 1556 } 1557 1558 private: 1559 bool _bfd_loaded; 1560 1561 typedef details::handle<bfd *, 1562 details::deleter<bfd_boolean, bfd *, &bfd_close> > 1563 bfd_handle_t; 1564 1565 typedef details::handle<asymbol **> bfd_symtab_t; 1566 1567 struct bfd_fileobject { 1568 bfd_handle_t handle; 1569 bfd_vma base_addr; 1570 bfd_symtab_t symtab; 1571 bfd_symtab_t dynamic_symtab; 1572 }; 1573 1574 typedef details::hashtable<std::string, bfd_fileobject>::type fobj_bfd_map_t; 1575 fobj_bfd_map_t _fobj_bfd_map; 1576 1577 bfd_fileobject *load_object_with_bfd(const std::string &filename_object) { 1578 using namespace details; 1579 1580 if (!_bfd_loaded) { 1581 using namespace details; 1582 bfd_init(); 1583 _bfd_loaded = true; 1584 } 1585 1586 fobj_bfd_map_t::iterator it = _fobj_bfd_map.find(filename_object); 1587 if (it != _fobj_bfd_map.end()) { 1588 return &it->second; 1589 } 1590 1591 // this new object is empty for now. 1592 bfd_fileobject *r = &_fobj_bfd_map[filename_object]; 1593 1594 // we do the work temporary in this one; 1595 bfd_handle_t bfd_handle; 1596 1597 int fd = open(filename_object.c_str(), O_RDONLY); 1598 bfd_handle.reset(bfd_fdopenr(filename_object.c_str(), "default", fd)); 1599 if (!bfd_handle) { 1600 close(fd); 1601 return r; 1602 } 1603 1604 if (!bfd_check_format(bfd_handle.get(), bfd_object)) { 1605 return r; // not an object? You lose. 1606 } 1607 1608 if ((bfd_get_file_flags(bfd_handle.get()) & HAS_SYMS) == 0) { 1609 return r; // that's what happen when you forget to compile in debug. 1610 } 1611 1612 ssize_t symtab_storage_size = bfd_get_symtab_upper_bound(bfd_handle.get()); 1613 1614 ssize_t dyn_symtab_storage_size = 1615 bfd_get_dynamic_symtab_upper_bound(bfd_handle.get()); 1616 1617 if (symtab_storage_size <= 0 && dyn_symtab_storage_size <= 0) { 1618 return r; // weird, is the file is corrupted? 1619 } 1620 1621 bfd_symtab_t symtab, dynamic_symtab; 1622 ssize_t symcount = 0, dyn_symcount = 0; 1623 1624 if (symtab_storage_size > 0) { 1625 symtab.reset(static_cast<bfd_symbol **>( 1626 malloc(static_cast<size_t>(symtab_storage_size)))); 1627 symcount = bfd_canonicalize_symtab(bfd_handle.get(), symtab.get()); 1628 } 1629 1630 if (dyn_symtab_storage_size > 0) { 1631 dynamic_symtab.reset(static_cast<bfd_symbol **>( 1632 malloc(static_cast<size_t>(dyn_symtab_storage_size)))); 1633 dyn_symcount = bfd_canonicalize_dynamic_symtab(bfd_handle.get(), 1634 dynamic_symtab.get()); 1635 } 1636 1637 if (symcount <= 0 && dyn_symcount <= 0) { 1638 return r; // damned, that's a stripped file that you got there! 1639 } 1640 1641 r->handle = move(bfd_handle); 1642 r->symtab = move(symtab); 1643 r->dynamic_symtab = move(dynamic_symtab); 1644 return r; 1645 } 1646 1647 struct find_sym_result { 1648 bool found; 1649 const char *filename; 1650 const char *funcname; 1651 unsigned int line; 1652 }; 1653 1654 struct find_sym_context { 1655 TraceResolverLinuxImpl *self; 1656 bfd_fileobject *fobj; 1657 void *addr; 1658 void *base_addr; 1659 find_sym_result result; 1660 }; 1661 1662 find_sym_result find_symbol_details(bfd_fileobject *fobj, void *addr, 1663 void *base_addr) { 1664 find_sym_context context; 1665 context.self = this; 1666 context.fobj = fobj; 1667 context.addr = addr; 1668 context.base_addr = base_addr; 1669 context.result.found = false; 1670 bfd_map_over_sections(fobj->handle.get(), &find_in_section_trampoline, 1671 static_cast<void *>(&context)); 1672 return context.result; 1673 } 1674 1675 static void find_in_section_trampoline(bfd *, asection *section, void *data) { 1676 find_sym_context *context = static_cast<find_sym_context *>(data); 1677 context->self->find_in_section( 1678 reinterpret_cast<bfd_vma>(context->addr), 1679 reinterpret_cast<bfd_vma>(context->base_addr), context->fobj, section, 1680 context->result); 1681 } 1682 1683 void find_in_section(bfd_vma addr, bfd_vma base_addr, bfd_fileobject *fobj, 1684 asection *section, find_sym_result &result) { 1685 if (result.found) 1686 return; 1687 1688 #ifdef bfd_get_section_flags 1689 if ((bfd_get_section_flags(fobj->handle.get(), section) & SEC_ALLOC) == 0) 1690 #else 1691 if ((bfd_section_flags(section) & SEC_ALLOC) == 0) 1692 #endif 1693 return; // a debug section is never loaded automatically. 1694 1695 #ifdef bfd_get_section_vma 1696 bfd_vma sec_addr = bfd_get_section_vma(fobj->handle.get(), section); 1697 #else 1698 bfd_vma sec_addr = bfd_section_vma(section); 1699 #endif 1700 #ifdef bfd_get_section_size 1701 bfd_size_type size = bfd_get_section_size(section); 1702 #else 1703 bfd_size_type size = bfd_section_size(section); 1704 #endif 1705 1706 // are we in the boundaries of the section? 1707 if (addr < sec_addr || addr >= sec_addr + size) { 1708 addr -= base_addr; // oops, a relocated object, lets try again... 1709 if (addr < sec_addr || addr >= sec_addr + size) { 1710 return; 1711 } 1712 } 1713 1714 #if defined(__clang__) 1715 #pragma clang diagnostic push 1716 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" 1717 #endif 1718 if (!result.found && fobj->symtab) { 1719 result.found = bfd_find_nearest_line( 1720 fobj->handle.get(), section, fobj->symtab.get(), addr - sec_addr, 1721 &result.filename, &result.funcname, &result.line); 1722 } 1723 1724 if (!result.found && fobj->dynamic_symtab) { 1725 result.found = bfd_find_nearest_line( 1726 fobj->handle.get(), section, fobj->dynamic_symtab.get(), 1727 addr - sec_addr, &result.filename, &result.funcname, &result.line); 1728 } 1729 #if defined(__clang__) 1730 #pragma clang diagnostic pop 1731 #endif 1732 } 1733 1734 ResolvedTrace::source_locs_t 1735 backtrace_inliners(bfd_fileobject *fobj, find_sym_result previous_result) { 1736 // This function can be called ONLY after a SUCCESSFUL call to 1737 // find_symbol_details. The state is global to the bfd_handle. 1738 ResolvedTrace::source_locs_t results; 1739 while (previous_result.found) { 1740 find_sym_result result; 1741 result.found = bfd_find_inliner_info(fobj->handle.get(), &result.filename, 1742 &result.funcname, &result.line); 1743 1744 if (result 1745 .found) /* and not ( 1746 cstrings_eq(previous_result.filename, 1747 result.filename) and 1748 cstrings_eq(previous_result.funcname, result.funcname) 1749 and result.line == previous_result.line 1750 )) */ 1751 { 1752 ResolvedTrace::SourceLoc src_loc; 1753 src_loc.line = result.line; 1754 if (result.filename) { 1755 src_loc.filename = result.filename; 1756 } 1757 if (result.funcname) { 1758 src_loc.function = demangle(result.funcname); 1759 } 1760 results.push_back(src_loc); 1761 } 1762 previous_result = result; 1763 } 1764 return results; 1765 } 1766 1767 bool cstrings_eq(const char *a, const char *b) { 1768 if (!a || !b) { 1769 return false; 1770 } 1771 return strcmp(a, b) == 0; 1772 } 1773 }; 1774 #endif // BACKWARD_HAS_BFD == 1 1775 1776 #if BACKWARD_HAS_DW == 1 1777 1778 template <> 1779 class TraceResolverLinuxImpl<trace_resolver_tag::libdw> 1780 : public TraceResolverLinuxBase { 1781 public: 1782 TraceResolverLinuxImpl() : _dwfl_handle_initialized(false) {} 1783 1784 ResolvedTrace resolve(ResolvedTrace trace) override { 1785 using namespace details; 1786 1787 Dwarf_Addr trace_addr = reinterpret_cast<Dwarf_Addr>(trace.addr); 1788 1789 if (!_dwfl_handle_initialized) { 1790 // initialize dwfl... 1791 _dwfl_cb.reset(new Dwfl_Callbacks); 1792 _dwfl_cb->find_elf = &dwfl_linux_proc_find_elf; 1793 _dwfl_cb->find_debuginfo = &dwfl_standard_find_debuginfo; 1794 _dwfl_cb->debuginfo_path = 0; 1795 1796 _dwfl_handle.reset(dwfl_begin(_dwfl_cb.get())); 1797 _dwfl_handle_initialized = true; 1798 1799 if (!_dwfl_handle) { 1800 return trace; 1801 } 1802 1803 // ...from the current process. 1804 dwfl_report_begin(_dwfl_handle.get()); 1805 int r = dwfl_linux_proc_report(_dwfl_handle.get(), getpid()); 1806 dwfl_report_end(_dwfl_handle.get(), NULL, NULL); 1807 if (r < 0) { 1808 return trace; 1809 } 1810 } 1811 1812 if (!_dwfl_handle) { 1813 return trace; 1814 } 1815 1816 // find the module (binary object) that contains the trace's address. 1817 // This is not using any debug information, but the addresses ranges of 1818 // all the currently loaded binary object. 1819 Dwfl_Module *mod = dwfl_addrmodule(_dwfl_handle.get(), trace_addr); 1820 if (mod) { 1821 // now that we found it, lets get the name of it, this will be the 1822 // full path to the running binary or one of the loaded library. 1823 const char *module_name = dwfl_module_info(mod, 0, 0, 0, 0, 0, 0, 0); 1824 if (module_name) { 1825 trace.object_filename = module_name; 1826 } 1827 // We also look after the name of the symbol, equal or before this 1828 // address. This is found by walking the symtab. We should get the 1829 // symbol corresponding to the function (mangled) containing the 1830 // address. If the code corresponding to the address was inlined, 1831 // this is the name of the out-most inliner function. 1832 const char *sym_name = dwfl_module_addrname(mod, trace_addr); 1833 if (sym_name) { 1834 trace.object_function = demangle(sym_name); 1835 } 1836 } 1837 1838 // now let's get serious, and find out the source location (file and 1839 // line number) of the address. 1840 1841 // This function will look in .debug_aranges for the address and map it 1842 // to the location of the compilation unit DIE in .debug_info and 1843 // return it. 1844 Dwarf_Addr mod_bias = 0; 1845 Dwarf_Die *cudie = dwfl_module_addrdie(mod, trace_addr, &mod_bias); 1846 1847 #if 1 1848 if (!cudie) { 1849 // Sadly clang does not generate the section .debug_aranges, thus 1850 // dwfl_module_addrdie will fail early. Clang doesn't either set 1851 // the lowpc/highpc/range info for every compilation unit. 1852 // 1853 // So in order to save the world: 1854 // for every compilation unit, we will iterate over every single 1855 // DIEs. Normally functions should have a lowpc/highpc/range, which 1856 // we will use to infer the compilation unit. 1857 1858 // note that this is probably badly inefficient. 1859 while ((cudie = dwfl_module_nextcu(mod, cudie, &mod_bias))) { 1860 Dwarf_Die die_mem; 1861 Dwarf_Die *fundie = 1862 find_fundie_by_pc(cudie, trace_addr - mod_bias, &die_mem); 1863 if (fundie) { 1864 break; 1865 } 1866 } 1867 } 1868 #endif 1869 1870 //#define BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE 1871 #ifdef BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE 1872 if (!cudie) { 1873 // If it's still not enough, lets dive deeper in the shit, and try 1874 // to save the world again: for every compilation unit, we will 1875 // load the corresponding .debug_line section, and see if we can 1876 // find our address in it. 1877 1878 Dwarf_Addr cfi_bias; 1879 Dwarf_CFI *cfi_cache = dwfl_module_eh_cfi(mod, &cfi_bias); 1880 1881 Dwarf_Addr bias; 1882 while ((cudie = dwfl_module_nextcu(mod, cudie, &bias))) { 1883 if (dwarf_getsrc_die(cudie, trace_addr - bias)) { 1884 1885 // ...but if we get a match, it might be a false positive 1886 // because our (address - bias) might as well be valid in a 1887 // different compilation unit. So we throw our last card on 1888 // the table and lookup for the address into the .eh_frame 1889 // section. 1890 1891 handle<Dwarf_Frame *> frame; 1892 dwarf_cfi_addrframe(cfi_cache, trace_addr - cfi_bias, &frame); 1893 if (frame) { 1894 break; 1895 } 1896 } 1897 } 1898 } 1899 #endif 1900 1901 if (!cudie) { 1902 return trace; // this time we lost the game :/ 1903 } 1904 1905 // Now that we have a compilation unit DIE, this function will be able 1906 // to load the corresponding section in .debug_line (if not already 1907 // loaded) and hopefully find the source location mapped to our 1908 // address. 1909 Dwarf_Line *srcloc = dwarf_getsrc_die(cudie, trace_addr - mod_bias); 1910 1911 if (srcloc) { 1912 const char *srcfile = dwarf_linesrc(srcloc, 0, 0); 1913 if (srcfile) { 1914 trace.source.filename = srcfile; 1915 } 1916 int line = 0, col = 0; 1917 dwarf_lineno(srcloc, &line); 1918 dwarf_linecol(srcloc, &col); 1919 trace.source.line = static_cast<unsigned>(line); 1920 trace.source.col = static_cast<unsigned>(col); 1921 } 1922 1923 deep_first_search_by_pc(cudie, trace_addr - mod_bias, 1924 inliners_search_cb(trace)); 1925 if (trace.source.function.size() == 0) { 1926 // fallback. 1927 trace.source.function = trace.object_function; 1928 } 1929 1930 return trace; 1931 } 1932 1933 private: 1934 typedef details::handle<Dwfl *, details::deleter<void, Dwfl *, &dwfl_end> > 1935 dwfl_handle_t; 1936 details::handle<Dwfl_Callbacks *, details::default_delete<Dwfl_Callbacks *> > 1937 _dwfl_cb; 1938 dwfl_handle_t _dwfl_handle; 1939 bool _dwfl_handle_initialized; 1940 1941 // defined here because in C++98, template function cannot take locally 1942 // defined types... grrr. 1943 struct inliners_search_cb { 1944 void operator()(Dwarf_Die *die) { 1945 switch (dwarf_tag(die)) { 1946 const char *name; 1947 case DW_TAG_subprogram: 1948 if ((name = dwarf_diename(die))) { 1949 trace.source.function = name; 1950 } 1951 break; 1952 1953 case DW_TAG_inlined_subroutine: 1954 ResolvedTrace::SourceLoc sloc; 1955 Dwarf_Attribute attr_mem; 1956 1957 if ((name = dwarf_diename(die))) { 1958 sloc.function = name; 1959 } 1960 if ((name = die_call_file(die))) { 1961 sloc.filename = name; 1962 } 1963 1964 Dwarf_Word line = 0, col = 0; 1965 dwarf_formudata(dwarf_attr(die, DW_AT_call_line, &attr_mem), &line); 1966 dwarf_formudata(dwarf_attr(die, DW_AT_call_column, &attr_mem), &col); 1967 sloc.line = static_cast<unsigned>(line); 1968 sloc.col = static_cast<unsigned>(col); 1969 1970 trace.inliners.push_back(sloc); 1971 break; 1972 }; 1973 } 1974 ResolvedTrace &trace; 1975 inliners_search_cb(ResolvedTrace &t) : trace(t) {} 1976 }; 1977 1978 static bool die_has_pc(Dwarf_Die *die, Dwarf_Addr pc) { 1979 Dwarf_Addr low, high; 1980 1981 // continuous range 1982 if (dwarf_hasattr(die, DW_AT_low_pc) && dwarf_hasattr(die, DW_AT_high_pc)) { 1983 if (dwarf_lowpc(die, &low) != 0) { 1984 return false; 1985 } 1986 if (dwarf_highpc(die, &high) != 0) { 1987 Dwarf_Attribute attr_mem; 1988 Dwarf_Attribute *attr = dwarf_attr(die, DW_AT_high_pc, &attr_mem); 1989 Dwarf_Word value; 1990 if (dwarf_formudata(attr, &value) != 0) { 1991 return false; 1992 } 1993 high = low + value; 1994 } 1995 return pc >= low && pc < high; 1996 } 1997 1998 // non-continuous range. 1999 Dwarf_Addr base; 2000 ptrdiff_t offset = 0; 2001 while ((offset = dwarf_ranges(die, offset, &base, &low, &high)) > 0) { 2002 if (pc >= low && pc < high) { 2003 return true; 2004 } 2005 } 2006 return false; 2007 } 2008 2009 static Dwarf_Die *find_fundie_by_pc(Dwarf_Die *parent_die, Dwarf_Addr pc, 2010 Dwarf_Die *result) { 2011 if (dwarf_child(parent_die, result) != 0) { 2012 return 0; 2013 } 2014 2015 Dwarf_Die *die = result; 2016 do { 2017 switch (dwarf_tag(die)) { 2018 case DW_TAG_subprogram: 2019 case DW_TAG_inlined_subroutine: 2020 if (die_has_pc(die, pc)) { 2021 return result; 2022 } 2023 }; 2024 bool declaration = false; 2025 Dwarf_Attribute attr_mem; 2026 dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), 2027 &declaration); 2028 if (!declaration) { 2029 // let's be curious and look deeper in the tree, 2030 // function are not necessarily at the first level, but 2031 // might be nested inside a namespace, structure etc. 2032 Dwarf_Die die_mem; 2033 Dwarf_Die *indie = find_fundie_by_pc(die, pc, &die_mem); 2034 if (indie) { 2035 *result = die_mem; 2036 return result; 2037 } 2038 } 2039 } while (dwarf_siblingof(die, result) == 0); 2040 return 0; 2041 } 2042 2043 template <typename CB> 2044 static bool deep_first_search_by_pc(Dwarf_Die *parent_die, Dwarf_Addr pc, 2045 CB cb) { 2046 Dwarf_Die die_mem; 2047 if (dwarf_child(parent_die, &die_mem) != 0) { 2048 return false; 2049 } 2050 2051 bool branch_has_pc = false; 2052 Dwarf_Die *die = &die_mem; 2053 do { 2054 bool declaration = false; 2055 Dwarf_Attribute attr_mem; 2056 dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), 2057 &declaration); 2058 if (!declaration) { 2059 // let's be curious and look deeper in the tree, function are 2060 // not necessarily at the first level, but might be nested 2061 // inside a namespace, structure, a function, an inlined 2062 // function etc. 2063 branch_has_pc = deep_first_search_by_pc(die, pc, cb); 2064 } 2065 if (!branch_has_pc) { 2066 branch_has_pc = die_has_pc(die, pc); 2067 } 2068 if (branch_has_pc) { 2069 cb(die); 2070 } 2071 } while (dwarf_siblingof(die, &die_mem) == 0); 2072 return branch_has_pc; 2073 } 2074 2075 static const char *die_call_file(Dwarf_Die *die) { 2076 Dwarf_Attribute attr_mem; 2077 Dwarf_Word file_idx = 0; 2078 2079 dwarf_formudata(dwarf_attr(die, DW_AT_call_file, &attr_mem), &file_idx); 2080 2081 if (file_idx == 0) { 2082 return 0; 2083 } 2084 2085 Dwarf_Die die_mem; 2086 Dwarf_Die *cudie = dwarf_diecu(die, &die_mem, 0, 0); 2087 if (!cudie) { 2088 return 0; 2089 } 2090 2091 Dwarf_Files *files = 0; 2092 size_t nfiles; 2093 dwarf_getsrcfiles(cudie, &files, &nfiles); 2094 if (!files) { 2095 return 0; 2096 } 2097 2098 return dwarf_filesrc(files, file_idx, 0, 0); 2099 } 2100 }; 2101 #endif // BACKWARD_HAS_DW == 1 2102 2103 #if BACKWARD_HAS_DWARF == 1 2104 2105 template <> 2106 class TraceResolverLinuxImpl<trace_resolver_tag::libdwarf> 2107 : public TraceResolverLinuxBase { 2108 public: 2109 TraceResolverLinuxImpl() : _dwarf_loaded(false) {} 2110 2111 ResolvedTrace resolve(ResolvedTrace trace) override { 2112 // trace.addr is a virtual address in memory pointing to some code. 2113 // Let's try to find from which loaded object it comes from. 2114 // The loaded object can be yourself btw. 2115 2116 Dl_info symbol_info; 2117 int dladdr_result = 0; 2118 #if defined(__GLIBC__) 2119 link_map *link_map; 2120 // We request the link map so we can get information about offsets 2121 dladdr_result = 2122 dladdr1(trace.addr, &symbol_info, reinterpret_cast<void **>(&link_map), 2123 RTLD_DL_LINKMAP); 2124 #else 2125 // Android doesn't have dladdr1. Don't use the linker map. 2126 dladdr_result = dladdr(trace.addr, &symbol_info); 2127 #endif 2128 if (!dladdr_result) { 2129 return trace; // dat broken trace... 2130 } 2131 2132 // Now we get in symbol_info: 2133 // .dli_fname: 2134 // pathname of the shared object that contains the address. 2135 // .dli_fbase: 2136 // where the object is loaded in memory. 2137 // .dli_sname: 2138 // the name of the nearest symbol to trace.addr, we expect a 2139 // function name. 2140 // .dli_saddr: 2141 // the exact address corresponding to .dli_sname. 2142 // 2143 // And in link_map: 2144 // .l_addr: 2145 // difference between the address in the ELF file and the address 2146 // in memory 2147 // l_name: 2148 // absolute pathname where the object was found 2149 2150 if (symbol_info.dli_sname) { 2151 trace.object_function = demangle(symbol_info.dli_sname); 2152 } 2153 2154 if (!symbol_info.dli_fname) { 2155 return trace; 2156 } 2157 2158 trace.object_filename = resolve_exec_path(symbol_info); 2159 dwarf_fileobject &fobj = load_object_with_dwarf(symbol_info.dli_fname); 2160 if (!fobj.dwarf_handle) { 2161 return trace; // sad, we couldn't load the object :( 2162 } 2163 2164 #if defined(__GLIBC__) 2165 // Convert the address to a module relative one by looking at 2166 // the module's loading address in the link map 2167 Dwarf_Addr address = reinterpret_cast<uintptr_t>(trace.addr) - 2168 reinterpret_cast<uintptr_t>(link_map->l_addr); 2169 #else 2170 Dwarf_Addr address = reinterpret_cast<uintptr_t>(trace.addr); 2171 #endif 2172 2173 if (trace.object_function.empty()) { 2174 symbol_cache_t::iterator it = fobj.symbol_cache.lower_bound(address); 2175 2176 if (it != fobj.symbol_cache.end()) { 2177 if (it->first != address) { 2178 if (it != fobj.symbol_cache.begin()) { 2179 --it; 2180 } 2181 } 2182 trace.object_function = demangle(it->second.c_str()); 2183 } 2184 } 2185 2186 // Get the Compilation Unit DIE for the address 2187 Dwarf_Die die = find_die(fobj, address); 2188 2189 if (!die) { 2190 return trace; // this time we lost the game :/ 2191 } 2192 2193 // libdwarf doesn't give us direct access to its objects, it always 2194 // allocates a copy for the caller. We keep that copy alive in a cache 2195 // and we deallocate it later when it's no longer required. 2196 die_cache_entry &die_object = get_die_cache(fobj, die); 2197 if (die_object.isEmpty()) 2198 return trace; // We have no line section for this DIE 2199 2200 die_linemap_t::iterator it = die_object.line_section.lower_bound(address); 2201 2202 if (it != die_object.line_section.end()) { 2203 if (it->first != address) { 2204 if (it == die_object.line_section.begin()) { 2205 // If we are on the first item of the line section 2206 // but the address does not match it means that 2207 // the address is below the range of the DIE. Give up. 2208 return trace; 2209 } else { 2210 --it; 2211 } 2212 } 2213 } else { 2214 return trace; // We didn't find the address. 2215 } 2216 2217 // Get the Dwarf_Line that the address points to and call libdwarf 2218 // to get source file, line and column info. 2219 Dwarf_Line line = die_object.line_buffer[it->second]; 2220 Dwarf_Error error = DW_DLE_NE; 2221 2222 char *filename; 2223 if (dwarf_linesrc(line, &filename, &error) == DW_DLV_OK) { 2224 trace.source.filename = std::string(filename); 2225 dwarf_dealloc(fobj.dwarf_handle.get(), filename, DW_DLA_STRING); 2226 } 2227 2228 Dwarf_Unsigned number = 0; 2229 if (dwarf_lineno(line, &number, &error) == DW_DLV_OK) { 2230 trace.source.line = number; 2231 } else { 2232 trace.source.line = 0; 2233 } 2234 2235 if (dwarf_lineoff_b(line, &number, &error) == DW_DLV_OK) { 2236 trace.source.col = number; 2237 } else { 2238 trace.source.col = 0; 2239 } 2240 2241 std::vector<std::string> namespace_stack; 2242 deep_first_search_by_pc(fobj, die, address, namespace_stack, 2243 inliners_search_cb(trace, fobj, die)); 2244 2245 dwarf_dealloc(fobj.dwarf_handle.get(), die, DW_DLA_DIE); 2246 2247 return trace; 2248 } 2249 2250 public: 2251 static int close_dwarf(Dwarf_Debug dwarf) { 2252 return dwarf_finish(dwarf, NULL); 2253 } 2254 2255 private: 2256 bool _dwarf_loaded; 2257 2258 typedef details::handle<int, details::deleter<int, int, &::close> > 2259 dwarf_file_t; 2260 2261 typedef details::handle<Elf *, details::deleter<int, Elf *, &elf_end> > 2262 dwarf_elf_t; 2263 2264 typedef details::handle<Dwarf_Debug, 2265 details::deleter<int, Dwarf_Debug, &close_dwarf> > 2266 dwarf_handle_t; 2267 2268 typedef std::map<Dwarf_Addr, int> die_linemap_t; 2269 2270 typedef std::map<Dwarf_Off, Dwarf_Off> die_specmap_t; 2271 2272 struct die_cache_entry { 2273 die_specmap_t spec_section; 2274 die_linemap_t line_section; 2275 Dwarf_Line *line_buffer; 2276 Dwarf_Signed line_count; 2277 Dwarf_Line_Context line_context; 2278 2279 inline bool isEmpty() { 2280 return line_buffer == NULL || line_count == 0 || line_context == NULL || 2281 line_section.empty(); 2282 } 2283 2284 die_cache_entry() : line_buffer(0), line_count(0), line_context(0) {} 2285 2286 ~die_cache_entry() { 2287 if (line_context) { 2288 dwarf_srclines_dealloc_b(line_context); 2289 } 2290 } 2291 }; 2292 2293 typedef std::map<Dwarf_Off, die_cache_entry> die_cache_t; 2294 2295 typedef std::map<uintptr_t, std::string> symbol_cache_t; 2296 2297 struct dwarf_fileobject { 2298 dwarf_file_t file_handle; 2299 dwarf_elf_t elf_handle; 2300 dwarf_handle_t dwarf_handle; 2301 symbol_cache_t symbol_cache; 2302 2303 // Die cache 2304 die_cache_t die_cache; 2305 die_cache_entry *current_cu; 2306 }; 2307 2308 typedef details::hashtable<std::string, dwarf_fileobject>::type 2309 fobj_dwarf_map_t; 2310 fobj_dwarf_map_t _fobj_dwarf_map; 2311 2312 static bool cstrings_eq(const char *a, const char *b) { 2313 if (!a || !b) { 2314 return false; 2315 } 2316 return strcmp(a, b) == 0; 2317 } 2318 2319 dwarf_fileobject &load_object_with_dwarf(const std::string &filename_object) { 2320 2321 if (!_dwarf_loaded) { 2322 // Set the ELF library operating version 2323 // If that fails there's nothing we can do 2324 _dwarf_loaded = elf_version(EV_CURRENT) != EV_NONE; 2325 } 2326 2327 fobj_dwarf_map_t::iterator it = _fobj_dwarf_map.find(filename_object); 2328 if (it != _fobj_dwarf_map.end()) { 2329 return it->second; 2330 } 2331 2332 // this new object is empty for now 2333 dwarf_fileobject &r = _fobj_dwarf_map[filename_object]; 2334 2335 dwarf_file_t file_handle; 2336 file_handle.reset(open(filename_object.c_str(), O_RDONLY)); 2337 if (file_handle.get() < 0) { 2338 return r; 2339 } 2340 2341 // Try to get an ELF handle. We need to read the ELF sections 2342 // because we want to see if there is a .gnu_debuglink section 2343 // that points to a split debug file 2344 dwarf_elf_t elf_handle; 2345 elf_handle.reset(elf_begin(file_handle.get(), ELF_C_READ, NULL)); 2346 if (!elf_handle) { 2347 return r; 2348 } 2349 2350 const char *e_ident = elf_getident(elf_handle.get(), 0); 2351 if (!e_ident) { 2352 return r; 2353 } 2354 2355 // Get the number of sections 2356 // We use the new APIs as elf_getshnum is deprecated 2357 size_t shdrnum = 0; 2358 if (elf_getshdrnum(elf_handle.get(), &shdrnum) == -1) { 2359 return r; 2360 } 2361 2362 // Get the index to the string section 2363 size_t shdrstrndx = 0; 2364 if (elf_getshdrstrndx(elf_handle.get(), &shdrstrndx) == -1) { 2365 return r; 2366 } 2367 2368 std::string debuglink; 2369 // Iterate through the ELF sections to try to get a gnu_debuglink 2370 // note and also to cache the symbol table. 2371 // We go the preprocessor way to avoid having to create templated 2372 // classes or using gelf (which might throw a compiler error if 64 bit 2373 // is not supported 2374 #define ELF_GET_DATA(ARCH) \ 2375 Elf_Scn *elf_section = 0; \ 2376 Elf_Data *elf_data = 0; \ 2377 Elf##ARCH##_Shdr *section_header = 0; \ 2378 Elf_Scn *symbol_section = 0; \ 2379 size_t symbol_count = 0; \ 2380 size_t symbol_strings = 0; \ 2381 Elf##ARCH##_Sym *symbol = 0; \ 2382 const char *section_name = 0; \ 2383 \ 2384 while ((elf_section = elf_nextscn(elf_handle.get(), elf_section)) != NULL) { \ 2385 section_header = elf##ARCH##_getshdr(elf_section); \ 2386 if (section_header == NULL) { \ 2387 return r; \ 2388 } \ 2389 \ 2390 if ((section_name = elf_strptr(elf_handle.get(), shdrstrndx, \ 2391 section_header->sh_name)) == NULL) { \ 2392 return r; \ 2393 } \ 2394 \ 2395 if (cstrings_eq(section_name, ".gnu_debuglink")) { \ 2396 elf_data = elf_getdata(elf_section, NULL); \ 2397 if (elf_data && elf_data->d_size > 0) { \ 2398 debuglink = \ 2399 std::string(reinterpret_cast<const char *>(elf_data->d_buf)); \ 2400 } \ 2401 } \ 2402 \ 2403 switch (section_header->sh_type) { \ 2404 case SHT_SYMTAB: \ 2405 symbol_section = elf_section; \ 2406 symbol_count = section_header->sh_size / section_header->sh_entsize; \ 2407 symbol_strings = section_header->sh_link; \ 2408 break; \ 2409 \ 2410 /* We use .dynsyms as a last resort, we prefer .symtab */ \ 2411 case SHT_DYNSYM: \ 2412 if (!symbol_section) { \ 2413 symbol_section = elf_section; \ 2414 symbol_count = section_header->sh_size / section_header->sh_entsize; \ 2415 symbol_strings = section_header->sh_link; \ 2416 } \ 2417 break; \ 2418 } \ 2419 } \ 2420 \ 2421 if (symbol_section && symbol_count && symbol_strings) { \ 2422 elf_data = elf_getdata(symbol_section, NULL); \ 2423 symbol = reinterpret_cast<Elf##ARCH##_Sym *>(elf_data->d_buf); \ 2424 for (size_t i = 0; i < symbol_count; ++i) { \ 2425 int type = ELF##ARCH##_ST_TYPE(symbol->st_info); \ 2426 if (type == STT_FUNC && symbol->st_value > 0) { \ 2427 r.symbol_cache[symbol->st_value] = std::string( \ 2428 elf_strptr(elf_handle.get(), symbol_strings, symbol->st_name)); \ 2429 } \ 2430 ++symbol; \ 2431 } \ 2432 } 2433 2434 if (e_ident[EI_CLASS] == ELFCLASS32) { 2435 ELF_GET_DATA(32) 2436 } else if (e_ident[EI_CLASS] == ELFCLASS64) { 2437 // libelf might have been built without 64 bit support 2438 #if __LIBELF64 2439 ELF_GET_DATA(64) 2440 #endif 2441 } 2442 2443 if (!debuglink.empty()) { 2444 // We have a debuglink section! Open an elf instance on that 2445 // file instead. If we can't open the file, then return 2446 // the elf handle we had already opened. 2447 dwarf_file_t debuglink_file; 2448 debuglink_file.reset(open(debuglink.c_str(), O_RDONLY)); 2449 if (debuglink_file.get() > 0) { 2450 dwarf_elf_t debuglink_elf; 2451 debuglink_elf.reset(elf_begin(debuglink_file.get(), ELF_C_READ, NULL)); 2452 2453 // If we have a valid elf handle, return the new elf handle 2454 // and file handle and discard the original ones 2455 if (debuglink_elf) { 2456 elf_handle = move(debuglink_elf); 2457 file_handle = move(debuglink_file); 2458 } 2459 } 2460 } 2461 2462 // Ok, we have a valid ELF handle, let's try to get debug symbols 2463 Dwarf_Debug dwarf_debug; 2464 Dwarf_Error error = DW_DLE_NE; 2465 dwarf_handle_t dwarf_handle; 2466 2467 int dwarf_result = dwarf_elf_init(elf_handle.get(), DW_DLC_READ, NULL, NULL, 2468 &dwarf_debug, &error); 2469 2470 // We don't do any special handling for DW_DLV_NO_ENTRY specially. 2471 // If we get an error, or the file doesn't have debug information 2472 // we just return. 2473 if (dwarf_result != DW_DLV_OK) { 2474 return r; 2475 } 2476 2477 dwarf_handle.reset(dwarf_debug); 2478 2479 r.file_handle = move(file_handle); 2480 r.elf_handle = move(elf_handle); 2481 r.dwarf_handle = move(dwarf_handle); 2482 2483 return r; 2484 } 2485 2486 die_cache_entry &get_die_cache(dwarf_fileobject &fobj, Dwarf_Die die) { 2487 Dwarf_Error error = DW_DLE_NE; 2488 2489 // Get the die offset, we use it as the cache key 2490 Dwarf_Off die_offset; 2491 if (dwarf_dieoffset(die, &die_offset, &error) != DW_DLV_OK) { 2492 die_offset = 0; 2493 } 2494 2495 die_cache_t::iterator it = fobj.die_cache.find(die_offset); 2496 2497 if (it != fobj.die_cache.end()) { 2498 fobj.current_cu = &it->second; 2499 return it->second; 2500 } 2501 2502 die_cache_entry &de = fobj.die_cache[die_offset]; 2503 fobj.current_cu = &de; 2504 2505 Dwarf_Addr line_addr; 2506 Dwarf_Small table_count; 2507 2508 // The addresses in the line section are not fully sorted (they might 2509 // be sorted by block of code belonging to the same file), which makes 2510 // it necessary to do so before searching is possible. 2511 // 2512 // As libdwarf allocates a copy of everything, let's get the contents 2513 // of the line section and keep it around. We also create a map of 2514 // program counter to line table indices so we can search by address 2515 // and get the line buffer index. 2516 // 2517 // To make things more difficult, the same address can span more than 2518 // one line, so we need to keep the index pointing to the first line 2519 // by using insert instead of the map's [ operator. 2520 2521 // Get the line context for the DIE 2522 if (dwarf_srclines_b(die, 0, &table_count, &de.line_context, &error) == 2523 DW_DLV_OK) { 2524 // Get the source lines for this line context, to be deallocated 2525 // later 2526 if (dwarf_srclines_from_linecontext(de.line_context, &de.line_buffer, 2527 &de.line_count, 2528 &error) == DW_DLV_OK) { 2529 2530 // Add all the addresses to our map 2531 for (int i = 0; i < de.line_count; i++) { 2532 if (dwarf_lineaddr(de.line_buffer[i], &line_addr, &error) != 2533 DW_DLV_OK) { 2534 line_addr = 0; 2535 } 2536 de.line_section.insert(std::pair<Dwarf_Addr, int>(line_addr, i)); 2537 } 2538 } 2539 } 2540 2541 // For each CU, cache the function DIEs that contain the 2542 // DW_AT_specification attribute. When building with -g3 the function 2543 // DIEs are separated in declaration and specification, with the 2544 // declaration containing only the name and parameters and the 2545 // specification the low/high pc and other compiler attributes. 2546 // 2547 // We cache those specifications so we don't skip over the declarations, 2548 // because they have no pc, and we can do namespace resolution for 2549 // DWARF function names. 2550 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 2551 Dwarf_Die current_die = 0; 2552 if (dwarf_child(die, ¤t_die, &error) == DW_DLV_OK) { 2553 for (;;) { 2554 Dwarf_Die sibling_die = 0; 2555 2556 Dwarf_Half tag_value; 2557 dwarf_tag(current_die, &tag_value, &error); 2558 2559 if (tag_value == DW_TAG_subprogram || 2560 tag_value == DW_TAG_inlined_subroutine) { 2561 2562 Dwarf_Bool has_attr = 0; 2563 if (dwarf_hasattr(current_die, DW_AT_specification, &has_attr, 2564 &error) == DW_DLV_OK) { 2565 if (has_attr) { 2566 Dwarf_Attribute attr_mem; 2567 if (dwarf_attr(current_die, DW_AT_specification, &attr_mem, 2568 &error) == DW_DLV_OK) { 2569 Dwarf_Off spec_offset = 0; 2570 if (dwarf_formref(attr_mem, &spec_offset, &error) == 2571 DW_DLV_OK) { 2572 Dwarf_Off spec_die_offset; 2573 if (dwarf_dieoffset(current_die, &spec_die_offset, &error) == 2574 DW_DLV_OK) { 2575 de.spec_section[spec_offset] = spec_die_offset; 2576 } 2577 } 2578 } 2579 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 2580 } 2581 } 2582 } 2583 2584 int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); 2585 if (result == DW_DLV_ERROR) { 2586 break; 2587 } else if (result == DW_DLV_NO_ENTRY) { 2588 break; 2589 } 2590 2591 if (current_die != die) { 2592 dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); 2593 current_die = 0; 2594 } 2595 2596 current_die = sibling_die; 2597 } 2598 } 2599 return de; 2600 } 2601 2602 static Dwarf_Die get_referenced_die(Dwarf_Debug dwarf, Dwarf_Die die, 2603 Dwarf_Half attr, bool global) { 2604 Dwarf_Error error = DW_DLE_NE; 2605 Dwarf_Attribute attr_mem; 2606 2607 Dwarf_Die found_die = NULL; 2608 if (dwarf_attr(die, attr, &attr_mem, &error) == DW_DLV_OK) { 2609 Dwarf_Off offset; 2610 int result = 0; 2611 if (global) { 2612 result = dwarf_global_formref(attr_mem, &offset, &error); 2613 } else { 2614 result = dwarf_formref(attr_mem, &offset, &error); 2615 } 2616 2617 if (result == DW_DLV_OK) { 2618 if (dwarf_offdie(dwarf, offset, &found_die, &error) != DW_DLV_OK) { 2619 found_die = NULL; 2620 } 2621 } 2622 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 2623 } 2624 return found_die; 2625 } 2626 2627 static std::string get_referenced_die_name(Dwarf_Debug dwarf, Dwarf_Die die, 2628 Dwarf_Half attr, bool global) { 2629 Dwarf_Error error = DW_DLE_NE; 2630 std::string value; 2631 2632 Dwarf_Die found_die = get_referenced_die(dwarf, die, attr, global); 2633 2634 if (found_die) { 2635 char *name; 2636 if (dwarf_diename(found_die, &name, &error) == DW_DLV_OK) { 2637 if (name) { 2638 value = std::string(name); 2639 } 2640 dwarf_dealloc(dwarf, name, DW_DLA_STRING); 2641 } 2642 dwarf_dealloc(dwarf, found_die, DW_DLA_DIE); 2643 } 2644 2645 return value; 2646 } 2647 2648 // Returns a spec DIE linked to the passed one. The caller should 2649 // deallocate the DIE 2650 static Dwarf_Die get_spec_die(dwarf_fileobject &fobj, Dwarf_Die die) { 2651 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 2652 Dwarf_Error error = DW_DLE_NE; 2653 Dwarf_Off die_offset; 2654 if (fobj.current_cu && 2655 dwarf_die_CU_offset(die, &die_offset, &error) == DW_DLV_OK) { 2656 die_specmap_t::iterator it = 2657 fobj.current_cu->spec_section.find(die_offset); 2658 2659 // If we have a DIE that completes the current one, check if 2660 // that one has the pc we are looking for 2661 if (it != fobj.current_cu->spec_section.end()) { 2662 Dwarf_Die spec_die = 0; 2663 if (dwarf_offdie(dwarf, it->second, &spec_die, &error) == DW_DLV_OK) { 2664 return spec_die; 2665 } 2666 } 2667 } 2668 2669 // Maybe we have an abstract origin DIE with the function information? 2670 return get_referenced_die(fobj.dwarf_handle.get(), die, 2671 DW_AT_abstract_origin, true); 2672 } 2673 2674 static bool die_has_pc(dwarf_fileobject &fobj, Dwarf_Die die, Dwarf_Addr pc) { 2675 Dwarf_Addr low_pc = 0, high_pc = 0; 2676 Dwarf_Half high_pc_form = 0; 2677 Dwarf_Form_Class return_class; 2678 Dwarf_Error error = DW_DLE_NE; 2679 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 2680 bool has_lowpc = false; 2681 bool has_highpc = false; 2682 bool has_ranges = false; 2683 2684 if (dwarf_lowpc(die, &low_pc, &error) == DW_DLV_OK) { 2685 // If we have a low_pc check if there is a high pc. 2686 // If we don't have a high pc this might mean we have a base 2687 // address for the ranges list or just an address. 2688 has_lowpc = true; 2689 2690 if (dwarf_highpc_b(die, &high_pc, &high_pc_form, &return_class, &error) == 2691 DW_DLV_OK) { 2692 // We do have a high pc. In DWARF 4+ this is an offset from the 2693 // low pc, but in earlier versions it's an absolute address. 2694 2695 has_highpc = true; 2696 // In DWARF 2/3 this would be a DW_FORM_CLASS_ADDRESS 2697 if (return_class == DW_FORM_CLASS_CONSTANT) { 2698 high_pc = low_pc + high_pc; 2699 } 2700 2701 // We have low and high pc, check if our address 2702 // is in that range 2703 return pc >= low_pc && pc < high_pc; 2704 } 2705 } else { 2706 // Reset the low_pc, in case dwarf_lowpc failing set it to some 2707 // undefined value. 2708 low_pc = 0; 2709 } 2710 2711 // Check if DW_AT_ranges is present and search for the PC in the 2712 // returned ranges list. We always add the low_pc, as it not set it will 2713 // be 0, in case we had a DW_AT_low_pc and DW_AT_ranges pair 2714 bool result = false; 2715 2716 Dwarf_Attribute attr; 2717 if (dwarf_attr(die, DW_AT_ranges, &attr, &error) == DW_DLV_OK) { 2718 2719 Dwarf_Off offset; 2720 if (dwarf_global_formref(attr, &offset, &error) == DW_DLV_OK) { 2721 Dwarf_Ranges *ranges; 2722 Dwarf_Signed ranges_count = 0; 2723 Dwarf_Unsigned byte_count = 0; 2724 2725 if (dwarf_get_ranges_a(dwarf, offset, die, &ranges, &ranges_count, 2726 &byte_count, &error) == DW_DLV_OK) { 2727 has_ranges = ranges_count != 0; 2728 for (int i = 0; i < ranges_count; i++) { 2729 if (ranges[i].dwr_addr1 != 0 && 2730 pc >= ranges[i].dwr_addr1 + low_pc && 2731 pc < ranges[i].dwr_addr2 + low_pc) { 2732 result = true; 2733 break; 2734 } 2735 } 2736 dwarf_ranges_dealloc(dwarf, ranges, ranges_count); 2737 } 2738 } 2739 } 2740 2741 // Last attempt. We might have a single address set as low_pc. 2742 if (!result && low_pc != 0 && pc == low_pc) { 2743 result = true; 2744 } 2745 2746 // If we don't have lowpc, highpc and ranges maybe this DIE is a 2747 // declaration that relies on a DW_AT_specification DIE that happens 2748 // later. Use the specification cache we filled when we loaded this CU. 2749 if (!result && (!has_lowpc && !has_highpc && !has_ranges)) { 2750 Dwarf_Die spec_die = get_spec_die(fobj, die); 2751 if (spec_die) { 2752 result = die_has_pc(fobj, spec_die, pc); 2753 dwarf_dealloc(dwarf, spec_die, DW_DLA_DIE); 2754 } 2755 } 2756 2757 return result; 2758 } 2759 2760 static void get_type(Dwarf_Debug dwarf, Dwarf_Die die, std::string &type) { 2761 Dwarf_Error error = DW_DLE_NE; 2762 2763 Dwarf_Die child = 0; 2764 if (dwarf_child(die, &child, &error) == DW_DLV_OK) { 2765 get_type(dwarf, child, type); 2766 } 2767 2768 if (child) { 2769 type.insert(0, "::"); 2770 dwarf_dealloc(dwarf, child, DW_DLA_DIE); 2771 } 2772 2773 char *name; 2774 if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { 2775 type.insert(0, std::string(name)); 2776 dwarf_dealloc(dwarf, name, DW_DLA_STRING); 2777 } else { 2778 type.insert(0, "<unknown>"); 2779 } 2780 } 2781 2782 static std::string get_type_by_signature(Dwarf_Debug dwarf, Dwarf_Die die) { 2783 Dwarf_Error error = DW_DLE_NE; 2784 2785 Dwarf_Sig8 signature; 2786 Dwarf_Bool has_attr = 0; 2787 if (dwarf_hasattr(die, DW_AT_signature, &has_attr, &error) == DW_DLV_OK) { 2788 if (has_attr) { 2789 Dwarf_Attribute attr_mem; 2790 if (dwarf_attr(die, DW_AT_signature, &attr_mem, &error) == DW_DLV_OK) { 2791 if (dwarf_formsig8(attr_mem, &signature, &error) != DW_DLV_OK) { 2792 return std::string("<no type signature>"); 2793 } 2794 } 2795 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 2796 } 2797 } 2798 2799 Dwarf_Unsigned next_cu_header; 2800 Dwarf_Sig8 tu_signature; 2801 std::string result; 2802 bool found = false; 2803 2804 while (dwarf_next_cu_header_d(dwarf, 0, 0, 0, 0, 0, 0, 0, &tu_signature, 0, 2805 &next_cu_header, 0, &error) == DW_DLV_OK) { 2806 2807 if (strncmp(signature.signature, tu_signature.signature, 8) == 0) { 2808 Dwarf_Die type_cu_die = 0; 2809 if (dwarf_siblingof_b(dwarf, 0, 0, &type_cu_die, &error) == DW_DLV_OK) { 2810 Dwarf_Die child_die = 0; 2811 if (dwarf_child(type_cu_die, &child_die, &error) == DW_DLV_OK) { 2812 get_type(dwarf, child_die, result); 2813 found = !result.empty(); 2814 dwarf_dealloc(dwarf, child_die, DW_DLA_DIE); 2815 } 2816 dwarf_dealloc(dwarf, type_cu_die, DW_DLA_DIE); 2817 } 2818 } 2819 } 2820 2821 if (found) { 2822 while (dwarf_next_cu_header_d(dwarf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2823 &next_cu_header, 0, &error) == DW_DLV_OK) { 2824 // Reset the cu header state. Unfortunately, libdwarf's 2825 // next_cu_header API keeps its own iterator per Dwarf_Debug 2826 // that can't be reset. We need to keep fetching elements until 2827 // the end. 2828 } 2829 } else { 2830 // If we couldn't resolve the type just print out the signature 2831 std::ostringstream string_stream; 2832 string_stream << "<0x" << std::hex << std::setfill('0'); 2833 for (int i = 0; i < 8; ++i) { 2834 string_stream << std::setw(2) << std::hex 2835 << (int)(unsigned char)(signature.signature[i]); 2836 } 2837 string_stream << ">"; 2838 result = string_stream.str(); 2839 } 2840 return result; 2841 } 2842 2843 struct type_context_t { 2844 bool is_const; 2845 bool is_typedef; 2846 bool has_type; 2847 bool has_name; 2848 std::string text; 2849 2850 type_context_t() 2851 : is_const(false), is_typedef(false), has_type(false), has_name(false) { 2852 } 2853 }; 2854 2855 // Types are resolved from right to left: we get the variable name first 2856 // and then all specifiers (like const or pointer) in a chain of DW_AT_type 2857 // DIEs. Call this function recursively until we get a complete type 2858 // string. 2859 static void set_parameter_string(dwarf_fileobject &fobj, Dwarf_Die die, 2860 type_context_t &context) { 2861 char *name; 2862 Dwarf_Error error = DW_DLE_NE; 2863 2864 // typedefs contain also the base type, so we skip it and only 2865 // print the typedef name 2866 if (!context.is_typedef) { 2867 if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { 2868 if (!context.text.empty()) { 2869 context.text.insert(0, " "); 2870 } 2871 context.text.insert(0, std::string(name)); 2872 dwarf_dealloc(fobj.dwarf_handle.get(), name, DW_DLA_STRING); 2873 } 2874 } else { 2875 context.is_typedef = false; 2876 context.has_type = true; 2877 if (context.is_const) { 2878 context.text.insert(0, "const "); 2879 context.is_const = false; 2880 } 2881 } 2882 2883 bool next_type_is_const = false; 2884 bool is_keyword = true; 2885 2886 Dwarf_Half tag = 0; 2887 Dwarf_Bool has_attr = 0; 2888 if (dwarf_tag(die, &tag, &error) == DW_DLV_OK) { 2889 switch (tag) { 2890 case DW_TAG_structure_type: 2891 case DW_TAG_union_type: 2892 case DW_TAG_class_type: 2893 case DW_TAG_enumeration_type: 2894 context.has_type = true; 2895 if (dwarf_hasattr(die, DW_AT_signature, &has_attr, &error) == 2896 DW_DLV_OK) { 2897 // If we have a signature it means the type is defined 2898 // in .debug_types, so we need to load the DIE pointed 2899 // at by the signature and resolve it 2900 if (has_attr) { 2901 std::string type = 2902 get_type_by_signature(fobj.dwarf_handle.get(), die); 2903 if (context.is_const) 2904 type.insert(0, "const "); 2905 2906 if (!context.text.empty()) 2907 context.text.insert(0, " "); 2908 context.text.insert(0, type); 2909 } 2910 2911 // Treat enums like typedefs, and skip printing its 2912 // base type 2913 context.is_typedef = (tag == DW_TAG_enumeration_type); 2914 } 2915 break; 2916 case DW_TAG_const_type: 2917 next_type_is_const = true; 2918 break; 2919 case DW_TAG_pointer_type: 2920 context.text.insert(0, "*"); 2921 break; 2922 case DW_TAG_reference_type: 2923 context.text.insert(0, "&"); 2924 break; 2925 case DW_TAG_restrict_type: 2926 context.text.insert(0, "restrict "); 2927 break; 2928 case DW_TAG_rvalue_reference_type: 2929 context.text.insert(0, "&&"); 2930 break; 2931 case DW_TAG_volatile_type: 2932 context.text.insert(0, "volatile "); 2933 break; 2934 case DW_TAG_typedef: 2935 // Propagate the const-ness to the next type 2936 // as typedefs are linked to its base type 2937 next_type_is_const = context.is_const; 2938 context.is_typedef = true; 2939 context.has_type = true; 2940 break; 2941 case DW_TAG_base_type: 2942 context.has_type = true; 2943 break; 2944 case DW_TAG_formal_parameter: 2945 context.has_name = true; 2946 break; 2947 default: 2948 is_keyword = false; 2949 break; 2950 } 2951 } 2952 2953 if (!is_keyword && context.is_const) { 2954 context.text.insert(0, "const "); 2955 } 2956 2957 context.is_const = next_type_is_const; 2958 2959 Dwarf_Die ref = 2960 get_referenced_die(fobj.dwarf_handle.get(), die, DW_AT_type, true); 2961 if (ref) { 2962 set_parameter_string(fobj, ref, context); 2963 dwarf_dealloc(fobj.dwarf_handle.get(), ref, DW_DLA_DIE); 2964 } 2965 2966 if (!context.has_type && context.has_name) { 2967 context.text.insert(0, "void "); 2968 context.has_type = true; 2969 } 2970 } 2971 2972 // Resolve the function return type and parameters 2973 static void set_function_parameters(std::string &function_name, 2974 std::vector<std::string> &ns, 2975 dwarf_fileobject &fobj, Dwarf_Die die) { 2976 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 2977 Dwarf_Error error = DW_DLE_NE; 2978 Dwarf_Die current_die = 0; 2979 std::string parameters; 2980 bool has_spec = true; 2981 // Check if we have a spec DIE. If we do we use it as it contains 2982 // more information, like parameter names. 2983 Dwarf_Die spec_die = get_spec_die(fobj, die); 2984 if (!spec_die) { 2985 has_spec = false; 2986 spec_die = die; 2987 } 2988 2989 std::vector<std::string>::const_iterator it = ns.begin(); 2990 std::string ns_name; 2991 for (it = ns.begin(); it < ns.end(); ++it) { 2992 ns_name.append(*it).append("::"); 2993 } 2994 2995 if (!ns_name.empty()) { 2996 function_name.insert(0, ns_name); 2997 } 2998 2999 // See if we have a function return type. It can be either on the 3000 // current die or in its spec one (usually true for inlined functions) 3001 std::string return_type = 3002 get_referenced_die_name(dwarf, die, DW_AT_type, true); 3003 if (return_type.empty()) { 3004 return_type = get_referenced_die_name(dwarf, spec_die, DW_AT_type, true); 3005 } 3006 if (!return_type.empty()) { 3007 return_type.append(" "); 3008 function_name.insert(0, return_type); 3009 } 3010 3011 if (dwarf_child(spec_die, ¤t_die, &error) == DW_DLV_OK) { 3012 for (;;) { 3013 Dwarf_Die sibling_die = 0; 3014 3015 Dwarf_Half tag_value; 3016 dwarf_tag(current_die, &tag_value, &error); 3017 3018 if (tag_value == DW_TAG_formal_parameter) { 3019 // Ignore artificial (ie, compiler generated) parameters 3020 bool is_artificial = false; 3021 Dwarf_Attribute attr_mem; 3022 if (dwarf_attr(current_die, DW_AT_artificial, &attr_mem, &error) == 3023 DW_DLV_OK) { 3024 Dwarf_Bool flag = 0; 3025 if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { 3026 is_artificial = flag != 0; 3027 } 3028 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3029 } 3030 3031 if (!is_artificial) { 3032 type_context_t context; 3033 set_parameter_string(fobj, current_die, context); 3034 3035 if (parameters.empty()) { 3036 parameters.append("("); 3037 } else { 3038 parameters.append(", "); 3039 } 3040 parameters.append(context.text); 3041 } 3042 } 3043 3044 int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); 3045 if (result == DW_DLV_ERROR) { 3046 break; 3047 } else if (result == DW_DLV_NO_ENTRY) { 3048 break; 3049 } 3050 3051 if (current_die != die) { 3052 dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); 3053 current_die = 0; 3054 } 3055 3056 current_die = sibling_die; 3057 } 3058 } 3059 if (parameters.empty()) 3060 parameters = "("; 3061 parameters.append(")"); 3062 3063 // If we got a spec DIE we need to deallocate it 3064 if (has_spec) 3065 dwarf_dealloc(dwarf, spec_die, DW_DLA_DIE); 3066 3067 function_name.append(parameters); 3068 } 3069 3070 // defined here because in C++98, template function cannot take locally 3071 // defined types... grrr. 3072 struct inliners_search_cb { 3073 void operator()(Dwarf_Die die, std::vector<std::string> &ns) { 3074 Dwarf_Error error = DW_DLE_NE; 3075 Dwarf_Half tag_value; 3076 Dwarf_Attribute attr_mem; 3077 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 3078 3079 dwarf_tag(die, &tag_value, &error); 3080 3081 switch (tag_value) { 3082 char *name; 3083 case DW_TAG_subprogram: 3084 if (!trace.source.function.empty()) 3085 break; 3086 if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { 3087 trace.source.function = std::string(name); 3088 dwarf_dealloc(dwarf, name, DW_DLA_STRING); 3089 } else { 3090 // We don't have a function name in this DIE. 3091 // Check if there is a referenced non-defining 3092 // declaration. 3093 trace.source.function = 3094 get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true); 3095 if (trace.source.function.empty()) { 3096 trace.source.function = 3097 get_referenced_die_name(dwarf, die, DW_AT_specification, true); 3098 } 3099 } 3100 3101 // Append the function parameters, if available 3102 set_function_parameters(trace.source.function, ns, fobj, die); 3103 3104 // If the object function name is empty, it's possible that 3105 // there is no dynamic symbol table (maybe the executable 3106 // was stripped or not built with -rdynamic). See if we have 3107 // a DWARF linkage name to use instead. We try both 3108 // linkage_name and MIPS_linkage_name because the MIPS tag 3109 // was the unofficial one until it was adopted in DWARF4. 3110 // Old gcc versions generate MIPS_linkage_name 3111 if (trace.object_function.empty()) { 3112 details::demangler demangler; 3113 3114 if (dwarf_attr(die, DW_AT_linkage_name, &attr_mem, &error) != 3115 DW_DLV_OK) { 3116 if (dwarf_attr(die, DW_AT_MIPS_linkage_name, &attr_mem, &error) != 3117 DW_DLV_OK) { 3118 break; 3119 } 3120 } 3121 3122 char *linkage; 3123 if (dwarf_formstring(attr_mem, &linkage, &error) == DW_DLV_OK) { 3124 trace.object_function = demangler.demangle(linkage); 3125 dwarf_dealloc(dwarf, linkage, DW_DLA_STRING); 3126 } 3127 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3128 } 3129 break; 3130 3131 case DW_TAG_inlined_subroutine: 3132 ResolvedTrace::SourceLoc sloc; 3133 3134 if (dwarf_diename(die, &name, &error) == DW_DLV_OK) { 3135 sloc.function = std::string(name); 3136 dwarf_dealloc(dwarf, name, DW_DLA_STRING); 3137 } else { 3138 // We don't have a name for this inlined DIE, it could 3139 // be that there is an abstract origin instead. 3140 // Get the DW_AT_abstract_origin value, which is a 3141 // reference to the source DIE and try to get its name 3142 sloc.function = 3143 get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true); 3144 } 3145 3146 set_function_parameters(sloc.function, ns, fobj, die); 3147 3148 std::string file = die_call_file(dwarf, die, cu_die); 3149 if (!file.empty()) 3150 sloc.filename = file; 3151 3152 Dwarf_Unsigned number = 0; 3153 if (dwarf_attr(die, DW_AT_call_line, &attr_mem, &error) == DW_DLV_OK) { 3154 if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) { 3155 sloc.line = number; 3156 } 3157 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3158 } 3159 3160 if (dwarf_attr(die, DW_AT_call_column, &attr_mem, &error) == 3161 DW_DLV_OK) { 3162 if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) { 3163 sloc.col = number; 3164 } 3165 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3166 } 3167 3168 trace.inliners.push_back(sloc); 3169 break; 3170 }; 3171 } 3172 ResolvedTrace &trace; 3173 dwarf_fileobject &fobj; 3174 Dwarf_Die cu_die; 3175 inliners_search_cb(ResolvedTrace &t, dwarf_fileobject &f, Dwarf_Die c) 3176 : trace(t), fobj(f), cu_die(c) {} 3177 }; 3178 3179 static Dwarf_Die find_fundie_by_pc(dwarf_fileobject &fobj, 3180 Dwarf_Die parent_die, Dwarf_Addr pc, 3181 Dwarf_Die result) { 3182 Dwarf_Die current_die = 0; 3183 Dwarf_Error error = DW_DLE_NE; 3184 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 3185 3186 if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) { 3187 return NULL; 3188 } 3189 3190 for (;;) { 3191 Dwarf_Die sibling_die = 0; 3192 Dwarf_Half tag_value; 3193 dwarf_tag(current_die, &tag_value, &error); 3194 3195 switch (tag_value) { 3196 case DW_TAG_subprogram: 3197 case DW_TAG_inlined_subroutine: 3198 if (die_has_pc(fobj, current_die, pc)) { 3199 return current_die; 3200 } 3201 }; 3202 bool declaration = false; 3203 Dwarf_Attribute attr_mem; 3204 if (dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == 3205 DW_DLV_OK) { 3206 Dwarf_Bool flag = 0; 3207 if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { 3208 declaration = flag != 0; 3209 } 3210 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3211 } 3212 3213 if (!declaration) { 3214 // let's be curious and look deeper in the tree, functions are 3215 // not necessarily at the first level, but might be nested 3216 // inside a namespace, structure, a function, an inlined 3217 // function etc. 3218 Dwarf_Die die_mem = 0; 3219 Dwarf_Die indie = find_fundie_by_pc(fobj, current_die, pc, die_mem); 3220 if (indie) { 3221 result = die_mem; 3222 return result; 3223 } 3224 } 3225 3226 int res = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); 3227 if (res == DW_DLV_ERROR) { 3228 return NULL; 3229 } else if (res == DW_DLV_NO_ENTRY) { 3230 break; 3231 } 3232 3233 if (current_die != parent_die) { 3234 dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); 3235 current_die = 0; 3236 } 3237 3238 current_die = sibling_die; 3239 } 3240 return NULL; 3241 } 3242 3243 template <typename CB> 3244 static bool deep_first_search_by_pc(dwarf_fileobject &fobj, 3245 Dwarf_Die parent_die, Dwarf_Addr pc, 3246 std::vector<std::string> &ns, CB cb) { 3247 Dwarf_Die current_die = 0; 3248 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 3249 Dwarf_Error error = DW_DLE_NE; 3250 3251 if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) { 3252 return false; 3253 } 3254 3255 bool branch_has_pc = false; 3256 bool has_namespace = false; 3257 for (;;) { 3258 Dwarf_Die sibling_die = 0; 3259 3260 Dwarf_Half tag; 3261 if (dwarf_tag(current_die, &tag, &error) == DW_DLV_OK) { 3262 if (tag == DW_TAG_namespace || tag == DW_TAG_class_type) { 3263 char *ns_name = NULL; 3264 if (dwarf_diename(current_die, &ns_name, &error) == DW_DLV_OK) { 3265 if (ns_name) { 3266 ns.push_back(std::string(ns_name)); 3267 } else { 3268 ns.push_back("<unknown>"); 3269 } 3270 dwarf_dealloc(dwarf, ns_name, DW_DLA_STRING); 3271 } else { 3272 ns.push_back("<unknown>"); 3273 } 3274 has_namespace = true; 3275 } 3276 } 3277 3278 bool declaration = false; 3279 Dwarf_Attribute attr_mem; 3280 if (tag != DW_TAG_class_type && 3281 dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == 3282 DW_DLV_OK) { 3283 Dwarf_Bool flag = 0; 3284 if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) { 3285 declaration = flag != 0; 3286 } 3287 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3288 } 3289 3290 if (!declaration) { 3291 // let's be curious and look deeper in the tree, function are 3292 // not necessarily at the first level, but might be nested 3293 // inside a namespace, structure, a function, an inlined 3294 // function etc. 3295 branch_has_pc = deep_first_search_by_pc(fobj, current_die, pc, ns, cb); 3296 } 3297 3298 if (!branch_has_pc) { 3299 branch_has_pc = die_has_pc(fobj, current_die, pc); 3300 } 3301 3302 if (branch_has_pc) { 3303 cb(current_die, ns); 3304 } 3305 3306 int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error); 3307 if (result == DW_DLV_ERROR) { 3308 return false; 3309 } else if (result == DW_DLV_NO_ENTRY) { 3310 break; 3311 } 3312 3313 if (current_die != parent_die) { 3314 dwarf_dealloc(dwarf, current_die, DW_DLA_DIE); 3315 current_die = 0; 3316 } 3317 3318 if (has_namespace) { 3319 has_namespace = false; 3320 ns.pop_back(); 3321 } 3322 current_die = sibling_die; 3323 } 3324 3325 if (has_namespace) { 3326 ns.pop_back(); 3327 } 3328 return branch_has_pc; 3329 } 3330 3331 static std::string die_call_file(Dwarf_Debug dwarf, Dwarf_Die die, 3332 Dwarf_Die cu_die) { 3333 Dwarf_Attribute attr_mem; 3334 Dwarf_Error error = DW_DLE_NE; 3335 Dwarf_Unsigned file_index; 3336 3337 std::string file; 3338 3339 if (dwarf_attr(die, DW_AT_call_file, &attr_mem, &error) == DW_DLV_OK) { 3340 if (dwarf_formudata(attr_mem, &file_index, &error) != DW_DLV_OK) { 3341 file_index = 0; 3342 } 3343 dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR); 3344 3345 if (file_index == 0) { 3346 return file; 3347 } 3348 3349 char **srcfiles = 0; 3350 Dwarf_Signed file_count = 0; 3351 if (dwarf_srcfiles(cu_die, &srcfiles, &file_count, &error) == DW_DLV_OK) { 3352 if (file_count > 0 && file_index <= static_cast<Dwarf_Unsigned>(file_count)) { 3353 file = std::string(srcfiles[file_index - 1]); 3354 } 3355 3356 // Deallocate all strings! 3357 for (int i = 0; i < file_count; ++i) { 3358 dwarf_dealloc(dwarf, srcfiles[i], DW_DLA_STRING); 3359 } 3360 dwarf_dealloc(dwarf, srcfiles, DW_DLA_LIST); 3361 } 3362 } 3363 return file; 3364 } 3365 3366 Dwarf_Die find_die(dwarf_fileobject &fobj, Dwarf_Addr addr) { 3367 // Let's get to work! First see if we have a debug_aranges section so 3368 // we can speed up the search 3369 3370 Dwarf_Debug dwarf = fobj.dwarf_handle.get(); 3371 Dwarf_Error error = DW_DLE_NE; 3372 Dwarf_Arange *aranges; 3373 Dwarf_Signed arange_count; 3374 3375 Dwarf_Die returnDie; 3376 bool found = false; 3377 if (dwarf_get_aranges(dwarf, &aranges, &arange_count, &error) != 3378 DW_DLV_OK) { 3379 aranges = NULL; 3380 } 3381 3382 if (aranges) { 3383 // We have aranges. Get the one where our address is. 3384 Dwarf_Arange arange; 3385 if (dwarf_get_arange(aranges, arange_count, addr, &arange, &error) == 3386 DW_DLV_OK) { 3387 3388 // We found our address. Get the compilation-unit DIE offset 3389 // represented by the given address range. 3390 Dwarf_Off cu_die_offset; 3391 if (dwarf_get_cu_die_offset(arange, &cu_die_offset, &error) == 3392 DW_DLV_OK) { 3393 // Get the DIE at the offset returned by the aranges search. 3394 // We set is_info to 1 to specify that the offset is from 3395 // the .debug_info section (and not .debug_types) 3396 int dwarf_result = 3397 dwarf_offdie_b(dwarf, cu_die_offset, 1, &returnDie, &error); 3398 3399 found = dwarf_result == DW_DLV_OK; 3400 } 3401 dwarf_dealloc(dwarf, arange, DW_DLA_ARANGE); 3402 } 3403 } 3404 3405 if (found) 3406 return returnDie; // The caller is responsible for freeing the die 3407 3408 // The search for aranges failed. Try to find our address by scanning 3409 // all compilation units. 3410 Dwarf_Unsigned next_cu_header; 3411 Dwarf_Half tag = 0; 3412 returnDie = 0; 3413 3414 while (!found && 3415 dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3416 &next_cu_header, 0, &error) == DW_DLV_OK) { 3417 3418 if (returnDie) 3419 dwarf_dealloc(dwarf, returnDie, DW_DLA_DIE); 3420 3421 if (dwarf_siblingof(dwarf, 0, &returnDie, &error) == DW_DLV_OK) { 3422 if ((dwarf_tag(returnDie, &tag, &error) == DW_DLV_OK) && 3423 tag == DW_TAG_compile_unit) { 3424 if (die_has_pc(fobj, returnDie, addr)) { 3425 found = true; 3426 } 3427 } 3428 } 3429 } 3430 3431 if (found) { 3432 while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3433 &next_cu_header, 0, &error) == DW_DLV_OK) { 3434 // Reset the cu header state. Libdwarf's next_cu_header API 3435 // keeps its own iterator per Dwarf_Debug that can't be reset. 3436 // We need to keep fetching elements until the end. 3437 } 3438 } 3439 3440 if (found) 3441 return returnDie; 3442 3443 // We couldn't find any compilation units with ranges or a high/low pc. 3444 // Try again by looking at all DIEs in all compilation units. 3445 Dwarf_Die cudie; 3446 while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3447 &next_cu_header, 0, &error) == DW_DLV_OK) { 3448 if (dwarf_siblingof(dwarf, 0, &cudie, &error) == DW_DLV_OK) { 3449 Dwarf_Die die_mem = 0; 3450 Dwarf_Die resultDie = find_fundie_by_pc(fobj, cudie, addr, die_mem); 3451 3452 if (resultDie) { 3453 found = true; 3454 break; 3455 } 3456 } 3457 } 3458 3459 if (found) { 3460 while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3461 &next_cu_header, 0, &error) == DW_DLV_OK) { 3462 // Reset the cu header state. Libdwarf's next_cu_header API 3463 // keeps its own iterator per Dwarf_Debug that can't be reset. 3464 // We need to keep fetching elements until the end. 3465 } 3466 } 3467 3468 if (found) 3469 return cudie; 3470 3471 // We failed. 3472 return NULL; 3473 } 3474 }; 3475 #endif // BACKWARD_HAS_DWARF == 1 3476 3477 template <> 3478 class TraceResolverImpl<system_tag::linux_tag> 3479 : public TraceResolverLinuxImpl<trace_resolver_tag::current> {}; 3480 3481 #endif // BACKWARD_SYSTEM_LINUX 3482 3483 #ifdef BACKWARD_SYSTEM_DARWIN 3484 3485 template <typename STACKTRACE_TAG> class TraceResolverDarwinImpl; 3486 3487 template <> 3488 class TraceResolverDarwinImpl<trace_resolver_tag::backtrace_symbol> 3489 : public TraceResolverImplBase { 3490 public: 3491 void load_addresses(void *const*addresses, int address_count) override { 3492 if (address_count == 0) { 3493 return; 3494 } 3495 _symbols.reset(backtrace_symbols(addresses, address_count)); 3496 } 3497 3498 ResolvedTrace resolve(ResolvedTrace trace) override { 3499 // parse: 3500 // <n> <file> <addr> <mangled-name> + <offset> 3501 char *filename = _symbols[trace.idx]; 3502 3503 // skip "<n> " 3504 while (*filename && *filename != ' ') 3505 filename++; 3506 while (*filename == ' ') 3507 filename++; 3508 3509 // find start of <mangled-name> from end (<file> may contain a space) 3510 char *p = filename + strlen(filename) - 1; 3511 // skip to start of " + <offset>" 3512 while (p > filename && *p != ' ') 3513 p--; 3514 while (p > filename && *p == ' ') 3515 p--; 3516 while (p > filename && *p != ' ') 3517 p--; 3518 while (p > filename && *p == ' ') 3519 p--; 3520 char *funcname_end = p + 1; 3521 3522 // skip to start of "<manged-name>" 3523 while (p > filename && *p != ' ') 3524 p--; 3525 char *funcname = p + 1; 3526 3527 // skip to start of " <addr> " 3528 while (p > filename && *p == ' ') 3529 p--; 3530 while (p > filename && *p != ' ') 3531 p--; 3532 while (p > filename && *p == ' ') 3533 p--; 3534 3535 // skip "<file>", handling the case where it contains a 3536 char *filename_end = p + 1; 3537 if (p == filename) { 3538 // something went wrong, give up 3539 filename_end = filename + strlen(filename); 3540 funcname = filename_end; 3541 } 3542 trace.object_filename.assign( 3543 filename, filename_end); // ok even if filename_end is the ending \0 3544 // (then we assign entire string) 3545 3546 if (*funcname) { // if it's not end of string 3547 *funcname_end = '\0'; 3548 3549 trace.object_function = this->demangle(funcname); 3550 trace.object_function += " "; 3551 trace.object_function += (funcname_end + 1); 3552 trace.source.function = trace.object_function; // we cannot do better. 3553 } 3554 return trace; 3555 } 3556 3557 private: 3558 details::handle<char **> _symbols; 3559 }; 3560 3561 template <> 3562 class TraceResolverImpl<system_tag::darwin_tag> 3563 : public TraceResolverDarwinImpl<trace_resolver_tag::current> {}; 3564 3565 #endif // BACKWARD_SYSTEM_DARWIN 3566 3567 #ifdef BACKWARD_SYSTEM_WINDOWS 3568 3569 // Load all symbol info 3570 // Based on: 3571 // https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227 3572 3573 struct module_data { 3574 std::string image_name; 3575 std::string module_name; 3576 void *base_address; 3577 DWORD load_size; 3578 }; 3579 3580 class get_mod_info { 3581 HANDLE process; 3582 static const int buffer_length = 4096; 3583 3584 public: 3585 get_mod_info(HANDLE h) : process(h) {} 3586 3587 module_data operator()(HMODULE module) { 3588 module_data ret; 3589 char temp[buffer_length]; 3590 MODULEINFO mi; 3591 3592 GetModuleInformation(process, module, &mi, sizeof(mi)); 3593 ret.base_address = mi.lpBaseOfDll; 3594 ret.load_size = mi.SizeOfImage; 3595 3596 GetModuleFileNameExA(process, module, temp, sizeof(temp)); 3597 ret.image_name = temp; 3598 GetModuleBaseNameA(process, module, temp, sizeof(temp)); 3599 ret.module_name = temp; 3600 std::vector<char> img(ret.image_name.begin(), ret.image_name.end()); 3601 std::vector<char> mod(ret.module_name.begin(), ret.module_name.end()); 3602 SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, 3603 ret.load_size); 3604 return ret; 3605 } 3606 }; 3607 3608 template <> class TraceResolverImpl<system_tag::windows_tag> 3609 : public TraceResolverImplBase { 3610 public: 3611 TraceResolverImpl() { 3612 3613 HANDLE process = GetCurrentProcess(); 3614 3615 std::vector<module_data> modules; 3616 DWORD cbNeeded; 3617 std::vector<HMODULE> module_handles(1); 3618 SymInitialize(process, NULL, false); 3619 DWORD symOptions = SymGetOptions(); 3620 symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME; 3621 SymSetOptions(symOptions); 3622 EnumProcessModules(process, &module_handles[0], 3623 static_cast<DWORD>(module_handles.size() * sizeof(HMODULE)), 3624 &cbNeeded); 3625 module_handles.resize(cbNeeded / sizeof(HMODULE)); 3626 EnumProcessModules(process, &module_handles[0], 3627 static_cast<DWORD>(module_handles.size() * sizeof(HMODULE)), 3628 &cbNeeded); 3629 std::transform(module_handles.begin(), module_handles.end(), 3630 std::back_inserter(modules), get_mod_info(process)); 3631 void *base = modules[0].base_address; 3632 IMAGE_NT_HEADERS *h = ImageNtHeader(base); 3633 image_type = h->FileHeader.Machine; 3634 } 3635 3636 static const int max_sym_len = 255; 3637 struct symbol_t { 3638 SYMBOL_INFO sym; 3639 char buffer[max_sym_len]; 3640 } sym; 3641 3642 DWORD64 displacement; 3643 3644 ResolvedTrace resolve(ResolvedTrace t) override { 3645 HANDLE process = GetCurrentProcess(); 3646 3647 char name[256]; 3648 3649 memset(&sym, 0, sizeof(sym)); 3650 sym.sym.SizeOfStruct = sizeof(SYMBOL_INFO); 3651 sym.sym.MaxNameLen = max_sym_len; 3652 3653 if (!SymFromAddr(process, (ULONG64)t.addr, &displacement, &sym.sym)) { 3654 // TODO: error handling everywhere 3655 char* lpMsgBuf; 3656 DWORD dw = GetLastError(); 3657 3658 if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | 3659 FORMAT_MESSAGE_FROM_SYSTEM | 3660 FORMAT_MESSAGE_IGNORE_INSERTS, 3661 NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 3662 (char*)&lpMsgBuf, 0, NULL)) { 3663 std::fprintf(stderr, "%s\n", lpMsgBuf); 3664 LocalFree(lpMsgBuf); 3665 } 3666 3667 // abort(); 3668 } 3669 UnDecorateSymbolName(sym.sym.Name, (PSTR)name, 256, UNDNAME_COMPLETE); 3670 3671 DWORD offset = 0; 3672 IMAGEHLP_LINE line; 3673 if (SymGetLineFromAddr(process, (ULONG64)t.addr, &offset, &line)) { 3674 t.object_filename = line.FileName; 3675 t.source.filename = line.FileName; 3676 t.source.line = line.LineNumber; 3677 t.source.col = offset; 3678 } 3679 3680 t.source.function = name; 3681 t.object_filename = ""; 3682 t.object_function = name; 3683 3684 return t; 3685 } 3686 3687 DWORD machine_type() const { return image_type; } 3688 3689 private: 3690 DWORD image_type; 3691 }; 3692 3693 #endif 3694 3695 class TraceResolver : public TraceResolverImpl<system_tag::current_tag> {}; 3696 3697 /*************** CODE SNIPPET ***************/ 3698 3699 class SourceFile { 3700 public: 3701 typedef std::vector<std::pair<unsigned, std::string> > lines_t; 3702 3703 SourceFile() {} 3704 SourceFile(const std::string &path) { 3705 // 1. If BACKWARD_CXX_SOURCE_PREFIXES is set then assume it contains 3706 // a colon-separated list of path prefixes. Try prepending each 3707 // to the given path until a valid file is found. 3708 const std::vector<std::string> &prefixes = get_paths_from_env_variable(); 3709 for (size_t i = 0; i < prefixes.size(); ++i) { 3710 // Double slashes (//) should not be a problem. 3711 std::string new_path = prefixes[i] + '/' + path; 3712 _file.reset(new std::ifstream(new_path.c_str())); 3713 if (is_open()) 3714 break; 3715 } 3716 // 2. If no valid file found then fallback to opening the path as-is. 3717 if (!_file || !is_open()) { 3718 _file.reset(new std::ifstream(path.c_str())); 3719 } 3720 } 3721 bool is_open() const { return _file->is_open(); } 3722 3723 lines_t &get_lines(unsigned line_start, unsigned line_count, lines_t &lines) { 3724 using namespace std; 3725 // This function make uses of the dumbest algo ever: 3726 // 1) seek(0) 3727 // 2) read lines one by one and discard until line_start 3728 // 3) read line one by one until line_start + line_count 3729 // 3730 // If you are getting snippets many time from the same file, it is 3731 // somewhat a waste of CPU, feel free to benchmark and propose a 3732 // better solution ;) 3733 3734 _file->clear(); 3735 _file->seekg(0); 3736 string line; 3737 unsigned line_idx; 3738 3739 for (line_idx = 1; line_idx < line_start; ++line_idx) { 3740 std::getline(*_file, line); 3741 if (!*_file) { 3742 return lines; 3743 } 3744 } 3745 3746 // think of it like a lambda in C++98 ;) 3747 // but look, I will reuse it two times! 3748 // What a good boy am I. 3749 struct isspace { 3750 bool operator()(char c) { return std::isspace(c); } 3751 }; 3752 3753 bool started = false; 3754 for (; line_idx < line_start + line_count; ++line_idx) { 3755 getline(*_file, line); 3756 if (!*_file) { 3757 return lines; 3758 } 3759 if (!started) { 3760 if (std::find_if(line.begin(), line.end(), not_isspace()) == line.end()) 3761 continue; 3762 started = true; 3763 } 3764 lines.push_back(make_pair(line_idx, line)); 3765 } 3766 3767 lines.erase( 3768 std::find_if(lines.rbegin(), lines.rend(), not_isempty()).base(), 3769 lines.end()); 3770 return lines; 3771 } 3772 3773 lines_t get_lines(unsigned line_start, unsigned line_count) { 3774 lines_t lines; 3775 return get_lines(line_start, line_count, lines); 3776 } 3777 3778 // there is no find_if_not in C++98, lets do something crappy to 3779 // workaround. 3780 struct not_isspace { 3781 bool operator()(char c) { return !std::isspace(c); } 3782 }; 3783 // and define this one here because C++98 is not happy with local defined 3784 // struct passed to template functions, fuuuu. 3785 struct not_isempty { 3786 bool operator()(const lines_t::value_type &p) { 3787 return !(std::find_if(p.second.begin(), p.second.end(), not_isspace()) == 3788 p.second.end()); 3789 } 3790 }; 3791 3792 void swap(SourceFile &b) { _file.swap(b._file); } 3793 3794 #ifdef BACKWARD_ATLEAST_CXX11 3795 SourceFile(SourceFile &&from) : _file(nullptr) { swap(from); } 3796 SourceFile &operator=(SourceFile &&from) { 3797 swap(from); 3798 return *this; 3799 } 3800 #else 3801 explicit SourceFile(const SourceFile &from) { 3802 // some sort of poor man's move semantic. 3803 swap(const_cast<SourceFile &>(from)); 3804 } 3805 SourceFile &operator=(const SourceFile &from) { 3806 // some sort of poor man's move semantic. 3807 swap(const_cast<SourceFile &>(from)); 3808 return *this; 3809 } 3810 #endif 3811 3812 private: 3813 details::handle<std::ifstream *, details::default_delete<std::ifstream *> > 3814 _file; 3815 3816 std::vector<std::string> get_paths_from_env_variable_impl() { 3817 std::vector<std::string> paths; 3818 const char *prefixes_str = std::getenv("BACKWARD_CXX_SOURCE_PREFIXES"); 3819 if (prefixes_str && prefixes_str[0]) { 3820 paths = details::split_source_prefixes(prefixes_str); 3821 } 3822 return paths; 3823 } 3824 3825 const std::vector<std::string> &get_paths_from_env_variable() { 3826 static std::vector<std::string> paths = get_paths_from_env_variable_impl(); 3827 return paths; 3828 } 3829 3830 #ifdef BACKWARD_ATLEAST_CXX11 3831 SourceFile(const SourceFile &) = delete; 3832 SourceFile &operator=(const SourceFile &) = delete; 3833 #endif 3834 }; 3835 3836 class SnippetFactory { 3837 public: 3838 typedef SourceFile::lines_t lines_t; 3839 3840 lines_t get_snippet(const std::string &filename, unsigned line_start, 3841 unsigned context_size) { 3842 3843 SourceFile &src_file = get_src_file(filename); 3844 unsigned start = line_start - context_size / 2; 3845 return src_file.get_lines(start, context_size); 3846 } 3847 3848 lines_t get_combined_snippet(const std::string &filename_a, unsigned line_a, 3849 const std::string &filename_b, unsigned line_b, 3850 unsigned context_size) { 3851 SourceFile &src_file_a = get_src_file(filename_a); 3852 SourceFile &src_file_b = get_src_file(filename_b); 3853 3854 lines_t lines = 3855 src_file_a.get_lines(line_a - context_size / 4, context_size / 2); 3856 src_file_b.get_lines(line_b - context_size / 4, context_size / 2, lines); 3857 return lines; 3858 } 3859 3860 lines_t get_coalesced_snippet(const std::string &filename, unsigned line_a, 3861 unsigned line_b, unsigned context_size) { 3862 SourceFile &src_file = get_src_file(filename); 3863 3864 using std::max; 3865 using std::min; 3866 unsigned a = min(line_a, line_b); 3867 unsigned b = max(line_a, line_b); 3868 3869 if ((b - a) < (context_size / 3)) { 3870 return src_file.get_lines((a + b - context_size + 1) / 2, context_size); 3871 } 3872 3873 lines_t lines = src_file.get_lines(a - context_size / 4, context_size / 2); 3874 src_file.get_lines(b - context_size / 4, context_size / 2, lines); 3875 return lines; 3876 } 3877 3878 private: 3879 typedef details::hashtable<std::string, SourceFile>::type src_files_t; 3880 src_files_t _src_files; 3881 3882 SourceFile &get_src_file(const std::string &filename) { 3883 src_files_t::iterator it = _src_files.find(filename); 3884 if (it != _src_files.end()) { 3885 return it->second; 3886 } 3887 SourceFile &new_src_file = _src_files[filename]; 3888 new_src_file = SourceFile(filename); 3889 return new_src_file; 3890 } 3891 }; 3892 3893 /*************** PRINTER ***************/ 3894 3895 namespace ColorMode { 3896 enum type { automatic, never, always }; 3897 } 3898 3899 class cfile_streambuf : public std::streambuf { 3900 public: 3901 cfile_streambuf(FILE *_sink) : sink(_sink) {} 3902 int_type underflow() override { return traits_type::eof(); } 3903 int_type overflow(int_type ch) override { 3904 if (traits_type::not_eof(ch) && fputc(ch, sink) != EOF) { 3905 return ch; 3906 } 3907 return traits_type::eof(); 3908 } 3909 3910 std::streamsize xsputn(const char_type *s, std::streamsize count) override { 3911 return static_cast<std::streamsize>( 3912 fwrite(s, sizeof *s, static_cast<size_t>(count), sink)); 3913 } 3914 3915 #ifdef BACKWARD_ATLEAST_CXX11 3916 public: 3917 cfile_streambuf(const cfile_streambuf &) = delete; 3918 cfile_streambuf &operator=(const cfile_streambuf &) = delete; 3919 #else 3920 private: 3921 cfile_streambuf(const cfile_streambuf &); 3922 cfile_streambuf &operator=(const cfile_streambuf &); 3923 #endif 3924 3925 private: 3926 FILE *sink; 3927 std::vector<char> buffer; 3928 }; 3929 3930 #ifdef BACKWARD_SYSTEM_LINUX 3931 3932 namespace Color { 3933 enum type { yellow = 33, purple = 35, reset = 39 }; 3934 } // namespace Color 3935 3936 class Colorize { 3937 public: 3938 Colorize(std::ostream &os) : _os(os), _reset(false), _enabled(false) {} 3939 3940 void activate(ColorMode::type mode) { _enabled = mode == ColorMode::always; } 3941 3942 void activate(ColorMode::type mode, FILE *fp) { activate(mode, fileno(fp)); } 3943 3944 void set_color(Color::type ccode) { 3945 if (!_enabled) 3946 return; 3947 3948 // I assume that the terminal can handle basic colors. Seriously I 3949 // don't want to deal with all the termcap shit. 3950 _os << "\033[" << static_cast<int>(ccode) << "m"; 3951 _reset = (ccode != Color::reset); 3952 } 3953 3954 ~Colorize() { 3955 if (_reset) { 3956 set_color(Color::reset); 3957 } 3958 } 3959 3960 private: 3961 void activate(ColorMode::type mode, int fd) { 3962 activate(mode == ColorMode::automatic && isatty(fd) ? ColorMode::always 3963 : mode); 3964 } 3965 3966 std::ostream &_os; 3967 bool _reset; 3968 bool _enabled; 3969 }; 3970 3971 #else // ndef BACKWARD_SYSTEM_LINUX 3972 3973 namespace Color { 3974 enum type { yellow = 0, purple = 0, reset = 0 }; 3975 } // namespace Color 3976 3977 class Colorize { 3978 public: 3979 Colorize(std::ostream &) {} 3980 void activate(ColorMode::type) {} 3981 void activate(ColorMode::type, FILE *) {} 3982 void set_color(Color::type) {} 3983 }; 3984 3985 #endif // BACKWARD_SYSTEM_LINUX 3986 3987 class Printer { 3988 public: 3989 bool snippet; 3990 ColorMode::type color_mode; 3991 bool address; 3992 bool object; 3993 int inliner_context_size; 3994 int trace_context_size; 3995 bool reverse; 3996 3997 Printer() 3998 : snippet(true), color_mode(ColorMode::automatic), address(false), 3999 object(false), inliner_context_size(5), trace_context_size(7), 4000 reverse(true) {} 4001 4002 template <typename ST> FILE *print(ST &st, FILE *fp = stderr) { 4003 cfile_streambuf obuf(fp); 4004 std::ostream os(&obuf); 4005 Colorize colorize(os); 4006 colorize.activate(color_mode, fp); 4007 print_stacktrace(st, os, colorize); 4008 return fp; 4009 } 4010 4011 template <typename ST> std::ostream &print(ST &st, std::ostream &os) { 4012 Colorize colorize(os); 4013 colorize.activate(color_mode); 4014 print_stacktrace(st, os, colorize); 4015 return os; 4016 } 4017 4018 template <typename IT> 4019 FILE *print(IT begin, IT end, FILE *fp = stderr, size_t thread_id = 0) { 4020 cfile_streambuf obuf(fp); 4021 std::ostream os(&obuf); 4022 Colorize colorize(os); 4023 colorize.activate(color_mode, fp); 4024 print_stacktrace(begin, end, os, thread_id, colorize); 4025 return fp; 4026 } 4027 4028 template <typename IT> 4029 std::ostream &print(IT begin, IT end, std::ostream &os, 4030 size_t thread_id = 0) { 4031 Colorize colorize(os); 4032 colorize.activate(color_mode); 4033 print_stacktrace(begin, end, os, thread_id, colorize); 4034 return os; 4035 } 4036 4037 TraceResolver const &resolver() const { return _resolver; } 4038 4039 private: 4040 TraceResolver _resolver; 4041 SnippetFactory _snippets; 4042 4043 template <typename ST> 4044 void print_stacktrace(ST &st, std::ostream &os, Colorize &colorize) { 4045 print_header(os, st.thread_id()); 4046 _resolver.load_stacktrace(st); 4047 if ( reverse ) { 4048 for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { 4049 print_trace(os, _resolver.resolve(st[trace_idx - 1]), colorize); 4050 } 4051 } else { 4052 for (size_t trace_idx = 0; trace_idx < st.size(); ++trace_idx) { 4053 print_trace(os, _resolver.resolve(st[trace_idx]), colorize); 4054 } 4055 } 4056 } 4057 4058 template <typename IT> 4059 void print_stacktrace(IT begin, IT end, std::ostream &os, size_t thread_id, 4060 Colorize &colorize) { 4061 print_header(os, thread_id); 4062 for (; begin != end; ++begin) { 4063 print_trace(os, *begin, colorize); 4064 } 4065 } 4066 4067 void print_header(std::ostream &os, size_t thread_id) { 4068 os << "Stack trace (most recent call last)"; 4069 if (thread_id) { 4070 os << " in thread " << thread_id; 4071 } 4072 os << ":\n"; 4073 } 4074 4075 void print_trace(std::ostream &os, const ResolvedTrace &trace, 4076 Colorize &colorize) { 4077 os << "#" << std::left << std::setw(2) << trace.idx << std::right; 4078 bool already_indented = true; 4079 4080 if (!trace.source.filename.size() || object) { 4081 os << " Object \"" << trace.object_filename << "\", at " << trace.addr 4082 << ", in " << trace.object_function << "\n"; 4083 already_indented = false; 4084 } 4085 4086 for (size_t inliner_idx = trace.inliners.size(); inliner_idx > 0; 4087 --inliner_idx) { 4088 if (!already_indented) { 4089 os << " "; 4090 } 4091 const ResolvedTrace::SourceLoc &inliner_loc = 4092 trace.inliners[inliner_idx - 1]; 4093 print_source_loc(os, " | ", inliner_loc); 4094 if (snippet) { 4095 print_snippet(os, " | ", inliner_loc, colorize, Color::purple, 4096 inliner_context_size); 4097 } 4098 already_indented = false; 4099 } 4100 4101 if (trace.source.filename.size()) { 4102 if (!already_indented) { 4103 os << " "; 4104 } 4105 print_source_loc(os, " ", trace.source, trace.addr); 4106 if (snippet) { 4107 print_snippet(os, " ", trace.source, colorize, Color::yellow, 4108 trace_context_size); 4109 } 4110 } 4111 } 4112 4113 void print_snippet(std::ostream &os, const char *indent, 4114 const ResolvedTrace::SourceLoc &source_loc, 4115 Colorize &colorize, Color::type color_code, 4116 int context_size) { 4117 using namespace std; 4118 typedef SnippetFactory::lines_t lines_t; 4119 4120 lines_t lines = _snippets.get_snippet(source_loc.filename, source_loc.line, 4121 static_cast<unsigned>(context_size)); 4122 4123 for (lines_t::const_iterator it = lines.begin(); it != lines.end(); ++it) { 4124 if (it->first == source_loc.line) { 4125 colorize.set_color(color_code); 4126 os << indent << ">"; 4127 } else { 4128 os << indent << " "; 4129 } 4130 os << std::setw(4) << it->first << ": " << it->second << "\n"; 4131 if (it->first == source_loc.line) { 4132 colorize.set_color(Color::reset); 4133 } 4134 } 4135 } 4136 4137 void print_source_loc(std::ostream &os, const char *indent, 4138 const ResolvedTrace::SourceLoc &source_loc, 4139 void *addr = nullptr) { 4140 os << indent << "Source \"" << source_loc.filename << "\", line " 4141 << source_loc.line << ", in " << source_loc.function; 4142 4143 if (address && addr != nullptr) { 4144 os << " [" << addr << "]"; 4145 } 4146 os << "\n"; 4147 } 4148 }; 4149 4150 /*************** SIGNALS HANDLING ***************/ 4151 namespace { 4152 std::filesystem::path _dump_path; 4153 } 4154 4155 #if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN) 4156 4157 class SignalHandling { 4158 public: 4159 static std::vector<int> make_default_signals() { 4160 const int posix_signals[] = { 4161 // Signals for which the default action is "Core". 4162 SIGABRT, // Abort signal from abort(3) 4163 SIGBUS, // Bus error (bad memory access) 4164 SIGFPE, // Floating point exception 4165 SIGILL, // Illegal Instruction 4166 SIGIOT, // IOT trap. A synonym for SIGABRT 4167 SIGQUIT, // Quit from keyboard 4168 SIGSEGV, // Invalid memory reference 4169 SIGSYS, // Bad argument to routine (SVr4) 4170 SIGTRAP, // Trace/breakpoint trap 4171 SIGXCPU, // CPU time limit exceeded (4.2BSD) 4172 SIGXFSZ, // File size limit exceeded (4.2BSD) 4173 #if defined(BACKWARD_SYSTEM_DARWIN) 4174 SIGEMT, // emulation instruction executed 4175 #endif 4176 }; 4177 return std::vector<int>(posix_signals, 4178 posix_signals + 4179 sizeof posix_signals / sizeof posix_signals[0]); 4180 } 4181 4182 SignalHandling(const std::vector<int> &posix_signals = make_default_signals(), 4183 std::filesystem::path dump_path = {}) 4184 : _loaded(false) { 4185 _dump_path = dump_path; 4186 bool success = true; 4187 4188 const size_t stack_size = 1024 * 1024 * 8; 4189 _stack_content.reset(static_cast<char *>(malloc(stack_size))); 4190 if (_stack_content) { 4191 stack_t ss; 4192 ss.ss_sp = _stack_content.get(); 4193 ss.ss_size = stack_size; 4194 ss.ss_flags = 0; 4195 if (sigaltstack(&ss, nullptr) < 0) { 4196 success = false; 4197 } 4198 } else { 4199 success = false; 4200 } 4201 4202 for (size_t i = 0; i < posix_signals.size(); ++i) { 4203 struct sigaction action; 4204 memset(&action, 0, sizeof action); 4205 action.sa_flags = 4206 static_cast<int>(SA_SIGINFO | SA_ONSTACK | SA_NODEFER | SA_RESETHAND); 4207 sigfillset(&action.sa_mask); 4208 sigdelset(&action.sa_mask, posix_signals[i]); 4209 #if defined(__clang__) 4210 #pragma clang diagnostic push 4211 #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" 4212 #endif 4213 action.sa_sigaction = &sig_handler; 4214 #if defined(__clang__) 4215 #pragma clang diagnostic pop 4216 #endif 4217 4218 int r = sigaction(posix_signals[i], &action, nullptr); 4219 if (r < 0) 4220 success = false; 4221 } 4222 4223 _loaded = success; 4224 } 4225 4226 bool loaded() const { return _loaded; } 4227 4228 static void handleSignal(int, siginfo_t *info, void *_ctx) { 4229 ucontext_t *uctx = static_cast<ucontext_t *>(_ctx); 4230 4231 StackTrace st; 4232 void *error_addr = nullptr; 4233 #ifdef REG_RIP // x86_64 4234 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.gregs[REG_RIP]); 4235 #elif defined(REG_EIP) // x86_32 4236 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.gregs[REG_EIP]); 4237 #elif defined(__arm__) 4238 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.arm_pc); 4239 #elif defined(__aarch64__) 4240 #if defined(__APPLE__) 4241 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext->__ss.__pc); 4242 #else 4243 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.pc); 4244 #endif 4245 #elif defined(__mips__) 4246 error_addr = reinterpret_cast<void *>( 4247 reinterpret_cast<struct sigcontext *>(&uctx->uc_mcontext)->sc_pc); 4248 #elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \ 4249 defined(__POWERPC__) 4250 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.regs->nip); 4251 #elif defined(__riscv) 4252 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.__gregs[REG_PC]); 4253 #elif defined(__s390x__) 4254 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.psw.addr); 4255 #elif defined(__APPLE__) && defined(__x86_64__) 4256 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext->__ss.__rip); 4257 #elif defined(__APPLE__) 4258 error_addr = reinterpret_cast<void *>(uctx->uc_mcontext->__ss.__eip); 4259 #else 4260 #warning ":/ sorry, ain't know no nothing none not of your architecture!" 4261 #endif 4262 if (error_addr) { 4263 st.load_from(error_addr, 32, reinterpret_cast<void *>(uctx), 4264 info->si_addr); 4265 } else { 4266 st.load_here(32, reinterpret_cast<void *>(uctx), info->si_addr); 4267 } 4268 4269 Printer printer; 4270 printer.address = true; 4271 4272 if (!_dump_path.empty()) { 4273 std::ofstream error_stream; 4274 error_stream.open(_dump_path); 4275 printer.print(st, error_stream); 4276 error_stream.close(); 4277 } else { 4278 printer.print(st, stderr); 4279 } 4280 4281 #if (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || \ 4282 (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) 4283 psiginfo(info, nullptr); 4284 #else 4285 (void)info; 4286 #endif 4287 } 4288 4289 private: 4290 details::handle<char *> _stack_content; 4291 bool _loaded; 4292 4293 #ifdef __GNUC__ 4294 __attribute__((noreturn)) 4295 #endif 4296 static void 4297 sig_handler(int signo, siginfo_t *info, void *_ctx) { 4298 handleSignal(signo, info, _ctx); 4299 4300 // try to forward the signal. 4301 raise(info->si_signo); 4302 4303 // terminate the process immediately. 4304 puts("watf? exit"); 4305 _exit(EXIT_FAILURE); 4306 } 4307 }; 4308 4309 #endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN 4310 4311 #ifdef BACKWARD_SYSTEM_WINDOWS 4312 4313 class SignalHandling { 4314 public: 4315 static std::vector<int> make_default_signals() { return {}; } 4316 4317 SignalHandling(const std::vector<int> & = std::vector<int>(), 4318 std::filesystem::path dump_path = {}) 4319 : reporter_thread_([]() { 4320 /* We handle crashes in a utility thread: 4321 backward structures and some Windows functions called here 4322 need stack space, which we do not have when we encounter a 4323 stack overflow. 4324 To support reporting stack traces during a stack overflow, 4325 we create a utility thread at startup, which waits until a 4326 crash happens or the program exits normally. */ 4327 4328 { 4329 std::unique_lock<std::mutex> lk(mtx()); 4330 cv().wait(lk, [] { return crashed() != crash_status::running; }); 4331 } 4332 if (crashed() == crash_status::crashed) { 4333 handle_stacktrace(skip_recs()); 4334 } 4335 { 4336 std::unique_lock<std::mutex> lk(mtx()); 4337 crashed() = crash_status::ending; 4338 } 4339 cv().notify_one(); 4340 }) { 4341 _dump_path = dump_path; 4342 SetUnhandledExceptionFilter(crash_handler); 4343 4344 signal(SIGABRT, signal_handler); 4345 _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); 4346 4347 std::set_terminate(&terminator); 4348 #ifndef BACKWARD_ATLEAST_CXX17 4349 std::set_unexpected(&terminator); 4350 #endif 4351 _set_purecall_handler(&terminator); 4352 _set_invalid_parameter_handler(&invalid_parameter_handler); 4353 } 4354 bool loaded() const { return true; } 4355 4356 ~SignalHandling() { 4357 { 4358 std::unique_lock<std::mutex> lk(mtx()); 4359 crashed() = crash_status::normal_exit; 4360 } 4361 4362 cv().notify_one(); 4363 4364 reporter_thread_.join(); 4365 } 4366 4367 private: 4368 static CONTEXT *ctx() { 4369 static CONTEXT data; 4370 return &data; 4371 } 4372 4373 enum class crash_status { running, crashed, normal_exit, ending }; 4374 4375 static crash_status &crashed() { 4376 static crash_status data; 4377 return data; 4378 } 4379 4380 static std::mutex &mtx() { 4381 static std::mutex data; 4382 return data; 4383 } 4384 4385 static std::condition_variable &cv() { 4386 static std::condition_variable data; 4387 return data; 4388 } 4389 4390 static HANDLE &thread_handle() { 4391 static HANDLE handle; 4392 return handle; 4393 } 4394 4395 std::thread reporter_thread_; 4396 4397 // TODO: how not to hardcode these? 4398 static const constexpr int signal_skip_recs = 4399 #ifdef __clang__ 4400 // With clang, RtlCaptureContext also captures the stack frame of the 4401 // current function Below that, there are 3 internal Windows functions 4402 4 4403 #else 4404 // With MSVC cl, RtlCaptureContext misses the stack frame of the current 4405 // function The first entries during StackWalk are the 3 internal Windows 4406 // functions 4407 3 4408 #endif 4409 ; 4410 4411 static int &skip_recs() { 4412 static int data; 4413 return data; 4414 } 4415 4416 static inline void terminator() { 4417 crash_handler(signal_skip_recs); 4418 abort(); 4419 } 4420 4421 static inline void signal_handler(int) { 4422 crash_handler(signal_skip_recs); 4423 abort(); 4424 } 4425 4426 static inline void __cdecl invalid_parameter_handler(const wchar_t *, 4427 const wchar_t *, 4428 const wchar_t *, 4429 unsigned int, 4430 uintptr_t) { 4431 crash_handler(signal_skip_recs); 4432 abort(); 4433 } 4434 4435 NOINLINE static LONG WINAPI crash_handler(EXCEPTION_POINTERS *info) { 4436 // The exception info supplies a trace from exactly where the issue was, 4437 // no need to skip records 4438 crash_handler(0, info->ContextRecord); 4439 return EXCEPTION_CONTINUE_SEARCH; 4440 } 4441 4442 NOINLINE static void crash_handler(int skip, CONTEXT *ct = nullptr) { 4443 4444 if (ct == nullptr) { 4445 RtlCaptureContext(ctx()); 4446 } else { 4447 memcpy(ctx(), ct, sizeof(CONTEXT)); 4448 } 4449 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), 4450 GetCurrentProcess(), &thread_handle(), 0, FALSE, 4451 DUPLICATE_SAME_ACCESS); 4452 4453 skip_recs() = skip; 4454 4455 { 4456 std::unique_lock<std::mutex> lk(mtx()); 4457 crashed() = crash_status::crashed; 4458 } 4459 4460 cv().notify_one(); 4461 4462 { 4463 std::unique_lock<std::mutex> lk(mtx()); 4464 cv().wait(lk, [] { return crashed() != crash_status::crashed; }); 4465 } 4466 } 4467 4468 static void handle_stacktrace(int skip_frames = 0) { 4469 // printer creates the TraceResolver, which can supply us a machine type 4470 // for stack walking. Without this, StackTrace can only guess using some 4471 // macros. 4472 // StackTrace also requires that the PDBs are already loaded, which is done 4473 // in the constructor of TraceResolver 4474 Printer printer; 4475 4476 StackTrace st; 4477 st.set_machine_type(printer.resolver().machine_type()); 4478 st.set_thread_handle(thread_handle()); 4479 st.load_here(32 + skip_frames, ctx()); 4480 st.skip_n_firsts(skip_frames); 4481 4482 printer.address = true; 4483 4484 if (!_dump_path.empty()) { 4485 std::ofstream error_stream; 4486 error_stream.open(_dump_path); 4487 printer.print(st, error_stream); 4488 error_stream.close(); 4489 } else { 4490 printer.print(st, stderr); 4491 } 4492 4493 } 4494 }; 4495 4496 #endif // BACKWARD_SYSTEM_WINDOWS 4497 4498 #ifdef BACKWARD_SYSTEM_UNKNOWN 4499 4500 class SignalHandling { 4501 public: 4502 SignalHandling(const std::vector<int> & = std::vector<int>(), const 4503 std::filesystem::path & = {}) {} 4504 bool init() { return false; } 4505 bool loaded() { return false; } 4506 }; 4507 4508 #endif // BACKWARD_SYSTEM_UNKNOWN 4509 4510 } // namespace backward 4511 4512 #endif /* H_GUARD */