[Lldb-commits] [lldb] r335822 - Retrieve a function PDB symbol correctly from nested blocks

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Thu Jun 28 03:03:42 PDT 2018


Author: labath
Date: Thu Jun 28 03:03:42 2018
New Revision: 335822

URL: http://llvm.org/viewvc/llvm-project?rev=335822&view=rev
Log:
Retrieve a function PDB symbol correctly from nested blocks

Summary:
This patch fixes a problem with retrieving a function symbol by an
address in a nested block. In the current implementation of
ResolveSymbolContext function it retrieves a symbol with
PDB_SymType::None and then checks if found symbol's tag equals to
PDB_SymType::Function. So, if nested block's symbol was found,
ResolveSymbolContext does not resolve a function.

Reviewers: asmith, labath, zturner

Reviewed By: asmith, labath

Differential Revision: https://reviews.llvm.org/D47939
Patch by Aleksandr Urakov <aleksandr.urakov at jetbrains.com>

Added:
    lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp
    lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test
Modified:
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
    lldb/trunk/tools/lldb-test/lldb-test.cpp

Added: lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp?rev=335822&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp (added)
+++ lldb/trunk/lit/SymbolFile/PDB/Inputs/FunctionNestedBlockTest.cpp Thu Jun 28 03:03:42 2018
@@ -0,0 +1,8 @@
+int main() {
+  auto r = 0;
+  for (auto i = 1; i <= 10; i++) {
+    r += i & 1 + (i - 1) & 1 - 1;
+  }
+
+  return r;
+}

Added: lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test?rev=335822&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test (added)
+++ lldb/trunk/lit/SymbolFile/PDB/function-nested-block.test Thu Jun 28 03:03:42 2018
@@ -0,0 +1,7 @@
+REQUIRES: windows, lld
+RUN: clang-cl /c /Zi %S/Inputs/FunctionNestedBlockTest.cpp /o %t.obj
+RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe
+RUN: lldb-test symbols -find=function -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck %s
+
+CHECK: Found 1 functions:
+CHECK: name = "{{.*}}", mangled = "_main"

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=335822&r1=335821&r2=335822&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp Thu Jun 28 03:03:42 2018
@@ -347,6 +347,11 @@ bool SymbolFilePDB::ParseCompileUnitSupp
     FileSpec spec(file->getFileName(), false, FileSpec::Style::windows);
     support_files.AppendIfUnique(spec);
   }
+
+  // LLDB uses the DWARF-like file numeration (one based),
+  // the zeroth file is the compile unit itself
+  support_files.Insert(0, *sc.comp_unit);
+
   return true;
 }
 
