diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-01-27 22:17:16 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-06-04 11:59:19 +0000 |
commit | 390adc38fc112be360bd15499e5241bf4e675b6f (patch) | |
tree | 712d68d3aa03f7aa4902ba03dcac2a56f49ae0e5 /contrib/llvm-project/lldb/source/Plugins | |
parent | 8a84287b0edc66fc6dede3db770d10ff41da5464 (diff) | |
download | src-390adc38fc112be360bd15499e5241bf4e675b6f.tar.gz src-390adc38fc112be360bd15499e5241bf4e675b6f.zip |
Merge llvm-project main llvmorg-14-init-17616-g024a1fab5c35
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-14-init-17616-g024a1fab5c35.
PR: 261742
MFC after: 2 weeks
(cherry picked from commit 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins')
92 files changed, 2688 insertions, 1071 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp index 2cf32bdd3800..8c54219f0a14 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp @@ -1111,7 +1111,7 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, triple.getSubArch() == llvm::Triple::NoSubArch) triple.setArchName("armv8.7a"); - std::string features_str = ""; + std::string features_str; const char *triple_str = triple.getTriple().c_str(); // ARM Cortex M0-M7 devices only execute thumb instructions diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index d9cbcce22c52..188b6da7a712 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -338,7 +338,7 @@ bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { dyld_break = target.CreateBreakpoint( &containingModules, /*containingSourceFiles=*/nullptr, DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC, - /*offset=*/0, + /*m_offset=*/0, /*skip_prologue=*/eLazyBoolNo, /*internal=*/true, /*request_hardware=*/false); @@ -348,7 +348,7 @@ bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { dyld_break = target.CreateBreakpoint( &containingModules, /*containingSourceFiles=*/nullptr, DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC, - /*offset=*/0, + /*m_offset=*/0, /*skip_prologue=*/eLazyBoolNo, /*internal=*/true, /*request_hardware=*/false); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index a0cff3cc9bf8..51f34369c383 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -995,7 +995,8 @@ public: void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, unsigned NumCandidates, - SourceLocation OpenParLoc) override { + SourceLocation OpenParLoc, + bool Braced) override { // At the moment we don't filter out any overloaded candidates. } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp index 74dd04600b4b..fecffd1183f8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp @@ -138,7 +138,7 @@ getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt) { // We currently only support building namespaces. if (foreign_ctxt->isNamespace()) { - NamedDecl *ns = llvm::dyn_cast<NamedDecl>(foreign_ctxt); + NamedDecl *ns = llvm::cast<NamedDecl>(foreign_ctxt); llvm::StringRef ns_name = ns->getName(); auto lookup_result = emulateLookupInCtxt(sema, ns_name, *parent); diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index ea9c95c55cbb..4ef0a034b6dd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -137,7 +137,7 @@ EmulateInstructionMIPS::EmulateInstructionMIPS( break; } - std::string features = ""; + std::string features; uint32_t arch_flags = arch.GetFlags(); if (arch_flags & ArchSpec::eMIPSAse_msa) features += "+msa,"; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index e5732a50f3f2..26736f4c58ba 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -137,7 +137,7 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64( break; } - std::string features = ""; + std::string features; uint32_t arch_flags = arch.GetFlags(); if (arch_flags & ArchSpec::eMIPSAse_msa) features += "+msa,"; diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp index dc8c7c96aa11..a5c23615309d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp @@ -100,14 +100,14 @@ InstrumentationRuntimeMainThreadChecker::RetrieveReportData( if (!apiname_ptr) return StructuredData::ObjectSP(); - std::string apiName = ""; + std::string apiName; Status read_error; target.ReadCStringFromMemory(apiname_ptr, apiName, read_error); if (read_error.Fail()) return StructuredData::ObjectSP(); - std::string className = ""; - std::string selector = ""; + std::string className; + std::string selector; if (apiName.substr(0, 2) == "-[") { size_t spacePos = apiName.find(' '); if (spacePos != std::string::npos) { diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp index aef10bb2a778..977d8e4dbe07 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp @@ -711,7 +711,7 @@ addr_t InstrumentationRuntimeTSan::GetMainRacyAddress( std::string InstrumentationRuntimeTSan::GetLocationDescription( StructuredData::ObjectSP report, addr_t &global_addr, std::string &global_name, std::string &filename, uint32_t &line) { - std::string result = ""; + std::string result; ProcessSP process_sp = GetProcessSP(); @@ -820,8 +820,8 @@ bool InstrumentationRuntimeTSan::NotifyBreakpointHit( report->GetAsDictionary()->AddIntegerItem("memory_address", main_address); addr_t global_addr = 0; - std::string global_name = ""; - std::string location_filename = ""; + std::string global_name; + std::string location_filename; uint32_t location_line = 0; std::string location_description = instance->GetLocationDescription( report, global_addr, global_name, location_filename, location_line); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index df61cc3853eb..0fb65f5a317d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -579,6 +579,51 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::__[[:alnum:]]+::allocator<wchar_t> >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, + "std::string_view summary provider", + ConstString("^std::__[[:alnum:]]+::string_view$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, + "std::string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view<char, " + "std::__[[:alnum:]]+::char_traits<char> >$"), + stl_summary_flags, true); + AddCXXSummary( + cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, + "std::string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view<unsigned char, " + "std::__[[:alnum:]]+::char_traits<unsigned char> >$"), + stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16, + "std::u16string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view<char16_t, " + "std::__[[:alnum:]]+::char_traits<char16_t> >$"), + stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32, + "std::u32string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view<char32_t, " + "std::__[[:alnum:]]+::char_traits<char32_t> >$"), + stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxWStringViewSummaryProvider, + "std::wstring_view summary provider", + ConstString("^std::__[[:alnum:]]+::wstring_view$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxWStringViewSummaryProvider, + "std::wstring_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view<wchar_t, " + "std::__[[:alnum:]]+::char_traits<wchar_t> >$"), + stl_summary_flags, true); + SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( false); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index c8063915b178..d1d844bb4ca4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -72,6 +72,7 @@ ConstString GenericBitsetFrontEnd::GetDataContainerMemberName() { case StdLib::LibStdcpp: return ConstString("_M_w"); } + llvm_unreachable("Unknown StdLib enum"); } bool GenericBitsetFrontEnd::Update() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index b9aef0ae7d9e..21196393371e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -19,6 +19,7 @@ #include "lldb/Target/ProcessStructReader.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" @@ -26,6 +27,7 @@ #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include <tuple> using namespace lldb; using namespace lldb_private; @@ -560,7 +562,7 @@ ExtractLibcxxStringInfo(ValueObject &valobj) { return {}; ValueObjectSP layout_decider( - D->GetChildAtIndexPath(llvm::ArrayRef<size_t>({0, 0}))); + D->GetChildAtIndexPath(llvm::ArrayRef<size_t>({0, 0}))); // this child should exist if (!layout_decider) @@ -643,16 +645,10 @@ ExtractLibcxxStringInfo(ValueObject &valobj) { return std::make_pair(size, location_sp); } -bool lldb_private::formatters::LibcxxWStringSummaryProvider( - ValueObject &valobj, Stream &stream, - const TypeSummaryOptions &summary_options) { - auto string_info = ExtractLibcxxStringInfo(valobj); - if (!string_info) - return false; - uint64_t size; - ValueObjectSP location_sp; - std::tie(size, location_sp) = *string_info; - +static bool +LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + ValueObjectSP location_sp, size_t size) { if (size == 0) { stream.Printf("L\"\""); return true; @@ -660,7 +656,6 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider( if (!location_sp) return false; - StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) { const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary(); @@ -714,10 +709,9 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider( return false; } -template <StringPrinter::StringElementType element_type> -bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, - const TypeSummaryOptions &summary_options, - std::string prefix_token) { +bool lldb_private::formatters::LibcxxWStringSummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { auto string_info = ExtractLibcxxStringInfo(valobj); if (!string_info) return false; @@ -725,6 +719,17 @@ bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, ValueObjectSP location_sp; std::tie(size, location_sp) = *string_info; + return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options, + location_sp, size); +} + +template <StringPrinter::StringElementType element_type> +static bool +LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + std::string prefix_token, ValueObjectSP location_sp, + uint64_t size) { + if (size == 0) { stream.Printf("\"\""); return true; @@ -763,6 +768,21 @@ bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, } template <StringPrinter::StringElementType element_type> +static bool +LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + std::string prefix_token) { + auto string_info = ExtractLibcxxStringInfo(valobj); + if (!string_info) + return false; + uint64_t size; + ValueObjectSP location_sp; + std::tie(size, location_sp) = *string_info; + + return LibcxxStringSummaryProvider<element_type>( + valobj, stream, summary_options, prefix_token, location_sp, size); +} +template <StringPrinter::StringElementType element_type> static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token) { @@ -796,3 +816,83 @@ bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32( return formatStringImpl<StringPrinter::StringElementType::UTF32>( valobj, stream, summary_options, "U"); } + +static std::tuple<bool, ValueObjectSP, size_t> +LibcxxExtractStringViewData(ValueObject& valobj) { + ConstString g_data_name("__data"); + ConstString g_size_name("__size"); + auto dataobj = valobj.GetChildMemberWithName(g_data_name, true); + auto sizeobj = valobj.GetChildMemberWithName(g_size_name, true); + + if (!dataobj || !sizeobj) + return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {}); + + if (!dataobj->GetError().Success() || !sizeobj->GetError().Success()) + return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {}); + + bool success{false}; + uint64_t size = sizeobj->GetValueAsUnsigned(0, &success); + if (!success) + return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {}); + + return std::make_tuple(true,dataobj,size); +} + +template <StringPrinter::StringElementType element_type> +static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + std::string prefix_token) { + + bool success; + ValueObjectSP dataobj; + size_t size; + std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj); + + if (!success) { + stream << "Summary Unavailable"; + return true; + } + + return LibcxxStringSummaryProvider<element_type>( + valobj, stream, summary_options, prefix_token, dataobj, size); +} + +bool lldb_private::formatters::LibcxxStringViewSummaryProviderASCII( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + return formatStringViewImpl<StringPrinter::StringElementType::ASCII>( + valobj, stream, summary_options, ""); +} + +bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + return formatStringViewImpl<StringPrinter::StringElementType::UTF16>( + valobj, stream, summary_options, "u"); +} + +bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + return formatStringViewImpl<StringPrinter::StringElementType::UTF32>( + valobj, stream, summary_options, "U"); +} + +bool lldb_private::formatters::LibcxxWStringViewSummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + + bool success; + ValueObjectSP dataobj; + size_t size; + std::tie( success, dataobj, size ) = LibcxxExtractStringViewData(valobj); + + if (!success) { + stream << "Summary Unavailable"; + return true; + } + + + return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options, + dataobj, size); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index 80dc71787ceb..0f166ae24912 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -34,6 +34,22 @@ bool LibcxxWStringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // libc++ std::wstring +bool LibcxxStringViewSummaryProviderASCII( + ValueObject &valueObj, Stream &stream, + const TypeSummaryOptions &summary_options); // libc++ std::string_view + +bool LibcxxStringViewSummaryProviderUTF16( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options); // libc++ std::u16string_view + +bool LibcxxStringViewSummaryProviderUTF32( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options); // libc++ std::u32string_view + +bool LibcxxWStringViewSummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // libc++ std::wstring_view + bool LibcxxOptionalSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // libc++ std::optional<> diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSString.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSString.cpp index 2b5161e781f2..61705c866778 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSString.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSString.cpp @@ -8,14 +8,13 @@ #include "NSString.h" -#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/StringPrinter.h" #include "lldb/Target/Language.h" -#include "lldb/Target/ProcessStructReader.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" @@ -31,24 +30,6 @@ NSString_Additionals::GetAdditionalSummaries() { return g_map; } -static CompilerType GetNSPathStore2Type(Target &target) { - static ConstString g_type_name("__lldb_autogen_nspathstore2"); - - TypeSystemClang *ast_ctx = ScratchTypeSystemClang::GetForTarget(target); - - if (!ast_ctx) - return CompilerType(); - - CompilerType voidstar = - ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); - CompilerType uint32 = - ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); - - return ast_ctx->GetOrCreateStructForIdentifier( - g_type_name, - {{"isa", voidstar}, {"lengthAndRef", uint32}, {"buffer", voidstar}}); -} - bool lldb_private::formatters::NSStringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { @@ -229,11 +210,17 @@ bool lldb_private::formatters::NSStringSummaryProvider( return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); } else if (is_path_store) { - ProcessStructReader reader(valobj.GetProcessSP().get(), - valobj.GetValueAsUnsigned(0), - GetNSPathStore2Type(*valobj.GetTargetSP())); - explicit_length = - reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20; + // _lengthAndRefCount is the first ivar of NSPathStore2 (after the isa). + uint64_t length_ivar_offset = 1 * ptr_size; + CompilerType length_type = valobj.GetCompilerType().GetBasicTypeFromAST( + lldb::eBasicTypeUnsignedInt); + ValueObjectSP length_valobj_sp = + valobj.GetSyntheticChildAtOffset(length_ivar_offset, length_type, true, + ConstString("_lengthAndRefCount")); + if (!length_valobj_sp) + return false; + // Get the length out of _lengthAndRefCount. + explicit_length = length_valobj_sp->GetValueAsUnsigned(0) >> 20; lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4; options.SetLocation(location); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index bd6b6335ca8c..f2cf25f93eb2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -671,7 +671,7 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, static const ConstString g_objc_copyRealizedClassList( "_ZL33objc_copyRealizedClassList_nolockPj"); m_has_objc_copyRealizedClassList = HasSymbol(g_objc_copyRealizedClassList); - + WarnIfNoExpandedSharedCache(); RegisterObjCExceptionRecognizer(process); } @@ -2355,6 +2355,32 @@ void AppleObjCRuntimeV2::WarnIfNoClassesCached( } } +void AppleObjCRuntimeV2::WarnIfNoExpandedSharedCache() { + if (!m_objc_module_sp) + return; + + ObjectFile *object_file = m_objc_module_sp->GetObjectFile(); + if (!object_file) + return; + + if (!object_file->IsInMemory()) + return; + + Target &target = GetProcess()->GetTarget(); + Debugger &debugger = target.GetDebugger(); + if (auto stream = debugger.GetAsyncOutputStream()) { + const char *msg = "read from the shared cache"; + if (PlatformSP platform_sp = target.GetPlatform()) + msg = platform_sp->IsHost() + ? "read from the host's in-memory shared cache" + : "find the on-disk shared cache for this device"; + stream->Printf("warning: libobjc.A.dylib is being read from process " + "memory. This indicates that LLDB could not %s. This will " + "likely reduce debugging performance.\n", + msg); + } +} + DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() { if (!m_decl_vendor_up) m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 6266634e64c5..e1a6b7cde48a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -399,6 +399,7 @@ private: }; void WarnIfNoClassesCached(SharedCacheWarningReason reason); + void WarnIfNoExpandedSharedCache(); lldb::addr_t GetSharedCacheReadOnlyAddress(); lldb::addr_t GetSharedCacheBaseAddress(); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index aa6306bef8b9..ff41f187ba9d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -889,8 +889,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, ThreadPlanSP ret_plan_sp; lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); - DispatchFunction vtable_dispatch - = {"vtable", 0, false, false, DispatchFunction::eFixUpFixed}; + DispatchFunction vtable_dispatch = {"vtable", false, false, false, + DispatchFunction::eFixUpFixed}; // First step is to look and see if we are in one of the known ObjC // dispatch functions. We've already compiled a table of same, so diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index c6cb2be981a7..40a0ea3e97a4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -59,7 +59,7 @@ uint32_t AppleObjCTypeEncodingParser::ReadNumber(StringLexer &type) { // "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}" AppleObjCTypeEncodingParser::StructElement::StructElement() - : name(""), type(clang::QualType()) {} + : type(clang::QualType()) {} AppleObjCTypeEncodingParser::StructElement AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx, diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp index a70e6a079f76..516bcb21b019 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp @@ -115,7 +115,7 @@ Status MinidumpFileBuilder::AddSystemInfo(const llvm::Triple &target_triple) { sys_info.PlatformId = platform_id; m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo)); - std::string csd_string = ""; + std::string csd_string; error = WriteString(csd_string, &m_data); if (error.Fail()) { @@ -272,7 +272,8 @@ Status MinidumpFileBuilder::AddModuleList(Target &target) { mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target)); m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size); m.Checksum = static_cast<llvm::support::ulittle32_t>(0); - m.TimeDateStamp = static_cast<llvm::support::ulittle32_t>(std::time(0)); + m.TimeDateStamp = + static_cast<llvm::support::ulittle32_t>(std::time(nullptr)); m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>( size_before + module_stream_size + helper_data.GetByteSize()); m.VersionInfo = info; @@ -719,7 +720,7 @@ Status MinidumpFileBuilder::Dump(lldb::FileUP &core_file) const { header.Checksum = static_cast<llvm::support::ulittle32_t>( 0u), // not used in most of the writers header.TimeDateStamp = - static_cast<llvm::support::ulittle32_t>(std::time(0)); + static_cast<llvm::support::ulittle32_t>(std::time(nullptr)); header.Flags = static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h index da999d2b55a7..a1a3eeb656dd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h @@ -102,4 +102,4 @@ private: }; } // namespace lldb_private -#endif // LLDB_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H +#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 754d06de7cb9..2bf0a44e4a3e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -183,3 +183,97 @@ MmapArgList PlatformFreeBSD::GetMmapArgumentList(const ArchSpec &arch, args.push_back(0); return args; } + +CompilerType PlatformFreeBSD::GetSiginfoType(const llvm::Triple &triple) { + if (!m_type_system_up) + m_type_system_up.reset(new TypeSystemClang("siginfo", triple)); + TypeSystemClang *ast = m_type_system_up.get(); + + // generic types + CompilerType int_type = ast->GetBasicType(eBasicTypeInt); + CompilerType uint_type = ast->GetBasicType(eBasicTypeUnsignedInt); + CompilerType long_type = ast->GetBasicType(eBasicTypeLong); + CompilerType voidp_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + + // platform-specific types + CompilerType &pid_type = int_type; + CompilerType &uid_type = uint_type; + + CompilerType sigval_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t", + clang::TTK_Union, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(sigval_type); + ast->AddFieldToRecordType(sigval_type, "sival_int", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(sigval_type, "sival_ptr", voidp_type, + lldb::eAccessPublic, 0); + ast->CompleteTagDeclarationDefinition(sigval_type); + + // siginfo_t + CompilerType siginfo_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t", + clang::TTK_Struct, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(siginfo_type); + ast->AddFieldToRecordType(siginfo_type, "si_signo", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_errno", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_code", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_pid", pid_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_uid", uid_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_status", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_addr", voidp_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_value", sigval_type, + lldb::eAccessPublic, 0); + + // union used to hold the signal data + CompilerType union_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", + clang::TTK_Union, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(union_type); + + ast->AddFieldToRecordType( + union_type, "_fault", + ast->CreateStructForIdentifier(ConstString(), + { + {"_trapno", int_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_timer", + ast->CreateStructForIdentifier(ConstString(), + { + {"_timerid", int_type}, + {"_overrun", int_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_mesgq", + ast->CreateStructForIdentifier(ConstString(), + { + {"_mqd", int_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_poll", + ast->CreateStructForIdentifier(ConstString(), + { + {"_band", long_type}, + }), + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(union_type); + ast->AddFieldToRecordType(siginfo_type, "_reason", union_type, + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(siginfo_type); + return siginfo_type; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h index fd37b13de017..7f9dfd87a59a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_PLATFORM_FREEBSD_PLATFORMFREEBSD_H #include "Plugins/Platform/POSIX/PlatformPOSIX.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" namespace lldb_private { namespace platform_freebsd { @@ -53,7 +54,12 @@ public: unsigned flags, lldb::addr_t fd, lldb::addr_t offset) override; + CompilerType GetSiginfoType(const llvm::Triple &triple) override; + std::vector<ArchSpec> m_supported_architectures; + +private: + std::unique_ptr<TypeSystemClang> m_type_system_up; }; } // namespace platform_freebsd diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index 552b3890615c..ddba64bc5d11 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -202,3 +202,144 @@ MmapArgList PlatformNetBSD::GetMmapArgumentList(const ArchSpec &arch, MmapArgList args({addr, length, prot, flags_platform, fd, offset}); return args; } + +CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) { + if (!m_type_system_up) + m_type_system_up.reset(new TypeSystemClang("siginfo", triple)); + TypeSystemClang *ast = m_type_system_up.get(); + + // generic types + CompilerType int_type = ast->GetBasicType(eBasicTypeInt); + CompilerType uint_type = ast->GetBasicType(eBasicTypeUnsignedInt); + CompilerType long_type = ast->GetBasicType(eBasicTypeLong); + CompilerType long_long_type = ast->GetBasicType(eBasicTypeLongLong); + CompilerType voidp_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + + // platform-specific types + CompilerType &pid_type = int_type; + CompilerType &uid_type = uint_type; + CompilerType &clock_type = uint_type; + CompilerType &lwpid_type = int_type; + + CompilerType sigval_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t", + clang::TTK_Union, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(sigval_type); + ast->AddFieldToRecordType(sigval_type, "sival_int", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(sigval_type, "sival_ptr", voidp_type, + lldb::eAccessPublic, 0); + ast->CompleteTagDeclarationDefinition(sigval_type); + + CompilerType ptrace_option_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", + clang::TTK_Union, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(ptrace_option_type); + ast->AddFieldToRecordType(ptrace_option_type, "_pe_other_pid", pid_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(ptrace_option_type, "_pe_lwp", lwpid_type, + lldb::eAccessPublic, 0); + ast->CompleteTagDeclarationDefinition(ptrace_option_type); + + // siginfo_t + CompilerType siginfo_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t", + clang::TTK_Union, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(siginfo_type); + + // struct _ksiginfo + CompilerType ksiginfo_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", + clang::TTK_Struct, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(ksiginfo_type); + ast->AddFieldToRecordType(ksiginfo_type, "_signo", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(ksiginfo_type, "_code", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(ksiginfo_type, "_errno", int_type, + lldb::eAccessPublic, 0); + + // the structure is padded on 64-bit arches to fix alignment + if (triple.isArch64Bit()) + ast->AddFieldToRecordType(ksiginfo_type, "__pad0", int_type, + lldb::eAccessPublic, 0); + + // union used to hold the signal data + CompilerType union_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", + clang::TTK_Union, lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(union_type); + + ast->AddFieldToRecordType( + union_type, "_rt", + ast->CreateStructForIdentifier(ConstString(), + { + {"_pid", pid_type}, + {"_uid", uid_type}, + {"_value", sigval_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_child", + ast->CreateStructForIdentifier(ConstString(), + { + {"_pid", pid_type}, + {"_uid", uid_type}, + {"_status", int_type}, + {"_utime", clock_type}, + {"_stime", clock_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_fault", + ast->CreateStructForIdentifier(ConstString(), + { + {"_addr", voidp_type}, + {"_trap", int_type}, + {"_trap2", int_type}, + {"_trap3", int_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_poll", + ast->CreateStructForIdentifier(ConstString(), + { + {"_band", long_type}, + {"_fd", int_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType(union_type, "_syscall", + ast->CreateStructForIdentifier( + ConstString(), + { + {"_sysnum", int_type}, + {"_retval", int_type.GetArrayType(2)}, + {"_error", int_type}, + {"_args", long_long_type.GetArrayType(8)}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_ptrace_state", + ast->CreateStructForIdentifier(ConstString(), + { + {"_pe_report_event", int_type}, + {"_option", ptrace_option_type}, + }), + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(union_type); + ast->AddFieldToRecordType(ksiginfo_type, "_reason", union_type, + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(ksiginfo_type); + ast->AddFieldToRecordType(siginfo_type, "_info", ksiginfo_type, + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(siginfo_type); + return siginfo_type; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h index 7158fbd26efb..433cf6653126 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_PLATFORM_NETBSD_PLATFORMNETBSD_H #include "Plugins/Platform/POSIX/PlatformPOSIX.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" namespace lldb_private { namespace platform_netbsd { @@ -55,7 +56,12 @@ public: unsigned flags, lldb::addr_t fd, lldb::addr_t offset) override; + CompilerType GetSiginfoType(const llvm::Triple &triple) override; + std::vector<ArchSpec> m_supported_architectures; + +private: + std::unique_ptr<TypeSystemClang> m_type_system_up; }; } // namespace platform_netbsd diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp index 67c9484680a4..dd7546d8fa15 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp @@ -162,7 +162,10 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, Target &target, Status &error) { Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - std::string qemu = GetGlobalProperties().GetEmulatorPath().GetPath(); + FileSpec qemu = GetGlobalProperties().GetEmulatorPath(); + if (!qemu) + qemu.SetPath(("qemu-" + GetGlobalProperties().GetArchitecture()).str()); + FileSystem::Instance().ResolveExecutableLocation(qemu); llvm::SmallString<0> socket_model, socket_path; HostInfo::GetProcessTempDir().GetPath(socket_model); @@ -171,7 +174,11 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, llvm::sys::fs::createUniquePath(socket_model, socket_path, false); } while (FileSystem::Instance().Exists(socket_path)); - Args args({qemu, "-g", socket_path}); + Args args({qemu.GetPath(), "-g", socket_path}); + if (!launch_info.GetArg0().empty()) { + args.AppendArgument("-0"); + args.AppendArgument(launch_info.GetArg0()); + } args.AppendArguments(GetGlobalProperties().GetEmulatorArgs()); args.AppendArgument("--"); args.AppendArgument(launch_info.GetExecutableFile().GetPath()); @@ -184,6 +191,8 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, launch_info.SetArguments(args, true); Environment emulator_env = Host::GetEnvironment(); + if (ConstString sysroot = GetSDKRootDirectory()) + emulator_env["QEMU_LD_PREFIX"] = sysroot.GetStringRef().str(); for (const auto &KV : GetGlobalProperties().GetEmulatorEnvVars()) emulator_env[KV.first()] = KV.second; launch_info.GetEnvironment() = ComputeLaunchEnvironment( diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h index 71df1b7b7811..c5439e126db1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h @@ -47,6 +47,14 @@ public: Environment GetEnvironment() override; + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override { + return Platform::GetHostPlatform()->GetMmapArgumentList( + arch, addr, length, prot, flags, fd, offset); + } + private: static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); static void DebuggerInitialize(Debugger &debugger); diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td index 4e8fbcfd6760..c7ec4bbc6e78 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td @@ -8,7 +8,7 @@ let Definition = "platformqemuuser" in { def EmulatorPath: Property<"emulator-path", "FileSpec">, Global, DefaultStringValue<"">, - Desc<"Path to the emulator binary.">; + Desc<"Path to the emulator binary. If the path does not contain a directory separator, the filename is looked up in the PATH environment variable. If empty, the filename is derived from the architecture setting.">; def EmulatorArgs: Property<"emulator-args", "Args">, Global, DefaultStringValue<"">, diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 3535a5ad739d..0929a060d0b8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -96,7 +96,8 @@ bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec, const auto module_path = module_file_spec.GetPath(false); - if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) { + if (!m_gdb_client_up || + !m_gdb_client_up->GetModuleInfo(module_file_spec, arch, module_spec)) { LLDB_LOGF( log, "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", @@ -127,11 +128,7 @@ Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file, /// Default Constructor PlatformRemoteGDBServer::PlatformRemoteGDBServer() - : Platform(false), // This is a remote platform - m_gdb_client() { - m_gdb_client.SetPacketTimeout( - process_gdb_remote::ProcessGDBRemote::GetPacketTimeout()); -} + : Platform(/*is_host=*/false) {} /// Destructor. /// @@ -147,29 +144,36 @@ size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode( } bool PlatformRemoteGDBServer::GetRemoteOSVersion() { - m_os_version = m_gdb_client.GetOSVersion(); + if (m_gdb_client_up) + m_os_version = m_gdb_client_up->GetOSVersion(); return !m_os_version.empty(); } llvm::Optional<std::string> PlatformRemoteGDBServer::GetRemoteOSBuildString() { - return m_gdb_client.GetOSBuildString(); + if (!m_gdb_client_up) + return llvm::None; + return m_gdb_client_up->GetOSBuildString(); } llvm::Optional<std::string> PlatformRemoteGDBServer::GetRemoteOSKernelDescription() { - return m_gdb_client.GetOSKernelDescription(); + if (!m_gdb_client_up) + return llvm::None; + return m_gdb_client_up->GetOSKernelDescription(); } // Remote Platform subclasses need to override this function ArchSpec PlatformRemoteGDBServer::GetRemoteSystemArchitecture() { - return m_gdb_client.GetSystemArchitecture(); + if (!m_gdb_client_up) + return ArchSpec(); + return m_gdb_client_up->GetSystemArchitecture(); } FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() { if (IsConnected()) { Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); FileSpec working_dir; - if (m_gdb_client.GetWorkingDir(working_dir) && log) + if (m_gdb_client_up->GetWorkingDir(working_dir) && log) LLDB_LOGF(log, "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", working_dir.GetCString()); @@ -187,13 +191,17 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", working_dir.GetCString()); - return m_gdb_client.SetWorkingDir(working_dir) == 0; + return m_gdb_client_up->SetWorkingDir(working_dir) == 0; } else return Platform::SetRemoteWorkingDirectory(working_dir); } bool PlatformRemoteGDBServer::IsConnected() const { - return m_gdb_client.IsConnected(); + if (m_gdb_client_up) { + assert(m_gdb_client_up->IsConnected()); + return true; + } + return false; } Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { @@ -224,26 +232,31 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { m_platform_scheme = parsed_url->scheme.str(); m_platform_hostname = parsed_url->hostname.str(); - m_gdb_client.SetConnection(std::make_unique<ConnectionFileDescriptor>()); + auto client_up = + std::make_unique<process_gdb_remote::GDBRemoteCommunicationClient>(); + client_up->SetPacketTimeout( + process_gdb_remote::ProcessGDBRemote::GetPacketTimeout()); + client_up->SetConnection(std::make_unique<ConnectionFileDescriptor>()); if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { repro::GDBRemoteProvider &provider = g->GetOrCreate<repro::GDBRemoteProvider>(); - m_gdb_client.SetPacketRecorder(provider.GetNewPacketRecorder()); + client_up->SetPacketRecorder(provider.GetNewPacketRecorder()); } - m_gdb_client.Connect(url, &error); + client_up->Connect(url, &error); if (error.Fail()) return error; - if (m_gdb_client.HandshakeWithServer(&error)) { - m_gdb_client.GetHostInfo(); + if (client_up->HandshakeWithServer(&error)) { + m_gdb_client_up = std::move(client_up); + m_gdb_client_up->GetHostInfo(); // If a working directory was set prior to connecting, send it down // now. if (m_working_dir) - m_gdb_client.SetWorkingDir(m_working_dir); + m_gdb_client_up->SetWorkingDir(m_working_dir); m_supported_architectures.clear(); - ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); + ArchSpec remote_arch = m_gdb_client_up->GetSystemArchitecture(); if (remote_arch) { m_supported_architectures.push_back(remote_arch); if (remote_arch.GetTriple().isArch64Bit()) @@ -251,7 +264,7 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { ArchSpec(remote_arch.GetTriple().get32BitArchVariant())); } } else { - m_gdb_client.Disconnect(); + client_up->Disconnect(); if (error.Success()) error.SetErrorString("handshake failed"); } @@ -260,13 +273,14 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { Status PlatformRemoteGDBServer::DisconnectRemote() { Status error; - m_gdb_client.Disconnect(&error); + m_gdb_client_up.reset(); m_remote_signals_sp.reset(); return error; } const char *PlatformRemoteGDBServer::GetHostname() { - m_gdb_client.GetHostname(m_name); + if (m_gdb_client_up) + m_gdb_client_up->GetHostname(m_name); if (m_name.empty()) return nullptr; return m_name.c_str(); @@ -275,7 +289,7 @@ const char *PlatformRemoteGDBServer::GetHostname() { llvm::Optional<std::string> PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) { std::string name; - if (m_gdb_client.GetUserName(uid, name)) + if (m_gdb_client_up && m_gdb_client_up->GetUserName(uid, name)) return std::move(name); return llvm::None; } @@ -283,7 +297,7 @@ PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) { llvm::Optional<std::string> PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) { std::string name; - if (m_gdb_client.GetGroupName(gid, name)) + if (m_gdb_client_up && m_gdb_client_up->GetGroupName(gid, name)) return std::move(name); return llvm::None; } @@ -291,12 +305,16 @@ PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) { uint32_t PlatformRemoteGDBServer::FindProcesses( const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { - return m_gdb_client.FindProcesses(match_info, process_infos); + if (m_gdb_client_up) + return m_gdb_client_up->FindProcesses(match_info, process_infos); + return 0; } bool PlatformRemoteGDBServer::GetProcessInfo( lldb::pid_t pid, ProcessInstanceInfo &process_info) { - return m_gdb_client.GetProcessInfo(pid, process_info); + if (m_gdb_client_up) + return m_gdb_client_up->GetProcessInfo(pid, process_info); + return false; } Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { @@ -305,6 +323,8 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() called", __FUNCTION__); + if (!IsConnected()) + return Status("Not connected."); auto num_file_actions = launch_info.GetNumFileActions(); for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) { const auto file_action = launch_info.GetFileActionAtIndex(i); @@ -312,34 +332,34 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { continue; switch (file_action->GetFD()) { case STDIN_FILENO: - m_gdb_client.SetSTDIN(file_action->GetFileSpec()); + m_gdb_client_up->SetSTDIN(file_action->GetFileSpec()); break; case STDOUT_FILENO: - m_gdb_client.SetSTDOUT(file_action->GetFileSpec()); + m_gdb_client_up->SetSTDOUT(file_action->GetFileSpec()); break; case STDERR_FILENO: - m_gdb_client.SetSTDERR(file_action->GetFileSpec()); + m_gdb_client_up->SetSTDERR(file_action->GetFileSpec()); break; } } - m_gdb_client.SetDisableASLR( + m_gdb_client_up->SetDisableASLR( launch_info.GetFlags().Test(eLaunchFlagDisableASLR)); - m_gdb_client.SetDetachOnError( + m_gdb_client_up->SetDetachOnError( launch_info.GetFlags().Test(eLaunchFlagDetachOnError)); FileSpec working_dir = launch_info.GetWorkingDirectory(); if (working_dir) { - m_gdb_client.SetWorkingDir(working_dir); + m_gdb_client_up->SetWorkingDir(working_dir); } // Send the environment and the program + arguments after we connect - m_gdb_client.SendEnvironment(launch_info.GetEnvironment()); + m_gdb_client_up->SendEnvironment(launch_info.GetEnvironment()); ArchSpec arch_spec = launch_info.GetArchitecture(); const char *arch_triple = arch_spec.GetTriple().str().c_str(); - m_gdb_client.SendLaunchArchPacket(arch_triple); + m_gdb_client_up->SendLaunchArchPacket(arch_triple); LLDB_LOGF( log, "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", @@ -349,14 +369,14 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { { // Scope for the scoped timeout object process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout( - m_gdb_client, std::chrono::seconds(5)); - arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info); + *m_gdb_client_up, std::chrono::seconds(5)); + arg_packet_err = m_gdb_client_up->SendArgumentsPacket(launch_info); } if (arg_packet_err == 0) { std::string error_str; - if (m_gdb_client.GetLaunchSuccess(error_str)) { - const auto pid = m_gdb_client.GetCurrentProcessID(false); + if (m_gdb_client_up->GetLaunchSuccess(error_str)) { + const auto pid = m_gdb_client_up->GetCurrentProcessID(false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID(pid); LLDB_LOGF(log, @@ -428,6 +448,8 @@ PlatformRemoteGDBServer::DebugProcess(ProcessLaunchInfo &launch_info, bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) { + assert(IsConnected()); + ArchSpec remote_arch = GetRemoteSystemArchitecture(); llvm::Triple &remote_triple = remote_arch.GetTriple(); @@ -440,11 +462,11 @@ bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, // localhost, so we will need the remote debugserver to accept connections // only from localhost, no matter what our current hostname is launch_result = - m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name); + m_gdb_client_up->LaunchGDBServer("127.0.0.1", pid, port, socket_name); } else { // All other hosts should use their actual hostname launch_result = - m_gdb_client.LaunchGDBServer(nullptr, pid, port, socket_name); + m_gdb_client_up->LaunchGDBServer(nullptr, pid, port, socket_name); } if (!launch_result) @@ -457,7 +479,8 @@ bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, } bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { - return m_gdb_client.KillSpawnedProcess(pid); + assert(IsConnected()); + return m_gdb_client_up->KillSpawnedProcess(pid); } lldb::ProcessSP PlatformRemoteGDBServer::Attach( @@ -513,7 +536,9 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach( Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode) { - Status error = m_gdb_client.MakeDirectory(file_spec, mode); + if (!IsConnected()) + return Status("Not connected."); + Status error = m_gdb_client_up->MakeDirectory(file_spec, mode); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); LLDB_LOGF(log, "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " @@ -524,7 +549,10 @@ Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) { - Status error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); + if (!IsConnected()) + return Status("Not connected."); + Status error = + m_gdb_client_up->GetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); LLDB_LOGF(log, "PlatformRemoteGDBServer::GetFilePermissions(path='%s', " @@ -536,7 +564,10 @@ Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) { - Status error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); + if (!IsConnected()) + return Status("Not connected."); + Status error = + m_gdb_client_up->SetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); LLDB_LOGF(log, "PlatformRemoteGDBServer::SetFilePermissions(path='%s', " @@ -550,33 +581,47 @@ lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec, File::OpenOptions flags, uint32_t mode, Status &error) { - return m_gdb_client.OpenFile(file_spec, flags, mode, error); + if (IsConnected()) + return m_gdb_client_up->OpenFile(file_spec, flags, mode, error); + return LLDB_INVALID_UID; } bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd, Status &error) { - return m_gdb_client.CloseFile(fd, error); + if (IsConnected()) + return m_gdb_client_up->CloseFile(fd, error); + error = Status("Not connected."); + return false; } lldb::user_id_t PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) { - return m_gdb_client.GetFileSize(file_spec); + if (IsConnected()) + return m_gdb_client_up->GetFileSize(file_spec); + return LLDB_INVALID_UID; } void PlatformRemoteGDBServer::AutoCompleteDiskFileOrDirectory( CompletionRequest &request, bool only_dir) { - m_gdb_client.AutoCompleteDiskFileOrDirectory(request, only_dir); + if (IsConnected()) + m_gdb_client_up->AutoCompleteDiskFileOrDirectory(request, only_dir); } uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Status &error) { - return m_gdb_client.ReadFile(fd, offset, dst, dst_len, error); + if (IsConnected()) + return m_gdb_client_up->ReadFile(fd, offset, dst, dst_len, error); + error = Status("Not connected."); + return 0; } uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Status &error) { - return m_gdb_client.WriteFile(fd, offset, src, src_len, error); + if (IsConnected()) + return m_gdb_client_up->WriteFile(fd, offset, src, src_len, error); + error = Status("Not connected."); + return 0; } Status PlatformRemoteGDBServer::PutFile(const FileSpec &source, @@ -589,7 +634,9 @@ Status PlatformRemoteGDBServer::CreateSymlink( const FileSpec &src, // The name of the link is in src const FileSpec &dst) // The symlink points to dst { - Status error = m_gdb_client.CreateSymlink(src, dst); + if (!IsConnected()) + return Status("Not connected."); + Status error = m_gdb_client_up->CreateSymlink(src, dst); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); LLDB_LOGF(log, "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " @@ -600,7 +647,9 @@ Status PlatformRemoteGDBServer::CreateSymlink( } Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { - Status error = m_gdb_client.Unlink(file_spec); + if (!IsConnected()) + return Status("Not connected."); + Status error = m_gdb_client_up->Unlink(file_spec); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", file_spec.GetCString(), error.GetError(), error.AsCString()); @@ -608,7 +657,9 @@ Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { } bool PlatformRemoteGDBServer::GetFileExists(const FileSpec &file_spec) { - return m_gdb_client.GetFileExists(file_spec); + if (IsConnected()) + return m_gdb_client_up->GetFileExists(file_spec); + return false; } Status PlatformRemoteGDBServer::RunShellCommand( @@ -621,8 +672,10 @@ Status PlatformRemoteGDBServer::RunShellCommand( std::string *command_output, // Pass NULL if you don't want the command output const Timeout<std::micro> &timeout) { - return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, - signo_ptr, command_output, timeout); + if (!IsConnected()) + return Status("Not connected."); + return m_gdb_client_up->RunShellCommand(command, working_dir, status_ptr, + signo_ptr, command_output, timeout); } void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() { @@ -642,7 +695,7 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { StringExtractorGDBRemote response; auto result = - m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", response); + m_gdb_client_up->SendPacketAndWaitForResponse("jSignalsInfo", response); if (result != decltype(result)::Success || response.GetResponseType() != response.eResponse) @@ -693,7 +746,7 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { if (object_sp && object_sp->IsValid()) notify = object_sp->GetBooleanValue(); - std::string description{""}; + std::string description; object_sp = dict->GetValueForKey("description"); if (object_sp && object_sp->IsValid()) description = std::string(object_sp->GetStringValue()); @@ -754,7 +807,9 @@ size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger, size_t PlatformRemoteGDBServer::GetPendingGdbServerList( std::vector<std::string> &connection_urls) { std::vector<std::pair<uint16_t, std::string>> remote_servers; - m_gdb_client.QueryGDBServer(remote_servers); + if (!IsConnected()) + return 0; + m_gdb_client_up->QueryGDBServer(remote_servers); for (const auto &gdbserver : remote_servers) { const char *socket_name_cstr = gdbserver.second.empty() ? nullptr : gdbserver.second.c_str(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index f594f43b3f13..263516f520d5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -14,7 +14,6 @@ #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" -#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h" #include "lldb/Target/Platform.h" namespace lldb_private { @@ -154,8 +153,8 @@ public: GetPendingGdbServerList(std::vector<std::string> &connection_urls); protected: - process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client; - process_gdb_remote::GDBRemoteCommunicationReplayServer m_gdb_replay_server; + std::unique_ptr<process_gdb_remote::GDBRemoteCommunicationClient> + m_gdb_client_up; std::string m_platform_description; // After we connect we can get a more // complete description of what we are // connected to diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp index a62d3c1ba052..21c9ead0eca4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp @@ -54,7 +54,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>> NativeProcessFreeBSD::Factory::Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, MainLoop &mainloop) const { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); Status status; ::pid_t pid = ProcessLauncherPosixFork() @@ -108,7 +108,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>> NativeProcessFreeBSD::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop) const { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. @@ -135,7 +135,8 @@ NativeProcessFreeBSD::Factory::GetSupportedExtensions() const { Extension::savecore | #endif Extension::multiprocess | Extension::fork | Extension::vfork | - Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; + Extension::pass_signals | Extension::auxv | Extension::libraries_svr4 | + Extension::siginfo_read; } // Public Instance Methods @@ -170,7 +171,7 @@ void NativeProcessFreeBSD::MonitorCallback(lldb::pid_t pid, int signal) { } void NativeProcessFreeBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid); @@ -193,7 +194,7 @@ void NativeProcessFreeBSD::MonitorSIGSTOP(lldb::pid_t pid) { } void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); struct ptrace_lwpinfo info; const auto siginfo_err = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info)); @@ -254,6 +255,7 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) { for (const auto &thread : m_threads) static_cast<NativeThreadFreeBSD &>(*thread).SetStoppedByExec(); + SetCurrentThreadID(m_threads.front()->GetID()); SetState(StateType::eStateStopped, true); return; } @@ -312,6 +314,7 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) { } else thread->SetStoppedByBreakpoint(); FixupBreakpointPCAsNeeded(*thread); + SetCurrentThreadID(thread->GetID()); } SetState(StateType::eStateStopped, true); return; @@ -333,11 +336,13 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) { if (wp_index != LLDB_INVALID_INDEX32) { regctx.ClearWatchpointHit(wp_index); thread->SetStoppedByWatchpoint(wp_index); + SetCurrentThreadID(thread->GetID()); SetState(StateType::eStateStopped, true); break; } thread->SetStoppedByTrace(); + SetCurrentThreadID(thread->GetID()); } SetState(StateType::eStateStopped, true); @@ -352,7 +357,7 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) { } void NativeProcessFreeBSD::MonitorSignal(lldb::pid_t pid, int signal) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); struct ptrace_lwpinfo info; const auto siginfo_err = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info)); @@ -370,9 +375,10 @@ void NativeProcessFreeBSD::MonitorSignal(lldb::pid_t pid, int signal) { static_cast<NativeThreadFreeBSD &>(*abs_thread); assert(info.pl_lwpid >= 0); if (info.pl_lwpid == 0 || - static_cast<lldb::tid_t>(info.pl_lwpid) == thread.GetID()) + static_cast<lldb::tid_t>(info.pl_lwpid) == thread.GetID()) { thread.SetStoppedBySignal(info.pl_siginfo.si_signo, &info.pl_siginfo); - else + SetCurrentThreadID(thread.GetID()); + } else thread.SetStoppedWithNoReason(); } SetState(StateType::eStateStopped, true); @@ -380,7 +386,7 @@ void NativeProcessFreeBSD::MonitorSignal(lldb::pid_t pid, int signal) { Status NativeProcessFreeBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, int *result) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Log *log = GetLog(POSIXLog::Ptrace); Status error; int ret; @@ -424,7 +430,7 @@ NativeProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { } Status NativeProcessFreeBSD::Resume(const ResumeActionList &resume_actions) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "pid {0}", GetID()); Status ret; @@ -521,7 +527,7 @@ Status NativeProcessFreeBSD::Signal(int signo) { Status NativeProcessFreeBSD::Interrupt() { return Halt(); } Status NativeProcessFreeBSD::Kill() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "pid {0}", GetID()); Status error; @@ -608,7 +614,7 @@ Status NativeProcessFreeBSD::GetMemoryRegionInfo(lldb::addr_t load_addr, } Status NativeProcessFreeBSD::PopulateMemoryRegionCache() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); // If our cache is empty, pull the latest. There should always be at least // one memory region if memory region handling is supported. if (!m_mem_region_cache.empty()) { @@ -735,7 +741,7 @@ NativeProcessFreeBSD::GetFileLoadAddress(const llvm::StringRef &file_name, } void NativeProcessFreeBSD::SigchldHandler() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); int status; ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG); @@ -780,7 +786,7 @@ bool NativeProcessFreeBSD::HasThreadNoLock(lldb::tid_t thread_id) { } NativeThreadFreeBSD &NativeProcessFreeBSD::AddThread(lldb::tid_t thread_id) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); assert(thread_id > 0); @@ -796,7 +802,7 @@ NativeThreadFreeBSD &NativeProcessFreeBSD::AddThread(lldb::tid_t thread_id) { } void NativeProcessFreeBSD::RemoveThread(lldb::tid_t thread_id) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id); assert(thread_id > 0); @@ -809,6 +815,9 @@ void NativeProcessFreeBSD::RemoveThread(lldb::tid_t thread_id) { break; } } + + if (GetCurrentThreadID() == thread_id) + SetCurrentThreadID(m_threads.front()->GetID()); } Status NativeProcessFreeBSD::Attach() { @@ -845,7 +854,7 @@ Status NativeProcessFreeBSD::ReadMemory(lldb::addr_t addr, void *buf, unsigned char *dst = static_cast<unsigned char *>(buf); struct ptrace_io_desc io; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + Log *log = GetLog(POSIXLog::Memory); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); bytes_read = 0; @@ -873,7 +882,7 @@ Status NativeProcessFreeBSD::WriteMemory(lldb::addr_t addr, const void *buf, Status error; struct ptrace_io_desc io; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + Log *log = GetLog(POSIXLog::Memory); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); bytes_written = 0; @@ -953,7 +962,7 @@ bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const { void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork, NativeThreadFreeBSD &parent_thread) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "fork, child_pid={0}", child_pid); int status; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp index 4578138a89b3..143d94069bc6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp @@ -227,7 +227,7 @@ llvm::Error NativeRegisterContextFreeBSD_arm64::CopyHardwareWatchpointsFrom( llvm::Error NativeRegisterContextFreeBSD_arm64::ReadHardwareDebugInfo() { #ifdef LLDB_HAS_FREEBSD_WATCHPOINT - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); + Log *log = GetLog(POSIXLog::Registers); // we're fully stateful, so no need to reread control registers ever if (m_read_dbreg) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp index 80b3527aebce..a75668f3b5c7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp @@ -75,7 +75,7 @@ Status NativeThreadFreeBSD::Suspend() { void NativeThreadFreeBSD::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); SetStopped(); @@ -178,7 +178,7 @@ void NativeThreadFreeBSD::SetStepping() { } std::string NativeThreadFreeBSD::GetName() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); std::vector<struct kinfo_proc> kp; int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, @@ -213,7 +213,7 @@ lldb::StateType NativeThreadFreeBSD::GetState() { return m_state; } bool NativeThreadFreeBSD::GetStopReason(ThreadStopInfo &stop_info, std::string &description) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); description.clear(); switch (m_state) { @@ -313,3 +313,27 @@ NativeThreadFreeBSD::CopyWatchpointsFrom(NativeThreadFreeBSD &source) { } return s; } + +llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> +NativeThreadFreeBSD::GetSiginfo() const { + Log *log = GetLog(POSIXLog::Process); + + struct ptrace_lwpinfo info; + const auto siginfo_err = NativeProcessFreeBSD::PtraceWrapper( + PT_LWPINFO, GetID(), &info, sizeof(info)); + if (siginfo_err.Fail()) { + LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err); + return siginfo_err.ToError(); + } + + if (info.pl_event != PL_EVENT_SIGNAL) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Thread not signaled"); + if (!(info.pl_flags & PL_FLAG_SI)) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "No siginfo for thread"); + + return llvm::MemoryBuffer::getMemBufferCopy( + llvm::StringRef(reinterpret_cast<const char *>(&info.pl_siginfo), + sizeof(info.pl_siginfo))); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h index 3ec6daa409e4..6294a7a70963 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h @@ -47,6 +47,9 @@ public: Status RemoveHardwareBreakpoint(lldb::addr_t addr) override; + llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + GetSiginfo() const override; + private: // Interface for friend classes diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp index 339d33d25110..e3707365a9c3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp @@ -137,12 +137,115 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list, return false; } - const Symbol *pcb_sym = - GetTarget().GetExecutableModule()->FindFirstSymbolWithNameAndType( - ConstString("dumppcb")); - ThreadSP thread_sp(new ThreadFreeBSDKernel( - *this, 1, pcb_sym ? pcb_sym->GetFileAddress() : LLDB_INVALID_ADDRESS)); - new_thread_list.AddThread(thread_sp); + Status error; + + // struct field offsets are written as symbols so that we don't have + // to figure them out ourselves + int32_t offset_p_list = ReadSignedIntegerFromMemory( + FindSymbol("proc_off_p_list"), 4, -1, error); + int32_t offset_p_pid = + ReadSignedIntegerFromMemory(FindSymbol("proc_off_p_pid"), 4, -1, error); + int32_t offset_p_threads = ReadSignedIntegerFromMemory( + FindSymbol("proc_off_p_threads"), 4, -1, error); + int32_t offset_p_comm = ReadSignedIntegerFromMemory( + FindSymbol("proc_off_p_comm"), 4, -1, error); + + int32_t offset_td_tid = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_tid"), 4, -1, error); + int32_t offset_td_plist = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_plist"), 4, -1, error); + int32_t offset_td_pcb = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_pcb"), 4, -1, error); + int32_t offset_td_oncpu = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_oncpu"), 4, -1, error); + int32_t offset_td_name = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_name"), 4, -1, error); + + // fail if we were not able to read any of the offsets + if (offset_p_list == -1 || offset_p_pid == -1 || offset_p_threads == -1 || + offset_p_comm == -1 || offset_td_tid == -1 || offset_td_plist == -1 || + offset_td_pcb == -1 || offset_td_oncpu == -1 || offset_td_name == -1) + return false; + + // dumptid contains the thread-id of the crashing thread + // dumppcb contains its PCB + int32_t dumptid = + ReadSignedIntegerFromMemory(FindSymbol("dumptid"), 4, -1, error); + lldb::addr_t dumppcb = FindSymbol("dumppcb"); + + // stoppcbs is an array of PCBs on all CPUs + // each element is of size pcb_size + int32_t pcbsize = + ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error); + lldb::addr_t stoppcbs = FindSymbol("stoppcbs"); + + // from FreeBSD sys/param.h + constexpr size_t fbsd_maxcomlen = 19; + + // iterate through a linked list of all processes + // allproc is a pointer to the first list element, p_list field + // (found at offset_p_list) specifies the next element + for (lldb::addr_t proc = + ReadPointerFromMemory(FindSymbol("allproc"), error); + proc != 0 && proc != LLDB_INVALID_ADDRESS; + proc = ReadPointerFromMemory(proc + offset_p_list, error)) { + int32_t pid = + ReadSignedIntegerFromMemory(proc + offset_p_pid, 4, -1, error); + // process' command-line string + char comm[fbsd_maxcomlen + 1]; + ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error); + + // iterate through a linked list of all process' threads + // the initial thread is found in process' p_threads, subsequent + // elements are linked via td_plist field + for (lldb::addr_t td = + ReadPointerFromMemory(proc + offset_p_threads, error); + td != 0; td = ReadPointerFromMemory(td + offset_td_plist, error)) { + int32_t tid = + ReadSignedIntegerFromMemory(td + offset_td_tid, 4, -1, error); + lldb::addr_t pcb_addr = + ReadPointerFromMemory(td + offset_td_pcb, error); + // whether process was on CPU (-1 if not, otherwise CPU number) + int32_t oncpu = + ReadSignedIntegerFromMemory(td + offset_td_oncpu, 4, -2, error); + // thread name + char thread_name[fbsd_maxcomlen + 1]; + ReadCStringFromMemory(td + offset_td_name, thread_name, + sizeof(thread_name), error); + + // if we failed to read TID, ignore this thread + if (tid == -1) + continue; + + std::string thread_desc = llvm::formatv("(pid {0}) {1}", pid, comm); + if (*thread_name && strcmp(thread_name, comm)) { + thread_desc += '/'; + thread_desc += thread_name; + } + + // roughly: + // 1. if the thread crashed, its PCB is going to be at "dumppcb" + // 2. if the thread was on CPU, its PCB is going to be on the CPU + // 3. otherwise, its PCB is in the thread struct + if (tid == dumptid) { + // NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed + pcb_addr = dumppcb; + thread_desc += " (crashed)"; + } else if (oncpu != -1) { + // if we managed to read stoppcbs and pcb_size, use them to find + // the correct PCB + if (stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0) + pcb_addr = stoppcbs + oncpu * pcbsize; + else + pcb_addr = LLDB_INVALID_ADDRESS; + thread_desc += llvm::formatv(" (on CPU {0})", oncpu); + } + + ThreadSP thread_sp{ + new ThreadFreeBSDKernel(*this, tid, pcb_addr, thread_desc)}; + new_thread_list.AddThread(thread_sp); + } + } } else { const uint32_t num_threads = old_thread_list.GetSize(false); for (uint32_t i = 0; i < num_threads; ++i) @@ -163,6 +266,12 @@ DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() { return m_dyld_up.get(); } +lldb::addr_t ProcessFreeBSDKernel::FindSymbol(const char *name) { + ModuleSP mod_sp = GetTarget().GetExecutableModule(); + const Symbol *sym = mod_sp->FindFirstSymbolWithNameAndType(ConstString(name)); + return sym ? sym->GetLoadAddress(&GetTarget()) : LLDB_INVALID_ADDRESS; +} + #if LLDB_ENABLE_FBSDVMCORE ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h index 558eec5403db..5bd463126307 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h @@ -46,6 +46,8 @@ public: protected: bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override; + + lldb::addr_t FindSymbol(const char* name); }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp index 124c65d587ff..8d304086a163 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp @@ -24,8 +24,10 @@ using namespace lldb; using namespace lldb_private; ThreadFreeBSDKernel::ThreadFreeBSDKernel(Process &process, lldb::tid_t tid, - lldb::addr_t pcb_addr) - : Thread(process, tid), m_pcb_addr(pcb_addr) {} + lldb::addr_t pcb_addr, + std::string thread_name) + : Thread(process, tid), m_thread_name(std::move(thread_name)), + m_pcb_addr(pcb_addr) {} ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {} @@ -61,9 +63,8 @@ ThreadFreeBSDKernel::CreateRegisterContextForFrame(StackFrame *frame) { m_pcb_addr); break; case llvm::Triple::x86: - m_thread_reg_ctx_sp = - std::make_shared<RegisterContextFreeBSDKernel_i386>( - *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr); + m_thread_reg_ctx_sp = std::make_shared<RegisterContextFreeBSDKernel_i386>( + *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr); break; case llvm::Triple::x86_64: m_thread_reg_ctx_sp = diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h index 2842eba64e56..3bc019b63e68 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h @@ -14,7 +14,7 @@ class ThreadFreeBSDKernel : public lldb_private::Thread { public: ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid, - lldb::addr_t pcb_addr); + lldb::addr_t pcb_addr, std::string thread_name); ~ThreadFreeBSDKernel() override; @@ -25,10 +25,24 @@ public: lldb::RegisterContextSP CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + const char *GetName() override { + if (m_thread_name.empty()) + return nullptr; + return m_thread_name.c_str(); + } + + void SetName(const char *name) override { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } + protected: bool CalculateStopInfo() override; private: + std::string m_thread_name; lldb::RegisterContextSP m_thread_reg_ctx_sp; lldb::addr_t m_pcb_addr; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 0420d00e39d6..182eefb7bee7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -59,7 +59,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>> NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, MainLoop &mainloop) const { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); Status status; ::pid_t pid = ProcessLauncherPosixFork() @@ -113,7 +113,7 @@ llvm::Expected<std::unique_ptr<NativeProcessProtocol>> NativeProcessNetBSD::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop) const { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. @@ -172,7 +172,7 @@ void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) { } void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid); @@ -207,7 +207,7 @@ void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { } void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); ptrace_siginfo_t info; const auto siginfo_err = @@ -359,7 +359,7 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { } void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); ptrace_siginfo_t info; const auto siginfo_err = @@ -383,7 +383,7 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, int *result) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Log *log = GetLog(POSIXLog::Ptrace); Status error; int ret; @@ -459,7 +459,7 @@ static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo( } Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "pid {0}", GetID()); Status ret; @@ -562,7 +562,7 @@ Status NativeProcessNetBSD::Interrupt() { } Status NativeProcessNetBSD::Kill() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "pid {0}", GetID()); Status error; @@ -654,7 +654,7 @@ Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr, } Status NativeProcessNetBSD::PopulateMemoryRegionCache() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); // If our cache is empty, pull the latest. There should always be at least // one memory region if memory region handling is supported. if (!m_mem_region_cache.empty()) { @@ -772,7 +772,7 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, } void NativeProcessNetBSD::SigchldHandler() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); int status; ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG); @@ -817,7 +817,7 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { } NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); assert(thread_id > 0); @@ -833,7 +833,7 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { } void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id); assert(thread_id > 0); @@ -882,7 +882,7 @@ Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf, unsigned char *dst = static_cast<unsigned char *>(buf); struct ptrace_io_desc io; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + Log *log = GetLog(POSIXLog::Memory); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); bytes_read = 0; @@ -910,7 +910,7 @@ Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf, Status error; struct ptrace_io_desc io; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + Log *log = GetLog(POSIXLog::Memory); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); bytes_written = 0; @@ -1013,7 +1013,7 @@ Status NativeProcessNetBSD::ReinitializeThreads() { void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork, NativeThreadNetBSD &parent_thread) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Log *log = GetLog(POSIXLog::Process); LLDB_LOG(log, "clone, child_pid={0}", child_pid); int status; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp index 400b89a5fddf..3e8cf9fd9f23 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -75,7 +75,7 @@ Status NativeThreadNetBSD::Suspend() { void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); SetStopped(); @@ -178,7 +178,7 @@ void NativeThreadNetBSD::SetStepping() { } std::string NativeThreadNetBSD::GetName() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); #ifdef PT_LWPSTATUS struct ptrace_lwpstatus info = {}; @@ -225,7 +225,7 @@ lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, std::string &description) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + Log *log = GetLog(POSIXLog::Thread); description.clear(); switch (m_state) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp index f4d0803b264a..7ad88aabc2c0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp @@ -13,16 +13,20 @@ using namespace lldb_private; static constexpr Log::Category g_categories[] = { - {{"break"}, {"log breakpoints"}, POSIX_LOG_BREAKPOINTS}, - {{"memory"}, {"log memory reads and writes"}, POSIX_LOG_MEMORY}, - {{"process"}, {"log process events and activities"}, POSIX_LOG_PROCESS}, - {{"ptrace"}, {"log all calls to ptrace"}, POSIX_LOG_PTRACE}, - {{"registers"}, {"log register read/writes"}, POSIX_LOG_REGISTERS}, - {{"thread"}, {"log thread events and activities"}, POSIX_LOG_THREAD}, - {{"watch"}, {"log watchpoint related activities"}, POSIX_LOG_WATCHPOINTS}, + {{"break"}, {"log breakpoints"}, POSIXLog::Breakpoints}, + {{"memory"}, {"log memory reads and writes"}, POSIXLog::Memory}, + {{"process"}, {"log process events and activities"}, POSIXLog::Process}, + {{"ptrace"}, {"log all calls to ptrace"}, POSIXLog::Ptrace}, + {{"registers"}, {"log register read/writes"}, POSIXLog::Registers}, + {{"thread"}, {"log thread events and activities"}, POSIXLog::Thread}, + {{"watch"}, {"log watchpoint related activities"}, POSIXLog::Watchpoints}, }; -Log::Channel ProcessPOSIXLog::g_channel(g_categories, POSIX_LOG_DEFAULT); +static Log::Channel g_channel(g_categories, POSIXLog::Process); + +template <> Log::Channel &lldb_private::LogChannelFor<POSIXLog>() { + return g_channel; +} void ProcessPOSIXLog::Initialize() { static llvm::once_flag g_once_flag; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h index c0147c43410f..7b8b6cdbf255 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h @@ -13,27 +13,25 @@ #include "lldb/Utility/Log.h" -#define POSIX_LOG_PROCESS (1u << 1) -#define POSIX_LOG_THREAD (1u << 2) -#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define POSIX_LOG_PTRACE (1u << 5) -#define POSIX_LOG_REGISTERS (1u << 6) -#define POSIX_LOG_BREAKPOINTS (1u << 7) -#define POSIX_LOG_WATCHPOINTS (1u << 8) -#define POSIX_LOG_ALL (UINT32_MAX) -#define POSIX_LOG_DEFAULT POSIX_LOG_PROCESS - namespace lldb_private { -class ProcessPOSIXLog { - static Log::Channel g_channel; +enum class POSIXLog : Log::MaskType { + Breakpoints = Log::ChannelFlag<0>, + Memory = Log::ChannelFlag<1>, + Process = Log::ChannelFlag<2>, + Ptrace = Log::ChannelFlag<3>, + Registers = Log::ChannelFlag<4>, + Thread = Log::ChannelFlag<5>, + Watchpoints = Log::ChannelFlag<6>, + LLVM_MARK_AS_BITMASK_ENUM(Watchpoints) +}; + +class ProcessPOSIXLog { public: static void Initialize(); - - static Log *GetLogIfAllCategoriesSet(uint32_t mask) { - return g_channel.GetLogIfAll(mask); - } }; -} + +template <> Log::Channel &LogChannelFor<POSIXLog>(); +} // namespace lldb_private #endif // liblldb_ProcessPOSIXLog_h_ diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp index d74b66b58afc..b71de4cadb18 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "MemoryTagManagerAArch64MTE.h" +#include "llvm/Support/Error.h" +#include <assert.h> using namespace lldb_private; @@ -20,7 +22,7 @@ MemoryTagManagerAArch64MTE::GetLogicalTag(lldb::addr_t addr) const { } lldb::addr_t -MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const { +MemoryTagManagerAArch64MTE::RemoveTagBits(lldb::addr_t addr) const { // Here we're ignoring the whole top byte. If you've got MTE // you must also have TBI (top byte ignore). // The other 4 bits could contain other extension bits or @@ -30,7 +32,7 @@ MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const { ptrdiff_t MemoryTagManagerAArch64MTE::AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const { - return RemoveNonAddressBits(addr1) - RemoveNonAddressBits(addr2); + return RemoveTagBits(addr1) - RemoveTagBits(addr2); } lldb::addr_t MemoryTagManagerAArch64MTE::GetGranuleSize() const { @@ -66,6 +68,15 @@ MemoryTagManagerAArch64MTE::ExpandToGranule(TagRange range) const { return TagRange(new_start, new_len); } +static llvm::Error MakeInvalidRangeErr(lldb::addr_t addr, + lldb::addr_t end_addr) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "End address (0x%" PRIx64 + ") must be greater than the start address (0x%" PRIx64 ")", + end_addr, addr); +} + llvm::Expected<MemoryTagManager::TagRange> MemoryTagManagerAArch64MTE::MakeTaggedRange( lldb::addr_t addr, lldb::addr_t end_addr, @@ -74,17 +85,12 @@ MemoryTagManagerAArch64MTE::MakeTaggedRange( // We must remove tags here otherwise an address with a higher // tag value will always be > the other. ptrdiff_t len = AddressDiff(end_addr, addr); - if (len <= 0) { - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "End address (0x%" PRIx64 - ") must be greater than the start address (0x%" PRIx64 ")", - end_addr, addr); - } + if (len <= 0) + return MakeInvalidRangeErr(addr, end_addr); // Region addresses will not have memory tags. So when searching // we must use an untagged address. - MemoryRegionInfo::RangeType tag_range(RemoveNonAddressBits(addr), len); + MemoryRegionInfo::RangeType tag_range(RemoveTagBits(addr), len); tag_range = ExpandToGranule(tag_range); // Make a copy so we can use the original for errors and the final return. @@ -123,6 +129,91 @@ MemoryTagManagerAArch64MTE::MakeTaggedRange( return tag_range; } +llvm::Expected<std::vector<MemoryTagManager::TagRange>> +MemoryTagManagerAArch64MTE::MakeTaggedRanges( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const { + // First check that the range is not inverted. + // We must remove tags here otherwise an address with a higher + // tag value will always be > the other. + ptrdiff_t len = AddressDiff(end_addr, addr); + if (len <= 0) + return MakeInvalidRangeErr(addr, end_addr); + + std::vector<MemoryTagManager::TagRange> tagged_ranges; + // No memory regions means no tagged memory at all + if (memory_regions.empty()) + return tagged_ranges; + + // For the logic to work regions must be in ascending order + // which is what you'd have if you used GetMemoryRegions. + assert(std::is_sorted( + memory_regions.begin(), memory_regions.end(), + [](const MemoryRegionInfo &lhs, const MemoryRegionInfo &rhs) { + return lhs.GetRange().GetRangeBase() < rhs.GetRange().GetRangeBase(); + })); + + // If we're debugging userspace in an OS like Linux that uses an MMU, + // the only reason we'd get overlapping regions is incorrect data. + // It is possible that won't hold for embedded with memory protection + // units (MPUs) that allow overlaps. + // + // For now we're going to assume the former, as there is no good way + // to handle overlaps. For example: + // < requested range > + // [-- region 1 --] + // [-- region 2--] + // Where the first region will reduce the requested range to nothing + // and exit early before it sees the overlap. + MemoryRegionInfos::const_iterator overlap = std::adjacent_find( + memory_regions.begin(), memory_regions.end(), + [](const MemoryRegionInfo &lhs, const MemoryRegionInfo &rhs) { + return rhs.GetRange().DoesIntersect(lhs.GetRange()); + }); + UNUSED_IF_ASSERT_DISABLED(overlap); + assert(overlap == memory_regions.end()); + + // Region addresses will not have memory tags so when searching + // we must use an untagged address. + MemoryRegionInfo::RangeType range(RemoveTagBits(addr), len); + range = ExpandToGranule(range); + + // While there are regions to check and the range has non zero length + for (const MemoryRegionInfo ®ion : memory_regions) { + // If range we're checking has been reduced to zero length, exit early + if (!range.IsValid()) + break; + + // If the region doesn't overlap the range at all, ignore it. + if (!region.GetRange().DoesIntersect(range)) + continue; + + // If it's tagged record this sub-range. + // (assuming that it's already granule aligned) + if (region.GetMemoryTagged()) { + // The region found may extend outside the requested range. + // For example the first region might start before the range. + // We must only add what covers the requested range. + lldb::addr_t start = + std::max(range.GetRangeBase(), region.GetRange().GetRangeBase()); + lldb::addr_t end = + std::min(range.GetRangeEnd(), region.GetRange().GetRangeEnd()); + tagged_ranges.push_back(MemoryTagManager::TagRange(start, end - start)); + } + + // Move the range up to start at the end of the region. + lldb::addr_t old_end = range.GetRangeEnd(); + // This "slides" the range so it moves the end as well. + range.SetRangeBase(region.GetRange().GetRangeEnd()); + // So we set the end back to the original end address after sliding it up. + range.SetRangeEnd(old_end); + // (if the above were to try to set end < begin the range will just be set + // to 0 size) + } + + return tagged_ranges; +} + llvm::Expected<std::vector<lldb::addr_t>> MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags, size_t granules /*=0*/) const { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h index d4e8249da93f..7cda728b140f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h @@ -27,7 +27,7 @@ public: size_t GetTagSizeInBytes() const override; lldb::addr_t GetLogicalTag(lldb::addr_t addr) const override; - lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const override; + lldb::addr_t RemoveTagBits(lldb::addr_t addr) const override; ptrdiff_t AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const override; TagRange ExpandToGranule(TagRange range) const override; @@ -36,6 +36,10 @@ public: lldb::addr_t addr, lldb::addr_t end_addr, const lldb_private::MemoryRegionInfos &memory_regions) const override; + llvm::Expected<std::vector<TagRange>> MakeTaggedRanges( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const override; + llvm::Expected<std::vector<lldb::addr_t>> UnpackTagsData(const std::vector<uint8_t> &tags, size_t granules = 0) const override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 6c130be7b741..d6c4a8687ec5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -178,10 +178,10 @@ static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = { g_sve_regnums_arm64}}; static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = { - "Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL}; + "Pointer Authentication Registers", "pauth", k_num_pauth_register, nullptr}; static const lldb_private::RegisterSet g_reg_set_mte_arm64 = { - "MTE Control Register", "mte", k_num_mte_register, NULL}; + "MTE Control Register", "mte", k_num_mte_register, nullptr}; RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b5b105351de5..f6526d03863b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -173,6 +173,13 @@ bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() { return m_supports_qXfer_memory_map_read == eLazyBoolYes; } +bool GDBRemoteCommunicationClient::GetQXferSigInfoReadSupported() { + if (m_supports_qXfer_siginfo_read == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_qXfer_siginfo_read == eLazyBoolYes; +} + uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() { if (m_max_packet_size == 0) { GetRemoteQSupported(); @@ -273,6 +280,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) { m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; m_supports_qXfer_features_read = eLazyBoolCalculate; m_supports_qXfer_memory_map_read = eLazyBoolCalculate; + m_supports_qXfer_siginfo_read = eLazyBoolCalculate; m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; m_uses_native_signals = eLazyBoolCalculate; m_supports_qProcessInfoPID = true; @@ -320,6 +328,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { m_supports_augmented_libraries_svr4_read = eLazyBoolNo; m_supports_qXfer_features_read = eLazyBoolNo; m_supports_qXfer_memory_map_read = eLazyBoolNo; + m_supports_qXfer_siginfo_read = eLazyBoolNo; m_supports_multiprocess = eLazyBoolNo; m_supports_qEcho = eLazyBoolNo; m_supports_QPassSignals = eLazyBoolNo; @@ -362,6 +371,8 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { m_supports_qXfer_features_read = eLazyBoolYes; else if (x == "qXfer:memory-map:read+") m_supports_qXfer_memory_map_read = eLazyBoolYes; + else if (x == "qXfer:siginfo:read+") + m_supports_qXfer_siginfo_read = eLazyBoolYes; else if (x == "qEcho") m_supports_qEcho = eLazyBoolYes; else if (x == "QPassSignals+") diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index c69c33bb1c15..58ed22187747 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -337,6 +337,8 @@ public: bool GetQXferMemoryMapReadSupported(); + bool GetQXferSigInfoReadSupported(); + LazyBool SupportsAllocDeallocMemory() // const { // Uncomment this to have lldb pretend the debug server doesn't respond to @@ -551,6 +553,7 @@ protected: LazyBool m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; LazyBool m_supports_qXfer_features_read = eLazyBoolCalculate; LazyBool m_supports_qXfer_memory_map_read = eLazyBoolCalculate; + LazyBool m_supports_qXfer_siginfo_read = eLazyBoolCalculate; LazyBool m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate; LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp deleted file mode 100644 index c91d7cb5ac30..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ /dev/null @@ -1,314 +0,0 @@ -//===-- GDBRemoteCommunicationReplayServer.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 <cerrno> - -#include "lldb/Host/Config.h" -#include "llvm/ADT/ScopeExit.h" - -#include "GDBRemoteCommunicationReplayServer.h" -#include "ProcessGDBRemoteLog.h" - -// C Includes -// C++ Includes -#include <cstring> - -// Project includes -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Event.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/StringExtractorGDBRemote.h" - -using namespace llvm; -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_gdb_remote; - -/// Check if the given expected packet matches the actual packet. -static bool unexpected(llvm::StringRef expected, llvm::StringRef actual) { - // The 'expected' string contains the raw data, including the leading $ and - // trailing checksum. The 'actual' string contains only the packet's content. - if (expected.contains(actual)) - return false; - // Contains a PID which might be different. - if (expected.contains("vAttach")) - return false; - // Contains a ascii-hex-path. - if (expected.contains("QSetSTD")) - return false; - // Contains environment values. - if (expected.contains("QEnvironment")) - return false; - - return true; -} - -/// Check if we should reply to the given packet. -static bool skip(llvm::StringRef data) { - assert(!data.empty() && "Empty packet?"); - - // We've already acknowledge the '+' packet so we're done here. - if (data == "+") - return true; - - /// Don't 't reply to ^C. We need this because of stop reply packets, which - /// are only returned when the target halts. Reproducers synchronize these - /// 'asynchronous' replies, by recording them as a regular replies to the - /// previous packet (e.g. vCont). As a result, we should ignore real - /// asynchronous requests. - if (data.data()[0] == 0x03) - return true; - - return false; -} - -GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer() - : GDBRemoteCommunication("gdb-replay", "gdb-replay.rx_packet"), - m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"), - m_async_listener_sp( - Listener::MakeListener("lldb.gdb-replay.async-listener")), - m_async_thread_state_mutex() { - m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, - "async thread continue"); - m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, - "async thread should exit"); - - const uint32_t async_event_mask = - eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; - m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, - async_event_mask); -} - -GDBRemoteCommunicationReplayServer::~GDBRemoteCommunicationReplayServer() { - StopAsyncThread(); -} - -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( - Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) { - std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); - - StringExtractorGDBRemote packet; - PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); - - if (packet_result != PacketResult::Success) { - if (!IsConnected()) { - error.SetErrorString("lost connection"); - quit = true; - } else { - error.SetErrorString("timeout"); - } - return packet_result; - } - - m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); - - // Check if we should reply to this packet. - if (skip(packet.GetStringRef())) - return PacketResult::Success; - - // This completes the handshake. Since m_send_acks was true, we can unset it - // already. - if (packet.GetStringRef() == "QStartNoAckMode") - m_send_acks = false; - - // A QEnvironment packet is sent for every environment variable. If the - // number of environment variables is different during replay, the replies - // become out of sync. - if (packet.GetStringRef().find("QEnvironment") == 0) - return SendRawPacketNoLock("$OK#9a"); - - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - while (!m_packet_history.empty()) { - // Pop last packet from the history. - GDBRemotePacket entry = m_packet_history.back(); - m_packet_history.pop_back(); - - // Decode run-length encoding. - const std::string expanded_data = - GDBRemoteCommunication::ExpandRLE(entry.packet.data); - - // We've handled the handshake implicitly before. Skip the packet and move - // on. - if (entry.packet.data == "+") - continue; - - if (entry.type == GDBRemotePacket::ePacketTypeSend) { - if (unexpected(expanded_data, packet.GetStringRef())) { - LLDB_LOG(log, - "GDBRemoteCommunicationReplayServer expected packet: '{0}'", - expanded_data); - LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'", - packet.GetStringRef()); -#ifndef NDEBUG - // This behaves like a regular assert, but prints the expected and - // received packet before aborting. - printf("Reproducer expected packet: '%s'\n", expanded_data.c_str()); - printf("Reproducer received packet: '%s'\n", - packet.GetStringRef().data()); - llvm::report_fatal_error("Encountered unexpected packet during replay"); -#endif - return PacketResult::ErrorSendFailed; - } - - // Ignore QEnvironment packets as they're handled earlier. - if (expanded_data.find("QEnvironment") == 1) { - assert(m_packet_history.back().type == - GDBRemotePacket::ePacketTypeRecv); - m_packet_history.pop_back(); - } - - continue; - } - - if (entry.type == GDBRemotePacket::ePacketTypeInvalid) { - LLDB_LOG( - log, - "GDBRemoteCommunicationReplayServer skipped invalid packet: '{0}'", - packet.GetStringRef()); - continue; - } - - LLDB_LOG(log, - "GDBRemoteCommunicationReplayServer replied to '{0}' with '{1}'", - packet.GetStringRef(), entry.packet.data); - return SendRawPacketNoLock(entry.packet.data); - } - - quit = true; - - return packet_result; -} - -llvm::Error -GDBRemoteCommunicationReplayServer::LoadReplayHistory(const FileSpec &path) { - auto error_or_file = MemoryBuffer::getFile(path.GetPath()); - if (auto err = error_or_file.getError()) - return errorCodeToError(err); - - yaml::Input yin((*error_or_file)->getBuffer()); - yin >> m_packet_history; - - if (auto err = yin.error()) - return errorCodeToError(err); - - // We want to manipulate the vector like a stack so we need to reverse the - // order of the packets to have the oldest on at the back. - std::reverse(m_packet_history.begin(), m_packet_history.end()); - - return Error::success(); -} - -bool GDBRemoteCommunicationReplayServer::StartAsyncThread() { - std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); - if (!m_async_thread.IsJoinable()) { - // Create a thread that watches our internal state and controls which - // events make it to clients (into the DCProcess event queue). - llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( - "<lldb.gdb-replay.async>", - GDBRemoteCommunicationReplayServer::AsyncThread, this); - if (!async_thread) { - LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), - async_thread.takeError(), - "failed to launch host thread: {}"); - return false; - } - m_async_thread = *async_thread; - } - - // Wait for handshake. - m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); - - return m_async_thread.IsJoinable(); -} - -void GDBRemoteCommunicationReplayServer::StopAsyncThread() { - std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); - - if (!m_async_thread.IsJoinable()) - return; - - // Request thread to stop. - m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); - - // Disconnect client. - Disconnect(); - - // Stop the thread. - m_async_thread.Join(nullptr); - m_async_thread.Reset(); -} - -void GDBRemoteCommunicationReplayServer::ReceivePacket( - GDBRemoteCommunicationReplayServer &server, bool &done) { - Status error; - bool interrupt; - auto packet_result = server.GetPacketAndSendResponse(std::chrono::seconds(1), - error, interrupt, done); - if (packet_result != GDBRemoteCommunication::PacketResult::Success && - packet_result != - GDBRemoteCommunication::PacketResult::ErrorReplyTimeout) { - done = true; - } else { - server.m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); - } -} - -thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) { - GDBRemoteCommunicationReplayServer *server = - (GDBRemoteCommunicationReplayServer *)arg; - auto D = make_scope_exit([&]() { server->Disconnect(); }); - EventSP event_sp; - bool done = false; - while (!done) { - if (server->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { - const uint32_t event_type = event_sp->GetType(); - if (event_sp->BroadcasterIs(&server->m_async_broadcaster)) { - switch (event_type) { - case eBroadcastBitAsyncContinue: - ReceivePacket(*server, done); - if (done) - return {}; - break; - case eBroadcastBitAsyncThreadShouldExit: - default: - return {}; - } - } - } - } - - return {}; -} - -Status GDBRemoteCommunicationReplayServer::Connect( - process_gdb_remote::GDBRemoteCommunicationClient &client) { - repro::Loader *loader = repro::Reproducer::Instance().GetLoader(); - if (!loader) - return Status("No loader provided."); - - static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>> - multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create( - repro::Reproducer::Instance().GetLoader()); - if (!multi_loader) - return Status("No gdb remote provider found."); - - llvm::Optional<std::string> history_file = multi_loader->GetNextFile(); - if (!history_file) - return Status("No gdb remote packet log found."); - - if (auto error = LoadReplayHistory(FileSpec(*history_file))) - return Status("Unable to load replay history"); - - if (auto error = GDBRemoteCommunication::ConnectLocally(client, *this)) - return Status("Unable to connect to replay server"); - - return {}; -} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h deleted file mode 100644 index 2f8770d0accf..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ /dev/null @@ -1,88 +0,0 @@ -//===-- GDBRemoteCommunicationReplayServer.h --------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H -#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H - -// Other libraries and framework includes -#include "GDBRemoteCommunication.h" -#include "GDBRemoteCommunicationClient.h" -#include "GDBRemoteCommunicationHistory.h" - -// Project includes -#include "lldb/Host/HostThread.h" -#include "lldb/Utility/Broadcaster.h" -#include "lldb/lldb-private-forward.h" -#include "llvm/Support/Error.h" - -// C Includes -// C++ Includes -#include <functional> -#include <map> -#include <thread> - -class StringExtractorGDBRemote; - -namespace lldb_private { -namespace process_gdb_remote { - -class ProcessGDBRemote; - -/// Dummy GDB server that replays packets from the GDB Remote Communication -/// history. This is used to replay GDB packets. -class GDBRemoteCommunicationReplayServer : public GDBRemoteCommunication { -public: - GDBRemoteCommunicationReplayServer(); - - ~GDBRemoteCommunicationReplayServer() override; - - PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout, - Status &error, bool &interrupt, - bool &quit); - - bool HandshakeWithClient() { return GetAck() == PacketResult::Success; } - - llvm::Error LoadReplayHistory(const FileSpec &path); - - bool StartAsyncThread(); - void StopAsyncThread(); - - Status Connect(process_gdb_remote::GDBRemoteCommunicationClient &client); - -protected: - enum { - eBroadcastBitAsyncContinue = (1 << 0), - eBroadcastBitAsyncThreadShouldExit = (1 << 1), - }; - - static void ReceivePacket(GDBRemoteCommunicationReplayServer &server, - bool &done); - static lldb::thread_result_t AsyncThread(void *arg); - - /// Replay history with the oldest packet at the end. - std::vector<GDBRemotePacket> m_packet_history; - - /// Server thread. - Broadcaster m_async_broadcaster; - lldb::ListenerSP m_async_listener_sp; - HostThread m_async_thread; - std::recursive_mutex m_async_thread_state_mutex; - - bool m_skip_acks = false; - -private: - GDBRemoteCommunicationReplayServer( - const GDBRemoteCommunicationReplayServer &) = delete; - const GDBRemoteCommunicationReplayServer & - operator=(const GDBRemoteCommunicationReplayServer &) = delete; -}; - -} // namespace process_gdb_remote -} // namespace lldb_private - -#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONREPLAYSERVER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 30f14a52dfb5..123a8198a89b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1086,7 +1086,7 @@ void GDBRemoteCommunicationServerLLGS::NewSubprocess( } void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); + Log *log = GetLog(GDBRLog::Comm); bool interrupt = false; bool done = false; @@ -2920,6 +2920,18 @@ GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, return std::move(*buffer_or_error); } + if (object == "siginfo") { + NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); + if (!thread) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "no current thread"); + + auto buffer_or_error = thread->GetSiginfo(); + if (!buffer_or_error) + return buffer_or_error.takeError(); + return std::move(*buffer_or_error); + } + if (object == "libraries-svr4") { auto library_list = m_current_process->GetLoadedSVR4Libraries(); if (!library_list) @@ -3838,6 +3850,8 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures( ret.push_back("qXfer:auxv:read+"); if (bool(plugin_features & Extension::libraries_svr4)) ret.push_back("qXfer:libraries-svr4:read+"); + if (bool(plugin_features & Extension::siginfo_read)) + ret.push_back("qXfer:siginfo:read+"); if (bool(plugin_features & Extension::memory_tagging)) ret.push_back("memory-tagging+"); if (bool(plugin_features & Extension::savecore)) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp new file mode 100644 index 000000000000..b391edced695 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp @@ -0,0 +1,86 @@ +//===-- GDBRemoteRegisterFallback.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 "GDBRemoteRegisterFallback.h" + +namespace lldb_private { +namespace process_gdb_remote { + +#define REG(name, size) \ + DynamicRegisterInfo::Register { \ + ConstString(#name), empty_alt_name, reg_set, size, LLDB_INVALID_INDEX32, \ + lldb::eEncodingUint, lldb::eFormatHex, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, {}, {} \ + } +#define R64(name) REG(name, 8) +#define R32(name) REG(name, 4) + +static std::vector<DynamicRegisterInfo::Register> GetRegisters_aarch64() { + ConstString empty_alt_name; + ConstString reg_set{"general purpose registers"}; + + std::vector<DynamicRegisterInfo::Register> registers{ + R64(x0), R64(x1), R64(x2), R64(x3), R64(x4), R64(x5), R64(x6), + R64(x7), R64(x8), R64(x9), R64(x10), R64(x11), R64(x12), R64(x13), + R64(x14), R64(x15), R64(x16), R64(x17), R64(x18), R64(x19), R64(x20), + R64(x21), R64(x22), R64(x23), R64(x24), R64(x25), R64(x26), R64(x27), + R64(x28), R64(x29), R64(x30), R64(sp), R64(pc), R32(cpsr), + }; + + return registers; +} + +static std::vector<DynamicRegisterInfo::Register> GetRegisters_x86() { + ConstString empty_alt_name; + ConstString reg_set{"general purpose registers"}; + + std::vector<DynamicRegisterInfo::Register> registers{ + R32(eax), R32(ecx), R32(edx), R32(ebx), R32(esp), R32(ebp), + R32(esi), R32(edi), R32(eip), R32(eflags), R32(cs), R32(ss), + R32(ds), R32(es), R32(fs), R32(gs), + }; + + return registers; +} + +static std::vector<DynamicRegisterInfo::Register> GetRegisters_x86_64() { + ConstString empty_alt_name; + ConstString reg_set{"general purpose registers"}; + + std::vector<DynamicRegisterInfo::Register> registers{ + R64(rax), R64(rbx), R64(rcx), R64(rdx), R64(rsi), R64(rdi), + R64(rbp), R64(rsp), R64(r8), R64(r9), R64(r10), R64(r11), + R64(r12), R64(r13), R64(r14), R64(r15), R64(rip), R32(eflags), + R32(cs), R32(ss), R32(ds), R32(es), R32(fs), R32(gs), + }; + + return registers; +} + +#undef R32 +#undef R64 +#undef REG + +std::vector<DynamicRegisterInfo::Register> +GetFallbackRegisters(const ArchSpec &arch_to_use) { + switch (arch_to_use.GetMachine()) { + case llvm::Triple::aarch64: + return GetRegisters_aarch64(); + case llvm::Triple::x86: + return GetRegisters_x86(); + case llvm::Triple::x86_64: + return GetRegisters_x86_64(); + default: + break; + } + + return {}; +} + +} // namespace process_gdb_remote +} // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h new file mode 100644 index 000000000000..82e03c6b9b1c --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h @@ -0,0 +1,26 @@ +//===-- GDBRemoteRegisterFallback.h -----------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERFALLBACK_H +#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERFALLBACK_H + +#include <vector> + +#include "lldb/Target/DynamicRegisterInfo.h" +#include "lldb/Utility/ArchSpec.h" + +namespace lldb_private { +namespace process_gdb_remote { + +std::vector<DynamicRegisterInfo::Register> +GetFallbackRegisters(const ArchSpec &arch_to_use); + +} // namespace process_gdb_remote +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTEREGISTERFALLBACK_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index af95ef0718a5..5f3c1ad9c1e1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -23,13 +23,6 @@ #include <ctime> #include <sys/types.h> -#include <algorithm> -#include <csignal> -#include <map> -#include <memory> -#include <mutex> -#include <sstream> - #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" @@ -70,8 +63,16 @@ #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" +#include <algorithm> +#include <csignal> +#include <map> +#include <memory> +#include <mutex> +#include <sstream> +#include <thread> #include "GDBRemoteRegisterContext.h" +#include "GDBRemoteRegisterFallback.h" #ifdef LLDB_ENABLE_ALL #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" #endif // LLDB_ENABLE_ALL @@ -255,9 +256,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_addr_to_mmap_size(), m_thread_create_bp_sp(), m_waiting_for_attach(false), m_destroy_tried_resuming(false), m_command_sp(), m_breakpoint_pc_offset(0), - m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false), - m_allow_flash_writes(false), m_erased_flash_ranges(), - m_vfork_in_progress(false) { + m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false), + m_erased_flash_ranges(), m_vfork_in_progress(false) { m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, @@ -397,6 +397,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { // 2 - If the target definition doesn't have any of the info from the // target.xml (registers) then proceed to read the target.xml. // 3 - Fall back on the qRegisterInfo packets. + // 4 - Use hardcoded defaults if available. FileSpec target_definition_fspec = GetGlobalPluginProperties().GetTargetDefinitionFile(); @@ -510,6 +511,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { } } + if (registers.empty()) + registers = GetFallbackRegisters(arch_to_use); + AddRemoteRegisters(registers, arch_to_use); } @@ -527,7 +531,7 @@ Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, } Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Log *log = GetLog(GDBRLog::Process); Status error(WillLaunchOrAttach()); if (error.Fail()) @@ -604,8 +608,7 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { ReadModuleFromMemory(FileSpec(namebuf), standalone_value); } - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( - LIBLLDB_LOG_DYNAMIC_LOADER)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (module_sp.get()) { target.GetImages().AppendIfNeeded(module_sp, false); @@ -3320,24 +3323,6 @@ Status ProcessGDBRemote::DoSignal(int signo) { return error; } -Status ProcessGDBRemote::ConnectToReplayServer() { - Status status = m_gdb_replay_server.Connect(m_gdb_comm); - if (status.Fail()) - return status; - - // Enable replay mode. - m_replay_mode = true; - - // Start server thread. - m_gdb_replay_server.StartAsyncThread(); - - // Start client thread. - StartAsyncThread(); - - // Do the usual setup. - return ConnectToDebugserver(""); -} - Status ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { // Make sure we aren't already connected? @@ -4374,9 +4359,9 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( } else if (name == "osabi") { node.GetElementText(target_info.osabi); } else if (name == "xi:include" || name == "include") { - llvm::StringRef href = node.GetAttributeValue("href"); + std::string href = node.GetAttributeValue("href"); if (!href.empty()) - target_info.includes.push_back(href.str()); + target_info.includes.push_back(href); } else if (name == "feature") { feature_nodes.push_back(node); } else if (name == "groups") { @@ -4415,9 +4400,9 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( const XMLNode &node) -> bool { llvm::StringRef name = node.GetName(); if (name == "xi:include" || name == "include") { - llvm::StringRef href = node.GetAttributeValue("href"); + std::string href = node.GetAttributeValue("href"); if (!href.empty()) - target_info.includes.push_back(href.str()); + target_info.includes.push_back(href); } return true; }); @@ -4553,7 +4538,7 @@ llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { "Error finding library-list-svr4 xml element"); // main link map structure - llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); + std::string main_lm = root_element.GetAttributeValue("main-lm"); // FIXME: we're silently ignoring invalid data here if (!main_lm.empty()) llvm::to_integer(main_lm, list.m_link_map); @@ -4641,15 +4626,15 @@ llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { "library", [log, &list](const XMLNode &library) -> bool { LoadedModuleInfoList::LoadedModuleInfo module; - llvm::StringRef name = library.GetAttributeValue("name"); - module.set_name(name.str()); + std::string name = library.GetAttributeValue("name"); + module.set_name(name); // The base address of a given library will be the address of its // first section. Most remotes send only one section for Windows // targets for example. const XMLNode §ion = library.FindFirstChildElementWithName("section"); - llvm::StringRef address = section.GetAttributeValue("address"); + std::string address = section.GetAttributeValue("address"); uint64_t address_value = LLDB_INVALID_ADDRESS; llvm::to_integer(address, address_value); module.set_base(address_value); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 488336b8c1b8..bdf130e3ec11 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -34,7 +34,6 @@ #include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunicationClient.h" -#include "GDBRemoteCommunicationReplayServer.h" #include "GDBRemoteRegisterContext.h" #include "llvm/ADT/DenseMap.h" @@ -251,7 +250,6 @@ protected: }; GDBRemoteCommunicationClient m_gdb_comm; - GDBRemoteCommunicationReplayServer m_gdb_replay_server; std::atomic<lldb::pid_t> m_debugserver_pid; llvm::Optional<StringExtractorGDBRemote> m_last_stop_packet; @@ -292,7 +290,6 @@ protected: lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach bool m_use_g_packet_for_reading; - bool m_replay_mode; bool m_allow_flash_writes; using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>; using FlashRange = FlashRangeVector::Entry; @@ -320,8 +317,6 @@ protected: bool DoUpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; - Status ConnectToReplayServer(); - Status EstablishConnectionIfNeeded(const ProcessInfo &process_info); Status LaunchAndConnectToDebugserver(const ProcessInfo &process_info); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp index 40990ef66494..3322f6b8048a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp @@ -15,25 +15,29 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; static constexpr Log::Category g_categories[] = { - {{"async"}, {"log asynchronous activity"}, GDBR_LOG_ASYNC}, - {{"break"}, {"log breakpoints"}, GDBR_LOG_BREAKPOINTS}, - {{"comm"}, {"log communication activity"}, GDBR_LOG_COMM}, - {{"packets"}, {"log gdb remote packets"}, GDBR_LOG_PACKETS}, - {{"memory"}, {"log memory reads and writes"}, GDBR_LOG_MEMORY}, + {{"async"}, {"log asynchronous activity"}, GDBRLog::Async}, + {{"break"}, {"log breakpoints"}, GDBRLog::Breakpoints}, + {{"comm"}, {"log communication activity"}, GDBRLog::Comm}, + {{"packets"}, {"log gdb remote packets"}, GDBRLog::Packets}, + {{"memory"}, {"log memory reads and writes"}, GDBRLog::Memory}, {{"data-short"}, {"log memory bytes for memory reads and writes for short transactions " "only"}, - GDBR_LOG_MEMORY_DATA_SHORT}, + GDBRLog::MemoryDataShort}, {{"data-long"}, {"log memory bytes for memory reads and writes for all transactions"}, - GDBR_LOG_MEMORY_DATA_LONG}, - {{"process"}, {"log process events and activities"}, GDBR_LOG_PROCESS}, - {{"step"}, {"log step related activities"}, GDBR_LOG_STEP}, - {{"thread"}, {"log thread events and activities"}, GDBR_LOG_THREAD}, - {{"watch"}, {"log watchpoint related activities"}, GDBR_LOG_WATCHPOINTS}, + GDBRLog::MemoryDataLong}, + {{"process"}, {"log process events and activities"}, GDBRLog::Process}, + {{"step"}, {"log step related activities"}, GDBRLog::Step}, + {{"thread"}, {"log thread events and activities"}, GDBRLog::Thread}, + {{"watch"}, {"log watchpoint related activities"}, GDBRLog::Watchpoints}, }; -Log::Channel ProcessGDBRemoteLog::g_channel(g_categories, GDBR_LOG_DEFAULT); +static Log::Channel g_channel(g_categories, GDBRLog::Packets); + +template <> Log::Channel &lldb_private::LogChannelFor<GDBRLog>() { + return g_channel; +} void ProcessGDBRemoteLog::Initialize() { static llvm::once_flag g_once_flag; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index bd3e993cf72a..44e390ec8cad 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -11,35 +11,52 @@ #include "lldb/Utility/Log.h" -#define GDBR_LOG_PROCESS (1u << 1) -#define GDBR_LOG_THREAD (1u << 2) -#define GDBR_LOG_PACKETS (1u << 3) -#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define GDBR_LOG_MEMORY_DATA_SHORT \ - (1u << 5) // Log short memory reads/writes bytes -#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define GDBR_LOG_BREAKPOINTS (1u << 7) -#define GDBR_LOG_WATCHPOINTS (1u << 8) -#define GDBR_LOG_STEP (1u << 9) -#define GDBR_LOG_COMM (1u << 10) -#define GDBR_LOG_ASYNC (1u << 11) -#define GDBR_LOG_ALL (UINT32_MAX) -#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS - namespace lldb_private { namespace process_gdb_remote { -class ProcessGDBRemoteLog { - static Log::Channel g_channel; +enum class GDBRLog : Log::MaskType { + Async = Log::ChannelFlag<0>, + Breakpoints = Log::ChannelFlag<1>, + Comm = Log::ChannelFlag<2>, + Memory = Log::ChannelFlag<3>, // Log memory reads/writes calls + MemoryDataLong = Log::ChannelFlag<4>, // Log all memory reads/writes bytes + MemoryDataShort = Log::ChannelFlag<5>, // Log short memory reads/writes bytes + Packets = Log::ChannelFlag<6>, + Process = Log::ChannelFlag<7>, + Step = Log::ChannelFlag<8>, + Thread = Log::ChannelFlag<9>, + Watchpoints = Log::ChannelFlag<10>, + LLVM_MARK_AS_BITMASK_ENUM(Watchpoints) +}; +#define GDBR_LOG_PROCESS ::lldb_private::process_gdb_remote::GDBRLog::Process +#define GDBR_LOG_THREAD ::lldb_private::process_gdb_remote::GDBRLog::Thread +#define GDBR_LOG_PACKETS ::lldb_private::process_gdb_remote::GDBRLog::Packets +#define GDBR_LOG_MEMORY ::lldb_private::process_gdb_remote::GDBRLog::Memory +#define GDBR_LOG_MEMORY_DATA_SHORT \ + ::lldb_private::process_gdb_remote::GDBRLog::MemoryDataShort +#define GDBR_LOG_MEMORY_DATA_LONG \ + ::lldb_private::process_gdb_remote::GDBRLog::MemoryDataLong +#define GDBR_LOG_BREAKPOINTS \ + ::lldb_private::process_gdb_remote::GDBRLog::Breakpoints +#define GDBR_LOG_WATCHPOINTS \ + ::lldb_private::process_gdb_remote::GDBRLog::Watchpoints +#define GDBR_LOG_STEP ::lldb_private::process_gdb_remote::GDBRLog::Step +#define GDBR_LOG_COMM ::lldb_private::process_gdb_remote::GDBRLog::Comm +#define GDBR_LOG_ASYNC ::lldb_private::process_gdb_remote::GDBRLog::Async + +class ProcessGDBRemoteLog { public: static void Initialize(); - static Log *GetLogIfAllCategoriesSet(uint32_t mask) { return g_channel.GetLogIfAll(mask); } - static Log *GetLogIfAnyCategoryIsSet(uint32_t mask) { return g_channel.GetLogIfAny(mask); } + static Log *GetLogIfAllCategoriesSet(GDBRLog mask) { return GetLog(mask); } + static Log *GetLogIfAnyCategoryIsSet(GDBRLog mask) { return GetLog(mask); } }; } // namespace process_gdb_remote + +template <> Log::Channel &LogChannelFor<process_gdb_remote::GDBRLog>(); + } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTELOG_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 2a9896e41085..3d23c074c1be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -39,7 +39,7 @@ ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid) m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown), m_queue_serial_number(LLDB_INVALID_QUEUE_ID), m_associated_with_libdispatch_queue(eLazyBoolCalculate) { - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(), GetID()); // At this point we can clone reg_info for architectures supporting @@ -54,7 +54,7 @@ ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid) ThreadGDBRemote::~ThreadGDBRemote() { ProcessSP process_sp(GetProcess()); - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID()); DestroyThread(); @@ -222,7 +222,7 @@ void ThreadGDBRemote::SetAssociatedWithLibdispatchQueue( StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { StructuredData::ObjectSP object_sp; const lldb::user_id_t tid = GetProtocolID(); - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOGF(log, "Fetching extended information for thread %4.4" PRIx64, tid); ProcessSP process_sp(GetProcess()); if (process_sp) { @@ -236,7 +236,7 @@ StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { void ThreadGDBRemote::WillResume(StateType resume_state) { int signo = GetResumeSignal(); const lldb::user_id_t tid = GetProtocolID(); - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOGF(log, "Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state)); @@ -346,3 +346,23 @@ bool ThreadGDBRemote::CalculateStopInfo() { ->CalculateThreadStopInfo(this); return false; } + +llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> +ThreadGDBRemote::GetSiginfo(size_t max_size) const { + ProcessSP process_sp(GetProcess()); + if (!process_sp) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "no process"); + ProcessGDBRemote *gdb_process = + static_cast<ProcessGDBRemote *>(process_sp.get()); + if (!gdb_process->m_gdb_comm.GetQXferSigInfoReadSupported()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "qXfer:siginfo:read not supported"); + + llvm::Expected<std::string> response = + gdb_process->m_gdb_comm.ReadExtFeature("siginfo", ""); + if (!response) + return response.takeError(); + + return llvm::MemoryBuffer::getMemBufferCopy(response.get()); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index b7d75021c062..fb83c74fd2c5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -90,6 +90,9 @@ public: StructuredData::ObjectSP FetchThreadExtendedInfo() override; + llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + GetSiginfo(size_t max_size) const override; + protected: friend class ProcessGDBRemote; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index cb21a3e7e65f..5eb7cb0e6a5c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -164,9 +164,6 @@ Status ScriptedProcess::DoLaunch(Module *exe_module, SetPrivateState(eStateStopped); - UpdateThreadListIfNeeded(); - GetThreadList(); - return {}; } @@ -225,8 +222,8 @@ bool ScriptedProcess::IsAlive() { size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) { if (!m_interpreter) - return GetInterface().ErrorWithMessage<size_t>(LLVM_PRETTY_FUNCTION, - "No interpreter.", error); + return ScriptedInterface::ErrorWithMessage<size_t>( + LLVM_PRETTY_FUNCTION, "No interpreter.", error); lldb::DataExtractorSP data_extractor_sp = GetInterface().ReadMemoryAtAddress(addr, size, error); @@ -238,7 +235,7 @@ size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) - return GetInterface().ErrorWithMessage<size_t>( + return ScriptedInterface::ErrorWithMessage<size_t>( LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error); return size; @@ -296,7 +293,7 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, ScriptLanguage language = m_interpreter->GetLanguage(); if (language != eScriptLanguagePython) - return GetInterface().ErrorWithMessage<bool>( + return ScriptedInterface::ErrorWithMessage<bool>( LLVM_PRETTY_FUNCTION, llvm::Twine("ScriptInterpreter language (" + llvm::Twine(m_interpreter->LanguageToString(language)) + @@ -304,19 +301,57 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, .str(), error); - lldb::ThreadSP thread_sp; - thread_sp = std::make_shared<ScriptedThread>(*this, error); + StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); + + if (!thread_info_sp) + return ScriptedInterface::ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, + "Couldn't fetch thread list from Scripted Process.", error); + + auto create_scripted_thread = + [this, &old_thread_list, &error, + &new_thread_list](ConstString key, StructuredData::Object *val) -> bool { + if (!val) + return ScriptedInterface::ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); + + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + if (!llvm::to_integer(key.AsCString(), tid)) + return ScriptedInterface::ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, "Invalid thread id", error); + + if (ThreadSP thread_sp = + old_thread_list.FindThreadByID(tid, false /*=can_update*/)) { + // If the thread was already in the old_thread_list, + // just add it back to the new_thread_list. + new_thread_list.AddThread(thread_sp); + return true; + } + + auto thread_or_error = ScriptedThread::Create(*this, val->GetAsGeneric()); + + if (!thread_or_error) + return ScriptedInterface::ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error); + + ThreadSP thread_sp = thread_or_error.get(); + lldbassert(thread_sp && "Couldn't initialize scripted thread."); + + RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); + if (!reg_ctx_sp) + return ScriptedInterface::ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Invalid Register Context for thread " + + llvm::Twine(key.AsCString())) + .str(), + error); - if (!thread_sp || error.Fail()) - return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, - error.AsCString(), error); + new_thread_list.AddThread(thread_sp); - RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); - if (!reg_ctx_sp) - return GetInterface().ErrorWithMessage<bool>( - LLVM_PRETTY_FUNCTION, "Invalid Register Context", error); + return true; + }; - new_thread_list.AddThread(thread_sp); + thread_info_sp->ForEach(create_scripted_thread); return new_thread_list.GetSize(false) > 0; } @@ -324,7 +359,6 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, void ScriptedProcess::RefreshStateAfterStop() { // Let all threads recover from stopping and do any clean up based on the // previous thread state (if any). - m_thread_list.RefreshStateAfterStop(); } bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp index 959b8c581885..b6cbb62fd6e6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -28,44 +28,60 @@ void ScriptedThread::CheckInterpreterAndScriptObject() const { lldbassert(GetInterface() && "Invalid Scripted Thread Interface."); } -ScriptedThread::ScriptedThread(ScriptedProcess &process, Status &error) - : Thread(process, LLDB_INVALID_THREAD_ID), m_scripted_process(process) { - if (!process.IsValid()) { - error.SetErrorString("Invalid scripted process"); - return; - } +llvm::Expected<std::shared_ptr<ScriptedThread>> +ScriptedThread::Create(ScriptedProcess &process, + StructuredData::Generic *script_object) { + if (!process.IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid scripted process."); process.CheckInterpreterAndScriptObject(); - auto scripted_thread_interface = GetInterface(); - if (!scripted_thread_interface) { - error.SetErrorString("Failed to get scripted thread interface."); - return; - } - - llvm::Optional<std::string> class_name = - process.GetInterface().GetScriptedThreadPluginName(); - if (!class_name || class_name->empty()) { - error.SetErrorString("Failed to get scripted thread class name."); - return; + auto scripted_thread_interface = + process.GetInterface().CreateScriptedThreadInterface(); + if (!scripted_thread_interface) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed to create scripted thread interface."); + + llvm::StringRef thread_class_name; + if (!script_object) { + llvm::Optional<std::string> class_name = + process.GetInterface().GetScriptedThreadPluginName(); + if (!class_name || class_name->empty()) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed to get scripted thread class name."); + thread_class_name = *class_name; } ExecutionContext exe_ctx(process); - - StructuredData::GenericSP object_sp = + StructuredData::GenericSP owned_script_object_sp = scripted_thread_interface->CreatePluginObject( - class_name->c_str(), exe_ctx, - process.m_scripted_process_info.GetArgsSP()); - if (!object_sp || !object_sp->IsValid()) { - error.SetErrorString("Failed to create valid script object"); - return; - } + thread_class_name, exe_ctx, + process.m_scripted_process_info.GetArgsSP(), script_object); - m_script_object_sp = object_sp; + if (!owned_script_object_sp) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Failed to create script object."); + if (!owned_script_object_sp->IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Created script object is invalid."); - SetID(scripted_thread_interface->GetThreadID()); + lldb::tid_t tid = scripted_thread_interface->GetThreadID(); + + return std::make_shared<ScriptedThread>(process, scripted_thread_interface, + tid, owned_script_object_sp); } +ScriptedThread::ScriptedThread(ScriptedProcess &process, + ScriptedThreadInterfaceSP interface_sp, + lldb::tid_t tid, + StructuredData::GenericSP script_object_sp) + : Thread(process, tid), m_scripted_process(process), + m_scripted_thread_interface_sp(interface_sp), + m_script_object_sp(script_object_sp) {} + ScriptedThread::~ScriptedThread() { DestroyThread(); } const char *ScriptedThread::GetName() { @@ -137,6 +153,11 @@ bool ScriptedThread::CalculateStopInfo() { StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason(); Status error; + if (!dict_sp) + return GetInterface()->ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stop info.", error, + LIBLLDB_LOG_THREAD); + lldb::StopInfoSP stop_info_sp; lldb::StopReason stop_reason_type; @@ -150,12 +171,12 @@ bool ScriptedThread::CalculateStopInfo() { if (!dict_sp->GetValueForKeyAsDictionary("data", data_dict)) return GetInterface()->ErrorWithMessage<bool>( LLVM_PRETTY_FUNCTION, - "Couldn't find value for key 'type' in stop reason dictionary.", error, + "Couldn't find value for key 'data' in stop reason dictionary.", error, LIBLLDB_LOG_THREAD); switch (stop_reason_type) { case lldb::eStopReasonNone: - break; + return true; case lldb::eStopReasonBreakpoint: { lldb::break_id_t break_id; data_dict->GetValueForKeyAsInteger("break_id", break_id, @@ -172,6 +193,13 @@ bool ScriptedThread::CalculateStopInfo() { stop_info_sp = StopInfo::CreateStopReasonWithSignal(*this, signal, description.data()); } break; + case lldb::eStopReasonException: { + llvm::StringRef description; + data_dict->GetValueForKeyAsString("desc", description); + + stop_info_sp = + StopInfo::CreateStopReasonWithException(*this, description.data()); + } break; default: return GetInterface()->ErrorWithMessage<bool>( LLVM_PRETTY_FUNCTION, @@ -181,6 +209,9 @@ bool ScriptedThread::CalculateStopInfo() { error, LIBLLDB_LOG_THREAD); } + if (!stop_info_sp) + return false; + SetStopInfo(stop_info_sp); return true; } @@ -190,7 +221,7 @@ void ScriptedThread::RefreshStateAfterStop() { } lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const { - return m_scripted_process.GetInterface().GetScriptedThreadInterface(); + return m_scripted_thread_interface_sp; } std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h index cdcd543702a4..8d8a7c2a3df9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h @@ -25,11 +25,18 @@ class ScriptedProcess; namespace lldb_private { class ScriptedThread : public lldb_private::Thread { + public: - ScriptedThread(ScriptedProcess &process, Status &error); + ScriptedThread(ScriptedProcess &process, + lldb::ScriptedThreadInterfaceSP interface_sp, lldb::tid_t tid, + StructuredData::GenericSP script_object_sp = nullptr); ~ScriptedThread() override; + static llvm::Expected<std::shared_ptr<ScriptedThread>> + Create(ScriptedProcess &process, + StructuredData::Generic *script_object = nullptr); + lldb::RegisterContextSP GetRegisterContext() override; lldb::RegisterContextSP @@ -59,8 +66,9 @@ private: std::shared_ptr<DynamicRegisterInfo> GetDynamicRegisterInfo(); const ScriptedProcess &m_scripted_process; + lldb::ScriptedThreadInterfaceSP m_scripted_thread_interface_sp = nullptr; + lldb_private::StructuredData::GenericSP m_script_object_sp = nullptr; std::shared_ptr<DynamicRegisterInfo> m_register_info_sp = nullptr; - lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 7c71c9329e57..68f4e90d70f6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -69,6 +69,30 @@ Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { return std::string(utf8.get()); } +static bool python_is_finalizing() { +#if PY_MAJOR_VERSION == 2 + return false; +#elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 + return _Py_Finalizing != nullptr; +#else + return _Py_IsFinalizing(); +#endif +} + +void PythonObject::Reset() { + if (m_py_obj && Py_IsInitialized()) { + if (python_is_finalizing()) { + // Leak m_py_obj rather than crashing the process. + // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure + } else { + PyGILState_STATE state = PyGILState_Ensure(); + Py_DECREF(m_py_obj); + PyGILState_Release(state); + } + } + m_py_obj = nullptr; +} + Expected<long long> PythonObject::AsLongLong() const { if (!m_py_obj) return nullDeref(); @@ -257,6 +281,9 @@ PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { } StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { +#if PY_MAJOR_VERSION >= 3 + assert(PyGILState_Check()); +#endif switch (GetObjectType()) { case PyObjectType::Dictionary: return PythonDictionary(PyRefType::Borrowed, m_py_obj) @@ -279,7 +306,8 @@ StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { case PyObjectType::None: return StructuredData::ObjectSP(); default: - return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); + return StructuredData::ObjectSP(new StructuredPythonObject( + PythonObject(PyRefType::Borrowed, m_py_obj))); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 56bc55d239d1..2094f0b3afd2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -83,30 +83,6 @@ protected: PyGILState_STATE m_state; }; -class StructuredPythonObject : public StructuredData::Generic { -public: - StructuredPythonObject() : StructuredData::Generic() {} - - StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { - Py_XINCREF(GetValue()); - } - - ~StructuredPythonObject() override { - if (Py_IsInitialized()) - Py_XDECREF(GetValue()); - SetValue(nullptr); - } - - bool IsValid() const override { return GetValue() && GetValue() != Py_None; } - - void Serialize(llvm::json::OStream &s) const override; - -private: - StructuredPythonObject(const StructuredPythonObject &) = delete; - const StructuredPythonObject & - operator=(const StructuredPythonObject &) = delete; -}; - enum class PyObjectType { Unknown, None, @@ -263,11 +239,7 @@ public: ~PythonObject() { Reset(); } - void Reset() { - if (m_py_obj && Py_IsInitialized()) - Py_DECREF(m_py_obj); - m_py_obj = nullptr; - } + void Reset(); void Dump() const { if (m_py_obj) @@ -767,6 +739,30 @@ public: } }; +class StructuredPythonObject : public StructuredData::Generic { +public: + StructuredPythonObject() : StructuredData::Generic() {} + + // Take ownership of the object we received. + StructuredPythonObject(PythonObject obj) + : StructuredData::Generic(obj.release()) {} + + ~StructuredPythonObject() override { + // Hand ownership back to a (temporary) PythonObject instance and let it + // take care of releasing it. + PythonObject(PyRefType::Owned, static_cast<PyObject *>(GetValue())); + } + + bool IsValid() const override { return GetValue() && GetValue() != Py_None; } + + void Serialize(llvm::json::OStream &s) const override; + +private: + StructuredPythonObject(const StructuredPythonObject &) = delete; + const StructuredPythonObject & + operator=(const StructuredPythonObject &) = delete; +}; + } // namespace python } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 2bb69dc47731..4df235356737 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -18,6 +18,7 @@ // LLDB Python header must be included first #include "lldb-python.h" +#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" #include "llvm/Support/Error.h" @@ -54,17 +55,15 @@ void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); // 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, - const StructuredDataImpl &args_impl, - std::string &error_string); +python::PythonObject LLDBSwigPythonCreateScriptedProcess( + const char *python_class_name, const char *session_dictionary_name, + const lldb::TargetSP &target_sp, const StructuredDataImpl &args_impl, + std::string &error_string); -void *LLDBSwigPythonCreateScriptedThread(const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP &process_sp, - const StructuredDataImpl &args_impl, - std::string &error_string); +python::PythonObject LLDBSwigPythonCreateScriptedThread( + const char *python_class_name, const char *session_dictionary_name, + const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl, + std::string &error_string); llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, @@ -83,16 +82,17 @@ bool LLDBSwigPythonCallTypeScript(const char *python_function_name, const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval); -void * +python::PythonObject 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, - lldb::DebuggerSP debugger_sp); +python::PythonObject +LLDBSwigPythonCreateCommandObject(const char *python_class_name, + const char *session_dictionary_name, + lldb::DebuggerSP debugger_sp); -void *LLDBSwigPythonCreateScriptedThreadPlan( +python::PythonObject LLDBSwigPythonCreateScriptedThreadPlan( const char *python_class_name, const char *session_dictionary_name, const StructuredDataImpl &args_data, std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp); @@ -101,7 +101,7 @@ bool LLDBSWIGPythonCallThreadPlan(void *implementor, const char *method_name, lldb_private::Event *event_sp, bool &got_error); -void *LLDBSwigPythonCreateScriptedBreakpointResolver( +python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver( const char *python_class_name, const char *session_dictionary_name, const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp); @@ -109,11 +109,10 @@ 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, - const StructuredDataImpl &args, - lldb_private::Status &error); +python::PythonObject LLDBSwigPythonCreateScriptedStopHook( + lldb::TargetSP target_sp, const char *python_class_name, + const char *session_dictionary_name, const StructuredDataImpl &args, + lldb_private::Status &error); bool LLDBSwigPythonStopHookCallHandleStop(void *implementor, lldb::ExecutionContextRefSP exc_ctx, @@ -150,12 +149,14 @@ 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); +python::PythonObject +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); +python::PythonObject +LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name, + const char *session_dictionary_name); PyObject * LLDBSwigPython_GetRecognizedArguments(PyObject *implementor, diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 6afa4742698b..1bf647e4acfc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -37,7 +37,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" -#include "lldb/Utility/ReproducerInstrumentation.h" +#include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/Timer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -70,6 +70,14 @@ extern "C" void init_lldb(void); #define LLDBSwigPyInit init_lldb #endif +#if defined(_WIN32) +// Don't mess with the signal handlers on Windows. +#define LLDB_USE_PYTHON_SET_INTERRUPT 0 +#else +// PyErr_SetInterrupt was introduced in 3.2. +#define LLDB_USE_PYTHON_SET_INTERRUPT \ + (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3) +#endif static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { ScriptInterpreter *script_interpreter = @@ -77,8 +85,6 @@ static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); } -static bool g_initialized = false; - namespace { // Initializing Python is not a straightforward process. We cannot control @@ -211,6 +217,28 @@ private: PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; bool m_was_already_initialized = false; }; + +#if LLDB_USE_PYTHON_SET_INTERRUPT +/// Saves the current signal handler for the specified signal and restores +/// it at the end of the current scope. +struct RestoreSignalHandlerScope { + /// The signal handler. + struct sigaction m_prev_handler; + int m_signal_code; + RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) { + // Initialize sigaction to their default state. + std::memset(&m_prev_handler, 0, sizeof(m_prev_handler)); + // Don't install a new handler, just read back the old one. + struct sigaction *new_handler = nullptr; + int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler); + lldbassert(signal_err == 0 && "sigaction failed to read handler"); + } + ~RestoreSignalHandlerScope() { + int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr); + lldbassert(signal_err == 0 && "sigaction failed to restore old handler"); + } +}; +#endif } // namespace void ScriptInterpreterPython::ComputePythonDirForApple( @@ -325,12 +353,12 @@ llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() { void ScriptInterpreterPython::Initialize() { static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), lldb::eScriptLanguagePython, ScriptInterpreterPythonImpl::CreateInstance); + ScriptInterpreterPythonImpl::Initialize(); }); } @@ -342,7 +370,6 @@ ScriptInterpreterPythonImpl::Locker::Locker( : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { - repro::Recorder::PrivateThread(); DoAcquireLock(); if ((on_entry & InitSession) == InitSession) { if (!DoInitSession(on_entry, in, out, err)) { @@ -408,8 +435,6 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_active_io_handler(eIOHandlerNone), m_session_is_active(false), m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { - InitializePrivate(); - m_scripted_process_interface_up = std::make_unique<ScriptedProcessPythonInterface>(*this); @@ -921,6 +946,22 @@ void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { } bool ScriptInterpreterPythonImpl::Interrupt() { +#if LLDB_USE_PYTHON_SET_INTERRUPT + // If the interpreter isn't evaluating any Python at the moment then return + // false to signal that this function didn't handle the interrupt and the + // next component should try handling it. + if (!IsExecutingPython()) + return false; + + // Tell Python that it should pretend to have received a SIGINT. + PyErr_SetInterrupt(); + // PyErr_SetInterrupt has no way to return an error so we can only pretend the + // signal got successfully handled and return true. + // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but + // the error handling is limited to checking the arguments which would be + // just our (hardcoded) input signal code SIGINT, so that's not useful at all. + return true; +#else Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (IsExecutingPython()) { @@ -942,6 +983,7 @@ bool ScriptInterpreterPythonImpl::Interrupt() { "ScriptInterpreterPythonImpl::Interrupt() python code not running, " "can't interrupt"); return false; +#endif } bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( @@ -1414,16 +1456,12 @@ ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - ret_val = LLDBSWIGPython_CreateFrameRecognizer(class_name, - m_dictionary_name.c_str()); - } + Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); + PythonObject ret_val = LLDBSWIGPython_CreateFrameRecognizer( + class_name, m_dictionary_name.c_str()); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( @@ -1478,16 +1516,12 @@ ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( if (!process_sp) return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - ret_val = LLDBSWIGPythonCreateOSPlugin( - class_name, m_dictionary_name.c_str(), process_sp); - } + Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); + PythonObject ret_val = LLDBSWIGPythonCreateOSPlugin( + class_name, m_dictionary_name.c_str(), process_sp); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( @@ -1733,19 +1767,16 @@ StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( if (!python_interpreter) return {}; - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedThreadPlan( - class_name, python_interpreter->m_dictionary_name.c_str(), - args_data, error_str, thread_plan_sp); - if (!ret_val) - return {}; - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + PythonObject ret_val = LLDBSwigPythonCreateScriptedThreadPlan( + class_name, python_interpreter->m_dictionary_name.c_str(), args_data, + error_str, thread_plan_sp); + if (!ret_val) + return {}; - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); + return StructuredData::ObjectSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop( @@ -1836,18 +1867,15 @@ ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( if (!python_interpreter) return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver( - class_name, python_interpreter->m_dictionary_name.c_str(), args_data, - bkpt_sp); - } + PythonObject ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver( + class_name, python_interpreter->m_dictionary_name.c_str(), args_data, + bkpt_sp); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback( @@ -1911,18 +1939,15 @@ StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( return StructuredData::GenericSP(); } - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedStopHook( - target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), - args_data, error); - } + PythonObject ret_val = LLDBSwigPythonCreateScriptedStopHook( + target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), + args_data, error); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop( @@ -2011,16 +2036,13 @@ ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( if (!python_interpreter) return StructuredData::ObjectSP(); - void *ret_val = nullptr; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateSyntheticProvider( - class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + PythonObject ret_val = LLDBSwigPythonCreateSyntheticProvider( + class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); + return StructuredData::ObjectSP( + new StructuredPythonObject(std::move(ret_val))); } StructuredData::GenericSP @@ -2033,16 +2055,13 @@ ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) { if (!debugger_sp.get()) return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateCommandObject( - class_name, m_dictionary_name.c_str(), debugger_sp); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + PythonObject ret_val = LLDBSwigPythonCreateCommandObject( + class_name, m_dictionary_name.c_str(), debugger_sp); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( @@ -2152,8 +2171,12 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( return false; } - if (new_callee && old_callee != new_callee) - callee_wrapper_sp = std::make_shared<StructuredPythonObject>(new_callee); + if (new_callee && old_callee != new_callee) { + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + callee_wrapper_sp = std::make_shared<StructuredPythonObject>( + PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee))); + } return ret_val; } @@ -2805,7 +2828,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj, exc_options) && module_pyobj) - *module_sp = std::make_shared<StructuredPythonObject>(module_pyobj); + *module_sp = std::make_shared<StructuredPythonObject>(PythonObject( + PyRefType::Owned, static_cast<PyObject *>(module_pyobj))); } return true; @@ -3145,12 +3169,7 @@ ScriptInterpreterPythonImpl::AcquireInterpreterLock() { return py_lock; } -void ScriptInterpreterPythonImpl::InitializePrivate() { - if (g_initialized) - return; - - g_initialized = true; - +void ScriptInterpreterPythonImpl::Initialize() { LLDB_SCOPED_TIMER(); // RAII-based initialization which correctly handles multiple-initialization, @@ -3180,6 +3199,25 @@ void ScriptInterpreterPythonImpl::InitializePrivate() { "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line"); + +#if LLDB_USE_PYTHON_SET_INTERRUPT + // Python will not just overwrite its internal SIGINT handler but also the + // one from the process. Backup the current SIGINT handler to prevent that + // Python deletes it. + RestoreSignalHandlerScope save_sigint(SIGINT); + + // Setup a default SIGINT signal handler that works the same way as the + // normal Python REPL signal handler which raises a KeyboardInterrupt. + // Also make sure to not pollute the user's REPL with the signal module nor + // our utility function. + PyRun_SimpleString("def lldb_setup_sigint_handler():\n" + " import signal;\n" + " def signal_handler(sig, frame):\n" + " raise KeyboardInterrupt()\n" + " signal.signal(signal.SIGINT, signal_handler);\n" + "lldb_setup_sigint_handler();\n" + "del lldb_setup_sigint_handler\n"); +#endif } void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location, diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index defc2acffcfa..3b80c67d201a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -341,7 +341,7 @@ public: static bool WatchpointCallbackFunction(void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id); - static void InitializePrivate(); + static void Initialize(); class SynchronicityHandler { private: diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp index e3c1931a565a..e39f8be73e49 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -32,7 +32,7 @@ ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) { + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { if (class_name.empty()) return {}; @@ -43,15 +43,12 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - void *ret_val = LLDBSwigPythonCreateScriptedProcess( + PythonObject ret_val = LLDBSwigPythonCreateScriptedProcess( class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp, args_impl, error_string); - if (!ret_val) - return {}; - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); return m_object_instance_sp; } @@ -92,6 +89,17 @@ ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( return mem_region; } +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { + Status error; + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_threads_info", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { Status error; @@ -154,12 +162,8 @@ ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { } lldb::ScriptedThreadInterfaceSP -ScriptedProcessPythonInterface::GetScriptedThreadInterface() { - if (!m_scripted_thread_interface_sp) - m_scripted_thread_interface_sp = - std::make_shared<ScriptedThreadPythonInterface>(m_interpreter); - - return m_scripted_thread_interface_sp; +ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { + return std::make_shared<ScriptedThreadPythonInterface>(m_interpreter); } #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h index 421bdd59887c..e34a181849eb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -25,7 +25,8 @@ public: StructuredData::GenericSP CreatePluginObject(const llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) override; + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; Status Launch() override; @@ -39,6 +40,8 @@ public: GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) override; + StructuredData::DictionarySP GetThreadsInfo() override; + StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override; StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override; @@ -55,7 +58,7 @@ public: llvm::Optional<std::string> GetScriptedThreadPluginName() override; private: - lldb::ScriptedThreadInterfaceSP GetScriptedThreadInterface() override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp index 6a881bfe625c..d471b2c5f7e3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp @@ -31,9 +31,8 @@ ScriptedThreadPythonInterface::ScriptedThreadPythonInterface( StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( const llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) { - - if (class_name.empty()) + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + if (class_name.empty() && !script_obj) return {}; ProcessSP process_sp = exe_ctx.GetProcessSP(); @@ -43,15 +42,21 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - void *ret_val = LLDBSwigPythonCreateScriptedThread( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), process_sp, - args_impl, error_string); + PythonObject ret_val; + + if (!script_obj) + ret_val = LLDBSwigPythonCreateScriptedThread( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), process_sp, + args_impl, error_string); + else + ret_val = PythonObject(PyRefType::Borrowed, + static_cast<PyObject *>(script_obj->GetValue())); if (!ret_val) return {}; m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); return m_object_instance_sp; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h index 996b8d43136b..59bb182ae3f3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h @@ -24,7 +24,8 @@ public: StructuredData::GenericSP CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) override; + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; lldb::tid_t GetThreadID() override; @@ -45,4 +46,4 @@ public: } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSTHREADINTERFACE_H +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h index 48f27b09b95c..c99372fa110c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h @@ -9,6 +9,13 @@ #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H +// BEGIN FIXME +// This declaration works around a clang module build failure. +// It should be deleted ASAP. +#include "llvm/Support/Error.h" +static llvm::Expected<bool> *g_fcxx_modules_workaround; +// END + #include "lldb/Host/Config.h" // Python.h needs to be included before any system headers in order to avoid diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp index 7a8ab9c9bcfd..25cb368763c1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -7,8 +7,13 @@ //===----------------------------------------------------------------------===// #include "DIERef.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" #include "llvm/Support/Format.h" +using namespace lldb; +using namespace lldb_private; + void llvm::format_provider<DIERef>::format(const DIERef &ref, raw_ostream &OS, StringRef Style) { if (ref.dwo_num()) @@ -16,3 +21,35 @@ void llvm::format_provider<DIERef>::format(const DIERef &ref, raw_ostream &OS, OS << (ref.section() == DIERef::DebugInfo ? "INFO" : "TYPE"); OS << "/" << format_hex_no_prefix(ref.die_offset(), 8); } + +constexpr uint32_t k_dwo_num_mask = 0x3FFFFFFF; +constexpr uint32_t k_dwo_num_valid_bitmask = (1u << 30); +constexpr uint32_t k_section_bitmask = (1u << 31); + +llvm::Optional<DIERef> DIERef::Decode(const DataExtractor &data, + lldb::offset_t *offset_ptr) { + const uint32_t bitfield_storage = data.GetU32(offset_ptr); + uint32_t dwo_num = bitfield_storage & k_dwo_num_mask; + bool dwo_num_valid = (bitfield_storage & (k_dwo_num_valid_bitmask)) != 0; + Section section = (Section)((bitfield_storage & (k_section_bitmask)) != 0); + // DIE offsets can't be zero and if we fail to decode something from data, + // it will return 0 + dw_offset_t die_offset = data.GetU32(offset_ptr); + if (die_offset == 0) + return llvm::None; + if (dwo_num_valid) + return DIERef(dwo_num, section, die_offset); + else + return DIERef(llvm::None, section, die_offset); +} + +void DIERef::Encode(DataEncoder &encoder) const { + uint32_t bitfield_storage = m_dwo_num; + if (m_dwo_num_valid) + bitfield_storage |= k_dwo_num_valid_bitmask; + if (m_section) + bitfield_storage |= k_section_bitmask; + encoder.AppendU32(bitfield_storage); + static_assert(sizeof(m_die_offset) == 4, "m_die_offset must be 4 bytes"); + encoder.AppendU32(m_die_offset); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h index f7e09ee17283..23e1eec26ec3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -54,6 +54,37 @@ public: return m_die_offset < other.m_die_offset; } + bool operator==(const DIERef &rhs) const { + return dwo_num() == rhs.dwo_num() && m_section == rhs.m_section && + m_die_offset == rhs.m_die_offset; + } + + bool operator!=(const DIERef &rhs) const { return !(*this == rhs); } + + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \return + /// Returns a valid DIERef if decoding succeeded, llvm::None if there was + /// unsufficient or invalid values that were decoded. + static llvm::Optional<DIERef> Decode(const lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr); + + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + void Encode(lldb_private::DataEncoder &encoder) const; + private: uint32_t m_dwo_num : 30; uint32_t m_dwo_num_valid : 1; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index b90f104c4d21..be555c130bfe 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -933,7 +933,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, DW_TAG_value_to_name(tag), type_name_cstr); CompilerType return_clang_type; - Type *func_type = NULL; + Type *func_type = nullptr; if (attrs.type.IsValid()) func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true); @@ -1027,7 +1027,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, class_opaque_type, attrs.name.GetCString(), clang_type, attrs.accessibility, attrs.is_artificial, is_variadic, attrs.is_objc_direct_call); - type_handled = objc_method_decl != NULL; + type_handled = objc_method_decl != nullptr; if (type_handled) { LinkDeclContextToDIE(objc_method_decl, die); m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); @@ -1178,7 +1178,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, attrs.is_artificial); - type_handled = cxx_method_decl != NULL; + type_handled = cxx_method_decl != nullptr; // Artificial methods are always handled even when we // don't create a new declaration for them. type_handled |= attrs.is_artificial; @@ -2036,7 +2036,7 @@ bool DWARFASTParserClang::ParseTemplateDIE( if (name && name[0]) template_param_infos.names.push_back(name); else - template_param_infos.names.push_back(NULL); + template_param_infos.names.push_back(nullptr); // Get the signed value for any integer or enumeration if available clang_type.IsIntegerOrEnumerationType(is_signed); @@ -3336,7 +3336,8 @@ DWARFASTParserClang::GetOwningClangModule(const DWARFDIE &die) { auto it = m_die_to_module.find(module_die.GetDIE()); if (it != m_die_to_module.end()) return it->second; - const char *name = module_die.GetAttributeValueAsString(DW_AT_name, 0); + const char *name = + module_die.GetAttributeValueAsString(DW_AT_name, nullptr); if (!name) return {}; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h index 1d3d70dfef01..c4995e721554 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -64,11 +64,11 @@ public: virtual void Dump(Stream &s) = 0; - StatsDuration GetIndexTime() { return m_index_time; } + StatsDuration::Duration GetIndexTime() { return m_index_time; } protected: Module &m_module; - StatsDuration m_index_time{0.0}; + StatsDuration m_index_time; /// Helper function implementing common logic for processing function dies. If /// the function given by "ref" matches search criteria given by diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 71d4c1e6c52f..2457e8276e20 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -269,7 +269,7 @@ protected: ExtractUnitDIENoDwoIfNeeded(); // m_first_die_mutex is not required as m_first_die is never cleared. if (!m_first_die) - return NULL; + return nullptr; return &m_first_die; } @@ -277,7 +277,7 @@ protected: const DWARFDebugInfoEntry *DIEPtr() { ExtractDIEsIfNeeded(); if (m_die_array.empty()) - return NULL; + return nullptr; return &m_die_array[0]; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp index 3f1d6677bacf..d2b8fe19db53 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp @@ -13,18 +13,20 @@ using namespace lldb_private; static constexpr Log::Category g_categories[] = { {{"comp"}, {"log insertions of object files into DWARF debug maps"}, - DWARF_LOG_TYPE_COMPLETION}, - {{"info"}, {"log the parsing of .debug_info"}, DWARF_LOG_DEBUG_INFO}, - {{"line"}, {"log the parsing of .debug_line"}, DWARF_LOG_DEBUG_LINE}, + DWARFLog::TypeCompletion}, + {{"info"}, {"log the parsing of .debug_info"}, DWARFLog::DebugInfo}, + {{"line"}, {"log the parsing of .debug_line"}, DWARFLog::DebugLine}, {{"lookups"}, {"log any lookups that happen by name, regex, or address"}, - DWARF_LOG_LOOKUPS}, - {{"map"}, - {"log struct/unions/class type completions"}, - DWARF_LOG_DEBUG_MAP}, + DWARFLog::Lookups}, + {{"map"}, {"log struct/unions/class type completions"}, DWARFLog::DebugMap}, }; -Log::Channel LogChannelDWARF::g_channel(g_categories, DWARF_LOG_DEFAULT); +static Log::Channel g_channel(g_categories, DWARFLog::DebugInfo); + +template <> Log::Channel &lldb_private::LogChannelFor<DWARFLog>() { + return g_channel; +} void LogChannelDWARF::Initialize() { Log::Register("dwarf", g_channel); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h index 2fc23563ef93..8076c719e9c4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h @@ -11,25 +11,32 @@ #include "lldb/Utility/Log.h" -#define DWARF_LOG_DEBUG_INFO (1u << 1) -#define DWARF_LOG_DEBUG_LINE (1u << 2) -#define DWARF_LOG_LOOKUPS (1u << 3) -#define DWARF_LOG_TYPE_COMPLETION (1u << 4) -#define DWARF_LOG_DEBUG_MAP (1u << 5) -#define DWARF_LOG_ALL (UINT32_MAX) -#define DWARF_LOG_DEFAULT (DWARF_LOG_DEBUG_INFO) - namespace lldb_private { -class LogChannelDWARF { - static Log::Channel g_channel; +enum class DWARFLog : Log::MaskType { + DebugInfo = Log::ChannelFlag<0>, + DebugLine = Log::ChannelFlag<1>, + DebugMap = Log::ChannelFlag<2>, + Lookups = Log::ChannelFlag<3>, + TypeCompletion = Log::ChannelFlag<4>, + LLVM_MARK_AS_BITMASK_ENUM(TypeCompletion) +}; +#define DWARF_LOG_DEBUG_INFO ::lldb_private::DWARFLog::DebugInfo +#define DWARF_LOG_DEBUG_LINE ::lldb_private::DWARFLog::DebugLine +#define DWARF_LOG_LOOKUPS ::lldb_private::DWARFLog::Lookups +#define DWARF_LOG_TYPE_COMPLETION ::lldb_private::DWARFLog::TypeCompletion +#define DWARF_LOG_DEBUG_MAP ::lldb_private::DWARFLog::DebugMap + +class LogChannelDWARF { public: static void Initialize(); static void Terminate(); - static Log *GetLogIfAll(uint32_t mask) { return g_channel.GetLogIfAll(mask); } - static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); } + static Log *GetLogIfAll(DWARFLog mask) { return GetLog(mask); } + static Log *GetLogIfAny(DWARFLog mask) { return GetLog(mask); } }; -} + +template <> Log::Channel &LogChannelFor<DWARFLog>(); +} // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_LOGCHANNELDWARF_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index ab10e9ca98f9..e15a22affcb2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -12,9 +12,12 @@ #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" +#include "lldb/Core/DataFileCache.h" #include "lldb/Core/Module.h" #include "lldb/Core/Progress.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" #include "llvm/Support/FormatVariadic.h" @@ -24,17 +27,19 @@ using namespace lldb_private; using namespace lldb; void ManualDWARFIndex::Index() { - if (!m_dwarf) + if (m_indexed) return; - - SymbolFileDWARF &main_dwarf = *m_dwarf; - m_dwarf = nullptr; + m_indexed = true; ElapsedTime elapsed(m_index_time); - LLDB_SCOPED_TIMERF("%p", static_cast<void *>(&main_dwarf)); + LLDB_SCOPED_TIMERF("%p", static_cast<void *>(m_dwarf)); + if (LoadFromCache()) { + m_dwarf->SetDebugInfoIndexWasLoadedFromCache(); + return; + } - DWARFDebugInfo &main_info = main_dwarf.DebugInfo(); - SymbolFileDWARFDwo *dwp_dwarf = main_dwarf.GetDwpSymbolFile().get(); + DWARFDebugInfo &main_info = m_dwarf->DebugInfo(); + SymbolFileDWARFDwo *dwp_dwarf = m_dwarf->GetDwpSymbolFile().get(); DWARFDebugInfo *dwp_info = dwp_dwarf ? &dwp_dwarf->DebugInfo() : nullptr; std::vector<DWARFUnit *> units_to_index; @@ -125,6 +130,8 @@ void ManualDWARFIndex::Index() { pool.async(finalize_fn, &IndexSet::types); pool.async(finalize_fn, &IndexSet::namespaces); pool.wait(); + + SaveToCache(); } void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, @@ -480,3 +487,214 @@ void ManualDWARFIndex::Dump(Stream &s) { s.Printf("\nNamespaces:\n"); m_set.namespaces.Dump(&s); } + +constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX"); +// Define IDs for the different tables when encoding and decoding the +// ManualDWARFIndex NameToDIE objects so we can avoid saving any empty maps. +enum DataID { + kDataIDFunctionBasenames = 1u, + kDataIDFunctionFullnames, + kDataIDFunctionMethods, + kDataIDFunctionSelectors, + kDataIDFunctionObjcClassSelectors, + kDataIDGlobals, + kDataIDTypes, + kDataIDNamespaces, + kDataIDEnd = 255u, + +}; +constexpr uint32_t CURRENT_CACHE_VERSION = 1; + +bool ManualDWARFIndex::IndexSet::Decode(const DataExtractor &data, + lldb::offset_t *offset_ptr) { + StringTableReader strtab; + // We now decode the string table for all strings in the data cache file. + if (!strtab.Decode(data, offset_ptr)) + return false; + + llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4); + if (identifier != kIdentifierManualDWARFIndex) + return false; + const uint32_t version = data.GetU32(offset_ptr); + if (version != CURRENT_CACHE_VERSION) + return false; + + bool done = false; + while (!done) { + switch (data.GetU8(offset_ptr)) { + default: + // If we got here, this is not expected, we expect the data IDs to match + // one of the values from the DataID enumeration. + return false; + case kDataIDFunctionBasenames: + if (!function_basenames.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDFunctionFullnames: + if (!function_fullnames.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDFunctionMethods: + if (!function_methods.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDFunctionSelectors: + if (!function_selectors.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDFunctionObjcClassSelectors: + if (!objc_class_selectors.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDGlobals: + if (!globals.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDTypes: + if (!types.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDNamespaces: + if (!namespaces.Decode(data, offset_ptr, strtab)) + return false; + break; + case kDataIDEnd: + // We got to the end of our NameToDIE encodings. + done = true; + break; + } + } + // Success! + return true; +} + +void ManualDWARFIndex::IndexSet::Encode(DataEncoder &encoder) const { + ConstStringTable strtab; + + // Encoder the DWARF index into a separate encoder first. This allows us + // gather all of the strings we willl need in "strtab" as we will need to + // write the string table out before the symbol table. + DataEncoder index_encoder(encoder.GetByteOrder(), + encoder.GetAddressByteSize()); + + index_encoder.AppendData(kIdentifierManualDWARFIndex); + // Encode the data version. + index_encoder.AppendU32(CURRENT_CACHE_VERSION); + + if (!function_basenames.IsEmpty()) { + index_encoder.AppendU8(kDataIDFunctionBasenames); + function_basenames.Encode(index_encoder, strtab); + } + if (!function_fullnames.IsEmpty()) { + index_encoder.AppendU8(kDataIDFunctionFullnames); + function_fullnames.Encode(index_encoder, strtab); + } + if (!function_methods.IsEmpty()) { + index_encoder.AppendU8(kDataIDFunctionMethods); + function_methods.Encode(index_encoder, strtab); + } + if (!function_selectors.IsEmpty()) { + index_encoder.AppendU8(kDataIDFunctionSelectors); + function_selectors.Encode(index_encoder, strtab); + } + if (!objc_class_selectors.IsEmpty()) { + index_encoder.AppendU8(kDataIDFunctionObjcClassSelectors); + objc_class_selectors.Encode(index_encoder, strtab); + } + if (!globals.IsEmpty()) { + index_encoder.AppendU8(kDataIDGlobals); + globals.Encode(index_encoder, strtab); + } + if (!types.IsEmpty()) { + index_encoder.AppendU8(kDataIDTypes); + types.Encode(index_encoder, strtab); + } + if (!namespaces.IsEmpty()) { + index_encoder.AppendU8(kDataIDNamespaces); + namespaces.Encode(index_encoder, strtab); + } + index_encoder.AppendU8(kDataIDEnd); + + // Now that all strings have been gathered, we will emit the string table. + strtab.Encode(encoder); + // Followed the the symbol table data. + encoder.AppendData(index_encoder.GetData()); +} + +bool ManualDWARFIndex::Decode(const DataExtractor &data, + lldb::offset_t *offset_ptr, + bool &signature_mismatch) { + signature_mismatch = false; + CacheSignature signature; + if (!signature.Decode(data, offset_ptr)) + return false; + if (CacheSignature(m_dwarf->GetObjectFile()) != signature) { + signature_mismatch = true; + return false; + } + IndexSet set; + if (!set.Decode(data, offset_ptr)) + return false; + m_set = std::move(set); + return true; +} + +bool ManualDWARFIndex::Encode(DataEncoder &encoder) const { + CacheSignature signature(m_dwarf->GetObjectFile()); + if (!signature.Encode(encoder)) + return false; + m_set.Encode(encoder); + return true; +} + +std::string ManualDWARFIndex::GetCacheKey() { + std::string key; + llvm::raw_string_ostream strm(key); + // DWARF Index can come from different object files for the same module. A + // module can have one object file as the main executable and might have + // another object file in a separate symbol file, or we might have a .dwo file + // that claims its module is the main executable. + ObjectFile *objfile = m_dwarf->GetObjectFile(); + strm << objfile->GetModule()->GetCacheKey() << "-dwarf-index-" + << llvm::format_hex(objfile->GetCacheHash(), 10); + return strm.str(); +} + +bool ManualDWARFIndex::LoadFromCache() { + DataFileCache *cache = Module::GetIndexCache(); + if (!cache) + return false; + ObjectFile *objfile = m_dwarf->GetObjectFile(); + if (!objfile) + return false; + std::unique_ptr<llvm::MemoryBuffer> mem_buffer_up = + cache->GetCachedData(GetCacheKey()); + if (!mem_buffer_up) + return false; + DataExtractor data(mem_buffer_up->getBufferStart(), + mem_buffer_up->getBufferSize(), + endian::InlHostByteOrder(), + objfile->GetAddressByteSize()); + bool signature_mismatch = false; + lldb::offset_t offset = 0; + const bool result = Decode(data, &offset, signature_mismatch); + if (signature_mismatch) + cache->RemoveCacheFile(GetCacheKey()); + return result; +} + +void ManualDWARFIndex::SaveToCache() { + DataFileCache *cache = Module::GetIndexCache(); + if (!cache) + return; // Caching is not enabled. + ObjectFile *objfile = m_dwarf->GetObjectFile(); + if (!objfile) + return; + DataEncoder file(endian::InlHostByteOrder(), objfile->GetAddressByteSize()); + // Encode will return false if the object file doesn't have anything to make + // a signature from. + if (Encode(file)) { + if (cache->SetCachedData(GetCacheKey(), file.GetData())) + m_dwarf->SetDebugInfoIndexWasSavedToCache(); + } +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index 36f371402b90..5c5e43de9ca6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -55,7 +55,7 @@ public: void Dump(Stream &s) override; -private: + // Make IndexSet public so we can unit test the encoding and decoding logic. struct IndexSet { NameToDIE function_basenames; NameToDIE function_fullnames; @@ -65,21 +65,113 @@ private: NameToDIE globals; NameToDIE types; NameToDIE namespaces; + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr); + void Encode(DataEncoder &encoder) const; + bool operator==(const IndexSet &rhs) const { + return function_basenames == rhs.function_basenames && + function_fullnames == rhs.function_fullnames && + function_methods == rhs.function_methods && + function_selectors == rhs.function_selectors && + objc_class_selectors == rhs.objc_class_selectors && + globals == rhs.globals && types == rhs.types && + namespaces == rhs.namespaces; + } }; + +private: void Index(); + + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + bool &signature_mismatch); + + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + /// + /// \return + /// True if the symbol table's object file can generate a valid signature + /// and all data for the symbol table was encoded, false otherwise. + bool Encode(DataEncoder &encoder) const; + + /// Get the cache key string for this symbol table. + /// + /// The cache key must start with the module's cache key and is followed + /// by information that indicates this key is for caching the symbol table + /// contents and should also include the has of the object file. A module can + /// be represented by an ObjectFile object for the main executable, but can + /// also have a symbol file that is from the same or a different object file. + /// This means we might have two symbol tables cached in the index cache, one + /// for the main executable and one for the symbol file. + /// + /// \return + /// The unique cache key used to save and retrieve data from the index + /// cache. + std::string GetCacheKey(); + + /// Save the symbol table data out into a cache. + /// + /// The symbol table will only be saved to a cache file if caching is enabled. + /// + /// We cache the contents of the symbol table since symbol tables in LLDB take + /// some time to initialize. This is due to the many sources for data that are + /// used to create a symbol table: + /// - standard symbol table + /// - dynamic symbol table (ELF) + /// - compressed debug info sections + /// - unwind information + /// - function pointers found in runtimes for global constructor/destructors + /// - other sources. + /// All of the above sources are combined and one symbol table results after + /// all sources have been considered. + void SaveToCache(); + + /// Load the symbol table from the index cache. + /// + /// Quickly load the finalized symbol table from the index cache. This saves + /// time when the debugger starts up. The index cache file for the symbol + /// table has the modification time set to the same time as the main module. + /// If the cache file exists and the modification times match, we will load + /// the symbol table from the serlized cache file. + /// + /// \return + /// True if the symbol table was successfully loaded from the index cache, + /// false if the symbol table wasn't cached or was out of date. + bool LoadFromCache(); + void IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, IndexSet &set); static void IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language, IndexSet &set); - /// The DWARF file which we are indexing. Set to nullptr after the index is - /// built. + /// The DWARF file which we are indexing. SymbolFileDWARF *m_dwarf; /// Which dwarf units should we skip while building the index. llvm::DenseSet<dw_offset_t> m_units_to_avoid; IndexSet m_set; + bool m_indexed = false; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index 493d1b4a2702..413920f33619 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -8,8 +8,11 @@ #include "NameToDIE.h" #include "DWARFUnit.h" +#include "lldb/Core/DataFileCache.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" @@ -18,7 +21,7 @@ using namespace lldb; using namespace lldb_private; void NameToDIE::Finalize() { - m_map.Sort(); + m_map.Sort(std::less<DIERef>()); m_map.SizeToFit(); } @@ -87,3 +90,50 @@ void NameToDIE::Append(const NameToDIE &other) { other.m_map.GetValueAtIndexUnchecked(i)); } } + +constexpr llvm::StringLiteral kIdentifierNameToDIE("N2DI"); + +bool NameToDIE::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + const StringTableReader &strtab) { + m_map.Clear(); + llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4); + if (identifier != kIdentifierNameToDIE) + return false; + const uint32_t count = data.GetU32(offset_ptr); + for (uint32_t i = 0; i < count; ++i) { + llvm::StringRef str(strtab.Get(data.GetU32(offset_ptr))); + // No empty strings allowed in the name to DIE maps. + if (str.empty()) + return false; + if (llvm::Optional<DIERef> die_ref = DIERef::Decode(data, offset_ptr)) + m_map.Append(ConstString(str), die_ref.getValue()); + else + return false; + } + return true; +} + +void NameToDIE::Encode(DataEncoder &encoder, ConstStringTable &strtab) const { + encoder.AppendData(kIdentifierNameToDIE); + encoder.AppendU32(m_map.GetSize()); + for (const auto &entry : m_map) { + // Make sure there are no empty strings. + assert((bool)entry.cstring); + encoder.AppendU32(strtab.Add(entry.cstring)); + entry.value.Encode(encoder); + } +} + +bool NameToDIE::operator==(const NameToDIE &rhs) const { + const size_t size = m_map.GetSize(); + if (size != rhs.m_map.GetSize()) + return false; + for (size_t i = 0; i < size; ++i) { + if (m_map.GetCStringAtIndex(i) != rhs.m_map.GetCStringAtIndex(i)) + return false; + if (m_map.GetValueRefAtIndexUnchecked(i) != + rhs.m_map.GetValueRefAtIndexUnchecked(i)) + return false; + } + return true; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h index 994af07189f8..61df1a628ab5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -48,6 +48,44 @@ public: const DIERef &die_ref)> const &callback) const; + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + bool Decode(const lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + const lldb_private::StringTableReader &strtab); + + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + void Encode(lldb_private::DataEncoder &encoder, + lldb_private::ConstStringTable &strtab) const; + + /// Used for unit testing the encoding and decoding. + bool operator==(const NameToDIE &rhs) const; + + bool IsEmpty() const { return m_map.IsEmpty(); } + + void Clear() { m_map.Clear(); } + protected: lldb_private::UniqueCStringMap<DIERef> m_map; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 8c995ef2eb2a..02d1a6a4a8be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2140,7 +2140,8 @@ void SymbolFileDWARF::FindGlobalVariables( llvm::StringRef basename; llvm::StringRef context; - bool name_is_mangled = (bool)Mangled(name); + bool name_is_mangled = Mangled::GetManglingScheme(name.GetStringRef()) != + Mangled::eManglingSchemeNone; if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(), context, basename)) @@ -4085,8 +4086,8 @@ LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) { return LanguageTypeFromDWARF(lang); } -StatsDuration SymbolFileDWARF::GetDebugInfoIndexTime() { +StatsDuration::Duration SymbolFileDWARF::GetDebugInfoIndexTime() { if (m_index) return m_index->GetIndexTime(); - return StatsDuration(0.0); + return {}; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index e81ce28cb86e..f84a78620e17 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -319,10 +319,10 @@ public: /// Same as GetLanguage() but reports all C++ versions as C++ (no version). static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit); - lldb_private::StatsDuration GetDebugInfoParseTime() override { + lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override { return m_parse_time; } - lldb_private::StatsDuration GetDebugInfoIndexTime() override; + lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override; lldb_private::StatsDuration &GetDebugInfoParseTimeRef() { return m_parse_time; @@ -559,7 +559,7 @@ protected: /// Try to filter out this debug info by comparing it to the lowest code /// address in the module. lldb::addr_t m_first_code_address = LLDB_INVALID_ADDRESS; - lldb_private::StatsDuration m_parse_time{0.0}; + lldb_private::StatsDuration m_parse_time; }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARF_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 2491f6af8c19..6ee189e04250 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1447,8 +1447,8 @@ uint64_t SymbolFileDWARFDebugMap::GetDebugInfoSize() { return debug_info_size; } -StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoParseTime() { - StatsDuration elapsed(0.0); +StatsDuration::Duration SymbolFileDWARFDebugMap::GetDebugInfoParseTime() { + StatsDuration::Duration elapsed(0.0); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { ObjectFile *oso_objfile = oso_dwarf->GetObjectFile(); if (oso_objfile) { @@ -1464,8 +1464,8 @@ StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoParseTime() { return elapsed; } -StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoIndexTime() { - StatsDuration elapsed(0.0); +StatsDuration::Duration SymbolFileDWARFDebugMap::GetDebugInfoIndexTime() { + StatsDuration::Duration elapsed(0.0); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { ObjectFile *oso_objfile = oso_dwarf->GetObjectFile(); if (oso_objfile) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 74f32442de2f..2a6232a501b4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -143,8 +143,8 @@ public: llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } uint64_t GetDebugInfoSize() override; - lldb_private::StatsDuration GetDebugInfoParseTime() override; - lldb_private::StatsDuration GetDebugInfoIndexTime() override; + lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override; + lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override; protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index 9f09c0accc87..d8f737612c25 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -106,6 +106,24 @@ static void ParseExtendedInfo(PdbIndex &index, CompilandIndexItem &item) { } } +static void ParseInlineeLineTableForCompileUnit(CompilandIndexItem &item) { + for (const auto &ss : item.m_debug_stream.getSubsectionsArray()) { + if (ss.kind() != DebugSubsectionKind::InlineeLines) + continue; + + DebugInlineeLinesSubsectionRef inlinee_lines; + llvm::BinaryStreamReader reader(ss.getRecordData()); + if (llvm::Error error = inlinee_lines.initialize(reader)) { + consumeError(std::move(error)); + continue; + } + + for (const InlineeSourceLine &Line : inlinee_lines) { + item.m_inline_map[Line.Header->Inlinee] = Line; + } + } +} + CompilandIndexItem::CompilandIndexItem( PdbCompilandId id, llvm::pdb::ModuleDebugStreamRef debug_stream, llvm::pdb::DbiModuleDescriptor descriptor) @@ -142,6 +160,7 @@ CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) { cci = std::make_unique<CompilandIndexItem>( PdbCompilandId{modi}, std::move(debug_stream), std::move(descriptor)); ParseExtendedInfo(m_index, *cci); + ParseInlineeLineTableForCompileUnit(*cci); cci->m_strings.initialize(debug_stream.getSubsectionsArray()); PDBStringTable &strings = cantFail(m_index.pdb().getStringTable()); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h index 088de970cbf3..4ad27de98695 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h @@ -9,10 +9,12 @@ #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_COMPILEUNITINDEX_H #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_COMPILEUNITINDEX_H +#include "lldb/Utility/RangeMap.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" @@ -69,6 +71,17 @@ struct CompilandIndexItem { // command line, etc. This usually contains exactly 5 items which // are references to other strings. llvm::SmallVector<llvm::codeview::TypeIndex, 5> m_build_info; + + // Inlinee lines table in this compile unit. + std::map<llvm::codeview::TypeIndex, llvm::codeview::InlineeSourceLine> + m_inline_map; + + // It's the line table parsed from DEBUG_S_LINES sections, mapping the file + // address range to file index and source line number. + using GlobalLineTable = + lldb_private::RangeDataVector<lldb::addr_t, uint32_t, + std::pair<uint32_t, uint32_t>>; + GlobalLineTable m_global_line_table; }; /// Indexes information about all compile units. This is really just a map of diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 9473befa6cc3..dc0969a0ce7c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1081,7 +1081,7 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { clang::FunctionDecl *function_decl = nullptr; if (parent->isRecord()) { - clang::QualType parent_qt = llvm::dyn_cast<clang::TypeDecl>(parent) + clang::QualType parent_qt = llvm::cast<clang::TypeDecl>(parent) ->getTypeForDecl() ->getCanonicalTypeInternal(); lldb::opaque_compiler_type_t parent_opaque_ty = @@ -1318,7 +1318,7 @@ void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf( if (!context->isNamespace()) continue; - clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(context); + clang::NamespaceDecl *ns = llvm::cast<clang::NamespaceDecl>(context); std::string actual_ns = ns->getQualifiedNameAsString(); if (llvm::StringRef(actual_ns).startswith(*parent)) { clang::QualType qt = GetOrCreateType(tid); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h index 1b382e5263c1..edbdd9ee290b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h @@ -25,7 +25,6 @@ namespace llvm { namespace pdb { class DbiStream; class TpiStream; -class TpiStream; class InfoStream; class PublicsStream; class GlobalsStream; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index e859b1d5a86c..a035a791f868 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -330,31 +330,65 @@ uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() { Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi); CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset); - - if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32) { - // This is a function. It must be global. Creating the Function entry for - // it automatically creates a block for it. - CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); - return GetOrCreateFunction(block_id, *comp_unit)->GetBlock(false); - } - - lldbassert(sym.kind() == S_BLOCK32); - - // This is a block. Its parent is either a function or another block. In - // either case, its parent can be viewed as a block (e.g. a function contains - // 1 big block. So just get the parent block and add this block to it. - BlockSym block(static_cast<SymbolRecordKind>(sym.kind())); - cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block)); - lldbassert(block.Parent != 0); - PdbCompilandSymId parent_id(block_id.modi, block.Parent); - Block &parent_block = GetOrCreateBlock(parent_id); + CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); BlockSP child_block = std::make_shared<Block>(opaque_block_uid); - parent_block.AddChild(child_block); - m_ast->GetOrCreateBlockDecl(block_id); + switch (sym.kind()) { + case S_GPROC32: + case S_LPROC32: { + // This is a function. It must be global. Creating the Function entry + // for it automatically creates a block for it. + FunctionSP func = GetOrCreateFunction(block_id, *comp_unit); + Block &block = func->GetBlock(false); + if (block.GetNumRanges() == 0) + block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); + return block; + } + case S_BLOCK32: { + // This is a block. Its parent is either a function or another block. In + // either case, its parent can be viewed as a block (e.g. a function + // contains 1 big block. So just get the parent block and add this block + // to it. + BlockSym block(static_cast<SymbolRecordKind>(sym.kind())); + cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block)); + lldbassert(block.Parent != 0); + PdbCompilandSymId parent_id(block_id.modi, block.Parent); + Block &parent_block = GetOrCreateBlock(parent_id); + parent_block.AddChild(child_block); + m_ast->GetOrCreateBlockDecl(block_id); + m_blocks.insert({opaque_block_uid, child_block}); + break; + } + case S_INLINESITE: { + // This ensures line table is parsed first so we have inline sites info. + comp_unit->GetLineTable(); + + std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid]; + Block &parent_block = GetOrCreateBlock(inline_site->parent_id); + parent_block.AddChild(child_block); + + // Copy ranges from InlineSite to Block. + for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) { + auto *entry = inline_site->ranges.GetEntryAtIndex(i); + child_block->AddRange( + Block::Range(entry->GetRangeBase(), entry->GetByteSize())); + } + child_block->FinalizeRanges(); + + // Get the inlined function callsite info. + Declaration &decl = inline_site->inline_function_info->GetDeclaration(); + Declaration &callsite = inline_site->inline_function_info->GetCallSite(); + child_block->SetInlinedFunctionInfo( + inline_site->inline_function_info->GetName().GetCString(), nullptr, + &decl, &callsite); + m_blocks.insert({opaque_block_uid, child_block}); + break; + } + default: + lldbassert(false && "Symbol is not a block!"); + } - m_blocks.insert({opaque_block_uid, child_block}); return *child_block; } @@ -971,16 +1005,22 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( continue; if (type == PDB_SymType::Function) { sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get(); - sc.block = sc.GetFunctionBlock(); + Block &block = sc.function->GetBlock(true); + addr_t func_base = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + addr_t offset = file_addr - func_base; + sc.block = block.FindInnermostBlockByOffset(offset); } if (type == PDB_SymType::Block) { sc.block = &GetOrCreateBlock(csid); sc.function = sc.block->CalculateSymbolContextFunction(); } - resolved_flags |= eSymbolContextFunction; - resolved_flags |= eSymbolContextBlock; - break; + if (sc.function) + resolved_flags |= eSymbolContextFunction; + if (sc.block) + resolved_flags |= eSymbolContextBlock; + break; } } @@ -998,43 +1038,24 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( uint32_t SymbolFileNativePDB::ResolveSymbolContext( const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { - return 0; -} - -static void AppendLineEntryToSequence(LineTable &table, LineSequence &sequence, - const CompilandIndexItem &cci, - lldb::addr_t base_addr, - uint32_t file_number, - const LineFragmentHeader &block, - const LineNumberEntry &cur) { - LineInfo cur_info(cur.Flags); - - if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) - return; - - uint64_t addr = base_addr + cur.Offset; - - bool is_statement = cur_info.isStatement(); - bool is_prologue = IsFunctionPrologue(cci, addr); - bool is_epilogue = IsFunctionEpilogue(cci, addr); - - uint32_t lno = cur_info.getStartLine(); - - table.AppendLineEntryToSequence(&sequence, addr, lno, 0, file_number, - is_statement, false, is_prologue, is_epilogue, - false); -} + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + const uint32_t prev_size = sc_list.GetSize(); + if (resolve_scope & eSymbolContextCompUnit) { + for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; + ++cu_idx) { + CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get(); + if (!cu) + continue; -static void TerminateLineSequence(LineTable &table, - const LineFragmentHeader &block, - lldb::addr_t base_addr, uint32_t file_number, - uint32_t last_line, - std::unique_ptr<LineSequence> seq) { - // The end is always a terminal entry, so insert it regardless. - table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize, - last_line, 0, file_number, false, false, - false, false, true); - table.InsertSequence(seq.get()); + bool file_spec_matches_cu_file_spec = FileSpec::Match( + src_location_spec.GetFileSpec(), cu->GetPrimaryFile()); + if (file_spec_matches_cu_file_spec) { + cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); + break; + } + } + } + return sc_list.GetSize() - prev_size; } bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { @@ -1045,16 +1066,21 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); - CompilandIndexItem *cci = - m_index->compilands().GetCompiland(cu_id.asCompiland().modi); - lldbassert(cci); - auto line_table = std::make_unique<LineTable>(&comp_unit); + uint16_t modi = cu_id.asCompiland().modi; + CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi); + lldbassert(cii); + + // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records + // in this CU. Add line entries into the set first so that if there are line + // entries with same addres, the later is always more accurate than the + // former. + std::set<LineTable::Entry, LineTableEntryComparator> line_set; // This is basically a copy of the .debug$S subsections from all original COFF // object files merged together with address relocations applied. We are // looking for all DEBUG_S_LINES subsections. for (const DebugSubsectionRecord &dssr : - cci->m_debug_stream.getSubsectionsArray()) { + cii->m_debug_stream.getSubsectionsArray()) { if (dssr.kind() != DebugSubsectionKind::Lines) continue; @@ -1069,42 +1095,111 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { uint64_t virtual_addr = m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset); - const auto &checksums = cci->m_strings.checksums().getArray(); - const auto &strings = cci->m_strings.strings(); for (const LineColumnEntry &group : lines) { - // Indices in this structure are actually offsets of records in the - // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index - // into the global PDB string table. - auto iter = checksums.at(group.NameIndex); - if (iter == checksums.end()) + llvm::Expected<uint32_t> file_index_or_err = + GetFileIndex(*cii, group.NameIndex); + if (!file_index_or_err) continue; + uint32_t file_index = file_index_or_err.get(); + lldbassert(!group.LineNumbers.empty()); + CompilandIndexItem::GlobalLineTable::Entry line_entry( + LLDB_INVALID_ADDRESS, 0); + for (const LineNumberEntry &entry : group.LineNumbers) { + LineInfo cur_info(entry.Flags); - llvm::Expected<llvm::StringRef> efn = - strings.getString(iter->FileNameOffset); - if (!efn) { - llvm::consumeError(efn.takeError()); - continue; - } + if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) + continue; - // LLDB wants the index of the file in the list of support files. - auto fn_iter = llvm::find(cci->m_file_list, *efn); - lldbassert(fn_iter != cci->m_file_list.end()); - uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter); + uint64_t addr = virtual_addr + entry.Offset; - std::unique_ptr<LineSequence> sequence( - line_table->CreateLineSequenceContainer()); - lldbassert(!group.LineNumbers.empty()); + bool is_statement = cur_info.isStatement(); + bool is_prologue = IsFunctionPrologue(*cii, addr); + bool is_epilogue = IsFunctionEpilogue(*cii, addr); - for (const LineNumberEntry &entry : group.LineNumbers) { - AppendLineEntryToSequence(*line_table, *sequence, *cci, virtual_addr, - file_index, *lfh, entry); + uint32_t lno = cur_info.getStartLine(); + + line_set.emplace(addr, lno, 0, file_index, is_statement, false, + is_prologue, is_epilogue, false); + + if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { + line_entry.SetRangeEnd(addr); + cii->m_global_line_table.Append(line_entry); + } + line_entry.SetRangeBase(addr); + line_entry.data = {file_index, lno}; } LineInfo last_line(group.LineNumbers.back().Flags); - TerminateLineSequence(*line_table, *lfh, virtual_addr, file_index, - last_line.getEndLine(), std::move(sequence)); + line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0, + file_index, false, false, false, false, true); + + if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { + line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize); + cii->m_global_line_table.Append(line_entry); + } } } + cii->m_global_line_table.Sort(); + + // Parse all S_INLINESITE in this CU. + const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray(); + for (auto iter = syms.begin(); iter != syms.end();) { + if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) { + ++iter; + continue; + } + + uint32_t record_offset = iter.offset(); + CVSymbol func_record = + cii->m_debug_stream.readSymbolAtOffset(record_offset); + SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record); + addr_t file_vm_addr = m_index->MakeVirtualAddress(sol.so); + AddressRange func_range(file_vm_addr, sol.length, + comp_unit.GetModule()->GetSectionList()); + Address func_base = func_range.GetBaseAddress(); + PdbCompilandSymId func_id{modi, record_offset}; + + // Iterate all S_INLINESITEs in the function. + auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) { + if (kind != S_INLINESITE) + return false; + + ParseInlineSite(id, func_base); + + for (const auto &line_entry : + m_inline_sites[toOpaqueUid(id)]->line_entries) { + // If line_entry is not terminal entry, remove previous line entry at + // the same address and insert new one. Terminal entry inside an inline + // site might not be terminal entry for its parent. + if (!line_entry.is_terminal_entry) + line_set.erase(line_entry); + line_set.insert(line_entry); + } + // No longer useful after adding to line_set. + m_inline_sites[toOpaqueUid(id)]->line_entries.clear(); + return true; + }; + ParseSymbolArrayInScope(func_id, parse_inline_sites); + // Jump to the end of the function record. + iter = syms.at(getScopeEndOffset(func_record)); + } + + cii->m_global_line_table.Clear(); + + // Add line entries in line_set to line_table. + auto line_table = std::make_unique<LineTable>(&comp_unit); + std::unique_ptr<LineSequence> sequence( + line_table->CreateLineSequenceContainer()); + for (const auto &line_entry : line_set) { + line_table->AppendLineEntryToSequence( + sequence.get(), line_entry.file_addr, line_entry.line, + line_entry.column, line_entry.file_idx, + line_entry.is_start_of_statement, line_entry.is_start_of_basic_block, + line_entry.is_prologue_end, line_entry.is_epilogue_begin, + line_entry.is_terminal_entry); + } + line_table->InsertSequence(sequence.get()); + if (line_table->GetSize() == 0) return false; @@ -1117,6 +1212,33 @@ bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) { return false; } +llvm::Expected<uint32_t> +SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii, + uint32_t file_id) { + auto index_iter = m_file_indexes.find(file_id); + if (index_iter != m_file_indexes.end()) + return index_iter->getSecond(); + const auto &checksums = cii.m_strings.checksums().getArray(); + const auto &strings = cii.m_strings.strings(); + // Indices in this structure are actually offsets of records in the + // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index + // into the global PDB string table. + auto iter = checksums.at(file_id); + if (iter == checksums.end()) + return llvm::make_error<RawError>(raw_error_code::no_entry); + + llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset); + if (!efn) { + return efn.takeError(); + } + + // LLDB wants the index of the file in the list of support files. + auto fn_iter = llvm::find(cii.m_file_list, *efn); + lldbassert(fn_iter != cii.m_file_list.end()); + m_file_indexes[file_id] = std::distance(cii.m_file_list.begin(), fn_iter); + return m_file_indexes[file_id]; +} + bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); @@ -1141,11 +1263,223 @@ bool SymbolFileNativePDB::ParseImportedModules( return false; } +void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, + Address func_addr) { + lldb::user_id_t opaque_uid = toOpaqueUid(id); + if (m_inline_sites.find(opaque_uid) != m_inline_sites.end()) + return; + + addr_t func_base = func_addr.GetFileAddress(); + CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi); + CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset); + CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); + + InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind())); + cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)); + PdbCompilandSymId parent_id(id.modi, inline_site.Parent); + + std::shared_ptr<InlineSite> inline_site_sp = + std::make_shared<InlineSite>(parent_id); + + // Get the inlined function declaration info. + auto iter = cii->m_inline_map.find(inline_site.Inlinee); + if (iter == cii->m_inline_map.end()) + return; + InlineeSourceLine inlinee_line = iter->second; + + const FileSpecList &files = comp_unit->GetSupportFiles(); + FileSpec decl_file; + llvm::Expected<uint32_t> file_index_or_err = + GetFileIndex(*cii, inlinee_line.Header->FileID); + if (!file_index_or_err) + return; + uint32_t decl_file_idx = file_index_or_err.get(); + decl_file = files.GetFileSpecAtIndex(decl_file_idx); + uint32_t decl_line = inlinee_line.Header->SourceLineNum; + std::unique_ptr<Declaration> decl_up = + std::make_unique<Declaration>(decl_file, decl_line); + + // Parse range and line info. + uint32_t code_offset = 0; + int32_t line_offset = 0; + bool has_base = false; + bool is_new_line_offset = false; + + bool is_start_of_statement = false; + // The first instruction is the prologue end. + bool is_prologue_end = true; + + auto change_code_offset = [&](uint32_t code_delta) { + if (has_base) { + inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( + code_offset, code_delta, decl_line + line_offset)); + is_prologue_end = false; + is_start_of_statement = false; + } else { + is_start_of_statement = true; + } + has_base = true; + code_offset += code_delta; + + if (is_new_line_offset) { + LineTable::Entry line_entry(func_base + code_offset, + decl_line + line_offset, 0, decl_file_idx, + true, false, is_prologue_end, false, false); + inline_site_sp->line_entries.push_back(line_entry); + is_new_line_offset = false; + } + }; + auto change_code_length = [&](uint32_t length) { + inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( + code_offset, length, decl_line + line_offset)); + has_base = false; + + LineTable::Entry end_line_entry(func_base + code_offset + length, + decl_line + line_offset, 0, decl_file_idx, + false, false, false, false, true); + inline_site_sp->line_entries.push_back(end_line_entry); + }; + auto change_line_offset = [&](int32_t line_delta) { + line_offset += line_delta; + if (has_base) { + LineTable::Entry line_entry( + func_base + code_offset, decl_line + line_offset, 0, decl_file_idx, + is_start_of_statement, false, is_prologue_end, false, false); + inline_site_sp->line_entries.push_back(line_entry); + } else { + // Add line entry in next call to change_code_offset. + is_new_line_offset = true; + } + }; + + for (auto &annot : inline_site.annotations()) { + switch (annot.OpCode) { + case BinaryAnnotationsOpCode::CodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: + change_code_offset(annot.U1); + break; + case BinaryAnnotationsOpCode::ChangeLineOffset: + change_line_offset(annot.S1); + break; + case BinaryAnnotationsOpCode::ChangeCodeLength: + change_code_length(annot.U1); + code_offset += annot.U1; + break; + case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: + change_code_offset(annot.U1); + change_line_offset(annot.S1); + break; + case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: + change_code_offset(annot.U2); + change_code_length(annot.U1); + break; + default: + break; + } + } + + inline_site_sp->ranges.Sort(); + inline_site_sp->ranges.CombineConsecutiveEntriesWithEqualData(); + + // Get the inlined function callsite info. + std::unique_ptr<Declaration> callsite_up; + if (!inline_site_sp->ranges.IsEmpty()) { + auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0); + addr_t base_offset = entry->GetRangeBase(); + if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() == + S_INLINESITE) { + // Its parent is another inline site, lookup parent site's range vector + // for callsite line. + ParseInlineSite(parent_id, func_base); + std::shared_ptr<InlineSite> parent_site = + m_inline_sites[toOpaqueUid(parent_id)]; + FileSpec &parent_decl_file = + parent_site->inline_function_info->GetDeclaration().GetFile(); + if (auto *parent_entry = + parent_site->ranges.FindEntryThatContains(base_offset)) { + callsite_up = + std::make_unique<Declaration>(parent_decl_file, parent_entry->data); + } + } else { + // Its parent is a function, lookup global line table for callsite. + if (auto *entry = cii->m_global_line_table.FindEntryThatContains( + func_base + base_offset)) { + const FileSpec &callsite_file = + files.GetFileSpecAtIndex(entry->data.first); + callsite_up = + std::make_unique<Declaration>(callsite_file, entry->data.second); + } + } + } + + // Get the inlined function name. + CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee); + std::string inlinee_name; + if (inlinee_cvt.kind() == LF_MFUNC_ID) { + MemberFuncIdRecord mfr; + cantFail( + TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr)); + LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); + inlinee_name.append(std::string(types.getTypeName(mfr.ClassType))); + inlinee_name.append("::"); + inlinee_name.append(mfr.getName().str()); + } else if (inlinee_cvt.kind() == LF_FUNC_ID) { + FuncIdRecord fir; + cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir)); + TypeIndex parent_idx = fir.getParentScope(); + if (!parent_idx.isNoneType()) { + LazyRandomTypeCollection &ids = m_index->ipi().typeCollection(); + inlinee_name.append(std::string(ids.getTypeName(parent_idx))); + inlinee_name.append("::"); + } + inlinee_name.append(fir.getName().str()); + } + inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>( + inlinee_name.c_str(), llvm::StringRef(), decl_up.get(), + callsite_up.get()); + + m_inline_sites[opaque_uid] = inline_site_sp; +} + size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - GetOrCreateBlock(PdbSymUid(func.GetID()).asCompilandSym()); - // FIXME: Parse child blocks - return 1; + PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym(); + // After we iterate through inline sites inside the function, we already get + // all the info needed, removing from the map to save memory. + std::set<uint64_t> remove_uids; + auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) { + if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 || + kind == S_INLINESITE) { + GetOrCreateBlock(id); + if (kind == S_INLINESITE) + remove_uids.insert(toOpaqueUid(id)); + return true; + } + return false; + }; + size_t count = ParseSymbolArrayInScope(func_id, parse_blocks); + for (uint64_t uid : remove_uids) { + m_inline_sites.erase(uid); + } + return count; +} + +size_t SymbolFileNativePDB::ParseSymbolArrayInScope( + PdbCompilandSymId parent_id, + llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) { + CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi); + CVSymbolArray syms = + cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset); + + size_t count = 1; + for (auto iter = syms.begin(); iter != syms.end(); ++iter) { + PdbCompilandSymId child_id(parent_id.modi, iter.offset()); + if (fn(iter->kind(), child_id)) + ++count; + } + + return count; } void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } @@ -1396,6 +1730,9 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { } case S_BLOCK32: break; + case S_INLINESITE: + // TODO: Handle inline site case. + return 0; default: lldbassert(false && "Symbol is not a block!"); return 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 56a5ec0a464d..f1b6e34ca346 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -9,6 +9,7 @@ #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H +#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" #include "llvm/ADT/DenseMap.h" @@ -161,6 +162,25 @@ public: void DumpClangAST(Stream &s) override; private: + struct LineTableEntryComparator { + bool operator()(const lldb_private::LineTable::Entry &lhs, + const lldb_private::LineTable::Entry &rhs) const { + return lhs.file_addr < rhs.file_addr; + } + }; + + // From address range relative to function base to source line number. + using RangeSourceLineVector = + lldb_private::RangeDataVector<uint32_t, uint32_t, int32_t>; + // InlineSite contains information in a S_INLINESITE record. + struct InlineSite { + PdbCompilandSymId parent_id; + std::shared_ptr<InlineFunctionInfo> inline_function_info; + RangeSourceLineVector ranges; + std::vector<lldb_private::LineTable::Entry> line_entries; + InlineSite(PdbCompilandSymId parent_id) : parent_id(parent_id){}; + }; + uint32_t CalculateNumCompileUnits() override; lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; @@ -225,6 +245,16 @@ private: VariableList &variables); size_t ParseVariablesForBlock(PdbCompilandSymId block_id); + llvm::Expected<uint32_t> GetFileIndex(const CompilandIndexItem &cii, + uint32_t file_id); + + size_t ParseSymbolArrayInScope( + PdbCompilandSymId parent, + llvm::function_ref<bool(llvm::codeview::SymbolKind, PdbCompilandSymId)> + fn); + + void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr); + llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; @@ -241,6 +271,9 @@ private: llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions; llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands; llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types; + llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites; + // A map from file id in records to file index in support files. + llvm::DenseMap<uint32_t, uint32_t> m_file_indexes; }; } // namespace npdb diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 57e763176ba0..c71a0120efde 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -1345,7 +1345,30 @@ namespace { bool IsValueParam(const clang::TemplateArgument &argument) { return argument.getKind() == TemplateArgument::Integral; } + +void AddAccessSpecifierDecl(clang::CXXRecordDecl *cxx_record_decl, + ASTContext &ct, + clang::AccessSpecifier previous_access, + clang::AccessSpecifier access_specifier) { + if (!cxx_record_decl->isClass() && !cxx_record_decl->isStruct()) + return; + if (previous_access != access_specifier) { + // For struct, don't add AS_public if it's the first AccessSpecDecl. + // For class, don't add AS_private if it's the first AccessSpecDecl. + if ((cxx_record_decl->isStruct() && + previous_access == clang::AccessSpecifier::AS_none && + access_specifier == clang::AccessSpecifier::AS_public) || + (cxx_record_decl->isClass() && + previous_access == clang::AccessSpecifier::AS_none && + access_specifier == clang::AccessSpecifier::AS_private)) { + return; + } + cxx_record_decl->addDecl( + AccessSpecDecl::Create(ct, access_specifier, cxx_record_decl, + SourceLocation(), SourceLocation())); + } } +} // namespace static TemplateParameterList *CreateTemplateParameterList( ASTContext &ast, @@ -1453,7 +1476,7 @@ void TypeSystemClang::CreateFunctionTemplateSpecializationInfo( /// as `int I = 3`. static bool TemplateParameterAllowsValue(NamedDecl *param, const TemplateArgument &value) { - if (auto *type_param = llvm::dyn_cast<TemplateTypeParmDecl>(param)) { + if (llvm::isa<TemplateTypeParmDecl>(param)) { // Compare the argument kind, i.e. ensure that <typename> != <int>. if (value.getKind() != TemplateArgument::Type) return false; @@ -2552,6 +2575,22 @@ ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Type *object) { return nullptr; } +void TypeSystemClang::SetCXXRecordDeclAccess(const clang::CXXRecordDecl *object, + clang::AccessSpecifier access) { + if (access == clang::AccessSpecifier::AS_none) + m_cxx_record_decl_access.erase(object); + else + m_cxx_record_decl_access[object] = access; +} + +clang::AccessSpecifier +TypeSystemClang::GetCXXRecordDeclAccess(const clang::CXXRecordDecl *object) { + auto It = m_cxx_record_decl_access.find(object); + if (It != m_cxx_record_decl_access.end()) + return It->second; + return clang::AccessSpecifier::AS_none; +} + clang::DeclContext * TypeSystemClang::GetDeclContextForType(const CompilerType &type) { return GetDeclContextForType(ClangUtil::GetQualType(type)); @@ -7276,9 +7315,17 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType( } if (field) { - field->setAccess( - TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access)); - + clang::AccessSpecifier access_specifier = + TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access); + field->setAccess(access_specifier); + + if (clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<CXXRecordDecl>(record_decl)) { + AddAccessSpecifierDecl(cxx_record_decl, ast->getASTContext(), + ast->GetCXXRecordDeclAccess(cxx_record_decl), + access_specifier); + ast->SetCXXRecordDeclAccess(cxx_record_decl, access_specifier); + } record_decl->addDecl(field); VerifyDecl(field); @@ -7657,6 +7704,11 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( cxx_method_decl->setParams(llvm::ArrayRef<clang::ParmVarDecl *>(params)); + AddAccessSpecifierDecl(cxx_record_decl, getASTContext(), + GetCXXRecordDeclAccess(cxx_record_decl), + access_specifier); + SetCXXRecordDeclAccess(cxx_record_decl, access_specifier); + cxx_record_decl->addDecl(cxx_method_decl); // Sometimes the debug info will mention a constructor (default/copy/move), @@ -8190,6 +8242,11 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition( if (qual_type.isNull()) return false; + TypeSystemClang *lldb_ast = + llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + if (lldb_ast == nullptr) + return false; + // Make sure we use the same methodology as // TypeSystemClang::StartTagDeclarationDefinition() as to how we start/end // the definition. @@ -8220,6 +8277,8 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition( cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); cxx_record_decl->setHasExternalLexicalStorage(false); cxx_record_decl->setHasExternalVisibleStorage(false); + lldb_ast->SetCXXRecordDeclAccess(cxx_record_decl, + clang::AccessSpecifier::AS_none); return true; } } @@ -8233,10 +8292,6 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition( if (enum_decl->isCompleteDefinition()) return true; - TypeSystemClang *lldb_ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); - if (lldb_ast == nullptr) - return false; clang::ASTContext &ast = lldb_ast->getASTContext(); /// TODO This really needs to be fixed. diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 5e75a8aba9e8..c59ecdb31790 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -196,6 +196,11 @@ public: ClangASTMetadata *GetMetadata(const clang::Decl *object); ClangASTMetadata *GetMetadata(const clang::Type *object); + void SetCXXRecordDeclAccess(const clang::CXXRecordDecl *object, + clang::AccessSpecifier access); + clang::AccessSpecifier + GetCXXRecordDeclAccess(const clang::CXXRecordDecl *object); + // Basic Types CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) override; @@ -1084,6 +1089,12 @@ private: /// Maps Types to their associated ClangASTMetadata. TypeMetadataMap m_type_metadata; + typedef llvm::DenseMap<const clang::CXXRecordDecl *, clang::AccessSpecifier> + CXXRecordDeclAccessMap; + /// Maps CXXRecordDecl to their most recent added method/field's + /// AccessSpecifier. + CXXRecordDeclAccessMap m_cxx_record_decl_access; + /// The sema associated that is currently used to build this ASTContext. /// May be null if we are already done parsing this ASTContext or the /// ASTContext wasn't created by parsing source code. |