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; +} 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/ExpressionsTest1.script =================================================================== --- /dev/null +++ lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script @@ -0,0 +1 @@ +print sum(buf0, 1) 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/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: source/Core/RichManglingContext.cpp =================================================================== --- source/Core/RichManglingContext.cpp +++ source/Core/RichManglingContext.cpp @@ -131,6 +131,8 @@ case PluginCxxLanguage: m_buffer = get(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(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(m_cxx_method_parser) ->GetFullName() .GetStringRef(); + if (!m_buffer.data()) + m_buffer = llvm::StringRef("", 0); return; case None: return; 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/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/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/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/SymbolFile/PDB/PDBASTParser.h =================================================================== --- source/Plugins/SymbolFile/PDB/PDBASTParser.h +++ source/Plugins/SymbolFile/PDB/PDBASTParser.h @@ -69,7 +69,8 @@ typedef llvm::DenseMap CXXRecordDeclToUidMap; typedef llvm::DenseMap UidToDeclMap; - typedef llvm::DenseMap> + typedef std::set NamespacesSet; + typedef llvm::DenseMap ParentToNamespacesMap; typedef llvm::DenseMap 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 params; + if (std::unique_ptr sig = func->getSignature()) { + if (std::unique_ptr> + arg_enum = sig->findAllChildren()) { + while (std::unique_ptr 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/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 resolved_ids; - auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids, - this](UniqueCStringMap &Names) { + auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list, + &resolved_ids](UniqueCStringMap &Names) { std::vector 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 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());