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