1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31
32 // language.cc: Subclasses and singletons for google_breakpad::Language.
33 // See language.h for details.
34
35 #include "common/language.h"
36
37 #include <stdlib.h>
38
39 #if !defined(__ANDROID__)
40 #include <cxxabi.h>
41 #endif
42
43 #if defined(HAVE_RUST_DEMANGLE)
44 #include <rust_demangle.h>
45 #endif
46
47 #include <limits>
48
49 namespace {
50
MakeQualifiedNameWithSeparator(const string & parent_name,const char * separator,const string & name)51 string MakeQualifiedNameWithSeparator(const string& parent_name,
52 const char* separator,
53 const string& name) {
54 if (parent_name.empty()) {
55 return name;
56 }
57
58 return parent_name + separator + name;
59 }
60
61 } // namespace
62
63 namespace google_breakpad {
64
65 // C++ language-specific operations.
66 class CPPLanguage: public Language {
67 public:
CPPLanguage()68 CPPLanguage() {}
69
MakeQualifiedName(const string & parent_name,const string & name) const70 string MakeQualifiedName(const string &parent_name,
71 const string &name) const {
72 return MakeQualifiedNameWithSeparator(parent_name, "::", name);
73 }
74
DemangleName(const string & mangled,string * demangled) const75 virtual DemangleResult DemangleName(const string& mangled,
76 string* demangled) const {
77 #if defined(__ANDROID__)
78 // Android NDK doesn't provide abi::__cxa_demangle.
79 demangled->clear();
80 return kDontDemangle;
81 #else
82 int status;
83 char* demangled_c =
84 abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
85
86 DemangleResult result;
87 if (status == 0) {
88 result = kDemangleSuccess;
89 demangled->assign(demangled_c);
90 } else {
91 result = kDemangleFailure;
92 demangled->clear();
93 }
94
95 if (demangled_c) {
96 free(reinterpret_cast<void*>(demangled_c));
97 }
98
99 return result;
100 #endif
101 }
102 };
103
104 CPPLanguage CPPLanguageSingleton;
105
106 // Java language-specific operations.
107 class JavaLanguage: public Language {
108 public:
JavaLanguage()109 JavaLanguage() {}
110
MakeQualifiedName(const string & parent_name,const string & name) const111 string MakeQualifiedName(const string &parent_name,
112 const string &name) const {
113 return MakeQualifiedNameWithSeparator(parent_name, ".", name);
114 }
115 };
116
117 JavaLanguage JavaLanguageSingleton;
118
119 // Swift language-specific operations.
120 class SwiftLanguage: public Language {
121 public:
SwiftLanguage()122 SwiftLanguage() {}
123
MakeQualifiedName(const string & parent_name,const string & name) const124 string MakeQualifiedName(const string &parent_name,
125 const string &name) const {
126 return MakeQualifiedNameWithSeparator(parent_name, ".", name);
127 }
128
DemangleName(const string & mangled,string * demangled) const129 virtual DemangleResult DemangleName(const string& mangled,
130 string* demangled) const {
131 // There is no programmatic interface to a Swift demangler. Pass through the
132 // mangled form because it encodes more information than the qualified name
133 // that would have been built by MakeQualifiedName(). The output can be
134 // post-processed by xcrun swift-demangle to transform mangled Swift names
135 // into something more readable.
136 demangled->assign(mangled);
137 return kDemangleSuccess;
138 }
139 };
140
141 SwiftLanguage SwiftLanguageSingleton;
142
143 // Rust language-specific operations.
144 class RustLanguage: public Language {
145 public:
RustLanguage()146 RustLanguage() {}
147
MakeQualifiedName(const string & parent_name,const string & name) const148 string MakeQualifiedName(const string &parent_name,
149 const string &name) const {
150 return MakeQualifiedNameWithSeparator(parent_name, ".", name);
151 }
152
DemangleName(const string & mangled,string * demangled) const153 virtual DemangleResult DemangleName(const string& mangled,
154 string* demangled) const {
155 // Rust names use GCC C++ name mangling, but demangling them with
156 // abi_demangle doesn't produce stellar results due to them having
157 // another layer of encoding.
158 // If callers provide rustc-demangle, use that.
159 #if defined(HAVE_RUST_DEMANGLE)
160 char* rust_demangled = rust_demangle(mangled.c_str());
161 if (rust_demangled == nullptr) {
162 return kDemangleFailure;
163 }
164 demangled->assign(rust_demangled);
165 free_rust_demangled_name(rust_demangled);
166 #else
167 // Otherwise, pass through the mangled name so callers can demangle
168 // after the fact.
169 demangled->assign(mangled);
170 #endif
171 return kDemangleSuccess;
172 }
173 };
174
175 RustLanguage RustLanguageSingleton;
176
177 // Assembler language-specific operations.
178 class AssemblerLanguage: public Language {
179 public:
AssemblerLanguage()180 AssemblerLanguage() {}
181
HasFunctions() const182 bool HasFunctions() const { return false; }
MakeQualifiedName(const string & parent_name,const string & name) const183 string MakeQualifiedName(const string &parent_name,
184 const string &name) const {
185 return name;
186 }
187 };
188
189 AssemblerLanguage AssemblerLanguageSingleton;
190
191 const Language * const Language::CPlusPlus = &CPPLanguageSingleton;
192 const Language * const Language::Java = &JavaLanguageSingleton;
193 const Language * const Language::Swift = &SwiftLanguageSingleton;
194 const Language * const Language::Rust = &RustLanguageSingleton;
195 const Language * const Language::Assembler = &AssemblerLanguageSingleton;
196
197 } // namespace google_breakpad
198