/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/Mangled.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- Mangled.cpp -------------------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "lldb/Core/Mangled.h" |
10 | | |
11 | | #include "lldb/Core/DataFileCache.h" |
12 | | #include "lldb/Core/RichManglingContext.h" |
13 | | #include "lldb/Target/Language.h" |
14 | | #include "lldb/Utility/ConstString.h" |
15 | | #include "lldb/Utility/DataEncoder.h" |
16 | | #include "lldb/Utility/LLDBLog.h" |
17 | | #include "lldb/Utility/Log.h" |
18 | | #include "lldb/Utility/RegularExpression.h" |
19 | | #include "lldb/Utility/Stream.h" |
20 | | #include "lldb/lldb-enumerations.h" |
21 | | |
22 | | #include "llvm/ADT/StringRef.h" |
23 | | #include "llvm/Demangle/Demangle.h" |
24 | | #include "llvm/Support/Compiler.h" |
25 | | |
26 | | #include <mutex> |
27 | | #include <string> |
28 | | #include <string_view> |
29 | | #include <utility> |
30 | | |
31 | | #include <cstdlib> |
32 | | #include <cstring> |
33 | | using namespace lldb_private; |
34 | | |
35 | 123M | static inline bool cstring_is_mangled(llvm::StringRef s) { |
36 | 123M | return Mangled::GetManglingScheme(s) != Mangled::eManglingSchemeNone; |
37 | 123M | } |
38 | | |
39 | | #pragma mark Mangled |
40 | | |
41 | 158M | Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) { |
42 | 158M | if (name.empty()) |
43 | 59 | return Mangled::eManglingSchemeNone; |
44 | | |
45 | 158M | if (name.startswith("?")) |
46 | 0 | return Mangled::eManglingSchemeMSVC; |
47 | | |
48 | 158M | if (name.startswith("_R")) |
49 | 13.0k | return Mangled::eManglingSchemeRustV0; |
50 | | |
51 | 158M | if (name.startswith("_D")) |
52 | 138k | return Mangled::eManglingSchemeD; |
53 | | |
54 | 158M | if (name.startswith("_Z")) |
55 | 62.5M | return Mangled::eManglingSchemeItanium; |
56 | | |
57 | | // ___Z is a clang extension of block invocations |
58 | 95.6M | if (name.startswith("___Z")) |
59 | 4.34M | return Mangled::eManglingSchemeItanium; |
60 | | |
61 | | // Swift's older style of mangling used "_T" as a mangling prefix. This can |
62 | | // lead to false positives with other symbols that just so happen to start |
63 | | // with "_T". To minimize the chance of that happening, we only return true |
64 | | // for select old-style swift mangled names. The known cases are ObjC classes |
65 | | // and protocols. Classes are either prefixed with "_TtC" or "_TtGC". |
66 | | // Protocols are prefixed with "_TtP". |
67 | 91.3M | if (name.startswith("_TtC") || name.startswith("_TtGC")91.3M || |
68 | 91.3M | name.startswith("_TtP")91.3M ) |
69 | 2 | return Mangled::eManglingSchemeSwift; |
70 | | |
71 | | // Swift 4.2 used "$S" and "_$S". |
72 | | // Swift 5 and onward uses "$s" and "_$s". |
73 | | // Swift also uses "@__swiftmacro_" as a prefix for mangling filenames. |
74 | 91.3M | if (name.startswith("$S") || name.startswith("_$S")91.3M || |
75 | 91.3M | name.startswith("$s")91.3M || name.startswith("_$s")91.2M || |
76 | 91.3M | name.startswith("@__swiftmacro_")91.2M ) |
77 | 73.8k | return Mangled::eManglingSchemeSwift; |
78 | | |
79 | 91.2M | return Mangled::eManglingSchemeNone; |
80 | 91.3M | } |
81 | | |
82 | 110k | Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() { |
83 | 110k | if (s) |
84 | 93.0k | SetValue(s); |
85 | 110k | } |
86 | | |
87 | 7.80k | Mangled::Mangled(llvm::StringRef name) { |
88 | 7.80k | if (!name.empty()) |
89 | 6.21k | SetValue(ConstString(name)); |
90 | 7.80k | } |
91 | | |
92 | | // Convert to bool operator. This allows code to check any Mangled objects |
93 | | // to see if they contain anything valid using code such as: |
94 | | // |
95 | | // Mangled mangled(...); |
96 | | // if (mangled) |
97 | | // { ... |
98 | 9.72M | Mangled::operator bool() const { return m_mangled || m_demangled9.72M ; } |
99 | | |
100 | | // Clear the mangled and demangled values. |
101 | 270k | void Mangled::Clear() { |
102 | 270k | m_mangled.Clear(); |
103 | 270k | m_demangled.Clear(); |
104 | 270k | } |
105 | | |
106 | | // Compare the string values. |
107 | 0 | int Mangled::Compare(const Mangled &a, const Mangled &b) { |
108 | 0 | return ConstString::Compare(a.GetName(ePreferMangled), |
109 | 0 | b.GetName(ePreferMangled)); |
110 | 0 | } |
111 | | |
112 | 123M | void Mangled::SetValue(ConstString name) { |
113 | 123M | if (name) { |
114 | 123M | if (cstring_is_mangled(name.GetStringRef())) { |
115 | 32.7M | m_demangled.Clear(); |
116 | 32.7M | m_mangled = name; |
117 | 90.6M | } else { |
118 | 90.6M | m_demangled = name; |
119 | 90.6M | m_mangled.Clear(); |
120 | 90.6M | } |
121 | 123M | } else { |
122 | 0 | m_demangled.Clear(); |
123 | 0 | m_mangled.Clear(); |
124 | 0 | } |
125 | 123M | } |
126 | | |
127 | | // Local helpers for different demangling implementations. |
128 | 0 | static char *GetMSVCDemangledStr(std::string_view M) { |
129 | 0 | char *demangled_cstr = llvm::microsoftDemangle( |
130 | 0 | M, nullptr, nullptr, |
131 | 0 | llvm::MSDemangleFlags( |
132 | 0 | llvm::MSDF_NoAccessSpecifier | llvm::MSDF_NoCallingConvention | |
133 | 0 | llvm::MSDF_NoMemberType | llvm::MSDF_NoVariableType)); |
134 | |
|
135 | 0 | if (Log *log = GetLog(LLDBLog::Demangle)) { |
136 | 0 | if (demangled_cstr && demangled_cstr[0]) |
137 | 0 | LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M.data(), demangled_cstr); |
138 | 0 | else |
139 | 0 | LLDB_LOGF(log, "demangled msvc: %s -> error", M.data()); |
140 | 0 | } |
141 | |
|
142 | 0 | return demangled_cstr; |
143 | 0 | } |
144 | | |
145 | 2.68M | static char *GetItaniumDemangledStr(const char *M) { |
146 | 2.68M | char *demangled_cstr = nullptr; |
147 | | |
148 | 2.68M | llvm::ItaniumPartialDemangler ipd; |
149 | 2.68M | bool err = ipd.partialDemangle(M); |
150 | 2.68M | if (!err) { |
151 | | // Default buffer and size (will realloc in case it's too small). |
152 | 2.68M | size_t demangled_size = 80; |
153 | 2.68M | demangled_cstr = static_cast<char *>(std::malloc(demangled_size)); |
154 | 2.68M | demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size); |
155 | | |
156 | 2.68M | assert(demangled_cstr && |
157 | 2.68M | "finishDemangle must always succeed if partialDemangle did"); |
158 | 2.68M | assert(demangled_cstr[demangled_size - 1] == '\0' && |
159 | 2.68M | "Expected demangled_size to return length including trailing null"); |
160 | 2.68M | } |
161 | | |
162 | 2.68M | if (Log *log = GetLog(LLDBLog::Demangle)) { |
163 | 0 | if (demangled_cstr) |
164 | 0 | LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr); |
165 | 0 | else |
166 | 0 | LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M); |
167 | 0 | } |
168 | | |
169 | 2.68M | return demangled_cstr; |
170 | 2.68M | } |
171 | | |
172 | 4.38k | static char *GetRustV0DemangledStr(std::string_view M) { |
173 | 4.38k | char *demangled_cstr = llvm::rustDemangle(M); |
174 | | |
175 | 4.38k | if (Log *log = GetLog(LLDBLog::Demangle)) { |
176 | 0 | if (demangled_cstr && demangled_cstr[0]) |
177 | 0 | LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr); |
178 | 0 | else |
179 | 0 | LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M); |
180 | 0 | } |
181 | | |
182 | 4.38k | return demangled_cstr; |
183 | 4.38k | } |
184 | | |
185 | 58.4k | static char *GetDLangDemangledStr(std::string_view M) { |
186 | 58.4k | char *demangled_cstr = llvm::dlangDemangle(M); |
187 | | |
188 | 58.4k | if (Log *log = GetLog(LLDBLog::Demangle)) { |
189 | 0 | if (demangled_cstr && demangled_cstr[0]) |
190 | 0 | LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr); |
191 | 0 | else |
192 | 0 | LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M); |
193 | 0 | } |
194 | | |
195 | 58.4k | return demangled_cstr; |
196 | 58.4k | } |
197 | | |
198 | | // Explicit demangling for scheduled requests during batch processing. This |
199 | | // makes use of ItaniumPartialDemangler's rich demangle info |
200 | | bool Mangled::GetRichManglingInfo(RichManglingContext &context, |
201 | 23.3M | SkipMangledNameFn *skip_mangled_name) { |
202 | | // Others are not meant to arrive here. ObjC names or C's main() for example |
203 | | // have their names stored in m_demangled, while m_mangled is empty. |
204 | 23.3M | assert(m_mangled); |
205 | | |
206 | | // Check whether or not we are interested in this name at all. |
207 | 23.3M | ManglingScheme scheme = GetManglingScheme(m_mangled.GetStringRef()); |
208 | 23.3M | if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme)) |
209 | 1.78M | return false; |
210 | | |
211 | 21.5M | switch (scheme) { |
212 | 0 | case eManglingSchemeNone: |
213 | | // The current mangled_name_filter would allow llvm_unreachable here. |
214 | 0 | return false; |
215 | | |
216 | 21.5M | case eManglingSchemeItanium: |
217 | | // We want the rich mangling info here, so we don't care whether or not |
218 | | // there is a demangled string in the pool already. |
219 | 21.5M | return context.FromItaniumName(m_mangled); |
220 | | |
221 | 0 | case eManglingSchemeMSVC: { |
222 | | // We have no rich mangling for MSVC-mangled names yet, so first try to |
223 | | // demangle it if necessary. |
224 | 0 | if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) { |
225 | 0 | if (char *d = GetMSVCDemangledStr(m_mangled)) { |
226 | | // Without the rich mangling info we have to demangle the full name. |
227 | | // Copy it to string pool and connect the counterparts to accelerate |
228 | | // later access in GetDemangledName(). |
229 | 0 | m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d), |
230 | 0 | m_mangled); |
231 | 0 | ::free(d); |
232 | 0 | } else { |
233 | 0 | m_demangled.SetCString(""); |
234 | 0 | } |
235 | 0 | } |
236 | |
|
237 | 0 | if (m_demangled.IsEmpty()) { |
238 | | // Cannot demangle it, so don't try parsing. |
239 | 0 | return false; |
240 | 0 | } else { |
241 | | // Demangled successfully, we can try and parse it with |
242 | | // CPlusPlusLanguage::MethodName. |
243 | 0 | return context.FromCxxMethodName(m_demangled); |
244 | 0 | } |
245 | 0 | } |
246 | | |
247 | 4.08k | case eManglingSchemeRustV0: |
248 | 24.5k | case eManglingSchemeD: |
249 | 43.4k | case eManglingSchemeSwift: |
250 | | // Rich demangling scheme is not supported |
251 | 43.4k | return false; |
252 | 21.5M | } |
253 | 0 | llvm_unreachable("Fully covered switch above!"); |
254 | 0 | } |
255 | | |
256 | | // Generate the demangled name on demand using this accessor. Code in this |
257 | | // class will need to use this accessor if it wishes to decode the demangled |
258 | | // name. The result is cached and will be kept until a new string value is |
259 | | // supplied to this object, or until the end of the object's lifetime. |
260 | 116M | ConstString Mangled::GetDemangledName() const { |
261 | | // Check to make sure we have a valid mangled name and that we haven't |
262 | | // already decoded our mangled name. |
263 | 116M | if (m_mangled && m_demangled.IsNull()14.2M ) { |
264 | | // Don't bother running anything that isn't mangled |
265 | 10.9M | const char *mangled_name = m_mangled.GetCString(); |
266 | 10.9M | ManglingScheme mangling_scheme = |
267 | 10.9M | GetManglingScheme(m_mangled.GetStringRef()); |
268 | 10.9M | if (mangling_scheme != eManglingSchemeNone && |
269 | 10.9M | !m_mangled.GetMangledCounterpart(m_demangled)10.9M ) { |
270 | | // We didn't already mangle this name, demangle it and if all goes well |
271 | | // add it to our map. |
272 | 2.77M | char *demangled_name = nullptr; |
273 | 2.77M | switch (mangling_scheme) { |
274 | 0 | case eManglingSchemeMSVC: |
275 | 0 | demangled_name = GetMSVCDemangledStr(mangled_name); |
276 | 0 | break; |
277 | 2.68M | case eManglingSchemeItanium: { |
278 | 2.68M | demangled_name = GetItaniumDemangledStr(mangled_name); |
279 | 2.68M | break; |
280 | 0 | } |
281 | 4.38k | case eManglingSchemeRustV0: |
282 | 4.38k | demangled_name = GetRustV0DemangledStr(m_mangled); |
283 | 4.38k | break; |
284 | 58.4k | case eManglingSchemeD: |
285 | 58.4k | demangled_name = GetDLangDemangledStr(m_mangled); |
286 | 58.4k | break; |
287 | 27.4k | case eManglingSchemeSwift: |
288 | | // Demangling a swift name requires the swift compiler. This is |
289 | | // explicitly unsupported on llvm.org. |
290 | 27.4k | break; |
291 | 0 | case eManglingSchemeNone: |
292 | 0 | llvm_unreachable("eManglingSchemeNone was handled already"); |
293 | 2.77M | } |
294 | 2.77M | if (demangled_name) { |
295 | 2.68M | m_demangled.SetStringWithMangledCounterpart( |
296 | 2.68M | llvm::StringRef(demangled_name), m_mangled); |
297 | 2.68M | free(demangled_name); |
298 | 2.68M | } |
299 | 2.77M | } |
300 | 10.9M | if (m_demangled.IsNull()) { |
301 | | // Set the demangled string to the empty string to indicate we tried to |
302 | | // parse it once and failed. |
303 | 96.4k | m_demangled.SetCString(""); |
304 | 96.4k | } |
305 | 10.9M | } |
306 | | |
307 | 116M | return m_demangled; |
308 | 116M | } |
309 | | |
310 | 66 | ConstString Mangled::GetDisplayDemangledName() const { |
311 | 66 | return GetDemangledName(); |
312 | 66 | } |
313 | | |
314 | 180 | bool Mangled::NameMatches(const RegularExpression ®ex) const { |
315 | 180 | if (m_mangled && regex.Execute(m_mangled.GetStringRef())62 ) |
316 | 12 | return true; |
317 | | |
318 | 168 | ConstString demangled = GetDemangledName(); |
319 | 168 | return demangled && regex.Execute(demangled.GetStringRef()); |
320 | 180 | } |
321 | | |
322 | | // Get the demangled name if there is one, else return the mangled name. |
323 | 32.4M | ConstString Mangled::GetName(Mangled::NamePreference preference) const { |
324 | 32.4M | if (preference == ePreferMangled && m_mangled29.5M ) |
325 | 10.0M | return m_mangled; |
326 | | |
327 | | // Call the accessor to make sure we get a demangled name in case it hasn't |
328 | | // been demangled yet... |
329 | 22.4M | ConstString demangled = GetDemangledName(); |
330 | | |
331 | 22.4M | if (preference == ePreferDemangledWithoutArguments) { |
332 | 28.8k | if (Language *lang = Language::FindPlugin(GuessLanguage())) { |
333 | 14.6k | return lang->GetDemangledFunctionNameWithoutArguments(*this); |
334 | 14.6k | } |
335 | 28.8k | } |
336 | 22.4M | if (preference == ePreferDemangled) { |
337 | 2.84M | if (demangled) |
338 | 2.73M | return demangled; |
339 | 112k | return m_mangled; |
340 | 2.84M | } |
341 | 19.5M | return demangled; |
342 | 22.4M | } |
343 | | |
344 | | // Dump a Mangled object to stream "s". We don't force our demangled name to be |
345 | | // computed currently (we don't use the accessor). |
346 | 20 | void Mangled::Dump(Stream *s) const { |
347 | 20 | if (m_mangled) { |
348 | 4 | *s << ", mangled = " << m_mangled; |
349 | 4 | } |
350 | 20 | if (m_demangled) { |
351 | 19 | const char *demangled = m_demangled.AsCString(); |
352 | 19 | s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"0 ); |
353 | 19 | } |
354 | 20 | } |
355 | | |
356 | | // Dumps a debug version of this string with extra object and state information |
357 | | // to stream "s". |
358 | 0 | void Mangled::DumpDebug(Stream *s) const { |
359 | 0 | s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2), |
360 | 0 | static_cast<const void *>(this)); |
361 | 0 | m_mangled.DumpDebug(s); |
362 | 0 | s->Printf(", demangled = "); |
363 | 0 | m_demangled.DumpDebug(s); |
364 | 0 | } |
365 | | |
366 | | // Return the size in byte that this object takes in memory. The size includes |
367 | | // the size of the objects it owns, and not the strings that it references |
368 | | // because they are shared strings. |
369 | 0 | size_t Mangled::MemorySize() const { |
370 | 0 | return m_mangled.MemorySize() + m_demangled.MemorySize(); |
371 | 0 | } |
372 | | |
373 | | // We "guess" the language because we can't determine a symbol's language from |
374 | | // it's name. For example, a Pascal symbol can be mangled using the C++ |
375 | | // Itanium scheme, and defined in a compilation unit within the same module as |
376 | | // other C++ units. In addition, different targets could have different ways |
377 | | // of mangling names from a given language, likewise the compilation units |
378 | | // within those targets. |
379 | 172k | lldb::LanguageType Mangled::GuessLanguage() const { |
380 | 172k | lldb::LanguageType result = lldb::eLanguageTypeUnknown; |
381 | | // Ask each language plugin to check if the mangled name belongs to it. |
382 | 1.11M | Language::ForEach([this, &result](Language *l) { |
383 | 1.11M | if (l->SymbolNameFitsToLanguage(*this)) { |
384 | 42.1k | result = l->GetLanguageType(); |
385 | 42.1k | return false; |
386 | 42.1k | } |
387 | 1.07M | return true; |
388 | 1.11M | }); |
389 | 172k | return result; |
390 | 172k | } |
391 | | |
392 | | // Dump OBJ to the supplied stream S. |
393 | 0 | Stream &operator<<(Stream &s, const Mangled &obj) { |
394 | 0 | if (obj.GetMangledName()) |
395 | 0 | s << "mangled = '" << obj.GetMangledName() << "'"; |
396 | |
|
397 | 0 | ConstString demangled = obj.GetDemangledName(); |
398 | 0 | if (demangled) |
399 | 0 | s << ", demangled = '" << demangled << '\''; |
400 | 0 | else |
401 | 0 | s << ", demangled = <error>"; |
402 | 0 | return s; |
403 | 0 | } |
404 | | |
405 | | // When encoding Mangled objects we can get away with encoding as little |
406 | | // information as is required. The enumeration below helps us to efficiently |
407 | | // encode Mangled objects. |
408 | | enum MangledEncoding { |
409 | | /// If the Mangled object has neither a mangled name or demangled name we can |
410 | | /// encode the object with one zero byte using the Empty enumeration. |
411 | | Empty = 0u, |
412 | | /// If the Mangled object has only a demangled name and no mangled named, we |
413 | | /// can encode only the demangled name. |
414 | | DemangledOnly = 1u, |
415 | | /// If the mangle name can calculate the demangled name (it is the |
416 | | /// mangled/demangled counterpart), then we only need to encode the mangled |
417 | | /// name as the demangled name can be recomputed. |
418 | | MangledOnly = 2u, |
419 | | /// If we have a Mangled object with two different names that are not related |
420 | | /// then we need to save both strings. This can happen if we have a name that |
421 | | /// isn't a true mangled name, but we want to be able to lookup a symbol by |
422 | | /// name and type in the symbol table. We do this for Objective C symbols like |
423 | | /// "OBJC_CLASS_$_NSValue" where the mangled named will be set to |
424 | | /// "OBJC_CLASS_$_NSValue" and the demangled name will be manually set to |
425 | | /// "NSValue". If we tried to demangled the name "OBJC_CLASS_$_NSValue" it |
426 | | /// would fail, but in these cases we want these unrelated names to be |
427 | | /// preserved. |
428 | | MangledAndDemangled = 3u |
429 | | }; |
430 | | |
431 | | bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, |
432 | 45 | const StringTableReader &strtab) { |
433 | 45 | m_mangled.Clear(); |
434 | 45 | m_demangled.Clear(); |
435 | 45 | MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr); |
436 | 45 | switch (encoding) { |
437 | 2 | case Empty: |
438 | 2 | return true; |
439 | | |
440 | 38 | case DemangledOnly: |
441 | 38 | m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); |
442 | 38 | return true; |
443 | | |
444 | 3 | case MangledOnly: |
445 | 3 | m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); |
446 | 3 | return true; |
447 | | |
448 | 2 | case MangledAndDemangled: |
449 | 2 | m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); |
450 | 2 | m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); |
451 | 2 | return true; |
452 | 45 | } |
453 | 0 | return false; |
454 | 45 | } |
455 | | /// The encoding format for the Mangled object is as follows: |
456 | | /// |
457 | | /// uint8_t encoding; |
458 | | /// char str1[]; (only if DemangledOnly, MangledOnly) |
459 | | /// char str2[]; (only if MangledAndDemangled) |
460 | | /// |
461 | | /// The strings are stored as NULL terminated UTF8 strings and str1 and str2 |
462 | | /// are only saved if we need them based on the encoding. |
463 | | /// |
464 | | /// Some mangled names have a mangled name that can be demangled by the built |
465 | | /// in demanglers. These kinds of mangled objects know when the mangled and |
466 | | /// demangled names are the counterparts for each other. This is done because |
467 | | /// demangling is very expensive and avoiding demangling the same name twice |
468 | | /// saves us a lot of compute time. For these kinds of names we only need to |
469 | | /// save the mangled name and have the encoding set to "MangledOnly". |
470 | | /// |
471 | | /// If a mangled obejct has only a demangled name, then we save only that string |
472 | | /// and have the encoding set to "DemangledOnly". |
473 | | /// |
474 | | /// Some mangled objects have both mangled and demangled names, but the |
475 | | /// demangled name can not be computed from the mangled name. This is often used |
476 | | /// for runtime named, like Objective C runtime V2 and V3 names. Both these |
477 | | /// names must be saved and the encoding is set to "MangledAndDemangled". |
478 | | /// |
479 | | /// For a Mangled object with no names, we only need to set the encoding to |
480 | | /// "Empty" and not store any string values. |
481 | 77 | void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const { |
482 | 77 | MangledEncoding encoding = Empty; |
483 | 77 | if (m_mangled) { |
484 | 4 | encoding = MangledOnly; |
485 | 4 | if (m_demangled) { |
486 | | // We have both mangled and demangled names. If the demangled name is the |
487 | | // counterpart of the mangled name, then we only need to save the mangled |
488 | | // named. If they are different, we need to save both. |
489 | 3 | ConstString s; |
490 | 3 | if (!(m_mangled.GetMangledCounterpart(s) && s == m_demangled1 )) |
491 | 2 | encoding = MangledAndDemangled; |
492 | 3 | } |
493 | 73 | } else if (m_demangled) { |
494 | 71 | encoding = DemangledOnly; |
495 | 71 | } |
496 | 77 | file.AppendU8(encoding); |
497 | 77 | switch (encoding) { |
498 | 2 | case Empty: |
499 | 2 | break; |
500 | 71 | case DemangledOnly: |
501 | 71 | file.AppendU32(strtab.Add(m_demangled)); |
502 | 71 | break; |
503 | 2 | case MangledOnly: |
504 | 2 | file.AppendU32(strtab.Add(m_mangled)); |
505 | 2 | break; |
506 | 2 | case MangledAndDemangled: |
507 | 2 | file.AppendU32(strtab.Add(m_mangled)); |
508 | 2 | file.AppendU32(strtab.Add(m_demangled)); |
509 | 2 | break; |
510 | 77 | } |
511 | 77 | } |