1 //===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===// 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 #ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H 10 #define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H 11 12 #include "llvm/Demangle/MicrosoftDemangleNodes.h" 13 14 #include <cassert> 15 #include <string_view> 16 #include <utility> 17 18 namespace llvm { 19 namespace ms_demangle { 20 // This memory allocator is extremely fast, but it doesn't call dtors 21 // for allocated objects. That means you can't use STL containers 22 // (such as std::vector) with this allocator. But it pays off -- 23 // the demangler is 3x faster with this allocator compared to one with 24 // STL containers. 25 constexpr size_t AllocUnit = 4096; 26 27 class ArenaAllocator { 28 struct AllocatorNode { 29 uint8_t *Buf = nullptr; 30 size_t Used = 0; 31 size_t Capacity = 0; 32 AllocatorNode *Next = nullptr; 33 }; 34 addNode(size_t Capacity)35 void addNode(size_t Capacity) { 36 AllocatorNode *NewHead = new AllocatorNode; 37 NewHead->Buf = new uint8_t[Capacity]; 38 NewHead->Next = Head; 39 NewHead->Capacity = Capacity; 40 Head = NewHead; 41 NewHead->Used = 0; 42 } 43 44 public: ArenaAllocator()45 ArenaAllocator() { addNode(AllocUnit); } 46 ~ArenaAllocator()47 ~ArenaAllocator() { 48 while (Head) { 49 assert(Head->Buf); 50 delete[] Head->Buf; 51 AllocatorNode *Next = Head->Next; 52 delete Head; 53 Head = Next; 54 } 55 } 56 57 // Delete the copy constructor and the copy assignment operator. 58 ArenaAllocator(const ArenaAllocator &) = delete; 59 ArenaAllocator &operator=(const ArenaAllocator &) = delete; 60 allocUnalignedBuffer(size_t Size)61 char *allocUnalignedBuffer(size_t Size) { 62 assert(Head && Head->Buf); 63 64 uint8_t *P = Head->Buf + Head->Used; 65 66 Head->Used += Size; 67 if (Head->Used <= Head->Capacity) 68 return reinterpret_cast<char *>(P); 69 70 addNode(std::max(AllocUnit, Size)); 71 Head->Used = Size; 72 return reinterpret_cast<char *>(Head->Buf); 73 } 74 allocArray(size_t Count)75 template <typename T, typename... Args> T *allocArray(size_t Count) { 76 size_t Size = Count * sizeof(T); 77 assert(Head && Head->Buf); 78 79 size_t P = (size_t)Head->Buf + Head->Used; 80 uintptr_t AlignedP = 81 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); 82 uint8_t *PP = (uint8_t *)AlignedP; 83 size_t Adjustment = AlignedP - P; 84 85 Head->Used += Size + Adjustment; 86 if (Head->Used <= Head->Capacity) 87 return new (PP) T[Count](); 88 89 addNode(std::max(AllocUnit, Size)); 90 Head->Used = Size; 91 return new (Head->Buf) T[Count](); 92 } 93 alloc(Args &&...ConstructorArgs)94 template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) { 95 constexpr size_t Size = sizeof(T); 96 assert(Head && Head->Buf); 97 98 size_t P = (size_t)Head->Buf + Head->Used; 99 uintptr_t AlignedP = 100 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); 101 uint8_t *PP = (uint8_t *)AlignedP; 102 size_t Adjustment = AlignedP - P; 103 104 Head->Used += Size + Adjustment; 105 if (Head->Used <= Head->Capacity) 106 return new (PP) T(std::forward<Args>(ConstructorArgs)...); 107 108 static_assert(Size < AllocUnit); 109 addNode(AllocUnit); 110 Head->Used = Size; 111 return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...); 112 } 113 114 private: 115 AllocatorNode *Head = nullptr; 116 }; 117 118 struct BackrefContext { 119 static constexpr size_t Max = 10; 120 121 TypeNode *FunctionParams[Max]; 122 size_t FunctionParamCount = 0; 123 124 // The first 10 BackReferences in a mangled name can be back-referenced by 125 // special name @[0-9]. This is a storage for the first 10 BackReferences. 126 NamedIdentifierNode *Names[Max]; 127 size_t NamesCount = 0; 128 }; 129 130 enum class QualifierMangleMode { Drop, Mangle, Result }; 131 132 enum NameBackrefBehavior : uint8_t { 133 NBB_None = 0, // don't save any names as backrefs. 134 NBB_Template = 1 << 0, // save template instanations. 135 NBB_Simple = 1 << 1, // save simple names. 136 }; 137 138 enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder }; 139 140 // Demangler class takes the main role in demangling symbols. 141 // It has a set of functions to parse mangled symbols into Type instances. 142 // It also has a set of functions to convert Type instances to strings. 143 class Demangler { 144 public: 145 Demangler() = default; 146 virtual ~Demangler() = default; 147 148 // You are supposed to call parse() first and then check if error is true. If 149 // it is false, call output() to write the formatted name to the given stream. 150 SymbolNode *parse(std::string_view &MangledName); 151 152 TagTypeNode *parseTagUniqueName(std::string_view &MangledName); 153 154 // True if an error occurred. 155 bool Error = false; 156 157 void dumpBackReferences(); 158 159 private: 160 SymbolNode *demangleEncodedSymbol(std::string_view &MangledName, 161 QualifiedNameNode *QN); 162 SymbolNode *demangleDeclarator(std::string_view &MangledName); 163 SymbolNode *demangleMD5Name(std::string_view &MangledName); 164 SymbolNode *demangleTypeinfoName(std::string_view &MangledName); 165 166 VariableSymbolNode *demangleVariableEncoding(std::string_view &MangledName, 167 StorageClass SC); 168 FunctionSymbolNode *demangleFunctionEncoding(std::string_view &MangledName); 169 170 Qualifiers demanglePointerExtQualifiers(std::string_view &MangledName); 171 172 // Parser functions. This is a recursive-descent parser. 173 TypeNode *demangleType(std::string_view &MangledName, 174 QualifierMangleMode QMM); 175 PrimitiveTypeNode *demanglePrimitiveType(std::string_view &MangledName); 176 CustomTypeNode *demangleCustomType(std::string_view &MangledName); 177 TagTypeNode *demangleClassType(std::string_view &MangledName); 178 PointerTypeNode *demanglePointerType(std::string_view &MangledName); 179 PointerTypeNode *demangleMemberPointerType(std::string_view &MangledName); 180 FunctionSignatureNode *demangleFunctionType(std::string_view &MangledName, 181 bool HasThisQuals); 182 183 ArrayTypeNode *demangleArrayType(std::string_view &MangledName); 184 185 NodeArrayNode *demangleFunctionParameterList(std::string_view &MangledName, 186 bool &IsVariadic); 187 NodeArrayNode *demangleTemplateParameterList(std::string_view &MangledName); 188 189 std::pair<uint64_t, bool> demangleNumber(std::string_view &MangledName); 190 uint64_t demangleUnsigned(std::string_view &MangledName); 191 int64_t demangleSigned(std::string_view &MangledName); 192 193 void memorizeString(std::string_view s); 194 void memorizeIdentifier(IdentifierNode *Identifier); 195 196 /// Allocate a copy of \p Borrowed into memory that we own. 197 std::string_view copyString(std::string_view Borrowed); 198 199 QualifiedNameNode * 200 demangleFullyQualifiedTypeName(std::string_view &MangledName); 201 QualifiedNameNode * 202 demangleFullyQualifiedSymbolName(std::string_view &MangledName); 203 204 IdentifierNode *demangleUnqualifiedTypeName(std::string_view &MangledName, 205 bool Memorize); 206 IdentifierNode *demangleUnqualifiedSymbolName(std::string_view &MangledName, 207 NameBackrefBehavior NBB); 208 209 QualifiedNameNode *demangleNameScopeChain(std::string_view &MangledName, 210 IdentifierNode *UnqualifiedName); 211 IdentifierNode *demangleNameScopePiece(std::string_view &MangledName); 212 213 NamedIdentifierNode *demangleBackRefName(std::string_view &MangledName); 214 IdentifierNode * 215 demangleTemplateInstantiationName(std::string_view &MangledName, 216 NameBackrefBehavior NBB); 217 IntrinsicFunctionKind 218 translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group); 219 IdentifierNode *demangleFunctionIdentifierCode(std::string_view &MangledName); 220 IdentifierNode * 221 demangleFunctionIdentifierCode(std::string_view &MangledName, 222 FunctionIdentifierCodeGroup Group); 223 StructorIdentifierNode * 224 demangleStructorIdentifier(std::string_view &MangledName, bool IsDestructor); 225 ConversionOperatorIdentifierNode * 226 demangleConversionOperatorIdentifier(std::string_view &MangledName); 227 LiteralOperatorIdentifierNode * 228 demangleLiteralOperatorIdentifier(std::string_view &MangledName); 229 230 SymbolNode *demangleSpecialIntrinsic(std::string_view &MangledName); 231 SpecialTableSymbolNode * 232 demangleSpecialTableSymbolNode(std::string_view &MangledName, 233 SpecialIntrinsicKind SIK); 234 LocalStaticGuardVariableNode * 235 demangleLocalStaticGuard(std::string_view &MangledName, bool IsThread); 236 VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena, 237 std::string_view &MangledName, 238 std::string_view VariableName); 239 VariableSymbolNode * 240 demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, 241 std::string_view &MangledName); 242 FunctionSymbolNode *demangleInitFiniStub(std::string_view &MangledName, 243 bool IsDestructor); 244 245 NamedIdentifierNode *demangleSimpleName(std::string_view &MangledName, 246 bool Memorize); 247 NamedIdentifierNode * 248 demangleAnonymousNamespaceName(std::string_view &MangledName); 249 NamedIdentifierNode * 250 demangleLocallyScopedNamePiece(std::string_view &MangledName); 251 EncodedStringLiteralNode * 252 demangleStringLiteral(std::string_view &MangledName); 253 FunctionSymbolNode *demangleVcallThunkNode(std::string_view &MangledName); 254 255 std::string_view demangleSimpleString(std::string_view &MangledName, 256 bool Memorize); 257 258 FuncClass demangleFunctionClass(std::string_view &MangledName); 259 CallingConv demangleCallingConvention(std::string_view &MangledName); 260 StorageClass demangleVariableStorageClass(std::string_view &MangledName); 261 bool demangleThrowSpecification(std::string_view &MangledName); 262 wchar_t demangleWcharLiteral(std::string_view &MangledName); 263 uint8_t demangleCharLiteral(std::string_view &MangledName); 264 265 std::pair<Qualifiers, bool> demangleQualifiers(std::string_view &MangledName); 266 267 // Memory allocator. 268 ArenaAllocator Arena; 269 270 // A single type uses one global back-ref table for all function params. 271 // This means back-refs can even go "into" other types. Examples: 272 // 273 // // Second int* is a back-ref to first. 274 // void foo(int *, int*); 275 // 276 // // Second int* is not a back-ref to first (first is not a function param). 277 // int* foo(int*); 278 // 279 // // Second int* is a back-ref to first (ALL function types share the same 280 // // back-ref map. 281 // using F = void(*)(int*); 282 // F G(int *); 283 BackrefContext Backrefs; 284 }; 285 286 } // namespace ms_demangle 287 } // namespace llvm 288 289 #endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H 290