@@ -596,12 +601,6 @@ SymbolFilePDB::ResolveSymbolContext(cons
       resolve_scope & eSymbolContextFunction ||
       resolve_scope & eSymbolContextBlock ||
       resolve_scope & eSymbolContextLineEntry) {
-    addr_t file_vm_addr = so_addr.GetFileAddress();
-    auto symbol_up =
-        m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::None);
-    if (!symbol_up)
-      return 0;
-
     auto cu_sp = GetCompileUnitContainsAddress(so_addr);
     if (!cu_sp) {
       if (resolved_flags | eSymbolContextVariable) {
@@ -612,39 +611,39 @@ SymbolFilePDB::ResolveSymbolContext(cons
     sc.comp_unit = cu_sp.get();
     resolved_flags |= eSymbolContextCompUnit;
     lldbassert(sc.module_sp == cu_sp->GetModule());
+  }
 
-    switch (symbol_up->getSymTag()) {
-    case PDB_SymType::Function:
-      if (resolve_scope & eSymbolContextFunction) {
-        auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
-        assert(pdb_func);
-        auto func_uid = pdb_func->getSymIndexId();
-        sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
-        if (sc.function == nullptr)
-          sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
-        if (sc.function) {
-          resolved_flags |= eSymbolContextFunction;
-          if (resolve_scope & eSymbolContextBlock) {
-            Block &block = sc.function->GetBlock(true);
-            sc.block = block.FindBlockByID(sc.function->GetID());
-            if (sc.block)
-              resolved_flags |= eSymbolContextBlock;
-          }
+  if (resolve_scope & eSymbolContextFunction) {
+    addr_t file_vm_addr = so_addr.GetFileAddress();
+    auto symbol_up =
+        m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function);
+    if (symbol_up) {
+      auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
+      assert(pdb_func);
+      auto func_uid = pdb_func->getSymIndexId();
+      sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
+      if (sc.function == nullptr)
+        sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+      if (sc.function) {
+        resolved_flags |= eSymbolContextFunction;
+        if (resolve_scope & eSymbolContextBlock) {
+          Block &block = sc.function->GetBlock(true);
+          sc.block = block.FindBlockByID(sc.function->GetID());
+          if (sc.block)
+            resolved_flags |= eSymbolContextBlock;
         }
       }
-      break;
-    default:
-      break;
     }
+  }
 
-    if (resolve_scope & eSymbolContextLineEntry) {
-      if (auto *line_table = sc.comp_unit->GetLineTable()) {
-        Address addr(so_addr);
-        if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
-          resolved_flags |= eSymbolContextLineEntry;
-      }
+  if (resolve_scope & eSymbolContextLineEntry) {
+    if (auto *line_table = sc.comp_unit->GetLineTable()) {
+      Address addr(so_addr);
+      if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
+        resolved_flags |= eSymbolContextLineEntry;
     }
   }
+
   return resolved_flags;
 }
 
@@ -1631,7 +1630,9 @@ void SymbolFilePDB::BuildSupportFileIdTo
   auto source_files = m_session_up->getSourceFilesForCompiland(compiland);
   if (!source_files)
     return;
-  int index = 0;
+
+  // LLDB uses the DWARF-like file numeration (one based)
+  int index = 1;
 
   while (auto file = source_files->getNext()) {
     uint32_t source_id = file->getUniqueId();

Modified: lldb/trunk/tools/lldb-test/lldb-test.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-test/lldb-test.cpp?rev=335822&r1=335821&r2=335822&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-test/lldb-test.cpp (original)
+++ lldb/trunk/tools/lldb-test/lldb-test.cpp Thu Jun 28 03:03:42 2018
@@ -35,8 +35,8 @@
 #include "llvm/ADT/IntervalMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Signals.h"
@@ -108,8 +108,7 @@ enum class FindType {
 static cl::opt<FindType> Find(
     "find", cl::desc("Choose search type:"),
     cl::values(
-        clEnumValN(FindType::None, "none",
-                   "No search, just dump the module."),
+        clEnumValN(FindType::None, "none", "No search, just dump the module."),
         clEnumValN(FindType::Function, "function", "Find functions."),
         clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
         clEnumValN(FindType::Type, "type", "Find types."),
@@ -151,6 +150,8 @@ static cl::opt<bool> Verify("verify", cl
 static cl::opt<std::string> File("file",
                                  cl::desc("File (compile unit) to search."),
                                  cl::sub(SymbolsSubcommand));
+static cl::opt<int> Line("line", cl::desc("Line to search."),
+                         cl::sub(SymbolsSubcommand));
 
 static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
 
@@ -163,7 +164,7 @@ static Error verify(lldb_private::Module
 
 static Expected<Error (*)(lldb_private::Module &)> getAction();
 static int dumpSymbols(Debugger &Dbg);
-}
+} // namespace symbols
 
 namespace irmemorymap {
 static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"),
@@ -179,7 +180,7 @@ static cl::opt<bool> UseHostOnlyAllocati
 
 using AllocationT = std::pair<addr_t, addr_t>;
 using AddrIntervalMap =
-      IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
+    IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>;
 
 struct IRMemoryMapTestState {
   TargetSP Target;
@@ -334,7 +335,32 @@ opts::symbols::getDeclContext(SymbolVend
 Error opts::symbols::findFunctions(lldb_private::Module &Module) {
   SymbolVendor &Vendor = *Module.GetSymbolVendor();
   SymbolContextList List;
-  if (Regex) {
+  if (!File.empty()) {
+    assert(Line != 0);
+
+    FileSpec src_file(File, false);
+    size_t cu_count = Module.GetNumCompileUnits();
+    for (size_t i = 0; i < cu_count; i++) {
+      lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
+      if (!cu_sp)
+        continue;
+
+      LineEntry le;
+      cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
+      if (!le.IsValid())
+        continue;
+
+      auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
+      if (!addr.IsValid())
+        continue;
+
+      SymbolContext sc;
+      uint32_t resolved =
+          addr.CalculateSymbolContext(&sc, eSymbolContextFunction);
+      if (resolved & eSymbolContextFunction)
+        List.Append(sc);
+    }
+  } else if (Regex) {
     RegularExpression RE(Name);
     assert(RE.IsValid());
     Vendor.FindFunctions(RE, true, false, List);
@@ -346,7 +372,7 @@ Error opts::symbols::findFunctions(lldb_
         ContextOr->IsValid() ? &*ContextOr : nullptr;
 
     Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
-                          true, false, List);
+                         true, false, List);
   }
   outs() << formatv("Found {0} functions:\n", List.GetSize());
   StreamString Stream;
@@ -386,7 +412,7 @@ Error opts::symbols::findTypes(lldb_priv
   DenseSet<SymbolFile *> SearchedFiles;
   TypeMap Map;
   Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
-                    SearchedFiles, Map);
+                   SearchedFiles, Map);
 
   outs() << formatv("Found {0} types:\n", Map.GetSize());
   StreamString Stream;
@@ -458,8 +484,8 @@ Error opts::symbols::verify(lldb_private
     if (!comp_unit)
       return make_string_error("Connot parse compile unit {0}.", i);
 
-    outs() << "Processing '" << comp_unit->GetFilename().AsCString() <<
-      "' compile unit.\n";
+    outs() << "Processing '" << comp_unit->GetFilename().AsCString()
+           << "' compile unit.\n";
 
     LineTable *lt = comp_unit->GetLineTable();
     if (!lt)
@@ -478,7 +504,7 @@ Error opts::symbols::verify(lldb_private
 
     for (uint32_t i = 1; i < count; i++) {
       lldb::addr_t curr_end =
-        le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
+          le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
 
       if (!lt->GetLineEntryAtIndex(i, le))
         return make_string_error("Can't get a line entry of a compile unit");
@@ -499,9 +525,11 @@ Expected<Error (*)(lldb_private::Module
     if (Find != FindType::None)
       return make_string_error(
           "Cannot both search and verify symbol information.");
-    if (Regex || !Context.empty() || !Name.empty() || !File.empty())
-      return make_string_error("-regex, -context, -name and -file options are not "
-                               "applicable for symbol verification.");
+    if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
+        Line != 0)
+      return make_string_error(
+          "-regex, -context, -name, -file and -line options are not "
+          "applicable for symbol verification.");
     return verify;
   }
 
@@ -520,32 +548,38 @@ Expected<Error (*)(lldb_private::Module
 
   switch (Find) {
   case FindType::None:
-    if (!Context.empty() || !Name.empty() || !File.empty())
+    if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0)
       return make_string_error(
           "Specify search type (-find) to use search options.");
     return dumpModule;
 
   case FindType::Function:
-    if (!File.empty())
-      return make_string_error("Cannot search for functions by file name.");
-    if (Regex && getFunctionNameFlags() != 0)
-      return make_string_error("Cannot search for functions using both regular "
-                               "expressions and function-flags.");
+    if (!File.empty() + (Line != 0) == 1)
+      return make_string_error("Both file name and line number must be "
+                               "specified when searching a function "
+                               "by file position.");
+    if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2)
+      return make_string_error("Only one of regular expression, function-flags "
+                               "and file position may be used simultaneously "
+                               "when searching a function.");
     return findFunctions;
 
   case FindType::Namespace:
-    if (Regex || !File.empty())
+    if (Regex || !File.empty() || Line != 0)
       return make_string_error("Cannot search for namespaces using regular "
-                               "expressions or file names.");
+                               "expressions, file names or line numbers.");
     return findNamespaces;
 
   case FindType::Type:
-    if (Regex || !File.empty())
+    if (Regex || !File.empty() || Line != 0)
       return make_string_error("Cannot search for types using regular "
-                               "expressions or file names.");
+                               "expressions, file names or line numbers.");
     return findTypes;
 
   case FindType::Variable:
+    if (Line != 0)
+      return make_string_error("Cannot search for variables "
+                               "using line numbers.");
     return findVariables;
   }
 }




More information about the lldb-commits mailing list