1 /* $Id: ncbi_stack_libbackward.cpp 567764 2018-07-24 12:05:33Z ivanov $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Anton Perkov
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31 #include <ncbiconf.h>
32
33 #if defined(HAVE_LIBDW)
34 # define BACKWARD_HAS_DW 1
35 #elif defined(HAVE_LIBUNWIND)
36 # define BACKWARD_HAS_UNWIND 1
37 #endif
38
39 #include <backward.hpp>
40 #if defined(HAVE_CXA_DEMANGLE)
41 # include <cxxabi.h>
42 #endif
43 #include <stdio.h>
44
45 BEGIN_NCBI_SCOPE
46
47 #define CAN_HONOR_SIGNAL_HANDLING_CONFIGURATION 1
48
49 #if defined(USE_LIBBACKWARD_SIG_HANDLING)
50 # define TRACE_SIGNALS_BY_DEFAULT true
51 #else
52 # define TRACE_SIGNALS_BY_DEFAULT false
53 #endif
54
55 NCBI_PARAM_DECL(bool, Debug, Trace_Fatal_Signals);
56 NCBI_PARAM_DEF_EX(bool, Debug, Trace_Fatal_Signals, TRACE_SIGNALS_BY_DEFAULT,
57 0, DEBUG_TRACE_FATAL_SIGNALS);
58 typedef NCBI_PARAM_TYPE(Debug, Trace_Fatal_Signals) TTraceFatalSignals;
59
60 unique_ptr<backward::SignalHandling> s_SignalHandler;
61
62
63 // Call this function to get a backtrace.
64 class CStackTraceImpl
65 {
66 public:
67 CStackTraceImpl(void);
68 ~CStackTraceImpl(void);
69
70 void Expand(CStackTrace::TStack& stack);
71 static void s_HonorSignalHandlingConfiguration(void);
72
73 private:
74 typedef backward::StackTrace TStack;
75
76 TStack m_Stack;
77 };
78
79
CStackTraceImpl(void)80 CStackTraceImpl::CStackTraceImpl(void)
81 {
82 m_Stack.load_here();
83 }
84
85
~CStackTraceImpl(void)86 CStackTraceImpl::~CStackTraceImpl(void)
87 {
88 }
89
90
Expand(CStackTrace::TStack & stack)91 void CStackTraceImpl::Expand(CStackTrace::TStack& stack)
92 {
93 backward::TraceResolver resolver;
94 resolver.load_stacktrace(m_Stack);
95 for (size_t trace_idx = 0; trace_idx < m_Stack.size(); ++trace_idx) {
96 CStackTrace::SStackFrameInfo info;
97 const backward::ResolvedTrace& trace
98 = resolver.resolve(m_Stack[trace_idx]);
99 info.module = trace.object_filename;
100 info.addr = trace.addr;
101
102 if (!trace.source.filename.size()) {
103 /*os << " Object \""
104 << trace.object_filename
105 << ", at "
106 << trace.addr
107 << ", in "
108 << trace.object_function
109 << "\n";*/
110 }
111
112 for (size_t inliner_idx = 0; inliner_idx < trace.inliners.size(); ++inliner_idx) {
113 const backward::ResolvedTrace::SourceLoc& inliner_loc = trace.inliners[inliner_idx];
114 CStackTrace::SStackFrameInfo info2;
115 info2.file = inliner_loc.filename;
116 info2.line = inliner_loc.line;
117 info2.func = inliner_loc.function;
118 stack.push_back(move(info2));
119 }
120
121 if (trace.source.filename.size()) {
122 info.file = trace.source.filename;
123 info.line = trace.source.line;
124 //info.func = trace.source.function;
125 info.func = trace.object_function;
126 info.addr = trace.addr;
127 }
128 stack.push_back(move(info));
129 }
130 }
131
s_HonorSignalHandlingConfiguration(void)132 void CStackTraceImpl::s_HonorSignalHandlingConfiguration(void)
133 {
134 if (TTraceFatalSignals::GetDefault()) {
135 s_SignalHandler.reset(new backward::SignalHandling);
136 }
137 }
138
139 END_NCBI_SCOPE
140