aleksandr.urakov created this revision.
aleksandr.urakov added reviewers: zturner, asmith, stella.stamenova.
aleksandr.urakov added a project: LLDB.
Herald added subscribers: lldb-commits, teemperor, JDevlieghere, aprantl.

This patch contains several small fixes, which makes it possible to evaluate 
expressions on Windows using information from PDB. The changes are:

- several sanitize checks;
- make `IRExecutionUnit::MemoryManager::getSymbolAddress` to not return a magic 
value on a failure, because callers wait 0 in this case;
- entry point required to be a file address, not RVA, in the `ObjectFilePECOFF`;
- do not crash on a debuggee second chance exception - it may be an expression 
evaluation crash;
- create parameter declarations for functions in AST to make it possible to 
call debugee functions from expressions;
- relax name searching rules for variables, functions, namespaces and types. 
Now it works just like in the DWARF plugin;
- fix endless recursion in `SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc`.

Each change is small and it is hard to test each change separately, so I think 
that create one review for them all is not a bad idea, especially because they 
make together the test to work.

I remember about the new native PDB plugin, but these changes are old enough, 
for last two or three weeks I'm just releasing my stash :) And some of the 
changes may be useful for the new plugin too.

This review depends on https://reviews.llvm.org/D52461, 
https://reviews.llvm.org/D52618, https://reviews.llvm.org/D53368, x64 testing 
depends on https://reviews.llvm.org/D53753.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D53759

Files:
  lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp
  lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script
  lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script
  lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script
  lit/SymbolFile/PDB/expressions.test
  source/Core/RichManglingContext.cpp
  source/Expression/IRExecutionUnit.cpp
  source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
  source/Plugins/Process/Windows/Common/ProcessWindows.cpp
  source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
  source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
  source/Plugins/SymbolFile/PDB/PDBASTParser.h
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp

Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -286,6 +286,10 @@
     const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) {
   lldbassert(sc.comp_unit && sc.module_sp.get());
 
+  if (FunctionSP result =
+          sc.comp_unit->FindFunctionByUID(pdb_func.getSymIndexId()))
+    return result.get();
+
   auto file_vm_addr = pdb_func.getVirtualAddress();
   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
     return nullptr;
@@ -1042,8 +1046,6 @@
     const lldb_private::ConstString &name,
     const lldb_private::CompilerDeclContext *parent_decl_ctx,
     uint32_t max_matches, lldb_private::VariableList &variables) {
-  if (!parent_decl_ctx)
-    parent_decl_ctx = m_tu_decl_ctx_up.get();
   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
     return 0;
   if (name.IsEmpty())
@@ -1073,9 +1075,8 @@
     if (sc.comp_unit == nullptr)
       continue;
 
-    auto actual_parent_decl_ctx =
-        GetDeclContextContainingUID(result->getSymIndexId());
-    if (actual_parent_decl_ctx != *parent_decl_ctx)
+    if (parent_decl_ctx && GetDeclContextContainingUID(
+                               result->getSymIndexId()) != *parent_decl_ctx)
       continue;
 
     ParseVariables(sc, *pdb_data, &variables);
@@ -1266,20 +1267,28 @@
     CacheFunctionNames();
 
     std::set<uint32_t> resolved_ids;
-    auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids,
-                      this](UniqueCStringMap<uint32_t> &Names) {
+    auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list,
+                      &resolved_ids](UniqueCStringMap<uint32_t> &Names) {
       std::vector<uint32_t> ids;
-      if (Names.GetValues(name, ids)) {
-        for (auto id : ids) {
-          if (resolved_ids.find(id) == resolved_ids.end()) {
-            if (ResolveFunction(id, include_inlines, sc_list))
-              resolved_ids.insert(id);
-          }
-        }
+      if (!Names.GetValues(name, ids))
+        return;
+
+      for (uint32_t id : ids) {
+        if (resolved_ids.find(id) != resolved_ids.end())
+          continue;
+
+        if (parent_decl_ctx &&
+            GetDeclContextContainingUID(id) != *parent_decl_ctx)
+          continue;
+
+        if (ResolveFunction(id, include_inlines, sc_list))
+          resolved_ids.insert(id);
       }
     };
     if (name_type_mask & eFunctionNameTypeFull) {
       ResolveFn(m_func_full_names);
+      ResolveFn(m_func_base_names);
+      ResolveFn(m_func_method_names);
     }
     if (name_type_mask & eFunctionNameTypeBase) {
       ResolveFn(m_func_base_names);
@@ -1458,8 +1467,6 @@
     const std::string &name,
     const lldb_private::CompilerDeclContext *parent_decl_ctx,
     uint32_t max_matches, lldb_private::TypeMap &types) {
-  if (!parent_decl_ctx)
-    parent_decl_ctx = m_tu_decl_ctx_up.get();
   std::unique_ptr<IPDBEnumSymbols> results;
   if (name.empty())
     return;
@@ -1492,9 +1499,8 @@
     if (!ResolveTypeUID(result->getSymIndexId()))
       continue;
 
-    auto actual_parent_decl_ctx =
-        GetDeclContextContainingUID(result->getSymIndexId());
-    if (actual_parent_decl_ctx != *parent_decl_ctx)
+    if (parent_decl_ctx && GetDeclContextContainingUID(
+                               result->getSymIndexId()) != *parent_decl_ctx)
       continue;
 
     auto iter = m_types.find(result->getSymIndexId());
Index: source/Plugins/SymbolFile/PDB/PDBASTParser.h
===================================================================
--- source/Plugins/SymbolFile/PDB/PDBASTParser.h
+++ source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -69,7 +69,8 @@
   typedef llvm::DenseMap<clang::CXXRecordDecl *, lldb::user_id_t>
       CXXRecordDeclToUidMap;
   typedef llvm::DenseMap<lldb::user_id_t, clang::Decl *> UidToDeclMap;
-  typedef llvm::DenseMap<clang::DeclContext *, std::set<clang::NamespaceDecl *>>
+  typedef std::set<clang::NamespaceDecl *> NamespacesSet;
+  typedef llvm::DenseMap<clang::DeclContext *, NamespacesSet>
       ParentToNamespacesMap;
   typedef llvm::DenseMap<clang::DeclContext *, lldb::user_id_t>
       DeclContextToUidMap;
@@ -109,6 +110,7 @@
   CXXRecordDeclToUidMap m_forward_decl_to_uid;
   UidToDeclMap m_uid_to_decl;
   ParentToNamespacesMap m_parent_to_namespaces;
+  NamespacesSet m_namespaces;
   DeclContextToUidMap m_decl_context_to_uid;
 };
 
Index: source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -914,6 +914,26 @@
         decl_context, name.c_str(), type->GetForwardCompilerType(), storage,
         func->hasInlineAttribute());
 
