This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL333049: [SymbolFilePDB] Add support for resolving variable 
symbols (authored by asmith, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D45224?vs=140842&id=148144#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D45224

Files:
  lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesTest.cpp
  lldb/trunk/lit/SymbolFile/PDB/variables.test
  lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
  lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h

Index: lldb/trunk/lit/SymbolFile/PDB/variables.test
===================================================================
--- lldb/trunk/lit/SymbolFile/PDB/variables.test
+++ lldb/trunk/lit/SymbolFile/PDB/variables.test
@@ -0,0 +1,58 @@
+REQUIRES: windows
+RUN: clang-cl /Z7 /c %S/Inputs/VariablesTest.cpp /o %T/VariablesTest.cpp.obj
+RUN: link %T/VariablesTest.cpp.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/VariablesTest.cpp.exe
+RUN: lldb-test symbols %T/VariablesTest.cpp.exe | FileCheck %s
+
+CHECK: Module [[MOD:.*]]
+CHECK: SymbolVendor ([[MOD]])
+CHECK:     CompileUnit{{.*}}, language = "c++", file = '{{.*}}\VariablesTest.cpp'
+CHECK-DAG:   Variable{{.*}}, name = "g_IntVar"
+CHECK-SAME:  scope = global, external
+CHECK-DAG:   Variable{{.*}}, name = "m_StaticClassMember"
+CHECK-SAME:  scope = global, external
+CHECK-DAG:   Variable{{.*}}, name = "g_pConst"
+CHECK-SAME:  scope = global, external
+CHECK-DAG:   Variable{{.*}}, name = "same_name_var"
+CHECK-SAME:  scope = global, external
+CHECK-DAG:   Variable{{.*}}, name = "g_EnumVar"
+CHECK-SAME:  scope = global, external
+CHECK-DAG:   Variable{{.*}}, name = "g_tls"
+CHECK-SAME:  scope = thread local, external
+CHECK-DAG:   Variable{{.*}}, name = "ClassVar"
+CHECK-SAME:  scope = global, external
+CHECK-DAG:   Variable{{.*}}, name = "g_Const"
+CHECK-SAME:  scope = ??? (2)
+
+CHECK-DAG:   Function{[[FID1:.*]]}, mangled = ?f@@YAHHH@Z
+CHECK-NEXT:  Block{[[FID1]]}
+CHECK-DAG:     Variable{{.*}}, name = "var_arg1"
+CHECK-SAME:    scope = parameter
+CHECK-DAG:     Variable{{.*}}, name = "var_arg2"
+CHECK-SAME:    scope = parameter
+CHECK-DAG:     Variable{{.*}}, name = "same_name_var"
+CHECK-SAME:    scope = local
+
+CHECK-DAG:   Function{[[FID2:.*]]}, mangled = main
+CHECK-NEXT:  Block{[[FID2]]}
+CHECK-DAG:     Variable{{.*}}, name = "same_name_var"
+CHECK-SAME:    scope = local
+CHECK-DAG:     Variable{{.*}}, name = "local_const"
+CHECK-SAME:    scope = local
+CHECK-DAG:     Variable{{.*}}, name = "local_pCString"
+CHECK-SAME:    scope = local
+CHECK-DAG:     Variable{{.*}}, name = "a"
+CHECK-SAME:    scope = local
+
+CHECK-DAG:   Function{[[FID3:.*]]}, mangled = ??0Class@@QEAA@H@Z
+CHECK-NEXT:  Block{[[FID3]]}
+CHECK-DAG:     Variable{{.*}}, name = "this"
+CHECK-SAME:    scope = parameter
+CHECK-SAME:    artificial
+CHECK-DAG:     Variable{{.*}}, name = "a"
+CHECK-SAME:    scope = parameter
+
+CHECK-DAG:   Function{[[FID4:.*]]}, mangled = ?Func@Class@@QEAAXXZ
+CHECK-NEXT:  Block{[[FID4]]}
+CHECK-DAG:     Variable{{.*}}, name = "this"
+CHECK-SAME:    scope = parameter
+CHECK-SAME:    artificial
\ No newline at end of file
Index: lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesTest.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesTest.cpp
+++ lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesTest.cpp
@@ -0,0 +1,50 @@
+typedef int IntTypedef;
+IntTypedef g_IntVar;  // Testing globals.
+
+typedef enum Enum { // Testing constants.
+  RED,
+  GREEN,
+  BLUE
+} EnumTypedef;
+EnumTypedef g_EnumVar;  // Testing members.
+
+// FIXME: `sg_IntVar` appears both in global scope's children and compiland's
+// children but with different symbol's id.
+static int sg_IntVar = -1;  // Testing file statics.
+
+// FIXME: `g_Const` appears both in global scope's children and compiland's
+// children but with different symbol's id.
+const int g_Const = 0x88;  // Testing constant data.
+const int *g_pConst = &g_Const; // Avoid optimizing the const away
+
+thread_local int g_tls = 0;  // Testing thread-local storage.
+
+class Class {
+  static int m_StaticClassMember;
+public:
+  explicit Class(int a) {}
+  void Func() {}
+};
+int Class::m_StaticClassMember = 10; // Testing static class members.
+Class ClassVar(1);
+
+int f(int var_arg1, int var_arg2) {  // Testing parameters.
+  long same_name_var = -1;
+  return 1;
+}
+
+int same_name_var = 100;
+int main() {
+  int same_name_var = 0;  // Testing locals.
+  const char local_const = 0x1;
+
+  // FIXME: 'local_CString` is not found through compiland's children.
+  const char local_CString[] = "abc";  // Testing constant string.
+  const char *local_pCString = local_CString; // Avoid optimizing the const away
+
+  int a = 10;
+  a++;
+
+  ClassVar.Func();
+  return 0;
+}
Index: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -12,6 +12,7 @@
 
 #include "lldb/Core/UniqueCStringMap.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/VariableList.h"
 #include "lldb/Utility/UserID.h"
 
 #include "llvm/ADT/DenseMap.h"
@@ -181,6 +182,16 @@
   void FindTypesByName(const std::string &name, uint32_t max_matches,
                        lldb_private::TypeMap &types);
 
+  std::string GetMangledForPDBData(const llvm::pdb::PDBSymbolData &pdb_data);
+
+  lldb::VariableSP
+  ParseVariableForPDBData(const lldb_private::SymbolContext &sc,
+                          const llvm::pdb::PDBSymbolData &pdb_data);
+
+  size_t ParseVariables(const lldb_private::SymbolContext &sc,
+                        const llvm::pdb::PDBSymbol &pdb_data,
+                        lldb_private::VariableList *variable_list = nullptr);
+
   lldb::CompUnitSP
   GetCompileUnitContainsAddress(const lldb_private::Address &so_addr);
 
@@ -217,6 +228,7 @@
 
   llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units;
   llvm::DenseMap<uint32_t, lldb::TypeSP> m_types;
+  llvm::DenseMap<uint32_t, lldb::VariableSP> m_variables;
 
   std::vector<lldb::TypeSP> m_builtin_types;
   std::unique_ptr<llvm::pdb::IPDBSession> m_session_up;
Index: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -21,6 +21,7 @@
 #include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Symbol/TypeList.h"
 #include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/Variable.h"
 #include "lldb/Utility/RegularExpression.h"
 
 #include "llvm/DebugInfo/PDB/GenericError.h"
@@ -483,8 +484,51 @@
 
 size_t
 SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
-  // TODO: Implement this
-  return size_t();
+  if (!sc.comp_unit)
+    return 0;
+
+  size_t num_added = 0;
+  if (sc.function) {
+    auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
+        sc.function->GetID());
+    if (!pdb_func)
+      return 0;
+
+    num_added += ParseVariables(sc, *pdb_func);
+    sc.function->GetBlock(false).SetDidParseVariables(true, true);
+  } else if (sc.comp_unit) {
+    auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
+    if (!compiland)
+      return 0;
+
+    if (sc.comp_unit->GetVariableList(false))
+      return 0;
+
+    auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
+    if (results && results->getChildCount()) {
+      while (auto result = results->getNext()) {
+        auto cu_id = result->getCompilandId();
+        // FIXME: We are not able to determine variable's compile unit.
+        if (cu_id == 0)
+          continue;
+
+        if (cu_id == sc.comp_unit->GetID())
+          num_added += ParseVariables(sc, *result);
+      }
+    }
+
+    // FIXME: A `file static` or `global constant` variable appears both in
+    // compiland's children and global scope's children with unexpectedly
+    // different symbol's Id making it ambiguous.
+
+    // FIXME: 'local constant', for example, const char var[] = "abc", declared
+    // in a function scope, can't be found in PDB.
+
+    // Parse variables in this compiland.
+    num_added += ParseVariables(sc, *compiland);
+  }
+
+  return num_added;
 }
 
 lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -714,18 +758,270 @@
   return sc_list.GetSize() - old_size;
 }
 
