[Symbol] Search symbols with name and type in a symbol file

Summary:
This patch adds possibility of searching a public symbol with name and type in
a symbol file, not only in a symtab. It is helpful when working with PE, because
PE's symtabs contain only imported / exported symbols only. Such a search is
required for e.g. evaluation of an expression that calls some function of
the debuggee.

Reviewers: zturner, asmith, labath, clayborg, espindola

Reviewed By: clayborg

Subscribers: davide, emaste, arichardson, aleksandr.urakov, jingham,
             lldb-commits, stella.stamenova

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D53368

llvm-svn: 347960
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp
index 0705ac7..a4dc364 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -988,8 +988,10 @@
   if (module_sp) {
     ObjectFile *obj_file = module_sp->GetObjectFile();
     if (obj_file) {
-      // Give the symbol vendor a chance to add to the unified section list.
-      module_sp->GetSymbolVendor();
+      // Give the symbol vendor a chance to add to the unified section list
+      // and to symtab from symbol file
+      if (SymbolVendor *vendor = module_sp->GetSymbolVendor())
+        vendor->GetSymtab();
       return obj_file->GetAddressClass(GetFileAddress());
     }
   }
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 93ff6e2..da878a9 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1328,6 +1328,58 @@
     const std::string &scope_qualified_name,
     std::vector<lldb_private::ConstString> &mangled_names) {}
 
+void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) {
+  std::set<lldb::addr_t> sym_addresses;
+  for (size_t i = 0; i < symtab.GetNumSymbols(); i++)
+    sym_addresses.insert(symtab.SymbolAtIndex(i)->GetFileAddress());
+
+  auto results = m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>();
+  if (!results)
+    return;
+
+  auto section_list = m_obj_file->GetSectionList();
+  if (!section_list)
+    return;
+
+  while (auto pub_symbol = results->getNext()) {
+    auto section_idx = pub_symbol->getAddressSection() - 1;
+    if (section_idx >= section_list->GetSize())
+      continue;
+
+    auto section = section_list->GetSectionAtIndex(section_idx);
+    if (!section)
+      continue;
+
+    auto offset = pub_symbol->getAddressOffset();
+
+    auto file_addr = section->GetFileAddress() + offset;
+    if (sym_addresses.find(file_addr) != sym_addresses.end())
+      continue;
+    sym_addresses.insert(file_addr);
+
+    auto size = pub_symbol->getLength();
+    symtab.AddSymbol(
+        Symbol(pub_symbol->getSymIndexId(),   // symID
+               pub_symbol->getName().c_str(), // name
+               true,                          // name_is_mangled
+               pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type
+               true,      // external
+               false,     // is_debug
+               false,     // is_trampoline
+               false,     // is_artificial
+               section,   // section_sp
+               offset,    // value
+               size,      // size
+               size != 0, // size_is_valid
+               false,     // contains_linker_annotations
+               0          // flags
+               ));
+  }
+
+  symtab.CalculateSymbolSizes();
+  symtab.Finalize();
+}
+
 uint32_t SymbolFilePDB::FindTypes(
     const lldb_private::SymbolContext &sc,
     const lldb_private::ConstString &name,
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 12491e3..e4ca3b6 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -136,6 +136,8 @@
       const std::string &scope_qualified_name,
       std::vector<lldb_private::ConstString> &mangled_names) override;
 
+  void AddSymbols(lldb_private::Symtab &symtab) override;
+
   uint32_t
   FindTypes(const lldb_private::SymbolContext &sc,
             const lldb_private::ConstString &name,
diff --git a/lldb/source/Symbol/SymbolVendor.cpp b/lldb/source/Symbol/SymbolVendor.cpp
index e201b41..c0d1763 100644
--- a/lldb/source/Symbol/SymbolVendor.cpp
+++ b/lldb/source/Symbol/SymbolVendor.cpp
@@ -57,7 +57,7 @@
 //----------------------------------------------------------------------
 SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp)
     : ModuleChild(module_sp), m_type_list(), m_compile_units(),
-      m_sym_file_ap() {}
+      m_sym_file_ap(), m_symtab() {}
 
 //----------------------------------------------------------------------
 // Destructor
@@ -434,14 +434,23 @@
 
 Symtab *SymbolVendor::GetSymtab() {
   ModuleSP module_sp(GetModule());
-  if (module_sp) {
-    ObjectFile *objfile = module_sp->GetObjectFile();
-    if (objfile) {
-      // Get symbol table from unified section list.
-      return objfile->GetSymtab();
-    }
-  }
-  return nullptr;
+  if (!module_sp)
+    return nullptr;
+
+  std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+
+  if (m_symtab)
+    return m_symtab;
+
+  ObjectFile *objfile = module_sp->GetObjectFile();
+  if (!objfile)
+    return nullptr;
+
+  m_symtab = objfile->GetSymtab();
+  if (m_symtab && m_sym_file_ap)
+    m_sym_file_ap->AddSymbols(*m_symtab);
+
+  return m_symtab;
 }
 
 void SymbolVendor::ClearSymtab() {