Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:12:06

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 
0006 #pragma once
0007 
0008 #include <ostream>
0009 #include <string>
0010 #include <execinfo.h>
0011 #include <cxxabi.h>
0012 #include <dlfcn.h>
0013 #include <cstring>
0014 
0015 
0016 inline std::ostream& make_backtrace(std::ostream& os) {
0017 
0018     try {
0019         // Generate stack trace.
0020         const int max_frames = 100;
0021         void* backtrace_buffer[max_frames];
0022         int frame_count = backtrace(backtrace_buffer, max_frames);
0023         char** symbols = backtrace_symbols(backtrace_buffer, frame_count);
0024         // Skip the first two frames, because those are "make_backtrace" and "JException::JException"
0025         for (int i=2; i<frame_count; ++i) {
0026 
0027             std::string name;
0028 
0029             // We are going to get the symbol names from dl, so that we can demangle them
0030             Dl_info dlinfo;
0031             if (dladdr(backtrace_buffer[i], &dlinfo)) { // dladdr succeeded
0032                 if (dlinfo.dli_sname) { // dladdr found a corresponding symbol
0033 
0034                     int demangle_status = 0;
0035                     auto demangled_name = abi::__cxa_demangle(dlinfo.dli_sname, nullptr, nullptr, &demangle_status);
0036 
0037                     if (demangle_status == 0) { // Demangle succeeded, we have a symbol name!
0038                         name = std::string(demangled_name);
0039                     }
0040                     else { // Demangle failed, so we use mangled version
0041                         name = std::string(dlinfo.dli_sname);
0042                     }
0043                     free(demangled_name);
0044                 }
0045                 else { // Otherwise use the shared object name
0046                     name = std::string(dlinfo.dli_fname);
0047                 }
0048             }
0049             else { // dladdr failed for some reason, so we fall back on backtrace_symbols
0050                 name = symbols[i];
0051             }
0052 
0053             // Ignore frames where the name seems un-useful, particularly on macOS
0054             //if( name.find("?") != string::npos ) continue;
0055             //if( name == "0x0") continue;
0056             //if( name == "_sigtramp" ) continue;
0057             //if( name == "_pthread_body" ) continue;
0058             //if( name == "thread_start" ) continue;
0059 
0060             os << std::string(i+5, ' ') + "`- " << name << " (" << std::hex << backtrace_buffer[i] << std::dec << ")" << std::endl;
0061         }
0062         
0063         free(symbols);
0064     }
0065     catch (...) {
0066         // If this fails (e.g. bad alloc), just keep going
0067     }
0068     return os;
0069 }
0070