diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-12-25 22:30:44 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-12-25 22:30:44 +0000 |
| commit | 77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (patch) | |
| tree | 5c0eb39553003b9c75a901af6bc4ddabd6f2f28c /lldb/source | |
| parent | f65dcba83ce5035ab88a85fe17628b447eb56e1b (diff) | |
Diffstat (limited to 'lldb/source')
105 files changed, 2706 insertions, 719 deletions
diff --git a/lldb/source/API/SBData.cpp b/lldb/source/API/SBData.cpp index daf313ad55c9..9fc590578bce 100644 --- a/lldb/source/API/SBData.cpp +++ b/lldb/source/API/SBData.cpp @@ -374,6 +374,25 @@ void SBData::SetData(lldb::SBError &error, const void *buf, size_t size, } } +void SBData::SetDataWithOwnership(lldb::SBError &error, const void *buf, + size_t size, lldb::ByteOrder endian, + uint8_t addr_size) { + LLDB_RECORD_DUMMY( + void, SBData, SetData, + (lldb::SBError &, const void *, size_t, lldb::ByteOrder, uint8_t, bool), + error, buf, size, endian, addr_size, copy); + + lldb::DataBufferSP buffer_sp = std::make_shared<DataBufferHeap>(buf, size); + + if (!m_opaque_sp.get()) + m_opaque_sp = std::make_shared<DataExtractor>(buf, size, endian, addr_size); + else { + m_opaque_sp->SetData(buffer_sp); + m_opaque_sp->SetByteOrder(endian); + m_opaque_sp->SetAddressByteSize(addr_size); + } +} + bool SBData::Append(const SBData &rhs) { LLDB_RECORD_METHOD(bool, SBData, Append, (const lldb::SBData &), rhs); diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 844b91de4cd0..fa5dcb57de7e 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -11,8 +11,6 @@ #include "lldb/API/SBDebugger.h" -#include "lldb/lldb-private.h" - #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBCommandInterpreterRunOptions.h" @@ -52,6 +50,7 @@ #include "lldb/Target/TargetList.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/State.h" +#include "lldb/Version/Version.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -750,6 +749,9 @@ SBStructuredData SBDebugger::GetBuildConfiguration() { AddBoolConfigEntry( *config_up, "lua", LLDB_ENABLE_LUA, "A boolean value that indicates if lua support is enabled in LLDB"); + AddBoolConfigEntry(*config_up, "fbsdvmcore", LLDB_ENABLE_FBSDVMCORE, + "A boolean value that indicates if fbsdvmcore support is " + "enabled in LLDB"); AddLLVMTargets(*config_up); SBStructuredData data; diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 7107768ba884..c6bc3288c4b2 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -119,15 +119,13 @@ SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const { std::unique_lock<std::recursive_mutex> lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock); SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); - StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) { - frame = exe_ctx.GetFramePtr(); - if (frame) - sb_sym_ctx.SetSymbolContext(&frame->GetSymbolContext(scope)); + if (StackFrame *frame = exe_ctx.GetFramePtr()) + sb_sym_ctx = frame->GetSymbolContext(scope); } } diff --git a/lldb/source/API/SBReproducer.cpp b/lldb/source/API/SBReproducer.cpp index 68e632da1bde..c9c9a03c694a 100644 --- a/lldb/source/API/SBReproducer.cpp +++ b/lldb/source/API/SBReproducer.cpp @@ -23,7 +23,7 @@ #include "lldb/API/SBHostOS.h" #include "lldb/API/SBReproducer.h" #include "lldb/Host/FileSystem.h" -#include "lldb/lldb-private.h" +#include "lldb/Version/Version.h" using namespace lldb; using namespace lldb_private; @@ -165,111 +165,24 @@ const char *SBReproducer::Capture(const char *path) { } const char *SBReproducer::PassiveReplay(const char *path) { - static std::string error; - if (auto e = Reproducer::Initialize(ReproducerMode::PassiveReplay, - FileSpec(path))) { - error = llvm::toString(std::move(e)); - return error.c_str(); - } - - if (auto *l = lldb_private::repro::Reproducer::Instance().GetLoader()) { - FileSpec file = l->GetFile<SBProvider::Info>(); - auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); - if (!error_or_file) { - error = - "unable to read SB API data: " + error_or_file.getError().message(); - return error.c_str(); - } - static ReplayData r(std::move(*error_or_file)); - InstrumentationData::Initialize(r.GetDeserializer(), r.GetRegistry()); - } - - return nullptr; + return "Reproducer replay has been removed"; } const char *SBReproducer::Replay(const char *path) { - SBReplayOptions options; - return SBReproducer::Replay(path, options); + return "Reproducer replay has been removed"; } const char *SBReproducer::Replay(const char *path, bool skip_version_check) { - SBReplayOptions options; - options.SetCheckVersion(!skip_version_check); - return SBReproducer::Replay(path, options); + return Replay(path); } const char *SBReproducer::Replay(const char *path, const SBReplayOptions &options) { - static std::string error; - if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) { - error = llvm::toString(std::move(e)); - return error.c_str(); - } - - repro::Loader *loader = repro::Reproducer::Instance().GetLoader(); - if (!loader) { - error = "unable to get replay loader."; - return error.c_str(); - } - - if (options.GetCheckVersion()) { - llvm::Expected<std::string> version = loader->LoadBuffer<VersionProvider>(); - if (!version) { - error = llvm::toString(version.takeError()); - return error.c_str(); - } - if (lldb_private::GetVersion() != llvm::StringRef(*version).rtrim()) { - error = "reproducer capture and replay version don't match:\n"; - error.append("reproducer captured with:\n"); - error.append(*version); - error.append("reproducer replayed with:\n"); - error.append(lldb_private::GetVersion()); - return error.c_str(); - } - } - - if (options.GetVerify()) { - bool verification_failed = false; - llvm::raw_string_ostream os(error); - auto error_callback = [&](llvm::StringRef error) { - verification_failed = true; - os << "\nerror: " << error; - }; - - auto warning_callback = [&](llvm::StringRef warning) { - verification_failed = true; - os << "\nwarning: " << warning; - }; - - auto note_callback = [&](llvm::StringRef warning) {}; - - Verifier verifier(loader); - verifier.Verify(error_callback, warning_callback, note_callback); - - if (verification_failed) { - os.flush(); - return error.c_str(); - } - } - - FileSpec file = loader->GetFile<SBProvider::Info>(); - if (!file) { - error = "unable to get replay data from reproducer."; - return error.c_str(); - } - - SBRegistry registry; - registry.Replay(file); - - return nullptr; + return Replay(path); } const char *SBReproducer::Finalize(const char *path) { static std::string error; - if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) { - error = llvm::toString(std::move(e)); - return error.c_str(); - } repro::Loader *loader = repro::Reproducer::Instance().GetLoader(); if (!loader) { diff --git a/lldb/source/API/SBStructuredData.cpp b/lldb/source/API/SBStructuredData.cpp index 97a9eadcaf07..e99c6194c516 100644 --- a/lldb/source/API/SBStructuredData.cpp +++ b/lldb/source/API/SBStructuredData.cpp @@ -39,10 +39,10 @@ SBStructuredData::SBStructuredData(const lldb::EventSP &event_sp) LLDB_RECORD_CONSTRUCTOR(SBStructuredData, (const lldb::EventSP &), event_sp); } -SBStructuredData::SBStructuredData(lldb_private::StructuredDataImpl *impl) - : m_impl_up(impl ? impl : new StructuredDataImpl()) { +SBStructuredData::SBStructuredData(const lldb_private::StructuredDataImpl &impl) + : m_impl_up(new StructuredDataImpl(impl)) { LLDB_RECORD_CONSTRUCTOR(SBStructuredData, - (lldb_private::StructuredDataImpl *), impl); + (const lldb_private::StructuredDataImpl &), impl); } SBStructuredData::~SBStructuredData() = default; @@ -210,7 +210,7 @@ template <> void RegisterMethods<SBStructuredData>(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBStructuredData, (const lldb::SBStructuredData &)); LLDB_REGISTER_CONSTRUCTOR(SBStructuredData, (const lldb::EventSP &)); LLDB_REGISTER_CONSTRUCTOR(SBStructuredData, - (lldb_private::StructuredDataImpl *)); + (const lldb_private::StructuredDataImpl &)); LLDB_REGISTER_METHOD( lldb::SBStructuredData &, SBStructuredData, operator=,(const lldb::SBStructuredData &)); diff --git a/lldb/source/API/SBSymbolContext.cpp b/lldb/source/API/SBSymbolContext.cpp index 488d49884903..89fe051658ff 100644 --- a/lldb/source/API/SBSymbolContext.cpp +++ b/lldb/source/API/SBSymbolContext.cpp @@ -22,12 +22,10 @@ SBSymbolContext::SBSymbolContext() : m_opaque_up() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBSymbolContext); } -SBSymbolContext::SBSymbolContext(const SymbolContext *sc_ptr) : m_opaque_up() { +SBSymbolContext::SBSymbolContext(const SymbolContext &sc) + : m_opaque_up(std::make_unique<SymbolContext>(sc)) { LLDB_RECORD_CONSTRUCTOR(SBSymbolContext, - (const lldb_private::SymbolContext *), sc_ptr); - - if (sc_ptr) - m_opaque_up = std::make_unique<SymbolContext>(*sc_ptr); + (const lldb_private::SymbolContext &), sc); } SBSymbolContext::SBSymbolContext(const SBSymbolContext &rhs) : m_opaque_up() { @@ -49,13 +47,6 @@ const SBSymbolContext &SBSymbolContext::operator=(const SBSymbolContext &rhs) { return LLDB_RECORD_RESULT(*this); } -void SBSymbolContext::SetSymbolContext(const SymbolContext *sc_ptr) { - if (sc_ptr) - m_opaque_up = std::make_unique<SymbolContext>(*sc_ptr); - else - m_opaque_up->Clear(true); -} - bool SBSymbolContext::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSymbolContext, IsValid); return this->operator bool(); @@ -237,7 +228,7 @@ template <> void RegisterMethods<SBSymbolContext>(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBSymbolContext, ()); LLDB_REGISTER_CONSTRUCTOR(SBSymbolContext, - (const lldb_private::SymbolContext *)); + (const lldb_private::SymbolContext &)); LLDB_REGISTER_CONSTRUCTOR(SBSymbolContext, (const lldb::SBSymbolContext &)); LLDB_REGISTER_METHOD( const lldb::SBSymbolContext &, diff --git a/lldb/source/API/SBSymbolContextList.cpp b/lldb/source/API/SBSymbolContextList.cpp index 9db84dc1bf4b..70a8bbe6694c 100644 --- a/lldb/source/API/SBSymbolContextList.cpp +++ b/lldb/source/API/SBSymbolContextList.cpp @@ -56,9 +56,8 @@ SBSymbolContext SBSymbolContextList::GetContextAtIndex(uint32_t idx) { SBSymbolContext sb_sc; if (m_opaque_up) { SymbolContext sc; - if (m_opaque_up->GetContextAtIndex(idx, sc)) { - sb_sc.SetSymbolContext(&sc); - } + if (m_opaque_up->GetContextAtIndex(idx, sc)) + sb_sc = sc; } return LLDB_RECORD_RESULT(sb_sc); } diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp index 9af673b0f3a9..99ecb321595f 100644 --- a/lldb/source/API/SBThreadPlan.cpp +++ b/lldb/source/API/SBThreadPlan.cpp @@ -69,8 +69,8 @@ SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name) { Thread *thread = sb_thread.get(); if (thread) - m_opaque_wp = - std::make_shared<ThreadPlanPython>(*thread, class_name, nullptr); + m_opaque_wp = std::make_shared<ThreadPlanPython>(*thread, class_name, + StructuredDataImpl()); } SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name, @@ -82,7 +82,7 @@ SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name, Thread *thread = sb_thread.get(); if (thread) m_opaque_wp = std::make_shared<ThreadPlanPython>(*thread, class_name, - args_data.m_impl_up.get()); + *args_data.m_impl_up); } // Assignment operator diff --git a/lldb/source/API/SBTypeSummary.cpp b/lldb/source/API/SBTypeSummary.cpp index 3800ae940c70..2d7f8ef340c9 100644 --- a/lldb/source/API/SBTypeSummary.cpp +++ b/lldb/source/API/SBTypeSummary.cpp @@ -100,20 +100,11 @@ const lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() const { } SBTypeSummaryOptions::SBTypeSummaryOptions( - const lldb_private::TypeSummaryOptions *lldb_object_ptr) { + const lldb_private::TypeSummaryOptions &lldb_object) + : m_opaque_up(std::make_unique<TypeSummaryOptions>(lldb_object)) { LLDB_RECORD_CONSTRUCTOR(SBTypeSummaryOptions, - (const lldb_private::TypeSummaryOptions *), - lldb_object_ptr); - - SetOptions(lldb_object_ptr); -} - -void SBTypeSummaryOptions::SetOptions( - const lldb_private::TypeSummaryOptions *lldb_object_ptr) { - if (lldb_object_ptr) - m_opaque_up = std::make_unique<TypeSummaryOptions>(*lldb_object_ptr); - else - m_opaque_up = std::make_unique<TypeSummaryOptions>(); + (const lldb_private::TypeSummaryOptions &), + lldb_object); } SBTypeSummary::SBTypeSummary() : m_opaque_sp() { @@ -175,7 +166,7 @@ SBTypeSummary SBTypeSummary::CreateWithCallback(FormatCallback cb, const TypeSummaryOptions &opt) -> bool { SBStream stream; SBValue sb_value(valobj.GetSP()); - SBTypeSummaryOptions options(&opt); + SBTypeSummaryOptions options(opt); if (!cb(sb_value, options, stream)) return false; stm.Write(stream.GetData(), stream.GetSize()); @@ -492,7 +483,7 @@ void RegisterMethods<SBTypeSummaryOptions>(Registry &R) { LLDB_REGISTER_METHOD(void, SBTypeSummaryOptions, SetCapping, (lldb::TypeSummaryCapping)); LLDB_REGISTER_CONSTRUCTOR(SBTypeSummaryOptions, - (const lldb_private::TypeSummaryOptions *)); + (const lldb_private::TypeSummaryOptions &)); } template <> diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp index cc6cb6925bd0..b01cb2ff545b 100644 --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -50,15 +50,8 @@ SystemInitializerFull::~SystemInitializerFull() = default; llvm::Error SystemInitializerFull::Initialize() { llvm::Error error = SystemInitializerCommon::Initialize(); - if (error) { - // During active replay, the ::Initialize call is replayed like any other - // SB API call and the return value is ignored. Since we can't intercept - // this, we terminate here before the uninitialized debugger inevitably - // crashes. - if (repro::Reproducer::Instance().IsReplaying()) - llvm::report_fatal_error(std::move(error)); + if (error) return error; - } // Initialize LLVM and Clang llvm::InitializeAllTargets(); diff --git a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp index 92297fbc7c4b..308c3b987f58 100644 --- a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp @@ -27,10 +27,9 @@ using namespace lldb_private; // BreakpointResolverScripted: BreakpointResolverScripted::BreakpointResolverScripted( const BreakpointSP &bkpt, const llvm::StringRef class_name, - lldb::SearchDepth depth, StructuredDataImpl *args_data) + lldb::SearchDepth depth, const StructuredDataImpl &args_data) : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver), - m_class_name(std::string(class_name)), m_depth(depth), - m_args_ptr(args_data) { + m_class_name(std::string(class_name)), m_depth(depth), m_args(args_data) { CreateImplementationIfNeeded(bkpt); } @@ -52,7 +51,7 @@ void BreakpointResolverScripted::CreateImplementationIfNeeded( return; m_implementation_sp = script_interp->CreateScriptedBreakpointResolver( - m_class_name.c_str(), m_args_ptr, breakpoint_sp); + m_class_name.c_str(), m_args, breakpoint_sp); } void BreakpointResolverScripted::NotifyBreakpointSet() { @@ -75,14 +74,12 @@ BreakpointResolverScripted::CreateFromStructuredData( // The Python function will actually provide the search depth, this is a // placeholder. lldb::SearchDepth depth = lldb::eSearchDepthTarget; - - StructuredDataImpl *args_data_impl = new StructuredDataImpl(); + + StructuredDataImpl args_data_impl; StructuredData::Dictionary *args_dict = nullptr; - success = options_dict.GetValueForKeyAsDictionary( - GetKey(OptionNames::ScriptArgs), args_dict); - if (success) { - args_data_impl->SetObjectSP(args_dict->shared_from_this()); - } + if (options_dict.GetValueForKeyAsDictionary(GetKey(OptionNames::ScriptArgs), + args_dict)) + args_data_impl.SetObjectSP(args_dict->shared_from_this()); return new BreakpointResolverScripted(bkpt, class_name, depth, args_data_impl); } @@ -94,9 +91,9 @@ BreakpointResolverScripted::SerializeToStructuredData() { options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName), m_class_name); - if (m_args_ptr->IsValid()) - options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs), - m_args_ptr->GetObjectSP()); + if (m_args.IsValid()) + options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs), + m_args.GetObjectSP()); return WrapOptionsDict(options_dict_sp); } @@ -151,10 +148,6 @@ void BreakpointResolverScripted::Dump(Stream *s) const {} lldb::BreakpointResolverSP BreakpointResolverScripted::CopyForBreakpoint(BreakpointSP &breakpoint) { - // FIXME: Have to make a copy of the arguments from the m_args_ptr and then - // pass that to the new resolver. - lldb::BreakpointResolverSP ret_sp( - new BreakpointResolverScripted(breakpoint, m_class_name, m_depth, - nullptr)); - return ret_sp; + return std::make_shared<BreakpointResolverScripted>(breakpoint, m_class_name, + m_depth, m_args); } diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 094ce6f8558f..9df42f36fafd 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -716,7 +716,7 @@ protected: if (item_byte_size == read) { result.AppendWarningWithFormat( "unable to find a NULL terminated string at 0x%" PRIx64 - ".Consider increasing the maximum read length.\n", + ". Consider increasing the maximum read length.\n", data_addr); --read; break_on_no_NULL = true; diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp index 01f9dc64e6f0..4db3e070df3c 100644 --- a/lldb/source/Commands/CommandObjectReproducer.cpp +++ b/lldb/source/Commands/CommandObjectReproducer.cpp @@ -195,10 +195,6 @@ protected: SetError(result, std::move(e)); return result.Succeeded(); } - } else if (r.IsReplaying()) { - // Make this operation a NO-OP in replay mode. - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } else { result.AppendErrorWithFormat("Unable to get the reproducer generator"); return false; @@ -276,7 +272,7 @@ protected: auto &r = Reproducer::Instance(); - if (!r.IsCapturing() && !r.IsReplaying()) { + if (!r.IsCapturing()) { result.AppendError( "forcing a crash is only supported when capturing a reproducer."); result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -326,15 +322,10 @@ protected: auto &r = Reproducer::Instance(); if (r.IsCapturing()) { result.GetOutputStream() << "Reproducer is in capture mode.\n"; - } else if (r.IsReplaying()) { - result.GetOutputStream() << "Reproducer is in replay mode.\n"; - } else { - result.GetOutputStream() << "Reproducer is off.\n"; - } - - if (r.IsCapturing() || r.IsReplaying()) { result.GetOutputStream() << "Path: " << r.GetReproducerPath().GetPath() << '\n'; + } else { + result.GetOutputStream() << "Reproducer is off.\n"; } // Auto generate is hidden unless enabled because this is mostly for diff --git a/lldb/source/Commands/CommandObjectVersion.cpp b/lldb/source/Commands/CommandObjectVersion.cpp index 20c2d25b745c..e15faba5661e 100644 --- a/lldb/source/Commands/CommandObjectVersion.cpp +++ b/lldb/source/Commands/CommandObjectVersion.cpp @@ -9,7 +9,7 @@ #include "CommandObjectVersion.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/lldb-private.h" +#include "lldb/Version/Version.h" using namespace lldb; using namespace lldb_private; diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index e48879660403..038ed00905f1 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -13,6 +13,26 @@ let Definition = "modulelist" in { Global, DefaultStringValue<"">, Desc<"Debug info path which should be resolved while parsing, relative to the host filesystem.">; + def EnableLLDBIndexCache: Property<"enable-lldb-index-cache", "Boolean">, + Global, + DefaultFalse, + Desc<"Enable caching for debug sessions in LLDB. LLDB can cache data for each module for improved performance in subsequent debug sessions.">; + def LLDBIndexCachePath: Property<"lldb-index-cache-path", "FileSpec">, + Global, + DefaultStringValue<"">, + Desc<"The path to the LLDB index cache directory.">; + def LLDBIndexCacheMaxByteSize: Property<"lldb-index-cache-max-byte-size", "UInt64">, + Global, + DefaultUnsignedValue<0>, + Desc<"The maximum size for the LLDB index cache directory in bytes. A value over the amount of available space on the disk will be reduced to the amount of available space. A value of 0 disables the absolute size-based pruning.">; + def LLDBIndexCacheMaxPercent: Property<"lldb-index-cache-max-percent", "UInt64">, + Global, + DefaultUnsignedValue<0>, + Desc<"The maximum size for the cache directory in terms of percentage of the available space on the disk. Set to 100 to indicate no limit, 50 to indicate that the cache size will not be left over half the available disk space. A value over 100 will be reduced to 100. A value of 0 disables the percentage size-based pruning.">; + def LLDBIndexCacheExpirationDays: Property<"lldb-index-cache-expiration-days", "UInt64">, + Global, + DefaultUnsignedValue<7>, + Desc<"The expiration time in days for a file. When a file hasn't been accessed for the specified amount of days, it is removed from the cache. A value of 0 disables the expiration-based pruning.">; } let Definition = "debugger" in { diff --git a/lldb/source/Core/DataFileCache.cpp b/lldb/source/Core/DataFileCache.cpp new file mode 100644 index 000000000000..3f52b925ef46 --- /dev/null +++ b/lldb/source/Core/DataFileCache.cpp @@ -0,0 +1,307 @@ +//===-- DataFileCache.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 "lldb/Core/DataFileCache.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" +#include "llvm/Support/CachePruning.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace lldb_private; + +DataFileCache::DataFileCache(StringRef path) { + m_cache_dir.SetPath(path); + + // Prune the cache based off of the LLDB settings each time we create a cache + // object. + ModuleListProperties &properties = + ModuleList::GetGlobalModuleListProperties(); + CachePruningPolicy policy; + // Only scan once an hour. If we have lots of debug sessions we don't want + // to scan this directory too often. A timestamp file is written to the + // directory to ensure different processes don't scan the directory too often. + // This setting doesn't mean that a thread will continually scan the cache + // directory within this process. + policy.Interval = std::chrono::hours(1); + // Get the user settings for pruning. + policy.MaxSizeBytes = properties.GetLLDBIndexCacheMaxByteSize(); + policy.MaxSizePercentageOfAvailableSpace = + properties.GetLLDBIndexCacheMaxPercent(); + policy.Expiration = + std::chrono::hours(properties.GetLLDBIndexCacheExpirationDays() * 24); + pruneCache(path, policy); + + // This lambda will get called when the data is gotten from the cache and + // also after the data was set for a given key. We only need to take + // ownership of the data if we are geting the data, so we use the + // m_take_ownership member variable to indicate if we need to take + // ownership. + + auto add_buffer = [this](unsigned task, std::unique_ptr<llvm::MemoryBuffer> m) { + if (m_take_ownership) + m_mem_buff_up = std::move(m); + }; + Expected<FileCache> cache_or_err = + llvm::localCache("LLDBModuleCache", "lldb-module", path, add_buffer); + if (cache_or_err) + m_cache_callback = std::move(*cache_or_err); + else { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES)); + LLDB_LOG_ERROR(log, cache_or_err.takeError(), + "failed to create lldb index cache directory: {0}"); + } +} + +std::unique_ptr<llvm::MemoryBuffer> +DataFileCache::GetCachedData(StringRef key) { + std::lock_guard<std::mutex> guard(m_mutex); + + const unsigned task = 1; + m_take_ownership = true; + // If we call the "m_cache_callback" function and the data is cached, it will + // call the "add_buffer" lambda function from the constructor which will in + // turn take ownership of the member buffer that is passed to the callback and + // put it into a member variable. + Expected<AddStreamFn> add_stream_or_err = m_cache_callback(task, key); + m_take_ownership = false; + // At this point we either already called the "add_buffer" lambda with + // the data or we haven't. We can tell if we got the cached data by checking + // the add_stream function pointer value below. + if (add_stream_or_err) { + AddStreamFn &add_stream = *add_stream_or_err; + // If the "add_stream" is nullptr, then the data was cached and we already + // called the "add_buffer" lambda. If it is valid, then if we were to call + // the add_stream function it would cause a cache file to get generated + // and we would be expected to fill in the data. In this function we only + // want to check if the data was cached, so we don't want to call + // "add_stream" in this function. + if (!add_stream) + return std::move(m_mem_buff_up); + } else { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES)); + LLDB_LOG_ERROR(log, add_stream_or_err.takeError(), + "failed to get the cache add stream callback for key: {0}"); + } + // Data was not cached. + return std::unique_ptr<llvm::MemoryBuffer>(); +} + +bool DataFileCache::SetCachedData(StringRef key, llvm::ArrayRef<uint8_t> data) { + std::lock_guard<std::mutex> guard(m_mutex); + const unsigned task = 2; + // If we call this function and the data is cached, it will call the + // add_buffer lambda function from the constructor which will ignore the + // data. + Expected<AddStreamFn> add_stream_or_err = m_cache_callback(task, key); + // If we reach this code then we either already called the callback with + // the data or we haven't. We can tell if we had the cached data by checking + // the CacheAddStream function pointer value below. + if (add_stream_or_err) { + AddStreamFn &add_stream = *add_stream_or_err; + // If the "add_stream" is nullptr, then the data was cached. If it is + // valid, then if we call the add_stream function with a task it will + // cause the file to get generated, but we only want to check if the data + // is cached here, so we don't want to call it here. Note that the + // add_buffer will also get called in this case after the data has been + // provided, but we won't take ownership of the memory buffer as we just + // want to write the data. + if (add_stream) { + Expected<std::unique_ptr<CachedFileStream>> file_or_err = + add_stream(task); + if (file_or_err) { + CachedFileStream *cfs = file_or_err->get(); + cfs->OS->write((const char *)data.data(), data.size()); + return true; + } else { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES)); + LLDB_LOG_ERROR(log, file_or_err.takeError(), + "failed to get the cache file stream for key: {0}"); + } + } + } else { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES)); + LLDB_LOG_ERROR(log, add_stream_or_err.takeError(), + "failed to get the cache add stream callback for key: {0}"); + } + return false; +} + +FileSpec DataFileCache::GetCacheFilePath(llvm::StringRef key) { + FileSpec cache_file(m_cache_dir); + std::string filename("llvmcache-"); + filename += key.str(); + cache_file.AppendPathComponent(filename); + return cache_file; +} + +Status DataFileCache::RemoveCacheFile(llvm::StringRef key) { + FileSpec cache_file = GetCacheFilePath(key); + FileSystem &fs = FileSystem::Instance(); + if (!fs.Exists(cache_file)) + return Status(); + return fs.RemoveFile(cache_file); +} + +CacheSignature::CacheSignature(lldb_private::Module *module) { + Clear(); + UUID uuid = module->GetUUID(); + if (uuid.IsValid()) + m_uuid = uuid; + + std::time_t mod_time = 0; + mod_time = llvm::sys::toTimeT(module->GetModificationTime()); + if (mod_time != 0) + m_mod_time = mod_time; + + mod_time = llvm::sys::toTimeT(module->GetObjectModificationTime()); + if (mod_time != 0) + m_obj_mod_time = mod_time; +} + +CacheSignature::CacheSignature(lldb_private::ObjectFile *objfile) { + Clear(); + UUID uuid = objfile->GetUUID(); + if (uuid.IsValid()) + m_uuid = uuid; + + std::time_t mod_time = 0; + // Grab the modification time of the object file's file. It isn't always the + // same as the module's file when you have a executable file as the main + // executable, and you have a object file for a symbol file. + FileSystem &fs = FileSystem::Instance(); + mod_time = llvm::sys::toTimeT(fs.GetModificationTime(objfile->GetFileSpec())); + if (mod_time != 0) + m_mod_time = mod_time; + + mod_time = + llvm::sys::toTimeT(objfile->GetModule()->GetObjectModificationTime()); + if (mod_time != 0) + m_obj_mod_time = mod_time; +} + +enum SignatureEncoding { + eSignatureUUID = 1u, + eSignatureModTime = 2u, + eSignatureObjectModTime = 3u, + eSignatureEnd = 255u, +}; + +bool CacheSignature::Encode(DataEncoder &encoder) { + if (!IsValid()) + return false; // Invalid signature, return false! + + if (m_uuid.hasValue()) { + llvm::ArrayRef<uint8_t> uuid_bytes = m_uuid->GetBytes(); + encoder.AppendU8(eSignatureUUID); + encoder.AppendU8(uuid_bytes.size()); + encoder.AppendData(uuid_bytes); + } + if (m_mod_time.hasValue()) { + encoder.AppendU8(eSignatureModTime); + encoder.AppendU32(*m_mod_time); + } + if (m_obj_mod_time.hasValue()) { + encoder.AppendU8(eSignatureObjectModTime); + encoder.AppendU32(*m_obj_mod_time); + } + encoder.AppendU8(eSignatureEnd); + return true; +} + +bool CacheSignature::Decode(const DataExtractor &data, + lldb::offset_t *offset_ptr) { + Clear(); + while (uint8_t sig_encoding = data.GetU8(offset_ptr)) { + switch (sig_encoding) { + case eSignatureUUID: { + const uint8_t length = data.GetU8(offset_ptr); + const uint8_t *bytes = (const uint8_t *)data.GetData(offset_ptr, length); + if (bytes != nullptr && length > 0) + m_uuid = UUID::fromData(llvm::ArrayRef<uint8_t>(bytes, length)); + } break; + case eSignatureModTime: { + uint32_t mod_time = data.GetU32(offset_ptr); + if (mod_time > 0) + m_mod_time = mod_time; + } break; + case eSignatureObjectModTime: { + uint32_t mod_time = data.GetU32(offset_ptr); + if (mod_time > 0) + m_mod_time = mod_time; + } break; + case eSignatureEnd: + return true; + default: + break; + } + } + return false; +} + +uint32_t ConstStringTable::Add(ConstString s) { + auto pos = m_string_to_offset.find(s); + if (pos != m_string_to_offset.end()) + return pos->second; + const uint32_t offset = m_next_offset; + m_strings.push_back(s); + m_string_to_offset[s] = offset; + m_next_offset += s.GetLength() + 1; + return offset; +} + +static const llvm::StringRef kStringTableIdentifier("STAB"); + +bool ConstStringTable::Encode(DataEncoder &encoder) { + // Write an 4 character code into the stream. This will help us when decoding + // to make sure we find this identifier when decoding the string table to make + // sure we have the rigth data. It also helps to identify the string table + // when dumping the hex bytes in a cache file. + encoder.AppendData(kStringTableIdentifier); + size_t length_offset = encoder.GetByteSize(); + encoder.AppendU32(0); // Total length of all strings which will be fixed up. + size_t strtab_offset = encoder.GetByteSize(); + encoder.AppendU8(0); // Start the string table with with an empty string. + for (auto s: m_strings) { + // Make sure all of the offsets match up with what we handed out! + assert(m_string_to_offset.find(s)->second == + encoder.GetByteSize() - strtab_offset); + // Append the C string into the encoder + encoder.AppendCString(s.GetStringRef()); + } + // Fixup the string table length. + encoder.PutU32(length_offset, encoder.GetByteSize() - strtab_offset); + return true; +} + +bool StringTableReader::Decode(const DataExtractor &data, + lldb::offset_t *offset_ptr) { + llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4); + if (identifier != kStringTableIdentifier) + return false; + const uint32_t length = data.GetU32(offset_ptr); + // We always have at least one byte for the empty string at offset zero. + if (length == 0) + return false; + const char *bytes = (const char *)data.GetData(offset_ptr, length); + if (bytes == nullptr) + return false; + m_data = StringRef(bytes, length); + return true; +} + +StringRef StringTableReader::Get(uint32_t offset) const { + if (offset >= m_data.size()) + return StringRef(); + return StringRef(m_data.data() + offset); +} diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index 9122117ef5ff..60207f75b7df 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -1034,7 +1034,7 @@ public: // navigates to the next or the previous field. This is particularly useful to // do in-field validation and error setting. Fields with internal navigation // should call this method on their fields. - virtual void FieldDelegateExitCallback() { return; } + virtual void FieldDelegateExitCallback() {} // Fields may have internal navigation, for instance, a List Field have // multiple internal elements, which needs to be navigated. To allow for this @@ -1055,10 +1055,10 @@ public: virtual bool FieldDelegateOnLastOrOnlyElement() { return true; } // Select the first element in the field if multiple elements exists. - virtual void FieldDelegateSelectFirstElement() { return; } + virtual void FieldDelegateSelectFirstElement() {} // Select the last element in the field if multiple elements exists. - virtual void FieldDelegateSelectLastElement() { return; } + virtual void FieldDelegateSelectLastElement() {} // Returns true if the field has an error, false otherwise. virtual bool FieldDelegateHasError() { return false; } @@ -2000,7 +2000,6 @@ public: void FieldDelegateSelectLastElement() override { m_selection_type = SelectionType::NewButton; - return; } int GetNumberOfFields() { return m_fields.size(); } @@ -2292,7 +2291,7 @@ public: virtual std::string GetName() = 0; - virtual void UpdateFieldsVisibility() { return; } + virtual void UpdateFieldsVisibility() {} FieldDelegate *GetField(uint32_t field_index) { if (field_index < m_fields.size()) @@ -3765,13 +3764,11 @@ public: void SelectNext() { if (m_selected_match != m_delegate_sp->GetNumberOfMatches() - 1) m_selected_match++; - return; } void SelectPrevious() { if (m_selected_match != 0) m_selected_match--; - return; } void ExecuteCallback(Window &window) { @@ -4608,9 +4605,7 @@ public: virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0; virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0; virtual void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index, - TreeItem *&selected_item) { - return; - } + TreeItem *&selected_item) {} // This is invoked when a tree item is selected. If true is returned, the // views are updated. virtual bool TreeDelegateItemSelected(TreeItem &item) = 0; diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 20f4dbdb419f..c8aacdefefa2 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -8,9 +8,11 @@ #include "lldb/Core/Mangled.h" +#include "lldb/Core/DataFileCache.h" #include "lldb/Core/RichManglingContext.h" #include "lldb/Target/Language.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/DataEncoder.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Logging.h" #include "lldb/Utility/RegularExpression.h" @@ -411,3 +413,111 @@ Stream &operator<<(Stream &s, const Mangled &obj) { s << ", demangled = <error>"; return s; } + +// When encoding Mangled objects we can get away with encoding as little +// information as is required. The enumeration below helps us to efficiently +// encode Mangled objects. +enum MangledEncoding { + /// If the Mangled object has neither a mangled name or demangled name we can + /// encode the object with one zero byte using the Empty enumeration. + Empty = 0u, + /// If the Mangled object has only a demangled name and no mangled named, we + /// can encode only the demangled name. + DemangledOnly = 1u, + /// If the mangle name can calculate the demangled name (it is the + /// mangled/demangled counterpart), then we only need to encode the mangled + /// name as the demangled name can be recomputed. + MangledOnly = 2u, + /// If we have a Mangled object with two different names that are not related + /// then we need to save both strings. This can happen if we have a name that + /// isn't a true mangled name, but we want to be able to lookup a symbol by + /// name and type in the symbol table. We do this for Objective C symbols like + /// "OBJC_CLASS_$_NSValue" where the mangled named will be set to + /// "OBJC_CLASS_$_NSValue" and the demangled name will be manually set to + /// "NSValue". If we tried to demangled the name "OBJC_CLASS_$_NSValue" it + /// would fail, but in these cases we want these unrelated names to be + /// preserved. + MangledAndDemangled = 3u +}; + +bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + const StringTableReader &strtab) { + m_mangled.Clear(); + m_demangled.Clear(); + MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr); + switch (encoding) { + case Empty: + return true; + + case DemangledOnly: + m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + return true; + + case MangledOnly: + m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + return true; + + case MangledAndDemangled: + m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + return true; + } + return false; +} +/// The encoding format for the Mangled object is as follows: +/// +/// uint8_t encoding; +/// char str1[]; (only if DemangledOnly, MangledOnly) +/// char str2[]; (only if MangledAndDemangled) +/// +/// The strings are stored as NULL terminated UTF8 strings and str1 and str2 +/// are only saved if we need them based on the encoding. +/// +/// Some mangled names have a mangled name that can be demangled by the built +/// in demanglers. These kinds of mangled objects know when the mangled and +/// demangled names are the counterparts for each other. This is done because +/// demangling is very expensive and avoiding demangling the same name twice +/// saves us a lot of compute time. For these kinds of names we only need to +/// save the mangled name and have the encoding set to "MangledOnly". +/// +/// If a mangled obejct has only a demangled name, then we save only that string +/// and have the encoding set to "DemangledOnly". +/// +/// Some mangled objects have both mangled and demangled names, but the +/// demangled name can not be computed from the mangled name. This is often used +/// for runtime named, like Objective C runtime V2 and V3 names. Both these +/// names must be saved and the encoding is set to "MangledAndDemangled". +/// +/// For a Mangled object with no names, we only need to set the encoding to +/// "Empty" and not store any string values. +void Mangled::Encode(DataEncoder &file, ConstStringTable &strtab) const { + MangledEncoding encoding = Empty; + if (m_mangled) { + encoding = MangledOnly; + if (m_demangled) { + // We have both mangled and demangled names. If the demangled name is the + // counterpart of the mangled name, then we only need to save the mangled + // named. If they are different, we need to save both. + ConstString s; + if (!(m_mangled.GetMangledCounterpart(s) && s == m_demangled)) + encoding = MangledAndDemangled; + } + } else if (m_demangled) { + encoding = DemangledOnly; + } + file.AppendU8(encoding); + switch (encoding) { + case Empty: + break; + case DemangledOnly: + file.AppendU32(strtab.Add(m_demangled)); + break; + case MangledOnly: + file.AppendU32(strtab.Add(m_mangled)); + break; + case MangledAndDemangled: + file.AppendU32(strtab.Add(m_mangled)); + file.AppendU32(strtab.Add(m_demangled)); + break; + } +} diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index cbecbb9aa5fe..feecf984f7bf 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -10,6 +10,7 @@ #include "lldb/Core/AddressRange.h" #include "lldb/Core/AddressResolverFileLine.h" +#include "lldb/Core/DataFileCache.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Mangled.h" @@ -55,7 +56,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/DJB.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" @@ -233,8 +237,8 @@ Module::Module(const ModuleSpec &module_spec) Module::Module(const FileSpec &file_spec, const ArchSpec &arch, const ConstString *object_name, lldb::offset_t object_offset, const llvm::sys::TimePoint<> &object_mod_time) - : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), m_arch(arch), - m_file(file_spec), m_object_offset(object_offset), + : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), + m_arch(arch), m_file(file_spec), m_object_offset(object_offset), m_object_mod_time(object_mod_time), m_file_has_changed(false), m_first_file_changed_log(false) { // Scope for locker below... @@ -559,9 +563,8 @@ uint32_t Module::ResolveSymbolContextForAddress( // that the symbol has been resolved. if (so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() || - so_addr.GetOffset() == - addr_range.GetBaseAddress().GetOffset() + - addr_range.GetByteSize()) { + so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() + + addr_range.GetByteSize()) { resolved_flags |= flags; } } else { @@ -765,8 +768,7 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list, // pull anything out ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled)); ConstString full_name(sc.GetFunctionName()); - if (mangled_name != m_name && full_name != m_name) - { + if (mangled_name != m_name && full_name != m_name) { CPlusPlusLanguage::MethodName cpp_method(full_name); if (cpp_method.IsValid()) { if (cpp_method.GetContext().empty()) { @@ -940,7 +942,6 @@ void Module::FindTypes_Impl( size_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - LLDB_SCOPED_TIMER(); if (SymbolFile *symbols = GetSymbolFile()) symbols->FindTypes(name, parent_decl_ctx, max_matches, searched_symbol_files, types); @@ -960,8 +961,8 @@ void Module::FindTypesInNamespace(ConstString type_name, } } -lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, - ConstString name, bool exact_match) { +lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, ConstString name, + bool exact_match) { TypeList type_list; llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; FindTypes(name, exact_match, 1, searched_symbol_files, type_list); @@ -1332,9 +1333,8 @@ void Module::SymbolIndicesToSymbolContextList( } } -void Module::FindFunctionSymbols(ConstString name, - uint32_t name_type_mask, - SymbolContextList &sc_list) { +void Module::FindFunctionSymbols(ConstString name, uint32_t name_type_mask, + SymbolContextList &sc_list) { LLDB_SCOPED_TIMERF("Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)", name.AsCString(), name_type_mask); if (Symtab *symtab = GetSymtab()) @@ -1342,13 +1342,10 @@ void Module::FindFunctionSymbols(ConstString name, } void Module::FindSymbolsWithNameAndType(ConstString name, - SymbolType symbol_type, - SymbolContextList &sc_list) { + SymbolType symbol_type, + SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are // already thread safe. - LLDB_SCOPED_TIMERF( - "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", - name.AsCString(), symbol_type); if (Symtab *symtab = GetSymtab()) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsWithNameAndType(name, symbol_type, symbol_indexes); @@ -1608,14 +1605,16 @@ bool Module::FindSourceFile(const FileSpec &orig_spec, return false; } -llvm::Optional<std::string> Module::RemapSourceFile(llvm::StringRef path) const { +llvm::Optional<std::string> +Module::RemapSourceFile(llvm::StringRef path) const { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (auto remapped = m_source_mappings.RemapPath(path)) return remapped->GetPath(); return {}; } -void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) { +void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, + llvm::StringRef sysroot) { XcodeSDK sdk(sdk_name.str()); llvm::StringRef sdk_path(HostInfo::GetXcodeSDKPath(sdk)); if (sdk_path.empty()) @@ -1661,3 +1660,36 @@ bool Module::GetIsDynamicLinkEditor() { return false; } + +uint32_t Module::Hash() { + std::string identifier; + llvm::raw_string_ostream id_strm(identifier); + id_strm << m_arch.GetTriple().str() << '-' << m_file.GetPath(); + if (m_object_name) + id_strm << '(' << m_object_name.GetStringRef() << ')'; + if (m_object_offset > 0) + id_strm << m_object_offset; + const auto mtime = llvm::sys::toTimeT(m_object_mod_time); + if (mtime > 0) + id_strm << mtime; + return llvm::djbHash(id_strm.str()); +} + +std::string Module::GetCacheKey() { + std::string key; + llvm::raw_string_ostream strm(key); + strm << m_arch.GetTriple().str() << '-' << m_file.GetFilename(); + if (m_object_name) + strm << '(' << m_object_name.GetStringRef() << ')'; + strm << '-' << llvm::format_hex(Hash(), 10); + return strm.str(); +} + +DataFileCache *Module::GetIndexCache() { + if (!ModuleList::GetGlobalModuleListProperties().GetEnableLLDBIndexCache()) + return nullptr; + // NOTE: intentional leak so we don't crash if global destructor chain gets + // called as other threads still use the result of this function + static DataFileCache *g_data_file_cache = new DataFileCache(ModuleList::GetGlobalModuleListProperties().GetLLDBIndexCachePath().GetPath()); + return g_data_file_cache; +} diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 9176c9dbb357..48412137546d 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -85,6 +85,14 @@ ModuleListProperties::ModuleListProperties() { if (clang::driver::Driver::getDefaultModuleCachePath(path)) { lldbassert(SetClangModulesCachePath(FileSpec(path))); } + + path.clear(); + if (llvm::sys::path::cache_directory(path)) { + llvm::sys::path::append(path, "lldb"); + llvm::sys::path::append(path, "IndexCache"); + lldbassert(SetLLDBIndexCachePath(FileSpec(path))); + } + } bool ModuleListProperties::GetEnableExternalLookup() const { @@ -110,6 +118,47 @@ bool ModuleListProperties::SetClangModulesCachePath(const FileSpec &path) { nullptr, ePropertyClangModulesCachePath, path); } +FileSpec ModuleListProperties::GetLLDBIndexCachePath() const { + return m_collection_sp + ->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false, + ePropertyLLDBIndexCachePath) + ->GetCurrentValue(); +} + +bool ModuleListProperties::SetLLDBIndexCachePath(const FileSpec &path) { + return m_collection_sp->SetPropertyAtIndexAsFileSpec( + nullptr, ePropertyLLDBIndexCachePath, path); +} + +bool ModuleListProperties::GetEnableLLDBIndexCache() const { + const uint32_t idx = ePropertyEnableLLDBIndexCache; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_modulelist_properties[idx].default_uint_value != 0); +} + +bool ModuleListProperties::SetEnableLLDBIndexCache(bool new_value) { + return m_collection_sp->SetPropertyAtIndexAsBoolean( + nullptr, ePropertyEnableLLDBIndexCache, new_value); +} + +uint64_t ModuleListProperties::GetLLDBIndexCacheMaxByteSize() { + const uint32_t idx = ePropertyLLDBIndexCacheMaxByteSize; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_modulelist_properties[idx].default_uint_value); +} + +uint64_t ModuleListProperties::GetLLDBIndexCacheMaxPercent() { + const uint32_t idx = ePropertyLLDBIndexCacheMaxPercent; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_modulelist_properties[idx].default_uint_value); +} + +uint64_t ModuleListProperties::GetLLDBIndexCacheExpirationDays() { + const uint32_t idx = ePropertyLLDBIndexCacheExpirationDays; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_modulelist_properties[idx].default_uint_value); +} + void ModuleListProperties::UpdateSymlinkMappings() { FileSpecList list = m_collection_sp ->GetPropertyAtIndexAsOptionValueFileSpecList( diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index 801591129244..37050494aa2e 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -1345,6 +1345,12 @@ REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) { return GetREPLInstances().GetCallbackAtIndex(idx); } +LanguageSet PluginManager::GetREPLSupportedLanguagesAtIndex(uint32_t idx) { + const auto &instances = GetREPLInstances().GetInstances(); + return idx < instances.size() ? instances[idx].supported_languages + : LanguageSet(); +} + LanguageSet PluginManager::GetREPLAllTypeSystemSupportedLanguages() { const auto &instances = GetREPLInstances().GetInstances(); LanguageSet all; diff --git a/lldb/source/DataFormatters/CXXFunctionPointer.cpp b/lldb/source/DataFormatters/CXXFunctionPointer.cpp index 3b7b0bc27cf8..d7df280e56ef 100644 --- a/lldb/source/DataFormatters/CXXFunctionPointer.cpp +++ b/lldb/source/DataFormatters/CXXFunctionPointer.cpp @@ -9,6 +9,7 @@ #include "lldb/DataFormatters/CXXFunctionPointer.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Stream.h" @@ -38,8 +39,34 @@ bool lldb_private::formatters::CXXFunctionPointerSummaryProvider( Address so_addr; Target *target = exe_ctx.GetTargetPtr(); if (target && !target->GetSectionLoadList().IsEmpty()) { - if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, - so_addr)) { + target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, + so_addr); + if (so_addr.GetSection() == nullptr) { + // If we have an address that doesn't correspond to any symbol, + // it might have authentication bits. Strip them & see if it + // now points to a symbol -- if so, do the SymbolContext lookup + // based on the stripped address. + // If we find a symbol with the ptrauth bits stripped, print the + // raw value into the stream, and replace the Address with the + // one that points to a symbol for a fuller description. + if (Process *process = exe_ctx.GetProcessPtr()) { + if (ABISP abi_sp = process->GetABI()) { + addr_t fixed_addr = abi_sp->FixCodeAddress(func_ptr_address); + if (fixed_addr != func_ptr_address) { + Address test_address; + test_address.SetLoadAddress(fixed_addr, target); + if (test_address.GetSection() != nullptr) { + int addrsize = target->GetArchitecture().GetAddressByteSize(); + sstr.Printf("actual=0x%*.*" PRIx64 " ", addrsize * 2, + addrsize * 2, fixed_addr); + so_addr = test_address; + } + } + } + } + } + + if (so_addr.IsValid()) { so_addr.Dump(&sstr, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset); diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp index cda1ae60d857..0ef5f0adc832 100644 --- a/lldb/source/DataFormatters/FormatManager.cpp +++ b/lldb/source/DataFormatters/FormatManager.cpp @@ -724,15 +724,14 @@ void FormatManager::LoadSystemFormatters() { lldb::TypeSummaryImplSP string_array_format( new StringSummaryFormat(string_array_flags, "${var%char[]}")); - RegularExpression any_size_char_arr(llvm::StringRef("char ?\\[[0-9]+\\]")); + RegularExpression any_size_char_arr(R"(^((un)?signed )?char ?\[[0-9]+\]$)"); TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name); - sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("char *"), - string_format); - sys_category_sp->GetTypeSummariesContainer()->Add( - ConstString("unsigned char *"), string_format); + sys_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression(R"(^((un)?signed )?char ?(\*|\[\])$)"), string_format); + sys_category_sp->GetRegexTypeSummariesContainer()->Add( std::move(any_size_char_arr), string_array_format); diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index a10546c1deae..890d8b5d3107 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -460,22 +460,19 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { // first, then modify it, and if all goes well, we then replace the data // for this expression - // So first we copy the data into a heap buffer - std::unique_ptr<DataBufferHeap> head_data_up( - new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); - - // Make en encoder so we can write the address into the buffer using the - // correct byte order (endianness) - DataEncoder encoder(head_data_up->GetBytes(), head_data_up->GetByteSize(), + // Make en encoder that contains a copy of the location expression data + // so we can write the address into the buffer using the correct byte + // order. + DataEncoder encoder(m_data.GetDataStart(), m_data.GetByteSize(), m_data.GetByteOrder(), addr_byte_size); // Replace the address in the new buffer - if (encoder.PutUnsigned(offset, addr_byte_size, file_addr) == UINT32_MAX) + if (encoder.PutAddress(offset, file_addr) == UINT32_MAX) return false; // All went well, so now we can reset the data using a shared pointer to // the heap data so "m_data" will now correctly manage the heap data. - m_data.SetData(DataBufferSP(head_data_up.release())); + m_data.SetData(encoder.GetDataBuffer()); return true; } else { const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); @@ -521,15 +518,11 @@ bool DWARFExpression::LinkThreadLocalStorage( // We have to make a copy of the data as we don't know if this data is from a // read only memory mapped buffer, so we duplicate all of the data first, // then modify it, and if all goes well, we then replace the data for this - // expression - - // So first we copy the data into a heap buffer - std::shared_ptr<DataBufferHeap> heap_data_sp( - new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); + // expression. - // Make en encoder so we can write the address into the buffer using the - // correct byte order (endianness) - DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), + // Make en encoder that contains a copy of the location expression data so we + // can write the address into the buffer using the correct byte order. + DataEncoder encoder(m_data.GetDataStart(), m_data.GetByteSize(), m_data.GetByteOrder(), addr_byte_size); lldb::offset_t offset = 0; @@ -603,7 +596,7 @@ bool DWARFExpression::LinkThreadLocalStorage( // and read the // TLS data m_module_wp = new_module_sp; - m_data.SetData(heap_data_sp); + m_data.SetData(encoder.GetDataBuffer()); return true; } @@ -2817,4 +2810,3 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame, return MatchRegOp(*reg)(operand); } } - diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index f2d22f7ed9cc..3c4a87c27e20 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -483,8 +483,6 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, func_addr = m_function_load_addr; func_end = m_function_end_load_addr; - - return; } IRExecutionUnit::~IRExecutionUnit() { diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 4ae2724d4dd8..9eee5cf5b9a2 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -609,7 +609,6 @@ void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address, error.SetErrorToGenericError(); error.SetErrorString("Couldn't write scalar: its size was zero"); } - return; } void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, @@ -757,7 +756,6 @@ void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar, error.SetErrorToGenericError(); error.SetErrorString("Couldn't read scalar: its size was zero"); } - return; } void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address, @@ -773,8 +771,6 @@ void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address, return; *address = pointer_scalar.ULongLong(); - - return; } void IRMemoryMap::GetMemoryData(DataExtractor &extractor, diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp index 9cd6129eedd7..be41c60ebb5f 100644 --- a/lldb/source/Expression/REPL.cpp +++ b/lldb/source/Expression/REPL.cpp @@ -39,7 +39,11 @@ lldb::REPLSP REPL::Create(Status &err, lldb::LanguageType language, lldb::REPLSP ret; while (REPLCreateInstance create_instance = - PluginManager::GetREPLCreateCallbackAtIndex(idx++)) { + PluginManager::GetREPLCreateCallbackAtIndex(idx)) { + LanguageSet supported_languages = + PluginManager::GetREPLSupportedLanguagesAtIndex(idx++); + if (!supported_languages[language]) + continue; ret = (*create_instance)(err, language, debugger, target, repl_options); if (ret) { break; diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index b61781c0b82b..692594b03f16 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -254,9 +254,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, if (fixed_expression == nullptr) fixed_expression = &tmp_fixed_expression; - const char *fixed_text = user_expression_sp->GetFixedText(); - if (fixed_text != nullptr) - fixed_expression->append(fixed_text); + *fixed_expression = user_expression_sp->GetFixedText().str(); // If there is a fixed expression, try to parse it: if (!parse_success) { @@ -265,8 +263,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, user_expression_sp.reset(); execution_results = lldb::eExpressionParseError; - if (fixed_expression && !fixed_expression->empty() && - options.GetAutoApplyFixIts()) { + if (!fixed_expression->empty() && options.GetAutoApplyFixIts()) { const uint64_t max_fix_retries = options.GetRetriesWithFixIts(); for (uint64_t i = 0; i < max_fix_retries; ++i) { // Try parsing the fixed expression. @@ -285,8 +282,8 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, } else { // The fixed expression also didn't parse. Let's check for any new // Fix-Its we could try. - if (fixed_expression_sp->GetFixedText()) { - *fixed_expression = fixed_expression_sp->GetFixedText(); + if (!fixed_expression_sp->GetFixedText().empty()) { + *fixed_expression = fixed_expression_sp->GetFixedText().str(); } else { // Fixed expression didn't compile without a fixit, don't retry and // don't tell the user about it. diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp index 7687ad6c20a6..1e4a24abe301 100644 --- a/lldb/source/Host/common/FileSystem.cpp +++ b/lldb/source/Host/common/FileSystem.cpp @@ -513,3 +513,11 @@ void FileSystem::Collect(const llvm::Twine &file) { void FileSystem::SetHomeDirectory(std::string home_directory) { m_home_directory = std::move(home_directory); } + +Status FileSystem::RemoveFile(const FileSpec &file_spec) { + return RemoveFile(file_spec.GetPath()); +} + +Status FileSystem::RemoveFile(const llvm::Twine &path) { + return Status(llvm::sys::fs::remove(path)); +} diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp index 8d281b80e8f0..07e4f15c9e9e 100644 --- a/lldb/source/Host/common/ProcessLaunchInfo.cpp +++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp @@ -212,6 +212,14 @@ void ProcessLaunchInfo::SetDetachOnError(bool enable) { llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS); + + bool stdin_free = GetFileActionForFD(STDIN_FILENO) == nullptr; + bool stdout_free = GetFileActionForFD(STDOUT_FILENO) == nullptr; + bool stderr_free = GetFileActionForFD(STDERR_FILENO) == nullptr; + bool any_free = stdin_free || stdout_free || stderr_free; + if (!any_free) + return llvm::Error::success(); + LLDB_LOG(log, "Generating a pty to use for stdin/out/err"); int open_flags = O_RDWR | O_NOCTTY; @@ -226,19 +234,13 @@ llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() { const FileSpec secondary_file_spec(m_pty->GetSecondaryName()); - // Only use the secondary tty if we don't have anything specified for - // input and don't have an action for stdin - if (GetFileActionForFD(STDIN_FILENO) == nullptr) + if (stdin_free) AppendOpenFileAction(STDIN_FILENO, secondary_file_spec, true, false); - // Only use the secondary tty if we don't have anything specified for - // output and don't have an action for stdout - if (GetFileActionForFD(STDOUT_FILENO) == nullptr) + if (stdout_free) AppendOpenFileAction(STDOUT_FILENO, secondary_file_spec, false, true); - // Only use the secondary tty if we don't have anything specified for - // error and don't have an action for stderr - if (GetFileActionForFD(STDERR_FILENO) == nullptr) + if (stderr_free) AppendOpenFileAction(STDERR_FILENO, secondary_file_spec, false, true); return llvm::Error::success(); } diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 63178e6c8a7a..2f08b9fa8857 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -86,7 +86,6 @@ static void DupDescriptor(int error_fd, const FileSpec &file_spec, int fd, ExitWithError(error_fd, "DupDescriptor-dup2"); ::close(target_fd); - return; } [[noreturn]] static void ChildFunc(int error_fd, diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp index 84c5a472332a..1c8406f68784 100644 --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -15,7 +15,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Timer.h" -#include "lldb/lldb-private.h" +#include "lldb/Version/Version.h" #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 301bf949feef..bd03f18b47c0 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -2216,7 +2216,6 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return; } int CommandInterpreter::GetOptionArgumentPosition(const char *in_string) { @@ -2563,8 +2562,6 @@ void CommandInterpreter::HandleCommands(const StringList &commands, result.SetStatus(eReturnStatusSuccessFinishResult); m_debugger.SetAsyncExecution(old_async_execution); - - return; } // Make flags that we can pass into the IOHandler so our delegates can do the diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp index 506b0d6e7cde..1b1e6996764c 100644 --- a/lldb/source/Interpreter/CommandReturnObject.cpp +++ b/lldb/source/Interpreter/CommandReturnObject.cpp @@ -120,13 +120,13 @@ void CommandReturnObject::AppendRawError(llvm::StringRef in_string) { void CommandReturnObject::SetStatus(ReturnStatus status) { m_status = status; } -ReturnStatus CommandReturnObject::GetStatus() { return m_status; } +ReturnStatus CommandReturnObject::GetStatus() const { return m_status; } -bool CommandReturnObject::Succeeded() { +bool CommandReturnObject::Succeeded() const { return m_status <= eReturnStatusSuccessContinuingResult; } -bool CommandReturnObject::HasResult() { +bool CommandReturnObject::HasResult() const { return (m_status == eReturnStatusSuccessFinishResult || m_status == eReturnStatusSuccessContinuingResult); } @@ -145,7 +145,7 @@ void CommandReturnObject::Clear() { m_interactive = true; } -bool CommandReturnObject::GetDidChangeProcessState() { +bool CommandReturnObject::GetDidChangeProcessState() const { return m_did_change_process_state; } diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp index ccfbeec3d589..804532acf9f7 100644 --- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -817,6 +817,16 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl( lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) { lldb::addr_t pac_sign_extension = 0x0080000000000000ULL; + // Darwin systems originally couldn't determine the proper value + // dynamically, so the most common value was hardcoded. This has + // largely been cleaned up, but there are still a handful of + // environments that assume the default value is set to this value + // and there's no dynamic value to correct it. + // When no mask is specified, set it to 39 bits of addressing (0..38). + if (mask == 0) { + // ~((1ULL<<39)-1) + mask = 0xffffff8000000000; + } return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 85e2fcfc838c..7844f27139cf 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -211,7 +211,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, Stmt **last_stmt_ptr = Body->body_end() - 1; Stmt *last_stmt = *last_stmt_ptr; - while (dyn_cast<NullStmt>(last_stmt)) { + while (isa<NullStmt>(last_stmt)) { if (last_stmt_ptr != Body->body_begin()) { last_stmt_ptr--; last_stmt = *last_stmt_ptr; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 80469e292580..6ed3cc9384f0 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -293,7 +293,7 @@ public: NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to); // Check if we already completed this type. - if (m_decls_already_completed.count(to_named_decl) != 0) + if (m_decls_already_completed.contains(to_named_decl)) return; // Queue this type to be completed. m_decls_to_complete.insert(to_named_decl); @@ -806,7 +806,7 @@ void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast, md->removeOriginsWithContext(src_ast); } -ClangASTImporter::MapCompleter::~MapCompleter() { return; } +ClangASTImporter::MapCompleter::~MapCompleter() {} llvm::Expected<Decl *> ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 410d8a95cb12..510352e8c173 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -513,8 +513,6 @@ void ClangASTSource::FindExternalLexicalDecls( // is consulted again when a clang::DeclContext::lookup is called. const_cast<DeclContext *>(decl_context)->setMustBuildLookupTable(); } - - return; } void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 3afd1fd5f2d1..f3fec3f944a1 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -59,7 +59,7 @@ public: GetExternalCXXBaseSpecifiers(uint64_t Offset) override { return nullptr; } - void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } + void MaterializeVisibleDecls(const clang::DeclContext *DC) {} void InstallASTContext(TypeSystemClang &ast_context); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 846c1597292b..4af5d41a5921 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1954,8 +1954,6 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, return; context.AddNamedDecl(typedef_decl); - - return; } void ClangExpressionDeclMap::AddOneType(NameSearchContext &context, diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp index a6e36d81b950..8b132b54b7e6 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp @@ -353,7 +353,7 @@ protected: } bool InspectInstruction(llvm::Instruction &i) override { - if (dyn_cast<llvm::LoadInst>(&i) || dyn_cast<llvm::StoreInst>(&i)) + if (isa<llvm::LoadInst>(&i) || isa<llvm::StoreInst>(&i)) RegisterInstruction(i); return true; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index f80dc2b14467..e0e41925f7ef 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -1255,7 +1255,7 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name), llvm_value_ptr, *value_size, value_alignment); - } else if (dyn_cast<llvm::Function>(llvm_value_ptr)) { + } else if (isa<llvm::Function>(llvm_value_ptr)) { LLDB_LOG(log, "Function pointers aren't handled right now"); return false; diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index f1925990e94a..df61cc3853eb 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -35,6 +35,7 @@ #include "BlockPointer.h" #include "CPlusPlusNameParser.h" #include "CxxStringTypes.h" +#include "Generic.h" #include "LibCxx.h" #include "LibCxxAtomic.h" #include "LibCxxVariant.h" @@ -655,7 +656,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::tuple synthetic children", ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator, + AddCXXSynthetic(cpp_category_sp, LibcxxOptionalSyntheticFrontEndCreator, "libc++ std::optional synthetic children", ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"), stl_synth_flags, true); @@ -772,7 +773,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, - lldb_private::formatters::LibcxxOptionalSummaryProvider, + lldb_private::formatters::GenericOptionalSummaryProvider, "libc++ std::optional summary provider", ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"), stl_summary_flags, true); @@ -904,6 +905,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( + RegularExpression("^std::deque<.+>(( )?&)?$"), + SyntheticChildrenSP(new ScriptedSyntheticChildren( + stl_deref_flags, + "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider"))); + cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::set<.+> >(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, @@ -914,11 +920,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::optional<.+>(( )?&)?$"), - SyntheticChildrenSP(new ScriptedSyntheticChildren( - stl_synth_flags, - "lldb.formatters.cpp.gnu_libstdcpp.StdOptionalSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::multiset<.+> >(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, @@ -931,7 +932,7 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), SyntheticChildrenSP(new ScriptedSyntheticChildren( - stl_synth_flags, + stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( RegularExpression("^std::(__cxx11::)?forward_list<.+>(( )?&)?$"), @@ -942,11 +943,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::optional<.+>(( )?&)?$"), - TypeSummaryImplSP(new ScriptSummaryFormat( - stl_summary_flags, - "lldb.formatters.cpp.gnu_libstdcpp.StdOptionalSummaryProvider"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::bitset<.+>(( )?&)?$"), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -963,6 +959,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( + RegularExpression("^std::deque<.+>(( )?&)?$"), + TypeSummaryImplSP( + new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->GetRegexTypeSummariesContainer()->Add( RegularExpression("^std::multimap<.+> >(( )?&)?$"), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -1022,6 +1022,12 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::bitset synthetic child", ConstString("^std::bitset<.+>(( )?&)?$"), stl_deref_flags, true); + AddCXXSynthetic( + cpp_category_sp, + lldb_private::formatters::LibStdcppOptionalSyntheticFrontEndCreator, + "std::optional synthetic child", + ConstString("^std::optional<.+>(( )?&)?$"), stl_deref_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibStdcppUniquePointerSummaryProvider, "libstdc++ std::unique_ptr summary provider", @@ -1037,6 +1043,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libstdc++ std::weak_ptr summary provider", ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary( + cpp_category_sp, lldb_private::formatters::GenericOptionalSummaryProvider, + "libstd++ std::optional summary provider", + ConstString("^std::optional<.+>(( )?&)?$"), stl_summary_flags, true); } static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/Generic.h b/lldb/source/Plugins/Language/CPlusPlus/Generic.h new file mode 100644 index 000000000000..bfb28bebf90b --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/Generic.h @@ -0,0 +1,25 @@ +//===-- LibCxx.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_LANGUAGE_CPLUSPLUS_GENERIC_H +#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_GENERIC_H + +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Utility/Stream.h" + +namespace lldb_private { +namespace formatters { + +bool GenericOptionalSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); + +} // namespace formatters +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_GENERIC_H diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp new file mode 100644 index 000000000000..74b3f711de35 --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp @@ -0,0 +1,139 @@ +//===-- GenericOptional.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 "Generic.h" +#include "LibCxx.h" +#include "LibStdcpp.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +bool lldb_private::formatters::GenericOptionalSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { + stream.Printf(" Has Value=%s ", + valobj.GetNumChildren() == 0 ? "false" : "true"); + + return true; +} + +// Synthetic Children Provider +namespace { + +class GenericOptionalFrontend : public SyntheticChildrenFrontEnd { +public: + enum class StdLib { + LibCxx, + LibStdcpp, + }; + + GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib); + + size_t GetIndexOfChildWithName(ConstString name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + size_t CalculateNumChildren() override { return m_has_value ? 1U : 0U; } + + ValueObjectSP GetChildAtIndex(size_t idx) override; + bool Update() override; + +private: + bool m_has_value = false; + StdLib m_stdlib; +}; + +} // namespace + +GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj, + StdLib stdlib) + : SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) { + if (auto target_sp = m_backend.GetTargetSP()) { + Update(); + } +} + +bool GenericOptionalFrontend::Update() { + ValueObjectSP engaged_sp; + + if (m_stdlib == StdLib::LibCxx) + engaged_sp = + m_backend.GetChildMemberWithName(ConstString("__engaged_"), true); + else if (m_stdlib == StdLib::LibStdcpp) + engaged_sp = + m_backend.GetChildMemberWithName(ConstString("_M_payload"), true) + ->GetChildMemberWithName(ConstString("_M_engaged"), true); + + if (!engaged_sp) + return false; + + // _M_engaged/__engaged is a bool flag and is true if the optional contains a + // value. Converting it to unsigned gives us a size of 1 if it contains a + // value and 0 if not. + m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0; + + return false; +} + +ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(size_t _idx) { + if (!m_has_value) + return ValueObjectSP(); + + ValueObjectSP val_sp; + + if (m_stdlib == StdLib::LibCxx) + // __val_ contains the underlying value of an optional if it has one. + // Currently because it is part of an anonymous union + // GetChildMemberWithName() does not peer through and find it unless we are + // at the parent itself. We can obtain the parent through __engaged_. + val_sp = m_backend.GetChildMemberWithName(ConstString("__engaged_"), true) + ->GetParent() + ->GetChildAtIndex(0, true) + ->GetChildMemberWithName(ConstString("__val_"), true); + else if (m_stdlib == StdLib::LibStdcpp) { + val_sp = m_backend.GetChildMemberWithName(ConstString("_M_payload"), true) + ->GetChildMemberWithName(ConstString("_M_payload"), true); + + // In some implementations, _M_value contains the underlying value of an + // optional, and in other versions, it's in the payload member. + ValueObjectSP candidate = + val_sp->GetChildMemberWithName(ConstString("_M_value"), true); + if (candidate) + val_sp = candidate; + } + + if (!val_sp) + return ValueObjectSP(); + + CompilerType holder_type = val_sp->GetCompilerType(); + + if (!holder_type) + return ValueObjectSP(); + + return val_sp->Clone(ConstString("Value")); +} + +SyntheticChildrenFrontEnd * +formatters::LibStdcppOptionalSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new GenericOptionalFrontend( + *valobj_sp, GenericOptionalFrontend::StdLib::LibStdcpp); + return nullptr; +} + +SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new GenericOptionalFrontend(*valobj_sp, + GenericOptionalFrontend::StdLib::LibCxx); + return nullptr; +} diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index 99e206543197..80dc71787ceb 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -170,8 +170,8 @@ SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); SyntheticChildrenFrontEnd * -LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *, - lldb::ValueObjectSP valobj_sp); +LibcxxOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp); SyntheticChildrenFrontEnd * LibcxxVariantFrontEndCreator(CXXSyntheticChildren *, diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp deleted file mode 100644 index c1b40ba65e7d..000000000000 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp +++ /dev/null @@ -1,84 +0,0 @@ -//===-- LibCxxOptional.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 "LibCxx.h" -#include "lldb/DataFormatters/FormattersHelpers.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { - -class OptionalFrontEnd : public SyntheticChildrenFrontEnd { -public: - OptionalFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { - Update(); - } - - size_t GetIndexOfChildWithName(ConstString name) override { - return formatters::ExtractIndexFromString(name.GetCString()); - } - - bool MightHaveChildren() override { return true; } - bool Update() override; - size_t CalculateNumChildren() override { return m_has_value ? 1U : 0U; } - ValueObjectSP GetChildAtIndex(size_t idx) override; - -private: - /// True iff the option contains a value. - bool m_has_value = false; -}; -} // namespace - -bool OptionalFrontEnd::Update() { - ValueObjectSP engaged_sp( - m_backend.GetChildMemberWithName(ConstString("__engaged_"), true)); - - if (!engaged_sp) - return false; - - // __engaged_ is a bool flag and is true if the optional contains a value. - // Converting it to unsigned gives us a size of 1 if it contains a value - // and 0 if not. - m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0; - - return false; -} - -ValueObjectSP OptionalFrontEnd::GetChildAtIndex(size_t idx) { - if (!m_has_value) - return ValueObjectSP(); - - // __val_ contains the underlying value of an optional if it has one. - // Currently because it is part of an anonymous union GetChildMemberWithName() - // does not peer through and find it unless we are at the parent itself. - // We can obtain the parent through __engaged_. - ValueObjectSP val_sp( - m_backend.GetChildMemberWithName(ConstString("__engaged_"), true) - ->GetParent() - ->GetChildAtIndex(0, true) - ->GetChildMemberWithName(ConstString("__val_"), true)); - - if (!val_sp) - return ValueObjectSP(); - - CompilerType holder_type = val_sp->GetCompilerType(); - - if (!holder_type) - return ValueObjectSP(); - - return val_sp->Clone(ConstString("Value")); -} - -SyntheticChildrenFrontEnd * -formatters::LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *, - lldb::ValueObjectSP valobj_sp) { - if (valobj_sp) - return new OptionalFrontEnd(*valobj_sp); - return nullptr; -} diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h index b6f9c469fedd..1c1c8fdb9ea4 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h @@ -46,6 +46,10 @@ LibStdcppBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); SyntheticChildrenFrontEnd * +LibStdcppOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 9bc40c16e5d0..af11109ae45d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -80,8 +80,6 @@ public: LLDB_LOG(log, " AOEAS::CT Before:\n{1}", ClangUtil::DumpDecl(tag_decl)); LLDB_LOG(log, " AOEAS::CT After:{1}", ClangUtil::DumpDecl(tag_decl)); - - return; } void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override { @@ -107,7 +105,6 @@ public: LLDB_LOGF(log, " [CT] After:"); LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl)); } - return; } bool layoutRecordType( diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 719109c863e7..1d989b268b74 100644 --- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -589,6 +589,8 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, result_ptr->image_ptr = dlopen(name, RTLD_LAZY); if (result_ptr->image_ptr) result_ptr->error_str = nullptr; + else + result_ptr->error_str = dlerror(); return nullptr; } diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp index 90c290b6fbc7..67c9484680a4 100644 --- a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp +++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp @@ -47,6 +47,27 @@ public: return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, ePropertyEmulatorPath); } + + Args GetEmulatorArgs() { + Args result; + m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyEmulatorArgs, + result); + return result; + } + + Environment GetEmulatorEnvVars() { + Args args; + m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyEmulatorEnvVars, + args); + return Environment(args); + } + + Environment GetTargetEnvVars() { + Args args; + m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, ePropertyTargetEnvVars, + args); + return Environment(args); + } }; static PluginProperties &GetGlobalProperties() { @@ -98,6 +119,44 @@ static auto get_arg_range(const Args &args) { args.GetArgumentArrayRef().end()); } +// Returns the emulator environment which result in the desired environment +// being presented to the emulated process. We want to be careful about +// preserving the host environment, as it may contain entries (LD_LIBRARY_PATH, +// for example) needed for the operation of the emulator itself. +static Environment ComputeLaunchEnvironment(Environment target, + Environment host) { + std::vector<std::string> set_env; + for (const auto &KV : target) { + // If the host value differs from the target (or is unset), then set it + // through QEMU_SET_ENV. Identical entries will be forwarded automatically. + auto host_it = host.find(KV.first()); + if (host_it == host.end() || host_it->second != KV.second) + set_env.push_back(Environment::compose(KV)); + } + llvm::sort(set_env); + + std::vector<llvm::StringRef> unset_env; + for (const auto &KV : host) { + // If the target is missing some host entries, then unset them through + // QEMU_UNSET_ENV. + if (target.count(KV.first()) == 0) + unset_env.push_back(KV.first()); + } + llvm::sort(unset_env); + + // The actual QEMU_(UN)SET_ENV variables should not be forwarded to the + // target. + if (!set_env.empty()) { + host["QEMU_SET_ENV"] = llvm::join(set_env, ","); + unset_env.push_back("QEMU_SET_ENV"); + } + if (!unset_env.empty()) { + unset_env.push_back("QEMU_UNSET_ENV"); + host["QEMU_UNSET_ENV"] = llvm::join(unset_env, ","); + } + return host; +} + lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target &target, Status &error) { @@ -112,8 +171,10 @@ 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, launch_info.GetExecutableFile().GetPath()}); + Args args({qemu, "-g", socket_path}); + args.AppendArguments(GetGlobalProperties().GetEmulatorArgs()); + args.AppendArgument("--"); + args.AppendArgument(launch_info.GetExecutableFile().GetPath()); for (size_t i = 1; i < launch_info.GetArguments().size(); ++i) args.AppendArgument(launch_info.GetArguments()[i].ref()); @@ -121,11 +182,23 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, get_arg_range(args)); launch_info.SetArguments(args, true); + + Environment emulator_env = Host::GetEnvironment(); + for (const auto &KV : GetGlobalProperties().GetEmulatorEnvVars()) + emulator_env[KV.first()] = KV.second; + launch_info.GetEnvironment() = ComputeLaunchEnvironment( + std::move(launch_info.GetEnvironment()), std::move(emulator_env)); + launch_info.SetLaunchInSeparateProcessGroup(true); launch_info.GetFlags().Clear(eLaunchFlagDebug); launch_info.SetMonitorProcessCallback(ProcessLaunchInfo::NoOpMonitorCallback, false); + // This is automatically done for host platform in + // Target::FinalizeFileActions, but we're not a host platform. + llvm::Error Err = launch_info.SetUpPtyRedirection(); + LLDB_LOG_ERROR(log, std::move(Err), "SetUpPtyRedirection failed: {0}"); + error = Host::LaunchProcess(launch_info); if (error.Fail()) return nullptr; @@ -134,6 +207,7 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, launch_info.GetListener(), process_gdb_remote::ProcessGDBRemote::GetPluginNameStatic(), nullptr, true); + ListenerSP listener_sp = Listener::MakeListener("lldb.platform_qemu_user.debugprocess"); launch_info.SetHijackListener(listener_sp); @@ -143,6 +217,18 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, if (error.Fail()) return nullptr; + if (launch_info.GetPTY().GetPrimaryFileDescriptor() != + PseudoTerminal::invalid_fd) + process_sp->SetSTDIOFileDescriptor( + launch_info.GetPTY().ReleasePrimaryFileDescriptor()); + process_sp->WaitForProcessToStop(llvm::None, nullptr, false, listener_sp); return process_sp; } + +Environment PlatformQemuUser::GetEnvironment() { + Environment env = Host::GetEnvironment(); + for (const auto &KV : GetGlobalProperties().GetTargetEnvVars()) + env[KV.first()] = KV.second; + return env; +} diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h index f4f5d224a8cd..71df1b7b7811 100644 --- a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h +++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h @@ -45,7 +45,7 @@ public: void CalculateTrapHandlerSymbolNames() override {} - Environment GetEnvironment() override { return Host::GetEnvironment(); } + Environment GetEnvironment() override; private: static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); diff --git a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td index abfab7f59de4..4e8fbcfd6760 100644 --- a/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td +++ b/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td @@ -9,4 +9,16 @@ let Definition = "platformqemuuser" in { Global, DefaultStringValue<"">, Desc<"Path to the emulator binary.">; + def EmulatorArgs: Property<"emulator-args", "Args">, + Global, + DefaultStringValue<"">, + Desc<"Extra arguments to pass to the emulator.">; + def EmulatorEnvVars: Property<"emulator-env-vars", "Dictionary">, + Global, + ElementType<"String">, + Desc<"Extra variables to add to the emulator environment.">; + def TargetEnvVars: Property<"target-env-vars", "Dictionary">, + Global, + ElementType<"String">, + Desc<"Extra variables to add to emulated target environment.">; } diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 987f7c7f57e7..3535a5ad739d 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -225,18 +225,12 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { m_platform_hostname = parsed_url->hostname.str(); m_gdb_client.SetConnection(std::make_unique<ConnectionFileDescriptor>()); - if (repro::Reproducer::Instance().IsReplaying()) { - error = m_gdb_replay_server.Connect(m_gdb_client); - if (error.Success()) - m_gdb_replay_server.StartAsyncThread(); - } else { - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - repro::GDBRemoteProvider &provider = - g->GetOrCreate<repro::GDBRemoteProvider>(); - m_gdb_client.SetPacketRecorder(provider.GetNewPacketRecorder()); - } - m_gdb_client.Connect(url, &error); + if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { + repro::GDBRemoteProvider &provider = + g->GetOrCreate<repro::GDBRemoteProvider>(); + m_gdb_client.SetPacketRecorder(provider.GetNewPacketRecorder()); } + m_gdb_client.Connect(url, &error); if (error.Fail()) return error; diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp new file mode 100644 index 000000000000..339d33d25110 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp @@ -0,0 +1,218 @@ +//===-- ProcessFreeBSDKernel.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 "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/DynamicLoader.h" + +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" +#include "ProcessFreeBSDKernel.h" +#include "ThreadFreeBSDKernel.h" + +#if LLDB_ENABLE_FBSDVMCORE +#include <fvc.h> +#endif +#if defined(__FreeBSD__) +#include <kvm.h> +#endif + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ProcessFreeBSDKernel) + +namespace { + +#if LLDB_ENABLE_FBSDVMCORE +class ProcessFreeBSDKernelFVC : public ProcessFreeBSDKernel { +public: + ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp, lldb::ListenerSP listener, + fvc_t *fvc); + + ~ProcessFreeBSDKernelFVC(); + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Status &error) override; + +private: + fvc_t *m_fvc; + + const char *GetError(); +}; +#endif // LLDB_ENABLE_FBSDVMCORE + +#if defined(__FreeBSD__) +class ProcessFreeBSDKernelKVM : public ProcessFreeBSDKernel { +public: + ProcessFreeBSDKernelKVM(lldb::TargetSP target_sp, lldb::ListenerSP listener, + kvm_t *fvc); + + ~ProcessFreeBSDKernelKVM(); + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Status &error) override; + +private: + kvm_t *m_kvm; + + const char *GetError(); +}; +#endif // defined(__FreeBSD__) + +} // namespace + +ProcessFreeBSDKernel::ProcessFreeBSDKernel(lldb::TargetSP target_sp, + ListenerSP listener_sp) + : PostMortemProcess(target_sp, listener_sp) {} + +lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp, + ListenerSP listener_sp, + const FileSpec *crash_file, + bool can_connect) { + ModuleSP executable = target_sp->GetExecutableModule(); + if (crash_file && !can_connect && executable) { +#if LLDB_ENABLE_FBSDVMCORE + fvc_t *fvc = + fvc_open(executable->GetFileSpec().GetPath().c_str(), + crash_file->GetPath().c_str(), nullptr, nullptr, nullptr); + if (fvc) + return std::make_shared<ProcessFreeBSDKernelFVC>(target_sp, listener_sp, + fvc); +#endif + +#if defined(__FreeBSD__) + kvm_t *kvm = + kvm_open2(executable->GetFileSpec().GetPath().c_str(), + crash_file->GetPath().c_str(), O_RDONLY, nullptr, nullptr); + if (kvm) + return std::make_shared<ProcessFreeBSDKernelKVM>(target_sp, listener_sp, + kvm); +#endif + } + return nullptr; +} + +void ProcessFreeBSDKernel::Initialize() { + static llvm::once_flag g_once_flag; + + llvm::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); +} + +void ProcessFreeBSDKernel::Terminate() { + PluginManager::UnregisterPlugin(ProcessFreeBSDKernel::CreateInstance); +} + +Status ProcessFreeBSDKernel::DoDestroy() { return Status(); } + +bool ProcessFreeBSDKernel::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + return true; +} + +void ProcessFreeBSDKernel::RefreshStateAfterStop() {} + +bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + if (old_thread_list.GetSize(false) == 0) { + // Make up the thread the first time this is called so we can set our one + // and only core thread state up. + + // We cannot construct a thread without a register context as that crashes + // LLDB but we can construct a process without threads to provide minimal + // memory reading support. + switch (GetTarget().GetArchitecture().GetMachine()) { + case llvm::Triple::aarch64: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + break; + default: + 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); + } else { + const uint32_t num_threads = old_thread_list.GetSize(false); + for (uint32_t i = 0; i < num_threads; ++i) + new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false)); + } + return new_thread_list.GetSize(false) > 0; +} + +Status ProcessFreeBSDKernel::DoLoadCore() { + // The core is already loaded by CreateInstance(). + return Status(); +} + +DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() { + if (m_dyld_up.get() == nullptr) + m_dyld_up.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderStatic::GetPluginNameStatic())); + return m_dyld_up.get(); +} + +#if LLDB_ENABLE_FBSDVMCORE + +ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp, + ListenerSP listener_sp, + fvc_t *fvc) + : ProcessFreeBSDKernel(target_sp, listener_sp), m_fvc(fvc) {} + +ProcessFreeBSDKernelFVC::~ProcessFreeBSDKernelFVC() { + if (m_fvc) + fvc_close(m_fvc); +} + +size_t ProcessFreeBSDKernelFVC::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Status &error) { + ssize_t rd = 0; + rd = fvc_read(m_fvc, addr, buf, size); + if (rd < 0 || static_cast<size_t>(rd) != size) { + error.SetErrorStringWithFormat("Reading memory failed: %s", GetError()); + return rd > 0 ? rd : 0; + } + return rd; +} + +const char *ProcessFreeBSDKernelFVC::GetError() { return fvc_geterr(m_fvc); } + +#endif // LLDB_ENABLE_FBSDVMCORE + +#if defined(__FreeBSD__) + +ProcessFreeBSDKernelKVM::ProcessFreeBSDKernelKVM(lldb::TargetSP target_sp, + ListenerSP listener_sp, + kvm_t *fvc) + : ProcessFreeBSDKernel(target_sp, listener_sp), m_kvm(fvc) {} + +ProcessFreeBSDKernelKVM::~ProcessFreeBSDKernelKVM() { + if (m_kvm) + kvm_close(m_kvm); +} + +size_t ProcessFreeBSDKernelKVM::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Status &error) { + ssize_t rd = 0; + rd = kvm_read2(m_kvm, addr, buf, size); + if (rd < 0 || static_cast<size_t>(rd) != size) { + error.SetErrorStringWithFormat("Reading memory failed: %s", GetError()); + return rd > 0 ? rd : 0; + } + return rd; +} + +const char *ProcessFreeBSDKernelKVM::GetError() { return kvm_geterr(m_kvm); } + +#endif // defined(__FreeBSD__) diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h new file mode 100644 index 000000000000..558eec5403db --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h @@ -0,0 +1,51 @@ +//===-- ProcessFreeBSDKernel.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_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H +#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H + +#include "lldb/Target/PostMortemProcess.h" + +class ProcessFreeBSDKernel : public lldb_private::PostMortemProcess { +public: + ProcessFreeBSDKernel(lldb::TargetSP target_sp, lldb::ListenerSP listener); + + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener, + const lldb_private::FileSpec *crash_file_path, + bool can_connect); + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "freebsd-kernel"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "FreeBSD kernel vmcore debugging plug-in."; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + lldb_private::Status DoDestroy() override; + + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + + void RefreshStateAfterStop() override; + + lldb_private::Status DoLoadCore() override; + + lldb_private::DynamicLoader *GetDynamicLoader() override; + +protected: + bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp new file mode 100644 index 000000000000..11843ddc82d9 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp @@ -0,0 +1,110 @@ +//===-- RegisterContextFreeBSDKernel_arm64.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 "RegisterContextFreeBSDKernel_arm64.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Endian.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextFreeBSDKernel_arm64::RegisterContextFreeBSDKernel_arm64( + Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up, + lldb::addr_t pcb_addr) + : RegisterContextPOSIX_arm64(thread, std::move(register_info_up)), + m_pcb_addr(pcb_addr) {} + +bool RegisterContextFreeBSDKernel_arm64::ReadGPR() { return true; } + +bool RegisterContextFreeBSDKernel_arm64::ReadFPR() { return true; } + +bool RegisterContextFreeBSDKernel_arm64::WriteGPR() { + assert(0); + return false; +} + +bool RegisterContextFreeBSDKernel_arm64::WriteFPR() { + assert(0); + return false; +} + +bool RegisterContextFreeBSDKernel_arm64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (m_pcb_addr == LLDB_INVALID_ADDRESS) + return false; + + struct { + llvm::support::ulittle64_t x[30]; + llvm::support::ulittle64_t lr; + llvm::support::ulittle64_t _reserved; + llvm::support::ulittle64_t sp; + } pcb; + + Status error; + size_t rd = + m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error); + if (rd != sizeof(pcb)) + return false; + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + switch (reg) { + case gpr_x0_arm64: + case gpr_x1_arm64: + case gpr_x2_arm64: + case gpr_x3_arm64: + case gpr_x4_arm64: + case gpr_x5_arm64: + case gpr_x6_arm64: + case gpr_x7_arm64: + case gpr_x8_arm64: + case gpr_x9_arm64: + case gpr_x10_arm64: + case gpr_x11_arm64: + case gpr_x12_arm64: + case gpr_x13_arm64: + case gpr_x14_arm64: + case gpr_x15_arm64: + case gpr_x16_arm64: + case gpr_x17_arm64: + case gpr_x18_arm64: + case gpr_x19_arm64: + case gpr_x20_arm64: + case gpr_x21_arm64: + case gpr_x22_arm64: + case gpr_x23_arm64: + case gpr_x24_arm64: + case gpr_x25_arm64: + case gpr_x26_arm64: + case gpr_x27_arm64: + case gpr_x28_arm64: + case gpr_fp_arm64: + static_assert(gpr_fp_arm64 - gpr_x0_arm64 == 29, + "nonconsecutive arm64 register numbers"); + value = pcb.x[reg - gpr_x0_arm64]; + break; + case gpr_sp_arm64: + value = pcb.sp; + break; + case gpr_pc_arm64: + // The pc of crashing thread is stored in lr. + value = pcb.lr; + break; + default: + return false; + } + return true; +} + +bool RegisterContextFreeBSDKernel_arm64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h new file mode 100644 index 000000000000..155dda6e748f --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h @@ -0,0 +1,41 @@ +//===-- RegisterContextFreeBSDKernel_arm64.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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H + +#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +class RegisterContextFreeBSDKernel_arm64 : public RegisterContextPOSIX_arm64 { +public: + RegisterContextFreeBSDKernel_arm64( + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up, + lldb::addr_t pcb_addr); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + bool ReadGPR() override; + + bool ReadFPR() override; + + bool WriteGPR() override; + + bool WriteFPR() override; + +private: + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp new file mode 100644 index 000000000000..fde85c9c9f0d --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp @@ -0,0 +1,83 @@ +//===-- RegisterContextFreeBSDKernel_i386.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 "RegisterContextFreeBSDKernel_i386.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Endian.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextFreeBSDKernel_i386::RegisterContextFreeBSDKernel_i386( + Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr) + : RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) { +} + +bool RegisterContextFreeBSDKernel_i386::ReadGPR() { return true; } + +bool RegisterContextFreeBSDKernel_i386::ReadFPR() { return true; } + +bool RegisterContextFreeBSDKernel_i386::WriteGPR() { + assert(0); + return false; +} + +bool RegisterContextFreeBSDKernel_i386::WriteFPR() { + assert(0); + return false; +} + +bool RegisterContextFreeBSDKernel_i386::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (m_pcb_addr == LLDB_INVALID_ADDRESS) + return false; + + struct { + llvm::support::ulittle32_t edi; + llvm::support::ulittle32_t esi; + llvm::support::ulittle32_t ebp; + llvm::support::ulittle32_t esp; + llvm::support::ulittle32_t ebx; + llvm::support::ulittle32_t eip; + } pcb; + + Status error; + size_t rd = + m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error); + if (rd != sizeof(pcb)) + return false; + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + switch (reg) { +#define REG(x) \ + case lldb_##x##_i386: \ + value = pcb.x; \ + break; + + REG(edi); + REG(esi); + REG(ebp); + REG(esp); + REG(eip); + +#undef REG + + default: + return false; + } + + return true; +} + +bool RegisterContextFreeBSDKernel_i386::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h new file mode 100644 index 000000000000..218e3374f8df --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h @@ -0,0 +1,41 @@ +//===-- RegisterContextFreeBSDKernel_i386.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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H + +#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +class RegisterContextFreeBSDKernel_i386 : public RegisterContextPOSIX_x86 { +public: + RegisterContextFreeBSDKernel_i386( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + lldb::addr_t pcb_addr); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + bool ReadGPR() override; + + bool ReadFPR() override; + + bool WriteGPR() override; + + bool WriteFPR() override; + +private: + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp new file mode 100644 index 000000000000..ff57842e345c --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp @@ -0,0 +1,88 @@ +//===-- RegisterContextFreeBSDKernel_x86_64.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 "RegisterContextFreeBSDKernel_x86_64.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Endian.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextFreeBSDKernel_x86_64::RegisterContextFreeBSDKernel_x86_64( + Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr) + : RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) { +} + +bool RegisterContextFreeBSDKernel_x86_64::ReadGPR() { return true; } + +bool RegisterContextFreeBSDKernel_x86_64::ReadFPR() { return true; } + +bool RegisterContextFreeBSDKernel_x86_64::WriteGPR() { + assert(0); + return false; +} + +bool RegisterContextFreeBSDKernel_x86_64::WriteFPR() { + assert(0); + return false; +} + +bool RegisterContextFreeBSDKernel_x86_64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (m_pcb_addr == LLDB_INVALID_ADDRESS) + return false; + + struct { + llvm::support::ulittle64_t r15; + llvm::support::ulittle64_t r14; + llvm::support::ulittle64_t r13; + llvm::support::ulittle64_t r12; + llvm::support::ulittle64_t rbp; + llvm::support::ulittle64_t rsp; + llvm::support::ulittle64_t rbx; + llvm::support::ulittle64_t rip; + } pcb; + + Status error; + size_t rd = + m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error); + if (rd != sizeof(pcb)) + return false; + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + switch (reg) { +#define REG(x) \ + case lldb_##x##_x86_64: \ + value = pcb.x; \ + break; + + REG(r15); + REG(r14); + REG(r13); + REG(r12); + REG(rbp); + REG(rsp); + REG(rbx); + REG(rip); + +#undef REG + + default: + return false; + } + + return true; +} + +bool RegisterContextFreeBSDKernel_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h new file mode 100644 index 000000000000..9a2ac638dfea --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h @@ -0,0 +1,41 @@ +//===-- RegisterContextFreeBSDKernel_x86_64.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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H + +#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +class RegisterContextFreeBSDKernel_x86_64 : public RegisterContextPOSIX_x86 { +public: + RegisterContextFreeBSDKernel_x86_64( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + lldb::addr_t pcb_addr); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + bool ReadGPR() override; + + bool ReadFPR() override; + + bool WriteGPR() override; + + bool WriteFPR() override; + +private: + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp new file mode 100644 index 000000000000..124c65d587ff --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp @@ -0,0 +1,85 @@ +//===-- ThreadFreeBSDKernel.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 "ThreadFreeBSDKernel.h" + +#include "lldb/Target/Unwind.h" +#include "lldb/Utility/Log.h" + +#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#include "ProcessFreeBSDKernel.h" +#include "RegisterContextFreeBSDKernel_arm64.h" +#include "RegisterContextFreeBSDKernel_i386.h" +#include "RegisterContextFreeBSDKernel_x86_64.h" +#include "ThreadFreeBSDKernel.h" + +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) {} + +ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {} + +void ThreadFreeBSDKernel::RefreshStateAfterStop() {} + +lldb::RegisterContextSP ThreadFreeBSDKernel::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp = CreateRegisterContextForFrame(nullptr); + return m_reg_context_sp; +} + +lldb::RegisterContextSP +ThreadFreeBSDKernel::CreateRegisterContextForFrame(StackFrame *frame) { + RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + if (m_thread_reg_ctx_sp) + return m_thread_reg_ctx_sp; + + ProcessFreeBSDKernel *process = + static_cast<ProcessFreeBSDKernel *>(GetProcess().get()); + ArchSpec arch = process->GetTarget().GetArchitecture(); + + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + m_thread_reg_ctx_sp = + std::make_shared<RegisterContextFreeBSDKernel_arm64>( + *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch, 0), + 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); + break; + case llvm::Triple::x86_64: + m_thread_reg_ctx_sp = + std::make_shared<RegisterContextFreeBSDKernel_x86_64>( + *this, new RegisterContextFreeBSD_x86_64(arch), m_pcb_addr); + break; + default: + assert(false && "Unsupported architecture passed to ThreadFreeBSDKernel"); + break; + } + + reg_ctx_sp = m_thread_reg_ctx_sp; + } else { + reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; +} + +bool ThreadFreeBSDKernel::CalculateStopInfo() { return false; } diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h new file mode 100644 index 000000000000..2842eba64e56 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h @@ -0,0 +1,36 @@ +//===-- ThreadFreeBSDKernel.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_FREEBSDKERNEL_THREADFREEBSDKERNEL_H +#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H + +#include "lldb/Target/Thread.h" + +class ThreadFreeBSDKernel : public lldb_private::Thread { +public: + ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid, + lldb::addr_t pcb_addr); + + ~ThreadFreeBSDKernel() override; + + void RefreshStateAfterStop() override; + + lldb::RegisterContextSP GetRegisterContext() override; + + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + +protected: + bool CalculateStopInfo() override; + +private: + lldb::RegisterContextSP m_thread_reg_ctx_sp; + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index b852a0164375..65dbc8ea95b3 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -64,6 +64,10 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp, DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); lldb::offset_t data_offset = 0; if (elf_header.Parse(data, &data_offset)) { + // Check whether we're dealing with a raw FreeBSD "full memory dump" + // ELF vmcore that needs to be handled via FreeBSDKernel plugin instead. + if (elf_header.e_ident[7] == 0xFF && elf_header.e_version == 0) + return process_sp; if (elf_header.e_type == llvm::ELF::ET_CORE) process_sp = std::make_shared<ProcessElfCore>(target_sp, listener_sp, *crash_file); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 07dfa5e04ee5..b5b105351de5 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1006,6 +1006,23 @@ GDBRemoteCommunicationClient::GetProcessArchitecture() { return m_process_arch; } +bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary( + UUID &uuid, addr_t &value, bool &value_is_offset) { + if (m_qProcessInfo_is_valid == eLazyBoolCalculate) + GetCurrentProcessInfo(); + + // Return true if we have a UUID or an address/offset of the + // main standalone / firmware binary being used. + if (!m_process_standalone_uuid.IsValid() && + m_process_standalone_value == LLDB_INVALID_ADDRESS) + return false; + + uuid = m_process_standalone_uuid; + value = m_process_standalone_value; + value_is_offset = m_process_standalone_value_is_offset; + return true; +} + bool GDBRemoteCommunicationClient::GetGDBServerVersion() { if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) { m_gdb_server_name.clear(); @@ -2147,6 +2164,25 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { } else if (name.equals("elf_abi")) { elf_abi = std::string(value); ++num_keys_decoded; + } else if (name.equals("main-binary-uuid")) { + m_process_standalone_uuid.SetFromStringRef(value); + ++num_keys_decoded; + } else if (name.equals("main-binary-slide")) { + StringExtractor extractor(value); + m_process_standalone_value = + extractor.GetU64(LLDB_INVALID_ADDRESS, 16); + if (m_process_standalone_value != LLDB_INVALID_ADDRESS) { + m_process_standalone_value_is_offset = true; + ++num_keys_decoded; + } + } else if (name.equals("main-binary-address")) { + StringExtractor extractor(value); + m_process_standalone_value = + extractor.GetU64(LLDB_INVALID_ADDRESS, 16); + if (m_process_standalone_value != LLDB_INVALID_ADDRESS) { + m_process_standalone_value_is_offset = false; + ++num_keys_decoded; + } } } if (num_keys_decoded > 0) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 6765372ce124..c69c33bb1c15 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -217,6 +217,9 @@ public: const ArchSpec &GetProcessArchitecture(); + bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value, + bool &value_is_offset); + void GetRemoteQSupported(); bool GetVContSupported(char flavor); @@ -584,6 +587,9 @@ protected: ArchSpec m_host_arch; ArchSpec m_process_arch; + UUID m_process_standalone_uuid; + lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS; + bool m_process_standalone_value_is_offset = false; llvm::VersionTuple m_os_version; llvm::VersionTuple m_maccatalyst_version; std::string m_os_build; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 3ade8c815feb..93fe36c0d9d6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -526,18 +526,15 @@ Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - Status error(WillLaunchOrAttach()); + Status error(WillLaunchOrAttach()); if (error.Fail()) return error; - if (repro::Reproducer::Instance().IsReplaying()) - error = ConnectToReplayServer(); - else - error = ConnectToDebugserver(remote_url); - + error = ConnectToDebugserver(remote_url); if (error.Fail()) return error; + StartAsyncThread(); lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); @@ -564,6 +561,94 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { } } + // The remote stub may know about the "main binary" in + // the context of a firmware debug session, and can + // give us a UUID and an address/slide of where the + // binary is loaded in memory. + UUID standalone_uuid; + addr_t standalone_value; + bool standalone_value_is_offset; + if (m_gdb_comm.GetProcessStandaloneBinary( + standalone_uuid, standalone_value, standalone_value_is_offset)) { + ModuleSP module_sp; + + if (standalone_uuid.IsValid()) { + ModuleSpec module_spec; + module_spec.GetUUID() = standalone_uuid; + + // Look up UUID in global module cache before attempting + // a more expensive search. + Status error = ModuleList::GetSharedModule(module_spec, module_sp, + nullptr, nullptr, nullptr); + + if (!module_sp) { + // Force a an external lookup, if that tool is available. + if (!module_spec.GetSymbolFileSpec()) + Symbols::DownloadObjectAndSymbolFile(module_spec, true); + + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + module_sp = std::make_shared<Module>(module_spec); + } + } + + // If we couldn't find the binary anywhere else, as a last resort, + // read it out of memory. + if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS && + !standalone_value_is_offset) { + char namebuf[80]; + snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, + standalone_value); + module_sp = + ReadModuleFromMemory(FileSpec(namebuf), standalone_value); + } + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( + LIBLLDB_LOG_DYNAMIC_LOADER)); + if (module_sp.get()) { + target.GetImages().AppendIfNeeded(module_sp, false); + + bool changed = false; + if (module_sp->GetObjectFile()) { + if (standalone_value != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("Loading binary UUID %s at %s 0x%" PRIx64, + standalone_uuid.GetAsString().c_str(), + standalone_value_is_offset ? "offset" : "address", + standalone_value); + module_sp->SetLoadAddress(target, standalone_value, + standalone_value_is_offset, changed); + } else { + // No address/offset/slide, load the binary at file address, + // offset 0. + if (log) + log->Printf("Loading binary UUID %s at file address", + standalone_uuid.GetAsString().c_str()); + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + } else { + // In-memory image, load at its true address, offset 0. + if (log) + log->Printf("Loading binary UUID %s from memory", + standalone_uuid.GetAsString().c_str()); + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + + ModuleList added_module; + added_module.Append(module_sp, false); + target.ModulesDidLoad(added_module); + } else { + if (log) + log->Printf("Unable to find binary with UUID %s and load it at " + "%s 0x%" PRIx64, + standalone_uuid.GetAsString().c_str(), + standalone_value_is_offset ? "offset" : "address", + standalone_value); + } + } + } + const StateType state = SetThreadStopInfo(response); if (state != eStateInvalid) { SetPrivateState(state); @@ -3259,9 +3344,6 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { if (platform_sp && !platform_sp->IsHost()) return Status("Lost debug server connection"); - if (repro::Reproducer::Instance().IsReplaying()) - return ConnectToReplayServer(); - auto error = LaunchAndConnectToDebugserver(process_info); if (error.Fail()) { const char *error_string = error.AsCString(); @@ -3540,7 +3622,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { // So it is safer to simply ignore any remaining packets by // explicitly checking for eStateExited before reentering the // fetch loop. - + bool done = false; while (!done && process->GetPrivateState() != eStateExited) { LLDB_LOGF(log, diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index c1b7294a7f58..cb21a3e7e65f 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -311,6 +311,11 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, error.AsCString(), error); + RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); + if (!reg_ctx_sp) + return GetInterface().ErrorWithMessage<bool>( + LLVM_PRETTY_FUNCTION, "Invalid Register Context", error); + new_thread_list.AddThread(thread_sp); return new_thread_list.GetSize(false) > 0; diff --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp index 1adbd4e7799d..959b8c581885 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -198,13 +198,17 @@ std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() { if (!m_register_info_sp) { StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo(); + + Status error; if (!reg_info) - return nullptr; + return GetInterface() + ->ErrorWithMessage<std::shared_ptr<DynamicRegisterInfo>>( + LLVM_PRETTY_FUNCTION, + "Failed to get scripted thread registers info.", error, + LIBLLDB_LOG_THREAD); m_register_info_sp = std::make_shared<DynamicRegisterInfo>( *reg_info, m_scripted_process.GetTarget().GetArchitecture()); - assert(m_register_info_sp->GetNumRegisters() > 0); - assert(m_register_info_sp->GetNumRegisterSets() > 0); } return m_register_info_sp; diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp index e99b7b88379a..b82a2647e9a0 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Lua.h" +#include "SWIGLuaBridge.h" #include "lldb/Host/FileSystem.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/Error.h" @@ -15,30 +16,6 @@ using namespace lldb_private; using namespace lldb; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" - -// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has -// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is -// incompatible with C -#if _MSC_VER -#pragma warning (push) -#pragma warning (disable : 4190) -#endif - -extern "C" llvm::Expected<bool> LLDBSwigLuaBreakpointCallbackFunction( - lua_State *L, lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp, StructuredDataImpl *extra_args_impl); - -extern "C" llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction( - lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp); - -#if _MSC_VER -#pragma warning (pop) -#endif - -#pragma clang diagnostic pop - static int lldb_print(lua_State *L) { int n = lua_gettop(L); lua_getglobal(L, "io"); @@ -105,13 +82,7 @@ Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, lua_pushlightuserdata(m_lua_state, baton); lua_gettable(m_lua_state, LUA_REGISTRYINDEX); - auto *extra_args_impl = [&]() -> StructuredDataImpl * { - if (extra_args_sp == nullptr) - return nullptr; - auto *extra_args_impl = new StructuredDataImpl(); - extra_args_impl->SetObjectSP(extra_args_sp); - return extra_args_impl; - }(); + StructuredDataImpl extra_args_impl(std::move(extra_args_sp)); return LLDBSwigLuaBreakpointCallbackFunction(m_lua_state, stop_frame_sp, bp_loc_sp, extra_args_impl); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h b/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h new file mode 100644 index 000000000000..5fca18f2dd6d --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h @@ -0,0 +1,28 @@ +//===-- SWIGLuaBridge.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_PLUGINS_SCRIPTINTERPRETER_LUA_SWIGLUABRIDGE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_LUA_SWIGLUABRIDGE_H + +#include "lldb/lldb-forward.h" +#include "lua.hpp" +#include "llvm/Support/Error.h" + +namespace lldb_private { + +llvm::Expected<bool> LLDBSwigLuaBreakpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, + lldb::BreakpointLocationSP bp_loc_sp, + const StructuredDataImpl &extra_args_impl); + +llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp); + +} // namespace lldb_private + +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_LUA_SWIGLUABRIDGE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index c7af13598843..2bb69dc47731 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -57,20 +57,20 @@ void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); void *LLDBSwigPythonCreateScriptedProcess(const char *python_class_name, const char *session_dictionary_name, const lldb::TargetSP &target_sp, - StructuredDataImpl *args_impl, + 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, - StructuredDataImpl *args_impl, + const StructuredDataImpl &args_impl, std::string &error_string); llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::BreakpointLocationSP &sb_bp_loc, - lldb_private::StructuredDataImpl *args_impl); + const lldb_private::StructuredDataImpl &args_impl); bool LLDBSwigPythonWatchpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, @@ -90,11 +90,11 @@ LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name, void *LLDBSwigPythonCreateCommandObject(const char *python_class_name, const char *session_dictionary_name, - const lldb::DebuggerSP debugger_sp); + lldb::DebuggerSP debugger_sp); void *LLDBSwigPythonCreateScriptedThreadPlan( const char *python_class_name, const char *session_dictionary_name, - lldb_private::StructuredDataImpl *args_data, std::string &error_string, + const StructuredDataImpl &args_data, std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp); bool LLDBSWIGPythonCallThreadPlan(void *implementor, const char *method_name, @@ -103,16 +103,17 @@ bool LLDBSWIGPythonCallThreadPlan(void *implementor, const char *method_name, void *LLDBSwigPythonCreateScriptedBreakpointResolver( const char *python_class_name, const char *session_dictionary_name, - lldb_private::StructuredDataImpl *args, const lldb::BreakpointSP &bkpt_sp); + const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp); unsigned int LLDBSwigPythonCallBreakpointResolver(void *implementor, const char *method_name, lldb_private::SymbolContext *sym_ctx); -void *LLDBSwigPythonCreateScriptedStopHook( - lldb::TargetSP target_sp, const char *python_class_name, - const char *session_dictionary_name, lldb_private::StructuredDataImpl *args, - lldb_private::Status &error); +void *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, @@ -136,18 +137,18 @@ PyObject *LLDBSwigPython_GetValueSynthProviderInstance(PyObject *implementor); bool LLDBSwigPythonCallCommand(const char *python_function_name, const char *session_dictionary_name, - lldb::DebuggerSP &debugger, const char *args, + lldb::DebuggerSP debugger, const char *args, lldb_private::CommandReturnObject &cmd_retobj, lldb::ExecutionContextRefSP exe_ctx_ref_sp); bool LLDBSwigPythonCallCommandObject( - PyObject *implementor, lldb::DebuggerSP &debugger, const char *args, + PyObject *implementor, lldb::DebuggerSP debugger, const char *args, lldb_private::CommandReturnObject &cmd_retobj, lldb::ExecutionContextRefSP exe_ctx_ref_sp); bool LLDBSwigPythonCallModuleInit(const char *python_module_name, const char *session_dictionary_name, - lldb::DebuggerSP &debugger); + lldb::DebuggerSP debugger); void *LLDBSWIGPythonCreateOSPlugin(const char *python_class_name, const char *session_dictionary_name, @@ -165,20 +166,20 @@ bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, const lldb::ProcessSP &process, std::string &output); -bool LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, - const char *session_dictionary_name, - lldb::ThreadSP &thread, - std::string &output); +llvm::Optional<std::string> +LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, + const char *session_dictionary_name, + lldb::ThreadSP thread); bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, const char *session_dictionary_name, const lldb::TargetSP &target, std::string &output); -bool LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, - const char *session_dictionary_name, - lldb::StackFrameSP &frame, - std::string &output); +llvm::Optional<std::string> +LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, + const char *session_dictionary_name, + lldb::StackFrameSP frame); bool LLDBSWIGPythonRunScriptKeywordValue(const char *python_function_name, const char *session_dictionary_name, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 5f282d74e364..6afa4742698b 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1718,7 +1718,7 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( } StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( - const char *class_name, StructuredDataImpl *args_data, + const char *class_name, const StructuredDataImpl &args_data, std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); @@ -1820,7 +1820,7 @@ lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( - const char *class_name, StructuredDataImpl *args_data, + const char *class_name, const StructuredDataImpl &args_data, lldb::BreakpointSP &bkpt_sp) { if (class_name == nullptr || class_name[0] == '\0') @@ -1890,8 +1890,8 @@ ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( } StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( - TargetSP target_sp, const char *class_name, StructuredDataImpl *args_data, - Status &error) { + TargetSP target_sp, const char *class_name, + const StructuredDataImpl &args_data, Status &error) { if (!target_sp) { error.SetErrorString("No target for scripted stop-hook."); @@ -2197,7 +2197,7 @@ bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( LLDBSwigPythonBreakpointCallbackFunction( python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, - bp_loc_sp, bp_option_data->m_extra_args_up.get()); + bp_loc_sp, bp_option_data->m_extra_args); if (!maybe_ret_val) { @@ -2521,7 +2521,6 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( const char *impl_function, Thread *thread, std::string &output, Status &error) { - bool ret_val; if (!thread) { error.SetErrorString("no thread"); return false; @@ -2531,16 +2530,16 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( return false; } - { - ThreadSP thread_sp(thread->shared_from_this()); - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSWIGPythonRunScriptKeywordThread( - impl_function, m_dictionary_name.c_str(), thread_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + if (llvm::Optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( + impl_function, m_dictionary_name.c_str(), + thread->shared_from_this())) { + output = std::move(*result); + return true; } - return ret_val; + error.SetErrorString("python script evaluation failed"); + return false; } bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( @@ -2571,7 +2570,6 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( const char *impl_function, StackFrame *frame, std::string &output, Status &error) { - bool ret_val; if (!frame) { error.SetErrorString("no frame"); return false; @@ -2581,16 +2579,16 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( return false; } - { - StackFrameSP frame_sp(frame->shared_from_this()); - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSWIGPythonRunScriptKeywordFrame( - impl_function, m_dictionary_name.c_str(), frame_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + if (llvm::Optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( + impl_function, m_dictionary_name.c_str(), + frame->shared_from_this())) { + output = std::move(*result); + return true; } - return ret_val; + error.SetErrorString("python script evaluation failed"); + return false; } bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( @@ -2655,7 +2653,6 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( } ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; - lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this(); // Before executing Python code, lock the GIL. Locker py_lock(this, @@ -2792,7 +2789,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( // if we are here, everything worked // call __lldb_init_module(debugger,dict) if (!LLDBSwigPythonCallModuleInit(module_name.c_str(), - m_dictionary_name.c_str(), debugger_sp)) { + m_dictionary_name.c_str(), + m_debugger.shared_from_this())) { error.SetErrorString("calling __lldb_init_module failed"); return false; } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h index 8cfc24e71283..2e8301a85eb6 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -33,13 +33,12 @@ public: CommandDataPython() : BreakpointOptions::CommandData() { interpreter = lldb::eScriptLanguagePython; } - CommandDataPython(StructuredData::ObjectSP extra_args_sp) : - BreakpointOptions::CommandData(), - m_extra_args_up(new StructuredDataImpl()) { - interpreter = lldb::eScriptLanguagePython; - m_extra_args_up->SetObjectSP(extra_args_sp); + CommandDataPython(StructuredData::ObjectSP extra_args_sp) + : BreakpointOptions::CommandData(), + m_extra_args(std::move(extra_args_sp)) { + interpreter = lldb::eScriptLanguagePython; } - lldb::StructuredDataImplUP m_extra_args_up; + StructuredDataImpl m_extra_args; }; ScriptInterpreterPython(Debugger &debugger) diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index a3f83b696ed4..defc2acffcfa 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -79,7 +79,7 @@ public: StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, - StructuredDataImpl *args_data, + const StructuredDataImpl &args_data, std::string &error_str, lldb::ThreadPlanSP thread_plan) override; @@ -99,7 +99,7 @@ public: StructuredData::GenericSP CreateScriptedBreakpointResolver(const char *class_name, - StructuredDataImpl *args_data, + const StructuredDataImpl &args_data, lldb::BreakpointSP &bkpt_sp) override; bool ScriptedBreakpointResolverSearchCallback( StructuredData::GenericSP implementor_sp, @@ -110,7 +110,8 @@ public: StructuredData::GenericSP CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, - StructuredDataImpl *args_data, Status &error) override; + const StructuredDataImpl &args_data, + Status &error) override; bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp, ExecutionContext &exc_ctx, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp index 29680dab5a14..e3c1931a565a 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -37,11 +37,7 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( return {}; TargetSP target_sp = exe_ctx.GetTargetSP(); - StructuredDataImpl *args_impl = nullptr; - if (args_sp) { - args_impl = new StructuredDataImpl(); - args_impl->SetObjectSP(args_sp); - } + StructuredDataImpl args_impl(args_sp); std::string error_string; Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp index d2c28bc426ee..6a881bfe625c 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp @@ -37,11 +37,7 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( return {}; ProcessSP process_sp = exe_ctx.GetProcessSP(); - StructuredDataImpl *args_impl = nullptr; - if (args_sp) { - args_impl = new StructuredDataImpl(); - args_impl->SetObjectSP(args_sp); - } + StructuredDataImpl args_impl(args_sp); std::string error_string; Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 4ac6e165dda3..b90f104c4d21 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1530,7 +1530,6 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( return type_sp; SymbolFileDWARF *dwarf = die.GetDWARF(); - TypeList &type_list = dwarf->GetTypeList(); DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); dw_tag_t sc_parent_tag = sc_parent_die.Tag(); @@ -1550,10 +1549,6 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( if (symbol_context_scope != nullptr) type_sp->SetSymbolContextScope(symbol_context_scope); - // We are ready to put this type into the uniqued list up at the module - // level. - type_list.Insert(type_sp); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); return type_sp; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index cece29dcf9ac..71d4c1e6c52f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -153,7 +153,7 @@ public: const DWARFAbbreviationDeclarationSet *GetAbbreviations() const; dw_offset_t GetAbbrevOffset() const; uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); } - dw_addr_t GetAddrBase() const { return m_addr_base ? *m_addr_base : 0; } + dw_addr_t GetAddrBase() const { return m_addr_base.getValueOr(0); } dw_addr_t GetBaseAddress() const { return m_base_addr; } dw_offset_t GetLineTableOffset(); dw_addr_t GetRangesBase() const { return m_ranges_base; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 8c20244a6c44..8c995ef2eb2a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1097,7 +1097,8 @@ bool SymbolFileDWARF::ParseImportedModules( if (const char *include_path = module_die.GetAttributeValueAsString( DW_AT_LLVM_include_path, nullptr)) { FileSpec include_spec(include_path, dwarf_cu->GetPathStyle()); - MakeAbsoluteAndRemap(include_spec, *dwarf_cu, m_objfile_sp->GetModule()); + MakeAbsoluteAndRemap(include_spec, *dwarf_cu, + m_objfile_sp->GetModule()); module.search_path = ConstString(include_spec.GetPath()); } if (const char *sysroot = dwarf_cu->DIE().GetAttributeValueAsString( @@ -1924,7 +1925,7 @@ void SymbolFileDWARF::ResolveFunctionAndBlock(lldb::addr_t file_vm_addr, block_die = function_die.LookupDeepestBlock(file_vm_addr); } - if (!sc.function || ! lookup_block) + if (!sc.function || !lookup_block) return; Block &block = sc.function->GetBlock(true); @@ -2319,7 +2320,8 @@ void SymbolFileDWARF::FindFunctions(ConstString name, if (log) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, sc_list)", + "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, " + "sc_list)", name.GetCString(), name_type_mask); } @@ -2352,8 +2354,7 @@ void SymbolFileDWARF::FindFunctions(ConstString name, log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " "name_type_mask=0x%x, include_inlines=%d, sc_list) => %u", - name.GetCString(), name_type_mask, include_inlines, - num_matches); + name.GetCString(), name_type_mask, include_inlines, num_matches); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 271ce7be1eea..e81ce28cb86e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -253,8 +253,8 @@ public: ExternalTypeModuleMap; /// Return the list of Clang modules imported by this SymbolFile. - const ExternalTypeModuleMap& getExternalTypeModules() const { - return m_external_type_modules; + const ExternalTypeModuleMap &getExternalTypeModules() const { + return m_external_type_modules; } virtual DWARFDIE GetDIE(const DIERef &die_ref); @@ -328,7 +328,6 @@ public: return m_parse_time; } - protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; @@ -428,9 +427,10 @@ protected: virtual lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); - virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, lldb_private::ConstString type_name, - bool must_be_implementation); + virtual lldb::TypeSP + FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE &die, + lldb_private::ConstString type_name, + bool must_be_implementation); lldb_private::Symbol * GetObjCClassSymbol(lldb_private::ConstString objc_class_name); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index c29fc2230a67..9473befa6cc3 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -30,6 +30,70 @@ using namespace lldb_private::npdb; using namespace llvm::codeview; using namespace llvm::pdb; +namespace { +struct CreateMethodDecl : public TypeVisitorCallbacks { + CreateMethodDecl(PdbIndex &m_index, TypeSystemClang &m_clang, + TypeIndex func_type_index, + clang::FunctionDecl *&function_decl, + lldb::opaque_compiler_type_t parent_ty, + llvm::StringRef proc_name, CompilerType func_ct) + : m_index(m_index), m_clang(m_clang), func_type_index(func_type_index), + function_decl(function_decl), parent_ty(parent_ty), + proc_name(proc_name), func_ct(func_ct) {} + PdbIndex &m_index; + TypeSystemClang &m_clang; + TypeIndex func_type_index; + clang::FunctionDecl *&function_decl; + lldb::opaque_compiler_type_t parent_ty; + llvm::StringRef proc_name; + CompilerType func_ct; + + llvm::Error visitKnownMember(CVMemberRecord &cvr, + OverloadedMethodRecord &overloaded) override { + TypeIndex method_list_idx = overloaded.MethodList; + + CVType method_list_type = m_index.tpi().getType(method_list_idx); + assert(method_list_type.kind() == LF_METHODLIST); + + MethodOverloadListRecord method_list; + llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>( + method_list_type, method_list)); + + for (const OneMethodRecord &method : method_list.Methods) { + if (method.getType().getIndex() == func_type_index.getIndex()) + AddMethod(overloaded.Name, method.getAccess(), method.getOptions(), + method.Attrs); + } + + return llvm::Error::success(); + } + + llvm::Error visitKnownMember(CVMemberRecord &cvr, + OneMethodRecord &record) override { + AddMethod(record.getName(), record.getAccess(), record.getOptions(), + record.Attrs); + return llvm::Error::success(); + } + + void AddMethod(llvm::StringRef name, MemberAccess access, + MethodOptions options, MemberAttributes attrs) { + if (name != proc_name || function_decl) + return; + lldb::AccessType access_type = TranslateMemberAccess(access); + bool is_virtual = attrs.isVirtual(); + bool is_static = attrs.isStatic(); + bool is_artificial = (options & MethodOptions::CompilerGenerated) == + MethodOptions::CompilerGenerated; + function_decl = m_clang.AddMethodToCXXRecordType( + parent_ty, proc_name, + /*mangled_name=*/nullptr, func_ct, /*access=*/access_type, + /*is_virtual=*/is_virtual, /*is_static=*/is_static, + /*is_inline=*/false, /*is_explicit=*/false, + /*is_attr_used=*/false, /*is_artificial=*/is_artificial); + } +}; +} // namespace + static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index, PdbCompilandSymId id) { CVSymbol sym = index.ReadSymbolRecord(id); @@ -681,7 +745,8 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) { // Visit all members of this class, then perform any finalization necessary // to complete the class. CompilerType ct = ToCompilerType(tag_qt); - UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index); + UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index, + m_cxx_record_map); auto error = llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer); completer.complete(); @@ -1014,8 +1079,62 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { proc_name.consume_front(context_name); proc_name.consume_front("::"); - clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration( - parent, OptionalClangModuleID(), proc_name, func_ct, storage, false); + clang::FunctionDecl *function_decl = nullptr; + if (parent->isRecord()) { + clang::QualType parent_qt = llvm::dyn_cast<clang::TypeDecl>(parent) + ->getTypeForDecl() + ->getCanonicalTypeInternal(); + lldb::opaque_compiler_type_t parent_opaque_ty = + ToCompilerType(parent_qt).GetOpaqueQualType(); + + auto iter = m_cxx_record_map.find(parent_opaque_ty); + if (iter != m_cxx_record_map.end()) { + if (iter->getSecond().contains({proc_name, func_ct})) { + return nullptr; + } + } + + CVType cvt = m_index.tpi().getType(type_id.index); + MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind())); + llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>( + cvt, func_record)); + TypeIndex class_index = func_record.getClassType(); + CVType parent_cvt = m_index.tpi().getType(class_index); + ClassRecord class_record = CVTagRecord::create(parent_cvt).asClass(); + // If it's a forward reference, try to get the real TypeIndex. + if (class_record.isForwardRef()) { + llvm::Expected<TypeIndex> eti = + m_index.tpi().findFullDeclForForwardRef(class_index); + if (eti) { + class_record = + CVTagRecord::create(m_index.tpi().getType(*eti)).asClass(); + } + } + if (!class_record.FieldList.isSimple()) { + CVType field_list = m_index.tpi().getType(class_record.FieldList); + CreateMethodDecl process(m_index, m_clang, type_id.index, function_decl, + parent_opaque_ty, proc_name, func_ct); + if (llvm::Error err = visitMemberRecordStream(field_list.data(), process)) + llvm::consumeError(std::move(err)); + } + + if (!function_decl) { + function_decl = m_clang.AddMethodToCXXRecordType( + parent_opaque_ty, proc_name, + /*mangled_name=*/nullptr, func_ct, + /*access=*/lldb::AccessType::eAccessPublic, + /*is_virtual=*/false, /*is_static=*/false, + /*is_inline=*/false, /*is_explicit=*/false, + /*is_attr_used=*/false, /*is_artificial=*/false); + } + + m_cxx_record_map[parent_opaque_ty].insert({proc_name, func_ct}); + } else { + function_decl = m_clang.CreateFunctionDeclaration( + parent, OptionalClangModuleID(), proc_name, func_ct, storage, false); + CreateFunctionParameters(func_id, *function_decl, + func_type->getNumParams()); + } lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0); m_uid_to_decl[toOpaqueUid(func_id)] = function_decl; @@ -1024,8 +1143,6 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { status.uid = toOpaqueUid(func_id); m_decl_to_status.insert({function_decl, status}); - CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams()); - return function_decl; } @@ -1163,15 +1280,15 @@ clang::QualType PdbAstBuilder::CreateFunctionType( } static bool isTagDecl(clang::DeclContext &context) { - return !!llvm::dyn_cast<clang::TagDecl>(&context); + return llvm::isa<clang::TagDecl>(&context); } static bool isFunctionDecl(clang::DeclContext &context) { - return !!llvm::dyn_cast<clang::FunctionDecl>(&context); + return llvm::isa<clang::FunctionDecl>(&context); } static bool isBlockDecl(clang::DeclContext &context) { - return !!llvm::dyn_cast<clang::BlockDecl>(&context); + return llvm::isa<clang::BlockDecl>(&context); } void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index 7bb2584d19a3..73accf5e5e68 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -137,6 +137,12 @@ private: llvm::DenseMap<clang::Decl *, DeclStatus> m_decl_to_status; llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl; llvm::DenseMap<lldb::user_id_t, clang::QualType> m_uid_to_type; + + // From class/struct's opaque_compiler_type_t to a set containing the pairs of + // method's name and CompilerType. + llvm::DenseMap<lldb::opaque_compiler_type_t, + llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> + m_cxx_record_map; }; } // namespace npdb diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index bf101ac1acf1..e859b1d5a86c 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -900,7 +900,7 @@ lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { return TranslateLanguage(item->m_compile_opts->getLanguage()); } -void SymbolFileNativePDB::AddSymbols(Symtab &symtab) { return; } +void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {} size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index c8fb46c75034..d0b27bc5bf79 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -28,13 +28,15 @@ using namespace lldb_private::npdb; using Error = llvm::Error; -UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id, - CompilerType &derived_ct, - clang::TagDecl &tag_decl, - PdbAstBuilder &ast_builder, - PdbIndex &index) +UdtRecordCompleter::UdtRecordCompleter( + PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl, + PdbAstBuilder &ast_builder, PdbIndex &index, + llvm::DenseMap<lldb::opaque_compiler_type_t, + llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> + &cxx_record_map) : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl), - m_ast_builder(ast_builder), m_index(index) { + m_ast_builder(ast_builder), m_index(index), + m_cxx_record_map(cxx_record_map) { CVType cvt = m_index.tpi().getType(m_id.index); switch (cvt.kind()) { case LF_ENUM: @@ -78,14 +80,24 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, clang::QualType method_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx)); m_ast_builder.CompleteType(method_qt); + CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt); + lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType(); + auto iter = m_cxx_record_map.find(derived_opaque_ty); + if (iter != m_cxx_record_map.end()) { + if (iter->getSecond().contains({name, method_ct})) { + return; + } + } lldb::AccessType access_type = TranslateMemberAccess(access); bool is_artificial = (options & MethodOptions::CompilerGenerated) == MethodOptions::CompilerGenerated; m_ast_builder.clang().AddMethodToCXXRecordType( - m_derived_ct.GetOpaqueQualType(), name.data(), nullptr, - m_ast_builder.ToCompilerType(method_qt), access_type, attrs.isVirtual(), - attrs.isStatic(), false, false, false, is_artificial); + derived_opaque_ty, name.data(), nullptr, method_ct, + access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false, + is_artificial); + + m_cxx_record_map[derived_opaque_ty].insert({name, method_ct}); } Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h index ae7e47c82fe5..9c6b5ed28bc2 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h @@ -54,11 +54,17 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { PdbIndex &m_index; std::vector<IndexedBase> m_bases; ClangASTImporter::LayoutInfo m_layout; + llvm::DenseMap<lldb::opaque_compiler_type_t, + llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> + &m_cxx_record_map; public: - UdtRecordCompleter(PdbTypeSymId id, CompilerType &derived_ct, - clang::TagDecl &tag_decl, PdbAstBuilder &ast_builder, - PdbIndex &index); + UdtRecordCompleter( + PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl, + PdbAstBuilder &ast_builder, PdbIndex &index, + llvm::DenseMap<lldb::opaque_compiler_type_t, + llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, + 8>> &cxx_record_map); #define MEMBER_RECORD(EnumName, EnumVal, Name) \ llvm::Error visitKnownMember(llvm::codeview::CVMemberRecord &CVR, \ diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index db0ae241be7e..a40b6ec9a635 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -239,7 +239,6 @@ void SymbolFilePDB::GetCompileUnitIndex( } } index = UINT32_MAX; - return; } std::unique_ptr<llvm::pdb::PDBSymbolCompiland> @@ -402,7 +401,7 @@ static size_t ParseFunctionBlocksForPDBSymbol( block = parent_block; else break; - } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) { + } else if (llvm::isa<PDBSymbolBlock>(pdb_symbol)) { auto uid = pdb_symbol->getSymIndexId(); if (parent_block->FindBlockByID(uid)) break; diff --git a/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp index 919cdf46a5c0..a72e46a0b703 100644 --- a/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp +++ b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp @@ -73,8 +73,7 @@ bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, if (thread == nullptr) { const uint32_t num_threads = process->GetThreadList().GetSize(); - size_t tid = m_options.m_thread_index ? *m_options.m_thread_index - : LLDB_INVALID_THREAD_ID; + size_t tid = m_options.m_thread_index.getValueOr(LLDB_INVALID_THREAD_ID); result.AppendErrorWithFormatv( "Thread index {0} is out of range (valid values are 1 - {1}).\n", tid, num_threads); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index b1dbc382ff04..88c3aedb4c6b 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -2581,6 +2581,7 @@ RemoveWrappingTypes(QualType type, ArrayRef<clang::Type::TypeClass> mask = {}) { case clang::Type::Typedef: case clang::Type::TypeOf: case clang::Type::TypeOfExpr: + case clang::Type::Using: type = type->getLocallyUnqualifiedSingleStepDesugaredType(); break; default: @@ -4063,6 +4064,7 @@ TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) { case clang::Type::Paren: case clang::Type::TypeOf: case clang::Type::TypeOfExpr: + case clang::Type::Using: llvm_unreachable("Handled in RemoveWrappingTypes!"); case clang::Type::UnaryTransform: break; @@ -4088,8 +4090,8 @@ TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) { return lldb::eTypeClassVector; case clang::Type::Builtin: // Ext-Int is just an integer type. - case clang::Type::ExtInt: - case clang::Type::DependentExtInt: + case clang::Type::BitInt: + case clang::Type::DependentBitInt: return lldb::eTypeClassBuiltin; case clang::Type::ObjCObjectPointer: return lldb::eTypeClassObjCObjectPointer; @@ -4722,6 +4724,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::Type::Typedef: case clang::Type::TypeOf: case clang::Type::TypeOfExpr: + case clang::Type::Using: llvm_unreachable("Handled in RemoveWrappingTypes!"); case clang::Type::UnaryTransform: @@ -4744,8 +4747,8 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, // TODO: Set this to more than one??? break; - case clang::Type::ExtInt: - case clang::Type::DependentExtInt: + case clang::Type::BitInt: + case clang::Type::DependentBitInt: return qual_type->isUnsignedIntegerType() ? lldb::eEncodingUint : lldb::eEncodingSint; @@ -5104,6 +5107,7 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) { case clang::Type::Typedef: case clang::Type::TypeOf: case clang::Type::TypeOfExpr: + case clang::Type::Using: llvm_unreachable("Handled in RemoveWrappingTypes!"); case clang::Type::UnaryTransform: break; @@ -5124,8 +5128,8 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) { case clang::Type::Vector: break; - case clang::Type::ExtInt: - case clang::Type::DependentExtInt: + case clang::Type::BitInt: + case clang::Type::DependentBitInt: return qual_type->isUnsignedIntegerType() ? lldb::eFormatUnsigned : lldb::eFormatDecimal; @@ -5145,6 +5149,8 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) { case clang::BuiltinType::UChar: case clang::BuiltinType::WChar_U: return lldb::eFormatChar; + case clang::BuiltinType::Char8: + return lldb::eFormatUnicode8; case clang::BuiltinType::Char16: return lldb::eFormatUnicode16; case clang::BuiltinType::Char32: @@ -8953,6 +8959,7 @@ bool TypeSystemClang::DumpTypeValue( case eFormatCharPrintable: case eFormatCharArray: case eFormatBytes: + case eFormatUnicode8: case eFormatBytesWithASCII: item_count = byte_size; byte_size = 1; diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index bfab741b0d66..e7b19f5e0c51 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -23,6 +23,8 @@ #include "lldb/Utility/Timer.h" #include "lldb/lldb-private.h" +#include "llvm/Support/DJB.h" + using namespace lldb; using namespace lldb_private; @@ -737,13 +739,24 @@ Symtab *ObjectFile::GetSymtab() { // not be able to access the symbol table contents since all APIs in Symtab // are protected by a mutex in the Symtab object itself. llvm::call_once(*m_symtab_once_up, [&]() { - ElapsedTime elapsed(module_sp->GetSymtabParseTime()); - Symtab *symtab = new Symtab(this); - std::lock_guard<std::recursive_mutex> symtab_guard(symtab->GetMutex()); - m_symtab_up.reset(symtab); - ParseSymtab(*m_symtab_up); - m_symtab_up->Finalize(); + Symtab *symtab = new Symtab(this); + std::lock_guard<std::recursive_mutex> symtab_guard(symtab->GetMutex()); + m_symtab_up.reset(symtab); + if (!m_symtab_up->LoadFromCache()) { + ElapsedTime elapsed(module_sp->GetSymtabParseTime()); + ParseSymtab(*m_symtab_up); + m_symtab_up->Finalize(); + } }); } return m_symtab_up.get(); } + +uint32_t ObjectFile::GetCacheHash() { + if (m_cache_hash) + return *m_cache_hash; + StreamString strm; + strm.Format("{0}-{1}-{2}", m_file, GetType(), GetStrata()); + m_cache_hash = llvm::djbHash(strm.GetString()); + return *m_cache_hash; +} diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index a8c81ee3082f..fa7226dfd046 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -17,6 +17,7 @@ #include "lldb/Symbol/Symtab.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/DataEncoder.h" #include "lldb/Utility/Stream.h" using namespace lldb; @@ -595,3 +596,131 @@ void Symbol::SynthesizeNameIfNeeded() const { m_mangled.SetDemangledName(ConstString(os.str())); } } + +bool Symbol::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + const SectionList *section_list, + const StringTableReader &strtab) { + if (!data.ValidOffsetForDataOfSize(*offset_ptr, 8)) + return false; + m_uid = data.GetU32(offset_ptr); + m_type_data = data.GetU16(offset_ptr); + const uint16_t bitfields = data.GetU16(offset_ptr); + m_type_data_resolved = (1u << 15 & bitfields) != 0; + m_is_synthetic = (1u << 14 & bitfields) != 0; + m_is_debug = (1u << 13 & bitfields) != 0; + m_is_external = (1u << 12 & bitfields) != 0; + m_size_is_sibling = (1u << 11 & bitfields) != 0; + m_size_is_synthesized = (1u << 10 & bitfields) != 0; + m_size_is_valid = (1u << 9 & bitfields) != 0; + m_demangled_is_synthesized = (1u << 8 & bitfields) != 0; + m_contains_linker_annotations = (1u << 7 & bitfields) != 0; + m_is_weak = (1u << 6 & bitfields) != 0; + m_type = bitfields & 0x003f; + if (!m_mangled.Decode(data, offset_ptr, strtab)) + return false; + if (!data.ValidOffsetForDataOfSize(*offset_ptr, 20)) + return false; + const bool is_addr = data.GetU8(offset_ptr) != 0; + const uint64_t value = data.GetU64(offset_ptr); + if (is_addr) { + m_addr_range.GetBaseAddress().ResolveAddressUsingFileSections( + value, section_list); + } else { + m_addr_range.GetBaseAddress().Clear(); + m_addr_range.GetBaseAddress().SetOffset(value); + } + m_addr_range.SetByteSize(data.GetU64(offset_ptr)); + m_flags = data.GetU32(offset_ptr); + return true; +} + +/// The encoding format for the symbol is as follows: +/// +/// uint32_t m_uid; +/// uint16_t m_type_data; +/// uint16_t bitfield_data; +/// Mangled mangled; +/// uint8_t is_addr; +/// uint64_t file_addr_or_value; +/// uint64_t size; +/// uint32_t flags; +/// +/// The only tricky thing in this encoding is encoding all of the bits in the +/// bitfields. We use a trick to store all bitfields as a 16 bit value and we +/// do the same thing when decoding the symbol. There are test that ensure this +/// encoding works for each individual bit. Everything else is very easy to +/// store. +void Symbol::Encode(DataEncoder &file, ConstStringTable &strtab) const { + file.AppendU32(m_uid); + file.AppendU16(m_type_data); + uint16_t bitfields = m_type; + if (m_type_data_resolved) + bitfields |= 1u << 15; + if (m_is_synthetic) + bitfields |= 1u << 14; + if (m_is_debug) + bitfields |= 1u << 13; + if (m_is_external) + bitfields |= 1u << 12; + if (m_size_is_sibling) + bitfields |= 1u << 11; + if (m_size_is_synthesized) + bitfields |= 1u << 10; + if (m_size_is_valid) + bitfields |= 1u << 9; + if (m_demangled_is_synthesized) + bitfields |= 1u << 8; + if (m_contains_linker_annotations) + bitfields |= 1u << 7; + if (m_is_weak) + bitfields |= 1u << 6; + file.AppendU16(bitfields); + m_mangled.Encode(file, strtab); + // A symbol's value might be an address, or it might be a constant. If the + // symbol's base address doesn't have a section, then it is a constant value. + // If it does have a section, we will encode the file address and re-resolve + // the address when we decode it. + bool is_addr = m_addr_range.GetBaseAddress().GetSection().get() != NULL; + file.AppendU8(is_addr); + file.AppendU64(m_addr_range.GetBaseAddress().GetFileAddress()); + file.AppendU64(m_addr_range.GetByteSize()); + file.AppendU32(m_flags); +} + +bool Symbol::operator==(const Symbol &rhs) const { + if (m_uid != rhs.m_uid) + return false; + if (m_type_data != rhs.m_type_data) + return false; + if (m_type_data_resolved != rhs.m_type_data_resolved) + return false; + if (m_is_synthetic != rhs.m_is_synthetic) + return false; + if (m_is_debug != rhs.m_is_debug) + return false; + if (m_is_external != rhs.m_is_external) + return false; + if (m_size_is_sibling != rhs.m_size_is_sibling) + return false; + if (m_size_is_synthesized != rhs.m_size_is_synthesized) + return false; + if (m_size_is_valid != rhs.m_size_is_valid) + return false; + if (m_demangled_is_synthesized != rhs.m_demangled_is_synthesized) + return false; + if (m_contains_linker_annotations != rhs.m_contains_linker_annotations) + return false; + if (m_is_weak != rhs.m_is_weak) + return false; + if (m_type != rhs.m_type) + return false; + if (m_mangled != rhs.m_mangled) + return false; + if (m_addr_range.GetBaseAddress() != rhs.m_addr_range.GetBaseAddress()) + return false; + if (m_addr_range.GetByteSize() != rhs.m_addr_range.GetByteSize()) + return false; + if (m_flags != rhs.m_flags) + return false; + return true; +} diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp index 53f8dd68c8b7..b85901af4d67 100644 --- a/lldb/source/Symbol/SymbolFile.cpp +++ b/lldb/source/Symbol/SymbolFile.cpp @@ -125,9 +125,7 @@ void SymbolFile::FindFunctions(const RegularExpression ®ex, void SymbolFile::GetMangledNamesForFunction( const std::string &scope_qualified_name, - std::vector<ConstString> &mangled_names) { - return; -} + std::vector<ConstString> &mangled_names) {} void SymbolFile::FindTypes( ConstString name, const CompilerDeclContext &parent_decl_ctx, @@ -147,9 +145,11 @@ void SymbolFile::AssertModuleLock() { // We assert that we have to module lock by trying to acquire the lock from a // different thread. Note that we must abort if the result is true to // guarantee correctness. - assert(std::async(std::launch::async, - [this] { return this->GetModuleMutex().try_lock(); }) - .get() == false && + assert(std::async( + std::launch::async, + [this] { + return this->GetModuleMutex().try_lock(); + }).get() == false && "Module is not locked"); #endif } diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index c67955523bfb..75450a156c28 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -9,6 +9,7 @@ #include <map> #include <set> +#include "lldb/Core/DataFileCache.h" #include "lldb/Core/Module.h" #include "lldb/Core/RichManglingContext.h" #include "lldb/Core/Section.h" @@ -17,11 +18,15 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symtab.h" #include "lldb/Target/Language.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/Endian.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DJB.h" using namespace lldb; using namespace lldb_private; @@ -109,7 +114,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order, s->Indent(); pos->Dump(s, target, std::distance(begin, pos), name_preference); } - } break; + } + break; case eSortOrderByName: { // Although we maintain a lookup by exact name map, the table isn't @@ -663,7 +669,6 @@ uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name, std::vector<uint32_t> &indexes) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - LLDB_SCOPED_TIMER(); if (symbol_name) { if (!m_name_indexes_computed) InitNameIndexes(); @@ -808,7 +813,6 @@ Symtab::FindAllSymbolsWithNameAndType(ConstString name, std::vector<uint32_t> &symbol_indexes) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - LLDB_SCOPED_TIMER(); // Initialize all of the lookup by name indexes before converting NAME to a // uniqued string NAME_STR below. if (!m_name_indexes_computed) @@ -1006,6 +1010,7 @@ void Symtab::Finalize() { collection new_symbols(m_symbols.begin(), m_symbols.end()); m_symbols.swap(new_symbols); } + SaveToCache(); } Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { @@ -1152,3 +1157,191 @@ const Symbol *Symtab::GetParent(Symbol *child_symbol) const { } return nullptr; } + +std::string Symtab::GetCacheKey() { + std::string key; + llvm::raw_string_ostream strm(key); + // Symbol table 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. + strm << m_objfile->GetModule()->GetCacheKey() << "-symtab-" + << llvm::format_hex(m_objfile->GetCacheHash(), 10); + return strm.str(); +} + +void Symtab::SaveToCache() { + DataFileCache *cache = Module::GetIndexCache(); + if (!cache) + return; // Caching is not enabled. + InitNameIndexes(); // Init the name indexes so we can cache them as well. + const auto byte_order = endian::InlHostByteOrder(); + DataEncoder file(byte_order, /*addr_size=*/8); + // Encode will return false if the symbol table's object file doesn't have + // anything to make a signature from. + if (Encode(file)) + cache->SetCachedData(GetCacheKey(), file.GetData()); +} + +constexpr llvm::StringLiteral kIdentifierCStrMap("CMAP"); + +static void EncodeCStrMap(DataEncoder &encoder, ConstStringTable &strtab, + const UniqueCStringMap<uint32_t> &cstr_map) { + encoder.AppendData(kIdentifierCStrMap); + encoder.AppendU32(cstr_map.GetSize()); + for (const auto &entry: cstr_map) { + // Make sure there are no empty strings. + assert((bool)entry.cstring); + encoder.AppendU32(strtab.Add(entry.cstring)); + encoder.AppendU32(entry.value); + } +} + +bool DecodeCStrMap(const DataExtractor &data, lldb::offset_t *offset_ptr, + const StringTableReader &strtab, + UniqueCStringMap<uint32_t> &cstr_map) { + llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4); + if (identifier != kIdentifierCStrMap) + 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))); + uint32_t value = data.GetU32(offset_ptr); + // No empty strings in the name indexes in Symtab + if (str.empty()) + return false; + cstr_map.Append(ConstString(str), value); + } + return true; +} + +constexpr llvm::StringLiteral kIdentifierSymbolTable("SYMB"); +constexpr uint32_t CURRENT_CACHE_VERSION = 1; + +/// The encoding format for the symbol table is as follows: +/// +/// Signature signature; +/// ConstStringTable strtab; +/// Identifier four character code: 'SYMB' +/// uint32_t version; +/// uint32_t num_symbols; +/// Symbol symbols[num_symbols]; +/// uint8_t num_cstr_maps; +/// UniqueCStringMap<uint32_t> cstr_maps[num_cstr_maps] +bool Symtab::Encode(DataEncoder &encoder) const { + // Name indexes must be computed before calling this function. + assert(m_name_indexes_computed); + + // Encode the object file's signature + CacheSignature signature(m_objfile); + if (!signature.Encode(encoder)) + return false; + ConstStringTable strtab; + + // Encoder the symbol table 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 symtab_encoder(encoder.GetByteOrder(), + encoder.GetAddressByteSize()); + symtab_encoder.AppendData(kIdentifierSymbolTable); + // Encode the symtab data version. + symtab_encoder.AppendU32(CURRENT_CACHE_VERSION); + // Encode the number of symbols. + symtab_encoder.AppendU32(m_symbols.size()); + // Encode the symbol data for all symbols. + for (const auto &symbol: m_symbols) + symbol.Encode(symtab_encoder, strtab); + + // Emit a byte for how many C string maps we emit. We will fix this up after + // we emit the C string maps since we skip emitting C string maps if they are + // empty. + size_t num_cmaps_offset = symtab_encoder.GetByteSize(); + uint8_t num_cmaps = 0; + symtab_encoder.AppendU8(0); + for (const auto &pair: m_name_to_symbol_indices) { + if (pair.second.IsEmpty()) + continue; + ++num_cmaps; + symtab_encoder.AppendU8(pair.first); + EncodeCStrMap(symtab_encoder, strtab, pair.second); + } + if (num_cmaps > 0) + symtab_encoder.PutU8(num_cmaps_offset, num_cmaps); + + // Now that all strings have been gathered, we will emit the string table. + strtab.Encode(encoder); + // Followed the the symbol table data. + encoder.AppendData(symtab_encoder.GetData()); + return true; +} + +bool Symtab::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + bool &signature_mismatch) { + signature_mismatch = false; + CacheSignature signature; + StringTableReader strtab; + { // Scope for "elapsed" object below so it can measure the time parse. + ElapsedTime elapsed(m_objfile->GetModule()->GetSymtabParseTime()); + if (!signature.Decode(data, offset_ptr)) + return false; + if (CacheSignature(m_objfile) != signature) { + signature_mismatch = true; + return false; + } + // We now decode the string table for all strings in the data cache file. + if (!strtab.Decode(data, offset_ptr)) + return false; + + // And now we can decode the symbol table with string table we just decoded. + llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4); + if (identifier != kIdentifierSymbolTable) + return false; + const uint32_t version = data.GetU32(offset_ptr); + if (version != CURRENT_CACHE_VERSION) + return false; + const uint32_t num_symbols = data.GetU32(offset_ptr); + if (num_symbols == 0) + return true; + m_symbols.resize(num_symbols); + SectionList *sections = m_objfile->GetModule()->GetSectionList(); + for (uint32_t i=0; i<num_symbols; ++i) { + if (!m_symbols[i].Decode(data, offset_ptr, sections, strtab)) + return false; + } + } + + { // Scope for "elapsed" object below so it can measure the time to index. + ElapsedTime elapsed(m_objfile->GetModule()->GetSymtabIndexTime()); + const uint8_t num_cstr_maps = data.GetU8(offset_ptr); + for (uint8_t i=0; i<num_cstr_maps; ++i) { + uint8_t type = data.GetU8(offset_ptr); + UniqueCStringMap<uint32_t> &cstr_map = + GetNameToSymbolIndexMap((lldb::FunctionNameType)type); + if (!DecodeCStrMap(data, offset_ptr, strtab, cstr_map)) + return false; + } + m_name_indexes_computed = true; + } + return true; +} + +bool Symtab::LoadFromCache() { + DataFileCache *cache = Module::GetIndexCache(); + if (!cache) + 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(), + m_objfile->GetByteOrder(), + m_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; +} diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 5b4169d256d2..d6c82ed1dd80 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -662,7 +662,7 @@ ConstString Type::GetQualifiedName() { return GetForwardCompilerType().GetTypeName(); } -bool Type::GetTypeScopeAndBasename(const llvm::StringRef& name, +bool Type::GetTypeScopeAndBasename(llvm::StringRef name, llvm::StringRef &scope, llvm::StringRef &basename, TypeClass &type_class) { diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index cba51d266c5b..7b4295158425 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1883,14 +1883,32 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { have_debuginfo = true; if (source_lines_before > 0 || source_lines_after > 0) { + uint32_t start_line = m_sc.line_entry.line; + if (!start_line && m_sc.function) { + FileSpec source_file; + m_sc.function->GetStartLineSourceInfo(source_file, start_line); + } + size_t num_lines = target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - m_sc.line_entry.file, m_sc.line_entry.line, - m_sc.line_entry.column, source_lines_before, - source_lines_after, "->", &strm); + m_sc.line_entry.file, start_line, m_sc.line_entry.column, + source_lines_before, source_lines_after, "->", &strm); if (num_lines != 0) have_source = true; // TODO: Give here a one time warning if source file is missing. + if (!m_sc.line_entry.line) { + ConstString fn_name = m_sc.GetFunctionName(); + + if (!fn_name.IsEmpty()) + strm.Printf( + "Note: this address is compiler-generated code in function " + "%s that has no source code associated with it.", + fn_name.AsCString()); + else + strm.Printf("Note: this address is compiler-generated code that " + "has no source code associated with it."); + strm.EOL(); + } } } switch (disasm_display) { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 28575b50cf96..fa860399aca7 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -616,12 +616,8 @@ lldb::BreakpointSP Target::CreateScriptedBreakpoint( shared_from_this()); } - StructuredDataImpl *extra_args_impl = new StructuredDataImpl(); - if (extra_args_sp) - extra_args_impl->SetObjectSP(extra_args_sp); - BreakpointResolverSP resolver_sp(new BreakpointResolverScripted( - nullptr, class_name, depth, extra_args_impl)); + nullptr, class_name, depth, StructuredDataImpl(extra_args_sp))); return CreateBreakpoint(filter_sp, resolver_sp, internal, false, true); } @@ -3321,8 +3317,7 @@ void Target::FinalizeFileActions(ProcessLaunchInfo &info) { err_file_spec); } - if (default_to_use_pty && - (!in_file_spec || !out_file_spec || !err_file_spec)) { + if (default_to_use_pty) { llvm::Error Err = info.SetUpPtyRedirection(); LLDB_LOG_ERROR(log, std::move(Err), "SetUpPtyRedirection failed: {0}"); } @@ -3485,11 +3480,7 @@ Status Target::StopHookScripted::SetScriptCallback( } m_class_name = class_name; - - m_extra_args = new StructuredDataImpl(); - - if (extra_args_sp) - m_extra_args->SetObjectSP(extra_args_sp); + m_extra_args.SetObjectSP(extra_args_sp); m_implementation_sp = script_interp->CreateScriptedStopHook( GetTarget(), m_class_name.c_str(), m_extra_args, error); @@ -3527,9 +3518,9 @@ void Target::StopHookScripted::GetSubclassDescription( // Now print the extra args: // FIXME: We should use StructuredData.GetDescription on the m_extra_args // but that seems to rely on some printing plugin that doesn't exist. - if (!m_extra_args->IsValid()) + if (!m_extra_args.IsValid()) return; - StructuredData::ObjectSP object_sp = m_extra_args->GetObjectSP(); + StructuredData::ObjectSP object_sp = m_extra_args.GetObjectSP(); if (!object_sp || !object_sp->IsValid()) return; diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 1b32331d98f7..481a39a576e9 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -1370,15 +1370,9 @@ lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted( bool abort_other_plans, const char *class_name, StructuredData::ObjectSP extra_args_sp, bool stop_other_threads, Status &status) { - - StructuredDataImpl *extra_args_impl = nullptr; - if (extra_args_sp) { - extra_args_impl = new StructuredDataImpl(); - extra_args_impl->SetObjectSP(extra_args_sp); - } - ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name, - extra_args_impl)); + ThreadPlanSP thread_plan_sp(new ThreadPlanPython( + *this, class_name, StructuredDataImpl(extra_args_sp))); thread_plan_sp->SetStopOthers(stop_other_threads); status = QueueThreadPlan(thread_plan_sp, abort_other_plans); return thread_plan_sp; diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp index cd63d28a3934..a8a36ae65c46 100644 --- a/lldb/source/Target/ThreadPlanPython.cpp +++ b/lldb/source/Target/ThreadPlanPython.cpp @@ -26,7 +26,7 @@ using namespace lldb_private; // ThreadPlanPython ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name, - StructuredDataImpl *args_data) + const StructuredDataImpl &args_data) : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread, eVoteNoOpinion, eVoteNoOpinion), m_class_name(class_name), m_args_data(args_data), m_did_push(false), @@ -36,11 +36,6 @@ ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name, SetPrivate(false); } -ThreadPlanPython::~ThreadPlanPython() { - // FIXME, do I need to decrement the ref count on this implementation object - // to make it go away? -} - bool ThreadPlanPython::ValidatePlan(Stream *error) { if (!m_did_push) return true; diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index f09583cc50cc..80634647f9e0 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -210,7 +210,6 @@ void ThreadPlanStack::DiscardAllPlans() { for (int i = stack_size - 1; i > 0; i--) { DiscardPlan(); } - return; } void ThreadPlanStack::DiscardConsultingControllingPlans() { diff --git a/lldb/source/Target/UnwindLLDB.cpp b/lldb/source/Target/UnwindLLDB.cpp index 047147112f3b..77dd19b04ebd 100644 --- a/lldb/source/Target/UnwindLLDB.cpp +++ b/lldb/source/Target/UnwindLLDB.cpp @@ -312,7 +312,6 @@ void UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid(ABI *abi) { // Restore status after calling AddOneMoreFrame m_unwind_complete = old_m_unwind_complete; m_candidate_frame = old_m_candidate_frame; - return; } bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { diff --git a/lldb/source/Utility/DataEncoder.cpp b/lldb/source/Utility/DataEncoder.cpp index e88cd23c1d84..b21453977496 100644 --- a/lldb/source/Utility/DataEncoder.cpp +++ b/lldb/source/Utility/DataEncoder.cpp @@ -8,7 +8,7 @@ #include "lldb/Utility/DataEncoder.h" -#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "llvm/Support/Endian.h" @@ -22,83 +22,26 @@ using namespace lldb; using namespace lldb_private; using namespace llvm::support::endian; -// Default constructor. DataEncoder::DataEncoder() - : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)), - m_data_sp() {} + : m_data_sp(new DataBufferHeap()), m_byte_order(endian::InlHostByteOrder()), + m_addr_size(sizeof(void *)) {} -// This constructor allows us to use data that is owned by someone else. The -// data must stay around as long as this object is valid. -DataEncoder::DataEncoder(void *data, uint32_t length, ByteOrder endian, +DataEncoder::DataEncoder(const void *data, uint32_t length, ByteOrder endian, uint8_t addr_size) - : m_start(static_cast<uint8_t *>(data)), - m_end(static_cast<uint8_t *>(data) + length), m_byte_order(endian), - m_addr_size(addr_size), m_data_sp() {} + : m_data_sp(new DataBufferHeap(data, length)), m_byte_order(endian), + m_addr_size(addr_size) {} -// Make a shared pointer reference to the shared data in "data_sp" and set the -// endian swapping setting to "swap", and the address size to "addr_size". The -// shared data reference will ensure the data lives as long as any DataEncoder -// objects exist that have a reference to this data. -DataEncoder::DataEncoder(const DataBufferSP &data_sp, ByteOrder endian, - uint8_t addr_size) - : m_start(nullptr), m_end(nullptr), m_byte_order(endian), - m_addr_size(addr_size), m_data_sp() { - SetData(data_sp); -} +DataEncoder::DataEncoder(ByteOrder endian, uint8_t addr_size) + : m_data_sp(new DataBufferHeap()), m_byte_order(endian), + m_addr_size(addr_size) {} DataEncoder::~DataEncoder() = default; -// Clears the object contents back to a default invalid state, and release any -// references to shared data that this object may contain. -void DataEncoder::Clear() { - m_start = nullptr; - m_end = nullptr; - m_byte_order = endian::InlHostByteOrder(); - m_addr_size = sizeof(void *); - m_data_sp.reset(); +llvm::ArrayRef<uint8_t> DataEncoder::GetData() const { + return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(), GetByteSize()); } -// Assign the data for this object to be a subrange of the shared data in -// "data_sp" starting "data_offset" bytes into "data_sp" and ending -// "data_length" bytes later. If "data_offset" is not a valid offset into -// "data_sp", then this object will contain no bytes. If "data_offset" is -// within "data_sp" yet "data_length" is too large, the length will be capped -// at the number of bytes remaining in "data_sp". A ref counted pointer to the -// data in "data_sp" will be made in this object IF the number of bytes this -// object refers to in greater than zero (if at least one byte was available -// starting at "data_offset") to ensure the data stays around as long as it is -// needed. The address size and endian swap settings will remain unchanged from -// their current settings. -uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset, - uint32_t data_length) { - m_start = m_end = nullptr; - - if (data_length > 0) { - m_data_sp = data_sp; - if (data_sp) { - const size_t data_size = data_sp->GetByteSize(); - if (data_offset < data_size) { - m_start = data_sp->GetBytes() + data_offset; - const size_t bytes_left = data_size - data_offset; - // Cap the length of we asked for too many - if (data_length <= bytes_left) - m_end = m_start + data_length; // We got all the bytes we wanted - else - m_end = m_start + bytes_left; // Not all the bytes requested were - // available in the shared data - } - } - } - - uint32_t new_size = GetByteSize(); - - // Don't hold a shared pointer to the data buffer if we don't share any valid - // bytes in the shared buffer. - if (new_size == 0) - m_data_sp.reset(); - - return new_size; -} +size_t DataEncoder::GetByteSize() const { return m_data_sp->GetByteSize(); } // Extract a single unsigned char from the binary data and update the offset // pointed to by "offset_ptr". @@ -106,7 +49,7 @@ uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset, // RETURNS the byte that was extracted, or zero on failure. uint32_t DataEncoder::PutU8(uint32_t offset, uint8_t value) { if (ValidOffset(offset)) { - m_start[offset] = value; + m_data_sp->GetBytes()[offset] = value; return offset + 1; } return UINT32_MAX; @@ -115,9 +58,9 @@ uint32_t DataEncoder::PutU8(uint32_t offset, uint8_t value) { uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { if (m_byte_order != endian::InlHostByteOrder()) - write16be(m_start + offset, value); + write16be(m_data_sp->GetBytes() + offset, value); else - write16le(m_start + offset, value); + write16le(m_data_sp->GetBytes() + offset, value); return offset + sizeof(value); } @@ -127,9 +70,9 @@ uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) { uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { if (m_byte_order != endian::InlHostByteOrder()) - write32be(m_start + offset, value); + write32be(m_data_sp->GetBytes() + offset, value); else - write32le(m_start + offset, value); + write32le(m_data_sp->GetBytes() + offset, value); return offset + sizeof(value); } @@ -139,9 +82,9 @@ uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) { uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { if (m_byte_order != endian::InlHostByteOrder()) - write64be(m_start + offset, value); + write64be(m_data_sp->GetBytes() + offset, value); else - write64le(m_start + offset, value); + write64le(m_data_sp->GetBytes() + offset, value); return offset + sizeof(value); } @@ -171,7 +114,7 @@ uint32_t DataEncoder::PutData(uint32_t offset, const void *src, return offset; if (ValidOffsetForDataOfSize(offset, src_len)) { - memcpy(m_start + offset, src, src_len); + memcpy(m_data_sp->GetBytes() + offset, src, src_len); return offset + src_len; } return UINT32_MAX; @@ -186,3 +129,63 @@ uint32_t DataEncoder::PutCString(uint32_t offset, const char *cstr) { return PutData(offset, cstr, strlen(cstr) + 1); return UINT32_MAX; } + +void DataEncoder::AppendU8(uint8_t value) { + m_data_sp->AppendData(&value, sizeof(value)); +} + +void DataEncoder::AppendU16(uint16_t value) { + uint32_t offset = m_data_sp->GetByteSize(); + m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value)); + PutU16(offset, value); +} + +void DataEncoder::AppendU32(uint32_t value) { + uint32_t offset = m_data_sp->GetByteSize(); + m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value)); + PutU32(offset, value); +} + +void DataEncoder::AppendU64(uint64_t value) { + uint32_t offset = m_data_sp->GetByteSize(); + m_data_sp->SetByteSize(m_data_sp->GetByteSize() + sizeof(value)); + PutU64(offset, value); +} + +void DataEncoder::AppendAddress(lldb::addr_t addr) { + switch (m_addr_size) { + case 4: + AppendU32(addr); + break; + case 8: + AppendU64(addr); + break; + default: + llvm_unreachable("AppendAddress unhandled case!"); + } +} + +void DataEncoder::AppendData(llvm::StringRef data) { + const char *bytes = data.data(); + const size_t length = data.size(); + if (bytes && length > 0) + m_data_sp->AppendData(bytes, length); +} + +void DataEncoder::AppendData(llvm::ArrayRef<uint8_t> data) { + const uint8_t *bytes = data.data(); + const size_t length = data.size(); + if (bytes && length > 0) + m_data_sp->AppendData(bytes, length); +} + +void DataEncoder::AppendCString(llvm::StringRef data) { + const char *bytes = data.data(); + const size_t length = data.size(); + if (bytes) { + if (length > 0) + m_data_sp->AppendData(bytes, length); + if (length == 0 || bytes[length - 1] != '\0') + AppendU8(0); + } +} diff --git a/lldb/source/Utility/FileSpec.cpp b/lldb/source/Utility/FileSpec.cpp index 601edb86c1b0..24f8c2b1c23f 100644 --- a/lldb/source/Utility/FileSpec.cpp +++ b/lldb/source/Utility/FileSpec.cpp @@ -310,7 +310,7 @@ llvm::Optional<FileSpec::Style> FileSpec::GuessPathStyle(llvm::StringRef absolut return Style::posix; if (absolute_path.startswith(R"(\\)")) return Style::windows; - if (absolute_path.size() > 3 && llvm::isAlpha(absolute_path[0]) && + if (absolute_path.size() >= 3 && llvm::isAlpha(absolute_path[0]) && absolute_path.substr(1, 2) == R"(:\)") return Style::windows; return llvm::None; diff --git a/lldb/source/Utility/Reproducer.cpp b/lldb/source/Utility/Reproducer.cpp index b63863c535fa..a306d6c1ef25 100644 --- a/lldb/source/Utility/Reproducer.cpp +++ b/lldb/source/Utility/Reproducer.cpp @@ -44,10 +44,6 @@ llvm::Error Reproducer::Initialize(ReproducerMode mode, } return Instance().SetCapture(root); } break; - case ReproducerMode::Replay: - return Instance().SetReplay(root, /*passive*/ false); - case ReproducerMode::PassiveReplay: - return Instance().SetReplay(root, /*passive*/ true); case ReproducerMode::Off: break; }; @@ -116,26 +112,6 @@ llvm::Error Reproducer::SetCapture(llvm::Optional<FileSpec> root) { return Error::success(); } -llvm::Error Reproducer::SetReplay(llvm::Optional<FileSpec> root, bool passive) { - std::lock_guard<std::mutex> guard(m_mutex); - - if (root && m_generator) - return make_error<StringError>( - "cannot replay a reproducer when generating one", - inconvertibleErrorCode()); - - if (!root) { - m_loader.reset(); - return Error::success(); - } - - m_loader.emplace(*root, passive); - if (auto e = m_loader->LoadIndex()) - return e; - - return Error::success(); -} - FileSpec Reproducer::GetReproducerPath() const { if (auto g = GetGenerator()) return g->GetRoot(); @@ -222,8 +198,7 @@ void Generator::AddProvidersToIndex() { } Loader::Loader(FileSpec root, bool passive) - : m_root(MakeAbsolute(std::move(root))), m_loaded(false), - m_passive_replay(passive) {} + : m_root(MakeAbsolute(std::move(root))), m_loaded(false) {} llvm::Error Loader::LoadIndex() { if (m_loaded) diff --git a/lldb/source/lldb.cpp b/lldb/source/Version/Version.cpp index 371902f6c1b5..b391fe1eacd8 100644 --- a/lldb/source/lldb.cpp +++ b/lldb/source/Version/Version.cpp @@ -1,4 +1,4 @@ -//===-- lldb.cpp ----------------------------------------------------------===// +//===-- Version.cpp -------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,23 +6,16 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Version/Version.h" #include "VCSVersion.inc" -#include "lldb/lldb-private.h" +#include "lldb/Version/Version.inc" #include "clang/Basic/Version.h" -using namespace lldb; -using namespace lldb_private; - -// LLDB_VERSION_STRING is set through a define so unlike the other defines -// expanded with CMake, it lacks the double quotes. -#define QUOTE(str) #str -#define EXPAND_AND_QUOTE(str) QUOTE(str) - static const char *GetLLDBVersion() { -#ifdef LLDB_VERSION_STRING - return EXPAND_AND_QUOTE(LLDB_VERSION_STRING); +#ifdef LLDB_FULL_VERSION_STRING + return LLDB_FULL_VERSION_STRING; #else - return "lldb version " CLANG_VERSION_STRING; + return "lldb version " LLDB_VERSION_STRING; #endif } @@ -30,7 +23,7 @@ static const char *GetLLDBRevision() { #ifdef LLDB_REVISION return LLDB_REVISION; #else - return NULL; + return nullptr; #endif } @@ -38,12 +31,13 @@ static const char *GetLLDBRepository() { #ifdef LLDB_REPOSITORY return LLDB_REPOSITORY; #else - return NULL; + return nullptr; #endif } const char *lldb_private::GetVersion() { static std::string g_version_str; + if (g_version_str.empty()) { const char *lldb_version = GetLLDBVersion(); const char *lldb_repo = GetLLDBRepository(); @@ -67,11 +61,13 @@ const char *lldb_private::GetVersion() { g_version_str += "\n clang revision "; g_version_str += clang_rev; } + std::string llvm_rev(clang::getLLVMRevision()); if (llvm_rev.length() > 0) { g_version_str += "\n llvm revision "; g_version_str += llvm_rev; } } + return g_version_str.c_str(); } |