+    std::vector<clang::ParmVarDecl *> params;
+    if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) {
+      if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg>>
+              arg_enum = sig->findAllChildren<PDBSymbolTypeFunctionArg>()) {
+        while (std::unique_ptr<PDBSymbolTypeFunctionArg> arg =
+                   arg_enum->getNext()) {
+          Type *arg_type = symbol_file->ResolveTypeUID(arg->getTypeId());
+          if (!arg_type)
+            continue;
+
+          clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration(
+              nullptr, arg_type->GetForwardCompilerType(), clang::SC_None);
+          if (param)
+            params.push_back(param);
+        }
+      }
+    }
+    if (params.size())
+      m_ast.SetFunctionParameters(decl, params.data(), params.size());
+
     m_uid_to_decl[sym_id] = decl;
 
     return decl;
@@ -1018,6 +1038,7 @@
           namespace_name_c_str, curr_context);
 
       m_parent_to_namespaces[curr_context].insert(namespace_decl);
+      m_namespaces.insert(namespace_decl);
 
       curr_context = namespace_decl;
     }
@@ -1053,18 +1074,22 @@
 clang::NamespaceDecl *
 PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent,
                                 llvm::StringRef name) {
-  if (!parent)
-    parent = m_ast.GetTranslationUnitDecl();
+  NamespacesSet *set;
+  if (parent) {
+    auto pit = m_parent_to_namespaces.find(parent);
+    if (pit == m_parent_to_namespaces.end())
+      return nullptr;
 
-  auto it = m_parent_to_namespaces.find(parent);
-  if (it == m_parent_to_namespaces.end())
-    return nullptr;
+    set = &pit->second;
+  } else
+    set = &m_namespaces;
+  assert(set);
 
-  for (auto namespace_decl : it->second)
+  for (clang::NamespaceDecl *namespace_decl : *set)
     if (namespace_decl->getName().equals(name))
       return namespace_decl;
 
-  for (auto namespace_decl : it->second)
+  for (clang::NamespaceDecl *namespace_decl : *set)
     if (namespace_decl->isAnonymousNamespace())
       return FindNamespaceDecl(namespace_decl, name);
 
Index: source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
===================================================================
--- source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
+++ source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
@@ -42,7 +42,7 @@
     lldb::DataBufferSP &data_sp) {
   if (!CacheAllRegisterValues())
     return false;
-  if (data_sp->GetByteSize() < sizeof(m_context)) {
+  if (!data_sp || data_sp->GetByteSize() < sizeof(m_context)) {
     data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
   }
   memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
Index: source/Plugins/Process/Windows/Common/ProcessWindows.cpp
===================================================================
--- source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -954,8 +954,9 @@
   }
 
   if (!first_chance) {
-    // Any second chance exception is an application crash by definition.
-    SetPrivateState(eStateCrashed);
+    // Not any second chance exception is an application crash by definition.
+    // It may be an expression evaluation crash.
+    SetPrivateState(eStateStopped);
   }
 
   ExceptionResult result = ExceptionResult::SendToApplication;
Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
===================================================================
--- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -813,7 +813,7 @@
     return m_entry_point_address;
 
   SectionList *section_list = GetSectionList();
-  addr_t offset = m_coff_header_opt.entry;
+  addr_t offset = m_coff_header_opt.entry + m_coff_header_opt.image_base;
 
   if (!section_list)
     m_entry_point_address.SetOffset(offset);
Index: source/Expression/IRExecutionUnit.cpp
===================================================================
--- source/Expression/IRExecutionUnit.cpp
+++ source/Expression/IRExecutionUnit.cpp
@@ -1013,7 +1013,7 @@
           Name.c_str());
 
     m_parent.ReportSymbolLookupError(name_cs);
