diff options
Diffstat (limited to 'lldb/source/Plugins')
41 files changed, 653 insertions, 594 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 50e9f7827838..1437d7b58293 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -516,7 +516,7 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, // Try to create a configuration from the files. If there is no valid // configuration possible with the files, this just returns an invalid // configuration. - return CppModuleConfiguration(files); + return CppModuleConfiguration(files, target->GetArchitecture().GetTriple()); } bool ClangUserExpression::PrepareForParsing( diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index ffab16b1682b..befb1f125406 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -10,6 +10,7 @@ #include "ClangHost.h" #include "lldb/Host/FileSystem.h" +#include "llvm/ADT/Triple.h" using namespace lldb_private; @@ -30,7 +31,35 @@ bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) { return false; } -bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { +static llvm::SmallVector<std::string, 2> +getTargetIncludePaths(const llvm::Triple &triple) { + llvm::SmallVector<std::string, 2> paths; + if (!triple.str().empty()) { + paths.push_back("/usr/include/" + triple.str()); + if (!triple.getArchName().empty() || + triple.getOSAndEnvironmentName().empty()) + paths.push_back(("/usr/include/" + triple.getArchName() + "-" + + triple.getOSAndEnvironmentName()) + .str()); + } + return paths; +} + +/// Returns the include path matching the given pattern for the given file +/// path (or None if the path doesn't match the pattern). +static llvm::Optional<llvm::StringRef> +guessIncludePath(llvm::StringRef path_to_file, llvm::StringRef pattern) { + if (pattern.empty()) + return llvm::NoneType(); + size_t pos = path_to_file.find(pattern); + if (pos == llvm::StringRef::npos) + return llvm::NoneType(); + + return path_to_file.substr(0, pos + pattern.size()); +} + +bool CppModuleConfiguration::analyzeFile(const FileSpec &f, + const llvm::Triple &triple) { using namespace llvm::sys::path; // Convert to slashes to make following operations simpler. std::string dir_buffer = convert_to_slash(f.GetDirectory().GetStringRef()); @@ -43,15 +72,25 @@ bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { // need to be specified in the header search. if (libcpp_regex.match(f.GetPath()) && parent_path(posix_dir, Style::posix).endswith("c++")) { - return m_std_inc.TrySet(posix_dir); + if (!m_std_inc.TrySet(posix_dir)) + return false; + if (triple.str().empty()) + return true; + + posix_dir.consume_back("c++/v1"); + // Check if this is a target-specific libc++ include directory. + return m_std_target_inc.TrySet( + (posix_dir + triple.str() + "/c++/v1").str()); } - // Check for /usr/include. On Linux this might be /usr/include/bits, so - // we should remove that '/bits' suffix to get the actual include directory. - if (posix_dir.endswith("/usr/include/bits")) - posix_dir.consume_back("/bits"); - if (posix_dir.endswith("/usr/include")) - return m_c_inc.TrySet(posix_dir); + llvm::Optional<llvm::StringRef> inc_path; + // Target specific paths contains /usr/include, so we check them first + for (auto &path : getTargetIncludePaths(triple)) { + if ((inc_path = guessIncludePath(posix_dir, path))) + return m_c_target_inc.TrySet(*inc_path); + } + if ((inc_path = guessIncludePath(posix_dir, "/usr/include"))) + return m_c_inc.TrySet(*inc_path); // File wasn't interesting, continue analyzing. return true; @@ -92,11 +131,11 @@ bool CppModuleConfiguration::hasValidConfig() { } CppModuleConfiguration::CppModuleConfiguration( - const FileSpecList &support_files) { + const FileSpecList &support_files, const llvm::Triple &triple) { // Analyze all files we were given to build the configuration. bool error = !llvm::all_of(support_files, std::bind(&CppModuleConfiguration::analyzeFile, - this, std::placeholders::_1)); + this, std::placeholders::_1, triple)); // If we have a valid configuration at this point, set the // include directories and module list that should be used. if (!error && hasValidConfig()) { @@ -109,6 +148,10 @@ CppModuleConfiguration::CppModuleConfiguration( // This order matches the way Clang orders these directories. m_include_dirs = {m_std_inc.Get().str(), m_resource_inc, m_c_inc.Get().str()}; + if (m_c_target_inc.Valid()) + m_include_dirs.push_back(m_c_target_inc.Get().str()); + if (m_std_target_inc.Valid()) + m_include_dirs.push_back(m_std_target_inc.Get().str()); m_imported_modules = {"std"}; } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h index 907db5d625dc..5db8abbdbdf3 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -42,8 +42,15 @@ class CppModuleConfiguration { /// If valid, the include path used for the std module. SetOncePath m_std_inc; + /// If valid, the per-target include path used for the std module. + /// This is an optional path only required on some systems. + SetOncePath m_std_target_inc; /// If valid, the include path to the C library (e.g. /usr/include). SetOncePath m_c_inc; + /// If valid, the include path to target-specific C library files + /// (e.g. /usr/include/x86_64-linux-gnu). + /// This is an optional path only required on some systems. + SetOncePath m_c_target_inc; /// The Clang resource include path for this configuration. std::string m_resource_inc; @@ -53,11 +60,13 @@ class CppModuleConfiguration { /// Analyze a given source file to build the current configuration. /// Returns false iff there was a fatal error that makes analyzing any /// further files pointless as the configuration is now invalid. - bool analyzeFile(const FileSpec &f); + bool analyzeFile(const FileSpec &f, const llvm::Triple &triple); public: /// Creates a configuration by analyzing the given list of used source files. - explicit CppModuleConfiguration(const FileSpecList &support_files); + /// The triple (if valid) is used to search for target-specific include paths. + explicit CppModuleConfiguration(const FileSpecList &support_files, + const llvm::Triple &triple); /// Creates an empty and invalid configuration. CppModuleConfiguration() = default; diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 83e8e52b86f2..f1925990e94a 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -914,11 +914,21 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( + RegularExpression("^std::optional<.+>(( )?&)?$"), + SyntheticChildrenSP(new ScriptedSyntheticChildren( + stl_synth_flags, + "lldb.formatters.cpp.gnu_libstdcpp.StdOptionalSynthProvider"))); + cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::multiset<.+> >(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( + RegularExpression("^std::unordered_(multi)?(map|set)<.+> >$"), + SyntheticChildrenSP(new ScriptedSyntheticChildren( + stl_deref_flags, + "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider"))); + cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, @@ -928,9 +938,15 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider"))); + stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression("^std::optional<.+>(( )?&)?$"), + TypeSummaryImplSP(new ScriptSummaryFormat( + stl_summary_flags, + "lldb.formatters.cpp.gnu_libstdcpp.StdOptionalSummaryProvider"))); + cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::bitset<.+>(( )?&)?$"), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -955,13 +971,17 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression("^std::unordered_(multi)?(map|set)<.+> >$"), + TypeSummaryImplSP( + new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::(__cxx11::)?forward_list<.+>(( )?&)?$"), TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); + new ScriptSummaryFormat(stl_summary_flags, "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); AddCXXSynthetic( cpp_category_sp, diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index fc8255983436..c8063915b178 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -81,12 +81,11 @@ bool GenericBitsetFrontEnd::Update() { TargetSP target_sp = m_backend.GetTargetSP(); if (!target_sp) return false; - size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay(); size_t size = 0; if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) - size = arg->value.getLimitedValue(capping_size); + size = arg->value.getLimitedValue(); m_elements.assign(size, ValueObjectSP()); m_first = m_backend.GetChildMemberWithName(GetDataContainerMemberName(), true) diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp index c0c819632851..c1b40ba65e7d 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp @@ -45,7 +45,7 @@ bool OptionalFrontEnd::Update() { // __engaged_ is a bool flag and is true if the optional contains a value. // Converting it to unsigned gives us a size of 1 if it contains a value // and 0 if not. - m_has_value = engaged_sp->GetValueAsUnsigned(0) == 1; + m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0; return false; } diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 3a441973fc73..57c5ba87c397 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -62,9 +62,7 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: CalculateNumChildren() { - if (m_num_elements != UINT32_MAX) - return m_num_elements; - return 0; + return m_num_elements; } lldb::ValueObjectSP lldb_private::formatters:: @@ -160,7 +158,7 @@ lldb::ValueObjectSP lldb_private::formatters:: bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: Update() { - m_num_elements = UINT32_MAX; + m_num_elements = 0; m_next_element = nullptr; m_elements_cache.clear(); ValueObjectSP table_sp = @@ -195,8 +193,13 @@ bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: if (!num_elements_sp) return false; - m_num_elements = num_elements_sp->GetValueAsUnsigned(0); + m_tree = table_sp->GetChildAtNamePath(next_path).get(); + if (m_tree == nullptr) + return false; + + m_num_elements = num_elements_sp->GetValueAsUnsigned(0); + if (m_num_elements > 0) m_next_element = table_sp->GetChildAtNamePath(next_path).get(); diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp index bad730512ff4..ce701fd823fd 100644 --- a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp @@ -116,9 +116,10 @@ bool ObjectFileBreakpad::ParseHeader() { return true; } -Symtab *ObjectFileBreakpad::GetSymtab() { - // TODO - return nullptr; +void ObjectFileBreakpad::ParseSymtab(Symtab &symtab) { + // Nothing to do for breakpad files, all information is parsed as debug info + // which means "lldb_private::Function" objects are used, or symbols are added + // by the SymbolFileBreakpad::AddSymbols(...) function in the symbol file. } void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) { diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h index c320c7ad3e2e..f04e0b4dd7a7 100644 --- a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h +++ b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h @@ -71,7 +71,7 @@ public: return AddressClass::eInvalid; } - Symtab *GetSymtab() override; + void ParseSymtab(lldb_private::Symtab &symtab) override; bool IsStripped() override { return false; } diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 8e0f228a988f..96e94ef08a45 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2687,155 +2687,131 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, return 0; } -Symtab *ObjectFileELF::GetSymtab() { +void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) { ModuleSP module_sp(GetModule()); if (!module_sp) - return nullptr; + return; + + Progress progress( + llvm::formatv("Parsing symbol table for {0}", + m_file.GetFilename().AsCString("<Unknown>"))); + ElapsedTime elapsed(module_sp->GetSymtabParseTime()); // We always want to use the main object file so we (hopefully) only have one // cached copy of our symtab, dynamic sections, etc. ObjectFile *module_obj_file = module_sp->GetObjectFile(); if (module_obj_file && module_obj_file != this) - return module_obj_file->GetSymtab(); - - if (m_symtab_up == nullptr) { - Progress progress( - llvm::formatv("Parsing symbol table for {0}", - m_file.GetFilename().AsCString("<Unknown>"))); - ElapsedTime elapsed(module_sp->GetSymtabParseTime()); - SectionList *section_list = module_sp->GetSectionList(); - if (!section_list) - return nullptr; + return module_obj_file->ParseSymtab(lldb_symtab); - uint64_t symbol_id = 0; - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - // Sharable objects and dynamic executables usually have 2 distinct symbol - // tables, one named ".symtab", and the other ".dynsym". The dynsym is a - // smaller version of the symtab that only contains global symbols. The - // information found in the dynsym is therefore also found in the symtab, - // while the reverse is not necessarily true. - Section *symtab = - section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); - if (symtab) { - m_symtab_up = std::make_unique<Symtab>(symtab->GetObjectFile()); - symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab); - } - - // The symtab section is non-allocable and can be stripped, while the - // .dynsym section which should always be always be there. To support the - // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo - // section, nomatter if .symtab was already parsed or not. This is because - // minidebuginfo normally removes the .symtab symbols which have their - // matching .dynsym counterparts. - if (!symtab || - GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { - Section *dynsym = - section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) - .get(); - if (dynsym) { - if (!m_symtab_up) - m_symtab_up = std::make_unique<Symtab>(dynsym->GetObjectFile()); - symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym); - } - } + SectionList *section_list = module_sp->GetSectionList(); + if (!section_list) + return; - // DT_JMPREL - // If present, this entry's d_ptr member holds the address of - // relocation - // entries associated solely with the procedure linkage table. - // Separating - // these relocation entries lets the dynamic linker ignore them during - // process initialization, if lazy binding is enabled. If this entry is - // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must - // also be present. - const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL); - if (symbol) { - // Synthesize trampoline symbols to help navigate the PLT. - addr_t addr = symbol->d_ptr; - Section *reloc_section = - section_list->FindSectionContainingFileAddress(addr).get(); - if (reloc_section) { - user_id_t reloc_id = reloc_section->GetID(); - const ELFSectionHeaderInfo *reloc_header = - GetSectionHeaderByIndex(reloc_id); - if (reloc_header) { - if (m_symtab_up == nullptr) - m_symtab_up = - std::make_unique<Symtab>(reloc_section->GetObjectFile()); - - ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header, - reloc_id); - } - } - } + uint64_t symbol_id = 0; - if (DWARFCallFrameInfo *eh_frame = - GetModule()->GetUnwindTable().GetEHFrameInfo()) { - if (m_symtab_up == nullptr) - m_symtab_up = std::make_unique<Symtab>(this); - ParseUnwindSymbols(m_symtab_up.get(), eh_frame); + // Sharable objects and dynamic executables usually have 2 distinct symbol + // tables, one named ".symtab", and the other ".dynsym". The dynsym is a + // smaller version of the symtab that only contains global symbols. The + // information found in the dynsym is therefore also found in the symtab, + // while the reverse is not necessarily true. + Section *symtab = + section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); + if (symtab) + symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, symtab); + + // The symtab section is non-allocable and can be stripped, while the + // .dynsym section which should always be always be there. To support the + // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo + // section, nomatter if .symtab was already parsed or not. This is because + // minidebuginfo normally removes the .symtab symbols which have their + // matching .dynsym counterparts. + if (!symtab || + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { + Section *dynsym = + section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) + .get(); + if (dynsym) + symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, dynsym); + } + + // DT_JMPREL + // If present, this entry's d_ptr member holds the address of + // relocation + // entries associated solely with the procedure linkage table. + // Separating + // these relocation entries lets the dynamic linker ignore them during + // process initialization, if lazy binding is enabled. If this entry is + // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must + // also be present. + const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL); + if (symbol) { + // Synthesize trampoline symbols to help navigate the PLT. + addr_t addr = symbol->d_ptr; + Section *reloc_section = + section_list->FindSectionContainingFileAddress(addr).get(); + if (reloc_section) { + user_id_t reloc_id = reloc_section->GetID(); + const ELFSectionHeaderInfo *reloc_header = + GetSectionHeaderByIndex(reloc_id); + if (reloc_header) + ParseTrampolineSymbols(&lldb_symtab, symbol_id, reloc_header, reloc_id); } + } - // If we still don't have any symtab then create an empty instance to avoid - // do the section lookup next time. - if (m_symtab_up == nullptr) - m_symtab_up = std::make_unique<Symtab>(this); - - // In the event that there's no symbol entry for the entry point we'll - // artificially create one. We delegate to the symtab object the figuring - // out of the proper size, this will usually make it span til the next - // symbol it finds in the section. This means that if there are missing - // symbols the entry point might span beyond its function definition. - // We're fine with this as it doesn't make it worse than not having a - // symbol entry at all. - if (CalculateType() == eTypeExecutable) { - ArchSpec arch = GetArchitecture(); - auto entry_point_addr = GetEntryPointAddress(); - bool is_valid_entry_point = - entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); - addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); - if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress( - entry_point_file_addr)) { - uint64_t symbol_id = m_symtab_up->GetNumSymbols(); - // Don't set the name for any synthetic symbols, the Symbol - // object will generate one if needed when the name is accessed - // via accessors. - SectionSP section_sp = entry_point_addr.GetSection(); - Symbol symbol( - /*symID=*/symbol_id, - /*name=*/llvm::StringRef(), // Name will be auto generated. - /*type=*/eSymbolTypeCode, - /*external=*/true, - /*is_debug=*/false, - /*is_trampoline=*/false, - /*is_artificial=*/true, - /*section_sp=*/section_sp, - /*offset=*/0, - /*size=*/0, // FDE can span multiple symbols so don't use its size. - /*size_is_valid=*/false, - /*contains_linker_annotations=*/false, - /*flags=*/0); - // When the entry point is arm thumb we need to explicitly set its - // class address to reflect that. This is important because expression - // evaluation relies on correctly setting a breakpoint at this - // address. - if (arch.GetMachine() == llvm::Triple::arm && - (entry_point_file_addr & 1)) { - symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1); - m_address_class_map[entry_point_file_addr ^ 1] = - AddressClass::eCodeAlternateISA; - } else { - m_address_class_map[entry_point_file_addr] = AddressClass::eCode; - } - m_symtab_up->AddSymbol(symbol); + if (DWARFCallFrameInfo *eh_frame = + GetModule()->GetUnwindTable().GetEHFrameInfo()) { + ParseUnwindSymbols(&lldb_symtab, eh_frame); + } + + // In the event that there's no symbol entry for the entry point we'll + // artificially create one. We delegate to the symtab object the figuring + // out of the proper size, this will usually make it span til the next + // symbol it finds in the section. This means that if there are missing + // symbols the entry point might span beyond its function definition. + // We're fine with this as it doesn't make it worse than not having a + // symbol entry at all. + if (CalculateType() == eTypeExecutable) { + ArchSpec arch = GetArchitecture(); + auto entry_point_addr = GetEntryPointAddress(); + bool is_valid_entry_point = + entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); + addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); + if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress( + entry_point_file_addr)) { + uint64_t symbol_id = lldb_symtab.GetNumSymbols(); + // Don't set the name for any synthetic symbols, the Symbol + // object will generate one if needed when the name is accessed + // via accessors. + SectionSP section_sp = entry_point_addr.GetSection(); + Symbol symbol( + /*symID=*/symbol_id, + /*name=*/llvm::StringRef(), // Name will be auto generated. + /*type=*/eSymbolTypeCode, + /*external=*/true, + /*is_debug=*/false, + /*is_trampoline=*/false, + /*is_artificial=*/true, + /*section_sp=*/section_sp, + /*offset=*/0, + /*size=*/0, // FDE can span multiple symbols so don't use its size. + /*size_is_valid=*/false, + /*contains_linker_annotations=*/false, + /*flags=*/0); + // When the entry point is arm thumb we need to explicitly set its + // class address to reflect that. This is important because expression + // evaluation relies on correctly setting a breakpoint at this + // address. + if (arch.GetMachine() == llvm::Triple::arm && + (entry_point_file_addr & 1)) { + symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1); + m_address_class_map[entry_point_file_addr ^ 1] = + AddressClass::eCodeAlternateISA; + } else { + m_address_class_map[entry_point_file_addr] = AddressClass::eCode; } + lldb_symtab.AddSymbol(symbol); } - - m_symtab_up->CalculateSymbolSizes(); } - - return m_symtab_up.get(); } void ObjectFileELF::RelocateSection(lldb_private::Section *section) diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 5738e5cf60d5..554f623ec8af 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -110,7 +110,7 @@ public: lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; - lldb_private::Symtab *GetSymtab() override; + void ParseSymtab(lldb_private::Symtab &symtab) override; bool IsStripped() override; @@ -123,7 +123,7 @@ public: lldb_private::UUID GetUUID() override; /// Return the contents of the .gnu_debuglink section, if the object file - /// contains it. + /// contains it. llvm::Optional<lldb_private::FileSpec> GetDebugLink(); uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; @@ -278,8 +278,9 @@ private: /// number of dynamic symbols parsed. size_t ParseDynamicSymbols(); - /// Populates m_symtab_up will all non-dynamic linker symbols. This method - /// will parse the symbols only once. Returns the number of symbols parsed. + /// Populates the symbol table with all non-dynamic linker symbols. This + /// method will parse the symbols only once. Returns the number of symbols + /// parsed. unsigned ParseSymbolTable(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id, lldb_private::Section *symtab); @@ -384,7 +385,7 @@ private: lldb_private::UUID &uuid); bool AnySegmentHasPhysicalAddress(); - + /// Takes the .gnu_debugdata and returns the decompressed object file that is /// stored within that section. /// diff --git a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index bec0099517c8..ca9337454889 100644 --- a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -106,23 +106,10 @@ uint32_t ObjectFileJIT::GetAddressByteSize() const { return m_data.GetAddressByteSize(); } -Symtab *ObjectFileJIT::GetSymtab() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_symtab_up == nullptr) { - ElapsedTime elapsed(module_sp->GetSymtabParseTime()); - m_symtab_up = std::make_unique<Symtab>(this); - std::lock_guard<std::recursive_mutex> symtab_guard( - m_symtab_up->GetMutex()); - ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock()); - if (delegate_sp) - delegate_sp->PopulateSymtab(this, *m_symtab_up); - // TODO: get symbols from delegate - m_symtab_up->Finalize(); - } - } - return m_symtab_up.get(); +void ObjectFileJIT::ParseSymtab(Symtab &symtab) { + ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock()); + if (delegate_sp) + delegate_sp->PopulateSymtab(this, symtab); } bool ObjectFileJIT::IsStripped() { diff --git a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index 03ac001988a0..be31139df549 100644 --- a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -67,7 +67,7 @@ public: uint32_t GetAddressByteSize() const override; - lldb_private::Symtab *GetSymtab() override; + void ParseSymtab(lldb_private::Symtab &symtab) override; bool IsStripped() override; diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h index 36e71e21332f..da999d2b55a7 100644 --- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h +++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h @@ -68,7 +68,7 @@ public: bool IsExecutable() const override { return false; } - Symtab *GetSymtab() override { return nullptr; } + void ParseSymtab(lldb_private::Symtab &symtab) override {} bool IsStripped() override { return false; } diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp index 0e6329885528..7445f8311c50 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -246,7 +246,7 @@ bool ObjectFileWasm::ParseHeader() { return true; } -Symtab *ObjectFileWasm::GetSymtab() { return nullptr; } +void ObjectFileWasm::ParseSymtab(Symtab &symtab) {} static SectionType GetSectionTypeFromName(llvm::StringRef Name) { if (Name.consume_front(".debug_") || Name.consume_front(".zdebug_")) { diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h index 44939b6d4ea0..d7b5bc22caad 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h @@ -78,7 +78,7 @@ public: return AddressClass::eInvalid; } - Symtab *GetSymtab() override; + void ParseSymtab(lldb_private::Symtab &symtab) override; bool IsStripped() override { return !!GetExternalDebugInfoFileSpec(); } diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp new file mode 100644 index 000000000000..90c290b6fbc7 --- /dev/null +++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp @@ -0,0 +1,148 @@ +//===-- PlatformQemuUser.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Platform/QemuUser/PlatformQemuUser.h" +#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/Listener.h" +#include "lldb/Utility/Log.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(PlatformQemuUser) + +#define LLDB_PROPERTIES_platformqemuuser +#include "PlatformQemuUserProperties.inc" + +enum { +#define LLDB_PROPERTIES_platformqemuuser +#include "PlatformQemuUserPropertiesEnum.inc" +}; + +class PluginProperties : public Properties { +public: + PluginProperties() { + m_collection_sp = std::make_shared<OptionValueProperties>( + ConstString(PlatformQemuUser::GetPluginNameStatic())); + m_collection_sp->Initialize(g_platformqemuuser_properties); + } + + llvm::StringRef GetArchitecture() { + return m_collection_sp->GetPropertyAtIndexAsString( + nullptr, ePropertyArchitecture, ""); + } + + FileSpec GetEmulatorPath() { + return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, + ePropertyEmulatorPath); + } +}; + +static PluginProperties &GetGlobalProperties() { + static PluginProperties g_settings; + return g_settings; +} + +llvm::StringRef PlatformQemuUser::GetPluginDescriptionStatic() { + return "Platform for debugging binaries under user mode qemu"; +} + +void PlatformQemuUser::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), + PlatformQemuUser::CreateInstance, PlatformQemuUser::DebuggerInitialize); +} + +void PlatformQemuUser::Terminate() { + PluginManager::UnregisterPlugin(PlatformQemuUser::CreateInstance); +} + +void PlatformQemuUser::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForPlatformPlugin( + debugger, ConstString(GetPluginNameStatic()))) { + PluginManager::CreateSettingForPlatformPlugin( + debugger, GetGlobalProperties().GetValueProperties(), + ConstString("Properties for the qemu-user platform plugin."), + /*is_global_property=*/true); + } +} + +PlatformSP PlatformQemuUser::CreateInstance(bool force, const ArchSpec *arch) { + if (force) + return PlatformSP(new PlatformQemuUser()); + return nullptr; +} + +std::vector<ArchSpec> PlatformQemuUser::GetSupportedArchitectures() { + llvm::Triple triple = HostInfo::GetArchitecture().GetTriple(); + triple.setEnvironment(llvm::Triple::UnknownEnvironment); + triple.setArchName(GetGlobalProperties().GetArchitecture()); + if (triple.getArch() != llvm::Triple::UnknownArch) + return {ArchSpec(triple)}; + return {}; +} + +static auto get_arg_range(const Args &args) { + return llvm::make_range(args.GetArgumentArrayRef().begin(), + args.GetArgumentArrayRef().end()); +} + +lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, + Debugger &debugger, + Target &target, Status &error) { + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); + + std::string qemu = GetGlobalProperties().GetEmulatorPath().GetPath(); + + llvm::SmallString<0> socket_model, socket_path; + HostInfo::GetProcessTempDir().GetPath(socket_model); + llvm::sys::path::append(socket_model, "qemu-%%%%%%%%.socket"); + do { + llvm::sys::fs::createUniquePath(socket_model, socket_path, false); + } while (FileSystem::Instance().Exists(socket_path)); + + Args args( + {qemu, "-g", socket_path, launch_info.GetExecutableFile().GetPath()}); + for (size_t i = 1; i < launch_info.GetArguments().size(); ++i) + args.AppendArgument(launch_info.GetArguments()[i].ref()); + + LLDB_LOG(log, "{0} -> {1}", get_arg_range(launch_info.GetArguments()), + get_arg_range(args)); + + launch_info.SetArguments(args, true); + launch_info.SetLaunchInSeparateProcessGroup(true); + launch_info.GetFlags().Clear(eLaunchFlagDebug); + launch_info.SetMonitorProcessCallback(ProcessLaunchInfo::NoOpMonitorCallback, + false); + + error = Host::LaunchProcess(launch_info); + if (error.Fail()) + return nullptr; + + ProcessSP process_sp = target.CreateProcess( + launch_info.GetListener(), + process_gdb_remote::ProcessGDBRemote::GetPluginNameStatic(), nullptr, + true); + ListenerSP listener_sp = + Listener::MakeListener("lldb.platform_qemu_user.debugprocess"); + launch_info.SetHijackListener(listener_sp); + Process::ProcessEventHijacker hijacker(*process_sp, listener_sp); + + error = process_sp->ConnectRemote(("unix-connect://" + socket_path).str()); + if (error.Fail()) + return nullptr; + + process_sp->WaitForProcessToStop(llvm::None, nullptr, false, listener_sp); + return process_sp; +} diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h new file mode 100644 index 000000000000..f4f5d224a8cd --- /dev/null +++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h @@ -0,0 +1,57 @@ +//===-- PlatformQemuUser.h ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Platform.h" + +namespace lldb_private { + +class PlatformQemuUser : public Platform { +public: + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "qemu-user"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + llvm::StringRef GetDescription() override { + return GetPluginDescriptionStatic(); + } + + UserIDResolver &GetUserIDResolver() override { + return HostInfo::GetUserIDResolver(); + } + + std::vector<ArchSpec> GetSupportedArchitectures() override; + + lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info, + Debugger &debugger, Target &target, + Status &error) override; + + lldb::ProcessSP Attach(ProcessAttachInfo &attach_info, Debugger &debugger, + Target *target, Status &status) override { + status.SetErrorString("Not supported"); + return nullptr; + } + + bool IsConnected() const override { return true; } + + void CalculateTrapHandlerSymbolNames() override {} + + Environment GetEnvironment() override { return Host::GetEnvironment(); } + +private: + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + static void DebuggerInitialize(Debugger &debugger); + + PlatformQemuUser() : Platform(/*is_host=*/false) {} +}; + +} // namespace lldb_private diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td new file mode 100644 index 000000000000..abfab7f59de4 --- /dev/null +++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td @@ -0,0 +1,12 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "platformqemuuser" in { + def Architecture: Property<"architecture", "String">, + Global, + DefaultStringValue<"">, + Desc<"Architecture to emulate.">; + def EmulatorPath: Property<"emulator-path", "FileSpec">, + Global, + DefaultStringValue<"">, + Desc<"Path to the emulator binary.">; +} diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 23b346d5c17f..b852a0164375 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -281,8 +281,8 @@ size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size, return DoReadMemory(addr, buf, size, error); } -Status ProcessElfCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo ®ion_info) { +Status ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion_info) { region_info.Clear(); const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index fd36e5027816..67df3c5fac76 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -86,6 +86,10 @@ public: size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Status &error) override; + lldb_private::Status + GetMemoryRegionInfo(lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo ®ion_info) override; + lldb::addr_t GetImageInfoAddress() override; lldb_private::ArchSpec GetArchitecture(); @@ -101,10 +105,6 @@ protected: bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override; - lldb_private::Status - DoGetMemoryRegionInfo(lldb::addr_t load_addr, - lldb_private::MemoryRegionInfo ®ion_info) override; - private: struct NT_FILE_Entry { lldb::addr_t start; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 4ce79da48f07..25ae08838bf8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -81,11 +81,6 @@ GDBRemoteCommunication::~GDBRemoteCommunication() { if (m_decompression_scratch) free (m_decompression_scratch); #endif - - // Stop the communications read thread which is used to parse all incoming - // packets. This function will block until the read thread returns. - if (m_read_thread_enabled) - StopReadThread(); } char GDBRemoteCommunication::CalculcateChecksum(llvm::StringRef payload) { @@ -193,7 +188,7 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() { StringExtractorGDBRemote packet; - PacketResult result = ReadPacket(packet, GetPacketTimeout(), false); + PacketResult result = WaitForPacketNoLock(packet, GetPacketTimeout(), false); if (result == PacketResult::Success) { if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck) @@ -225,40 +220,18 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response, Timeout<std::micro> timeout, bool sync_on_timeout) { - if (m_read_thread_enabled) - return PopPacketFromQueue(response, timeout); - else - return WaitForPacketNoLock(response, timeout, sync_on_timeout); -} + using ResponseType = StringExtractorGDBRemote::ResponseType; -// This function is called when a packet is requested. -// A whole packet is popped from the packet queue and returned to the caller. -// Packets are placed into this queue from the communication read thread. See -// GDBRemoteCommunication::AppendBytesToCache. -GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::PopPacketFromQueue(StringExtractorGDBRemote &response, - Timeout<std::micro> timeout) { - auto pred = [&] { return !m_packet_queue.empty() && IsConnected(); }; - // lock down the packet queue - std::unique_lock<std::mutex> lock(m_packet_queue_mutex); - - if (!timeout) - m_condition_queue_not_empty.wait(lock, pred); - else { - if (!m_condition_queue_not_empty.wait_for(lock, *timeout, pred)) - return PacketResult::ErrorReplyTimeout; - if (!IsConnected()) - return PacketResult::ErrorDisconnected; + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); + for (;;) { + PacketResult result = + WaitForPacketNoLock(response, timeout, sync_on_timeout); + if (result != PacketResult::Success || + (response.GetResponseType() != ResponseType::eAck && + response.GetResponseType() != ResponseType::eNack)) + return result; + LLDB_LOG(log, "discarding spurious `{0}` packet", response.GetStringRef()); } - - // get the front element of the queue - response = m_packet_queue.front(); - - // remove the front element - m_packet_queue.pop(); - - // we got a packet - return PacketResult::Success; } GDBRemoteCommunication::PacketResult @@ -1287,53 +1260,6 @@ GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() { m_gdb_comm.SetPacketTimeout(m_saved_timeout); } -// This function is called via the Communications class read thread when bytes -// become available for this connection. This function will consume all -// incoming bytes and try to parse whole packets as they become available. Full -// packets are placed in a queue, so that all packet requests can simply pop -// from this queue. Async notification packets will be dispatched immediately -// to the ProcessGDBRemote Async thread via an event. -void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes, - size_t len, bool broadcast, - lldb::ConnectionStatus status) { - StringExtractorGDBRemote packet; - - while (true) { - PacketType type = CheckForPacket(bytes, len, packet); - - // scrub the data so we do not pass it back to CheckForPacket on future - // passes of the loop - bytes = nullptr; - len = 0; - - // we may have received no packet so lets bail out - if (type == PacketType::Invalid) - break; - - if (type == PacketType::Standard) { - // scope for the mutex - { - // lock down the packet queue - std::lock_guard<std::mutex> guard(m_packet_queue_mutex); - // push a new packet into the queue - m_packet_queue.push(packet); - // Signal condition variable that we have a packet - m_condition_queue_not_empty.notify_one(); - } - } - - if (type == PacketType::Notify) { - // put this packet into an event - const char *pdata = packet.GetStringRef().data(); - - // as the communication class, we are a broadcaster and the async thread - // is tuned to listen to us - BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify, - new EventDataBytes(pdata)); - } - } -} - void llvm::format_provider<GDBRemoteCommunication::PacketResult>::format( const GDBRemoteCommunication::PacketResult &result, raw_ostream &Stream, StringRef Style) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 5da568e9b4d4..afc7e740d4c9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -84,8 +84,6 @@ class GDBRemoteCommunication : public Communication { public: enum { eBroadcastBitRunPacketSent = kLoUserBroadcastBit, - eBroadcastBitGdbReadThreadGotNotify = - kLoUserBroadcastBit << 1 // Sent when we received a notify packet. }; enum class PacketType { Invalid = 0, Standard, Notify }; @@ -196,10 +194,6 @@ protected: bool sync_on_timeout, llvm::function_ref<void(llvm::StringRef)> output_callback); - // Pop a packet from the queue in a thread safe manner - PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response, - Timeout<std::micro> timeout); - PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response, Timeout<std::micro> timeout, bool sync_on_timeout); @@ -226,24 +220,7 @@ protected: static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg); - // GDB-Remote read thread - // . this thread constantly tries to read from the communication - // class and stores all packets received in a queue. The usual - // threads read requests simply pop packets off the queue in the - // usual order. - // This setup allows us to intercept and handle async packets, such - // as the notify packet. - - // This method is defined as part of communication.h - // when the read thread gets any bytes it will pass them on to this function - void AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast, - lldb::ConnectionStatus status) override; - private: - std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue - std::mutex m_packet_queue_mutex; // Mutex for accessing queue - std::condition_variable - m_condition_queue_not_empty; // Condition variable to wait for packets // Promise used to grab the port number from listening thread std::promise<uint16_t> m_port_promise; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 78e722eee080..07dfa5e04ee5 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -86,13 +86,6 @@ bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) { std::chrono::steady_clock::time_point start_of_handshake = std::chrono::steady_clock::now(); if (SendAck()) { - // Wait for any responses that might have been queued up in the remote - // GDB server and flush them all - StringExtractorGDBRemote response; - PacketResult packet_result = PacketResult::Success; - while (packet_result == PacketResult::Success) - packet_result = ReadPacket(response, milliseconds(10), false); - // The return value from QueryNoAckModeSupported() is true if the packet // was sent and _any_ response (including UNIMPLEMENTED) was received), or // false if no response was received. This quickly tells us if we have a @@ -106,17 +99,15 @@ bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) { std::chrono::duration<double>(end_of_handshake - start_of_handshake) .count(); if (error_ptr) { - if (packet_result == PacketResult::ErrorDisconnected) + if (!IsConnected()) error_ptr->SetErrorString("Connection shut down by remote side " "while waiting for reply to initial " "handshake packet"); - else if (packet_result == PacketResult::ErrorReplyTimeout) + else error_ptr->SetErrorStringWithFormat( "failed to get reply to handshake packet within timeout of " "%.1f seconds", handshake_timeout); - else - error_ptr->SetErrorString("failed to get reply to handshake packet"); } } } else { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 11cac9fa3a4d..49d88b72b01b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -46,7 +46,7 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse( Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) { StringExtractorGDBRemote packet; - PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); + PacketResult packet_result = ReadPacket(packet, timeout, false); if (packet_result == PacketResult::Success) { const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType(); @@ -150,10 +150,6 @@ GDBRemoteCommunicationServer::SendOKResponse() { return SendPacketNoLock("OK"); } -bool GDBRemoteCommunicationServer::HandshakeWithClient() { - return GetAck() == PacketResult::Success; -} - GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) { std::string json_string; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 68448eae2b9f..5de344061ec9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -44,10 +44,6 @@ public: Status &error, bool &interrupt, bool &quit); - // After connecting, do a little handshake with the client to make sure - // we are at least communicating - bool HandshakeWithClient(); - protected: std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler> m_packet_handlers; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 5360db3d8462..30f14a52dfb5 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1088,18 +1088,6 @@ void GDBRemoteCommunicationServerLLGS::NewSubprocess( void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); - if (!m_handshake_completed) { - if (!HandshakeWithClient()) { - LLDB_LOGF(log, - "GDBRemoteCommunicationServerLLGS::%s handshake with " - "client failed, exiting", - __FUNCTION__); - m_mainloop.RequestTermination(); - return; - } - m_handshake_completed = true; - } - bool interrupt = false; bool done = false; Status error; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 6c75771f6427..17ee4130dc34 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -104,7 +104,6 @@ protected: std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; uint32_t m_next_saved_registers_id = 1; - bool m_handshake_completed = false; bool m_thread_suffix_supported = false; bool m_list_threads_in_stop_reply = false; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 2233bf675819..3ade8c815feb 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -282,9 +282,7 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, __FUNCTION__); } - const uint32_t gdb_event_mask = - Communication::eBroadcastBitReadThreadDidExit | - GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; + const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit; if (m_async_listener_sp->StartListeningForEvents( &m_gdb_comm, gdb_event_mask) != gdb_event_mask) { LLDB_LOGF(log, @@ -1324,24 +1322,6 @@ Status ProcessGDBRemote::DoResume() { return error; } -void ProcessGDBRemote::HandleStopReplySequence() { - while (true) { - // Send vStopped - StringExtractorGDBRemote response; - m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response); - - // OK represents end of signal list - if (response.IsOKResponse()) - break; - - // If not OK or a normal packet we have a problem - if (!response.IsNormalResponse()) - break; - - SetLastStopPacket(response); - } -} - void ProcessGDBRemote::ClearThreadIDList() { std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); m_thread_ids.clear(); @@ -2897,8 +2877,8 @@ lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, return allocated_addr; } -Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr, - MemoryRegionInfo ®ion_info) { +Status ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr, + MemoryRegionInfo ®ion_info) { Status error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); return error; @@ -3539,31 +3519,6 @@ void ProcessGDBRemote::StopAsyncThread() { __FUNCTION__); } -bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) { - // get the packet at a string - const std::string &pkt = std::string(packet.GetStringRef()); - // skip %stop: - StringExtractorGDBRemote stop_info(pkt.c_str() + 5); - - // pass as a thread stop info packet - SetLastStopPacket(stop_info); - - // check for more stop reasons - HandleStopReplySequence(); - - // if the process is stopped then we need to fake a resume so that we can - // stop properly with the new break. This is possible due to - // SetPrivateState() broadcasting the state change as a side effect. - if (GetPrivateState() == lldb::StateType::eStateStopped) { - SetPrivateState(lldb::StateType::eStateRunning); - } - - // since we have some stopped packets we can halt the process - SetPrivateState(lldb::StateType::eStateStopped); - - return true; -} - thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ProcessGDBRemote *process = (ProcessGDBRemote *)arg; @@ -3712,17 +3667,6 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { done = true; break; - case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: { - lldb_private::Event *event = event_sp.get(); - const EventDataBytes *continue_packet = - EventDataBytes::GetEventDataFromEvent(event); - StringExtractorGDBRemote notify( - (const char *)continue_packet->GetBytes()); - // Hand this over to the process to handle - process->HandleNotifyPacket(notify); - break; - } - default: LLDB_LOGF(log, "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 8134bc6b530d..488336b8c1b8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -144,6 +144,9 @@ public: lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, Status &error) override; + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion_info) override; + Status DoDeallocateMemory(lldb::addr_t ptr) override; // Process STDIO @@ -343,8 +346,6 @@ protected: size_t UpdateThreadIDsFromStopReplyThreadsValue(llvm::StringRef value); - bool HandleNotifyPacket(StringExtractorGDBRemote &packet); - bool StartAsyncThread(); void StopAsyncThread(); @@ -375,8 +376,6 @@ protected: lldb::addr_t dispatch_queue_t, std::string &queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial); - void HandleStopReplySequence(); - void ClearThreadIDList(); bool UpdateThreadIDList(); @@ -421,9 +420,6 @@ protected: Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type, const std::vector<uint8_t> &tags) override; - Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo ®ion_info) override; - private: // For ProcessGDBRemote only std::string m_partial_profile_data; diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index 736cfa070088..37ee5466c5b9 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -73,7 +73,7 @@ public: bool IsExecutable() const override { return false; } ArchSpec GetArchitecture() override { return m_arch; } UUID GetUUID() override { return m_uuid; } - Symtab *GetSymtab() override { return m_symtab_up.get(); } + void ParseSymtab(lldb_private::Symtab &symtab) override {} bool IsStripped() override { return true; } ByteOrder GetByteOrder() const override { return m_arch.GetByteOrder(); } @@ -439,8 +439,8 @@ void ProcessMinidump::BuildMemoryRegions() { llvm::sort(*m_memory_regions); } -Status ProcessMinidump::DoGetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo ®ion) { +Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion) { BuildMemoryRegions(); region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, load_addr); return Status(); diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h index 5360269199cd..3501d38a0f27 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -75,6 +75,9 @@ public: ArchSpec GetArchitecture(); + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + Status GetMemoryRegions( lldb_private::MemoryRegionInfos ®ion_list) override; @@ -95,9 +98,6 @@ protected: bool DoUpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; - Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) override; - void ReadModuleList(); lldb::ModuleSP GetOrCreateModule(lldb_private::UUID minidump_uuid, diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index 15d3d43d9993..c1b7294a7f58 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -248,8 +248,8 @@ ArchSpec ScriptedProcess::GetArchitecture() { return GetTarget().GetArchitecture(); } -Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo ®ion) { +Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion) { CheckInterpreterAndScriptObject(); Status error; diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h index c8355f35548a..d56658a2e48a 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.h +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -84,6 +84,9 @@ public: ArchSpec GetArchitecture(); + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + Status GetMemoryRegions(lldb_private::MemoryRegionInfos ®ion_list) override; @@ -97,9 +100,6 @@ protected: bool DoUpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; - Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) override; - private: friend class ScriptedThread; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 798d947a0a7d..c7af13598843 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -15,8 +15,12 @@ #if LLDB_ENABLE_PYTHON +// LLDB Python header must be included first +#include "lldb-python.h" + #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" +#include "llvm/Support/Error.h" namespace lldb_private { @@ -41,20 +45,148 @@ template <> const char *GetPythonValueFormatString(unsigned long long); template <> const char *GetPythonValueFormatString(float t); template <> const char *GetPythonValueFormatString(double t); -extern "C" void *LLDBSwigPythonCreateScriptedProcess( +void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); + +// These prototypes are the Pythonic implementations of the required callbacks. +// Although these are scripting-language specific, their definition depends on +// the public API. + +void *LLDBSwigPythonCreateScriptedProcess(const char *python_class_name, + const char *session_dictionary_name, + const lldb::TargetSP &target_sp, + StructuredDataImpl *args_impl, + std::string &error_string); + +void *LLDBSwigPythonCreateScriptedThread(const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP &process_sp, + StructuredDataImpl *args_impl, + std::string &error_string); + +llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + const lldb::StackFrameSP &sb_frame, + const lldb::BreakpointLocationSP &sb_bp_loc, + lldb_private::StructuredDataImpl *args_impl); + +bool LLDBSwigPythonWatchpointCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp); + +bool LLDBSwigPythonCallTypeScript(const char *python_function_name, + const void *session_dictionary, + const lldb::ValueObjectSP &valobj_sp, + void **pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP &options_sp, + std::string &retval); + +void * +LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP &valobj_sp); + +void *LLDBSwigPythonCreateCommandObject(const char *python_class_name, + const char *session_dictionary_name, + const lldb::DebuggerSP debugger_sp); + +void *LLDBSwigPythonCreateScriptedThreadPlan( const char *python_class_name, const char *session_dictionary_name, - const lldb::TargetSP &target_sp, StructuredDataImpl *args_impl, - std::string &error_string); + lldb_private::StructuredDataImpl *args_data, std::string &error_string, + const lldb::ThreadPlanSP &thread_plan_sp); -extern "C" void *LLDBSwigPythonCreateScriptedThread( +bool LLDBSWIGPythonCallThreadPlan(void *implementor, const char *method_name, + lldb_private::Event *event_sp, + bool &got_error); + +void *LLDBSwigPythonCreateScriptedBreakpointResolver( const char *python_class_name, const char *session_dictionary_name, - const lldb::ProcessSP &process_sp, StructuredDataImpl *args_impl, - std::string &error_string); + lldb_private::StructuredDataImpl *args, const lldb::BreakpointSP &bkpt_sp); + +unsigned int +LLDBSwigPythonCallBreakpointResolver(void *implementor, const char *method_name, + lldb_private::SymbolContext *sym_ctx); + +void *LLDBSwigPythonCreateScriptedStopHook( + lldb::TargetSP target_sp, const char *python_class_name, + const char *session_dictionary_name, lldb_private::StructuredDataImpl *args, + lldb_private::Status &error); + +bool LLDBSwigPythonStopHookCallHandleStop(void *implementor, + lldb::ExecutionContextRefSP exc_ctx, + lldb::StreamSP stream); + +size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor, uint32_t max); + +PyObject *LLDBSwigPython_GetChildAtIndex(PyObject *implementor, uint32_t idx); + +int LLDBSwigPython_GetIndexOfChildWithName(PyObject *implementor, + const char *child_name); + +lldb::ValueObjectSP LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data); + +bool LLDBSwigPython_UpdateSynthProviderInstance(PyObject *implementor); + +bool LLDBSwigPython_MightHaveChildrenSynthProviderInstance( + PyObject *implementor); + +PyObject *LLDBSwigPython_GetValueSynthProviderInstance(PyObject *implementor); + +bool LLDBSwigPythonCallCommand(const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP &debugger, const char *args, + lldb_private::CommandReturnObject &cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); + +bool LLDBSwigPythonCallCommandObject( + PyObject *implementor, lldb::DebuggerSP &debugger, const char *args, + lldb_private::CommandReturnObject &cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); + +bool LLDBSwigPythonCallModuleInit(const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP &debugger); + +void *LLDBSWIGPythonCreateOSPlugin(const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP &process_sp); + +void *LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name, + const char *session_dictionary_name); + +PyObject * +LLDBSwigPython_GetRecognizedArguments(PyObject *implementor, + const lldb::StackFrameSP &frame_sp); + +bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, + const char *session_dictionary_name, + const lldb::ProcessSP &process, + std::string &output); + +bool LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, + const char *session_dictionary_name, + lldb::ThreadSP &thread, + std::string &output); + +bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, + const char *session_dictionary_name, + const lldb::TargetSP &target, + std::string &output); + +bool LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, + const char *session_dictionary_name, + lldb::StackFrameSP &frame, + std::string &output); + +bool LLDBSWIGPythonRunScriptKeywordValue(const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP &value, + std::string &output); -extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data); -extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data); -extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data); -extern "C" void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(void *data); +void *LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, + const lldb::TargetSP &target_sp); } // namespace lldb_private diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index c1f4c2d3b4d3..5f282d74e364 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -70,153 +70,6 @@ extern "C" void init_lldb(void); #define LLDBSwigPyInit init_lldb #endif -// These prototypes are the Pythonic implementations of the required callbacks. -// Although these are scripting-language specific, their definition depends on -// the public API. - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" - -// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has -// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is -// incompatible with C -#if _MSC_VER -#pragma warning (push) -#pragma warning (disable : 4190) -#endif - -extern "C" llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( - const char *python_function_name, const char *session_dictionary_name, - const lldb::StackFrameSP &sb_frame, - const lldb::BreakpointLocationSP &sb_bp_loc, StructuredDataImpl *args_impl); - -#if _MSC_VER -#pragma warning (pop) -#endif - -#pragma clang diagnostic pop - -extern "C" bool LLDBSwigPythonWatchpointCallbackFunction( - const char *python_function_name, const char *session_dictionary_name, - const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp); - -extern "C" bool LLDBSwigPythonCallTypeScript( - const char *python_function_name, void *session_dictionary, - const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, - const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval); - -extern "C" void * -LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP &valobj_sp); - -extern "C" void * -LLDBSwigPythonCreateCommandObject(const char *python_class_name, - const char *session_dictionary_name, - const lldb::DebuggerSP debugger_sp); - -extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan( - const char *python_class_name, const char *session_dictionary_name, - StructuredDataImpl *args_data, - std::string &error_string, - const lldb::ThreadPlanSP &thread_plan_sp); - -extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor, - const char *method_name, - Event *event_sp, bool &got_error); - -extern "C" void *LLDBSwigPythonCreateScriptedBreakpointResolver( - const char *python_class_name, const char *session_dictionary_name, - lldb_private::StructuredDataImpl *args, lldb::BreakpointSP &bkpt_sp); - -extern "C" unsigned int -LLDBSwigPythonCallBreakpointResolver(void *implementor, const char *method_name, - lldb_private::SymbolContext *sym_ctx); - -extern "C" void *LLDBSwigPythonCreateScriptedStopHook( - TargetSP target_sp, const char *python_class_name, - const char *session_dictionary_name, lldb_private::StructuredDataImpl *args, - lldb_private::Status &error); - -extern "C" bool -LLDBSwigPythonStopHookCallHandleStop(void *implementor, - lldb::ExecutionContextRefSP exc_ctx, - lldb::StreamSP stream); - -extern "C" size_t LLDBSwigPython_CalculateNumChildren(void *implementor, - uint32_t max); - -extern "C" void *LLDBSwigPython_GetChildAtIndex(void *implementor, - uint32_t idx); - -extern "C" int LLDBSwigPython_GetIndexOfChildWithName(void *implementor, - const char *child_name); - -extern lldb::ValueObjectSP -LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data); - -extern "C" bool LLDBSwigPython_UpdateSynthProviderInstance(void *implementor); - -extern "C" bool -LLDBSwigPython_MightHaveChildrenSynthProviderInstance(void *implementor); - -extern "C" void * -LLDBSwigPython_GetValueSynthProviderInstance(void *implementor); - -extern "C" bool -LLDBSwigPythonCallCommand(const char *python_function_name, - const char *session_dictionary_name, - lldb::DebuggerSP &debugger, const char *args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - -extern "C" bool -LLDBSwigPythonCallCommandObject(void *implementor, lldb::DebuggerSP &debugger, - const char *args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - -extern "C" bool -LLDBSwigPythonCallModuleInit(const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP &debugger); - -extern "C" void * -LLDBSWIGPythonCreateOSPlugin(const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP &process_sp); - -extern "C" void * -LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name, - const char *session_dictionary_name); - -extern "C" void * -LLDBSwigPython_GetRecognizedArguments(void *implementor, - const lldb::StackFrameSP &frame_sp); - -extern "C" bool LLDBSWIGPythonRunScriptKeywordProcess( - const char *python_function_name, const char *session_dictionary_name, - lldb::ProcessSP &process, std::string &output); - -extern "C" bool LLDBSWIGPythonRunScriptKeywordThread( - const char *python_function_name, const char *session_dictionary_name, - lldb::ThreadSP &thread, std::string &output); - -extern "C" bool LLDBSWIGPythonRunScriptKeywordTarget( - const char *python_function_name, const char *session_dictionary_name, - lldb::TargetSP &target, std::string &output); - -extern "C" bool LLDBSWIGPythonRunScriptKeywordFrame( - const char *python_function_name, const char *session_dictionary_name, - lldb::StackFrameSP &frame, std::string &output); - -extern "C" bool LLDBSWIGPythonRunScriptKeywordValue( - const char *python_function_name, const char *session_dictionary_name, - lldb::ValueObjectSP &value, std::string &output); - -extern "C" void * -LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, - const lldb::TargetSP &target_sp); static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { ScriptInterpreter *script_interpreter = @@ -1591,9 +1444,9 @@ lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( if (!implementor.IsAllocated()) return ValueObjectListSP(); - PythonObject py_return(PyRefType::Owned, - (PyObject *)LLDBSwigPython_GetRecognizedArguments( - implementor.get(), frame_sp)); + PythonObject py_return( + PyRefType::Owned, + LLDBSwigPython_GetRecognizedArguments(implementor.get(), frame_sp)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { @@ -2423,7 +2276,7 @@ size_t ScriptInterpreterPythonImpl::CalculateNumChildren( StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return 0; - void *implementor = generic->GetValue(); + auto *implementor = static_cast<PyObject *>(generic->GetValue()); if (!implementor) return 0; @@ -2446,7 +2299,7 @@ lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex( StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return lldb::ValueObjectSP(); - void *implementor = generic->GetValue(); + auto *implementor = static_cast<PyObject *>(generic->GetValue()); if (!implementor) return lldb::ValueObjectSP(); @@ -2454,7 +2307,7 @@ lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - void *child_ptr = LLDBSwigPython_GetChildAtIndex(implementor, idx); + PyObject *child_ptr = LLDBSwigPython_GetChildAtIndex(implementor, idx); if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue *sb_value_ptr = (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr); @@ -2478,7 +2331,7 @@ int ScriptInterpreterPythonImpl::GetIndexOfChildWithName( StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return UINT32_MAX; - void *implementor = generic->GetValue(); + auto *implementor = static_cast<PyObject *>(generic->GetValue()); if (!implementor) return UINT32_MAX; @@ -2503,7 +2356,7 @@ bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance( StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; - void *implementor = generic->GetValue(); + auto *implementor = static_cast<PyObject *>(generic->GetValue()); if (!implementor) return ret_val; @@ -2526,7 +2379,7 @@ bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance( StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; - void *implementor = generic->GetValue(); + auto *implementor = static_cast<PyObject *>(generic->GetValue()); if (!implementor) return ret_val; @@ -2550,14 +2403,15 @@ lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue( StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; - void *implementor = generic->GetValue(); + auto *implementor = static_cast<PyObject *>(generic->GetValue()); if (!implementor) return ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - void *child_ptr = LLDBSwigPython_GetValueSynthProviderInstance(implementor); + PyObject *child_ptr = + LLDBSwigPython_GetValueSynthProviderInstance(implementor); if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue *sb_value_ptr = (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr); @@ -2653,11 +2507,11 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( } { - ProcessSP process_sp(process->shared_from_this()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = LLDBSWIGPythonRunScriptKeywordProcess( - impl_function, m_dictionary_name.c_str(), process_sp, output); + impl_function, m_dictionary_name.c_str(), process->shared_from_this(), + output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } @@ -2753,11 +2607,10 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( } { - ValueObjectSP value_sp(value->GetSP()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = LLDBSWIGPythonRunScriptKeywordValue( - impl_function, m_dictionary_name.c_str(), value_sp, output); + impl_function, m_dictionary_name.c_str(), value->GetSP(), output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } @@ -3076,9 +2929,9 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( SynchronicityHandler synch_handler(debugger_sp, synchronicity); std::string args_str = args.str(); - ret_val = LLDBSwigPythonCallCommandObject(impl_obj_sp->GetValue(), - debugger_sp, args_str.c_str(), - cmd_retobj, exe_ctx_ref_sp); + ret_val = LLDBSwigPythonCallCommandObject( + static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp, + args_str.c_str(), cmd_retobj, exe_ctx_ref_sp); } if (!ret_val) diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index b07674af3bd9..9d23f1baf931 100644 --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -500,7 +500,7 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { for (Symbol &symbol : symbols) symtab.AddSymbol(std::move(symbol)); - symtab.CalculateSymbolSizes(); + symtab.Finalize(); } llvm::Expected<lldb::addr_t> @@ -927,4 +927,3 @@ uint64_t SymbolFileBreakpad::GetDebugInfoSize() { // Breakpad files are all debug info. return m_objfile_sp->GetByteSize(); } - diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 2dd7ae60b231..8c20244a6c44 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2067,6 +2067,13 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext( } void SymbolFileDWARF::PreloadSymbols() { + // Get the symbol table for the symbol file prior to taking the module lock + // so that it is available without needing to take the module lock. The DWARF + // indexing might end up needing to relocate items when DWARF sections are + // loaded as they might end up getting the section contents which can call + // ObjectFileELF::RelocateSection() which in turn will ask for the symbol + // table and can cause deadlocks. + GetSymtab(); std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); m_index->Preload(); } @@ -3271,15 +3278,14 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, } const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die); - const dw_tag_t parent_tag = die.GetParent().Tag(); + const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); + const dw_tag_t parent_tag = sc_parent_die.Tag(); bool is_static_member = (parent_tag == DW_TAG_compile_unit || parent_tag == DW_TAG_partial_unit) && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type); ValueType scope = eValueTypeInvalid; - - const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); SymbolContextScope *symbol_context_scope = nullptr; bool has_explicit_mangled = mangled != nullptr; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 8af90cb66e87..bf101ac1acf1 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1182,8 +1182,9 @@ void SymbolFileNativePDB::FindFunctions( FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // For now we only support lookup by method name. - if (!(name_type_mask & eFunctionNameTypeMethod)) + // For now we only support lookup by method name or full name. + if (!(name_type_mask & eFunctionNameTypeFull || + name_type_mask & eFunctionNameTypeMethod)) return; using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 45dfc4b9a152..db0ae241be7e 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1421,7 +1421,6 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { )); } - symtab.CalculateSymbolSizes(); symtab.Finalize(); } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index b20ae32a08ac..b1dbc382ff04 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -91,7 +91,7 @@ static void VerifyDecl(clang::Decl *decl) { assert(decl && "VerifyDecl called with nullptr?"); #ifndef NDEBUG // We don't care about the actual access value here but only want to trigger - // that Clang calls its internal Decl::AccessDeclContextSanity check. + // that Clang calls its internal Decl::AccessDeclContextCheck validation. decl->getAccess(); #endif } |