source: XIOS3/trunk/extern/cpptrace/src/symbols_with_libbacktrace.cpp @ 2573

Last change on this file since 2573 was 2573, checked in by ymipsl, 9 months ago

create new external source lib : cpptrace, for statck trace output
YM

File size: 3.4 KB
Line 
1#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
2
3#include "cpptrace.hpp"
4#include "symbols.hpp"
5#include "program_name.hpp"
6
7#include <cstdint>
8#include <cstdio>
9#include <memory>
10#include <mutex>
11#include <vector>
12
13#ifdef CPPTRACE_BACKTRACE_PATH
14#include CPPTRACE_BACKTRACE_PATH
15#else
16#include <backtrace.h>
17#endif
18
19namespace cpptrace {
20    namespace detail {
21        namespace libbacktrace {
22            int full_callback(void* data, uintptr_t address, const char* file, int line, const char* symbol) {
23                stacktrace_frame& frame = *static_cast<stacktrace_frame*>(data);
24                if(line == 0) {
25                    ///fprintf(stderr, "Getting bad data for some reason\n"); // TODO: Eliminate
26                }
27                frame.address = address;
28                frame.line = line;
29                frame.filename = file ? file : "";
30                frame.symbol = symbol ? symbol : "";
31                return 0;
32            }
33
34            void syminfo_callback(void* data, uintptr_t address, const char* symbol, uintptr_t, uintptr_t) {
35                stacktrace_frame& frame = *static_cast<stacktrace_frame*>(data);
36                frame.address = address;
37                frame.line = 0;
38                frame.filename = "";
39                frame.symbol = symbol ? symbol : "";
40            }
41
42            void error_callback(void*, const char* msg, int errnum) {
43                fprintf(stderr, "Libbacktrace error: %s, code %d\n", msg, errnum);
44            }
45
46            backtrace_state* get_backtrace_state() {
47                static std::mutex mutex;
48                const std::lock_guard<std::mutex> lock(mutex);
49                // backtrace_create_state must be called only one time per program
50                // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
51                static backtrace_state* state = nullptr;
52                static bool called = false;
53                if(!called) {
54                    state = backtrace_create_state(program_name(), true, error_callback, nullptr);
55                    called = true;
56                }
57                return state;
58            }
59
60            // TODO: Handle backtrace_pcinfo calling the callback multiple times on inlined functions
61            stacktrace_frame resolve_frame(const void* addr) {
62                stacktrace_frame frame;
63                frame.col = 0;
64                backtrace_pcinfo(
65                    get_backtrace_state(),
66                    reinterpret_cast<uintptr_t>(addr),
67                    full_callback,
68                    error_callback,
69                    &frame
70                );
71                if(frame.symbol.empty()) {
72                    // fallback, try to at least recover the symbol name with backtrace_syminfo
73                    backtrace_syminfo(
74                        get_backtrace_state(),
75                        reinterpret_cast<uintptr_t>(addr),
76                        syminfo_callback,
77                        error_callback,
78                        &frame
79                    );
80                }
81                return frame;
82            }
83
84            std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
85                std::vector<stacktrace_frame> trace;
86                trace.reserve(frames.size());
87                for(const void* frame : frames) {
88                    trace.push_back(resolve_frame(frame));
89                }
90                return trace;
91            }
92        }
93    }
94}
95
96#endif
Note: See TracBrowser for help on using the repository browser.