-    return 0xbad0bad0;
+    return 0;
   } else {
     if (log)
       log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
Index: source/Core/RichManglingContext.cpp
===================================================================
--- source/Core/RichManglingContext.cpp
+++ source/Core/RichManglingContext.cpp
@@ -131,6 +131,8 @@
   case PluginCxxLanguage:
     m_buffer =
         get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
+    if (!m_buffer.data())
+      m_buffer = llvm::StringRef("", 0);
     return;
   case None:
     return;
@@ -149,6 +151,8 @@
   case PluginCxxLanguage:
     m_buffer =
         get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
+    if (!m_buffer.data())
+      m_buffer = llvm::StringRef("", 0);
     return;
   case None:
     return;
@@ -168,6 +172,8 @@
     m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
                    ->GetFullName()
                    .GetStringRef();
+    if (!m_buffer.data())
+      m_buffer = llvm::StringRef("", 0);
     return;
   case None:
     return;
Index: lit/SymbolFile/PDB/expressions.test
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/expressions.test
@@ -0,0 +1,36 @@
+REQUIRES: windows
+RUN: cl /Zi /GS- /c %S/Inputs/ExpressionsTest.cpp /Fo%t.obj
+RUN: link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe
+RUN: %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s
+
+// Check the variable value through `print`
+CHECK: (lldb) print result
+CHECK: (char) $0 = '\x1c'
+
+// Call the function just like in the code
+CHECK: (lldb) print N0::N1::sum(N0::N1::buf1, sizeof(N0::N1::buf1))
+CHECK: (char) $1 = '\x1c'
+
+// Try the relaxed namespaces search
+CHECK: (lldb) print N1::sum(N1::buf1, sizeof(N1::buf1))
+CHECK: (char) $2 = '\x1c'
+
+// Try the relaxed variables and functions search
+CHECK: (lldb) print sum(buf1, sizeof(buf1))
+CHECK: (char) $3 = '\x1c'
+
+// Make a crash during expression calculation
+CHECK: (lldb) print sum(buf1, 1000000000)
+CHECK: The process has been returned to the state before expression evaluation.
+
+// Make one more crash
+CHECK: (lldb) print sum(buf0, 1)
+CHECK: The process has been returned to the state before expression evaluation.
+
+// Check if the process state was restored succesfully
+CHECK: (lldb) print sum(buf0, result - 28)
+CHECK: (char) $4 = '\0'
+
+// Call the function with arbitrary parameters
+CHECK: (lldb) print sum(buf1 + 3, 3)
+CHECK: (char) $5 = '\f'
Index: lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script
@@ -0,0 +1,2 @@
+print sum(buf0, result - 28)
+print sum(buf1 + 3, 3)
Index: lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script
@@ -0,0 +1 @@
+print sum(buf0, 1)
Index: lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script
@@ -0,0 +1,7 @@
+breakpoint set --file ExpressionsTest.cpp --line 19
+run
+print result
+print N0::N1::sum(N0::N1::buf1, sizeof(N0::N1::buf1))
+print N1::sum(N1::buf1, sizeof(N1::buf1))
+print sum(buf1, sizeof(buf1))
+print sum(buf1, 1000000000)
Index: lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp
@@ -0,0 +1,20 @@
+namespace N0 {
+namespace N1 {
+
+char *buf0 = nullptr;
+char buf1[] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+char sum(char *buf, int size) {
+  char result = 0;
+  for (int i = 0; i < size; i++)
+    result += buf[i];
+  return result;
+}
+
+} // namespace N1
+} // namespace N0
+
+int main() {
+  char result = N0::N1::sum(N0::N1::buf1, sizeof(N0::N1::buf1));
+  return 0;
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to