1 //===-- PDBASTParser.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "PDBASTParser.h"
11 
12 #include "clang/AST/CharUnits.h"
13 #include "clang/AST/Decl.h"
14 #include "clang/AST/DeclCXX.h"
15 
16 #include "lldb/Symbol/ClangASTContext.h"
17 #include "lldb/Symbol/ClangUtil.h"
18 #include "lldb/Symbol/Declaration.h"
19 #include "lldb/Symbol/SymbolFile.h"
20 #include "lldb/Symbol/TypeSystem.h"
21 
22 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
26 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
27 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
28 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
29 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
30 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 using namespace llvm;
35 
36 namespace
37 {
38 int
39 TranslateUdtKind(PDB_UdtType pdb_kind)
40 {
41     switch (pdb_kind)
42     {
43         case PDB_UdtType::Class:
44             return clang::TTK_Class;
45         case PDB_UdtType::Struct:
46             return clang::TTK_Struct;
47         case PDB_UdtType::Union:
48             return clang::TTK_Union;
49         case PDB_UdtType::Interface:
50             return clang::TTK_Interface;
51     }
52     return clang::TTK_Class;
53 }
54 
55 lldb::Encoding
56 TranslateBuiltinEncoding(PDB_BuiltinType type)
57 {
58     switch (type)
59     {
60         case PDB_BuiltinType::Float:
61             return lldb::eEncodingIEEE754;
62         case PDB_BuiltinType::Int:
63         case PDB_BuiltinType::Long:
64         case PDB_BuiltinType::Char:
65             return lldb::eEncodingSint;
66         case PDB_BuiltinType::Bool:
67         case PDB_BuiltinType::UInt:
68         case PDB_BuiltinType::ULong:
69         case PDB_BuiltinType::HResult:
70             return lldb::eEncodingUint;
71         default:
72             return lldb::eEncodingInvalid;
73     }
74 }
75 }
76 
77 PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast)
78 {
79 }
80 
81 PDBASTParser::~PDBASTParser()
82 {
83 }
84 
85 // DebugInfoASTParser interface
86 
87 lldb::TypeSP
88 PDBASTParser::CreateLLDBTypeFromPDBType(const llvm::PDBSymbol &type)
89 {
90     // PDB doesn't maintain enough information to robustly rebuild the entire
91     // tree, and this is most problematic when it comes to figure out the
92     // right DeclContext to put a type in.  So for now, everything goes in
93     // the translation unit decl as a fully qualified type.
94     clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
95     Declaration decl;
96 
97     if (auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type))
98     {
99         AccessType access = lldb::eAccessPublic;
100         PDB_UdtType udt_kind = udt->getUdtKind();
101 
102         if (udt_kind == PDB_UdtType::Class)
103             access = lldb::eAccessPrivate;
104 
105         CompilerType clang_type =
106             m_ast.CreateRecordType(tu_decl_ctx, access, udt->getName().c_str(), TranslateUdtKind(udt_kind),
107                                    lldb::eLanguageTypeC_plus_plus, nullptr);
108 
109         m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
110 
111         return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(udt->getName()),
112                                       udt->getLength(), nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
113                                       clang_type, Type::eResolveStateForward);
114     }
115     else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type))
116     {
117         std::string name = enum_type->getName();
118         lldb::Encoding encoding = TranslateBuiltinEncoding(enum_type->getBuiltinType());
119         uint64_t bytes = enum_type->getLength();
120         CompilerType builtin_type = m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8);
121 
122         CompilerType ast_enum = m_ast.CreateEnumerationType(name.c_str(), tu_decl_ctx, decl, builtin_type);
123         auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
124         while (auto enum_value = enum_values->getNext())
125         {
126             if (enum_value->getDataKind() != PDB_DataKind::Constant)
127                 continue;
128             AddEnumValue(ast_enum, *enum_value);
129         }
130 
131         return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, nullptr,
132                                       LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ast_enum, Type::eResolveStateFull);
133     }
134     else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type))
135     {
136         Type *target_type = m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
137         std::string name = type_def->getName();
138         uint64_t bytes = type_def->getLength();
139         if (!target_type)
140             return nullptr;
141         CompilerType target_ast_type = target_type->GetFullCompilerType();
142         CompilerDeclContext target_decl_ctx = m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
143         CompilerType ast_typedef = m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
144         return std::make_shared<Type>(type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
145                                       nullptr, target_type->GetID(), Type::eEncodingIsTypedefUID, decl, ast_typedef,
146                                       Type::eResolveStateFull);
147     }
148     else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type))
149     {
150         auto arg_enum = func_sig->getArguments();
151         uint32_t num_args = arg_enum->getChildCount();
152         std::vector<CompilerType> arg_list(num_args);
153         while (auto arg = arg_enum->getNext())
154         {
155             Type *arg_type = m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
156             // If there's some error looking up one of the dependent types of this function signature, bail.
157             if (!arg_type)
158                 return nullptr;
159             CompilerType arg_ast_type = arg_type->GetFullCompilerType();
160             arg_list.push_back(arg_ast_type);
161         }
162         auto pdb_return_type = func_sig->getReturnType();
163         Type *return_type = m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
164         // If there's some error looking up one of the dependent types of this function signature, bail.
165         if (!return_type)
166             return nullptr;
167         CompilerType return_ast_type = return_type->GetFullCompilerType();
168         uint32_t type_quals = 0;
169         if (func_sig->isConstType())
170             type_quals |= clang::Qualifiers::Const;
171         if (func_sig->isVolatileType())
172             type_quals |= clang::Qualifiers::Volatile;
173         CompilerType func_sig_ast_type =
174             m_ast.CreateFunctionType(return_ast_type, &arg_list[0], num_args, false, type_quals);
175 
176         return std::make_shared<Type>(func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0, nullptr,
177                                       LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_sig_ast_type,
178                                       Type::eResolveStateFull);
179     }
180     else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type))
181     {
182         uint32_t num_elements = array_type->getCount();
183         uint32_t element_uid = array_type->getElementType()->getSymIndexId();
184         uint32_t bytes = array_type->getLength();
185 
186         Type *element_type = m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
187         CompilerType element_ast_type = element_type->GetFullCompilerType();
188         CompilerType array_ast_type = m_ast.CreateArrayType(element_ast_type, num_elements, false);
189         return std::make_shared<Type>(array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), bytes, nullptr,
190                                       LLDB_INVALID_UID, Type::eEncodingIsUID, decl, array_ast_type,
191                                       Type::eResolveStateFull);
192     }
193     return nullptr;
194 }
195 
196 bool
197 PDBASTParser::AddEnumValue(CompilerType enum_type, const llvm::PDBSymbolData &enum_value) const
198 {
199     Declaration decl;
200     Variant v = enum_value.getValue();
201     std::string name = enum_value.getName();
202     int64_t raw_value;
203     switch (v.Type)
204     {
205         case PDB_VariantType::Int8:
206             raw_value = v.Value.Int8;
207             break;
208         case PDB_VariantType::Int16:
209             raw_value = v.Value.Int16;
210             break;
211         case PDB_VariantType::Int32:
212             raw_value = v.Value.Int32;
213             break;
214         case PDB_VariantType::Int64:
215             raw_value = v.Value.Int64;
216             break;
217         case PDB_VariantType::UInt8:
218             raw_value = v.Value.UInt8;
219             break;
220         case PDB_VariantType::UInt16:
221             raw_value = v.Value.UInt16;
222             break;
223         case PDB_VariantType::UInt32:
224             raw_value = v.Value.UInt32;
225             break;
226         case PDB_VariantType::UInt64:
227             raw_value = v.Value.UInt64;
228             break;
229         default:
230             return false;
231     }
232     CompilerType underlying_type = m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
233     uint32_t byte_size = m_ast.getASTContext()->getTypeSize(ClangUtil::GetQualType(underlying_type));
234     return m_ast.AddEnumerationValueToEnumerationType(enum_type.GetOpaqueQualType(), underlying_type, decl,
235                                                       name.c_str(), raw_value, byte_size * 8);
236 }
237