1 //===--- DLangDemangle.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 /// \file
10 /// This file defines a demangler for the D programming language as specified
11 /// in the ABI specification, available at:
12 /// https://dlang.org/spec/abi.html#name_mangling
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "llvm/Demangle/Demangle.h"
17 #include "llvm/Demangle/StringView.h"
18 #include "llvm/Demangle/Utility.h"
19 
20 #include <cctype>
21 #include <cstring>
22 #include <limits>
23 
24 using namespace llvm;
25 using llvm::itanium_demangle::OutputBuffer;
26 using llvm::itanium_demangle::StringView;
27 
28 namespace {
29 
30 /// Demangle information structure.
31 struct Demangler {
32   /// Initialize the information structure we use to pass around information.
33   ///
34   /// \param Mangled String to demangle.
35   Demangler(const char *Mangled);
36 
37   /// Extract and demangle the mangled symbol and append it to the output
38   /// string.
39   ///
40   /// \param Demangled Output buffer to write the demangled name.
41   ///
42   /// \return The remaining string on success or nullptr on failure.
43   ///
44   /// \see https://dlang.org/spec/abi.html#name_mangling .
45   /// \see https://dlang.org/spec/abi.html#MangledName .
46   const char *parseMangle(OutputBuffer *Demangled);
47 
48 private:
49   /// Extract and demangle a given mangled symbol and append it to the output
50   /// string.
51   ///
52   /// \param Demangled output buffer to write the demangled name.
53   /// \param Mangled mangled symbol to be demangled.
54   ///
55   /// \return The remaining string on success or nullptr on failure.
56   ///
57   /// \see https://dlang.org/spec/abi.html#name_mangling .
58   /// \see https://dlang.org/spec/abi.html#MangledName .
59   const char *parseMangle(OutputBuffer *Demangled, const char *Mangled);
60 
61   /// Extract the number from a given string.
62   ///
63   /// \param Mangled string to extract the number.
64   /// \param Ret assigned result value.
65   ///
66   /// \return The remaining string on success or nullptr on failure.
67   ///
68   /// \note A result larger than UINT_MAX is considered a failure.
69   ///
70   /// \see https://dlang.org/spec/abi.html#Number .
71   const char *decodeNumber(const char *Mangled, unsigned long *Ret);
72 
73   /// Extract the back reference position from a given string.
74   ///
75   /// \param Mangled string to extract the back reference position.
76   /// \param Ret assigned result value.
77   ///
78   /// \return the remaining string on success or nullptr on failure.
79   ///
80   /// \note Ret is always >= 0 on success, and unspecified on failure
81   ///
82   /// \see https://dlang.org/spec/abi.html#back_ref .
83   /// \see https://dlang.org/spec/abi.html#NumberBackRef .
84   const char *decodeBackrefPos(const char *Mangled, long &Ret);
85 
86   /// Extract the symbol pointed by the back reference form a given string.
87   ///
88   /// \param Mangled string to extract the back reference position.
89   /// \param Ret assigned result value.
90   ///
91   /// \return the remaining string on success or nullptr on failure.
92   ///
93   /// \see https://dlang.org/spec/abi.html#back_ref .
94   const char *decodeBackref(const char *Mangled, const char *&Ret);
95 
96   /// Extract and demangle backreferenced symbol from a given mangled symbol
97   /// and append it to the output string.
98   ///
99   /// \param Demangled output buffer to write the demangled name.
100   /// \param Mangled mangled symbol to be demangled.
101   ///
102   /// \return the remaining string on success or nullptr on failure.
103   ///
104   /// \see https://dlang.org/spec/abi.html#back_ref .
105   /// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
106   const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
107 
108   /// Check whether it is the beginning of a symbol name.
109   ///
110   /// \param Mangled string to extract the symbol name.
111   ///
112   /// \return true on success, false otherwise.
113   ///
114   /// \see https://dlang.org/spec/abi.html#SymbolName .
115   bool isSymbolName(const char *Mangled);
116 
117   /// Extract and demangle an identifier from a given mangled symbol append it
118   /// to the output string.
119   ///
120   /// \param Demangled Output buffer to write the demangled name.
121   /// \param Mangled Mangled symbol to be demangled.
122   ///
123   /// \return The remaining string on success or nullptr on failure.
124   ///
125   /// \see https://dlang.org/spec/abi.html#SymbolName .
126   const char *parseIdentifier(OutputBuffer *Demangled, const char *Mangled);
127 
128   /// Extract and demangle the plain identifier from a given mangled symbol and
129   /// prepend/append it to the output string, with a special treatment for some
130   /// magic compiler generated symbols.
131   ///
132   /// \param Demangled Output buffer to write the demangled name.
133   /// \param Mangled Mangled symbol to be demangled.
134   /// \param Len Length of the mangled symbol name.
135   ///
136   /// \return The remaining string on success or nullptr on failure.
137   ///
138   /// \see https://dlang.org/spec/abi.html#LName .
139   const char *parseLName(OutputBuffer *Demangled, const char *Mangled,
140                          unsigned long Len);
141 
142   /// Extract and demangle the qualified symbol from a given mangled symbol
143   /// append it to the output string.
144   ///
145   /// \param Demangled Output buffer to write the demangled name.
146   /// \param Mangled Mangled symbol to be demangled.
147   ///
148   /// \return The remaining string on success or nullptr on failure.
149   ///
150   /// \see https://dlang.org/spec/abi.html#QualifiedName .
151   const char *parseQualified(OutputBuffer *Demangled, const char *Mangled);
152 
153   /// Extract and demangle a type from a given mangled symbol append it to
154   /// the output string.
155   ///
156   /// \param Mangled mangled symbol to be demangled.
157   ///
158   /// \return the remaining string on success or nullptr on failure.
159   ///
160   /// \see https://dlang.org/spec/abi.html#Type .
161   const char *parseType(const char *Mangled);
162 
163   /// The string we are demangling.
164   const char *Str;
165 };
166 
167 } // namespace
168 
169 const char *Demangler::decodeNumber(const char *Mangled, unsigned long *Ret) {
170   // Return nullptr if trying to extract something that isn't a digit.
171   if (Mangled == nullptr || !std::isdigit(*Mangled))
172     return nullptr;
173 
174   unsigned long Val = 0;
175 
176   do {
177     unsigned long Digit = Mangled[0] - '0';
178 
179     // Check for overflow.
180     if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10)
181       return nullptr;
182 
183     Val = Val * 10 + Digit;
184     ++Mangled;
185   } while (std::isdigit(*Mangled));
186 
187   if (*Mangled == '\0')
188     return nullptr;
189 
190   *Ret = Val;
191   return Mangled;
192 }
193 
194 const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) {
195   // Return nullptr if trying to extract something that isn't a digit
196   if (Mangled == nullptr || !std::isalpha(*Mangled))
197     return nullptr;
198 
199   // Any identifier or non-basic type that has been emitted to the mangled
200   // symbol before will not be emitted again, but is referenced by a special
201   // sequence encoding the relative position of the original occurrence in the
202   // mangled symbol name.
203   // Numbers in back references are encoded with base 26 by upper case letters
204   // A-Z for higher digits but lower case letters a-z for the last digit.
205   //    NumberBackRef:
206   //        [a-z]
207   //        [A-Z] NumberBackRef
208   //        ^
209   unsigned long Val = 0;
210 
211   while (std::isalpha(*Mangled)) {
212     // Check for overflow
213     if (Val > (std::numeric_limits<unsigned long>::max() - 25) / 26)
214       break;
215 
216     Val *= 26;
217 
218     if (Mangled[0] >= 'a' && Mangled[0] <= 'z') {
219       Val += Mangled[0] - 'a';
220       if ((long)Val <= 0)
221         break;
222       Ret = Val;
223       return Mangled + 1;
224     }
225 
226     Val += Mangled[0] - 'A';
227     ++Mangled;
228   }
229 
230   return nullptr;
231 }
232 
233 const char *Demangler::decodeBackref(const char *Mangled, const char *&Ret) {
234   assert(Mangled != nullptr && *Mangled == 'Q' && "Invalid back reference!");
235   Ret = nullptr;
236 
237   // Position of 'Q'
238   const char *Qpos = Mangled;
239   long RefPos;
240   ++Mangled;
241 
242   Mangled = decodeBackrefPos(Mangled, RefPos);
243   if (Mangled == nullptr)
244     return nullptr;
245 
246   if (RefPos > Qpos - Str)
247     return nullptr;
248 
249   // Set the position of the back reference.
250   Ret = Qpos - RefPos;
251 
252   return Mangled;
253 }
254 
255 const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled,
256                                           const char *Mangled) {
257   // An identifier back reference always points to a digit 0 to 9.
258   //    IdentifierBackRef:
259   //        Q NumberBackRef
260   //        ^
261   const char *Backref;
262   unsigned long Len;
263 
264   // Get position of the back reference
265   Mangled = decodeBackref(Mangled, Backref);
266 
267   // Must point to a simple identifier
268   Backref = decodeNumber(Backref, &Len);
269   if (Backref == nullptr || strlen(Backref) < Len)
270     return nullptr;
271 
272   Backref = parseLName(Demangled, Backref, Len);
273   if (Backref == nullptr)
274     return nullptr;
275 
276   return Mangled;
277 }
278 
279 bool Demangler::isSymbolName(const char *Mangled) {
280   long Ret;
281   const char *Qref = Mangled;
282 
283   if (std::isdigit(*Mangled))
284     return true;
285 
286   // TODO: Handle template instances.
287 
288   if (*Mangled != 'Q')
289     return false;
290 
291   Mangled = decodeBackrefPos(Mangled + 1, Ret);
292   if (Mangled == nullptr || Ret > Qref - Str)
293     return false;
294 
295   return std::isdigit(Qref[-Ret]);
296 }
297 
298 const char *Demangler::parseMangle(OutputBuffer *Demangled,
299                                    const char *Mangled) {
300   // A D mangled symbol is comprised of both scope and type information.
301   //    MangleName:
302   //        _D QualifiedName Type
303   //        _D QualifiedName Z
304   //        ^
305   // The caller should have guaranteed that the start pointer is at the
306   // above location.
307   // Note that type is never a function type, but only the return type of
308   // a function or the type of a variable.
309   Mangled += 2;
310 
311   Mangled = parseQualified(Demangled, Mangled);
312 
313   if (Mangled != nullptr) {
314     // Artificial symbols end with 'Z' and have no type.
315     if (*Mangled == 'Z')
316       ++Mangled;
317     else {
318       Mangled = parseType(Mangled);
319     }
320   }
321 
322   return Mangled;
323 }
324 
325 const char *Demangler::parseQualified(OutputBuffer *Demangled,
326                                       const char *Mangled) {
327   // Qualified names are identifiers separated by their encoded length.
328   // Nested functions also encode their argument types without specifying
329   // what they return.
330   //    QualifiedName:
331   //        SymbolFunctionName
332   //        SymbolFunctionName QualifiedName
333   //        ^
334   //    SymbolFunctionName:
335   //        SymbolName
336   //        SymbolName TypeFunctionNoReturn
337   //        SymbolName M TypeFunctionNoReturn
338   //        SymbolName M TypeModifiers TypeFunctionNoReturn
339   // The start pointer should be at the above location.
340 
341   // Whether it has more than one symbol
342   size_t NotFirst = false;
343   do {
344     // Skip over anonymous symbols.
345     if (*Mangled == '0') {
346       do
347         ++Mangled;
348       while (*Mangled == '0');
349 
350       continue;
351     }
352 
353     if (NotFirst)
354       *Demangled << '.';
355     NotFirst = true;
356 
357     Mangled = parseIdentifier(Demangled, Mangled);
358 
359   } while (Mangled && isSymbolName(Mangled));
360 
361   return Mangled;
362 }
363 
364 const char *Demangler::parseIdentifier(OutputBuffer *Demangled,
365                                        const char *Mangled) {
366   unsigned long Len;
367 
368   if (Mangled == nullptr || *Mangled == '\0')
369     return nullptr;
370 
371   if (*Mangled == 'Q')
372     return parseSymbolBackref(Demangled, Mangled);
373 
374   // TODO: Parse lengthless template instances.
375 
376   const char *Endptr = decodeNumber(Mangled, &Len);
377 
378   if (Endptr == nullptr || Len == 0)
379     return nullptr;
380 
381   if (strlen(Endptr) < Len)
382     return nullptr;
383 
384   Mangled = Endptr;
385 
386   // TODO: Parse template instances with a length prefix.
387 
388   // There can be multiple different declarations in the same function that
389   // have the same mangled name.  To make the mangled names unique, a fake
390   // parent in the form `__Sddd' is added to the symbol.
391   if (Len >= 4 && Mangled[0] == '_' && Mangled[1] == '_' && Mangled[2] == 'S') {
392     const char *NumPtr = Mangled + 3;
393     while (NumPtr < (Mangled + Len) && std::isdigit(*NumPtr))
394       ++NumPtr;
395 
396     if (Mangled + Len == NumPtr) {
397       // Skip over the fake parent.
398       Mangled += Len;
399       return parseIdentifier(Demangled, Mangled);
400     }
401 
402     // Else demangle it as a plain identifier.
403   }
404 
405   return parseLName(Demangled, Mangled, Len);
406 }
407 
408 const char *Demangler::parseType(const char *Mangled) {
409   if (*Mangled == '\0')
410     return nullptr;
411 
412   switch (*Mangled) {
413   // TODO: Parse type qualifiers.
414   // TODO: Parse function types.
415   // TODO: Parse compound types.
416   // TODO: Parse delegate types.
417   // TODO: Parse tuple types.
418 
419   // Basic types.
420   case 'i':
421     ++Mangled;
422     // TODO: Add type name dumping
423     return Mangled;
424 
425     // TODO: Add support for the rest of the basic types.
426     // TODO: Parse back referenced types.
427 
428   default: // unhandled.
429     return nullptr;
430   }
431 }
432 
433 const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled,
434                                   unsigned long Len) {
435   switch (Len) {
436   case 6:
437     if (strncmp(Mangled, "__initZ", Len + 1) == 0) {
438       // The static initializer for a given symbol.
439       Demangled->prepend("initializer for ");
440       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
441       Mangled += Len;
442       return Mangled;
443     }
444     if (strncmp(Mangled, "__vtblZ", Len + 1) == 0) {
445       // The vtable symbol for a given class.
446       Demangled->prepend("vtable for ");
447       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
448       Mangled += Len;
449       return Mangled;
450     }
451     break;
452 
453   case 7:
454     if (strncmp(Mangled, "__ClassZ", Len + 1) == 0) {
455       // The classinfo symbol for a given class.
456       Demangled->prepend("ClassInfo for ");
457       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
458       Mangled += Len;
459       return Mangled;
460     }
461     break;
462 
463   case 11:
464     if (strncmp(Mangled, "__InterfaceZ", Len + 1) == 0) {
465       // The interface symbol for a given class.
466       Demangled->prepend("Interface for ");
467       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
468       Mangled += Len;
469       return Mangled;
470     }
471     break;
472 
473   case 12:
474     if (strncmp(Mangled, "__ModuleInfoZ", Len + 1) == 0) {
475       // The ModuleInfo symbol for a given module.
476       Demangled->prepend("ModuleInfo for ");
477       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
478       Mangled += Len;
479       return Mangled;
480     }
481     break;
482   }
483 
484   *Demangled << StringView(Mangled, Len);
485   Mangled += Len;
486 
487   return Mangled;
488 }
489 
490 Demangler::Demangler(const char *Mangled) : Str(Mangled) {}
491 
492 const char *Demangler::parseMangle(OutputBuffer *Demangled) {
493   return parseMangle(Demangled, this->Str);
494 }
495 
496 char *llvm::dlangDemangle(const char *MangledName) {
497   if (MangledName == nullptr || strncmp(MangledName, "_D", 2) != 0)
498     return nullptr;
499 
500   OutputBuffer Demangled;
501   if (!initializeOutputBuffer(nullptr, nullptr, Demangled, 1024))
502     return nullptr;
503 
504   if (strcmp(MangledName, "_Dmain") == 0) {
505     Demangled << "D main";
506   } else {
507 
508     Demangler D = Demangler(MangledName);
509     MangledName = D.parseMangle(&Demangled);
510 
511     // Check that the entire symbol was successfully demangled.
512     if (MangledName == nullptr || *MangledName != '\0') {
513       std::free(Demangled.getBuffer());
514       return nullptr;
515     }
516   }
517 
518   // OutputBuffer's internal buffer is not null terminated and therefore we need
519   // to add it to comply with C null terminated strings.
520   if (Demangled.getCurrentPosition() > 0) {
521     Demangled << '\0';
522     Demangled.setCurrentPosition(Demangled.getCurrentPosition() - 1);
523     return Demangled.getBuffer();
524   }
525 
526   std::free(Demangled.getBuffer());
527   return nullptr;
528 }
529