$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_06_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "TRACE/trace.h" 00002 #define TRACE_NAME "ExceptionStackTrace" 00003 00004 #include <cxxabi.h> 00005 #include <dlfcn.h> 00006 #include <execinfo.h> 00007 #include <libgen.h> 00008 #include <iostream> 00009 #include <regex> 00010 #include <sstream> 00011 00012 #include "ExceptionStackTrace.hh" 00013 00014 namespace artdaq::debug { 00015 #define SKIP_HEAD 2 00016 #define SKIP_TAIL 3 00017 00018 StackTraceCollector& getStackTraceCollector() 00019 { 00020 static StackTraceCollector collector = StackTraceCollector(); 00021 return collector; 00022 } 00023 00024 std::string StackTrace::demangle(std::string const& symbol) 00025 { 00026 int status; 00027 std::unique_ptr<char, void (*)(void*)> demangled_symbol(abi::__cxa_demangle(symbol.c_str(), nullptr, nullptr, &status), &std::free); 00028 return status != 0 ? symbol : &*demangled_symbol; 00029 } 00030 00031 std::string Trace::print() const 00032 { 00033 std::ostringstream os; 00034 os << '#' << index_ << " " 00035 // << ' ' << std::setw(16) << address_ << " in " 00036 << filename_ << " : " << function_ << " + " 00037 << "0x" << std::hex << offset_; 00038 return os.str(); 00039 } 00040 00041 void Trace::resolve() 00042 { 00043 auto m = std::smatch(); 00044 00045 if (std::regex_search(symbol_, m, std::regex{"(\\S*)\\((|\\S+)\\)\\s\\[(0x\\S+)\\]"}) && m.size() == 4) 00046 { 00047 filename_ = m[1]; 00048 function_ = m[2]; 00049 address_ = static_cast<uintptr_t>(stoull(m[3], 0, 16)); 00050 if (std::regex_search(function_, m, std::regex{"(\\S+)\\+(\\S+)"}) && m.size() == 3) 00051 { 00052 std::string offstr = m[2]; 00053 function_ = StackTrace::demangle(m[1]); 00054 offset_ = static_cast<uintptr_t>(stoull(offstr, 0, 16)); 00055 } 00056 } 00057 else //slow parse 00058 { 00059 if (std::regex_search(symbol_, m, std::regex{"(.*)\\("}) && m.size() == 2) 00060 filename_ = m[1]; 00061 00062 if (std::regex_search(symbol_, m, std::regex{"[(](.*)[+]"}) && m.size() == 2) 00063 function_ = StackTrace::demangle(m[1]); 00064 00065 if (std::regex_search(symbol_, m, std::regex{"[+](0x\\S+)\\)"}) && m.size() == 2) 00066 offset_ = static_cast<uintptr_t>(stoull(m[1], 0, 16)); 00067 00068 if (std::regex_search(symbol_, m, std::regex{"\\[(0x\\S+)\\]"}) && m.size() == 2) 00069 address_ = static_cast<uintptr_t>(stoull(m[1], 0, 16)); 00070 } 00071 } 00072 00073 StackTrace::StackTrace(std::string type_name) 00074 : type_name_{std::move(type_name)}, traces_uptr_{nullptr}, size_{::backtrace(frames_, sizeof frames_ / sizeof(void*))} 00075 { 00076 } 00077 00078 void StackTrace::resolve() 00079 { 00080 traces_uptr_ = std::make_unique<traces_t>(); 00081 00082 if (0 == size_) 00083 return; 00084 00085 traces_uptr_->reserve(size_); 00086 00087 char** symbols = ::backtrace_symbols(frames_, size_); 00088 00089 for (auto i = SKIP_HEAD; i < size_ - SKIP_TAIL; i++) 00090 traces_uptr_->emplace_back(size_ - SKIP_TAIL - i, symbols[size_ - i - 1]); 00091 00092 free(symbols); 00093 00094 for (auto& trace : *traces_uptr_) 00095 trace.resolve(); 00096 } 00097 00098 std::string StackTrace::print() const 00099 { 00100 if (!traces_uptr_) 00101 return "Error: Unresolved StackTrace, call resolve() first."; 00102 00103 if (0 == size_) 00104 { 00105 std::cout << "Error: possibly corrupt stack."; 00106 } 00107 std::ostringstream os; 00108 os << "Caught a \"" << StackTrace::demangle(type_name_) << "\" exception.\n"; 00109 00110 os << "Stack Trace: \n"; 00111 00112 for (auto const& trace : *traces_uptr_) 00113 os << trace << "\n"; 00114 00115 return os.str(); 00116 } 00117 00118 } // namespace artdaq::debug 00119 00120 extern "C" { 00121 #ifndef __clang__ 00122 void __cxa_throw(void* ex, void* info, void (*dest)(void*)) 00123 { 00124 artdaq::debug::getStackTraceCollector().collect_stacktrace(static_cast<std::type_info*>(info)->name()); 00125 00126 __cxa_throw_t* rethrow __attribute__((noreturn)) = (__cxa_throw_t*)dlsym(RTLD_NEXT, "__cxa_throw"); 00127 00128 rethrow(ex, info, dest); 00129 } 00130 #else 00131 __attribute__((noreturn)) void __cxa_throw(void* ex, std::type_info* info, void (*dest)(void*)) 00132 { 00133 artdaq::debug::getStackTraceCollector().collect_stacktrace(info->name()); 00134 00135 auto* rethrow = (__cxa_throw_t*)dlsym(RTLD_NEXT, "__cxa_throw"); 00136 00137 rethrow(ex, info, dest); 00138 } 00139 #endif 00140 }