|
39 | 39 | #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
|
40 | 40 | #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
|
41 | 41 | #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
| 42 | +#include "llvm/DebugInfo/PDB/Native/PublicsStream.h" |
42 | 43 | #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
|
43 | 44 | #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
44 | 45 | #include "llvm/DebugInfo/PDB/PDB.h"
|
@@ -1641,6 +1642,94 @@ void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) {
|
1641 | 1642 | clang->GetNativePDBParser()->Dump(s, filter);
|
1642 | 1643 | }
|
1643 | 1644 |
|
| 1645 | +void SymbolFileNativePDB::CacheFunctionNames() { |
| 1646 | + if (!m_func_full_names.IsEmpty()) |
| 1647 | + return; |
| 1648 | + |
| 1649 | + // (segment, code offset) -> gid |
| 1650 | + std::map<std::pair<uint16_t, uint32_t>, uint32_t> addr_ids; |
| 1651 | + |
| 1652 | + // First, find all function references in the globals table. |
| 1653 | + for (const uint32_t gid : m_index->globals().getGlobalsTable()) { |
| 1654 | + CVSymbol ref_sym = m_index->symrecords().readRecord(gid); |
| 1655 | + auto kind = ref_sym.kind(); |
| 1656 | + if (kind != S_PROCREF && kind != S_LPROCREF) |
| 1657 | + continue; |
| 1658 | + |
| 1659 | + ProcRefSym ref = |
| 1660 | + llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(ref_sym)); |
| 1661 | + if (ref.Name.empty()) |
| 1662 | + continue; |
| 1663 | + |
| 1664 | + // Find the function this is referencing. |
| 1665 | + CompilandIndexItem &cci = |
| 1666 | + m_index->compilands().GetOrCreateCompiland(ref.modi()); |
| 1667 | + auto iter = cci.m_debug_stream.getSymbolArray().at(ref.SymOffset); |
| 1668 | + if (iter == cci.m_debug_stream.getSymbolArray().end()) |
| 1669 | + continue; |
| 1670 | + kind = iter->kind(); |
| 1671 | + if (kind != S_GPROC32 && kind != S_LPROC32) |
| 1672 | + continue; |
| 1673 | + |
| 1674 | + ProcSym proc = |
| 1675 | + llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*iter)); |
| 1676 | + if ((proc.Flags & ProcSymFlags::IsUnreachable) != ProcSymFlags::None) |
| 1677 | + continue; |
| 1678 | + if (proc.Name.empty()) |
| 1679 | + continue; |
| 1680 | + |
| 1681 | + // The function/procedure symbol only contains the demangled name. |
| 1682 | + // The mangled names are in the publics table. Save the address of this |
| 1683 | + // function to lookup the mangled name later. |
| 1684 | + addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid); |
| 1685 | + |
| 1686 | + llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name); |
| 1687 | + if (basename.empty()) |
| 1688 | + basename = proc.Name; |
| 1689 | + |
| 1690 | + m_func_base_names.Append(ConstString(basename), gid); |
| 1691 | + m_func_full_names.Append(ConstString(proc.Name), gid); |
| 1692 | + |
| 1693 | + // To see if this is a member function, check the type. |
| 1694 | + auto type = m_index->tpi().getType(proc.FunctionType); |
| 1695 | + if (type.kind() == LF_MFUNCTION) { |
| 1696 | + MemberFunctionRecord mfr; |
| 1697 | + llvm::cantFail( |
| 1698 | + TypeDeserializer::deserializeAs<MemberFunctionRecord>(type, mfr)); |
| 1699 | + if (!mfr.getThisType().isNoneType()) |
| 1700 | + m_func_method_names.Append(ConstString(basename), gid); |
| 1701 | + } |
| 1702 | + } |
| 1703 | + |
| 1704 | + // The publics stream contains all mangled function names and their address. |
| 1705 | + for (auto pid : m_index->publics().getPublicsTable()) { |
| 1706 | + PdbGlobalSymId global{pid, true}; |
| 1707 | + CVSymbol sym = m_index->ReadSymbolRecord(global); |
| 1708 | + auto kind = sym.kind(); |
| 1709 | + if (kind != S_PUB32) |
| 1710 | + continue; |
| 1711 | + PublicSym32 pub = |
| 1712 | + llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym)); |
| 1713 | + // We only care about mangled names - if the name isn't mangled, it's |
| 1714 | + // already in the full name map. |
| 1715 | + if (!Mangled::IsMangledName(pub.Name)) |
| 1716 | + continue; |
| 1717 | + |
| 1718 | + // Check if this symbol is for one of our functions. |
| 1719 | + auto it = addr_ids.find({pub.Segment, pub.Offset}); |
| 1720 | + if (it != addr_ids.end()) |
| 1721 | + m_func_full_names.Append(ConstString(pub.Name), it->second); |
| 1722 | + } |
| 1723 | + |
| 1724 | + // Sort them before value searching is working properly. |
| 1725 | + m_func_full_names.Sort(); |
| 1726 | + m_func_full_names.SizeToFit(); |
| 1727 | + m_func_method_names.Sort(); |
| 1728 | + m_func_method_names.SizeToFit(); |
| 1729 | + m_func_base_names.Sort(); |
| 1730 | + m_func_base_names.SizeToFit(); |
| 1731 | +} |
| 1732 | + |
1644 | 1733 | void SymbolFileNativePDB::FindGlobalVariables(
|
1645 | 1734 | ConstString name, const CompilerDeclContext &parent_decl_ctx,
|
1646 | 1735 | uint32_t max_matches, VariableList &variables) {
|
@@ -1677,34 +1766,60 @@ void SymbolFileNativePDB::FindFunctions(
|
1677 | 1766 | if (name_type_mask & eFunctionNameTypeFull)
|
1678 | 1767 | name = lookup_info.GetName();
|
1679 | 1768 |
|
1680 |
| - // For now we only support lookup by method name or full name. |
1681 | 1769 | if (!(name_type_mask & eFunctionNameTypeFull ||
|
| 1770 | + name_type_mask & eFunctionNameTypeBase || |
1682 | 1771 | name_type_mask & eFunctionNameTypeMethod))
|
1683 | 1772 | return;
|
| 1773 | + CacheFunctionNames(); |
1684 | 1774 |
|
1685 |
| - using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; |
| 1775 | + std::set<uint32_t> resolved_ids; // avoid duplicate lookups |
| 1776 | + auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) { |
| 1777 | + std::vector<uint32_t> ids; |
| 1778 | + if (!Names.GetValues(name, ids)) |
| 1779 | + return; |
1686 | 1780 |
|
1687 |
| - std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName( |
1688 |
| - name.GetStringRef(), m_index->symrecords()); |
1689 |
| - for (const SymbolAndOffset &match : matches) { |
1690 |
| - if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF) |
1691 |
| - continue; |
1692 |
| - ProcRefSym proc(match.second.kind()); |
1693 |
| - cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc)); |
| 1781 | + for (uint32_t id : ids) { |
| 1782 | + if (!resolved_ids.insert(id).second) |
| 1783 | + continue; |
1694 | 1784 |
|
1695 |
| - if (!IsValidRecord(proc)) |
1696 |
| - continue; |
| 1785 | + PdbGlobalSymId global{id, false}; |
| 1786 | + if (parent_decl_ctx.IsValid() && |
| 1787 | + GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx) |
| 1788 | + continue; |
1697 | 1789 |
|
1698 |
| - CompilandIndexItem &cci = |
1699 |
| - m_index->compilands().GetOrCreateCompiland(proc.modi()); |
1700 |
| - SymbolContext sc; |
| 1790 | + CVSymbol sym = m_index->ReadSymbolRecord(global); |
| 1791 | + auto kind = sym.kind(); |
| 1792 | + lldbassert(kind == S_PROCREF || kind == S_LPROCREF); |
1701 | 1793 |
|
1702 |
| - sc.comp_unit = GetOrCreateCompileUnit(cci).get(); |
1703 |
| - PdbCompilandSymId func_id(proc.modi(), proc.SymOffset); |
1704 |
| - sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get(); |
| 1794 | + ProcRefSym proc = |
| 1795 | + cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym)); |
1705 | 1796 |
|
1706 |
| - sc_list.Append(sc); |
1707 |
| - } |
| 1797 | + if (!IsValidRecord(proc)) |
| 1798 | + continue; |
| 1799 | + |
| 1800 | + CompilandIndexItem &cci = |
| 1801 | + m_index->compilands().GetOrCreateCompiland(proc.modi()); |
| 1802 | + SymbolContext sc; |
| 1803 | + |
| 1804 | + sc.comp_unit = GetOrCreateCompileUnit(cci).get(); |
| 1805 | + if (!sc.comp_unit) |
| 1806 | + continue; |
| 1807 | + |
| 1808 | + PdbCompilandSymId func_id(proc.modi(), proc.SymOffset); |
| 1809 | + sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get(); |
| 1810 | + if (!sc.function) |
| 1811 | + continue; |
| 1812 | + |
| 1813 | + sc_list.Append(sc); |
| 1814 | + } |
| 1815 | + }; |
| 1816 | + |
| 1817 | + if (name_type_mask & eFunctionNameTypeFull) |
| 1818 | + resolve_from(m_func_full_names); |
| 1819 | + if (name_type_mask & eFunctionNameTypeBase) |
| 1820 | + resolve_from(m_func_base_names); |
| 1821 | + if (name_type_mask & eFunctionNameTypeMethod) |
| 1822 | + resolve_from(m_func_method_names); |
1708 | 1823 | }
|
1709 | 1824 |
|
1710 | 1825 | void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex,
|
|
0 commit comments