diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp | 180 |
1 files changed, 168 insertions, 12 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index fdc93304806..77b99ef4153 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamBuffer.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" @@ -24,6 +25,8 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" @@ -887,6 +890,131 @@ TypeSP SymbolFileNativePDB::GetOrCreateType(PdbSymUid type_uid) { return CreateAndCacheType(type_uid); } +static DWARFExpression MakeGlobalLocationExpression(uint16_t section, + uint32_t offset, + ModuleSP module) { + assert(section > 0); + assert(module); + + const ArchSpec &architecture = module->GetArchitecture(); + ByteOrder byte_order = architecture.GetByteOrder(); + uint32_t address_size = architecture.GetAddressByteSize(); + uint32_t byte_size = architecture.GetDataByteSize(); + assert(byte_order != eByteOrderInvalid && address_size != 0); + + RegisterKind register_kind = eRegisterKindDWARF; + StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); + stream.PutHex8(DW_OP_addr); + + SectionList *section_list = module->GetSectionList(); + assert(section_list); + + // Section indices in PDB are 1-based, but in DWARF they are 0-based, so we + // need to subtract 1. + uint32_t section_idx = section - 1; + if (section_idx >= section_list->GetSize()) + return DWARFExpression(nullptr); + + auto section_ptr = section_list->GetSectionAtIndex(section_idx); + if (!section_ptr) + return DWARFExpression(nullptr); + + stream.PutMaxHex64(section_ptr->GetFileAddress() + offset, address_size, + byte_order); + DataBufferSP buffer = + std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); + DataExtractor extractor(buffer, byte_order, address_size, byte_size); + DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); + result.SetRegisterKind(register_kind); + return result; +} + +VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbSymUid var_uid) { + const PdbCuSymId &cu_sym = var_uid.asCuSym(); + lldbassert(cu_sym.global); + CVSymbol sym = m_index->symrecords().readRecord(cu_sym.offset); + lldb::ValueType scope = eValueTypeInvalid; + TypeIndex ti; + llvm::StringRef name; + lldb::addr_t addr = 0; + uint16_t section = 0; + uint32_t offset = 0; + bool is_external = false; + switch (sym.kind()) { + case S_GDATA32: + is_external = true; + LLVM_FALLTHROUGH; + case S_LDATA32: { + DataSym ds(sym.kind()); + llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds)); + ti = ds.Type; + scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal + : eValueTypeVariableStatic; + name = ds.Name; + section = ds.Segment; + offset = ds.DataOffset; + addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset); + break; + } + case S_GTHREAD32: + is_external = true; + LLVM_FALLTHROUGH; + case S_LTHREAD32: { + ThreadLocalDataSym tlds(sym.kind()); + llvm::cantFail( + SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds)); + ti = tlds.Type; + name = tlds.Name; + section = tlds.Segment; + offset = tlds.DataOffset; + addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset); + scope = eValueTypeVariableThreadLocal; + break; + } + default: + llvm_unreachable("unreachable!"); + } + + CompUnitSP comp_unit; + llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); + if (modi) { + PdbSymUid cuid = PdbSymUid::makeCompilandId(*modi); + CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(cuid); + comp_unit = GetOrCreateCompileUnit(cci); + } + + Declaration decl; + PDB_SymType pdbst = GetPdbSymType(m_index->tpi(), ti); + PdbSymUid tuid = PdbSymUid::makeTypeSymId(pdbst, ti, false); + SymbolFileTypeSP type_sp = + std::make_shared<SymbolFileType>(*this, tuid.toOpaqueId()); + Variable::RangeList ranges; + + DWARFExpression location = MakeGlobalLocationExpression( + section, offset, GetObjectFile()->GetModule()); + + std::string global_name("::"); + global_name += name; + VariableSP var_sp = std::make_shared<Variable>( + var_uid.toOpaqueId(), name.str().c_str(), global_name.c_str(), type_sp, + scope, comp_unit.get(), ranges, &decl, location, is_external, false, + false); + var_sp->SetLocationIsConstantValueData(false); + + return var_sp; +} + +VariableSP SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbSymUid var_uid) { + lldbassert(var_uid.isGlobalVariable()); + + auto emplace_result = + m_global_vars.try_emplace(var_uid.toOpaqueId(), nullptr); + if (emplace_result.second) + emplace_result.first->second = CreateGlobalVariable(var_uid); + + return emplace_result.first->second; +} + lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(llvm::codeview::TypeIndex ti) { PDB_SymType pdbst = GetPdbSymType(m_index->tpi(), ti); @@ -1146,6 +1274,32 @@ size_t SymbolFileNativePDB::ParseFunctionBlocks(const SymbolContext &sc) { return 0; } +uint32_t SymbolFileNativePDB::FindGlobalVariables( + const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, VariableList &variables) { + using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; + + std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName( + name.GetStringRef(), m_index->symrecords()); + for (const SymbolAndOffset &result : results) { + VariableSP var; + switch (result.second.kind()) { + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: + case SymbolKind::S_GTHREAD32: + case SymbolKind::S_LTHREAD32: { + PdbSymUid uid = PdbSymUid::makeGlobalVariableUid(result.first); + var = GetOrCreateGlobalVariable(uid); + variables.AddVariable(var); + break; + } + default: + continue; + } + } + return variables.GetSize(); +} + uint32_t SymbolFileNativePDB::FindFunctions( const ConstString &name, const CompilerDeclContext *parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, bool append, @@ -1239,19 +1393,21 @@ Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { auto iter = m_types.find(type_uid); // lldb should not be passing us non-sensical type uids. the only way it // could have a type uid in the first place is if we handed it out, in which - // case we should know about the type. So this is not a get-or-create type - // operation, it is strictly a get, and the type is guaranteed to exist. - // - // However, since the implementation is not yet complete, we don't currently - // support all possible use cases. For example, we currently create all - // functions with indices of 0 for the signature type simply because this is - // not yet implemented. At the time the function object is created we should - // be creating an lldb::TypeSP for this, adding it to the m_types, and - // returning a valid Type object for it and putting it in this map. Once all - // cases like this are handled, we can promote this to an assert. - if (iter == m_types.end()) + // case we should know about the type. However, that doesn't mean we've + // instantiated it yet. We can vend out a UID for a future type. So if the + // type doesn't exist, let's instantiate it now. + if (iter != m_types.end()) + return &*iter->second; + + PdbSymUid uid = PdbSymUid::fromOpaqueId(type_uid); + lldbassert(uid.isTypeSym(uid.tag())); + const PdbTypeSymId &type_id = uid.asTypeSym(); + TypeIndex ti(type_id.index); + if (ti.isNoneType()) return nullptr; - return &*iter->second; + + TypeSP type_sp = CreateAndCacheType(uid); + return &*type_sp; } bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { |

