1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle // Original author: Jim Blandy <[email protected]> <[email protected]>
30*9712c20fSFrederick Mayle
31*9712c20fSFrederick Mayle // language.cc: Subclasses and singletons for google_breakpad::Language.
32*9712c20fSFrederick Mayle // See language.h for details.
33*9712c20fSFrederick Mayle
34*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
35*9712c20fSFrederick Mayle #include <config.h> // Must come first
36*9712c20fSFrederick Mayle #endif
37*9712c20fSFrederick Mayle
38*9712c20fSFrederick Mayle #include "common/language.h"
39*9712c20fSFrederick Mayle
40*9712c20fSFrederick Mayle #include <stdlib.h>
41*9712c20fSFrederick Mayle #include <array>
42*9712c20fSFrederick Mayle
43*9712c20fSFrederick Mayle #if !defined(__ANDROID__)
44*9712c20fSFrederick Mayle #include <cxxabi.h>
45*9712c20fSFrederick Mayle #endif
46*9712c20fSFrederick Mayle
47*9712c20fSFrederick Mayle #if defined(HAVE_RUSTC_DEMANGLE)
48*9712c20fSFrederick Mayle #include <rustc_demangle.h>
49*9712c20fSFrederick Mayle #endif
50*9712c20fSFrederick Mayle
51*9712c20fSFrederick Mayle #include <limits>
52*9712c20fSFrederick Mayle
53*9712c20fSFrederick Mayle namespace {
54*9712c20fSFrederick Mayle
MakeQualifiedNameWithSeparator(const string & parent_name,const char * separator,const string & name)55*9712c20fSFrederick Mayle string MakeQualifiedNameWithSeparator(const string& parent_name,
56*9712c20fSFrederick Mayle const char* separator,
57*9712c20fSFrederick Mayle const string& name) {
58*9712c20fSFrederick Mayle if (parent_name.empty()) {
59*9712c20fSFrederick Mayle return name;
60*9712c20fSFrederick Mayle }
61*9712c20fSFrederick Mayle
62*9712c20fSFrederick Mayle return parent_name + separator + name;
63*9712c20fSFrederick Mayle }
64*9712c20fSFrederick Mayle
65*9712c20fSFrederick Mayle } // namespace
66*9712c20fSFrederick Mayle
67*9712c20fSFrederick Mayle namespace google_breakpad {
68*9712c20fSFrederick Mayle
69*9712c20fSFrederick Mayle // C++ language-specific operations.
70*9712c20fSFrederick Mayle class CPPLanguage: public Language {
71*9712c20fSFrederick Mayle public:
CPPLanguage()72*9712c20fSFrederick Mayle CPPLanguage() {}
73*9712c20fSFrederick Mayle
MakeQualifiedName(const string & parent_name,const string & name) const74*9712c20fSFrederick Mayle string MakeQualifiedName(const string& parent_name,
75*9712c20fSFrederick Mayle const string& name) const {
76*9712c20fSFrederick Mayle return MakeQualifiedNameWithSeparator(parent_name, "::", name);
77*9712c20fSFrederick Mayle }
78*9712c20fSFrederick Mayle
DemangleName(const string & mangled,string * demangled) const79*9712c20fSFrederick Mayle virtual DemangleResult DemangleName(const string& mangled,
80*9712c20fSFrederick Mayle string* demangled) const {
81*9712c20fSFrederick Mayle #if defined(__ANDROID__)
82*9712c20fSFrederick Mayle // Android NDK doesn't provide abi::__cxa_demangle.
83*9712c20fSFrederick Mayle demangled->clear();
84*9712c20fSFrederick Mayle return kDontDemangle;
85*9712c20fSFrederick Mayle #else
86*9712c20fSFrederick Mayle // Attempting to demangle non-C++ symbols with the C++ demangler would print
87*9712c20fSFrederick Mayle // warnings and fail, so return kDontDemangle for these.
88*9712c20fSFrederick Mayle if (!IsMangledName(mangled)) {
89*9712c20fSFrederick Mayle demangled->clear();
90*9712c20fSFrederick Mayle return kDontDemangle;
91*9712c20fSFrederick Mayle }
92*9712c20fSFrederick Mayle
93*9712c20fSFrederick Mayle int status;
94*9712c20fSFrederick Mayle char* demangled_c =
95*9712c20fSFrederick Mayle abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
96*9712c20fSFrederick Mayle
97*9712c20fSFrederick Mayle DemangleResult result;
98*9712c20fSFrederick Mayle if (status == 0) {
99*9712c20fSFrederick Mayle result = kDemangleSuccess;
100*9712c20fSFrederick Mayle demangled->assign(demangled_c);
101*9712c20fSFrederick Mayle } else {
102*9712c20fSFrederick Mayle result = kDemangleFailure;
103*9712c20fSFrederick Mayle demangled->clear();
104*9712c20fSFrederick Mayle }
105*9712c20fSFrederick Mayle
106*9712c20fSFrederick Mayle if (demangled_c) {
107*9712c20fSFrederick Mayle free(reinterpret_cast<void*>(demangled_c));
108*9712c20fSFrederick Mayle }
109*9712c20fSFrederick Mayle
110*9712c20fSFrederick Mayle return result;
111*9712c20fSFrederick Mayle #endif
112*9712c20fSFrederick Mayle }
113*9712c20fSFrederick Mayle
114*9712c20fSFrederick Mayle private:
IsMangledName(const string & name)115*9712c20fSFrederick Mayle static bool IsMangledName(const string& name) {
116*9712c20fSFrederick Mayle // NOTE: For proper cross-compilation support, this should depend on target
117*9712c20fSFrederick Mayle // binary's platform, not current build platform.
118*9712c20fSFrederick Mayle #if defined(__APPLE__)
119*9712c20fSFrederick Mayle // Mac C++ symbols can have up to 4 underscores, followed by a "Z".
120*9712c20fSFrederick Mayle // Non-C++ symbols are not coded that way, but may have leading underscores.
121*9712c20fSFrederick Mayle size_t i = name.find_first_not_of('_');
122*9712c20fSFrederick Mayle return i > 0 && i != string::npos && i <= 4 && name[i] == 'Z';
123*9712c20fSFrederick Mayle #else
124*9712c20fSFrederick Mayle // Linux C++ symbols always start with "_Z".
125*9712c20fSFrederick Mayle return name.size() > 2 && name[0] == '_' && name[1] == 'Z';
126*9712c20fSFrederick Mayle #endif
127*9712c20fSFrederick Mayle }
128*9712c20fSFrederick Mayle };
129*9712c20fSFrederick Mayle
130*9712c20fSFrederick Mayle CPPLanguage CPPLanguageSingleton;
131*9712c20fSFrederick Mayle
132*9712c20fSFrederick Mayle // Java language-specific operations.
133*9712c20fSFrederick Mayle class JavaLanguage: public Language {
134*9712c20fSFrederick Mayle public:
JavaLanguage()135*9712c20fSFrederick Mayle JavaLanguage() {}
136*9712c20fSFrederick Mayle
MakeQualifiedName(const string & parent_name,const string & name) const137*9712c20fSFrederick Mayle string MakeQualifiedName(const string& parent_name,
138*9712c20fSFrederick Mayle const string& name) const {
139*9712c20fSFrederick Mayle return MakeQualifiedNameWithSeparator(parent_name, ".", name);
140*9712c20fSFrederick Mayle }
141*9712c20fSFrederick Mayle };
142*9712c20fSFrederick Mayle
143*9712c20fSFrederick Mayle JavaLanguage JavaLanguageSingleton;
144*9712c20fSFrederick Mayle
145*9712c20fSFrederick Mayle // Swift language-specific operations.
146*9712c20fSFrederick Mayle class SwiftLanguage: public Language {
147*9712c20fSFrederick Mayle public:
SwiftLanguage()148*9712c20fSFrederick Mayle SwiftLanguage() {}
149*9712c20fSFrederick Mayle
MakeQualifiedName(const string & parent_name,const string & name) const150*9712c20fSFrederick Mayle string MakeQualifiedName(const string& parent_name,
151*9712c20fSFrederick Mayle const string& name) const {
152*9712c20fSFrederick Mayle return MakeQualifiedNameWithSeparator(parent_name, ".", name);
153*9712c20fSFrederick Mayle }
154*9712c20fSFrederick Mayle
DemangleName(const string & mangled,string * demangled) const155*9712c20fSFrederick Mayle virtual DemangleResult DemangleName(const string& mangled,
156*9712c20fSFrederick Mayle string* demangled) const {
157*9712c20fSFrederick Mayle // There is no programmatic interface to a Swift demangler. Pass through the
158*9712c20fSFrederick Mayle // mangled form because it encodes more information than the qualified name
159*9712c20fSFrederick Mayle // that would have been built by MakeQualifiedName(). The output can be
160*9712c20fSFrederick Mayle // post-processed by xcrun swift-demangle to transform mangled Swift names
161*9712c20fSFrederick Mayle // into something more readable.
162*9712c20fSFrederick Mayle demangled->assign(mangled);
163*9712c20fSFrederick Mayle return kDemangleSuccess;
164*9712c20fSFrederick Mayle }
165*9712c20fSFrederick Mayle };
166*9712c20fSFrederick Mayle
167*9712c20fSFrederick Mayle SwiftLanguage SwiftLanguageSingleton;
168*9712c20fSFrederick Mayle
169*9712c20fSFrederick Mayle // Rust language-specific operations.
170*9712c20fSFrederick Mayle class RustLanguage: public Language {
171*9712c20fSFrederick Mayle public:
RustLanguage()172*9712c20fSFrederick Mayle RustLanguage() {}
173*9712c20fSFrederick Mayle
MakeQualifiedName(const string & parent_name,const string & name) const174*9712c20fSFrederick Mayle string MakeQualifiedName(const string& parent_name,
175*9712c20fSFrederick Mayle const string& name) const {
176*9712c20fSFrederick Mayle return MakeQualifiedNameWithSeparator(parent_name, ".", name);
177*9712c20fSFrederick Mayle }
178*9712c20fSFrederick Mayle
DemangleName(const string & mangled,string * demangled) const179*9712c20fSFrederick Mayle virtual DemangleResult DemangleName(const string& mangled,
180*9712c20fSFrederick Mayle string* demangled) const {
181*9712c20fSFrederick Mayle // Rust names use GCC C++ name mangling, but demangling them with
182*9712c20fSFrederick Mayle // abi_demangle doesn't produce stellar results due to them having
183*9712c20fSFrederick Mayle // another layer of encoding.
184*9712c20fSFrederick Mayle // If callers provide rustc-demangle, use that.
185*9712c20fSFrederick Mayle #if defined(HAVE_RUSTC_DEMANGLE)
186*9712c20fSFrederick Mayle std::array<char, 1 * 1024 * 1024> rustc_demangled;
187*9712c20fSFrederick Mayle if (rustc_demangle(mangled.c_str(), rustc_demangled.data(),
188*9712c20fSFrederick Mayle rustc_demangled.size()) == 0) {
189*9712c20fSFrederick Mayle return kDemangleFailure;
190*9712c20fSFrederick Mayle }
191*9712c20fSFrederick Mayle demangled->assign(rustc_demangled.data());
192*9712c20fSFrederick Mayle #else
193*9712c20fSFrederick Mayle // Otherwise, pass through the mangled name so callers can demangle
194*9712c20fSFrederick Mayle // after the fact.
195*9712c20fSFrederick Mayle demangled->assign(mangled);
196*9712c20fSFrederick Mayle #endif
197*9712c20fSFrederick Mayle return kDemangleSuccess;
198*9712c20fSFrederick Mayle }
199*9712c20fSFrederick Mayle };
200*9712c20fSFrederick Mayle
201*9712c20fSFrederick Mayle RustLanguage RustLanguageSingleton;
202*9712c20fSFrederick Mayle
203*9712c20fSFrederick Mayle // Assembler language-specific operations.
204*9712c20fSFrederick Mayle class AssemblerLanguage: public Language {
205*9712c20fSFrederick Mayle public:
AssemblerLanguage()206*9712c20fSFrederick Mayle AssemblerLanguage() {}
207*9712c20fSFrederick Mayle
HasFunctions() const208*9712c20fSFrederick Mayle bool HasFunctions() const { return false; }
MakeQualifiedName(const string & parent_name,const string & name) const209*9712c20fSFrederick Mayle string MakeQualifiedName(const string& parent_name,
210*9712c20fSFrederick Mayle const string& name) const {
211*9712c20fSFrederick Mayle return name;
212*9712c20fSFrederick Mayle }
213*9712c20fSFrederick Mayle };
214*9712c20fSFrederick Mayle
215*9712c20fSFrederick Mayle AssemblerLanguage AssemblerLanguageSingleton;
216*9712c20fSFrederick Mayle
217*9712c20fSFrederick Mayle const Language * const Language::CPlusPlus = &CPPLanguageSingleton;
218*9712c20fSFrederick Mayle const Language * const Language::Java = &JavaLanguageSingleton;
219*9712c20fSFrederick Mayle const Language * const Language::Swift = &SwiftLanguageSingleton;
220*9712c20fSFrederick Mayle const Language * const Language::Rust = &RustLanguageSingleton;
221*9712c20fSFrederick Mayle const Language * const Language::Assembler = &AssemblerLanguageSingleton;
222*9712c20fSFrederick Mayle
223*9712c20fSFrederick Mayle } // namespace google_breakpad
224