aleksandr.urakov updated this revision to Diff 174916.
aleksandr.urakov added a comment.

Update the patch, move symtab finalization back to object files.

This patch makes object files and symbol files (in the case if they add symbols 
in a symtab) to be responsible for finalization of a symtab. It's because a 
symtab is used in a bunch of places, where it's undesirable to retrieve one 
through a symbol vendor. For example, when the object file itself uses its 
symtab, we can't retrieve it from the symbol vendor, because the symbol vendor 
is implemented in the terms of an object file, so such a solution will 
introduce a circular dependency, which is undesirable.

But on the other hand, if the object file uses its own symtab, then it likely 
doesn't rely on presence of symbols from the symbol file in that symtab. The 
only things it requires are symbols from the object file and finalization of 
the symtab.

So after this update we have the following guarantees:

- if a symtab is retrieved from an object file, then it's consistent and 
guaranteed contains symbols from the object file. It may (or may not) also 
contain symbols from a symbol file;
- if a symtab is retrieved from a symbol vendor, then it's consistent and 
guaranteed contains symbols from an object file and a symbol file.

I've taken a look at the places, where the symtab is retrieved from an object 
file, and it seems that the only place we need to fix due to that guarantees is 
the preventive usage of the symbol vendor in the `Address::GetAddressClass` 
function.

The disadvantages of the current solution are:

- when symbols are added in the symtab both from an object file and a symbol 
file, the symtab is finalized twice;
- the symtabs retrieved from different places have different guarantees.

But to solve these we need to make some other more higher-level entity (besides 
the object file) to own the symtab (e.g. symbol vendor) and to rewrite all the 
related things in object files and symbol files. The problem is that it's not 
trivial to make it and not to break a lot of current code.

What do you think about this approach?


https://reviews.llvm.org/D53368

Files:
  include/lldb/Symbol/SymbolFile.h
  include/lldb/Symbol/SymbolVendor.h
  source/Core/Address.cpp
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
  source/Symbol/SymbolVendor.cpp
  unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp

Index: unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
===================================================================
--- unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
+++ unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
@@ -620,3 +620,20 @@
   EXPECT_EQ(0u, num_results);
   EXPECT_EQ(0u, results.GetSize());
 }
+
+TEST_F(SymbolFilePDBTests, TestFindSymbolsWithNameAndType) {
+  FileSpec fspec(m_pdb_test_exe.c_str());
+  ArchSpec aspec("i686-pc-windows");
+  lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+  SymbolContextList sc_list;
+  EXPECT_EQ(1u,
+            module->FindSymbolsWithNameAndType(ConstString("?foo@@YAHH@Z"),
+                                               lldb::eSymbolTypeAny, sc_list));
+  EXPECT_EQ(1u, sc_list.GetSize());
+
+  SymbolContext sc;
+  EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
+  EXPECT_STREQ("int foo(int)",
+               sc.GetFunctionName(Mangled::ePreferDemangled).AsCString());
+}
Index: source/Symbol/SymbolVendor.cpp
===================================================================
--- source/Symbol/SymbolVendor.cpp
+++ 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() {
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ 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,
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ 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,
Index: source/Core/Address.cpp
===================================================================
--- source/Core/Address.cpp
+++ 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());
     }
   }
Index: include/lldb/Symbol/SymbolVendor.h
===================================================================
--- include/lldb/Symbol/SymbolVendor.h
+++ include/lldb/Symbol/SymbolVendor.h
@@ -165,6 +165,8 @@
                                    // file)
   std::unique_ptr<SymbolFile> m_sym_file_ap; // A single symbol file. Subclasses
                                              // can add more of these if needed.
+  Symtab *m_symtab; // Save a symtab once to not pass it through `AddSymbols` of
+                    // the symbol file each time when it is needed
 
 private:
   //------------------------------------------------------------------
Index: include/lldb/Symbol/SymbolFile.h
===================================================================
--- include/lldb/Symbol/SymbolFile.h
+++ include/lldb/Symbol/SymbolFile.h
@@ -233,6 +233,8 @@
     return {};
   }
 
+  virtual void AddSymbols(Symtab &symtab) {}
+
   //------------------------------------------------------------------
   /// Notify the SymbolFile that the file addresses in the Sections
   /// for this module have been changed.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to