• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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