1 //===-- PdbIndex.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 "PdbIndex.h" 11 #include "PdbUtil.h" 12 13 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 14 #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 15 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 16 #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" 17 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 18 #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" 19 #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" 20 #include "llvm/Object/COFF.h" 21 #include "llvm/Support/Error.h" 22 23 #include "lldb/Utility/LLDBAssert.h" 24 #include "lldb/lldb-defines.h" 25 26 using namespace lldb_private; 27 using namespace lldb_private::npdb; 28 using namespace llvm::codeview; 29 using namespace llvm::pdb; 30 31 PdbIndex::PdbIndex() : m_cus(*this), m_va_to_modi(m_allocator) {} 32 33 #define ASSIGN_PTR_OR_RETURN(result_ptr, expr) \ 34 { \ 35 auto expected_result = expr; \ 36 if (!expected_result) \ 37 return expected_result.takeError(); \ 38 result_ptr = &expected_result.get(); \ 39 } 40 41 llvm::Expected<std::unique_ptr<PdbIndex>> 42 PdbIndex::create(std::unique_ptr<llvm::pdb::PDBFile> file) { 43 lldbassert(file); 44 45 std::unique_ptr<PdbIndex> result(new PdbIndex()); 46 ASSIGN_PTR_OR_RETURN(result->m_dbi, file->getPDBDbiStream()); 47 ASSIGN_PTR_OR_RETURN(result->m_tpi, file->getPDBTpiStream()); 48 ASSIGN_PTR_OR_RETURN(result->m_ipi, file->getPDBIpiStream()); 49 ASSIGN_PTR_OR_RETURN(result->m_info, file->getPDBInfoStream()); 50 ASSIGN_PTR_OR_RETURN(result->m_publics, file->getPDBPublicsStream()); 51 ASSIGN_PTR_OR_RETURN(result->m_globals, file->getPDBGlobalsStream()); 52 ASSIGN_PTR_OR_RETURN(result->m_symrecords, file->getPDBSymbolStream()); 53 54 result->m_file = std::move(file); 55 56 return std::move(result); 57 } 58 59 lldb::addr_t PdbIndex::MakeVirtualAddress(uint16_t segment, 60 uint32_t offset) const { 61 // Segment indices are 1-based. 62 lldbassert(segment > 0); 63 64 uint32_t max_section = dbi().getSectionHeaders().size(); 65 lldbassert(segment <= max_section + 1); 66 67 // If this is an absolute symbol, it's indicated by the magic section index 68 // |max_section+1|. In this case, the offset is meaningless, so just return. 69 if (segment == max_section + 1) 70 return LLDB_INVALID_ADDRESS; 71 72 const llvm::object::coff_section &cs = dbi().getSectionHeaders()[segment - 1]; 73 return m_load_address + static_cast<lldb::addr_t>(cs.VirtualAddress) + 74 static_cast<lldb::addr_t>(offset); 75 } 76 77 lldb::addr_t PdbIndex::MakeVirtualAddress(const SegmentOffset &so) const { 78 return MakeVirtualAddress(so.segment, so.offset); 79 } 80 81 llvm::Optional<uint16_t> 82 PdbIndex::GetModuleIndexForAddr(uint16_t segment, uint32_t offset) const { 83 return GetModuleIndexForVa(MakeVirtualAddress(segment, offset)); 84 } 85 86 llvm::Optional<uint16_t> PdbIndex::GetModuleIndexForVa(lldb::addr_t va) const { 87 auto iter = m_va_to_modi.find(va); 88 if (iter == m_va_to_modi.end()) 89 return llvm::None; 90 91 return iter.value(); 92 } 93 94 void PdbIndex::ParseSectionContribs() { 95 class Visitor : public ISectionContribVisitor { 96 PdbIndex &m_ctx; 97 llvm::IntervalMap<uint64_t, uint16_t> &m_imap; 98 99 public: 100 Visitor(PdbIndex &ctx, llvm::IntervalMap<uint64_t, uint16_t> &imap) 101 : m_ctx(ctx), m_imap(imap) {} 102 103 void visit(const SectionContrib &C) override { 104 uint64_t va = m_ctx.MakeVirtualAddress(C.ISect, C.Off); 105 uint64_t end = va + C.Size; 106 // IntervalMap's start and end represent a closed range, not a half-open 107 // range, so we have to subtract 1. 108 m_imap.insert(va, end - 1, C.Imod); 109 } 110 void visit(const SectionContrib2 &C) override { visit(C.Base); } 111 }; 112 Visitor v(*this, m_va_to_modi); 113 dbi().visitSectionContributions(v); 114 } 115 116 void PdbIndex::BuildAddrToSymbolMap(CompilandIndexItem &cci) { 117 lldbassert(cci.m_symbols_by_va.empty() && 118 "Addr to symbol map is already built!"); 119 uint16_t modi = cci.m_uid.asCompiland().modi; 120 const CVSymbolArray &syms = cci.m_debug_stream.getSymbolArray(); 121 for (auto iter = syms.begin(); iter != syms.end(); ++iter) { 122 if (!SymbolHasAddress(*iter)) 123 continue; 124 125 SegmentOffset so = GetSegmentAndOffset(*iter); 126 lldb::addr_t va = MakeVirtualAddress(so); 127 128 // We need to add 4 here to adjust for the codeview debug magic 129 // at the beginning of the debug info stream. 130 uint32_t sym_offset = iter.offset() + 4; 131 PdbSymUid cu_sym_uid = 132 PdbSymUid::makeCuSymId(CVSymToPDBSym(iter->kind()), modi, sym_offset); 133 134 // If the debug info is incorrect, we could have multiple symbols with the 135 // same address. So use try_emplace instead of insert, and the first one 136 // will win. 137 auto emplace_result = cci.m_symbols_by_va.try_emplace(va, cu_sym_uid); 138 (void)emplace_result; 139 140 // The odds of an error in some function such as GetSegmentAndOffset or 141 // MakeVirtualAddress are much higher than the odds of encountering bad 142 // debug info, so assert that this item was inserted in the map as opposed 143 // to having already been there. 144 lldbassert(emplace_result.second); 145 } 146 } 147 148 std::vector<SymbolAndUid> PdbIndex::FindSymbolsByVa(lldb::addr_t va) { 149 std::vector<SymbolAndUid> result; 150 151 llvm::Optional<uint16_t> modi = GetModuleIndexForVa(va); 152 if (!modi) 153 return result; 154 155 CompilandIndexItem &cci = compilands().GetOrCreateCompiland(*modi); 156 if (cci.m_symbols_by_va.empty()) 157 BuildAddrToSymbolMap(cci); 158 159 // The map is sorted by starting address of the symbol. So for example 160 // we could (in theory) have this situation 161 // 162 // [------------------] 163 // [----------] 164 // [-----------] 165 // [-------------] 166 // [----] 167 // [-----] 168 // ^ Address we're searching for 169 // In order to find this, we use the upper_bound of the key value which would 170 // be the first symbol whose starting address is higher than the element we're 171 // searching for. 172 173 auto ub = cci.m_symbols_by_va.upper_bound(va); 174 175 for (auto iter = cci.m_symbols_by_va.begin(); iter != ub; ++iter) { 176 const PdbCuSymId &cu_sym_id = iter->second.asCuSym(); 177 CVSymbol sym = ReadSymbolRecord(cu_sym_id); 178 179 SegmentOffsetLength sol; 180 if (SymbolIsCode(sym)) 181 sol = GetSegmentOffsetAndLength(sym); 182 else 183 sol.so = GetSegmentAndOffset(sym); 184 185 lldb::addr_t start = MakeVirtualAddress(sol.so); 186 lldb::addr_t end = start + sol.length; 187 if (va >= start && va < end) 188 result.push_back({std::move(sym), iter->second}); 189 } 190 191 return result; 192 } 193 194 CVSymbol PdbIndex::ReadSymbolRecord(PdbCuSymId cu_sym) const { 195 // We need to subtract 4 here to adjust for the codeview debug magic 196 // at the beginning of the debug info stream. 197 PdbSymUid cuid = PdbSymUid::makeCompilandId(cu_sym.modi); 198 const CompilandIndexItem *cci = compilands().GetCompiland(cuid); 199 auto iter = cci->m_debug_stream.getSymbolArray().at(cu_sym.offset - 4); 200 lldbassert(iter != cci->m_debug_stream.getSymbolArray().end()); 201 return *iter; 202 } 203