7a02bbdecc1ff422209ae6b3763bb9f583d92e93
[iec.git] / src / type3_AndroidCloud / anbox-master / external / process-cpp-minimal / src / core / posix / backtrace.cpp
1 /*
2  * Copyright © 2014 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 3,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Thomas Voß <thomas.voss@canonical.com>
17  */
18
19 #include "backtrace.h"
20
21 #include <cxxabi.h>
22
23 #include <execinfo.h>
24
25 namespace bt = core::posix::backtrace;
26
27 namespace impl
28 {
29 std::tuple<std::string, bool> demangle(const std::string& symbol)
30 {
31     int status = 1;
32     auto result = abi::__cxa_demangle(symbol.c_str(),
33                                       nullptr,
34                                       nullptr,
35                                       &status);
36
37     if (!result || status != 0)
38     {
39         return std::make_tuple(std::string(), false);
40     }
41
42     std::string s{result};
43     ::free(result);
44
45     return std::make_tuple(s, true);
46 }
47
48 struct Frame : public bt::Frame
49 {
50     struct Symbol : public bt::Frame::Symbol
51     {
52         Symbol(const char* symbol) : raw_(symbol)
53         {
54             auto first = raw_.find_first_of("(");
55             auto last = raw_.find_last_of(")");
56
57             if (first != std::string::npos && last != std::string::npos)
58             {
59                 auto mangled_symbol = raw_.substr(first+1,
60                                                   (last-1) - (first+1));
61
62                 auto plus = mangled_symbol.find_first_of("+");
63                 if (plus != std::string::npos)
64                     mangled_symbol.erase(plus);
65
66                 std::tie(demangled_, is_cxx_) = demangle(mangled_symbol);
67                 if (!is_cxx_)
68                     demangled_ = raw_;
69             }
70         }
71
72         bool is_cxx() const
73         {
74             return is_cxx_;
75         }
76
77         std::string demangled() const
78         {
79             return demangled_;
80         }
81
82         std::string raw() const
83         {
84             return raw_;
85         }
86
87         std::string raw_;
88         std::string demangled_;
89         bool is_cxx_ = false;
90     };
91
92     std::size_t depth_;
93     void* frame_pointer_;
94     Symbol symbol_;
95
96     Frame(std::size_t depth, void* frame_pointer, const char* symbol)
97         : depth_(depth),
98           frame_pointer_(frame_pointer),
99           symbol_(symbol)
100     {
101     }
102
103     std::size_t depth() const
104     {
105         return depth_;
106     }
107
108     virtual void* frame_pointer() const
109     {
110         return frame_pointer_;
111     }
112
113     const Symbol& symbol() const
114     {
115         return symbol_;
116     }
117 };
118 }
119
120 std::shared_ptr<bt::Frame::Symbol> bt::Frame::Symbol::for_testing_from_raw_symbol(const char* symbol)
121 {
122     return std::shared_ptr<bt::Frame::Symbol>(new impl::Frame::Symbol(symbol));
123 }
124
125 void bt::visit_with_handler(const bt::FrameHandler& handler)
126 {
127     static const unsigned int max_frames=64;
128     void *frames[max_frames];
129
130     auto frame_count = ::backtrace(frames, max_frames);
131     auto symbols = ::backtrace_symbols(frames, frame_count);
132
133     struct Scope
134     {
135         Scope(char** symbols) : symbols(symbols)
136         {
137         }
138
139         ~Scope()
140         {
141             ::free(symbols);
142         }
143
144         char** symbols = nullptr;
145     } scope{symbols};
146
147     for (int i = 0; i < frame_count; i++)
148     {
149         impl::Frame frame(i, frames[i], symbols[i]);
150         if (!handler(frame))
151             return;
152     }
153 }