+std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) {
+  std::string decorated_name;
+  auto vm_addr = pdb_data.getVirtualAddress();
+  if (vm_addr != LLDB_INVALID_ADDRESS && vm_addr) {
+    auto result_up =
+        m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol);
+    if (result_up) {
+      while (auto symbol_up = result_up->getNext()) {
+        if (symbol_up->getRawSymbol().getVirtualAddress() == vm_addr) {
+          decorated_name = symbol_up->getRawSymbol().getName();
+          break;
+        }
+      }
+    }
+  }
+  if (!decorated_name.empty())
+    return decorated_name;
+
+  return std::string();
+}
+
+VariableSP SymbolFilePDB::ParseVariableForPDBData(
+    const lldb_private::SymbolContext &sc,
+    const llvm::pdb::PDBSymbolData &pdb_data) {
+  VariableSP var_sp;
+  uint32_t var_uid = pdb_data.getSymIndexId();
+  auto result = m_variables.find(var_uid);
+  if (result != m_variables.end())
+    return result->second;
+
+  ValueType scope = eValueTypeInvalid;
+  bool is_static_member = false;
+  bool is_external = false;
+  bool is_artificial = false;
+
+  switch (pdb_data.getDataKind()) {
+  case PDB_DataKind::Global:
+    scope = eValueTypeVariableGlobal;
+    is_external = true;
+    break;
+  case PDB_DataKind::Local:
+    scope = eValueTypeVariableLocal;
+    break;
+  case PDB_DataKind::FileStatic:
+    scope = eValueTypeVariableStatic;
+    break;
+  case PDB_DataKind::StaticMember:
+    is_static_member = true;
+    scope = eValueTypeVariableStatic;
+    break;
+  case PDB_DataKind::Member:
+    scope = eValueTypeVariableStatic;
+    break;
+  case PDB_DataKind::Param:
+    scope = eValueTypeVariableArgument;
+    break;
+  case PDB_DataKind::Constant:
+    scope = eValueTypeConstResult;
+    break;
+  default:
+    break;
+  }
+
+  switch (pdb_data.getLocationType()) {
+  case PDB_LocType::TLS:
+    scope = eValueTypeVariableThreadLocal;
+    break;
+  case PDB_LocType::RegRel: {
+    // It is a `this` pointer.
+    if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) {
+      scope = eValueTypeVariableArgument;
+      is_artificial = true;
+    }
+  } break;
+  default:
+    break;
+  }
+
+  Declaration decl;
+  if (!is_artificial && !pdb_data.isCompilerGenerated()) {
+    if (auto lines = pdb_data.getLineNumbers()) {
+      if (auto first_line = lines->getNext()) {
+        uint32_t src_file_id = first_line->getSourceFileId();
+        auto src_file = m_session_up->getSourceFileById(src_file_id);
+        if (src_file) {
+          FileSpec spec(src_file->getFileName(), /*resolve_path*/ false);
+          decl.SetFile(spec);
+          decl.SetColumn(first_line->getColumnNumber());
+          decl.SetLine(first_line->getLineNumber());
+        }
+      }
+    }
+  }
+
+  Variable::RangeList ranges;
+  SymbolContextScope *context_scope = sc.comp_unit;
+  if (scope == eValueTypeVariableLocal) {
+    if (sc.function) {
+      context_scope = sc.function->GetBlock(true).FindBlockByID(
+          pdb_data.getClassParentId());
+      if (context_scope == nullptr)
+        context_scope = sc.function;
+    }
+  }
+
+  SymbolFileTypeSP type_sp =
+      std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId());
+
+  auto var_name = pdb_data.getName();
+  auto mangled = GetMangledForPDBData(pdb_data);
+  auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
+
+  DWARFExpression location(nullptr);
+
+  var_sp = std::make_shared<Variable>(
+      var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
+      ranges, &decl, location, is_external, is_artificial, is_static_member);
+
+  m_variables.insert(std::make_pair(var_uid, var_sp));
+  return var_sp;
+}
+
+size_t
+SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc,
+                              const llvm::pdb::PDBSymbol &pdb_symbol,
+                              lldb_private::VariableList *variable_list) {
+  size_t num_added = 0;
+
+  if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) {
+    VariableListSP local_variable_list_sp;
+
+    auto result = m_variables.find(pdb_data->getSymIndexId());
+    if (result != m_variables.end()) {
+      if (variable_list)
+        variable_list->AddVariableIfUnique(result->second);
+    } else {
+      // Prepare right VariableList for this variable.
+      if (auto lexical_parent = pdb_data->getLexicalParent()) {
+        switch (lexical_parent->getSymTag()) {
+        case PDB_SymType::Exe:
+          assert(sc.comp_unit);
+          LLVM_FALLTHROUGH;
+        case PDB_SymType::Compiland: {
+          if (sc.comp_unit) {
+            local_variable_list_sp = sc.comp_unit->GetVariableList(false);
+            if (!local_variable_list_sp) {
+              local_variable_list_sp = std::make_shared<VariableList>();
+              sc.comp_unit->SetVariableList(local_variable_list_sp);
+            }
+          }
+        } break;
+        case PDB_SymType::Block:
+        case PDB_SymType::Function: {
+          if (sc.function) {
+            Block *block = sc.function->GetBlock(true).FindBlockByID(
+                lexical_parent->getSymIndexId());
+            if (block) {
+              local_variable_list_sp = block->GetBlockVariableList(false);
+              if (!local_variable_list_sp) {
+                local_variable_list_sp = std::make_shared<VariableList>();
+                block->SetVariableList(local_variable_list_sp);
+              }
+            }
+          }
+        } break;
+        default:
+          break;
+        }
+      }
+
+      if (local_variable_list_sp) {
+        if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) {
+          local_variable_list_sp->AddVariableIfUnique(var_sp);
+          if (variable_list)
+            variable_list->AddVariableIfUnique(var_sp);
+          ++num_added;
+        }
+      }
+    }
+  }
+
+  if (auto results = pdb_symbol.findAllChildren()) {
+    while (auto result = results->getNext())
+      num_added += ParseVariables(sc, *result, variable_list);
+  }
+
+  return num_added;
+}
+
 uint32_t SymbolFilePDB::FindGlobalVariables(
     const lldb_private::ConstString &name,
     const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
     uint32_t max_matches, lldb_private::VariableList &variables) {
-  return uint32_t();
+  if (!append)
+    variables.Clear();
+  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+    return 0;
+  if (name.IsEmpty())
+    return 0;
+
+  auto results =
+      m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(),
+                                      PDB_NameSearchFlags::NS_CaseSensitive);
+  if (!results)
+    return 0;
+
+  uint32_t matches = 0;
+  size_t old_size = variables.GetSize();
+  while (auto result = results->getNext()) {
+    auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get());
+    if (max_matches > 0 && matches >= max_matches)
+      break;
+
+    SymbolContext sc;
+    sc.module_sp = m_obj_file->GetModule();
+    lldbassert(sc.module_sp.get());
+
+    sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+    // FIXME: We are not able to determine the compile unit.
+    if (sc.comp_unit == nullptr)
+      continue;
+
+    ParseVariables(sc, *pdb_data, &variables);
+    matches = variables.GetSize() - old_size;
+  }
+
+  return matches;
 }
 
 uint32_t
 SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
                                    bool append, uint32_t max_matches,
                                    lldb_private::VariableList &variables) {
-  return uint32_t();
+  if (!regex.IsValid())
+    return 0;
+  auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
+  if (!results)
+    return 0;
+
+  uint32_t matches = 0;
+  size_t old_size = variables.GetSize();
+  while (auto pdb_data = results->getNext()) {
+    if (max_matches > 0 && matches >= max_matches)
+      break;
+
+    auto var_name = pdb_data->getName();
+    if (var_name.empty())
+      continue;
+    if (!regex.Execute(var_name))
+      continue;
+    SymbolContext sc;
+    sc.module_sp = m_obj_file->GetModule();
+    lldbassert(sc.module_sp.get());
+
+    sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+    // FIXME: We are not able to determine the compile unit.
+    if (sc.comp_unit == nullptr)
+      continue;
+
+    ParseVariables(sc, *pdb_data, &variables);
+    matches = variables.GetSize() - old_size;
+  }
+
+  return matches;
 }
 
 bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to