diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/lldb/source | |
parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb/source')
448 files changed, 14431 insertions, 8020 deletions
diff --git a/contrib/llvm-project/lldb/source/API/SBBreakpoint.cpp b/contrib/llvm-project/lldb/source/API/SBBreakpoint.cpp index 6631afb1483f..f1fb6f904f5f 100644 --- a/contrib/llvm-project/lldb/source/API/SBBreakpoint.cpp +++ b/contrib/llvm-project/lldb/source/API/SBBreakpoint.cpp @@ -25,7 +25,6 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" diff --git a/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp b/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp index 3c4aab6175c6..75b66364d4f1 100644 --- a/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp +++ b/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp @@ -18,7 +18,6 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" diff --git a/contrib/llvm-project/lldb/source/API/SBBreakpointOptionCommon.cpp b/contrib/llvm-project/lldb/source/API/SBBreakpointOptionCommon.cpp index 685ed172c820..1a14bce4cd24 100644 --- a/contrib/llvm-project/lldb/source/API/SBBreakpointOptionCommon.cpp +++ b/contrib/llvm-project/lldb/source/API/SBBreakpointOptionCommon.cpp @@ -19,7 +19,6 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Target/Process.h" diff --git a/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp b/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp index 396c0eef0603..c3cbb00145ed 100644 --- a/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp @@ -70,19 +70,21 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { SBCommandReturnObject sb_return(result); SBCommandInterpreter sb_interpreter(&m_interpreter); SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); - bool ret = m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), - sb_return); - return ret; + m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), sb_return); } std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; std::optional<std::string> m_auto_repeat_command; }; } // namespace lldb_private +SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() { + LLDB_INSTRUMENT_VA(this); +} + SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) : m_opaque_ptr(interpreter) { LLDB_INSTRUMENT_VA(this, interpreter); diff --git a/contrib/llvm-project/lldb/source/API/SBDebugger.cpp b/contrib/llvm-project/lldb/source/API/SBDebugger.cpp index 9cf464660648..fbcf30e67fc1 100644 --- a/contrib/llvm-project/lldb/source/API/SBDebugger.cpp +++ b/contrib/llvm-project/lldb/source/API/SBDebugger.cpp @@ -39,10 +39,10 @@ #include "lldb/Core/DebuggerEvents.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Progress.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Host/Config.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Host/XML.h" #include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -781,6 +781,9 @@ SBStructuredData SBDebugger::GetBuildConfiguration() { AddBoolConfigEntry( *config_up, "editline", LLDB_ENABLE_LIBEDIT, "A boolean value that indicates if editline support is enabled in LLDB"); + AddBoolConfigEntry(*config_up, "editline_wchar", LLDB_EDITLINE_USE_WCHAR, + "A boolean value that indicates if editline wide " + "characters support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "lzma", LLDB_ENABLE_LZMA, "A boolean value that indicates if lzma support is enabled in LLDB"); @@ -1538,14 +1541,11 @@ bool SBDebugger::SetCurrentPlatformSDKRoot(const char *sysroot) { bool SBDebugger::GetCloseInputOnEOF() const { LLDB_INSTRUMENT_VA(this); - return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false); + return false; } void SBDebugger::SetCloseInputOnEOF(bool b) { LLDB_INSTRUMENT_VA(this, b); - - if (m_opaque_sp) - m_opaque_sp->SetCloseInputOnEOF(b); } SBTypeCategory SBDebugger::GetCategory(const char *category_name) { diff --git a/contrib/llvm-project/lldb/source/API/SBEvent.cpp b/contrib/llvm-project/lldb/source/API/SBEvent.cpp index 13ed148e7737..f12df2939420 100644 --- a/contrib/llvm-project/lldb/source/API/SBEvent.cpp +++ b/contrib/llvm-project/lldb/source/API/SBEvent.cpp @@ -12,7 +12,6 @@ #include "lldb/Utility/Instrumentation.h" #include "lldb/Breakpoint/Breakpoint.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Target/Process.h" #include "lldb/Utility/ConstString.h" diff --git a/contrib/llvm-project/lldb/source/API/SBFormat.cpp b/contrib/llvm-project/lldb/source/API/SBFormat.cpp new file mode 100644 index 000000000000..51cddceea037 --- /dev/null +++ b/contrib/llvm-project/lldb/source/API/SBFormat.cpp @@ -0,0 +1,44 @@ +//===-- SBFormat.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/API/SBFormat.h" +#include "Utils.h" +#include "lldb/Core/FormatEntity.h" +#include "lldb/lldb-types.h" +#include <lldb/API/SBError.h> +#include <lldb/Utility/Status.h> + +using namespace lldb; +using namespace lldb_private; + +SBFormat::SBFormat() : m_opaque_sp() {} + +SBFormat::SBFormat(const SBFormat &rhs) { + m_opaque_sp = clone(rhs.m_opaque_sp); +} + +SBFormat::~SBFormat() = default; + +SBFormat &SBFormat::operator=(const SBFormat &rhs) { + if (this != &rhs) + m_opaque_sp = clone(rhs.m_opaque_sp); + return *this; +} + +SBFormat::operator bool() const { return (bool)m_opaque_sp; } + +SBFormat::SBFormat(const char *format, lldb::SBError &error) { + FormatEntrySP format_entry_sp = std::make_shared<FormatEntity::Entry>(); + Status status = FormatEntity::Parse(format, *format_entry_sp); + + error.SetError(status); + if (error.Success()) + m_opaque_sp = format_entry_sp; +} + +lldb::FormatEntrySP SBFormat::GetFormatEntrySP() const { return m_opaque_sp; } diff --git a/contrib/llvm-project/lldb/source/API/SBFrame.cpp b/contrib/llvm-project/lldb/source/API/SBFrame.cpp index a19ce63bab15..a16bbc2ae756 100644 --- a/contrib/llvm-project/lldb/source/API/SBFrame.cpp +++ b/contrib/llvm-project/lldb/source/API/SBFrame.cpp @@ -17,7 +17,6 @@ #include "Utils.h" #include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -46,6 +45,7 @@ #include "lldb/API/SBAddress.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBExpressionOptions.h" +#include "lldb/API/SBFormat.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBSymbolContext.h" #include "lldb/API/SBThread.h" @@ -948,6 +948,40 @@ SBValue SBFrame::FindRegister(const char *name) { return result; } +SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, + SBStream &output) { + Stream &strm = output.ref(); + + std::unique_lock<std::recursive_mutex> lock; + ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + + StackFrame *frame = nullptr; + Target *target = exe_ctx.GetTargetPtr(); + Process *process = exe_ctx.GetProcessPtr(); + SBError error; + + if (!format) { + error.SetErrorString("The provided SBFormat object is invalid"); + return error; + } + + if (target && process) { + Process::StopLocker stop_locker; + if (stop_locker.TryLock(&process->GetRunLock())) { + frame = exe_ctx.GetFramePtr(); + if (frame && + frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get())) { + return error; + } + } + } + error.SetErrorStringWithFormat( + "It was not possible to generate a frame " + "description with the given format string '%s'", + format.GetFormatEntrySP()->string.c_str()); + return error; +} + bool SBFrame::GetDescription(SBStream &description) { LLDB_INSTRUMENT_VA(this, description); diff --git a/contrib/llvm-project/lldb/source/API/SBHostOS.cpp b/contrib/llvm-project/lldb/source/API/SBHostOS.cpp index cb026fd9203b..a77a703bba37 100644 --- a/contrib/llvm-project/lldb/source/API/SBHostOS.cpp +++ b/contrib/llvm-project/lldb/source/API/SBHostOS.cpp @@ -101,61 +101,23 @@ lldb::thread_t SBHostOS::ThreadCreate(const char *name, lldb::thread_func_t thread_function, void *thread_arg, SBError *error_ptr) { LLDB_INSTRUMENT_VA(name, thread_function, thread_arg, error_ptr); - llvm::Expected<HostThread> thread = - ThreadLauncher::LaunchThread(name, [thread_function, thread_arg] { - return thread_function(thread_arg); - }); - if (!thread) { - if (error_ptr) - error_ptr->SetError(Status(thread.takeError())); - else - llvm::consumeError(thread.takeError()); - return LLDB_INVALID_HOST_THREAD; - } - - return thread->Release(); + return LLDB_INVALID_HOST_THREAD; } void SBHostOS::ThreadCreated(const char *name) { LLDB_INSTRUMENT_VA(name); } bool SBHostOS::ThreadCancel(lldb::thread_t thread, SBError *error_ptr) { LLDB_INSTRUMENT_VA(thread, error_ptr); - - Status error; - HostThread host_thread(thread); - error = host_thread.Cancel(); - if (error_ptr) - error_ptr->SetError(error); - host_thread.Release(); - return error.Success(); + return false; } bool SBHostOS::ThreadDetach(lldb::thread_t thread, SBError *error_ptr) { LLDB_INSTRUMENT_VA(thread, error_ptr); - - Status error; -#if defined(_WIN32) - if (error_ptr) - error_ptr->SetErrorString("ThreadDetach is not supported on this platform"); -#else - HostThread host_thread(thread); - error = host_thread.GetNativeThread().Detach(); - if (error_ptr) - error_ptr->SetError(error); - host_thread.Release(); -#endif - return error.Success(); + return false; } bool SBHostOS::ThreadJoin(lldb::thread_t thread, lldb::thread_result_t *result, SBError *error_ptr) { LLDB_INSTRUMENT_VA(thread, result, error_ptr); - - Status error; - HostThread host_thread(thread); - error = host_thread.Join(result); - if (error_ptr) - error_ptr->SetError(error); - host_thread.Release(); - return error.Success(); + return false; } diff --git a/contrib/llvm-project/lldb/source/API/SBInstruction.cpp b/contrib/llvm-project/lldb/source/API/SBInstruction.cpp index ea14e90abfd2..30703eea6fa6 100644 --- a/contrib/llvm-project/lldb/source/API/SBInstruction.cpp +++ b/contrib/llvm-project/lldb/source/API/SBInstruction.cpp @@ -19,8 +19,8 @@ #include "lldb/Core/Disassembler.h" #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" diff --git a/contrib/llvm-project/lldb/source/API/SBInstructionList.cpp b/contrib/llvm-project/lldb/source/API/SBInstructionList.cpp index ae87d7965766..3f37b984cb46 100644 --- a/contrib/llvm-project/lldb/source/API/SBInstructionList.cpp +++ b/contrib/llvm-project/lldb/source/API/SBInstructionList.cpp @@ -13,7 +13,7 @@ #include "lldb/API/SBStream.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/Stream.h" diff --git a/contrib/llvm-project/lldb/source/API/SBModule.cpp b/contrib/llvm-project/lldb/source/API/SBModule.cpp index b865502228e0..262e26c6bf43 100644 --- a/contrib/llvm-project/lldb/source/API/SBModule.cpp +++ b/contrib/llvm-project/lldb/source/API/SBModule.cpp @@ -437,26 +437,25 @@ lldb::SBType SBModule::FindFirstType(const char *name_cstr) { LLDB_INSTRUMENT_VA(this, name_cstr); ModuleSP module_sp(GetSP()); - if (!name_cstr || !module_sp) - return {}; - SymbolContext sc; - const bool exact_match = false; - ConstString name(name_cstr); + if (name_cstr && module_sp) { + ConstString name(name_cstr); + TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_find_one); + TypeResults results; + module_sp->FindTypes(query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + return SBType(type_sp); - SBType sb_type = SBType(module_sp->FindFirstType(sc, name, exact_match)); - - if (sb_type.IsValid()) - return sb_type; + auto type_system_or_err = + module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + llvm::consumeError(std::move(err)); + return {}; + } - auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (auto err = type_system_or_err.takeError()) { - llvm::consumeError(std::move(err)); - return {}; + if (auto ts = *type_system_or_err) + return SBType(ts->GetBuiltinTypeByName(name)); } - - if (auto ts = *type_system_or_err) - return SBType(ts->GetBuiltinTypeByName(name)); - return {}; } @@ -471,7 +470,7 @@ lldb::SBType SBModule::GetBasicType(lldb::BasicType type) { llvm::consumeError(std::move(err)); } else { if (auto ts = *type_system_or_err) - return SBType(ts->GetBasicTypeFromAST(type)); + return SBType(ts->GetBasicTypeFromAST(type)); } } return SBType(); @@ -485,13 +484,11 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) { ModuleSP module_sp(GetSP()); if (type && module_sp) { TypeList type_list; - const bool exact_match = false; - ConstString name(type); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_sp->FindTypes(name, exact_match, UINT32_MAX, searched_symbol_files, - type_list); - - if (type_list.Empty()) { + TypeQuery query(type); + TypeResults results; + module_sp->FindTypes(query, results); + if (results.GetTypeMap().Empty()) { + ConstString name(type); auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); if (auto err = type_system_or_err.takeError()) { @@ -502,11 +499,8 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) { retval.Append(SBType(compiler_type)); } } else { - for (size_t idx = 0; idx < type_list.GetSize(); idx++) { - TypeSP type_sp(type_list.GetTypeAtIndex(idx)); - if (type_sp) - retval.Append(SBType(type_sp)); - } + for (const TypeSP &type_sp : results.GetTypeMap().Types()) + retval.Append(SBType(type_sp)); } } return retval; diff --git a/contrib/llvm-project/lldb/source/API/SBPlatform.cpp b/contrib/llvm-project/lldb/source/API/SBPlatform.cpp index f8300a5bab30..3623fd35bcdf 100644 --- a/contrib/llvm-project/lldb/source/API/SBPlatform.cpp +++ b/contrib/llvm-project/lldb/source/API/SBPlatform.cpp @@ -7,12 +7,15 @@ //===----------------------------------------------------------------------===// #include "lldb/API/SBPlatform.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBEnvironment.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBModuleSpec.h" #include "lldb/API/SBPlatform.h" +#include "lldb/API/SBProcessInfoList.h" +#include "lldb/API/SBTarget.h" #include "lldb/API/SBUnixSignals.h" #include "lldb/Host/File.h" #include "lldb/Target/Platform.h" @@ -574,6 +577,43 @@ SBError SBPlatform::Launch(SBLaunchInfo &launch_info) { }); } +SBProcess SBPlatform::Attach(SBAttachInfo &attach_info, + const SBDebugger &debugger, SBTarget &target, + SBError &error) { + LLDB_INSTRUMENT_VA(this, attach_info, debugger, target, error); + + if (PlatformSP platform_sp = GetSP()) { + if (platform_sp->IsConnected()) { + ProcessAttachInfo &info = attach_info.ref(); + Status status; + ProcessSP process_sp = platform_sp->Attach(info, debugger.ref(), + target.GetSP().get(), status); + error.SetError(status); + return SBProcess(process_sp); + } + + error.SetErrorString("not connected"); + return {}; + } + + error.SetErrorString("invalid platform"); + return {}; +} + +SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) { + if (PlatformSP platform_sp = GetSP()) { + if (platform_sp->IsConnected()) { + ProcessInstanceInfoList list = platform_sp->GetAllProcesses(); + return SBProcessInfoList(list); + } + error.SetErrorString("not connected"); + return {}; + } + + error.SetErrorString("invalid platform"); + return {}; +} + SBError SBPlatform::Kill(const lldb::pid_t pid) { LLDB_INSTRUMENT_VA(this, pid); return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { diff --git a/contrib/llvm-project/lldb/source/API/SBProcess.cpp b/contrib/llvm-project/lldb/source/API/SBProcess.cpp index 67d08f1f02be..4864ea0e7d02 100644 --- a/contrib/llvm-project/lldb/source/API/SBProcess.cpp +++ b/contrib/llvm-project/lldb/source/API/SBProcess.cpp @@ -17,8 +17,8 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" diff --git a/contrib/llvm-project/lldb/source/API/SBProcessInfoList.cpp b/contrib/llvm-project/lldb/source/API/SBProcessInfoList.cpp new file mode 100644 index 000000000000..a711bcb58301 --- /dev/null +++ b/contrib/llvm-project/lldb/source/API/SBProcessInfoList.cpp @@ -0,0 +1,74 @@ +//===-- SBProcessInfoList.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/API/SBProcessInfoList.h" +#include "lldb/API/SBProcessInfo.h" +#include "lldb/Utility/Instrumentation.h" +#include "lldb/Utility/ProcessInfo.h" + +#include "Utils.h" + +using namespace lldb; +using namespace lldb_private; + +SBProcessInfoList::SBProcessInfoList() = default; + +SBProcessInfoList::~SBProcessInfoList() = default; + +SBProcessInfoList::SBProcessInfoList(const ProcessInfoList &impl) + : m_opaque_up(std::make_unique<ProcessInfoList>(impl)) { + LLDB_INSTRUMENT_VA(this, impl); +} + +SBProcessInfoList::SBProcessInfoList(const lldb::SBProcessInfoList &rhs) { + + LLDB_INSTRUMENT_VA(this, rhs); + + m_opaque_up = clone(rhs.m_opaque_up); +} + +const lldb::SBProcessInfoList & +SBProcessInfoList::operator=(const lldb::SBProcessInfoList &rhs) { + + LLDB_INSTRUMENT_VA(this, rhs); + + if (this != &rhs) + m_opaque_up = clone(rhs.m_opaque_up); + return *this; +} + +uint32_t SBProcessInfoList::GetSize() const { + LLDB_INSTRUMENT_VA(this); + + if (m_opaque_up) + return m_opaque_up->GetSize(); + + return 0; +} + +void SBProcessInfoList::Clear() { + LLDB_INSTRUMENT_VA(this); + + if (m_opaque_up) + m_opaque_up->Clear(); +} + +bool SBProcessInfoList::GetProcessInfoAtIndex(uint32_t idx, + SBProcessInfo &info) { + LLDB_INSTRUMENT_VA(this, idx, info); + + if (m_opaque_up) { + lldb_private::ProcessInstanceInfo process_instance_info; + if (m_opaque_up->GetProcessInfoAtIndex(idx, process_instance_info)) { + info.SetProcessInfo(process_instance_info); + return true; + } + } + + return false; +} diff --git a/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp b/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp index 68815026c464..e46f990698d8 100644 --- a/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp +++ b/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp @@ -15,7 +15,6 @@ #include "lldb/API/SBFileSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/SourceManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Utility/Stream.h" #include "lldb/Target/Target.h" diff --git a/contrib/llvm-project/lldb/source/API/SBStream.cpp b/contrib/llvm-project/lldb/source/API/SBStream.cpp index 9275a02bb62c..fc8f09a7bb9a 100644 --- a/contrib/llvm-project/lldb/source/API/SBStream.cpp +++ b/contrib/llvm-project/lldb/source/API/SBStream.cpp @@ -9,8 +9,8 @@ #include "lldb/API/SBStream.h" #include "lldb/API/SBFile.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Status.h" diff --git a/contrib/llvm-project/lldb/source/API/SBTarget.cpp b/contrib/llvm-project/lldb/source/API/SBTarget.cpp index 3fef7428abe2..8e616afbcb4e 100644 --- a/contrib/llvm-project/lldb/source/API/SBTarget.cpp +++ b/contrib/llvm-project/lldb/source/API/SBTarget.cpp @@ -37,6 +37,7 @@ #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Section.h" #include "lldb/Core/StructuredDataImpl.h" @@ -1321,27 +1322,39 @@ SBWatchpoint SBTarget::FindWatchpointByID(lldb::watch_id_t wp_id) { } lldb::SBWatchpoint SBTarget::WatchAddress(lldb::addr_t addr, size_t size, - bool read, bool write, + bool read, bool modify, SBError &error) { LLDB_INSTRUMENT_VA(this, addr, size, read, write, error); + SBWatchpointOptions options; + options.SetWatchpointTypeRead(read); + options.SetWatchpointTypeWrite(eWatchpointWriteTypeOnModify); + return WatchpointCreateByAddress(addr, size, options, error); +} + +lldb::SBWatchpoint +SBTarget::WatchpointCreateByAddress(lldb::addr_t addr, size_t size, + SBWatchpointOptions options, + SBError &error) { + LLDB_INSTRUMENT_VA(this, addr, size, options, error); + SBWatchpoint sb_watchpoint; lldb::WatchpointSP watchpoint_sp; TargetSP target_sp(GetSP()); - if (target_sp && (read || write) && addr != LLDB_INVALID_ADDRESS && - size > 0) { + uint32_t watch_type = 0; + if (options.GetWatchpointTypeRead()) + watch_type |= LLDB_WATCH_TYPE_READ; + if (options.GetWatchpointTypeWrite() == eWatchpointWriteTypeAlways) + watch_type |= LLDB_WATCH_TYPE_WRITE; + if (options.GetWatchpointTypeWrite() == eWatchpointWriteTypeOnModify) + watch_type |= LLDB_WATCH_TYPE_MODIFY; + if (watch_type == 0) { + error.SetErrorString("Can't create a watchpoint that is neither read nor " + "write nor modify."); + return sb_watchpoint; + } + if (target_sp && addr != LLDB_INVALID_ADDRESS && size > 0) { std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); - uint32_t watch_type = 0; - if (read) - watch_type |= LLDB_WATCH_TYPE_READ; - if (write) - watch_type |= LLDB_WATCH_TYPE_WRITE; - if (watch_type == 0) { - error.SetErrorString( - "Can't create a watchpoint that is neither read nor write."); - return sb_watchpoint; - } - // Target::CreateWatchpoint() is thread safe. Status cw_error; // This API doesn't take in a type, so we can't figure out what it is. @@ -1477,28 +1490,29 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple, const char *uuid_cstr, const char *symfile) { LLDB_INSTRUMENT_VA(this, path, triple, uuid_cstr, symfile); - lldb::SBModule sb_module; TargetSP target_sp(GetSP()); - if (target_sp) { - ModuleSpec module_spec; - if (path) - module_spec.GetFileSpec().SetFile(path, FileSpec::Style::native); + if (!target_sp) + return {}; - if (uuid_cstr) - module_spec.GetUUID().SetFromStringRef(uuid_cstr); + ModuleSpec module_spec; + if (path) + module_spec.GetFileSpec().SetFile(path, FileSpec::Style::native); - if (triple) - module_spec.GetArchitecture() = Platform::GetAugmentedArchSpec( - target_sp->GetPlatform().get(), triple); - else - module_spec.GetArchitecture() = target_sp->GetArchitecture(); + if (uuid_cstr) + module_spec.GetUUID().SetFromStringRef(uuid_cstr); - if (symfile) - module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native); + if (triple) + module_spec.GetArchitecture() = + Platform::GetAugmentedArchSpec(target_sp->GetPlatform().get(), triple); + else + module_spec.GetArchitecture() = target_sp->GetArchitecture(); - sb_module.SetSP(target_sp->GetOrCreateModule(module_spec, true /* notify */)); - } - return sb_module; + if (symfile) + module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native); + + SBModuleSpec sb_modulespec(module_spec); + + return AddModule(sb_modulespec); } lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) { @@ -1506,9 +1520,27 @@ lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) { lldb::SBModule sb_module; TargetSP target_sp(GetSP()); - if (target_sp) + if (target_sp) { sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up, true /* notify */)); + if (!sb_module.IsValid() && module_spec.m_opaque_up->GetUUID().IsValid()) { + Status error; + if (PluginManager::DownloadObjectAndSymbolFile(*module_spec.m_opaque_up, + error, + /* force_lookup */ true)) { + if (FileSystem::Instance().Exists( + module_spec.m_opaque_up->GetFileSpec())) { + sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up, + true /* notify */)); + } + } + } + } + // If the target hasn't initialized any architecture yet, use the + // binary's architecture. + if (sb_module.IsValid() && !target_sp->GetArchitecture().IsValid() && + sb_module.GetSP()->GetArchitecture().IsValid()) + target_sp->SetArchitecture(sb_module.GetSP()->GetArchitecture()); return sb_module; } @@ -1772,21 +1804,13 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) { TargetSP target_sp(GetSP()); if (typename_cstr && typename_cstr[0] && target_sp) { ConstString const_typename(typename_cstr); - SymbolContext sc; - const bool exact_match = false; - - const ModuleList &module_list = target_sp->GetImages(); - size_t count = module_list.GetSize(); - for (size_t idx = 0; idx < count; idx++) { - ModuleSP module_sp(module_list.GetModuleAtIndex(idx)); - if (module_sp) { - TypeSP type_sp( - module_sp->FindFirstType(sc, const_typename, exact_match)); - if (type_sp) - return SBType(type_sp); - } - } - + TypeQuery query(const_typename.GetStringRef(), + TypeQueryOptions::e_find_one); + TypeResults results; + target_sp->GetImages().FindTypes(/*search_first=*/nullptr, query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + return SBType(type_sp); // Didn't find the type in the symbols; Try the loaded language runtimes. if (auto process_sp = target_sp->GetProcessSP()) { for (auto *runtime : process_sp->GetLanguageRuntimes()) { @@ -1827,17 +1851,11 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) { if (typename_cstr && typename_cstr[0] && target_sp) { ModuleList &images = target_sp->GetImages(); ConstString const_typename(typename_cstr); - bool exact_match = false; - TypeList type_list; - llvm::DenseSet<SymbolFile *> searched_symbol_files; - images.FindTypes(nullptr, const_typename, exact_match, UINT32_MAX, - searched_symbol_files, type_list); - - for (size_t idx = 0; idx < type_list.GetSize(); idx++) { - TypeSP type_sp(type_list.GetTypeAtIndex(idx)); - if (type_sp) - sb_type_list.Append(SBType(type_sp)); - } + TypeQuery query(typename_cstr); + TypeResults results; + images.FindTypes(nullptr, query, results); + for (const TypeSP &type_sp : results.GetTypeMap().Types()) + sb_type_list.Append(SBType(type_sp)); // Try the loaded language runtimes if (auto process_sp = target_sp->GetProcessSP()) { diff --git a/contrib/llvm-project/lldb/source/API/SBThread.cpp b/contrib/llvm-project/lldb/source/API/SBThread.cpp index bd316ddf54a9..fa4c80e59d97 100644 --- a/contrib/llvm-project/lldb/source/API/SBThread.cpp +++ b/contrib/llvm-project/lldb/source/API/SBThread.cpp @@ -12,6 +12,7 @@ #include "lldb/API/SBDebugger.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFormat.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" @@ -22,7 +23,6 @@ #include "lldb/API/SBValue.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Core/ValueObject.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -181,7 +181,7 @@ size_t SBThread::GetStopReasonDataCount() { exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID( site_id)); if (bp_site_sp) - return bp_site_sp->GetNumberOfOwners() * 2; + return bp_site_sp->GetNumberOfConstituents() * 2; else return 0; // Breakpoint must have cleared itself... } break; @@ -241,7 +241,7 @@ uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) { if (bp_site_sp) { uint32_t bp_index = idx / 2; BreakpointLocationSP bp_loc_sp( - bp_site_sp->GetOwnerAtIndex(bp_index)); + bp_site_sp->GetConstituentAtIndex(bp_index)); if (bp_loc_sp) { if (idx & 1) { // Odd idx, return the breakpoint location ID @@ -1224,17 +1224,41 @@ bool SBThread::GetDescription(SBStream &description, bool stop_format) const { ExecutionContext exe_ctx(m_opaque_sp.get(), lock); if (exe_ctx.HasThreadScope()) { - exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm, - LLDB_INVALID_THREAD_ID, - stop_format); - // strm.Printf("SBThread: tid = 0x%4.4" PRIx64, - // exe_ctx.GetThreadPtr()->GetID()); + exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat( + strm, LLDB_INVALID_THREAD_ID, stop_format); } else strm.PutCString("No value"); return true; } +SBError SBThread::GetDescriptionWithFormat(const SBFormat &format, + SBStream &output) { + Stream &strm = output.ref(); + + SBError error; + if (!format) { + error.SetErrorString("The provided SBFormat object is invalid"); + return error; + } + + std::unique_lock<std::recursive_mutex> lock; + ExecutionContext exe_ctx(m_opaque_sp.get(), lock); + + if (exe_ctx.HasThreadScope()) { + if (exe_ctx.GetThreadPtr()->DumpUsingFormat( + strm, LLDB_INVALID_THREAD_ID, format.GetFormatEntrySP().get())) { + return error; + } + } + + error.SetErrorStringWithFormat( + "It was not possible to generate a thread description with the given " + "format string '%s'", + format.GetFormatEntrySP()->string.c_str()); + return error; +} + SBThread SBThread::GetExtendedBacktraceThread(const char *type) { LLDB_INSTRUMENT_VA(this, type); diff --git a/contrib/llvm-project/lldb/source/API/SBThreadPlan.cpp b/contrib/llvm-project/lldb/source/API/SBThreadPlan.cpp index 2e66ac120839..f756bca3176e 100644 --- a/contrib/llvm-project/lldb/source/API/SBThreadPlan.cpp +++ b/contrib/llvm-project/lldb/source/API/SBThreadPlan.cpp @@ -15,7 +15,6 @@ #include "lldb/API/SBSymbolContext.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/CompileUnit.h" diff --git a/contrib/llvm-project/lldb/source/API/SBType.cpp b/contrib/llvm-project/lldb/source/API/SBType.cpp index ee5b64474280..ac0e56303fae 100644 --- a/contrib/llvm-project/lldb/source/API/SBType.cpp +++ b/contrib/llvm-project/lldb/source/API/SBType.cpp @@ -586,6 +586,14 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) { return eTemplateArgumentKindNull; } +SBType SBType::FindDirectNestedType(const char *name) { + LLDB_INSTRUMENT_VA(this, name); + + if (!IsValid()) + return SBType(); + return SBType(m_opaque_sp->FindDirectNestedType(name)); +} + SBTypeList::SBTypeList() : m_opaque_up(new TypeListImpl()) { LLDB_INSTRUMENT_VA(this); } diff --git a/contrib/llvm-project/lldb/source/API/SBUnixSignals.cpp b/contrib/llvm-project/lldb/source/API/SBUnixSignals.cpp index 7cccbaff1d2f..519881b186e4 100644 --- a/contrib/llvm-project/lldb/source/API/SBUnixSignals.cpp +++ b/contrib/llvm-project/lldb/source/API/SBUnixSignals.cpp @@ -66,7 +66,7 @@ const char *SBUnixSignals::GetSignalAsCString(int32_t signo) const { LLDB_INSTRUMENT_VA(this, signo); if (auto signals_sp = GetSP()) - return ConstString(signals_sp->GetSignalAsCString(signo)).GetCString(); + return ConstString(signals_sp->GetSignalAsStringRef(signo)).GetCString(); return nullptr; } diff --git a/contrib/llvm-project/lldb/source/API/SBValue.cpp b/contrib/llvm-project/lldb/source/API/SBValue.cpp index e8ed36380d37..34d01d759ba5 100644 --- a/contrib/llvm-project/lldb/source/API/SBValue.cpp +++ b/contrib/llvm-project/lldb/source/API/SBValue.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/Declaration.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -115,7 +114,7 @@ public: Target *target = value_sp->GetTargetSP().get(); // If this ValueObject holds an error, then it is valuable for that. - if (value_sp->GetError().Fail()) + if (value_sp->GetError().Fail()) return value_sp; if (!target) @@ -1039,8 +1038,8 @@ lldb::ValueObjectSP SBValue::GetSP(ValueLocker &locker) const { // IsValid means that the SBValue has a value in it. But that's not the // only time that ValueObjects are useful. We also want to return the value // if there's an error state in it. - if (!m_opaque_sp || (!m_opaque_sp->IsValid() - && (m_opaque_sp->GetRootSP() + if (!m_opaque_sp || (!m_opaque_sp->IsValid() + && (m_opaque_sp->GetRootSP() && !m_opaque_sp->GetRootSP()->GetError().Fail()))) { locker.GetError().SetErrorString("No value"); return ValueObjectSP(); @@ -1434,10 +1433,17 @@ lldb::SBWatchpoint SBValue::Watch(bool resolve_location, bool read, bool write, return sb_watchpoint; uint32_t watch_type = 0; - if (read) + if (read) { watch_type |= LLDB_WATCH_TYPE_READ; - if (write) - watch_type |= LLDB_WATCH_TYPE_WRITE; + // read + write, the most likely intention + // is to catch all writes to this, not just + // value modifications. + if (write) + watch_type |= LLDB_WATCH_TYPE_WRITE; + } else { + if (write) + watch_type |= LLDB_WATCH_TYPE_MODIFY; + } Status rc; CompilerType type(value_sp->GetCompilerType()); @@ -1499,3 +1505,14 @@ lldb::SBValue SBValue::Persist() { } return persisted_sb; } + +lldb::SBValue SBValue::GetVTable() { + SBValue vtable_sb; + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (!value_sp) + return vtable_sb; + + vtable_sb.SetSP(value_sp->GetVTable()); + return vtable_sb; +} diff --git a/contrib/llvm-project/lldb/source/API/SBWatchpoint.cpp b/contrib/llvm-project/lldb/source/API/SBWatchpoint.cpp index f5a7f53a8b30..9664bbe61860 100644 --- a/contrib/llvm-project/lldb/source/API/SBWatchpoint.cpp +++ b/contrib/llvm-project/lldb/source/API/SBWatchpoint.cpp @@ -16,7 +16,6 @@ #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Breakpoint/WatchpointList.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -95,16 +94,11 @@ SBError SBWatchpoint::GetError() { int32_t SBWatchpoint::GetHardwareIndex() { LLDB_INSTRUMENT_VA(this); - int32_t hw_index = -1; - - lldb::WatchpointSP watchpoint_sp(GetSP()); - if (watchpoint_sp) { - std::lock_guard<std::recursive_mutex> guard( - watchpoint_sp->GetTarget().GetAPIMutex()); - hw_index = watchpoint_sp->GetHardwareIndex(); - } - - return hw_index; + // For processes using gdb remote protocol, + // we cannot determine the hardware breakpoint + // index reliably; providing possibly correct + // guesses is not useful to anyone. + return -1; } addr_t SBWatchpoint::GetWatchAddress() { @@ -148,9 +142,9 @@ void SBWatchpoint::SetEnabled(bool enabled) { const bool notify = true; if (process_sp) { if (enabled) - process_sp->EnableWatchpoint(watchpoint_sp.get(), notify); + process_sp->EnableWatchpoint(watchpoint_sp, notify); else - process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); + process_sp->DisableWatchpoint(watchpoint_sp, notify); } else { watchpoint_sp->SetEnabled(enabled, notify); } @@ -355,7 +349,8 @@ bool SBWatchpoint::IsWatchingWrites() { std::lock_guard<std::recursive_mutex> guard( watchpoint_sp->GetTarget().GetAPIMutex()); - return watchpoint_sp->WatchpointWrite(); + return watchpoint_sp->WatchpointWrite() || + watchpoint_sp->WatchpointModify(); } return false; diff --git a/contrib/llvm-project/lldb/source/API/SBWatchpointOptions.cpp b/contrib/llvm-project/lldb/source/API/SBWatchpointOptions.cpp new file mode 100644 index 000000000000..62e9c21a8579 --- /dev/null +++ b/contrib/llvm-project/lldb/source/API/SBWatchpointOptions.cpp @@ -0,0 +1,73 @@ +//===-- SBWatchpointOptions.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/API/SBWatchpointOptions.h" +#include "lldb/Breakpoint/Watchpoint.h" +#include "lldb/Utility/Instrumentation.h" + +#include "Utils.h" + +using namespace lldb; +using namespace lldb_private; + +class WatchpointOptionsImpl { +public: + bool m_read = false; + bool m_write = false; + bool m_modify = false; +}; + + +SBWatchpointOptions::SBWatchpointOptions() + : m_opaque_up(new WatchpointOptionsImpl()) { + LLDB_INSTRUMENT_VA(this); +} + +SBWatchpointOptions::SBWatchpointOptions(const SBWatchpointOptions &rhs) { + LLDB_INSTRUMENT_VA(this, rhs); + + m_opaque_up = clone(rhs.m_opaque_up); +} + +const SBWatchpointOptions & +SBWatchpointOptions::operator=(const SBWatchpointOptions &rhs) { + LLDB_INSTRUMENT_VA(this, rhs); + + if (this != &rhs) + m_opaque_up = clone(rhs.m_opaque_up); + return *this; +} + +SBWatchpointOptions::~SBWatchpointOptions() = default; + +void SBWatchpointOptions::SetWatchpointTypeRead(bool read) { + m_opaque_up->m_read = read; +} +bool SBWatchpointOptions::GetWatchpointTypeRead() const { + return m_opaque_up->m_read; +} + +void SBWatchpointOptions::SetWatchpointTypeWrite( + WatchpointWriteType write_type) { + if (write_type == eWatchpointWriteTypeOnModify) { + m_opaque_up->m_write = false; + m_opaque_up->m_modify = true; + } else if (write_type == eWatchpointWriteTypeAlways) { + m_opaque_up->m_write = true; + m_opaque_up->m_modify = false; + } else + m_opaque_up->m_write = m_opaque_up->m_modify = false; +} + +WatchpointWriteType SBWatchpointOptions::GetWatchpointTypeWrite() const { + if (m_opaque_up->m_modify) + return eWatchpointWriteTypeOnModify; + if (m_opaque_up->m_write) + return eWatchpointWriteTypeAlways; + return eWatchpointWriteTypeDisabled; +} diff --git a/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp b/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp index 27319debc858..c48466f25ede 100644 --- a/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp +++ b/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp @@ -68,9 +68,6 @@ llvm::Error SystemInitializerFull::Initialize() { #define LLDB_PLUGIN(p) LLDB_PLUGIN_INITIALIZE(p); #include "Plugins/Plugins.def" - // Initialize plug-ins in core LLDB - ProcessTrace::Initialize(); - // Scan for any system or user LLDB plug-ins PluginManager::Initialize(); diff --git a/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp b/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp index 9f00c967be43..6e6b51b56249 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp @@ -205,10 +205,9 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData( if (success && names_array) { size_t num_names = names_array->GetSize(); for (size_t i = 0; i < num_names; i++) { - llvm::StringRef name; - Status error; - success = names_array->GetItemAtIndexAsString(i, name); - target.AddNameToBreakpoint(result_sp, name.str().c_str(), error); + if (std::optional<llvm::StringRef> maybe_name = + names_array->GetItemAtIndexAsString(i)) + target.AddNameToBreakpoint(result_sp, *maybe_name, error); } } @@ -238,11 +237,10 @@ bool Breakpoint::SerializedBreakpointMatchesNames( size_t num_names = names_array->GetSize(); for (size_t i = 0; i < num_names; i++) { - llvm::StringRef name; - if (names_array->GetItemAtIndexAsString(i, name)) { - if (llvm::is_contained(names, name)) - return true; - } + std::optional<llvm::StringRef> maybe_name = + names_array->GetItemAtIndexAsString(i); + if (maybe_name && llvm::is_contained(names, *maybe_name)) + return true; } return false; } @@ -413,7 +411,7 @@ const char *Breakpoint::GetConditionText() const { void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous) { // The default "Baton" class will keep a copy of "baton" and won't free or - // delete it when it goes goes out of scope. + // delete it when it goes out of scope. m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton), is_synchronous); @@ -841,9 +839,8 @@ bool Breakpoint::HasResolvedLocations() const { size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); } -bool Breakpoint::AddName(llvm::StringRef new_name) { +void Breakpoint::AddName(llvm::StringRef new_name) { m_name_list.insert(new_name.str()); - return true; } void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp index 3ead1eca6913..99f94d04bb31 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -204,7 +204,7 @@ bool BreakpointLocation::IsCallbackSynchronous() { void BreakpointLocation::SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous) { // The default "Baton" class will keep a copy of "baton" and won't free or - // delete it when it goes goes out of scope. + // delete it when it goes out of scope. GetLocationOptions().SetCallback( callback, std::make_shared<UntypedBaton>(baton), is_synchronous); SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged); @@ -250,6 +250,7 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, DiagnosticManager diagnostics; if (condition_hash != m_condition_hash || !m_user_expression_sp || + !m_user_expression_sp->IsParseCacheable() || !m_user_expression_sp->MatchesContext(exe_ctx)) { LanguageType language = eLanguageTypeUnknown; // See if we can figure out the language from the frame, otherwise use the @@ -472,10 +473,10 @@ bool BreakpointLocation::ClearBreakpointSite() { // physical implementation of the breakpoint as well if there are no more // owners. Otherwise just remove this owner. if (process_sp) - process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(), - GetID(), m_bp_site_sp); + process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(), + GetID(), m_bp_site_sp); else - m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID()); + m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID()); m_bp_site_sp.reset(); return true; @@ -626,22 +627,19 @@ void BreakpointLocation::Dump(Stream *s) const { bool is_resolved = IsResolved(); bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); - auto hardware_index = is_resolved ? - m_bp_site_sp->GetHardwareIndex() : LLDB_INVALID_INDEX32; lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) .GetThreadSpecNoCreate() ->GetTID(); s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " - "hw_index = %i hit_count = %-4u ignore_count = %-4u", + "hit_count = %-4u ignore_count = %-4u", GetID(), tid, (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()), (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled", - is_hardware ? "hardware" : "software", hardware_index, - GetHitCount(), + is_hardware ? "hardware" : "software", GetHitCount(), GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) .GetIgnoreCount()); } diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointName.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointName.cpp index cb513fb436d6..5a4aad172fc0 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointName.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointName.cpp @@ -28,13 +28,6 @@ const Flags::ValueType BreakpointName::Permissions::permissions_mask (0x5u) }; -BreakpointName::BreakpointName(ConstString name, const Breakpoint &bkpt, - const char *help) : - m_name(name), m_options(bkpt.GetOptions()) -{ - SetHelp(help); -} - bool BreakpointName::Permissions::GetDescription(Stream *s, lldb::DescriptionLevel level) { if (!AnySet()) diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp index 268c52341dfe..6c6037dd9edd 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp @@ -88,10 +88,9 @@ BreakpointOptions::CommandData::CreateFromStructuredData( if (success) { size_t num_elems = user_source->GetSize(); for (size_t i = 0; i < num_elems; i++) { - llvm::StringRef elem_string; - success = user_source->GetItemAtIndexAsString(i, elem_string); - if (success) - data_up->user_source.AppendString(elem_string); + if (std::optional<llvm::StringRef> maybe_elem_string = + user_source->GetItemAtIndexAsString(i)) + data_up->user_source.AppendString(*maybe_elem_string); } } diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp index c1e77d3c70da..89ea308b1eb0 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp @@ -110,27 +110,26 @@ BreakpointResolverSP BreakpointResolver::CreateFromStructuredData( return result_sp; } - BreakpointResolver *resolver = nullptr; switch (resolver_type) { case FileLineResolver: - resolver = BreakpointResolverFileLine::CreateFromStructuredData( - nullptr, *subclass_options, error); + result_sp = BreakpointResolverFileLine::CreateFromStructuredData( + *subclass_options, error); break; case AddressResolver: - resolver = BreakpointResolverAddress::CreateFromStructuredData( - nullptr, *subclass_options, error); + result_sp = BreakpointResolverAddress::CreateFromStructuredData( + *subclass_options, error); break; case NameResolver: - resolver = BreakpointResolverName::CreateFromStructuredData( - nullptr, *subclass_options, error); + result_sp = BreakpointResolverName::CreateFromStructuredData( + *subclass_options, error); break; case FileRegexResolver: - resolver = BreakpointResolverFileRegex::CreateFromStructuredData( - nullptr, *subclass_options, error); + result_sp = BreakpointResolverFileRegex::CreateFromStructuredData( + *subclass_options, error); break; case PythonResolver: - resolver = BreakpointResolverScripted::CreateFromStructuredData( - nullptr, *subclass_options, error); + result_sp = BreakpointResolverScripted::CreateFromStructuredData( + *subclass_options, error); break; case ExceptionResolver: error.SetErrorString("Exception resolvers are hard."); @@ -139,12 +138,12 @@ BreakpointResolverSP BreakpointResolver::CreateFromStructuredData( llvm_unreachable("Should never get an unresolvable resolver type."); } - if (!resolver || error.Fail()) - return result_sp; + if (error.Fail() || !result_sp) + return {}; // Add on the global offset option: - resolver->SetOffset(offset); - return BreakpointResolverSP(resolver); + result_sp->SetOffset(offset); + return result_sp; } StructuredData::DictionarySP BreakpointResolver::WrapOptionsDict( diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverAddress.cpp index 26f289103bb8..a0c628a8e299 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverAddress.cpp @@ -30,9 +30,8 @@ BreakpointResolverAddress::BreakpointResolverAddress(const BreakpointSP &bkpt, : BreakpointResolver(bkpt, BreakpointResolver::AddressResolver), m_addr(addr), m_resolved_addr(LLDB_INVALID_ADDRESS) {} -BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData( - const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, - Status &error) { +BreakpointResolverSP BreakpointResolverAddress::CreateFromStructuredData( + const StructuredData::Dictionary &options_dict, Status &error) { llvm::StringRef module_name; lldb::offset_t addr_offset; FileSpec module_filespec; @@ -56,7 +55,8 @@ BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData( } module_filespec.SetFile(module_name, FileSpec::Style::native); } - return new BreakpointResolverAddress(bkpt, address, module_filespec); + return std::make_shared<BreakpointResolverAddress>(nullptr, address, + module_filespec); } StructuredData::ObjectSP diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index 04374decd363..cc4e1d26724f 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -30,9 +30,8 @@ BreakpointResolverFileLine::BreakpointResolverFileLine( m_location_spec(location_spec), m_skip_prologue(skip_prologue), m_removed_prefix_opt(removed_prefix_opt) {} -BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData( - const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, - Status &error) { +BreakpointResolverSP BreakpointResolverFileLine::CreateFromStructuredData( + const StructuredData::Dictionary &options_dict, Status &error) { llvm::StringRef filename; uint32_t line; uint16_t column; @@ -90,8 +89,8 @@ BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData( if (!location_spec) return nullptr; - return new BreakpointResolverFileLine(bkpt, offset, skip_prologue, - location_spec); + return std::make_shared<BreakpointResolverFileLine>( + nullptr, offset, skip_prologue, location_spec); } StructuredData::ObjectSP @@ -207,7 +206,7 @@ void BreakpointResolverFileLine::DeduceSourceMapping( [path_separator](llvm::StringRef a, llvm::StringRef b, bool case_sensitive) -> std::optional<llvm::StringRef> { if (case_sensitive ? a.consume_back(b) : a.consume_back_insensitive(b)) { - if (a.empty() || a.endswith(path_separator)) { + if (a.empty() || a.ends_with(path_separator)) { return a; } } diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp index cb3ee5fb7427..06d346afb9f6 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -26,9 +26,8 @@ BreakpointResolverFileRegex::BreakpointResolverFileRegex( m_regex(std::move(regex)), m_exact_match(exact_match), m_function_names(func_names) {} -BreakpointResolver *BreakpointResolverFileRegex::CreateFromStructuredData( - const lldb::BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, - Status &error) { +BreakpointResolverSP BreakpointResolverFileRegex::CreateFromStructuredData( + const StructuredData::Dictionary &options_dict, Status &error) { bool success; llvm::StringRef regex_string; @@ -56,19 +55,19 @@ BreakpointResolver *BreakpointResolverFileRegex::CreateFromStructuredData( if (success && names_array) { size_t num_names = names_array->GetSize(); for (size_t i = 0; i < num_names; i++) { - llvm::StringRef name; - success = names_array->GetItemAtIndexAsString(i, name); - if (!success) { + std::optional<llvm::StringRef> maybe_name = + names_array->GetItemAtIndexAsString(i); + if (!maybe_name) { error.SetErrorStringWithFormat( "BRFR::CFSD: Malformed element %zu in the names array.", i); return nullptr; } - names_set.insert(std::string(name)); + names_set.insert(std::string(*maybe_name)); } } - return new BreakpointResolverFileRegex(bkpt, std::move(regex), names_set, - exact_match); + return std::make_shared<BreakpointResolverFileRegex>( + nullptr, std::move(regex), names_set, exact_match); } StructuredData::ObjectSP diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp index b533bdfb9c11..82eef43ad6cf 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -56,12 +56,10 @@ BreakpointResolverName::BreakpointResolverName( } } -BreakpointResolverName::BreakpointResolverName(const BreakpointSP &bkpt, - std::vector<std::string> names, - FunctionNameType name_type_mask, - LanguageType language, - lldb::addr_t offset, - bool skip_prologue) +BreakpointResolverName::BreakpointResolverName( + const BreakpointSP &bkpt, const std::vector<std::string> &names, + FunctionNameType name_type_mask, LanguageType language, lldb::addr_t offset, + bool skip_prologue) : BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset), m_match_type(Breakpoint::Exact), m_language(language), m_skip_prologue(skip_prologue) { @@ -88,9 +86,8 @@ BreakpointResolverName::BreakpointResolverName( m_regex(rhs.m_regex), m_match_type(rhs.m_match_type), m_language(rhs.m_language), m_skip_prologue(rhs.m_skip_prologue) {} -BreakpointResolver *BreakpointResolverName::CreateFromStructuredData( - const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, - Status &error) { +BreakpointResolverSP BreakpointResolverName::CreateFromStructuredData( + const StructuredData::Dictionary &options_dict, Status &error) { LanguageType language = eLanguageTypeUnknown; llvm::StringRef language_name; bool success = options_dict.GetValueForKeyAsString( @@ -124,8 +121,9 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData( success = options_dict.GetValueForKeyAsString( GetKey(OptionNames::RegexString), regex_text); if (success) { - return new BreakpointResolverName(bkpt, RegularExpression(regex_text), - language, offset, skip_prologue); + return std::make_shared<BreakpointResolverName>( + nullptr, RegularExpression(regex_text), language, offset, + skip_prologue); } else { StructuredData::Array *names_array; success = options_dict.GetValueForKeyAsArray( @@ -157,10 +155,9 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData( std::vector<std::string> names; std::vector<FunctionNameType> name_masks; for (size_t i = 0; i < num_elem; i++) { - llvm::StringRef name; - - success = names_array->GetItemAtIndexAsString(i, name); - if (!success) { + std::optional<llvm::StringRef> maybe_name = + names_array->GetItemAtIndexAsString(i); + if (!maybe_name) { error.SetErrorString("BRN::CFSD: name entry is not a string."); return nullptr; } @@ -170,17 +167,18 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData( error.SetErrorString("BRN::CFSD: name mask entry is not an integer."); return nullptr; } - names.push_back(std::string(name)); + names.push_back(std::string(*maybe_name)); name_masks.push_back(static_cast<FunctionNameType>(fnt)); } - BreakpointResolverName *resolver = new BreakpointResolverName( - bkpt, names[0].c_str(), name_masks[0], language, - Breakpoint::MatchType::Exact, offset, skip_prologue); + std::shared_ptr<BreakpointResolverName> resolver_sp = + std::make_shared<BreakpointResolverName>( + nullptr, names[0].c_str(), name_masks[0], language, + Breakpoint::MatchType::Exact, offset, skip_prologue); for (size_t i = 1; i < num_elem; i++) { - resolver->AddNameLookup(ConstString(names[i]), name_masks[i]); + resolver_sp->AddNameLookup(ConstString(names[i]), name_masks[i]); } - return resolver; + return resolver_sp; } } diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverScripted.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverScripted.cpp index 308c3b987f58..dbfa8b8572f2 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverScripted.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverScripted.cpp @@ -58,13 +58,11 @@ void BreakpointResolverScripted::NotifyBreakpointSet() { CreateImplementationIfNeeded(GetBreakpoint()); } -BreakpointResolver * -BreakpointResolverScripted::CreateFromStructuredData( - const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, - Status &error) { +BreakpointResolverSP BreakpointResolverScripted::CreateFromStructuredData( + const StructuredData::Dictionary &options_dict, Status &error) { llvm::StringRef class_name; bool success; - + success = options_dict.GetValueForKeyAsString( GetKey(OptionNames::PythonClassName), class_name); if (!success) { @@ -80,8 +78,8 @@ BreakpointResolverScripted::CreateFromStructuredData( 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); + return std::make_shared<BreakpointResolverScripted>(nullptr, class_name, + depth, args_data_impl); } StructuredData::ObjectSP diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSite.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSite.cpp index 11ebc59c7e12..3ca93f908e30 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSite.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSite.cpp @@ -12,14 +12,12 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/BreakpointSiteList.h" #include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; -BreakpointSite::BreakpointSite(BreakpointSiteList *list, - const BreakpointLocationSP &owner, +BreakpointSite::BreakpointSite(const BreakpointLocationSP &constituent, lldb::addr_t addr, bool use_hardware) : StoppointSite(GetNextID(), addr, 0, use_hardware), m_type(eSoftware), // Process subclasses need to set this correctly using @@ -28,14 +26,14 @@ BreakpointSite::BreakpointSite(BreakpointSiteList *list, m_enabled(false) // Need to create it disabled, so the first enable turns // it on. { - m_owners.Add(owner); + m_constituents.Add(constituent); } BreakpointSite::~BreakpointSite() { BreakpointLocationSP bp_loc_sp; - const size_t owner_count = m_owners.GetSize(); - for (size_t i = 0; i < owner_count; i++) { - m_owners.GetByIndex(i)->ClearBreakpointSite(); + const size_t constituent_count = m_constituents.GetSize(); + for (size_t i = 0; i < constituent_count; i++) { + m_constituents.GetByIndex(i)->ClearBreakpointSite(); } } @@ -49,23 +47,23 @@ break_id_t BreakpointSite::GetNextID() { bool BreakpointSite::ShouldStop(StoppointCallbackContext *context) { m_hit_counter.Increment(); - // ShouldStop can do a lot of work, and might even come come back and hit - // this breakpoint site again. So don't hold the m_owners_mutex the whole - // while. Instead make a local copy of the collection and call ShouldStop on - // the copy. - BreakpointLocationCollection owners_copy; + // ShouldStop can do a lot of work, and might even come back and hit + // this breakpoint site again. So don't hold the m_constituents_mutex the + // whole while. Instead make a local copy of the collection and call + // ShouldStop on the copy. + BreakpointLocationCollection constituents_copy; { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - owners_copy = m_owners; + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + constituents_copy = m_constituents; } - return owners_copy.ShouldStop(context); + return constituents_copy.ShouldStop(context); } bool BreakpointSite::IsBreakpointAtThisSite(lldb::break_id_t bp_id) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - const size_t owner_count = m_owners.GetSize(); - for (size_t i = 0; i < owner_count; i++) { - if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + const size_t constituent_count = m_constituents.GetSize(); + for (size_t i = 0; i < constituent_count; i++) { + if (m_constituents.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) return true; } return false; @@ -76,20 +74,20 @@ void BreakpointSite::Dump(Stream *s) const { return; s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 - " type = %s breakpoint hw_index = %i hit_count = %-4u", + " type = %s breakpoint hit_count = %-4u", GetID(), (uint64_t)m_addr, IsHardware() ? "hardware" : "software", - GetHardwareIndex(), GetHitCount()); + GetHitCount()); } void BreakpointSite::GetDescription(Stream *s, lldb::DescriptionLevel level) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); if (level != lldb::eDescriptionLevelBrief) s->Printf("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress()); - m_owners.GetDescription(s, level); + m_constituents.GetDescription(s, level); } -bool BreakpointSite::IsInternal() const { return m_owners.IsInternal(); } +bool BreakpointSite::IsInternal() const { return m_constituents.IsInternal(); } uint8_t *BreakpointSite::GetTrapOpcodeBytes() { return &m_trap_opcode[0]; } @@ -122,36 +120,36 @@ bool BreakpointSite::IsEnabled() const { return m_enabled; } void BreakpointSite::SetEnabled(bool enabled) { m_enabled = enabled; } -void BreakpointSite::AddOwner(const BreakpointLocationSP &owner) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - m_owners.Add(owner); +void BreakpointSite::AddConstituent(const BreakpointLocationSP &constituent) { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + m_constituents.Add(constituent); } -size_t BreakpointSite::RemoveOwner(lldb::break_id_t break_id, - lldb::break_id_t break_loc_id) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - m_owners.Remove(break_id, break_loc_id); - return m_owners.GetSize(); +size_t BreakpointSite::RemoveConstituent(lldb::break_id_t break_id, + lldb::break_id_t break_loc_id) { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + m_constituents.Remove(break_id, break_loc_id); + return m_constituents.GetSize(); } -size_t BreakpointSite::GetNumberOfOwners() { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - return m_owners.GetSize(); +size_t BreakpointSite::GetNumberOfConstituents() { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + return m_constituents.GetSize(); } -BreakpointLocationSP BreakpointSite::GetOwnerAtIndex(size_t index) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - return m_owners.GetByIndex(index); +BreakpointLocationSP BreakpointSite::GetConstituentAtIndex(size_t index) { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + return m_constituents.GetByIndex(index); } bool BreakpointSite::ValidForThisThread(Thread &thread) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - return m_owners.ValidForThisThread(thread); + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + return m_constituents.ValidForThisThread(thread); } void BreakpointSite::BumpHitCounts() { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) { loc_sp->BumpHitCount(); } } @@ -198,10 +196,10 @@ bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, return true; } -size_t -BreakpointSite::CopyOwnersList(BreakpointLocationCollection &out_collection) { - std::lock_guard<std::recursive_mutex> guard(m_owners_mutex); - for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) { +size_t BreakpointSite::CopyConstituentsList( + BreakpointLocationCollection &out_collection) { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) { out_collection.Add(loc_sp); } return out_collection.GetSize(); diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSiteList.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSiteList.cpp deleted file mode 100644 index ab15da82ea45..000000000000 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointSiteList.cpp +++ /dev/null @@ -1,193 +0,0 @@ -//===-- BreakpointSiteList.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/Breakpoint/BreakpointSiteList.h" - -#include "lldb/Utility/Stream.h" -#include <algorithm> - -using namespace lldb; -using namespace lldb_private; - -BreakpointSiteList::BreakpointSiteList() = default; - -BreakpointSiteList::~BreakpointSiteList() = default; - -// Add breakpoint site to the list. However, if the element already exists in -// the list, then we don't add it, and return LLDB_INVALID_BREAK_ID. - -lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) { - lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); - std::lock_guard<std::recursive_mutex> guard(m_mutex); - collection::iterator iter = m_bp_site_list.find(bp_site_load_addr); - - if (iter == m_bp_site_list.end()) { - m_bp_site_list.insert(iter, collection::value_type(bp_site_load_addr, bp)); - return bp->GetID(); - } else { - return LLDB_INVALID_BREAK_ID; - } -} - -bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context, - lldb::break_id_t site_id) { - BreakpointSiteSP site_sp(FindByID(site_id)); - if (site_sp) { - // Let the BreakpointSite decide if it should stop here (could not have - // reached it's target hit count yet, or it could have a callback that - // decided it shouldn't stop (shared library loads/unloads). - return site_sp->ShouldStop(context); - } - // We should stop here since this BreakpointSite isn't valid anymore or it - // doesn't exist. - return true; -} -lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) { - if (BreakpointSiteSP bp = FindByAddress(addr)) - return bp.get()->GetID(); - return LLDB_INVALID_BREAK_ID; -} - -bool BreakpointSiteList::Remove(lldb::break_id_t break_id) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - collection::iterator pos = GetIDIterator(break_id); // Predicate - if (pos != m_bp_site_list.end()) { - m_bp_site_list.erase(pos); - return true; - } - return false; -} - -bool BreakpointSiteList::RemoveByAddress(lldb::addr_t address) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - collection::iterator pos = m_bp_site_list.find(address); - if (pos != m_bp_site_list.end()) { - m_bp_site_list.erase(pos); - return true; - } - return false; -} - -class BreakpointSiteIDMatches { -public: - BreakpointSiteIDMatches(lldb::break_id_t break_id) : m_break_id(break_id) {} - - bool operator()(std::pair<lldb::addr_t, BreakpointSiteSP> val_pair) const { - return m_break_id == val_pair.second->GetID(); - } - -private: - const lldb::break_id_t m_break_id; -}; - -BreakpointSiteList::collection::iterator -BreakpointSiteList::GetIDIterator(lldb::break_id_t break_id) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return std::find_if(m_bp_site_list.begin(), - m_bp_site_list.end(), // Search full range - BreakpointSiteIDMatches(break_id)); // Predicate -} - -BreakpointSiteList::collection::const_iterator -BreakpointSiteList::GetIDConstIterator(lldb::break_id_t break_id) const { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return std::find_if(m_bp_site_list.begin(), - m_bp_site_list.end(), // Search full range - BreakpointSiteIDMatches(break_id)); // Predicate -} - -BreakpointSiteSP BreakpointSiteList::FindByID(lldb::break_id_t break_id) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - BreakpointSiteSP stop_sp; - collection::iterator pos = GetIDIterator(break_id); - if (pos != m_bp_site_list.end()) - stop_sp = pos->second; - - return stop_sp; -} - -const BreakpointSiteSP -BreakpointSiteList::FindByID(lldb::break_id_t break_id) const { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - BreakpointSiteSP stop_sp; - collection::const_iterator pos = GetIDConstIterator(break_id); - if (pos != m_bp_site_list.end()) - stop_sp = pos->second; - - return stop_sp; -} - -BreakpointSiteSP BreakpointSiteList::FindByAddress(lldb::addr_t addr) { - BreakpointSiteSP found_sp; - std::lock_guard<std::recursive_mutex> guard(m_mutex); - collection::iterator iter = m_bp_site_list.find(addr); - if (iter != m_bp_site_list.end()) - found_sp = iter->second; - return found_sp; -} - -bool BreakpointSiteList::BreakpointSiteContainsBreakpoint( - lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - collection::const_iterator pos = GetIDConstIterator(bp_site_id); - if (pos != m_bp_site_list.end()) - return pos->second->IsBreakpointAtThisSite(bp_id); - - return false; -} - -void BreakpointSiteList::Dump(Stream *s) const { - s->Printf("%p: ", static_cast<const void *>(this)); - // s->Indent(); - s->Printf("BreakpointSiteList with %u BreakpointSites:\n", - (uint32_t)m_bp_site_list.size()); - s->IndentMore(); - collection::const_iterator pos; - collection::const_iterator end = m_bp_site_list.end(); - for (pos = m_bp_site_list.begin(); pos != end; ++pos) - pos->second->Dump(s); - s->IndentLess(); -} - -void BreakpointSiteList::ForEach( - std::function<void(BreakpointSite *)> const &callback) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - for (auto pair : m_bp_site_list) - callback(pair.second.get()); -} - -bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound, - lldb::addr_t upper_bound, - BreakpointSiteList &bp_site_list) const { - if (lower_bound > upper_bound) - return false; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - collection::const_iterator lower, upper, pos; - lower = m_bp_site_list.lower_bound(lower_bound); - if (lower == m_bp_site_list.end() || (*lower).first >= upper_bound) - return false; - - // This is one tricky bit. The breakpoint might overlap the bottom end of - // the range. So we grab the breakpoint prior to the lower bound, and check - // that that + its byte size isn't in our range. - if (lower != m_bp_site_list.begin()) { - collection::const_iterator prev_pos = lower; - prev_pos--; - const BreakpointSiteSP &prev_bp = (*prev_pos).second; - if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) - bp_site_list.Add(prev_bp); - } - - upper = m_bp_site_list.upper_bound(upper_bound); - - for (pos = lower; pos != upper; pos++) { - bp_site_list.Add((*pos).second); - } - return true; -} diff --git a/contrib/llvm-project/lldb/source/Breakpoint/StopPointSiteList.cpp b/contrib/llvm-project/lldb/source/Breakpoint/StopPointSiteList.cpp new file mode 100644 index 000000000000..275d0fbf265a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Breakpoint/StopPointSiteList.cpp @@ -0,0 +1,37 @@ +//===-- StopPointSiteList.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/Breakpoint/StopPointSiteList.h" +#include "lldb/Breakpoint/BreakpointSite.h" +#include "lldb/Breakpoint/WatchpointResource.h" + +#include "lldb/Utility/Stream.h" +#include <algorithm> + +using namespace lldb; +using namespace lldb_private; + +// This method is only defined when we're specializing for +// BreakpointSite / BreakpointLocation / Breakpoint. +// Watchpoints don't have a similar structure, they are +// WatchpointResource / Watchpoint + +template <> +bool StopPointSiteList<BreakpointSite>::StopPointSiteContainsBreakpoint( + typename BreakpointSite::SiteID site_id, lldb::break_id_t bp_id) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + typename collection::const_iterator pos = GetIDConstIterator(site_id); + if (pos != m_site_list.end()) + return pos->second->IsBreakpointAtThisSite(bp_id); + + return false; +} + +namespace lldb_private { +template class StopPointSiteList<BreakpointSite>; +} // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Breakpoint/StoppointSite.cpp b/contrib/llvm-project/lldb/source/Breakpoint/StoppointSite.cpp index ba8c48326bdb..a28b6b927a1f 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/StoppointSite.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/StoppointSite.cpp @@ -13,11 +13,10 @@ using namespace lldb; using namespace lldb_private; StoppointSite::StoppointSite(break_id_t id, addr_t addr, bool hardware) - : m_id(id), m_addr(addr), m_is_hardware_required(hardware), - m_hardware_index(LLDB_INVALID_INDEX32), m_byte_size(0), m_hit_counter() {} + : m_id(id), m_addr(addr), m_is_hardware_required(hardware), m_byte_size(0), + m_hit_counter() {} -StoppointSite::StoppointSite(break_id_t id, addr_t addr, - uint32_t byte_size, bool hardware) +StoppointSite::StoppointSite(break_id_t id, addr_t addr, uint32_t byte_size, + bool hardware) : m_id(id), m_addr(addr), m_is_hardware_required(hardware), - m_hardware_index(LLDB_INVALID_INDEX32), m_byte_size(byte_size), - m_hit_counter() {} + m_byte_size(byte_size), m_hit_counter() {} diff --git a/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp b/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp index a20a4ad98c5a..4602ce4213b9 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp @@ -9,9 +9,11 @@ #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Breakpoint/WatchpointResource.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectMemory.h" +#include "lldb/DataFormatters/DumpValueObjectOptions.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Process.h" @@ -29,7 +31,8 @@ Watchpoint::Watchpoint(Target &target, lldb::addr_t addr, uint32_t size, : StoppointSite(0, addr, size, hardware), m_target(target), m_enabled(false), m_is_hardware(hardware), m_is_watch_variable(false), m_is_ephemeral(false), m_disabled_count(0), m_watch_read(0), - m_watch_write(0), m_ignore_count(0), m_being_created(true) { + m_watch_write(0), m_watch_modify(0), m_ignore_count(0), + m_being_created(true) { if (type && type->IsValid()) m_type = *type; @@ -66,7 +69,7 @@ Watchpoint::~Watchpoint() = default; void Watchpoint::SetCallback(WatchpointHitCallback callback, void *baton, bool is_synchronous) { // The default "Baton" class will keep a copy of "baton" and won't free or - // delete it when it goes goes out of scope. + // delete it when it goes out of scope. m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton), is_synchronous); @@ -160,7 +163,7 @@ bool Watchpoint::VariableWatchpointDisabler(void *baton, "callback for watchpoint %" PRId32 " matched internal breakpoint execution context", watch_sp->GetID()); - process_sp->DisableWatchpoint(watch_sp.get()); + process_sp->DisableWatchpoint(watch_sp); return false; } LLDB_LOGF(log, @@ -193,7 +196,7 @@ bool Watchpoint::IsWatchVariable() const { return m_is_watch_variable; } void Watchpoint::SetWatchVariable(bool val) { m_is_watch_variable = val; } bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) { - ConstString watch_name("$__lldb__watch_value"); + ConstString g_watch_name("$__lldb__watch_value"); m_old_value_sp = m_new_value_sp; Address watch_address(GetLoadAddress()); if (!m_type.IsValid()) { @@ -205,12 +208,47 @@ bool Watchpoint::CaptureWatchedValue(const ExecutionContext &exe_ctx) { return false; } m_new_value_sp = ValueObjectMemory::Create( - exe_ctx.GetBestExecutionContextScope(), watch_name.GetStringRef(), + exe_ctx.GetBestExecutionContextScope(), g_watch_name.GetStringRef(), watch_address, m_type); - m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name); + m_new_value_sp = m_new_value_sp->CreateConstantValue(g_watch_name); return (m_new_value_sp && m_new_value_sp->GetError().Success()); } +bool Watchpoint::WatchedValueReportable(const ExecutionContext &exe_ctx) { + if (!m_watch_modify || m_watch_read) + return true; + if (!m_type.IsValid()) + return true; + + ConstString g_watch_name("$__lldb__watch_value"); + Address watch_address(GetLoadAddress()); + ValueObjectSP newest_valueobj_sp = ValueObjectMemory::Create( + exe_ctx.GetBestExecutionContextScope(), g_watch_name.GetStringRef(), + watch_address, m_type); + newest_valueobj_sp = newest_valueobj_sp->CreateConstantValue(g_watch_name); + Status error; + + DataExtractor new_data; + DataExtractor old_data; + + newest_valueobj_sp->GetData(new_data, error); + if (error.Fail()) + return true; + m_new_value_sp->GetData(old_data, error); + if (error.Fail()) + return true; + + if (new_data.GetByteSize() != old_data.GetByteSize() || + new_data.GetByteSize() == 0) + return true; + + if (memcmp(new_data.GetDataStart(), old_data.GetDataStart(), + old_data.GetByteSize()) == 0) + return false; // Value has not changed, user requested modify watchpoint + + return true; +} + // RETURNS - true if we should stop at this breakpoint, false if we // should continue. @@ -230,33 +268,69 @@ void Watchpoint::Dump(Stream *s) const { // If prefix is nullptr, we display the watch id and ignore the prefix // altogether. -void Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const { - if (!prefix) { - s->Printf("\nWatchpoint %u hit:", GetID()); - prefix = ""; - } +bool Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const { + bool printed_anything = false; + + // For read watchpoints, don't display any before/after value changes. + if (m_watch_read && !m_watch_modify && !m_watch_write) + return printed_anything; + + s->Printf("\n"); + s->Printf("Watchpoint %u hit:\n", GetID()); + + StreamString values_ss; + if (prefix) + values_ss.Indent(prefix); if (m_old_value_sp) { - const char *old_value_cstr = m_old_value_sp->GetValueAsCString(); - if (old_value_cstr && old_value_cstr[0]) - s->Printf("\n%sold value: %s", prefix, old_value_cstr); - else { - const char *old_summary_cstr = m_old_value_sp->GetSummaryAsCString(); - if (old_summary_cstr && old_summary_cstr[0]) - s->Printf("\n%sold value: %s", prefix, old_summary_cstr); + if (auto *old_value_cstr = m_old_value_sp->GetValueAsCString()) { + values_ss.Printf("old value: %s", old_value_cstr); + } else { + if (auto *old_summary_cstr = m_old_value_sp->GetSummaryAsCString()) + values_ss.Printf("old value: %s", old_summary_cstr); + else { + StreamString strm; + DumpValueObjectOptions options; + options.SetUseDynamicType(eNoDynamicValues) + .SetHideRootType(true) + .SetHideRootName(true) + .SetHideName(true); + m_old_value_sp->Dump(strm, options); + if (strm.GetData()) + values_ss.Printf("old value: %s", strm.GetData()); + } } } if (m_new_value_sp) { - const char *new_value_cstr = m_new_value_sp->GetValueAsCString(); - if (new_value_cstr && new_value_cstr[0]) - s->Printf("\n%snew value: %s", prefix, new_value_cstr); + if (values_ss.GetSize()) + values_ss.Printf("\n"); + + if (auto *new_value_cstr = m_new_value_sp->GetValueAsCString()) + values_ss.Printf("new value: %s", new_value_cstr); else { - const char *new_summary_cstr = m_new_value_sp->GetSummaryAsCString(); - if (new_summary_cstr && new_summary_cstr[0]) - s->Printf("\n%snew value: %s", prefix, new_summary_cstr); + if (auto *new_summary_cstr = m_new_value_sp->GetSummaryAsCString()) + values_ss.Printf("new value: %s", new_summary_cstr); + else { + StreamString strm; + DumpValueObjectOptions options; + options.SetUseDynamicType(eNoDynamicValues) + .SetHideRootType(true) + .SetHideRootName(true) + .SetHideName(true); + m_new_value_sp->Dump(strm, options); + if (strm.GetData()) + values_ss.Printf("new value: %s", strm.GetData()); + } } } + + if (values_ss.GetSize()) { + s->Printf("%s", values_ss.GetData()); + printed_anything = true; + } + + return printed_anything; } void Watchpoint::DumpWithLevel(Stream *s, @@ -268,10 +342,10 @@ void Watchpoint::DumpWithLevel(Stream *s, description_level <= lldb::eDescriptionLevelVerbose); s->Printf("Watchpoint %u: addr = 0x%8.8" PRIx64 - " size = %u state = %s type = %s%s", + " size = %u state = %s type = %s%s%s", GetID(), GetLoadAddress(), m_byte_size, IsEnabled() ? "enabled" : "disabled", m_watch_read ? "r" : "", - m_watch_write ? "w" : ""); + m_watch_write ? "w" : "", m_watch_modify ? "m" : ""); if (description_level >= lldb::eDescriptionLevelFull) { if (!m_decl_str.empty()) @@ -288,8 +362,8 @@ void Watchpoint::DumpWithLevel(Stream *s, } if (description_level >= lldb::eDescriptionLevelVerbose) { - s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u", - GetHardwareIndex(), GetHitCount(), GetIgnoreCount()); + s->Printf("\n hit_count = %-4u ignore_count = %-4u", GetHitCount(), + GetIgnoreCount()); } } @@ -314,9 +388,7 @@ bool Watchpoint::IsDisabledDuringEphemeralMode() { void Watchpoint::SetEnabled(bool enabled, bool notify) { if (!enabled) { - if (!m_is_ephemeral) - SetHardwareIndex(LLDB_INVALID_INDEX32); - else + if (m_is_ephemeral) ++m_disabled_count; // Don't clear the snapshots for now. @@ -333,10 +405,13 @@ void Watchpoint::SetEnabled(bool enabled, bool notify) { void Watchpoint::SetWatchpointType(uint32_t type, bool notify) { int old_watch_read = m_watch_read; int old_watch_write = m_watch_write; + int old_watch_modify = m_watch_modify; m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0; m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0; + m_watch_modify = (type & LLDB_WATCH_TYPE_MODIFY) != 0; if (notify && - (old_watch_read != m_watch_read || old_watch_write != m_watch_write)) + (old_watch_read != m_watch_read || old_watch_write != m_watch_write || + old_watch_modify != m_watch_modify)) SendWatchpointChangedEvent(eWatchpointEventTypeTypeChanged); } @@ -344,6 +419,8 @@ bool Watchpoint::WatchpointRead() const { return m_watch_read != 0; } bool Watchpoint::WatchpointWrite() const { return m_watch_write != 0; } +bool Watchpoint::WatchpointModify() const { return m_watch_modify != 0; } + uint32_t Watchpoint::GetIgnoreCount() const { return m_ignore_count; } void Watchpoint::SetIgnoreCount(uint32_t n) { diff --git a/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResource.cpp b/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResource.cpp new file mode 100644 index 000000000000..d0f8dc346f3c --- /dev/null +++ b/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResource.cpp @@ -0,0 +1,124 @@ +//===-- WatchpointResource.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 <assert.h> + +#include "lldb/Breakpoint/WatchpointResource.h" + +#include <algorithm> + +using namespace lldb; +using namespace lldb_private; + +WatchpointResource::WatchpointResource(lldb::addr_t addr, size_t size, + bool read, bool write) + : m_id(GetNextID()), m_addr(addr), m_size(size), + m_watch_read(read), m_watch_write(write) {} + +WatchpointResource::~WatchpointResource() { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + m_constituents.clear(); +} + +addr_t WatchpointResource::GetLoadAddress() const { return m_addr; } + +size_t WatchpointResource::GetByteSize() const { return m_size; } + +bool WatchpointResource::WatchpointResourceRead() const { return m_watch_read; } + +bool WatchpointResource::WatchpointResourceWrite() const { + return m_watch_write; +} + +void WatchpointResource::SetType(bool read, bool write) { + m_watch_read = read; + m_watch_write = write; +} + +wp_resource_id_t WatchpointResource::GetID() const { return m_id; } + +void WatchpointResource::SetID(wp_resource_id_t id) { m_id = id; } + +bool WatchpointResource::Contains(addr_t addr) { + if (addr >= m_addr && addr < m_addr + m_size) + return true; + return false; +} + +void WatchpointResource::AddConstituent(const WatchpointSP &wp_sp) { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + m_constituents.push_back(wp_sp); +} + +void WatchpointResource::RemoveConstituent(WatchpointSP &wp_sp) { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + const auto &it = + std::find(m_constituents.begin(), m_constituents.end(), wp_sp); + if (it != m_constituents.end()) + m_constituents.erase(it); +} + +size_t WatchpointResource::GetNumberOfConstituents() { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + return m_constituents.size(); +} + +bool WatchpointResource::ConstituentsContains(const WatchpointSP &wp_sp) { + return ConstituentsContains(wp_sp.get()); +} + +bool WatchpointResource::ConstituentsContains(const Watchpoint *wp) { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + WatchpointCollection::const_iterator match = + std::find_if(m_constituents.begin(), m_constituents.end(), + [&wp](const WatchpointSP &x) { return x.get() == wp; }); + return match != m_constituents.end(); +} + +WatchpointSP WatchpointResource::GetConstituentAtIndex(size_t idx) { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + assert(idx < m_constituents.size()); + if (idx >= m_constituents.size()) + return {}; + + return m_constituents[idx]; +} + +WatchpointResource::WatchpointCollection +WatchpointResource::CopyConstituentsList() { + std::lock_guard<std::mutex> guard(m_constituents_mutex); + return m_constituents; +} + +bool WatchpointResource::ShouldStop(StoppointCallbackContext *context) { + // LWP_TODO: Need to poll all Watchpoint constituents and see if + // we should stop, like BreakpointSites do. +#if 0 + m_hit_counter.Increment(); + // ShouldStop can do a lot of work, and might even come back and hit + // this breakpoint site again. So don't hold the m_constituents_mutex the + // whole while. Instead make a local copy of the collection and call + // ShouldStop on the copy. + WatchpointResourceCollection constituents_copy; + { + std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); + constituents_copy = m_constituents; + } + return constituents_copy.ShouldStop(context); +#endif + return true; +} + +void WatchpointResource::Dump(Stream *s) const { + return; // LWP_TODO +} + +wp_resource_id_t WatchpointResource::GetNextID() { + static wp_resource_id_t g_next_id = 0; + return ++g_next_id; +} diff --git a/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResourceList.cpp b/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResourceList.cpp new file mode 100644 index 000000000000..d1d364832098 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResourceList.cpp @@ -0,0 +1,114 @@ +//===-- WatchpointResourceList.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/Breakpoint/WatchpointResourceList.h" +#include "lldb/Breakpoint/WatchpointResource.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +using namespace lldb; +using namespace lldb_private; + +WatchpointResourceList::WatchpointResourceList() : m_resources(), m_mutex() {} + +WatchpointResourceList::~WatchpointResourceList() { Clear(); } + +wp_resource_id_t +WatchpointResourceList::Add(const WatchpointResourceSP &wp_res_sp) { + Log *log = GetLog(LLDBLog::Watchpoints); + std::lock_guard<std::mutex> guard(m_mutex); + LLDB_LOGF(log, "WatchpointResourceList::Add(addr 0x%" PRIx64 " size %zu)", + wp_res_sp->GetLoadAddress(), wp_res_sp->GetByteSize()); + + m_resources.push_back(wp_res_sp); + return wp_res_sp->GetID(); +} + +bool WatchpointResourceList::Remove(wp_resource_id_t id) { + std::lock_guard<std::mutex> guard(m_mutex); + Log *log = GetLog(LLDBLog::Watchpoints); + for (collection::iterator pos = m_resources.begin(); pos != m_resources.end(); + ++pos) { + if ((*pos)->GetID() == id) { + LLDB_LOGF(log, + "WatchpointResourceList::Remove(addr 0x%" PRIx64 " size %zu)", + (*pos)->GetLoadAddress(), (*pos)->GetByteSize()); + m_resources.erase(pos); + return true; + } + } + return false; +} + +bool WatchpointResourceList::RemoveByAddress(addr_t addr) { + std::lock_guard<std::mutex> guard(m_mutex); + Log *log = GetLog(LLDBLog::Watchpoints); + for (collection::iterator pos = m_resources.begin(); pos != m_resources.end(); + ++pos) { + if ((*pos)->Contains(addr)) { + LLDB_LOGF(log, + "WatchpointResourceList::RemoveByAddress(addr 0x%" PRIx64 + " size %zu)", + (*pos)->GetLoadAddress(), (*pos)->GetByteSize()); + m_resources.erase(pos); + return true; + } + } + return false; +} + +WatchpointResourceSP WatchpointResourceList::FindByAddress(addr_t addr) { + std::lock_guard<std::mutex> guard(m_mutex); + for (WatchpointResourceSP wp_res_sp : m_resources) + if (wp_res_sp->Contains(addr)) + return wp_res_sp; + return {}; +} + +WatchpointResourceSP +WatchpointResourceList::FindByWatchpointSP(WatchpointSP &wp_sp) { + return FindByWatchpoint(wp_sp.get()); +} + +WatchpointResourceSP +WatchpointResourceList::FindByWatchpoint(const Watchpoint *wp) { + std::lock_guard<std::mutex> guard(m_mutex); + for (WatchpointResourceSP wp_res_sp : m_resources) + if (wp_res_sp->ConstituentsContains(wp)) + return wp_res_sp; + return {}; +} + +WatchpointResourceSP WatchpointResourceList::FindByID(wp_resource_id_t id) { + std::lock_guard<std::mutex> guard(m_mutex); + for (WatchpointResourceSP wp_res_sp : m_resources) + if (wp_res_sp->GetID() == id) + return wp_res_sp; + return {}; +} + +uint32_t WatchpointResourceList::GetSize() { + std::lock_guard<std::mutex> guard(m_mutex); + return m_resources.size(); +} + +lldb::WatchpointResourceSP +WatchpointResourceList::GetResourceAtIndex(uint32_t idx) { + std::lock_guard<std::mutex> guard(m_mutex); + if (idx < m_resources.size()) + return m_resources[idx]; + + return {}; +} + +void WatchpointResourceList::Clear() { + std::lock_guard<std::mutex> guard(m_mutex); + m_resources.clear(); +} + +std::mutex &WatchpointResourceList::GetMutex() { return m_mutex; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp b/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp index 4d7e3d7f2497..16078a92ab5f 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandCompletions.cpp @@ -44,7 +44,7 @@ typedef void (*CompletionCallback)(CommandInterpreter &interpreter, lldb_private::SearchFilter *searcher); struct CommonCompletionElement { - uint32_t type; + uint64_t type; CompletionCallback callback; }; @@ -54,6 +54,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( bool handled = false; const CommonCompletionElement common_completions[] = { + {lldb::eNoCompletion, nullptr}, {lldb::eSourceFileCompletion, CommandCompletions::SourceFiles}, {lldb::eDiskFileCompletion, CommandCompletions::DiskFiles}, {lldb::eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, @@ -83,12 +84,13 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( CommandCompletions::RemoteDiskDirectories}, {lldb::eTypeCategoryNameCompletion, CommandCompletions::TypeCategoryNames}, - {lldb::CompletionType::eNoCompletion, + {lldb::eThreadIDCompletion, CommandCompletions::ThreadIDs}, + {lldb::eTerminatorCompletion, nullptr} // This one has to be last in the list. }; for (int i = 0;; i++) { - if (common_completions[i].type == lldb::eNoCompletion) + if (common_completions[i].type == lldb::eTerminatorCompletion) break; else if ((common_completions[i].type & completion_mask) == common_completions[i].type && @@ -333,7 +335,7 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, llvm::StringRef SearchDir; llvm::StringRef PartialItem; - if (CompletionBuffer.startswith("~")) { + if (CompletionBuffer.starts_with("~")) { llvm::StringRef Buffer = CompletionBuffer; size_t FirstSep = Buffer.find_if([](char c) { return path::is_separator(c); }); @@ -422,7 +424,7 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, auto Name = path::filename(Entry.path()); // Omit ".", ".." - if (Name == "." || Name == ".." || !Name.startswith(PartialItem)) + if (Name == "." || Name == ".." || !Name.starts_with(PartialItem)) continue; bool is_dir = Status->isDirectory(); @@ -606,7 +608,7 @@ void CommandCompletions::Registers(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher) { std::string reg_prefix; - if (request.GetCursorArgumentPrefix().startswith("$")) + if (request.GetCursorArgumentPrefix().starts_with("$")) reg_prefix = "$"; RegisterContext *reg_ctx = @@ -807,6 +809,23 @@ void CommandCompletions::TypeCategoryNames(CommandInterpreter &interpreter, }); } +void CommandCompletions::ThreadIDs(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); + if (!exe_ctx.HasProcessScope()) + return; + + ThreadList &threads = exe_ctx.GetProcessPtr()->GetThreadList(); + lldb::ThreadSP thread_sp; + for (uint32_t idx = 0; (thread_sp = threads.GetThreadAtIndex(idx)); ++idx) { + StreamString strm; + thread_sp->GetStatus(strm, 0, 1, 1, true); + request.TryCompleteCurrentArg(std::to_string(thread_sp->GetID()), + strm.GetString()); + } +} + void CommandCompletions::CompleteModifiableCmdPathArgs( CommandInterpreter &interpreter, CompletionRequest &request, OptionElementVector &opt_element_vector) { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.cpp index c6680f8b140d..88c214d4fc56 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.cpp @@ -38,7 +38,7 @@ CommandObjectApropos::CommandObjectApropos(CommandInterpreter &interpreter) CommandObjectApropos::~CommandObjectApropos() = default; -bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { +void CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { const size_t argc = args.GetArgumentCount(); if (argc == 1) { @@ -90,6 +90,4 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { } else { result.AppendError("'apropos' must be called with exactly one argument.\n"); } - - return result.Succeeded(); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.h index 042753f24032..f43420c1815d 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectApropos.h @@ -23,7 +23,7 @@ public: ~CommandObjectApropos() override; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp index 327dae4fd2af..63492590d32d 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -528,7 +528,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); // The following are the various types of breakpoints that could be set: @@ -577,12 +577,12 @@ protected: if (num_files == 0) { if (!GetDefaultFile(target, file, result)) { result.AppendError("No file supplied and no default file available."); - return false; + return; } } else if (num_files > 1) { result.AppendError("Only one file at a time is allowed for file and " "line breakpoints."); - return false; + return; } else file = m_options.m_filenames.GetFileSpecAtIndex(0); @@ -603,8 +603,8 @@ protected: // will track the load location of the library. size_t num_modules_specified = m_options.m_modules.GetSize(); if (num_modules_specified == 1) { - const FileSpec *file_spec = - m_options.m_modules.GetFileSpecPointerAtIndex(0); + const FileSpec &file_spec = + m_options.m_modules.GetFileSpecAtIndex(0); bp_sp = target.CreateAddressInModuleBreakpoint( m_options.m_load_addr, internal, file_spec, m_options.m_hardware); } else if (num_modules_specified == 0) { @@ -613,7 +613,7 @@ protected: } else { result.AppendError("Only one shared library can be specified for " "address breakpoints."); - return false; + return; } break; } @@ -647,7 +647,7 @@ protected: result.AppendWarning( "Function name regex does not accept glob patterns."); } - return false; + return; } bp_sp = target.CreateFuncRegexBreakpoint( @@ -664,7 +664,7 @@ protected: if (!GetDefaultFile(target, file, result)) { result.AppendError( "No files provided and could not find default file."); - return false; + return; } else { m_options.m_filenames.Append(file); } @@ -675,7 +675,7 @@ protected: result.AppendErrorWithFormat( "Source text regular expression could not be compiled: \"%s\"", llvm::toString(std::move(err)).c_str()); - return false; + return; } bp_sp = target.CreateSourceRegexBreakpoint( &(m_options.m_modules), &(m_options.m_filenames), @@ -693,7 +693,7 @@ protected: "Error setting extra exception arguments: %s", precond_error.AsCString()); target.RemoveBreakpointByID(bp_sp->GetID()); - return false; + return; } } break; case eSetTypeScripted: { @@ -707,7 +707,7 @@ protected: result.AppendErrorWithFormat( "Error setting extra exception arguments: %s", error.AsCString()); target.RemoveBreakpointByID(bp_sp->GetID()); - return false; + return; } } break; default: @@ -726,7 +726,7 @@ protected: result.AppendErrorWithFormat("Invalid breakpoint name: %s", name.c_str()); target.RemoveBreakpointByID(bp_sp->GetID()); - return false; + return; } } } @@ -753,8 +753,6 @@ protected: } else if (!bp_sp) { result.AppendError("Breakpoint creation failed: No breakpoint created."); } - - return result.Succeeded(); } private: @@ -835,7 +833,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); std::unique_lock<std::recursive_mutex> lock; @@ -868,8 +866,6 @@ protected: } } } - - return result.Succeeded(); } private: @@ -906,7 +902,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; @@ -918,7 +914,7 @@ protected: if (num_breakpoints == 0) { result.AppendError("No breakpoints exist to be enabled."); - return false; + return; } if (command.empty()) { @@ -963,8 +959,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishNoResult); } } - - return result.Succeeded(); } }; @@ -1020,7 +1014,7 @@ the second re-enables the first location."); } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; target.GetBreakpointList().GetListMutex(lock); @@ -1030,7 +1024,7 @@ protected: if (num_breakpoints == 0) { result.AppendError("No breakpoints exist to be disabled."); - return false; + return; } if (command.empty()) { @@ -1076,8 +1070,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishNoResult); } } - - return result.Succeeded(); } }; @@ -1168,7 +1160,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); const BreakpointList &breakpoints = @@ -1181,7 +1173,7 @@ protected: if (num_breakpoints == 0) { result.AppendMessage("No breakpoints currently set."); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } Stream &output_stream = result.GetOutputStream(); @@ -1216,8 +1208,6 @@ protected: result.AppendError("Invalid breakpoint ID."); } } - - return result.Succeeded(); } private: @@ -1289,7 +1279,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); // The following are the various types of breakpoints that could be @@ -1310,7 +1300,7 @@ protected: // Early return if there's no breakpoint at all. if (num_breakpoints == 0) { result.AppendError("Breakpoint clear: No breakpoint cleared."); - return result.Succeeded(); + return; } // Find matching breakpoints and delete them. @@ -1357,8 +1347,6 @@ protected: } else { result.AppendError("Breakpoint clear: No breakpoint cleared."); } - - return result.Succeeded(); } private: @@ -1445,7 +1433,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); result.Clear(); @@ -1458,7 +1446,7 @@ protected: if (num_breakpoints == 0) { result.AppendError("No breakpoints exist to be deleted."); - return false; + return; } // Handle the delete all breakpoints case: @@ -1475,7 +1463,7 @@ protected: (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + return; } // Either we have some kind of breakpoint specification(s), @@ -1491,7 +1479,7 @@ protected: command, &target, result, &excluded_bp_ids, BreakpointName::Permissions::PermissionKinds::deletePerm); if (!result.Succeeded()) - return false; + return; } for (auto breakpoint_sp : breakpoints.Breakpoints()) { @@ -1504,14 +1492,14 @@ protected: } if (valid_bp_ids.GetSize() == 0) { result.AppendError("No disabled breakpoints."); - return false; + return; } } else { CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::deletePerm); if (!result.Succeeded()) - return false; + return; } int delete_count = 0; @@ -1542,7 +1530,6 @@ protected: "%d breakpoints deleted; %d breakpoint locations disabled.\n", delete_count, disable_count); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } private: @@ -1709,12 +1696,12 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { result.AppendError("No names provided."); - return false; + return; } Target &target = GetSelectedOrDummyTarget(false); @@ -1728,7 +1715,7 @@ protected: if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", entry.c_str(), error.AsCString()); - return false; + return; } } // Now configure them, we already pre-checked the names so we don't need to @@ -1741,7 +1728,7 @@ protected: if (!bp_sp) { result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", bp_id); - return false; + return; } } @@ -1765,7 +1752,6 @@ protected: m_bp_opts.GetBreakpointOptions(), m_access_options.GetPermissions()); } - return true; } private: @@ -1806,10 +1792,10 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (!m_name_options.m_name.OptionWasSet()) { result.AppendError("No name option provided."); - return false; + return; } Target &target = @@ -1823,7 +1809,7 @@ protected: size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { result.AppendError("No breakpoints, cannot add names."); - return false; + return; } // Particular breakpoint selected; disable that breakpoint. @@ -1835,7 +1821,7 @@ protected: if (result.Succeeded()) { if (valid_bp_ids.GetSize() == 0) { result.AppendError("No breakpoints specified, cannot add names."); - return false; + return; } size_t num_valid_ids = valid_bp_ids.GetSize(); const char *bp_name = m_name_options.m_name.GetCurrentValue(); @@ -1848,8 +1834,6 @@ protected: target.AddNameToBreakpoint(bp_sp, bp_name, error); } } - - return true; } private: @@ -1889,10 +1873,10 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (!m_name_options.m_name.OptionWasSet()) { result.AppendError("No name option provided."); - return false; + return; } Target &target = @@ -1906,7 +1890,7 @@ protected: size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { result.AppendError("No breakpoints, cannot delete names."); - return false; + return; } // Particular breakpoint selected; disable that breakpoint. @@ -1918,7 +1902,7 @@ protected: if (result.Succeeded()) { if (valid_bp_ids.GetSize() == 0) { result.AppendError("No breakpoints specified, cannot delete names."); - return false; + return; } ConstString bp_name(m_name_options.m_name.GetCurrentValue()); size_t num_valid_ids = valid_bp_ids.GetSize(); @@ -1929,8 +1913,6 @@ protected: target.RemoveNameFromBreakpoint(bp_sp, bp_name); } } - - return true; } private: @@ -1955,7 +1937,7 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); @@ -2005,7 +1987,6 @@ protected: } } } - return true; } private: @@ -2254,9 +2235,9 @@ public: size_t num_names = names_array->GetSize(); for (size_t i = 0; i < num_names; i++) { - llvm::StringRef name; - if (names_array->GetItemAtIndexAsString(i, name)) - request.TryCompleteCurrentArg(name); + if (std::optional<llvm::StringRef> maybe_name = + names_array->GetItemAtIndexAsString(i)) + request.TryCompleteCurrentArg(*maybe_name); } } } @@ -2267,7 +2248,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; @@ -2281,7 +2262,7 @@ protected: if (!error.Success()) { result.AppendError(error.AsCString()); - return false; + return; } Stream &output_stream = result.GetOutputStream(); @@ -2302,7 +2283,6 @@ protected: false); } } - return result.Succeeded(); } private: @@ -2383,7 +2363,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; @@ -2397,7 +2377,7 @@ protected: if (!result.Succeeded()) { result.SetStatus(eReturnStatusFailed); - return false; + return; } } FileSpec file_spec(m_options.m_filename); @@ -2408,7 +2388,6 @@ protected: result.AppendErrorWithFormat("error serializing breakpoints: %s.", error.AsCString()); } - return result.Succeeded(); } private: diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index 921243829fc6..fefafcd94546 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -334,7 +334,7 @@ are no syntax errors may indicate that a function was declared but never called. }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); const BreakpointList &breakpoints = target.GetBreakpointList(); @@ -342,7 +342,7 @@ protected: if (num_breakpoints == 0) { result.AppendError("No breakpoints exist to have commands added"); - return false; + return; } if (!m_func_options.GetName().empty()) { @@ -412,8 +412,6 @@ protected: CollectDataForBreakpointCommandCallback(m_bp_options_vec, result); } } - - return result.Succeeded(); } private: @@ -506,7 +504,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); const BreakpointList &breakpoints = target.GetBreakpointList(); @@ -514,13 +512,13 @@ protected: if (num_breakpoints == 0) { result.AppendError("No breakpoints exist to have commands deleted"); - return false; + return; } if (command.empty()) { result.AppendError( "No breakpoint specified from which to delete the commands"); - return false; + return; } BreakpointIDList valid_bp_ids; @@ -544,7 +542,7 @@ protected: result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); - return false; + return; } } else { bp->ClearCallback(); @@ -552,7 +550,6 @@ protected: } } } - return result.Succeeded(); } private: @@ -586,7 +583,7 @@ public: ~CommandObjectBreakpointCommandList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const BreakpointList &breakpoints = target->GetBreakpointList(); @@ -594,13 +591,13 @@ protected: if (num_breakpoints == 0) { result.AppendError("No breakpoints exist for which to list commands"); - return false; + return; } if (command.empty()) { result.AppendError( "No breakpoint specified for which to list the commands"); - return false; + return; } BreakpointIDList valid_bp_ids; @@ -624,7 +621,7 @@ protected: result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); - return false; + return; } } @@ -661,8 +658,6 @@ protected: } } } - - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp index 656ace223b5f..5b9af4a3e1b8 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp @@ -129,12 +129,12 @@ protected: OptionValueBoolean m_cmd_relative_to_command_file; }; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat( "'%s' takes exactly one executable filename argument.\n", GetCommandName().str().c_str()); - return false; + return; } FileSpec source_dir = {}; @@ -144,7 +144,7 @@ protected: result.AppendError("command source -C can only be specified " "from a command file"); result.SetStatus(eReturnStatusFailed); - return false; + return; } } @@ -155,7 +155,7 @@ protected: result.AppendError("command source -C can only be used " "with a relative path."); result.SetStatus(eReturnStatusFailed); - return false; + return; } cmd_file.MakeAbsolute(source_dir); } @@ -186,7 +186,6 @@ protected: } m_interpreter.HandleCommandsFromFile(cmd_file, options, result); - return result.Succeeded(); } CommandOptions m_options; @@ -384,11 +383,11 @@ rather than using a positional placeholder:" ~CommandObjectCommandsAlias() override = default; protected: - bool DoExecute(llvm::StringRef raw_command_line, + void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { if (raw_command_line.empty()) { result.AppendError("'command alias' requires at least two arguments"); - return false; + return; } ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); @@ -399,26 +398,26 @@ protected: if (args_with_suffix.HasArgs()) if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result, m_option_group, exe_ctx)) - return false; + return; llvm::StringRef raw_command_string = args_with_suffix.GetRawPart(); Args args(raw_command_string); if (args.GetArgumentCount() < 2) { result.AppendError("'command alias' requires at least two arguments"); - return false; + return; } // Get the alias command. auto alias_command = args[0].ref(); - if (alias_command.startswith("-")) { + if (alias_command.starts_with("-")) { result.AppendError("aliases starting with a dash are not supported"); if (alias_command == "--help" || alias_command == "--long-help") { result.AppendWarning("if trying to pass options to 'command alias' add " "a -- at the end of the options"); } - return false; + return; } // Strip the new alias name off 'raw_command_string' (leave it on args, @@ -431,7 +430,7 @@ protected: raw_command_string = raw_command_string.substr(pos); } else { result.AppendError("Error parsing command string. No alias created."); - return false; + return; } // Verify that the command is alias-able. @@ -439,7 +438,7 @@ protected: result.AppendErrorWithFormat( "'%s' is a permanent debugger command and cannot be redefined.\n", args[0].c_str()); - return false; + return; } if (m_interpreter.UserMultiwordCommandExists(alias_command)) { @@ -447,7 +446,7 @@ protected: "'%s' is a user container command and cannot be overwritten.\n" "Delete it first with 'command container delete'\n", args[0].c_str()); - return false; + return; } // Get CommandObject that is being aliased. The command name is read from @@ -462,17 +461,15 @@ protected: "'%s' does not begin with a valid command." " No alias created.", original_raw_command_string.str().c_str()); - return false; } else if (!cmd_obj->WantsRawCommandString()) { // Note that args was initialized with the original command, and has not // been updated to this point. Therefore can we pass it to the version of // Execute that does not need/expect raw input in the alias. - return HandleAliasingNormalCommand(args, result); + HandleAliasingNormalCommand(args, result); } else { - return HandleAliasingRawCommand(alias_command, raw_command_string, - *cmd_obj, result); + HandleAliasingRawCommand(alias_command, raw_command_string, *cmd_obj, + result); } - return result.Succeeded(); } bool HandleAliasingRawCommand(llvm::StringRef alias_command, @@ -653,13 +650,13 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { CommandObject::CommandMap::iterator pos; CommandObject *cmd_obj; if (args.empty()) { result.AppendError("must call 'unalias' with a valid alias"); - return false; + return; } auto command_name = args[0].ref(); @@ -669,7 +666,7 @@ protected: "'%s' is not a known command.\nTry 'help' to see a " "current list of commands.\n", args[0].c_str()); - return false; + return; } if (m_interpreter.CommandExists(command_name)) { @@ -683,7 +680,7 @@ protected: "'%s' is a permanent debugger command and cannot be removed.\n", args[0].c_str()); } - return false; + return; } if (!m_interpreter.RemoveAlias(command_name)) { @@ -694,11 +691,10 @@ protected: else result.AppendErrorWithFormat("'%s' is not an existing alias.\n", args[0].c_str()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } }; @@ -742,14 +738,14 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { CommandObject::CommandMap::iterator pos; if (args.empty()) { result.AppendErrorWithFormat("must call '%s' with one or more valid user " "defined regular expression command names", GetCommandName().str().c_str()); - return false; + return; } auto command_name = args[0].ref(); @@ -761,18 +757,17 @@ protected: &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), generate_upropos, generate_type_lookup); result.AppendError(error_msg_stream.GetString()); - return false; + return; } if (!m_interpreter.RemoveCommand(command_name)) { result.AppendErrorWithFormat( "'%s' is a permanent debugger command and cannot be removed.\n", args[0].c_str()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; } }; @@ -868,12 +863,12 @@ protected: } } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { result.AppendError("usage: 'command regex <command-name> " "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); - return false; + return; } Status error; @@ -914,8 +909,6 @@ protected: if (error.Fail()) { result.AppendError(error.AsCString()); } - - return result.Succeeded(); } Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed, @@ -1126,7 +1119,7 @@ public: bool WantsCompletion() override { return true; } protected: - bool DoExecute(llvm::StringRef raw_command_line, + void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); @@ -1147,8 +1140,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); } } - - return result.Succeeded(); } private: @@ -1222,7 +1213,7 @@ public: } protected: - bool DoExecute(llvm::StringRef raw_command_line, + void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); @@ -1243,8 +1234,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); } } - - return result.Succeeded(); } private: @@ -1330,10 +1319,10 @@ protected: bool silent = false; }; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.empty()) { result.AppendError("command script import needs one or more arguments"); - return false; + return; } FileSpec source_dir = {}; @@ -1342,7 +1331,7 @@ protected: if (!source_dir) { result.AppendError("command script import -c can only be specified " "from a command file"); - return false; + return; } } @@ -1371,8 +1360,6 @@ protected: error.AsCString()); } } - - return result.Succeeded(); } CommandOptions m_options; @@ -1567,16 +1554,16 @@ protected: io_handler.SetIsDone(true); } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { result.AppendError("only scripting language supported for scripted " "commands is currently Python"); - return false; + return; } if (command.GetArgumentCount() == 0) { result.AppendError("'command script add' requires at least one argument"); - return false; + return; } // Store the options in case we get multi-line input, also figure out the // default if not user supplied: @@ -1598,7 +1585,7 @@ protected: if (path_error.Fail()) { result.AppendErrorWithFormat("error in command path: %s", path_error.AsCString()); - return false; + return; } if (!m_container) { @@ -1617,7 +1604,7 @@ protected: if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) { m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt *this); // IOHandlerDelegate - return result.Succeeded(); + return; } CommandObjectSP new_cmd_sp; @@ -1629,7 +1616,7 @@ protected: ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); if (!interpreter) { result.AppendError("cannot find ScriptInterpreter"); - return false; + return; } auto cmd_obj_sp = interpreter->CreateScriptCommandObject( @@ -1637,7 +1624,7 @@ protected: if (!cmd_obj_sp) { result.AppendErrorWithFormatv("cannot create helper object for: " "'{0}'", m_options.m_class_name); - return false; + return; } new_cmd_sp.reset(new CommandObjectScriptingObject( @@ -1660,7 +1647,6 @@ protected: result.AppendErrorWithFormat("cannot add command: %s", llvm::toString(std::move(llvm_error)).c_str()); } - return result.Succeeded(); } CommandOptions m_options; @@ -1684,12 +1670,10 @@ public: ~CommandObjectCommandsScriptList() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); result.SetStatus(eReturnStatusSuccessFinishResult); - - return true; } }; @@ -1704,12 +1688,10 @@ public: ~CommandObjectCommandsScriptClear() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { m_interpreter.RemoveAllUser(); result.SetStatus(eReturnStatusSuccessFinishResult); - - return true; } }; @@ -1748,44 +1730,44 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { llvm::StringRef root_cmd = command[0].ref(); size_t num_args = command.GetArgumentCount(); if (root_cmd.empty()) { result.AppendErrorWithFormat("empty root command name"); - return false; + return; } if (!m_interpreter.HasUserCommands() && !m_interpreter.HasUserMultiwordCommands()) { result.AppendErrorWithFormat("can only delete user defined commands, " "but no user defined commands found"); - return false; + return; } CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd); if (!cmd_sp) { result.AppendErrorWithFormat("command '%s' not found.", command[0].c_str()); - return false; + return; } if (!cmd_sp->IsUserCommand()) { result.AppendErrorWithFormat("command '%s' is not a user command.", command[0].c_str()); - return false; + return; } if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) { result.AppendErrorWithFormat("command '%s' is a multi-word command.\n " "Delete with \"command container delete\"", command[0].c_str()); - return false; + return; } if (command.GetArgumentCount() == 1) { m_interpreter.RemoveUser(root_cmd); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } // We're deleting a command from a multiword command. Verify the command // path: @@ -1796,14 +1778,14 @@ protected: if (error.Fail()) { result.AppendErrorWithFormat("could not resolve command path: %s", error.AsCString()); - return false; + return; } if (!container) { // This means that command only had a leaf command, so the container is // the root. That should have been handled above. result.AppendErrorWithFormat("could not find a container for '%s'", command[0].c_str()); - return false; + return; } const char *leaf_cmd = command[num_args - 1].c_str(); llvm::Error llvm_error = container->RemoveUserSubcommand(leaf_cmd, @@ -1812,7 +1794,7 @@ protected: result.AppendErrorWithFormat("could not delete command '%s': %s", leaf_cmd, llvm::toString(std::move(llvm_error)).c_str()); - return false; + return; } Stream &out_stream = result.GetOutputStream(); @@ -1824,7 +1806,6 @@ protected: } out_stream << '\n'; result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } }; @@ -1945,12 +1926,12 @@ protected: std::string m_long_help; bool m_overwrite = false; }; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { size_t num_args = command.GetArgumentCount(); if (num_args == 0) { result.AppendError("no command was specified"); - return false; + return; } if (num_args == 1) { @@ -1965,10 +1946,10 @@ protected: if (add_error.Fail()) { result.AppendErrorWithFormat("error adding command: %s", add_error.AsCString()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } // We're adding this to a subcommand, first find the subcommand: @@ -1980,7 +1961,7 @@ protected: if (!add_to_me) { result.AppendErrorWithFormat("error adding command: %s", path_error.AsCString()); - return false; + return; } const char *cmd_name = command.GetArgumentAtIndex(num_args - 1); @@ -1992,11 +1973,10 @@ protected: if (llvm_error) { result.AppendErrorWithFormat("error adding subcommand: %s", llvm::toString(std::move(llvm_error)).c_str()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; } private: @@ -2039,12 +2019,12 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { size_t num_args = command.GetArgumentCount(); if (num_args == 0) { result.AppendError("No command was specified."); - return false; + return; } if (num_args == 1) { @@ -2057,27 +2037,27 @@ protected: if (!cmd_sp) { result.AppendErrorWithFormat("container command %s doesn't exist.", cmd_name); - return false; + return; } if (!cmd_sp->IsUserCommand()) { result.AppendErrorWithFormat( "container command %s is not a user command", cmd_name); - return false; + return; } if (!cmd_sp->GetAsMultiwordCommand()) { result.AppendErrorWithFormat("command %s is not a container command", cmd_name); - return false; + return; } bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name); if (!did_remove) { result.AppendErrorWithFormat("error removing command %s.", cmd_name); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } // We're removing a subcommand, first find the subcommand's owner: @@ -2089,7 +2069,7 @@ protected: if (!container) { result.AppendErrorWithFormat("error removing container command: %s", path_error.AsCString()); - return false; + return; } const char *leaf = command.GetArgumentAtIndex(num_args - 1); llvm::Error llvm_error = @@ -2097,10 +2077,9 @@ protected: if (llvm_error) { result.AppendErrorWithFormat("error removing container command: %s", llvm::toString(std::move(llvm_error)).c_str()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp index b2b7f201a5ad..695f3d7931cd 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -25,6 +25,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" +#include <regex> + using namespace llvm; using namespace lldb; using namespace lldb_private; @@ -56,7 +58,7 @@ void CommandObjectDWIMPrint::HandleArgumentCompletion( GetCommandInterpreter(), lldb::eVariablePathCompletion, request, nullptr); } -bool CommandObjectDWIMPrint::DoExecute(StringRef command, +void CommandObjectDWIMPrint::DoExecute(StringRef command, CommandReturnObject &result) { m_option_group.NotifyOptionParsingStarting(&m_exe_ctx); OptionsWithRaw args{command}; @@ -65,13 +67,13 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, if (expr.empty()) { result.AppendErrorWithFormatv("'{0}' takes a variable or expression", m_cmd_name); - return false; + return; } if (args.HasArgs()) { if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, m_exe_ctx)) - return false; + return; } // If the user has not specified, default to disabling persistent results. @@ -95,8 +97,46 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, m_expr_options.m_verbosity, m_format_options.GetFormat()); dump_options.SetHideRootName(suppress_result); + bool is_po = m_varobj_options.use_objc; + StackFrame *frame = m_exe_ctx.GetFramePtr(); + // Either Swift was explicitly specified, or the frame is Swift. + lldb::LanguageType language = m_expr_options.language; + if (language == lldb::eLanguageTypeUnknown && frame) + language = frame->GuessLanguage(); + + // Add a hint if object description was requested, but no description + // function was implemented. + auto maybe_add_hint = [&](llvm::StringRef output) { + // Identify the default output of object description for Swift and + // Objective-C + // "<Name: 0x...>. The regex is: + // - Start with "<". + // - Followed by 1 or more non-whitespace characters. + // - Followed by ": 0x". + // - Followed by 5 or more hex digits. + // - Followed by ">". + // - End with zero or more whitespace characters. + const std::regex swift_class_regex("^<\\S+: 0x[[:xdigit:]]{5,}>\\s*$"); + + if (GetDebugger().GetShowDontUsePoHint() && target_ptr && + (language == lldb::eLanguageTypeSwift || + language == lldb::eLanguageTypeObjC) && + std::regex_match(output.data(), swift_class_regex)) { + + static bool note_shown = false; + if (note_shown) + return; + + result.GetOutputStream() + << "note: object description requested, but type doesn't implement " + "a custom object description. Consider using \"p\" instead of " + "\"po\" (this note will only be shown once per debug session).\n"; + note_shown = true; + } + }; + // First, try `expr` as the name of a frame variable. if (frame) { auto valobj_sp = frame->FindVariable(ConstString(expr)); @@ -114,9 +154,17 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, flags, expr); } - valobj_sp->Dump(result.GetOutputStream(), dump_options); + if (is_po) { + StreamString temp_result_stream; + valobj_sp->Dump(temp_result_stream, dump_options); + llvm::StringRef output = temp_result_stream.GetString(); + maybe_add_hint(output); + result.GetOutputStream() << output; + } else { + valobj_sp->Dump(result.GetOutputStream(), dump_options); + } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } } @@ -124,8 +172,19 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, { auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); ValueObjectSP valobj_sp; - ExpressionResults expr_result = - target.EvaluateExpression(expr, exe_scope, valobj_sp, eval_options); + std::string fixed_expression; + + ExpressionResults expr_result = target.EvaluateExpression( + expr, exe_scope, valobj_sp, eval_options, &fixed_expression); + + // Only mention Fix-Its if the expression evaluator applied them. + // Compiler errors refer to the final expression after applying Fix-It(s). + if (!fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) { + Stream &error_stream = result.GetErrorStream(); + error_stream << " Evaluated this expression after applying Fix-It(s):\n"; + error_stream << " " << fixed_expression << "\n"; + } + if (expr_result == eExpressionCompleted) { if (verbosity != eDWIMPrintVerbosityNone) { StringRef flags; @@ -135,8 +194,17 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, expr); } - if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) - valobj_sp->Dump(result.GetOutputStream(), dump_options); + if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) { + if (is_po) { + StreamString temp_result_stream; + valobj_sp->Dump(temp_result_stream, dump_options); + llvm::StringRef output = temp_result_stream.GetString(); + maybe_add_hint(output); + result.GetOutputStream() << output; + } else { + valobj_sp->Dump(result.GetOutputStream(), dump_options); + } + } if (suppress_result) if (auto result_var_sp = @@ -148,14 +216,12 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command, } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } else { if (valobj_sp) result.SetError(valobj_sp->GetError()); else result.AppendErrorWithFormatv( "unknown error evaluating expression `{0}`", expr); - return false; } } } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h index 3fc6c01d4729..d868f8964c2a 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h @@ -44,7 +44,7 @@ public: OptionElementVector &opt_element_vector) override; private: - bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override; OptionGroupOptions m_option_group; OptionGroupFormat m_format_options = lldb::eFormatDefault; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp index dfde50a236ab..ac87f869f012 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp @@ -77,12 +77,12 @@ protected: return Diagnostics::CreateUniqueDirectory(); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { llvm::Expected<FileSpec> directory = GetDirectory(); if (!directory) { result.AppendError(llvm::toString(directory.takeError())); - return result.Succeeded(); + return; } llvm::Error error = Diagnostics::Instance().Create(*directory); @@ -90,13 +90,13 @@ protected: result.AppendErrorWithFormat("failed to write diagnostics to %s", directory->GetPath().c_str()); result.AppendError(llvm::toString(std::move(error))); - return result.Succeeded(); + return; } result.GetOutputStream() << "diagnostics written to " << *directory << '\n'; result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + return; } CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp index 6f78fc9f6287..d975e3980131 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -437,7 +437,7 @@ CommandObjectDisassemble::GetRangesForSelectedMode( return CommandObjectDisassemble::GetPCRanges(); } -bool CommandObjectDisassemble::DoExecute(Args &command, +void CommandObjectDisassemble::DoExecute(Args &command, CommandReturnObject &result) { Target *target = &GetSelectedTarget(); @@ -447,7 +447,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command, if (!m_options.arch.IsValid()) { result.AppendError( "use the --arch option or set the target architecture to disassemble"); - return false; + return; } const char *plugin_name = m_options.GetPluginName(); @@ -466,7 +466,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command, result.AppendErrorWithFormat( "Unable to find Disassembler plug-in for the '%s' architecture.\n", m_options.arch.GetArchitectureName()); - return false; + return; } else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec( m_options.arch, flavor_string)) result.AppendWarningWithFormat( @@ -481,7 +481,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command, GetCommandInterpreter().GetDebugger().GetTerminalWidth(); GetOptions()->GenerateOptionUsage(result.GetErrorStream(), *this, terminal_width); - return false; + return; } if (m_options.show_mixed && m_options.num_lines_context == 0) @@ -508,7 +508,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command, GetRangesForSelectedMode(result); if (!ranges) { result.AppendError(toString(ranges.takeError())); - return result.Succeeded(); + return; } bool print_sc_header = ranges->size() > 1; @@ -541,6 +541,4 @@ bool CommandObjectDisassemble::DoExecute(Args &command, if (print_sc_header) result.GetOutputStream() << "\n"; } - - return result.Succeeded(); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.h index b5146863628d..2e4d46dd0ec5 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.h @@ -73,7 +73,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; llvm::Expected<std::vector<AddressRange>> GetRangesForSelectedMode(CommandReturnObject &result); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp index e7e6e3820b99..3a2dc11e1e71 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp @@ -439,11 +439,11 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, ExpressionResults success = target.EvaluateExpression( expr, frame, result_valobj_sp, eval_options, &m_fixed_expression); - // We only tell you about the FixIt if we applied it. The compiler errors - // will suggest the FixIt if it parsed. + // Only mention Fix-Its if the expression evaluator applied them. + // Compiler errors refer to the final expression after applying Fix-It(s). if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) { - error_stream.Printf(" Fix-it applied, fixed expression was: \n %s\n", - m_fixed_expression.c_str()); + error_stream << " Evaluated this expression after applying Fix-It(s):\n"; + error_stream << " " << m_fixed_expression << "\n"; } if (result_valobj_sp) { @@ -594,7 +594,7 @@ GetExprOptions(ExecutionContext &ctx, return expr_options; } -bool CommandObjectExpression::DoExecute(llvm::StringRef command, +void CommandObjectExpression::DoExecute(llvm::StringRef command, CommandReturnObject &result) { m_fixed_expression.clear(); auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); @@ -602,7 +602,7 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, if (command.empty()) { GetMultilineExpression(); - return result.Succeeded(); + return; } OptionsWithRaw args(command); @@ -610,7 +610,7 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, if (args.HasArgs()) { if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx)) - return false; + return; if (m_repl_option.GetOptionValue().GetCurrentValue()) { Target &target = GetSelectedOrDummyTarget(); @@ -642,7 +642,7 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, nullptr, true); if (!repl_error.Success()) { result.SetError(repl_error); - return result.Succeeded(); + return; } } @@ -662,14 +662,14 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, "Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language)); result.SetError(repl_error); - return result.Succeeded(); + return; } } } // No expression following options else if (expr.empty()) { GetMultilineExpression(); - return result.Succeeded(); + return; } } @@ -691,8 +691,7 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, fixed_command.append(m_fixed_expression); history.AppendString(fixed_command); } - return true; + return; } result.SetStatus(eReturnStatusFailed); - return false; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h index b2b8fc73a1ee..6fccf10e5dbc 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.h @@ -75,7 +75,7 @@ protected: bool IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) override; - bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override; /// Evaluates the given expression. /// \param output_stream The stream to which the evaluation result will be diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp index 1390fd8748df..e7cb861c2b01 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp @@ -133,7 +133,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Thread *thread = m_exe_ctx.GetThreadPtr(); StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame); @@ -143,7 +143,7 @@ protected: if (m_options.reg || m_options.offset) { result.AppendError( "`frame diagnose --address` is incompatible with other arguments."); - return false; + return; } valobj_sp = frame_sp->GuessValueForAddress(*m_options.address); } else if (m_options.reg) { @@ -153,7 +153,7 @@ protected: StopInfoSP stop_info_sp = thread->GetStopInfo(); if (!stop_info_sp) { result.AppendError("No arguments provided, and no stop info."); - return false; + return; } valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp); @@ -161,7 +161,7 @@ protected: if (!valobj_sp) { result.AppendError("No diagnosis available."); - return false; + return; } DumpValueObjectOptions::DeclPrintingHelper helper = @@ -180,8 +180,6 @@ protected: ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(), options); printer.PrintValueObject(); - - return true; } CommandOptions m_options; @@ -205,10 +203,9 @@ public: ~CommandObjectFrameInfo() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -299,7 +296,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "thread" for validity as eCommandRequiresThread ensures // it is valid Thread *thread = m_exe_ctx.GetThreadPtr(); @@ -320,7 +317,7 @@ protected: // If you are already at the bottom of the stack, then just warn // and don't reset the frame. result.AppendError("Already at the bottom of the stack."); - return false; + return; } else frame_idx = 0; } @@ -345,7 +342,7 @@ protected: // If we are already at the top of the stack, just warn and don't // reset the frame. result.AppendError("Already at the top of the stack."); - return false; + return; } else frame_idx = num_frames - 1; } @@ -359,14 +356,14 @@ protected: m_options.GenerateOptionUsage( result.GetErrorStream(), *this, GetCommandInterpreter().GetDebugger().GetTerminalWidth()); - return false; + return; } if (command.GetArgumentCount() == 1) { if (command[0].ref().getAsInteger(0, frame_idx)) { result.AppendErrorWithFormat("invalid frame index argument '%s'.", command[0].c_str()); - return false; + return; } } else if (command.GetArgumentCount() == 0) { frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame); @@ -385,8 +382,6 @@ protected: result.AppendErrorWithFormat("Frame index (%u) out of range.\n", frame_idx); } - - return result.Succeeded(); } CommandOptions m_options; @@ -495,6 +490,8 @@ protected: case eValueTypeRegisterSet: case eValueTypeConstResult: case eValueTypeVariableThreadLocal: + case eValueTypeVTable: + case eValueTypeVTableEntry: return false; } } @@ -524,7 +521,7 @@ protected: return std::nullopt; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "frame" for validity as eCommandRequiresFrame ensures // it is valid StackFrame *frame = m_exe_ctx.GetFramePtr(); @@ -733,13 +730,11 @@ protected: m_cmd_name); // Increment statistics. - bool res = result.Succeeded(); TargetStats &target_stats = GetSelectedOrDummyTarget().GetStatistics(); - if (res) + if (result.Succeeded()) target_stats.GetFrameVariableStats().NotifySuccess(); else target_stats.GetFrameVariableStats().NotifyFailure(); - return res; } OptionGroupOptions m_option_group; @@ -821,7 +816,7 @@ private: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; public: CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter) @@ -877,33 +872,33 @@ Process 1234 stopped ~CommandObjectFrameRecognizerAdd() override = default; }; -bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command, +void CommandObjectFrameRecognizerAdd::DoExecute(Args &command, CommandReturnObject &result) { #if LLDB_ENABLE_PYTHON if (m_options.m_class_name.empty()) { result.AppendErrorWithFormat( "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str()); - return false; + return; } if (m_options.m_module.empty()) { result.AppendErrorWithFormat("%s needs a module name (-s argument).\n", m_cmd_name.c_str()); - return false; + return; } if (m_options.m_symbols.empty()) { result.AppendErrorWithFormat( "%s needs at least one symbol name (-n argument).\n", m_cmd_name.c_str()); - return false; + return; } if (m_options.m_regex && m_options.m_symbols.size() > 1) { result.AppendErrorWithFormat( "%s needs only one symbol regular expression (-n argument).\n", m_cmd_name.c_str()); - return false; + return; } ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); @@ -934,7 +929,6 @@ bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command, #endif result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } class CommandObjectFrameRecognizerClear : public CommandObjectParsed { @@ -946,12 +940,11 @@ public: ~CommandObjectFrameRecognizerClear() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { GetSelectedOrDummyTarget() .GetFrameRecognizerManager() .RemoveAllRecognizers(); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -995,33 +988,33 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() == 0) { if (!m_interpreter.Confirm( "About to delete all frame recognizers, do you want to do that?", true)) { result.AppendMessage("Operation cancelled..."); - return false; + return; } GetSelectedOrDummyTarget() .GetFrameRecognizerManager() .RemoveAllRecognizers(); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + return; } if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n", m_cmd_name.c_str()); - return false; + return; } uint32_t recognizer_id; if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) { result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n", command.GetArgumentAtIndex(0)); - return false; + return; } if (!GetSelectedOrDummyTarget() @@ -1029,10 +1022,9 @@ protected: .RemoveRecognizerWithID(recognizer_id)) { result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n", command.GetArgumentAtIndex(0)); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1046,7 +1038,7 @@ public: ~CommandObjectFrameRecognizerList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { bool any_printed = false; GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach( [&result, &any_printed]( @@ -1078,7 +1070,6 @@ protected: result.GetOutputStream().PutCString("no matching results found.\n"); result.SetStatus(eReturnStatusSuccessFinishNoResult); } - return result.Succeeded(); } }; @@ -1107,35 +1098,35 @@ public: ~CommandObjectFrameRecognizerInfo() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const char *frame_index_str = command.GetArgumentAtIndex(0); uint32_t frame_index; if (!llvm::to_integer(frame_index_str, frame_index)) { result.AppendErrorWithFormat("'%s' is not a valid frame index.", frame_index_str); - return false; + return; } Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process"); - return false; + return; } Thread *thread = m_exe_ctx.GetThreadPtr(); if (thread == nullptr) { result.AppendError("no thread"); - return false; + return; } if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat( "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str()); - return false; + return; } StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index); if (!frame_sp) { result.AppendErrorWithFormat("no frame with index %u", frame_index); - return false; + return; } auto recognizer = GetSelectedOrDummyTarget() @@ -1152,7 +1143,6 @@ protected: } output_stream.EOL(); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.cpp index a63d1718610c..b56e49b073b0 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.cpp @@ -24,7 +24,7 @@ CommandObjectGUI::CommandObjectGUI(CommandInterpreter &interpreter) CommandObjectGUI::~CommandObjectGUI() = default; -bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) { +void CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) { #if LLDB_ENABLE_CURSES Debugger &debugger = GetDebugger(); @@ -39,9 +39,7 @@ bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) { } else { result.AppendError("the gui command requires an interactive terminal."); } - return true; #else result.AppendError("lldb was not built with gui support"); - return false; #endif } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.h index 49bad49a957d..fde4342724c9 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectGUI.h @@ -22,7 +22,7 @@ public: ~CommandObjectGUI() override; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override; + void DoExecute(Args &args, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp index 10aa49ae01ba..ddb006e52d2c 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp @@ -74,7 +74,7 @@ CommandObjectHelp::CommandOptions::GetDefinitions() { return llvm::ArrayRef(g_help_options); } -bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { +void CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { CommandObject::CommandMap::iterator pos; CommandObject *cmd_obj; const size_t argc = command.GetArgumentCount(); @@ -142,14 +142,14 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { } s.Printf("\n"); result.AppendError(s.GetString()); - return false; + return; } else if (!sub_cmd_obj) { StreamString error_msg_stream; GenerateAdditionalHelpAvenuesMessage( &error_msg_stream, cmd_string.c_str(), m_interpreter.GetCommandPrefix(), sub_command.c_str()); result.AppendError(error_msg_stream.GetString()); - return false; + return; } else { GenerateAdditionalHelpAvenuesMessage( &result.GetOutputStream(), cmd_string.c_str(), @@ -197,8 +197,6 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { } } } - - return result.Succeeded(); } void CommandObjectHelp::HandleCompletion(CompletionRequest &request) { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.h index a0ed157b9caf..9b2c89e6654f 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.h @@ -76,7 +76,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; private: CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectLanguage.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectLanguage.h index 7a280902a07e..2f9f8fecc80d 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectLanguage.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectLanguage.h @@ -19,7 +19,7 @@ public: ~CommandObjectLanguage() override; protected: - bool DoExecute(Args &command, CommandReturnObject &result); + void DoExecute(Args &command, CommandReturnObject &result); }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp index 5dd6f8989837..6bfbf98078e6 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp @@ -162,19 +162,19 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() < 2) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); - return false; + return; } if (m_options.handler == eLogHandlerCircular && m_options.buffer_size.GetCurrentValue() == 0) { result.AppendError( "the circular buffer handler requires a non-zero buffer size.\n"); - return false; + return; } if ((m_options.handler != eLogHandlerCircular && @@ -182,13 +182,13 @@ protected: m_options.buffer_size.GetCurrentValue() != 0) { result.AppendError("a buffer size can only be specified for the circular " "and stream buffer handler.\n"); - return false; + return; } if (m_options.handler != eLogHandlerStream && m_options.log_file) { result.AppendError( "a file name can only be specified for the stream handler.\n"); - return false; + return; } // Store into a std::string since we're about to shift the channel off. @@ -212,7 +212,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); } CommandOptions m_options; @@ -257,12 +256,12 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); - return false; + return; } const std::string channel = std::string(args[0].ref()); @@ -278,7 +277,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishNoResult); result.GetErrorStream() << error_stream.str(); } - return result.Succeeded(); } }; @@ -315,7 +313,7 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { std::string output; llvm::raw_string_ostream output_stream(output); if (args.empty()) { @@ -330,7 +328,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); } result.GetOutputStream() << output_stream.str(); - return result.Succeeded(); } }; class CommandObjectLogDump : public CommandObjectParsed { @@ -398,12 +395,12 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); - return false; + return; } std::unique_ptr<llvm::raw_ostream> stream_up; @@ -417,7 +414,7 @@ protected: result.AppendErrorWithFormat("Unable to open log file '%s': %s", m_options.log_file.GetPath().c_str(), llvm::toString(file.takeError()).c_str()); - return false; + return; } stream_up = std::make_unique<llvm::raw_fd_ostream>( (*file)->GetDescriptor(), /*shouldClose=*/true); @@ -435,8 +432,6 @@ protected: result.SetStatus(eReturnStatusFailed); result.GetErrorStream() << error_stream.str(); } - - return result.Succeeded(); } CommandOptions m_options; @@ -467,7 +462,7 @@ public: ~CommandObjectLogTimerEnable() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { result.SetStatus(eReturnStatusFailed); if (args.GetArgumentCount() == 0) { @@ -488,7 +483,6 @@ protected: result.AppendError("Missing subcommand"); result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } - return result.Succeeded(); } }; @@ -503,7 +497,7 @@ public: ~CommandObjectLogTimerDisable() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Timer::DumpCategoryTimes(result.GetOutputStream()); Timer::SetDisplayDepth(0); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -512,7 +506,6 @@ protected: result.AppendError("Missing subcommand"); result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } - return result.Succeeded(); } }; @@ -526,7 +519,7 @@ public: ~CommandObjectLogTimerDump() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Timer::DumpCategoryTimes(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -534,7 +527,6 @@ protected: result.AppendError("Missing subcommand"); result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } - return result.Succeeded(); } }; @@ -549,7 +541,7 @@ public: ~CommandObjectLogTimerReset() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Timer::ResetCategoryTimes(); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -557,7 +549,6 @@ protected: result.AppendError("Missing subcommand"); result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } - return result.Succeeded(); } }; @@ -593,7 +584,7 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { result.SetStatus(eReturnStatusFailed); if (args.GetArgumentCount() == 1) { @@ -612,7 +603,6 @@ protected: result.AppendError("Missing subcommand"); result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp index ba5aad3d4ad5..b78a0492cca5 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp @@ -348,7 +348,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "target" for validity as eCommandRequiresTarget ensures // it is valid Target *target = m_exe_ctx.GetTargetPtr(); @@ -361,7 +361,7 @@ protected: m_cmd_name.c_str()); result.AppendWarning("Expressions should be quoted if they contain " "spaces or other special characters."); - return false; + return; } CompilerType compiler_type; @@ -372,8 +372,6 @@ protected: if (view_as_type_cstr && view_as_type_cstr[0]) { // We are viewing memory as a type - const bool exact_match = false; - TypeList type_list; uint32_t reference_count = 0; uint32_t pointer_count = 0; size_t idx; @@ -441,7 +439,7 @@ protected: } else { result.AppendErrorWithFormat("invalid type string: '%s'\n", view_as_type_cstr); - return false; + return; } break; @@ -452,18 +450,18 @@ protected: } } - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; ConstString lookup_type_name(type_str.c_str()); StackFrame *frame = m_exe_ctx.GetFramePtr(); ModuleSP search_first; - if (frame) { + if (frame) search_first = frame->GetSymbolContext(eSymbolContextModule).module_sp; - } - target->GetImages().FindTypes(search_first.get(), lookup_type_name, - exact_match, 1, searched_symbol_files, - type_list); + TypeQuery query(lookup_type_name.GetStringRef(), + TypeQueryOptions::e_find_one); + TypeResults results; + target->GetImages().FindTypes(search_first.get(), query, results); + TypeSP type_sp = results.GetFirstType(); - if (type_list.GetSize() == 0 && lookup_type_name.GetCString()) { + if (!type_sp && lookup_type_name.GetCString()) { LanguageType language_for_type = m_memory_options.m_language_for_type.GetCurrentValue(); std::set<LanguageType> languages_to_check; @@ -490,7 +488,7 @@ protected: "Mutiple types found matching raw type '%s', please disambiguate " "by specifying the language with -x", lookup_type_name.GetCString()); - return false; + return; } if (user_defined_types.size() == 1) { @@ -499,15 +497,14 @@ protected: } if (!compiler_type.IsValid()) { - if (type_list.GetSize() == 0) { + if (type_sp) { + compiler_type = type_sp->GetFullCompilerType(); + } else { result.AppendErrorWithFormat("unable to find any types that match " "the raw type '%s' for full type '%s'\n", lookup_type_name.GetCString(), view_as_type_cstr); - return false; - } else { - TypeSP type_sp(type_list.GetTypeAtIndex(0)); - compiler_type = type_sp->GetFullCompilerType(); + return; } } @@ -517,7 +514,7 @@ protected: compiler_type = pointer_type; else { result.AppendError("unable make a pointer type\n"); - return false; + return; } --pointer_count; } @@ -527,7 +524,7 @@ protected: result.AppendErrorWithFormat( "unable to get the byte size of the type '%s'\n", view_as_type_cstr); - return false; + return; } m_format_options.GetByteSizeValue() = *size; @@ -540,7 +537,7 @@ protected: // Look for invalid combinations of settings if (error.Fail()) { result.AppendError(error.AsCString()); - return false; + return; } lldb::addr_t addr; @@ -591,7 +588,7 @@ protected: if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid start address expression."); result.AppendError(error.AsCString()); - return false; + return; } if (argc == 2) { @@ -601,19 +598,19 @@ protected: if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid end address expression."); result.AppendError(error.AsCString()); - return false; + return; } else if (end_addr <= addr) { result.AppendErrorWithFormat( "end address (0x%" PRIx64 ") must be greater than the start address (0x%" PRIx64 ").\n", end_addr, addr); - return false; + return; } else if (m_format_options.GetCountValue().OptionWasSet()) { result.AppendErrorWithFormat( "specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count); - return false; + return; } total_byte_size = end_addr - addr; @@ -631,7 +628,7 @@ protected: "Please use --force to override this restriction just once.\n"); result.AppendErrorWithFormat("or set target.max-memory-read-size if you " "will often need a larger limit.\n"); - return false; + return; } WritableDataBufferSP data_sp; @@ -645,7 +642,7 @@ protected: std::optional<uint64_t> size = compiler_type.GetByteSize(nullptr); if (!size) { result.AppendError("can't get size of type"); - return false; + return; } bytes_read = *size * m_format_options.GetCountValue().GetCurrentValue(); @@ -659,7 +656,7 @@ protected: "can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size); - return false; + return; } Address address(addr, nullptr); @@ -673,7 +670,7 @@ protected: result.AppendErrorWithFormat( "failed to read memory from 0x%" PRIx64 ".\n", addr); } - return false; + return; } if (bytes_read < total_byte_size) @@ -699,7 +696,7 @@ protected: "can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size + 1) * item_count)); - return false; + return; } uint8_t *data_ptr = data_sp->GetBytes(); auto data_addr = addr; @@ -715,7 +712,7 @@ protected: if (error.Fail()) { result.AppendErrorWithFormat( "failed to read memory from 0x%" PRIx64 ".\n", addr); - return false; + return; } if (item_byte_size == read) { @@ -777,12 +774,12 @@ protected: result.GetOutputStream().Printf( "%zi bytes %s to '%s'\n", bytes_written, append ? "appended" : "written", path.c_str()); - return true; + return; } else { result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path.c_str()); - return false; + return; } } else { // We are going to write ASCII to the file just point the @@ -795,7 +792,7 @@ protected: path.c_str(), append ? "append" : "write"); result.AppendError(llvm::toString(outfile.takeError())); - return false; + return; } } else { output_stream_p = &result.GetOutputStream(); @@ -823,10 +820,10 @@ protected: result.AppendErrorWithFormat( "failed to create a value object for: (%s) %s\n", view_as_type_cstr, name_strm.GetData()); - return false; + return; } } - return true; + return; } result.SetStatus(eReturnStatusSuccessFinishResult); @@ -852,7 +849,7 @@ protected: result.AppendErrorWithFormat( "reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size); - return false; + return; } } @@ -863,7 +860,6 @@ protected: exe_scope, m_memory_tag_options.GetShowTags().GetCurrentValue()); m_next_addr = addr + bytes_dumped; output_stream_p->EOL(); - return true; } OptionGroupOptions m_option_group; @@ -1010,7 +1006,7 @@ protected: lldb::addr_t m_base_addr; bool m_is_valid = true; }; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "process" for validity as eCommandRequiresProcess // ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); @@ -1019,7 +1015,7 @@ protected: if (argc != 2) { result.AppendError("two addresses needed for memory find"); - return false; + return; } Status error; @@ -1027,19 +1023,19 @@ protected: &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) { result.AppendError("invalid low address"); - return false; + return; } lldb::addr_t high_addr = OptionArgParser::ToAddress( &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, &error); if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) { result.AppendError("invalid high address"); - return false; + return; } if (high_addr <= low_addr) { result.AppendError( "starting address must be smaller than ending address"); - return false; + return; } lldb::addr_t found_location = LLDB_INVALID_ADDRESS; @@ -1051,7 +1047,7 @@ protected: m_memory_options.m_string.GetValueAs<llvm::StringRef>().value_or(""); if (str.empty()) { result.AppendError("search string must have non-zero length."); - return false; + return; } buffer.CopyData(str); } else if (m_memory_options.m_expr.OptionWasSet()) { @@ -1067,7 +1063,7 @@ protected: std::optional<uint64_t> size = result_sp->GetCompilerType().GetByteSize(nullptr); if (!size) - return false; + return; switch (*size) { case 1: { uint8_t byte = (uint8_t)value; @@ -1089,21 +1085,21 @@ protected: case 6: case 7: result.AppendError("unknown type. pass a string instead"); - return false; + return; default: result.AppendError( "result size larger than 8 bytes. pass a string instead"); - return false; + return; } } else { result.AppendError( "expression evaluation failed. pass a string instead"); - return false; + return; } } else { result.AppendError( "please pass either a block of text, or an expression to evaluate."); - return false; + return; } size_t count = m_memory_options.m_count.GetCurrentValue(); @@ -1146,7 +1142,6 @@ protected: } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); - return true; } lldb::addr_t FastSearch(lldb::addr_t low, lldb::addr_t high, uint8_t *buffer, @@ -1291,7 +1286,7 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "process" for validity as eCommandRequiresProcess // ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); @@ -1303,19 +1298,19 @@ protected: result.AppendErrorWithFormat( "%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); - return false; + return; } if (argc > 1) { result.AppendErrorWithFormat( "%s takes only a destination address when writing file contents.\n", m_cmd_name.c_str()); - return false; + return; } } else if (argc < 2) { result.AppendErrorWithFormat( "%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); - return false; + return; } StreamString buffer( @@ -1333,7 +1328,7 @@ protected: if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid address expression\n"); result.AppendError(error.AsCString()); - return false; + return; } if (m_memory_options.m_infile) { @@ -1372,7 +1367,7 @@ protected: } else { result.AppendErrorWithFormat("Unable to read contents of file.\n"); } - return result.Succeeded(); + return; } else if (item_byte_size == 0) { if (m_format_options.GetFormat() == eFormatPointer) item_byte_size = buffer.GetAddressByteSize(); @@ -1415,7 +1410,7 @@ protected: case eFormatInstruction: case eFormatVoid: result.AppendError("unsupported format for writing memory"); - return false; + return; case eFormatDefault: case eFormatBytes: @@ -1426,20 +1421,20 @@ protected: // Be careful, getAsInteger with a radix of 16 rejects "0xab" so we // have to special case that: bool success = false; - if (entry.ref().startswith("0x")) + if (entry.ref().starts_with("0x")) success = !entry.ref().getAsInteger(0, uval64); if (!success) success = !entry.ref().getAsInteger(16, uval64); if (!success) { result.AppendErrorWithFormat( "'%s' is not a valid hex string value.\n", entry.c_str()); - return false; + return; } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) { result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - return false; + return; } buffer.PutMaxHex64(uval64, item_byte_size); break; @@ -1449,7 +1444,7 @@ protected: if (!success) { result.AppendErrorWithFormat( "'%s' is not a valid boolean string value.\n", entry.c_str()); - return false; + return; } buffer.PutMaxHex64(uval64, item_byte_size); break; @@ -1458,13 +1453,13 @@ protected: if (entry.ref().getAsInteger(2, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid binary string value.\n", entry.c_str()); - return false; + return; } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) { result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - return false; + return; } buffer.PutMaxHex64(uval64, item_byte_size); break; @@ -1486,7 +1481,7 @@ protected: result.AppendErrorWithFormat("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); - return false; + return; } break; } @@ -1494,13 +1489,13 @@ protected: if (entry.ref().getAsInteger(0, sval64)) { result.AppendErrorWithFormat( "'%s' is not a valid signed decimal value.\n", entry.c_str()); - return false; + return; } else if (!llvm::isIntN(item_byte_size * 8, sval64)) { result.AppendErrorWithFormat( "Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size); - return false; + return; } buffer.PutMaxHex64(sval64, item_byte_size); break; @@ -1511,13 +1506,13 @@ protected: result.AppendErrorWithFormat( "'%s' is not a valid unsigned decimal string value.\n", entry.c_str()); - return false; + return; } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) { result.AppendErrorWithFormat("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - return false; + return; } buffer.PutMaxHex64(uval64, item_byte_size); break; @@ -1526,13 +1521,13 @@ protected: if (entry.ref().getAsInteger(8, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid octal string value.\n", entry.c_str()); - return false; + return; } else if (!llvm::isUIntN(item_byte_size * 8, uval64)) { result.AppendErrorWithFormat("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size); - return false; + return; } buffer.PutMaxHex64(uval64, item_byte_size); break; @@ -1541,18 +1536,18 @@ protected: if (!buffer.GetString().empty()) { Status error; - if (process->WriteMemory(addr, buffer.GetString().data(), - buffer.GetString().size(), - error) == buffer.GetString().size()) - return true; - else { + const char *buffer_data = buffer.GetString().data(); + const size_t buffer_size = buffer.GetString().size(); + const size_t write_size = + process->WriteMemory(addr, buffer_data, buffer_size, error); + + if (write_size != buffer_size) { result.AppendErrorWithFormat("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString()); - return false; + return; } } - return true; } OptionGroupOptions m_option_group; @@ -1595,13 +1590,13 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0 || argc > 1) { result.AppendErrorWithFormat("%s takes an address expression", m_cmd_name.c_str()); - return false; + return; } Status error; @@ -1611,7 +1606,7 @@ protected: if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid address expression"); result.AppendError(error.AsCString()); - return false; + return; } Stream *output_stream = &result.GetOutputStream(); @@ -1622,7 +1617,7 @@ protected: if (!memory_history) { result.AppendError("no available memory history provider"); - return false; + return; } HistoryThreads thread_list = memory_history->GetHistoryThreads(addr); @@ -1633,8 +1628,6 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - - return true; } }; @@ -1747,12 +1740,12 @@ protected: } } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { ProcessSP process_sp = m_exe_ctx.GetProcessSP(); if (!process_sp) { m_prev_end_addr = LLDB_INVALID_ADDRESS; result.AppendError("invalid process"); - return false; + return; } Status error; @@ -1767,7 +1760,7 @@ protected: result.AppendError( "The \"--all\" option cannot be used when an address " "argument is given"); - return false; + return; } auto load_addr_str = command[0].ref(); @@ -1776,7 +1769,7 @@ protected: if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("invalid address argument \"%s\": %s\n", command[0].c_str(), error.AsCString()); - return false; + return; } } else if (argc > 1 || // When we're repeating the command, the previous end address is @@ -1792,10 +1785,10 @@ protected: result.AppendErrorWithFormat( "'%s' takes one argument or \"--all\" option:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); - return false; + return; } - // Is is important that we track the address used to request the region as + // It is important that we track the address used to request the region as // this will give the correct section name in the case that regions overlap. // On Windows we get mutliple regions that start at the same place but are // different sizes and refer to different sections. @@ -1832,11 +1825,10 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } result.AppendErrorWithFormat("%s\n", error.AsCString()); - return false; } std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp index b436a185cd14..f45d6eacab3d 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp @@ -42,12 +42,12 @@ public: ~CommandObjectMemoryTagRead() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if ((command.GetArgumentCount() < 1) || (command.GetArgumentCount() > 2)) { result.AppendError( "wrong number of arguments; expected at least <address-expression>, " "at most <address-expression> <end-address-expression>"); - return false; + return; } Status error; @@ -56,7 +56,7 @@ protected: if (start_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormatv("Invalid address expression, {0}", error.AsCString()); - return false; + return; } // Default 1 byte beyond start, rounds up to at most 1 granule later @@ -68,7 +68,7 @@ protected: if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormatv("Invalid end address expression, {0}", error.AsCString()); - return false; + return; } } @@ -78,7 +78,7 @@ protected: if (!tag_manager_or_err) { result.SetError(Status(tag_manager_or_err.takeError())); - return false; + return; } const MemoryTagManager *tag_manager = *tag_manager_or_err; @@ -103,7 +103,7 @@ protected: if (!tagged_range) { result.SetError(Status(tagged_range.takeError())); - return false; + return; } llvm::Expected<std::vector<lldb::addr_t>> tags = process->ReadMemoryTags( @@ -111,7 +111,7 @@ protected: if (!tags) { result.SetError(Status(tags.takeError())); - return false; + return; } result.AppendMessageWithFormatv("Logical tag: {0:x}", logical_tag); @@ -128,7 +128,6 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } }; @@ -195,11 +194,11 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() < 2) { result.AppendError("wrong number of arguments; expected " "<address-expression> <tag> [<tag> [...]]"); - return false; + return; } Status error; @@ -208,7 +207,7 @@ protected: if (start_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormatv("Invalid address expression, {0}", error.AsCString()); - return false; + return; } command.Shift(); // shift off start address @@ -221,7 +220,7 @@ protected: result.AppendErrorWithFormat( "'%s' is not a valid unsigned decimal string value.\n", entry.c_str()); - return false; + return; } tags.push_back(tag_value); } @@ -232,7 +231,7 @@ protected: if (!tag_manager_or_err) { result.SetError(Status(tag_manager_or_err.takeError())); - return false; + return; } const MemoryTagManager *tag_manager = *tag_manager_or_err; @@ -284,7 +283,7 @@ protected: if (!tagged_range) { result.SetError(Status(tagged_range.takeError())); - return false; + return; } Status status = process->WriteMemoryTags(tagged_range->GetRangeBase(), @@ -292,11 +291,10 @@ protected: if (status.Fail()) { result.SetError(status); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } OptionGroupOptions m_option_group; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp index 7ef829afaab6..4efa5652a717 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp @@ -159,25 +159,25 @@ llvm::Error CommandObjectMultiword::RemoveUserSubcommand(llvm::StringRef cmd_nam return llvm::Error::success(); } -bool CommandObjectMultiword::Execute(const char *args_string, +void CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result) { Args args(args_string); const size_t argc = args.GetArgumentCount(); if (argc == 0) { this->CommandObject::GenerateHelpText(result); - return result.Succeeded(); + return; } auto sub_command = args[0].ref(); if (sub_command.empty()) { result.AppendError("Need to specify a non-empty subcommand."); - return result.Succeeded(); + return; } if (m_subcommand_dict.empty()) { result.AppendErrorWithFormat("'%s' does not have any subcommands.\n", GetCommandName().str().c_str()); - return false; + return; } StringList matches; @@ -189,7 +189,7 @@ bool CommandObjectMultiword::Execute(const char *args_string, args.Shift(); sub_cmd_obj->Execute(args_string, result); - return result.Succeeded(); + return; } std::string error_msg; @@ -214,7 +214,6 @@ bool CommandObjectMultiword::Execute(const char *args_string, } error_msg.append("\n"); result.AppendRawError(error_msg.c_str()); - return false; } void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) { @@ -429,11 +428,10 @@ llvm::StringRef CommandObjectProxy::GetUnsupportedError() { return "command is not implemented"; } -bool CommandObjectProxy::Execute(const char *args_string, +void CommandObjectProxy::Execute(const char *args_string, CommandReturnObject &result) { - CommandObject *proxy_command = GetProxyCommandObject(); - if (proxy_command) - return proxy_command->Execute(args_string, result); - result.AppendError(GetUnsupportedError()); - return false; + if (CommandObject *proxy_command = GetProxyCommandObject()) + proxy_command->Execute(args_string, result); + else + result.AppendError(GetUnsupportedError()); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp index 54115b51be78..790f1dbb4753 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp @@ -169,7 +169,7 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() == 1) { const char *platform_name = args.GetArgumentAtIndex(0); if (platform_name && platform_name[0]) { @@ -194,7 +194,6 @@ protected: result.AppendError( "platform create takes a platform name as an argument\n"); } - return result.Succeeded(); } OptionGroupOptions m_option_group; @@ -212,7 +211,7 @@ public: ~CommandObjectPlatformList() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Stream &ostrm = result.GetOutputStream(); ostrm.Printf("Available platforms:\n"); @@ -235,7 +234,6 @@ protected: result.AppendError("no platforms are available\n"); } else result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -250,7 +248,7 @@ public: ~CommandObjectPlatformStatus() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Stream &ostrm = result.GetOutputStream(); Target *target = GetDebugger().GetSelectedTarget().get(); @@ -267,7 +265,6 @@ protected: } else { result.AppendError("no platform is currently selected\n"); } - return result.Succeeded(); } }; @@ -286,7 +283,7 @@ public: ~CommandObjectPlatformConnect() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Stream &ostrm = result.GetOutputStream(); PlatformSP platform_sp( @@ -307,7 +304,6 @@ protected: } else { result.AppendError("no platform is currently selected\n"); } - return result.Succeeded(); } Options *GetOptions() override { @@ -334,7 +330,7 @@ public: ~CommandObjectPlatformDisconnect() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -374,7 +370,6 @@ protected: } else { result.AppendError("no platform is currently selected"); } - return result.Succeeded(); } }; @@ -394,7 +389,7 @@ public: ~CommandObjectPlatformSettings() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -404,7 +399,6 @@ protected: } else { result.AppendError("no platform is currently selected"); } - return result.Succeeded(); } Options *GetOptions() override { @@ -430,7 +424,7 @@ public: ~CommandObjectPlatformMkDir() override = default; - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -453,7 +447,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } Options *GetOptions() override { @@ -489,7 +482,7 @@ public: nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -517,7 +510,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } Options *GetOptions() override { @@ -544,7 +536,7 @@ public: ~CommandObjectPlatformFClose() override = default; - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -554,7 +546,7 @@ public: if (!llvm::to_integer(cmd_line, fd)) { result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n", cmd_line); - return result.Succeeded(); + return; } Status error; bool success = platform_sp->CloseFile(fd, error); @@ -567,7 +559,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } }; @@ -588,7 +579,7 @@ public: ~CommandObjectPlatformFRead() override = default; - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -598,7 +589,7 @@ public: if (!llvm::to_integer(cmd_line, fd)) { result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n", cmd_line); - return result.Succeeded(); + return; } std::string buffer(m_options.m_count, 0); Status error; @@ -614,7 +605,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } Options *GetOptions() override { return &m_options; } @@ -684,7 +674,7 @@ public: ~CommandObjectPlatformFWrite() override = default; - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -695,7 +685,7 @@ public: if (!llvm::to_integer(cmd_line, fd)) { result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.", cmd_line); - return result.Succeeded(); + return; } uint64_t retcode = platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0], @@ -709,7 +699,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } Options *GetOptions() override { return &m_options; } @@ -839,12 +828,12 @@ public: GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 2) { result.AppendError("required arguments missing; specify both the " "source and destination file paths"); - return false; + return; } PlatformSP platform_sp( @@ -866,7 +855,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } }; @@ -911,12 +899,12 @@ public: nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 1) { result.AppendError("required argument missing; specify the source file " "path as the only argument"); - return false; + return; } PlatformSP platform_sp( @@ -937,7 +925,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } }; @@ -982,12 +969,12 @@ public: nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 1) { result.AppendError("required argument missing; specify the source file " "path as the only argument"); - return false; + return; } PlatformSP platform_sp( @@ -1007,7 +994,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } }; @@ -1052,12 +1038,12 @@ public: nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 1) { result.AppendError("required argument missing; specify the source file " "path as the only argument"); - return false; + return; } PlatformSP platform_sp( @@ -1072,7 +1058,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } }; @@ -1114,7 +1099,7 @@ public: nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { const char *src = args.GetArgumentAtIndex(0); const char *dst = args.GetArgumentAtIndex(1); @@ -1134,7 +1119,6 @@ public: } else { result.AppendError("no platform currently selected\n"); } - return result.Succeeded(); } }; @@ -1160,7 +1144,7 @@ public: Options *GetOptions() override { return &m_all_options; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = GetDebugger().GetSelectedTarget().get(); PlatformSP platform_sp; if (target) { @@ -1220,10 +1204,10 @@ protected: if (!process_sp && error.Success()) { result.AppendError("failed to launch or debug process"); - return false; + return; } else if (!error.Success()) { result.AppendError(error.AsCString()); - return false; + return; } const bool synchronous_execution = @@ -1242,7 +1226,7 @@ protected: if (rebroadcast_first_stop) { assert(first_stop_event_sp); process_sp->BroadcastEvent(first_stop_event_sp); - return true; + return; } switch (state) { @@ -1272,18 +1256,17 @@ protected: if (process_sp && process_sp->IsAlive()) { result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } } else { result.AppendError("'platform process launch' uses the current target " "file and arguments, or the executable and its " "arguments can be specified in this command"); - return false; + return; } } else { result.AppendError("no platform is selected\n"); } - return result.Succeeded(); } CommandOptionsProcessLaunch m_options; @@ -1310,7 +1293,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = GetDebugger().GetSelectedTarget().get(); PlatformSP platform_sp; if (target) { @@ -1398,7 +1381,6 @@ protected: } else { result.AppendError("no platform is selected\n"); } - return result.Succeeded(); } class CommandOptions : public Options { @@ -1578,7 +1560,7 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = GetDebugger().GetSelectedTarget().get(); PlatformSP platform_sp; if (target) { @@ -1627,7 +1609,6 @@ protected: } else { result.AppendError("no platform is currently selected"); } - return result.Succeeded(); } }; @@ -1649,7 +1630,7 @@ public: ~CommandObjectPlatformProcessAttach() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -1673,7 +1654,6 @@ public: } else { result.AppendError("no platform is currently selected"); } - return result.Succeeded(); } Options *GetOptions() override { return &m_all_options; } @@ -1788,7 +1768,7 @@ public: Options *GetOptions() override { return &m_options; } - bool DoExecute(llvm::StringRef raw_command_line, + void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); m_options.NotifyOptionParsingStarting(&exe_ctx); @@ -1796,7 +1776,7 @@ public: // Print out an usage syntax on an empty command line. if (raw_command_line.empty()) { result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str()); - return true; + return; } const bool is_alias = !raw_command_line.contains("platform"); @@ -1804,12 +1784,12 @@ public: if (args.HasArgs()) if (!ParseOptions(args.GetArgs(), result)) - return false; + return; if (args.GetRawPart().empty()) { result.GetOutputStream().Printf("%s <shell-command>\n", is_alias ? "shell" : "platform shell"); - return false; + return; } llvm::StringRef cmd = args.GetRawPart(); @@ -1856,7 +1836,6 @@ public: } else { result.SetStatus(eReturnStatusSuccessFinishResult); } - return true; } CommandOptions m_options; @@ -1887,10 +1866,10 @@ public: GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() != 2) { result.AppendError("platform target-install takes two arguments"); - return false; + return; } // TODO: move the bulk of this code over to the platform itself FileSpec src(args.GetArgumentAtIndex(0)); @@ -1898,13 +1877,13 @@ public: FileSpec dst(args.GetArgumentAtIndex(1)); if (!FileSystem::Instance().Exists(src)) { result.AppendError("source location does not exist or is not accessible"); - return false; + return; } PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); if (!platform_sp) { result.AppendError("no platform currently selected"); - return false; + return; } Status error = platform_sp->Install(src, dst); @@ -1913,7 +1892,6 @@ public: } else { result.AppendErrorWithFormat("install failed: %s", error.AsCString()); } - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp index 8661ebb5022b..f22885144b09 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlugin.cpp @@ -44,12 +44,12 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { size_t argc = command.GetArgumentCount(); if (argc != 1) { result.AppendError("'plugin load' requires one argument"); - return false; + return; } Status error; @@ -62,8 +62,6 @@ protected: else { result.AppendError(error.AsCString()); } - - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp index ab047ee926c9..6dc7648f872d 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp @@ -160,7 +160,7 @@ public: } protected: - bool DoExecute(Args &launch_args, CommandReturnObject &result) override { + void DoExecute(Args &launch_args, CommandReturnObject &result) override { Debugger &debugger = GetDebugger(); Target *target = debugger.GetSelectedTarget().get(); // If our listener is nullptr, users aren't allows to launch @@ -174,13 +174,13 @@ protected: if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) { result.AppendError("no file in target, create a debug target using the " "'target create' command"); - return false; + return; } StateType state = eStateInvalid; if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) - return false; + return; // Determine whether we will disable ASLR or leave it in the default state // (i.e. enabled if the platform supports it). First check if the process @@ -264,9 +264,6 @@ protected: // PushProcessIOHandler(). process_sp->SyncIOHandler(0, std::chrono::seconds(2)); - llvm::StringRef data = stream.GetString(); - if (!data.empty()) - result.AppendMessage(data); // If we didn't have a local executable, then we wouldn't have had an // executable module before launch. if (!exe_module_sp) @@ -282,6 +279,11 @@ protected: exe_module_sp->GetFileSpec().GetPath().c_str(), archname); } result.SetStatus(eReturnStatusSuccessFinishResult); + // This message will refer to an event that happened after the process + // launched. + llvm::StringRef data = stream.GetString(); + if (!data.empty()) + result.AppendMessage(data); result.SetDidChangeProcessState(true); } else { result.AppendError( @@ -290,7 +292,6 @@ protected: } else { result.AppendError(error.AsCString()); } - return result.Succeeded(); } CommandOptionsProcessLaunch m_options; @@ -320,7 +321,7 @@ public: Options *GetOptions() override { return &m_all_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); @@ -334,7 +335,7 @@ protected: Process *process = m_exe_ctx.GetProcessPtr(); if (!StopProcessIfNecessary(process, state, result)) - return false; + return; if (target == nullptr) { // If there isn't a current target create one. @@ -348,7 +349,7 @@ protected: target = new_target_sp.get(); if (target == nullptr || error.Fail()) { result.AppendError(error.AsCString("Error creating target")); - return false; + return; } } @@ -384,7 +385,7 @@ protected: } if (!result.Succeeded()) - return false; + return; // Okay, we're done. Last step is to warn if the executable module has // changed: @@ -429,8 +430,6 @@ protected: ExecutionContext exe_ctx(process_sp); m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result); } - - return result.Succeeded(); } CommandOptionsProcessAttach m_options; @@ -504,8 +503,7 @@ protected: bool m_any_bkpts_specified = false; }; - - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); bool synchronous_execution = m_interpreter.GetSynchronous(); StateType state = process->GetState(); @@ -521,10 +519,10 @@ protected: BreakpointSiteSP bp_site_sp( process->GetBreakpointSiteList().FindByID(bp_site_id)); if (bp_site_sp) { - const size_t num_owners = bp_site_sp->GetNumberOfOwners(); + const size_t num_owners = bp_site_sp->GetNumberOfConstituents(); for (size_t i = 0; i < num_owners; i++) { Breakpoint &bp_ref = - bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); + bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint(); if (!bp_ref.IsInternal()) { bp_ref.SetIgnoreCount(m_options.m_ignore); } @@ -543,13 +541,13 @@ protected: m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids, BreakpointName::Permissions::disablePerm); if (!result.Succeeded()) { - return false; + return; } result.Clear(); if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) { result.AppendError("continue-to breakpoints did not specify any actual " "breakpoints or locations"); - return false; + return; } // First figure out which breakpoints & locations were specified by the @@ -612,7 +610,7 @@ protected: if (!any_enabled) { result.AppendError("at least one of the continue-to breakpoints must " "be enabled."); - return false; + return; } // Also, if you specify BOTH a breakpoint and one of it's locations, @@ -737,7 +735,6 @@ protected: "Process cannot be continued from its current state (%s).\n", StateAsCString(state)); } - return result.Succeeded(); } Options *GetOptions() override { return &m_options; } @@ -809,7 +806,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); // FIXME: This will be a Command Option: bool keep_stopped; @@ -826,9 +823,7 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString()); - return false; } - return result.Succeeded(); } CommandOptions m_options; @@ -894,12 +889,12 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat( "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); - return false; + return; } Process *process = m_exe_ctx.GetProcessPtr(); @@ -908,7 +903,7 @@ protected: "Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", process->GetID()); - return false; + return; } const char *plugin_name = nullptr; @@ -929,9 +924,7 @@ protected: error); if (error.Fail() || process_sp == nullptr) { result.AppendError(error.AsCString("Error connecting to the process")); - return false; } - return true; } CommandOptions m_options; @@ -1032,7 +1025,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); for (auto &entry : command.entries()) { @@ -1071,7 +1064,6 @@ protected: error.AsCString()); } } - return result.Succeeded(); } CommandOptions m_options; @@ -1115,7 +1107,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); for (auto &entry : command.entries()) { @@ -1138,7 +1130,6 @@ protected: } } } - return result.Succeeded(); } }; @@ -1178,13 +1169,13 @@ public: UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals(); int signo = signals->GetFirstSignalNumber(); while (signo != LLDB_INVALID_SIGNAL_NUMBER) { - request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo)); + request.TryCompleteCurrentArg(signals->GetSignalAsStringRef(signo)); signo = signals->GetNextSignalNumber(signo); } } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (command.GetArgumentCount() == 1) { @@ -1214,7 +1205,6 @@ protected: "'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); } - return result.Succeeded(); } }; @@ -1233,11 +1223,11 @@ public: ~CommandObjectProcessInterrupt() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process to halt"); - return false; + return; } bool clear_thread_plans = true; @@ -1248,7 +1238,6 @@ protected: result.AppendErrorWithFormat("Failed to halt process: %s\n", error.AsCString()); } - return result.Succeeded(); } }; @@ -1267,11 +1256,11 @@ public: ~CommandObjectProcessKill() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process to kill"); - return false; + return; } Status error(process->Destroy(true)); @@ -1281,7 +1270,6 @@ protected: result.AppendErrorWithFormat("Failed to kill process: %s\n", error.AsCString()); } - return result.Succeeded(); } }; @@ -1356,7 +1344,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { ProcessSP process_sp = m_exe_ctx.GetProcessSP(); if (process_sp) { if (command.GetArgumentCount() == 1) { @@ -1390,10 +1378,7 @@ protected: } } else { result.AppendError("invalid process"); - return false; } - - return result.Succeeded(); } CommandOptions m_options; @@ -1451,7 +1436,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -1483,7 +1468,7 @@ protected: PlatformSP platform_sp = process->GetTarget().GetPlatform(); if (!platform_sp) { result.AppendError("Couldn'retrieve the target's platform"); - return result.Succeeded(); + return; } auto expected_crash_info = @@ -1491,7 +1476,7 @@ protected: if (!expected_crash_info) { result.AppendError(llvm::toString(expected_crash_info.takeError())); - return result.Succeeded(); + return; } StructuredData::DictionarySP crash_info_sp = *expected_crash_info; @@ -1502,8 +1487,6 @@ protected: crash_info_sp->GetDescription(strm); } } - - return result.Succeeded(); } private: @@ -1635,13 +1618,13 @@ public: str.Printf("=========== ===== ===== ======\n"); } - void PrintSignal(Stream &str, int32_t signo, const char *sig_name, + void PrintSignal(Stream &str, int32_t signo, llvm::StringRef sig_name, const UnixSignalsSP &signals_sp) { bool stop; bool suppress; bool notify; - str.Printf("%-11s ", sig_name); + str.Format("{0, -11} ", sig_name); if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) { bool pass = !suppress; str.Printf("%s %s %s", (pass ? "true " : "false"), @@ -1668,7 +1651,7 @@ public: { int32_t signo = signals_sp->GetFirstSignalNumber(); while (signo != LLDB_INVALID_SIGNAL_NUMBER) { - PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), + PrintSignal(str, signo, signals_sp->GetSignalAsStringRef(signo), signals_sp); signo = signals_sp->GetNextSignalNumber(signo); } @@ -1676,7 +1659,7 @@ public: } protected: - bool DoExecute(Args &signal_args, CommandReturnObject &result) override { + void DoExecute(Args &signal_args, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); // Any signals that are being set should be added to the Target's @@ -1693,28 +1676,28 @@ protected: !VerifyCommandOptionValue(m_options.stop, stop_action)) { result.AppendError("Invalid argument for command option --stop; must be " "true or false.\n"); - return false; + return; } if (!m_options.notify.empty() && !VerifyCommandOptionValue(m_options.notify, notify_action)) { result.AppendError("Invalid argument for command option --notify; must " "be true or false.\n"); - return false; + return; } if (!m_options.pass.empty() && !VerifyCommandOptionValue(m_options.pass, pass_action)) { result.AppendError("Invalid argument for command option --pass; must be " "true or false.\n"); - return false; + return; } bool no_actions = (stop_action == -1 && pass_action == -1 && notify_action == -1); if (m_options.only_target_values && !no_actions) { result.AppendError("-t is for reporting, not setting, target values."); - return false; + return; } size_t num_args = signal_args.GetArgumentCount(); @@ -1729,7 +1712,7 @@ protected: if (m_options.only_target_values) { target.PrintDummySignals(result.GetOutputStream(), signal_args); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } // This handles clearing values: @@ -1738,7 +1721,7 @@ protected: if (m_options.dummy) GetDummyTarget().ClearDummySignals(signal_args); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } // This rest handles setting values: @@ -1774,7 +1757,7 @@ protected: if (llvm::to_integer(arg.c_str(), signo)) { result.AppendErrorWithFormat("Can't set signal handling by signal " "number with no process"); - return false; + return; } num_signals_set = num_args; } @@ -1831,8 +1814,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); else result.SetStatus(eReturnStatusFailed); - - return result.Succeeded(); } CommandOptions m_options; @@ -1873,7 +1854,7 @@ public: ~CommandObjectProcessTraceStop() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { ProcessSP process_sp = m_exe_ctx.GetProcessSP(); TraceSP trace_sp = process_sp->GetTarget().GetTrace(); @@ -1882,8 +1863,6 @@ public: result.AppendError(toString(std::move(err))); else result.SetStatus(eReturnStatusSuccessFinishResult); - - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.cpp index 650cfca2c050..d7caf1546fb5 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.cpp @@ -62,7 +62,7 @@ bool CommandObjectQuit::ShouldAskForConfirmation(bool &is_a_detach) { return should_prompt; } -bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) { +void CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) { bool is_a_detach = true; if (ShouldAskForConfirmation(is_a_detach)) { StreamString message; @@ -71,14 +71,14 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) { (is_a_detach ? "detach from" : "kill")); if (!m_interpreter.Confirm(message.GetString(), true)) { result.SetStatus(eReturnStatusFailed); - return false; + return; } } if (command.GetArgumentCount() > 1) { result.AppendError("Too many arguments for 'quit'. Only an optional exit " "code is allowed"); - return false; + return; } // We parse the exit code argument if there is one. @@ -90,12 +90,12 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) { std::string arg_str = arg.str(); s.Printf("Couldn't parse '%s' as integer for exit code.", arg_str.data()); result.AppendError(s.GetString()); - return false; + return; } if (!m_interpreter.SetQuitExitCode(exit_code)) { result.AppendError("The current driver doesn't allow custom exit codes" " for the quit command."); - return false; + return; } } @@ -103,6 +103,4 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) { CommandInterpreter::eBroadcastBitQuitCommandReceived; m_interpreter.BroadcastEvent(event_type); result.SetStatus(eReturnStatusQuit); - - return true; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.h index ccbd863cd6f5..c27c0d1da3b9 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectQuit.h @@ -22,7 +22,7 @@ public: ~CommandObjectQuit() override; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override; + void DoExecute(Args &args, CommandReturnObject &result) override; bool ShouldAskForConfirmation(bool &is_a_detach); }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp index 6ff1d281504a..f638d707e17e 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.cpp @@ -54,7 +54,7 @@ llvm::Expected<std::string> CommandObjectRegexCommand::SubstituteVariables( return output.str(); } -bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, +void CommandObjectRegexCommand::DoExecute(llvm::StringRef command, CommandReturnObject &result) { EntryCollection::const_iterator pos, end = m_entries.end(); for (pos = m_entries.begin(); pos != end; ++pos) { @@ -64,7 +64,7 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, SubstituteVariables(pos->command, matches); if (!new_command) { result.SetError(new_command.takeError()); - return false; + return; } // Interpret the new command and return this as the result! @@ -73,8 +73,9 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, // We don't have to pass an override_context here, as the command that // called us should have set up the context appropriately. bool force_repeat_command = true; - return m_interpreter.HandleCommand(new_command->c_str(), eLazyBoolNo, - result, force_repeat_command); + m_interpreter.HandleCommand(new_command->c_str(), eLazyBoolNo, result, + force_repeat_command); + return; } } result.SetStatus(eReturnStatusFailed); @@ -85,7 +86,6 @@ bool CommandObjectRegexCommand::DoExecute(llvm::StringRef command, << "' failed to match any " "regular expression in the '" << m_cmd_name << "' regex "; - return false; } bool CommandObjectRegexCommand::AddRegexCommand(llvm::StringRef re_cstr, diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h index 47d493a8fdd7..c78b0b586c37 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegexCommand.h @@ -37,7 +37,7 @@ public: void HandleCompletion(CompletionRequest &request) override; protected: - bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override; /// Substitute variables of the format %\d+ in the input string. static llvm::Expected<std::string> SubstituteVariables( diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp index a0e88f6ab4ba..a4d53e5c8dd5 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp @@ -161,7 +161,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); @@ -234,7 +234,6 @@ protected: } } } - return result.Succeeded(); } class CommandOptions : public OptionGroup { @@ -348,7 +347,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { DataExtractor reg_data; RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); @@ -378,7 +377,7 @@ protected: // has been written. m_exe_ctx.GetThreadRef().Flush(); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } } if (error.AsCString()) { @@ -396,7 +395,6 @@ protected: reg_name.str().c_str()); } } - return result.Succeeded(); } }; @@ -406,8 +404,9 @@ public: CommandObjectRegisterInfo(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "register info", "View information about a register.", nullptr, - eCommandRequiresRegContext | - eCommandProcessMustBeLaunched) { + eCommandRequiresFrame | eCommandRequiresRegContext | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused) { SetHelpLong(R"( Name The name lldb uses for the register, optionally with an alias. Size The size of the register in bytes and again in bits. @@ -446,10 +445,10 @@ different for the same register when connected to different debug servers.)"); } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() != 1) { result.AppendError("register info takes exactly 1 argument: <reg-name>"); - return result.Succeeded(); + return; } llvm::StringRef reg_name = command[0].ref(); @@ -463,8 +462,6 @@ protected: } else result.AppendErrorWithFormat("No register found with name '%s'.\n", reg_name.str().c_str()); - - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp index 7e4f18a0d510..25f25b8e6594 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp @@ -65,14 +65,14 @@ CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter) CommandObjectScript::~CommandObjectScript() = default; -bool CommandObjectScript::DoExecute(llvm::StringRef command, +void CommandObjectScript::DoExecute(llvm::StringRef command, CommandReturnObject &result) { // Try parsing the language option but when the command contains a raw part // separated by the -- delimiter. OptionsWithRaw raw_args(command); if (raw_args.HasArgs()) { if (!ParseOptions(raw_args.GetArgs(), result)) - return false; + return; command = raw_args.GetRawPart(); } @@ -84,7 +84,7 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command, if (language == lldb::eScriptLanguageNone) { result.AppendError( "the script-lang setting is set to none - scripting not available"); - return false; + return; } ScriptInterpreter *script_interpreter = @@ -92,7 +92,7 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command, if (script_interpreter == nullptr) { result.AppendError("no script interpreter"); - return false; + return; } // Script might change Python code we use for formatting. Make sure we keep @@ -102,7 +102,7 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command, if (command.empty()) { script_interpreter->ExecuteInterpreterLoop(); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + return; } // We can do better when reporting the status of one-liner script execution. @@ -110,6 +110,4 @@ bool CommandObjectScript::DoExecute(llvm::StringRef command, result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusFailed); - - return result.Succeeded(); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.h index 9d164e864a8b..3a8c4a890404 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.h @@ -31,7 +31,7 @@ public: }; protected: - bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override; private: CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp index 6bf1ec99c888..d140bdfdba57 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp @@ -36,7 +36,7 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { llvm::StringRef file_path; if (!args.empty()) @@ -46,7 +46,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishNoResult); else result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); } }; @@ -127,7 +126,7 @@ protected: OptionValueBoolean m_clear; }; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet()) { m_interpreter.GetCommandHistory().Clear(); @@ -189,7 +188,6 @@ protected: stop_idx.second); } } - return result.Succeeded(); } CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp index 7069cb1d8399..5fb7dcc80279 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp @@ -169,27 +169,27 @@ insert-before or insert-after."); } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { Args cmd_args(command); // Process possible options. if (!ParseOptions(cmd_args, result)) - return false; + return; const size_t min_argc = m_options.m_force ? 1 : 2; const size_t argc = cmd_args.GetArgumentCount(); if ((argc < min_argc) && (!m_options.m_global)) { result.AppendError("'settings set' takes more arguments"); - return false; + return; } const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError( "'settings set' command requires a valid variable name"); - return false; + return; } // A missing value corresponds to clearing the setting when "force" is @@ -199,9 +199,8 @@ protected: &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } - return result.Succeeded(); + return; } // Split the raw command into var_name and value pair. @@ -227,11 +226,10 @@ protected: if (error.Fail() && !m_options.m_exists) { result.AppendError(error.AsCString()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } private: @@ -273,7 +271,7 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishResult); if (!args.empty()) { @@ -291,8 +289,6 @@ protected: GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue); } - - return result.Succeeded(); } }; @@ -368,7 +364,7 @@ public: }; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { FileSpec file_spec(m_options.m_filename); FileSystem::Instance().Resolve(file_spec); std::string path(file_spec.GetPath()); @@ -383,7 +379,7 @@ protected: if (!out_file.GetFile().IsValid()) { result.AppendErrorWithFormat("%s: unable to write to file", path.c_str()); - return false; + return; } // Exporting should not be context sensitive. @@ -392,7 +388,7 @@ protected: if (args.empty()) { GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file, OptionValue::eDumpGroupExport); - return result.Succeeded(); + return; } for (const auto &arg : args) { @@ -402,8 +398,6 @@ protected: result.AppendError(error.AsCString()); } } - - return result.Succeeded(); } private: @@ -461,7 +455,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { FileSpec file(m_options.m_filename); FileSystem::Instance().Resolve(file); CommandInterpreterRunOptions options; @@ -471,7 +465,6 @@ protected: options.SetPrintErrors(true); options.SetStopOnError(false); m_interpreter.HandleCommandsFromFile(file, options, result); - return result.Succeeded(); } private: @@ -517,7 +510,7 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishResult); const size_t argc = args.GetArgumentCount(); @@ -543,8 +536,6 @@ protected: GetDebugger().DumpAllDescriptions(m_interpreter, result.GetOutputStream()); } - - return result.Succeeded(); } }; @@ -601,7 +592,7 @@ public: } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -609,7 +600,7 @@ protected: // Process possible options. if (!ParseOptions(cmd_args, result)) - return false; + return; const size_t argc = cmd_args.GetArgumentCount(); if (argc == 0) { @@ -617,14 +608,14 @@ protected: "or an array followed by one or more indexes, or a " "dictionary followed by one or more key names to " "remove"); - return false; + return; } const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError( "'settings remove' command requires a valid variable name"); - return false; + return; } // Split the raw command into var_name and value pair. @@ -635,10 +626,7 @@ protected: &m_exe_ctx, eVarSetOperationRemove, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } - - return result.Succeeded(); } }; @@ -709,7 +697,7 @@ public: } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -718,7 +706,7 @@ protected: if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError("'settings replace' command requires a valid variable " "name; No value supplied"); - return false; + return; } // Split the raw command into var_name, index_value, and value triple. @@ -729,12 +717,9 @@ protected: &m_exe_ctx, eVarSetOperationReplace, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } else { result.SetStatus(eReturnStatusSuccessFinishNoResult); } - - return result.Succeeded(); } }; @@ -801,7 +786,7 @@ public: } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -810,14 +795,14 @@ protected: if (argc < 3) { result.AppendError("'settings insert-before' takes more arguments"); - return false; + return; } const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError("'settings insert-before' command requires a valid " "variable name; No value supplied"); - return false; + return; } // Split the raw command into var_name, index_value, and value triple. @@ -828,10 +813,7 @@ protected: &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } - - return result.Succeeded(); } }; @@ -897,7 +879,7 @@ public: } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -906,14 +888,14 @@ protected: if (argc < 3) { result.AppendError("'settings insert-after' takes more arguments"); - return false; + return; } const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError("'settings insert-after' command requires a valid " "variable name; No value supplied"); - return false; + return; } // Split the raw command into var_name, index_value, and value triple. @@ -924,10 +906,7 @@ protected: &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } - - return result.Succeeded(); } }; @@ -982,7 +961,7 @@ public: } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishNoResult); Args cmd_args(command); @@ -990,14 +969,14 @@ protected: if (argc < 2) { result.AppendError("'settings append' takes more arguments"); - return false; + return; } const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError("'settings append' command requires a valid variable " "name; No value supplied"); - return false; + return; } // Do not perform cmd_args.Shift() since StringRef is manipulating the raw @@ -1011,10 +990,7 @@ protected: &m_exe_ctx, eVarSetOperationAppend, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } - - return result.Succeeded(); } }; @@ -1089,39 +1065,36 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { result.SetStatus(eReturnStatusSuccessFinishNoResult); const size_t argc = command.GetArgumentCount(); if (m_options.m_clear_all) { if (argc != 0) { result.AppendError("'settings clear --all' doesn't take any arguments"); - return false; + return; } GetDebugger().GetValueProperties()->Clear(); - return result.Succeeded(); + return; } if (argc != 1) { result.AppendError("'settings clear' takes exactly one argument"); - return false; + return; } const char *var_name = command.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError("'settings clear' command requires a valid variable " "name; No value supplied"); - return false; + return; } Status error(GetDebugger().SetPropertyValue( &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef())); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; } - - return result.Succeeded(); } private: diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp index 16452c1784bd..db158a7f5263 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp @@ -532,14 +532,14 @@ protected: return true; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); if (target == nullptr) { target = GetDebugger().GetSelectedTarget().get(); if (target == nullptr) { result.AppendError("invalid target, create a debug target using the " "'target create' command."); - return false; + return; } } @@ -562,11 +562,11 @@ protected: } if (!m_module_list.GetSize()) { result.AppendError("No modules match the input."); - return false; + return; } } else if (target->GetImages().GetSize() == 0) { result.AppendError("The target has no associated executable images."); - return false; + return; } // Check the arguments to see what lines we should dump. @@ -595,7 +595,6 @@ protected: else result.SetStatus(eReturnStatusFailed); } - return result.Succeeded(); } CommandOptions m_options; @@ -910,7 +909,7 @@ protected: } } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); if (!m_options.symbol_name.empty()) { @@ -939,7 +938,7 @@ protected: if (sc_list.GetSize() == 0) { result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str()); - return false; + return; } std::set<SourceInfo> source_match_set; @@ -958,7 +957,7 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); else result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); + return; } else if (m_options.address != LLDB_INVALID_ADDRESS) { Address so_addr; StreamString error_strm; @@ -987,7 +986,7 @@ protected: "no modules have source information for file address 0x%" PRIx64 ".\n", m_options.address); - return false; + return; } } else { // The target has some things loaded, resolve this address to a compile @@ -1009,7 +1008,7 @@ protected: "is no line table information " "available for this address.\n", error_strm.GetData()); - return false; + return; } } } @@ -1018,7 +1017,7 @@ protected: result.AppendErrorWithFormat( "no modules contain load address 0x%" PRIx64 ".\n", m_options.address); - return false; + return; } } for (const SymbolContext &sc : sc_list) { @@ -1134,7 +1133,7 @@ protected: if (num_matches == 0) { result.AppendErrorWithFormat("Could not find source file \"%s\".\n", m_options.file_name.c_str()); - return false; + return; } if (num_matches > 1) { @@ -1155,7 +1154,7 @@ protected: result.AppendErrorWithFormat( "Multiple source files found matching: \"%s.\"\n", m_options.file_name.c_str()); - return false; + return; } } @@ -1184,11 +1183,9 @@ protected: } else { result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n", m_options.file_name.c_str()); - return false; } } } - return result.Succeeded(); } const SymbolContextList *GetBreakpointLocations() { @@ -1213,7 +1210,7 @@ public: ~CommandObjectSourceCacheDump() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // Dump the debugger source cache. result.GetOutputStream() << "Debugger Source File Cache\n"; SourceManager::SourceFileCache &cache = GetDebugger().GetSourceFileCache(); @@ -1227,7 +1224,6 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1240,7 +1236,7 @@ public: ~CommandObjectSourceCacheClear() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // Clear the debugger cache. SourceManager::SourceFileCache &cache = GetDebugger().GetSourceFileCache(); cache.Clear(); @@ -1250,7 +1246,6 @@ protected: process_sp->GetSourceFileCache().Clear(); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.h index f2117bd6ca3f..d552508f448e 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.h @@ -1,5 +1,4 @@ -//===-- CommandObjectSource.h.h -----------------------------------*- C++ -//-*-===// +//===-- CommandObjectSource.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. @@ -14,8 +13,6 @@ namespace lldb_private { -// CommandObjectMultiwordSource - class CommandObjectMultiwordSource : public CommandObjectMultiword { public: CommandObjectMultiwordSource(CommandInterpreter &interpreter); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp index b0b497cd80ba..262de0bda144 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp @@ -26,15 +26,14 @@ public: ~CommandObjectStatsEnable() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (DebuggerStats::GetCollectingStats()) { result.AppendError("statistics already enabled"); - return false; + return; } DebuggerStats::SetCollectingStats(true); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } }; @@ -48,15 +47,14 @@ public: ~CommandObjectStatsDisable() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (!DebuggerStats::GetCollectingStats()) { result.AppendError("need to enable statistics before disabling them"); - return false; + return; } DebuggerStats::SetCollectingStats(false); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } }; @@ -105,7 +103,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = nullptr; if (!m_options.m_all_targets) target = m_exe_ctx.GetTargetPtr(); @@ -113,7 +111,6 @@ protected: result.AppendMessageWithFormatv( "{0:2}", DebuggerStats::ReportStatistics(GetDebugger(), target)); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp index 3e024ff91b38..bc8bc51356c8 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp @@ -8,10 +8,12 @@ #include "CommandObjectTarget.h" +#include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" @@ -35,7 +37,6 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/LineTable.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/UnwindPlan.h" @@ -52,6 +53,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/State.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/Utility/Timer.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private-enumerations.h" @@ -61,6 +63,7 @@ #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatAdapters.h" @@ -261,7 +264,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue()); FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue()); @@ -274,7 +277,7 @@ protected: result.AppendErrorWithFormatv("Cannot open '{0}': {1}.", core_file.GetPath(), llvm::toString(file.takeError())); - return false; + return; } } @@ -288,7 +291,7 @@ protected: result.AppendErrorWithFormatv("Cannot open '{0}': {1}.", symfile.GetPath(), llvm::toString(file.takeError())); - return false; + return; } } @@ -308,7 +311,7 @@ protected: if (!target_sp) { result.AppendError(error.AsCString()); - return false; + return; } const llvm::StringRef label = @@ -316,7 +319,7 @@ protected: if (!label.empty()) { if (auto E = target_sp->SetLabel(label)) result.SetError(std::move(E)); - return false; + return; } auto on_error = llvm::make_scope_exit( @@ -351,7 +354,7 @@ protected: Status err = platform_sp->PutFile(file_spec, remote_file); if (err.Fail()) { result.AppendError(err.AsCString()); - return false; + return; } } } else { @@ -365,7 +368,7 @@ protected: Status err = platform_sp->GetFile(remote_file, file_spec); if (err.Fail()) { result.AppendError(err.AsCString()); - return false; + return; } } else { // If the remote file exists, we can debug reading that out of @@ -379,12 +382,12 @@ protected: if (platform_sp->IsHost()) { result.AppendError("Supply a local file, not a remote file, " "when debugging on the host."); - return false; + return; } if (platform_sp->IsConnected() && !platform_sp->GetFileExists(remote_file)) { result.AppendError("remote --> local transfer without local " "path is not implemented yet"); - return false; + return; } // Since there's only a remote file, we need to set the executable // file spec to the remote one. @@ -395,7 +398,7 @@ protected: } } else { result.AppendError("no platform found for target"); - return false; + return; } } @@ -434,9 +437,8 @@ protected: error = process_sp->LoadCore(); if (error.Fail()) { - result.AppendError( - error.AsCString("can't find plug-in for core file")); - return false; + result.AppendError(error.AsCString("unknown core file format")); + return; } else { result.AppendMessageWithFormatv( "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(), @@ -445,9 +447,8 @@ protected: on_error.release(); } } else { - result.AppendErrorWithFormatv( - "Unable to find process plug-in for core file '{0}'\n", - core_file.GetPath()); + result.AppendErrorWithFormatv("Unknown core file format '{0}'\n", + core_file.GetPath()); } } else { result.AppendMessageWithFormat( @@ -462,8 +463,6 @@ protected: "argument, or use the --core option.\n", m_cmd_name.c_str()); } - - return result.Succeeded(); } private: @@ -490,7 +489,7 @@ public: ~CommandObjectTargetList() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); bool show_stopped_process_status = false; @@ -499,7 +498,6 @@ protected: strm.PutCString("No targets.\n"); } result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -518,7 +516,7 @@ public: ~CommandObjectTargetSelect() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() == 1) { const char *target_identifier = args.GetArgumentAtIndex(0); uint32_t target_idx = LLDB_INVALID_INDEX32; @@ -568,7 +566,6 @@ protected: result.AppendError( "'target select' takes a single argument: a target index\n"); } - return result.Succeeded(); } }; @@ -604,7 +601,7 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { const size_t argc = args.GetArgumentCount(); std::vector<TargetSP> delete_target_list; TargetList &target_list = GetDebugger().GetTargetList(); @@ -618,7 +615,7 @@ protected: // Bail out if don't have any targets. if (num_targets == 0) { result.AppendError("no targets to delete"); - return false; + return; } for (auto &entry : args.entries()) { @@ -626,7 +623,7 @@ protected: if (entry.ref().getAsInteger(0, target_idx)) { result.AppendErrorWithFormat("invalid target index '%s'\n", entry.c_str()); - return false; + return; } if (target_idx < num_targets) { target_sp = target_list.GetTargetAtIndex(target_idx); @@ -644,13 +641,13 @@ protected: "target index %u is out of range, the only valid index is 0\n", target_idx); - return false; + return; } } else { target_sp = target_list.GetSelectedTarget(); if (!target_sp) { result.AppendErrorWithFormat("no target is currently selected\n"); - return false; + return; } delete_target_list.push_back(target_sp); } @@ -671,7 +668,7 @@ protected: (uint32_t)num_targets_to_delete); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } OptionGroupOptions m_option_group; @@ -692,7 +689,7 @@ public: ~CommandObjectTargetShowLaunchEnvironment() override = default; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); Environment env = target->GetEnvironment(); @@ -710,7 +707,6 @@ protected: strm.Format("{0}={1}\n", KV->first(), KV->second); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -863,7 +859,7 @@ protected: } } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); const size_t argc = args.GetArgumentCount(); Stream &s = result.GetOutputStream(); @@ -880,7 +876,7 @@ protected: if (!regex.IsValid()) { result.GetErrorStream().Printf( "error: invalid regular expression: '%s'\n", arg.c_str()); - return false; + return; } use_var_name = true; target->GetImages().FindGlobalVariables(regex, UINT32_MAX, @@ -896,7 +892,7 @@ protected: if (matches == 0) { result.AppendErrorWithFormat("can't find global variable '%s'", arg.c_str()); - return false; + return; } else { for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) { VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx)); @@ -1014,8 +1010,6 @@ protected: m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(), m_cmd_name); - - return result.Succeeded(); } OptionGroupOptions m_option_group; @@ -1062,7 +1056,7 @@ public: ~CommandObjectTargetModulesSearchPathsAdd() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const size_t argc = command.GetArgumentCount(); if (argc & 1) { @@ -1092,7 +1086,6 @@ protected: } } } - return result.Succeeded(); } }; @@ -1110,12 +1103,11 @@ public: ~CommandObjectTargetModulesSearchPathsClear() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); bool notify = true; target->GetImageSearchPathList().Clear(notify); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } }; @@ -1185,7 +1177,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); size_t argc = command.GetArgumentCount(); // check for at least 3 arguments and an odd number of parameters @@ -1196,7 +1188,7 @@ protected: result.AppendErrorWithFormat( "<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0)); - return result.Succeeded(); + return; } // shift off the index @@ -1217,14 +1209,12 @@ protected: result.AppendError("<path-prefix> can't be empty\n"); else result.AppendError("<new-path-prefix> can't be empty\n"); - return false; + return; } } } else { result.AppendError("insert requires at least three arguments\n"); - return result.Succeeded(); } - return result.Succeeded(); } }; @@ -1242,12 +1232,11 @@ public: ~CommandObjectTargetModulesSearchPathsList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); target->GetImageSearchPathList().Dump(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1278,11 +1267,11 @@ public: ~CommandObjectTargetModulesSearchPathsQuery() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (command.GetArgumentCount() != 1) { result.AppendError("query requires one argument\n"); - return result.Succeeded(); + return; } ConstString orig(command.GetArgumentAtIndex(0)); @@ -1293,7 +1282,6 @@ protected: result.GetOutputStream().Printf("%s\n", orig.GetCString()); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1462,9 +1450,90 @@ static bool DumpModuleSymbolFile(Stream &strm, Module *module) { return false; } +static bool GetSeparateDebugInfoList(StructuredData::Array &list, + Module *module, bool errors_only) { + if (module) { + if (SymbolFile *symbol_file = module->GetSymbolFile(/*can_create=*/true)) { + StructuredData::Dictionary d; + if (symbol_file->GetSeparateDebugInfo(d, errors_only)) { + list.AddItem( + std::make_shared<StructuredData::Dictionary>(std::move(d))); + return true; + } + } + } + return false; +} + +static void DumpDwoFilesTable(Stream &strm, + StructuredData::Array &dwo_listings) { + strm.PutCString("Dwo ID Err Dwo Path"); + strm.EOL(); + strm.PutCString( + "------------------ --- -----------------------------------------"); + strm.EOL(); + dwo_listings.ForEach([&strm](StructuredData::Object *dwo) { + StructuredData::Dictionary *dict = dwo->GetAsDictionary(); + if (!dict) + return false; + + uint64_t dwo_id; + if (dict->GetValueForKeyAsInteger("dwo_id", dwo_id)) + strm.Printf("0x%16.16" PRIx64 " ", dwo_id); + else + strm.Printf("0x???????????????? "); + + llvm::StringRef error; + if (dict->GetValueForKeyAsString("error", error)) + strm << "E " << error; + else { + llvm::StringRef resolved_dwo_path; + if (dict->GetValueForKeyAsString("resolved_dwo_path", + resolved_dwo_path)) { + strm << " " << resolved_dwo_path; + if (resolved_dwo_path.ends_with(".dwp")) { + llvm::StringRef dwo_name; + if (dict->GetValueForKeyAsString("dwo_name", dwo_name)) + strm << "(" << dwo_name << ")"; + } + } + } + strm.EOL(); + return true; + }); +} + +static void DumpOsoFilesTable(Stream &strm, + StructuredData::Array &oso_listings) { + strm.PutCString("Mod Time Err Oso Path"); + strm.EOL(); + strm.PutCString("------------------ --- ---------------------"); + strm.EOL(); + oso_listings.ForEach([&strm](StructuredData::Object *oso) { + StructuredData::Dictionary *dict = oso->GetAsDictionary(); + if (!dict) + return false; + + uint32_t oso_mod_time; + if (dict->GetValueForKeyAsInteger("oso_mod_time", oso_mod_time)) + strm.Printf("0x%16.16" PRIx32 " ", oso_mod_time); + + llvm::StringRef error; + if (dict->GetValueForKeyAsString("error", error)) + strm << "E " << error; + else { + llvm::StringRef oso_path; + if (dict->GetValueForKeyAsString("oso_path", oso_path)) + strm << " " << oso_path; + } + strm.EOL(); + return true; + }); +} + static void DumpAddress(ExecutionContextScope *exe_scope, const Address &so_addr, bool verbose, bool all_ranges, - Stream &strm) { + Stream &strm, llvm::StringRef pattern = "") { strm.IndentMore(); strm.Indent(" Address: "); so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress); @@ -1474,13 +1543,14 @@ static void DumpAddress(ExecutionContextScope *exe_scope, strm.Indent(" Summary: "); const uint32_t save_indent = strm.GetIndentLevel(); strm.SetIndentLevel(save_indent + 13); - so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription); + so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription, + Address::DumpStyleInvalid, UINT32_MAX, false, pattern); strm.SetIndentLevel(save_indent); // Print out detailed address information when verbose is enabled if (verbose) { strm.EOL(); so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext, - Address::DumpStyleInvalid, UINT32_MAX, all_ranges); + Address::DumpStyleInvalid, UINT32_MAX, all_ranges, pattern); } strm.IndentLess(); } @@ -1525,6 +1595,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, return 0; SymbolContext sc; + const bool use_color = interpreter.GetDebugger().GetUseColor(); std::vector<uint32_t> match_indexes; ConstString symbol_name(name); uint32_t num_matches = 0; @@ -1550,12 +1621,19 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, if (symbol->ValueIsAddress()) { DumpAddress( interpreter.GetExecutionContext().GetBestExecutionContextScope(), - symbol->GetAddressRef(), verbose, all_ranges, strm); + symbol->GetAddressRef(), verbose, all_ranges, strm, + use_color && name_is_regex ? name : nullptr); strm.EOL(); } else { strm.IndentMore(); strm.Indent(" Name: "); - strm.PutCString(symbol->GetDisplayName().GetStringRef()); + llvm::StringRef ansi_prefix = + interpreter.GetDebugger().GetRegexMatchAnsiPrefix(); + llvm::StringRef ansi_suffix = + interpreter.GetDebugger().GetRegexMatchAnsiSuffix(); + strm.PutCStringColorHighlighted( + symbol->GetDisplayName().GetStringRef(), + use_color ? name : nullptr, ansi_prefix, ansi_suffix); strm.EOL(); strm.Indent(" Value: "); strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue()); @@ -1628,16 +1706,18 @@ static size_t LookupTypeInModule(Target *target, CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name_cstr, bool name_is_regex) { - TypeList type_list; if (module && name_cstr && name_cstr[0]) { - const uint32_t max_num_matches = UINT32_MAX; - bool name_is_fully_qualified = false; - - ConstString name(name_cstr); - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - module->FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); + TypeQuery query(name_cstr); + TypeResults results; + module->FindTypes(query, results); + TypeList type_list; + SymbolContext sc; + if (module) + sc.module_sp = module->shared_from_this(); + // Sort the type results and put the results that matched in \a module + // first if \a module was specified. + sc.SortTypeList(results.GetTypeMap(), type_list); if (type_list.Empty()) return 0; @@ -1670,22 +1750,21 @@ static size_t LookupTypeInModule(Target *target, } strm.EOL(); } + return type_list.GetSize(); } - return type_list.GetSize(); + return 0; } static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter, Stream &strm, Module &module, const char *name_cstr, bool name_is_regex) { + TypeQuery query(name_cstr); + TypeResults results; + module.FindTypes(query, results); TypeList type_list; - const uint32_t max_num_matches = UINT32_MAX; - bool name_is_fully_qualified = false; - - ConstString name(name_cstr); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module.FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); - + SymbolContext sc; + sc.module_sp = module.shared_from_this(); + sc.SortTypeList(results.GetTypeMap(), type_list); if (type_list.Empty()) return 0; @@ -1879,7 +1958,7 @@ public: ~CommandObjectTargetModulesDumpObjfile() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); @@ -1918,7 +1997,6 @@ protected: } else { result.AppendError("no matching executable images found"); } - return result.Succeeded(); } }; @@ -1981,7 +2059,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); uint32_t num_dumped = 0; Mangled::NamePreference name_preference = @@ -2005,7 +2083,7 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all symtabs with {0} " "of {1} dumped.", num_dumped, num_modules)) break; @@ -2017,7 +2095,7 @@ protected: } } else { result.AppendError("the target has no associated executable images"); - return false; + return; } } else { // Dump specified images (by basename or fullpath) @@ -2035,8 +2113,8 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (INTERRUPT_REQUESTED(GetDebugger(), - "Interrupted in dump symtab list with {0} of {1} dumped.", + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump symtab list with {0} of {1} dumped.", num_dumped, num_matches)) break; @@ -2057,7 +2135,6 @@ protected: else { result.AppendError("no matching executable images found"); } - return result.Succeeded(); } CommandOptions m_options; @@ -2080,7 +2157,7 @@ public: ~CommandObjectTargetModulesDumpSections() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); uint32_t num_dumped = 0; @@ -2093,13 +2170,13 @@ protected: const size_t num_modules = target->GetImages().GetSize(); if (num_modules == 0) { result.AppendError("the target has no associated executable images"); - return false; + return; } result.GetOutputStream().Format("Dumping sections for {0} modules.\n", num_modules); for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all sections with {0} of {1} dumped", image_idx, num_modules)) break; @@ -2120,7 +2197,7 @@ protected: FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump section list with {0} of {1} dumped.", i, num_matches)) break; @@ -2148,7 +2225,6 @@ protected: else { result.AppendError("no matching executable images found"); } - return result.Succeeded(); } }; @@ -2166,11 +2242,11 @@ public: ~CommandObjectTargetModulesDumpClangPCMInfo() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat("'%s' takes exactly one pcm path argument.", m_cmd_name.c_str()); - return false; + return; } const char *pcm_path = command.GetArgumentAtIndex(0); @@ -2178,12 +2254,12 @@ protected: if (pcm_file.GetFileNameExtension() != ".pcm") { result.AppendError("file must have a .pcm extension"); - return false; + return; } if (!FileSystem::Instance().Exists(pcm_file)) { result.AppendError("pcm file does not exist"); - return false; + return; } clang::CompilerInstance compiler; @@ -2203,8 +2279,6 @@ protected: if (compiler.ExecuteAction(dump_module_info)) result.SetStatus(eReturnStatusSuccessFinishResult); - - return result.Succeeded(); } }; @@ -2225,14 +2299,14 @@ public: ~CommandObjectTargetModulesDumpClangAST() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const ModuleList &module_list = target->GetImages(); const size_t num_modules = module_list.GetSize(); if (num_modules == 0) { result.AppendError("the target has no associated executable images"); - return false; + return; } if (command.GetArgumentCount() == 0) { @@ -2246,7 +2320,7 @@ protected: sf->DumpClangAST(result.GetOutputStream()); } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } // Dump specified ASTs (by basename or fullpath) @@ -2265,7 +2339,7 @@ protected: } for (size_t i = 0; i < num_matches; ++i) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump clang ast list with {0} of {1} dumped.", i, num_matches)) break; @@ -2276,7 +2350,6 @@ protected: } } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } }; @@ -2297,7 +2370,7 @@ public: ~CommandObjectTargetModulesDumpSymfile() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); uint32_t num_dumped = 0; @@ -2312,7 +2385,7 @@ protected: const size_t num_modules = target_modules.GetSize(); if (num_modules == 0) { result.AppendError("the target has no associated executable images"); - return false; + return; } result.GetOutputStream().Format( "Dumping debug symbols for {0} modules.\n", num_modules); @@ -2357,7 +2430,6 @@ protected: else { result.AppendError("no matching executable images found"); } - return result.Succeeded(); } }; @@ -2381,7 +2453,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); uint32_t total_num_dumped = 0; @@ -2391,7 +2463,7 @@ protected: if (command.GetArgumentCount() == 0) { result.AppendError("file option must be specified."); - return result.Succeeded(); + return; } else { // Dump specified images (by basename or fullpath) const char *arg_cstr; @@ -2406,9 +2478,9 @@ protected: if (num_modules > 0) { uint32_t num_dumped = 0; for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all line tables with " - "{0} of {1} dumped", num_dumped, + "{0} of {1} dumped", num_dumped, num_modules)) break; @@ -2433,7 +2505,6 @@ protected: else { result.AppendError("no source filenames matched any command arguments"); } - return result.Succeeded(); } class CommandOptions : public Options { @@ -2462,6 +2533,185 @@ protected: CommandOptions m_options; }; +#pragma mark CommandObjectTargetModulesDumpSeparateDebugInfoFiles +#define LLDB_OPTIONS_target_modules_dump_separate_debug_info +#include "CommandOptions.inc" + +// Image debug separate debug info dumping command + +class CommandObjectTargetModulesDumpSeparateDebugInfoFiles + : public CommandObjectTargetModulesModuleAutoComplete { +public: + CommandObjectTargetModulesDumpSeparateDebugInfoFiles( + CommandInterpreter &interpreter) + : CommandObjectTargetModulesModuleAutoComplete( + interpreter, "target modules dump separate-debug-info", + "List the separate debug info symbol files for one or more target " + "modules.", + nullptr, eCommandRequiresTarget) {} + + ~CommandObjectTargetModulesDumpSeparateDebugInfoFiles() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() = default; + + ~CommandOptions() override = default; + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'j': + m_json.SetCurrentValue(true); + m_json.SetOptionWasSet(); + break; + case 'e': + m_errors_only.SetCurrentValue(true); + m_errors_only.SetOptionWasSet(); + break; + default: + llvm_unreachable("Unimplemented option"); + } + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_json.Clear(); + m_errors_only.Clear(); + } + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::ArrayRef(g_target_modules_dump_separate_debug_info_options); + } + + OptionValueBoolean m_json = false; + OptionValueBoolean m_errors_only = false; + }; + +protected: + void DoExecute(Args &command, CommandReturnObject &result) override { + Target &target = GetSelectedTarget(); + uint32_t num_dumped = 0; + + uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + + StructuredData::Array separate_debug_info_lists_by_module; + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const ModuleList &target_modules = target.GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules == 0) { + result.AppendError("the target has no associated executable images"); + return; + } + for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { + if (INTERRUPT_REQUESTED( + GetDebugger(), + "Interrupted in dumping all " + "separate debug info with {0} of {1} modules dumped", + num_dumped, num_modules)) + break; + + if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module, + module_sp.get(), + bool(m_options.m_errors_only))) + num_dumped++; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(&target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted dumping {0} " + "of {1} requested modules", + i, num_matches)) + break; + Module *module = module_list.GetModulePointerAtIndex(i); + if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module, + module, bool(m_options.m_errors_only))) + num_dumped++; + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); + } + } + + if (num_dumped > 0) { + Stream &strm = result.GetOutputStream(); + // Display the debug info files in some format. + if (m_options.m_json) { + // JSON format + separate_debug_info_lists_by_module.Dump(strm, + /*pretty_print=*/true); + } else { + // Human-readable table format + separate_debug_info_lists_by_module.ForEach( + [&result, &strm](StructuredData::Object *obj) { + if (!obj) { + return false; + } + + // Each item in `separate_debug_info_lists_by_module` should be a + // valid structured data dictionary. + StructuredData::Dictionary *separate_debug_info_list = + obj->GetAsDictionary(); + if (!separate_debug_info_list) { + return false; + } + + llvm::StringRef type; + llvm::StringRef symfile; + StructuredData::Array *files; + if (!(separate_debug_info_list->GetValueForKeyAsString("type", + type) && + separate_debug_info_list->GetValueForKeyAsString("symfile", + symfile) && + separate_debug_info_list->GetValueForKeyAsArray( + "separate-debug-info-files", files))) { + assert(false); + } + + strm << "Symbol file: " << symfile; + strm.EOL(); + strm << "Type: \"" << type << "\""; + strm.EOL(); + if (type == "dwo") { + DumpDwoFilesTable(strm, *files); + } else if (type == "oso") { + DumpOsoFilesTable(strm, *files); + } else { + result.AppendWarningWithFormat( + "Found unsupported debug info type '%s'.\n", + type.str().c_str()); + } + return true; + }); + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendError("no matching executable images found"); + } + } + + CommandOptions m_options; +}; + #pragma mark CommandObjectTargetModulesDump // Dump multi-word command for target modules @@ -2475,7 +2725,8 @@ public: "Commands for dumping information about one or more target " "modules.", "target modules dump " - "[objfile|symtab|sections|ast|symfile|line-table|pcm-info] " + "[objfile|symtab|sections|ast|symfile|line-table|pcm-info|separate-" + "debug-info] " "[<file1> <file2> ...]") { LoadSubCommand("objfile", CommandObjectSP( @@ -2499,6 +2750,10 @@ public: "pcm-info", CommandObjectSP( new CommandObjectTargetModulesDumpClangPCMInfo(interpreter))); + LoadSubCommand("separate-debug-info", + CommandObjectSP( + new CommandObjectTargetModulesDumpSeparateDebugInfoFiles( + interpreter))); } ~CommandObjectTargetModulesDump() override = default; @@ -2540,7 +2795,7 @@ protected: OptionGroupUUID m_uuid_option_group; OptionGroupFile m_symbol_file; - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); bool flush = false; @@ -2555,12 +2810,12 @@ protected: module_spec.GetSymbolFileSpec() = m_symbol_file.GetOptionValue().GetCurrentValue(); Status error; - if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) { + if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) { ModuleSP module_sp( target->GetOrCreateModule(module_spec, true /* notify */)); if (module_sp) { result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } else { StreamString strm; module_spec.GetUUID().Dump(strm); @@ -2583,7 +2838,7 @@ protected: "or symbol file with UUID %s", strm.GetData()); } - return false; + return; } } else { StreamString strm; @@ -2592,12 +2847,12 @@ protected: "Unable to locate the executable or symbol file with UUID %s", strm.GetData()); result.SetError(error); - return false; + return; } } else { result.AppendError( "one or more executable image paths must be specified"); - return false; + return; } } else { for (auto &entry : args.entries()) { @@ -2625,7 +2880,7 @@ protected: else result.AppendErrorWithFormat("unsupported module: %s", entry.c_str()); - return false; + return; } else { flush = true; } @@ -2650,8 +2905,6 @@ protected: if (process) process->Flush(); } - - return result.Succeeded(); } }; @@ -2692,7 +2945,7 @@ public: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const bool load = m_load_option.GetOptionValue().GetCurrentValue(); const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue(); @@ -2765,14 +3018,14 @@ protected: } else { result.AppendError("one or more section name + load " "address pair must be specified"); - return false; + return; } } else { if (m_slide_option.GetOptionValue().OptionWasSet()) { result.AppendError("The \"--slide <offset>\" option can't " "be used in conjunction with setting " "section load addresses.\n"); - return false; + return; } for (size_t i = 0; i < argc; i += 2) { @@ -2834,22 +3087,22 @@ protected: Address file_entry = objfile->GetEntryPointAddress(); if (!process) { result.AppendError("No process"); - return false; + return; } if (set_pc && !file_entry.IsValid()) { result.AppendError("No entry address in object file"); - return false; + return; } std::vector<ObjectFile::LoadableData> loadables( objfile->GetLoadableData(*target)); if (loadables.size() == 0) { result.AppendError("No loadable sections"); - return false; + return; } Status error = process->WriteObjectFile(std::move(loadables)); if (error.Fail()) { result.AppendError(error.AsCString()); - return false; + return; } if (set_pc) { ThreadList &thread_list = process->GetThreadList(); @@ -2911,9 +3164,7 @@ protected: } else { result.AppendError("either the \"--file <module>\" or the \"--uuid " "<uuid>\" option must be specified.\n"); - return false; } - return result.Succeeded(); } OptionGroupOptions m_option_group; @@ -2985,7 +3236,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = GetDebugger().GetSelectedTarget().get(); const bool use_global_module_list = m_options.m_use_global_module_list; // Define a local module list here to ensure it lives longer than any @@ -2995,7 +3246,7 @@ protected: if (target == nullptr && !use_global_module_list) { result.AppendError("invalid target, create a debug target using the " "'target create' command"); - return false; + return; } else { if (target) { uint32_t addr_byte_size = @@ -3028,7 +3279,7 @@ protected: result.AppendError( "Can only look up modules by address with a valid target."); } - return result.Succeeded(); + return; } size_t num_modules = 0; @@ -3058,7 +3309,7 @@ protected: if (argc == 1) { result.AppendErrorWithFormat("no modules found that match '%s'", arg.c_str()); - return false; + return; } } } @@ -3104,10 +3355,9 @@ protected: result.AppendError( "the target has no associated executable images"); } - return false; + return; } } - return result.Succeeded(); } void PrintModule(Target *target, Module *module, int indent, Stream &strm) { @@ -3341,7 +3591,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); Process *process = m_exe_ctx.GetProcessPtr(); ABI *abi = nullptr; @@ -3351,19 +3601,19 @@ protected: if (process == nullptr) { result.AppendError( "You must have a process running to use this command."); - return false; + return; } ThreadList threads(process->GetThreadList()); if (threads.GetSize() == 0) { result.AppendError("The process must be paused to use this command."); - return false; + return; } ThreadSP thread(threads.GetThreadAtIndex(0)); if (!thread) { result.AppendError("The process must be paused to use this command."); - return false; + return; } SymbolContextList sc_list; @@ -3390,13 +3640,13 @@ protected: } else { result.AppendError( "address-expression or function name option must be specified."); - return false; + return; } if (sc_list.GetSize() == 0) { result.AppendErrorWithFormat("no unwind data found that matches '%s'.", m_options.m_str.c_str()); - return false; + return; } for (const SymbolContext &sc : sc_list) { @@ -3595,7 +3845,6 @@ protected: result.GetOutputStream().Printf("\n"); } - return result.Succeeded(); } CommandOptions m_options; @@ -3899,7 +4148,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); bool syntax_error = false; uint32_t i; @@ -3920,7 +4169,7 @@ protected: num_successful_lookups++; if (!m_options.m_print_all) { result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + return; } } @@ -3930,7 +4179,7 @@ protected: std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); if (target_modules.GetSize() == 0) { result.AppendError("the target has no associated executable images"); - return false; + return; } for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { @@ -3970,7 +4219,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); else result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); } CommandOptions m_options; @@ -4258,7 +4506,7 @@ protected: bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, CommandReturnObject &result, bool &flush) { Status error; - if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) { + if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error)) { if (module_spec.GetSymbolFileSpec()) return AddModuleSymbols(m_exe_ctx.GetTargetPtr(), module_spec, flush, result); @@ -4419,7 +4667,7 @@ protected: return true; } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); result.SetStatus(eReturnStatusFailed); bool flush = false; @@ -4504,7 +4752,6 @@ protected: if (process) process->Flush(); } - return result.Succeeded(); } OptionGroupOptions m_option_group; @@ -4806,7 +5053,7 @@ protected: io_handler.SetIsDone(true); } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { m_stop_hook_sp.reset(); Target &target = GetSelectedOrDummyTarget(); @@ -4903,7 +5150,7 @@ protected: result.AppendErrorWithFormat("Couldn't add stop hook: %s", error.AsCString()); target.UndoCreateStopHook(new_hook_sp->GetID()); - return false; + return; } } else { m_stop_hook_sp = new_hook_sp; @@ -4911,8 +5158,6 @@ protected: *this); // IOHandlerDelegate } result.SetStatus(eReturnStatusSuccessFinishNoResult); - - return result.Succeeded(); } private: @@ -4942,19 +5187,21 @@ public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { + if (request.GetCursorIndex()) + return; lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), lldb::eStopHookIDCompletion, request, nullptr); } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); // FIXME: see if we can use the breakpoint id style parser? size_t num_args = command.GetArgumentCount(); if (num_args == 0) { if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { result.SetStatus(eReturnStatusFailed); - return false; + return; } else { target.RemoveAllStopHooks(); } @@ -4964,17 +5211,16 @@ protected: if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) { result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - return false; + return; } if (!target.RemoveStopHookByID(user_id)) { result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - return false; + return; } } } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } }; @@ -5004,7 +5250,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); // FIXME: see if we can use the breakpoint id style parser? size_t num_args = command.GetArgumentCount(); @@ -5018,18 +5264,17 @@ protected: if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) { result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - return false; + return; } success = target.SetStopHookActiveStateByID(user_id, m_enable); if (!success) { result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); - return false; + return; } } } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } private: @@ -5049,7 +5294,7 @@ public: ~CommandObjectTargetStopHookList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedOrDummyTarget(); size_t num_hooks = target.GetNumStopHooks(); @@ -5065,7 +5310,6 @@ protected: } } result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -5115,14 +5359,13 @@ public: ~CommandObjectTargetDumpTypesystem() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // Go over every scratch TypeSystem and dump to the command output. for (lldb::TypeSystemSP ts : GetSelectedTarget().GetScratchTypeSystems()) if (ts) ts->Dump(result.GetOutputStream().AsRawOstream()); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -5141,11 +5384,10 @@ public: ~CommandObjectTargetDumpSectionLoadList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target &target = GetSelectedTarget(); target.GetSectionLoadList().Dump(result.GetOutputStream(), &target); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp index 64f3edcad563..a1e7e3f11361 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp @@ -145,14 +145,14 @@ public: for (size_t idx = 0; idx < num_entries; idx++) { llvm::StringRef arg_string = copy_args[idx].ref(); - if (arg_string.equals("-c") || count_opt.startswith(arg_string)) { + if (arg_string.equals("-c") || count_opt.starts_with(arg_string)) { idx++; if (idx == num_entries) return std::nullopt; count_idx = idx; if (copy_args[idx].ref().getAsInteger(0, count_val)) return std::nullopt; - } else if (arg_string.equals("-s") || start_opt.startswith(arg_string)) { + } else if (arg_string.equals("-s") || start_opt.starts_with(arg_string)) { idx++; if (idx == num_entries) return std::nullopt; @@ -412,7 +412,7 @@ public: Options *GetOptions() override { return &m_all_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); bool synchronous_execution = m_interpreter.GetSynchronous(); @@ -424,7 +424,7 @@ protected: if (thread == nullptr) { result.AppendError("no selected thread in process"); - return false; + return; } } else { const char *thread_idx_cstr = command.GetArgumentAtIndex(0); @@ -433,7 +433,7 @@ protected: if (!llvm::to_integer(thread_idx_cstr, step_thread_idx)) { result.AppendErrorWithFormat("invalid thread index '%s'.\n", thread_idx_cstr); - return false; + return; } thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); @@ -441,20 +441,20 @@ protected: result.AppendErrorWithFormat( "Thread index %u is out of range (valid values are 0 - %u).\n", step_thread_idx, num_threads); - return false; + return; } } if (m_step_type == eStepTypeScripted) { if (m_class_options.GetName().empty()) { result.AppendErrorWithFormat("empty class name for scripted step."); - return false; + return; } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists( m_class_options.GetName().c_str())) { result.AppendErrorWithFormat( "class for scripted step: \"%s\" does not exist.", m_class_options.GetName().c_str()); - return false; + return; } } @@ -462,7 +462,7 @@ protected: m_step_type != eStepTypeInto) { result.AppendErrorWithFormat( "end line option is only valid for step into"); - return false; + return; } const bool abort_other_plans = false; @@ -494,14 +494,14 @@ protected: error)) { result.AppendErrorWithFormat("invalid end-line option: %s.", error.AsCString()); - return false; + return; } } else if (m_options.m_end_line_is_block_end) { Status error; Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; if (!block) { result.AppendErrorWithFormat("Could not find the current block."); - return false; + return; } AddressRange block_range; @@ -510,7 +510,7 @@ protected: if (!block_range.GetBaseAddress().IsValid()) { result.AppendErrorWithFormat( "Could not find the current block address."); - return false; + return; } lldb::addr_t pc_offset_in_block = pc_address.GetFileAddress() - @@ -569,7 +569,7 @@ protected: new_plan_status); } else { result.AppendError("step type is not supported"); - return false; + return; } // If we got a new plan, then set it to be a controlling plan (User level @@ -600,7 +600,7 @@ protected: if (!error.Success()) { result.AppendMessage(error.AsCString()); - return false; + return; } // There is a race condition where this thread will return up the call @@ -624,7 +624,6 @@ protected: } else { result.SetError(new_plan_status); } - return result.Succeeded(); } StepType m_step_type; @@ -672,13 +671,13 @@ public: nullptr); } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process exists. Cannot continue"); - return false; + return; } StateType state = process->GetState(); @@ -698,7 +697,7 @@ public: if (entry.ref().getAsInteger(0, thread_idx)) { result.AppendErrorWithFormat( "invalid thread index argument: \"%s\".\n", entry.c_str()); - return false; + return; } Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); @@ -708,13 +707,13 @@ public: } else { result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); - return false; + return; } } if (resume_threads.empty()) { result.AppendError("no valid thread indexes were specified"); - return false; + return; } else { if (resume_threads.size() == 1) result.AppendMessageWithFormat("Resuming thread: "); @@ -753,7 +752,7 @@ public: Thread *current_thread = GetDefaultThread(); if (current_thread == nullptr) { result.AppendError("the process doesn't have a current thread"); - return false; + return; } // Set the actions that the threads should each take when resuming for (uint32_t idx = 0; idx < num_threads; ++idx) { @@ -801,8 +800,6 @@ public: "Process cannot be continued from its current state (%s).\n", StateAsCString(state)); } - - return result.Succeeded(); } }; @@ -920,7 +917,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); Target *target = &GetSelectedTarget(); @@ -939,14 +936,14 @@ protected: if (!llvm::to_integer(command.GetArgumentAtIndex(i), line_number)) { result.AppendErrorWithFormat("invalid line number: '%s'.\n", command.GetArgumentAtIndex(i)); - return false; + return; } else line_numbers.push_back(line_number); } } else if (m_options.m_until_addrs.empty()) { result.AppendErrorWithFormat("No line number or address provided:\n%s", GetSyntax().str().c_str()); - return false; + return; } if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { @@ -962,7 +959,7 @@ protected: result.AppendErrorWithFormat( "Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, num_threads); - return false; + return; } const bool abort_other_plans = false; @@ -973,7 +970,7 @@ protected: result.AppendErrorWithFormat( "Frame index %u is out of range for thread id %" PRIu64 ".\n", m_options.m_frame_idx, thread->GetID()); - return false; + return; } ThreadPlanSP new_plan_sp; @@ -991,7 +988,7 @@ protected: result.AppendErrorWithFormat("Failed to resolve the line table for " "frame %u of thread id %" PRIu64 ".\n", m_options.m_frame_idx, thread->GetID()); - return false; + return; } LineEntry function_start; @@ -1003,7 +1000,7 @@ protected: if (!sc.function) { result.AppendErrorWithFormat("Have debug information but no " "function info - can't get until range."); - return false; + return; } AddressRange fun_addr_range = sc.function->GetAddressRange(); @@ -1067,7 +1064,7 @@ protected: result.AppendErrorWithFormat( "Until target outside of the current function.\n"); - return false; + return; } new_plan_sp = thread->QueueThreadPlanForStepUntil( @@ -1083,20 +1080,20 @@ protected: new_plan_sp->SetOkayToDiscard(false); } else { result.SetError(new_plan_status); - return false; + return; } } else { result.AppendErrorWithFormat("Frame index %u of thread id %" PRIu64 " has no debug information.\n", m_options.m_frame_idx, thread->GetID()); - return false; + return; } if (!process->GetThreadList().SetSelectedThreadByID(thread->GetID())) { result.AppendErrorWithFormat( "Failed to set the selected thread to thread id %" PRIu64 ".\n", thread->GetID()); - return false; + return; } StreamString stream; @@ -1125,7 +1122,6 @@ protected: error.AsCString()); } } - return result.Succeeded(); } CommandOptions m_options; @@ -1133,11 +1129,51 @@ protected: // CommandObjectThreadSelect +#define LLDB_OPTIONS_thread_select +#include "CommandOptions.inc" + class CommandObjectThreadSelect : public CommandObjectParsed { public: + class OptionGroupThreadSelect : public OptionGroup { + public: + OptionGroupThreadSelect() { OptionParsingStarting(nullptr); } + + ~OptionGroupThreadSelect() override = default; + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_thread_id = LLDB_INVALID_THREAD_ID; + } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + const int short_option = g_thread_select_options[option_idx].short_option; + switch (short_option) { + case 't': { + if (option_arg.getAsInteger(0, m_thread_id)) { + m_thread_id = LLDB_INVALID_THREAD_ID; + return Status("Invalid thread ID: '%s'.", option_arg.str().c_str()); + } + break; + } + + default: + llvm_unreachable("Unimplemented option"); + } + + return {}; + } + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::ArrayRef(g_thread_select_options); + } + + lldb::tid_t m_thread_id; + }; + CommandObjectThreadSelect(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "thread select", - "Change the currently selected thread.", nullptr, + "Change the currently selected thread.", + "thread select <thread-index> (or -t <thread-id>)", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { @@ -1147,6 +1183,7 @@ public: // Define the first (and only) variant of this arg. thread_idx_arg.arg_type = eArgTypeThreadIndex; thread_idx_arg.arg_repetition = eArgRepeatPlain; + thread_idx_arg.arg_opt_set_association = LLDB_OPT_SET_1; // There is only one variant this argument could be; put it into the // argument entry. @@ -1154,6 +1191,9 @@ public: // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); + + m_option_group.Append(&m_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); + m_option_group.Finalize(); } ~CommandObjectThreadSelect() override = default; @@ -1169,39 +1209,59 @@ public: nullptr); } + Options *GetOptions() override { return &m_option_group; } + protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process"); - return false; - } else if (command.GetArgumentCount() != 1) { + return; + } else if (m_options.m_thread_id == LLDB_INVALID_THREAD_ID && + command.GetArgumentCount() != 1) { result.AppendErrorWithFormat( - "'%s' takes exactly one thread index argument:\nUsage: %s\n", + "'%s' takes exactly one thread index argument, or a thread ID " + "option:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); - return false; - } - - uint32_t index_id; - if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) { - result.AppendErrorWithFormat("Invalid thread index '%s'", - command.GetArgumentAtIndex(0)); - return false; + return; + } else if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID && + command.GetArgumentCount() != 0) { + result.AppendErrorWithFormat("'%s' cannot take both a thread ID option " + "and a thread index argument:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); + return; } - Thread *new_thread = - process->GetThreadList().FindThreadByIndexID(index_id).get(); - if (new_thread == nullptr) { - result.AppendErrorWithFormat("invalid thread #%s.\n", - command.GetArgumentAtIndex(0)); - return false; + Thread *new_thread = nullptr; + if (command.GetArgumentCount() == 1) { + uint32_t index_id; + if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) { + result.AppendErrorWithFormat("Invalid thread index '%s'", + command.GetArgumentAtIndex(0)); + return; + } + new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); + if (new_thread == nullptr) { + result.AppendErrorWithFormat("Invalid thread index #%s.\n", + command.GetArgumentAtIndex(0)); + return; + } + } else { + new_thread = + process->GetThreadList().FindThreadByID(m_options.m_thread_id).get(); + if (new_thread == nullptr) { + result.AppendErrorWithFormat("Invalid thread ID %" PRIu64 ".\n", + m_options.m_thread_id); + return; + } } process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); result.SetStatus(eReturnStatusSuccessFinishNoResult); - - return result.Succeeded(); } + + OptionGroupThreadSelect m_options; + OptionGroupOptions m_option_group; }; // CommandObjectThreadList @@ -1221,7 +1281,7 @@ public: ~CommandObjectThreadList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); result.SetStatus(eReturnStatusSuccessFinishNoResult); Process *process = m_exe_ctx.GetProcessPtr(); @@ -1232,7 +1292,6 @@ protected: process->GetStatus(strm); process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, num_frames, num_frames_with_source, false); - return result.Succeeded(); } }; @@ -1511,12 +1570,12 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { // I am going to handle this by hand, because I don't want you to have to // say: // "thread return -- -5". - if (command.startswith("-x")) { + if (command.starts_with("-x")) { if (command.size() != 2U) result.AppendWarning("Return values ignored when returning from user " "called expressions"); @@ -1539,7 +1598,7 @@ protected: "Could not select 0th frame after unwinding expression."); } } - return result.Succeeded(); + return; } ValueObjectSP return_valobj_sp; @@ -1549,7 +1608,7 @@ protected: if (frame_sp->IsInlined()) { result.AppendError("Don't know how to return from inlined frames."); - return false; + return; } if (!command.empty()) { @@ -1570,7 +1629,7 @@ protected: else result.AppendErrorWithFormat( "Unknown error evaluating result expression."); - return false; + return; } } @@ -1582,11 +1641,10 @@ protected: result.AppendErrorWithFormat( "Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } CommandOptions m_options; @@ -1667,7 +1725,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); StackFrame *frame = m_exe_ctx.GetFramePtr(); Thread *thread = m_exe_ctx.GetThreadPtr(); @@ -1682,13 +1740,13 @@ protected: lldb::addr_t callAddr = dest.GetCallableLoadAddress(target); if (callAddr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("Invalid destination address."); - return false; + return; } if (!reg_ctx->SetPC(callAddr)) { result.AppendErrorWithFormat("Error changing PC value for thread %d.", thread->GetIndexID()); - return false; + return; } } else { // Pick either the absolute line, or work out a relative one. @@ -1704,7 +1762,7 @@ protected: if (!file) { result.AppendErrorWithFormat( "No source file available for the current location."); - return false; + return; } std::string warnings; @@ -1712,7 +1770,7 @@ protected: if (err.Fail()) { result.SetError(err); - return false; + return; } if (!warnings.empty()) @@ -1720,7 +1778,6 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } CommandOptions m_options; @@ -1804,7 +1861,7 @@ public: Options *GetOptions() override { return &m_options; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // If we are reporting all threads, dispatch to the Process to do that: if (command.GetArgumentCount() == 0 && m_options.m_tids.empty()) { Stream &strm = result.GetOutputStream(); @@ -1814,7 +1871,7 @@ public: m_exe_ctx.GetProcessPtr()->DumpThreadPlans( strm, desc_level, m_options.m_internal, true, m_options.m_unreported); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } else { // Do any TID's that the user may have specified as TID, then do any // Thread Indexes... @@ -1829,7 +1886,7 @@ public: if (!success) { result.AppendError("Error dumping plans:"); result.AppendError(tmp_strm.GetString()); - return false; + return; } // Otherwise, add our data to the output: result.GetOutputStream() << tmp_strm.GetString(); @@ -1899,13 +1956,13 @@ public: m_exe_ctx.GetThreadPtr()->AutoCompleteThreadPlans(request); } - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Thread *thread = m_exe_ctx.GetThreadPtr(); if (args.GetArgumentCount() != 1) { result.AppendErrorWithFormat("Too many arguments, expected one - the " "thread plan index - but got %zu.", args.GetArgumentCount()); - return false; + return; } uint32_t thread_plan_idx; @@ -1913,23 +1970,21 @@ public: result.AppendErrorWithFormat( "Invalid thread index: \"%s\" - should be unsigned int.", args.GetArgumentAtIndex(0)); - return false; + return; } if (thread_plan_idx == 0) { result.AppendErrorWithFormat( "You wouldn't really want me to discard the base thread plan."); - return false; + return; } if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) { result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; } else { result.AppendErrorWithFormat( "Could not find User thread plan with index %s.", args.GetArgumentAtIndex(0)); - return false; } } }; @@ -1965,13 +2020,13 @@ public: ~CommandObjectThreadPlanPrune() override = default; - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (args.GetArgumentCount() == 0) { process->PruneThreadPlans(); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } const size_t num_args = args.GetArgumentCount(); @@ -1984,16 +2039,15 @@ public: if (!llvm::to_integer(args.GetArgumentAtIndex(i), tid)) { result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", args.GetArgumentAtIndex(i)); - return false; + return; } if (!process->PruneThreadPlansForTID(tid)) { result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n", args.GetArgumentAtIndex(i)); - return false; + return; } } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; } }; @@ -2187,11 +2241,11 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result); if (!thread_sp) { result.AppendError("invalid thread\n"); - return false; + return; } llvm::Expected<TraceCursorSP> cursor_or_error = @@ -2199,7 +2253,7 @@ protected: if (!cursor_or_error) { result.AppendError(llvm::toString(cursor_or_error.takeError())); - return false; + return; } TraceCursorSP &cursor_sp = *cursor_or_error; @@ -2217,7 +2271,6 @@ protected: m_options.m_dumper_options); dumper.DumpFunctionCalls(); - return true; } CommandOptions m_options; @@ -2371,11 +2424,11 @@ public: } protected: - bool DoExecute(Args &args, CommandReturnObject &result) override { + void DoExecute(Args &args, CommandReturnObject &result) override { ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result); if (!thread_sp) { result.AppendError("invalid thread\n"); - return false; + return; } if (m_options.m_continue && m_last_id) { @@ -2390,14 +2443,14 @@ protected: if (!cursor_or_error) { result.AppendError(llvm::toString(cursor_or_error.takeError())); - return false; + return; } TraceCursorSP &cursor_sp = *cursor_or_error; if (m_options.m_dumper_options.id && !cursor_sp->HasId(*m_options.m_dumper_options.id)) { result.AppendError("invalid instruction id\n"); - return false; + return; } std::optional<StreamFile> out_file; @@ -2419,7 +2472,6 @@ protected: m_options.m_dumper_options); m_last_id = dumper.DumpInstructions(m_options.m_count); - return true; } CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.cpp index 504d5fa0118d..d7fa4190a245 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.cpp @@ -34,16 +34,16 @@ CommandObjectMultipleThreads::CommandObjectMultipleThreads( m_arguments.push_back({thread_arg}); } -bool CommandObjectIterateOverThreads::DoExecute(Args &command, +void CommandObjectIterateOverThreads::DoExecute(Args &command, CommandReturnObject &result) { result.SetStatus(m_success_return); bool all_threads = false; if (command.GetArgumentCount() == 0) { Thread *thread = m_exe_ctx.GetThreadPtr(); - if (!thread || !HandleOneThread(thread->GetID(), result)) - return false; - return result.Succeeded(); + if (thread) + HandleOneThread(thread->GetID(), result); + return; } else if (command.GetArgumentCount() == 1) { all_threads = ::strcmp(command.GetArgumentAtIndex(0), "all") == 0; m_unique_stacks = ::strcmp(command.GetArgumentAtIndex(0), "unique") == 0; @@ -71,7 +71,7 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command, if (!llvm::to_integer(command.GetArgumentAtIndex(i), thread_idx)) { result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); - return false; + return; } ThreadSP thread = @@ -80,7 +80,7 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command, if (!thread) { result.AppendErrorWithFormat("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); - return false; + return; } tids.push_back(thread->GetID()); @@ -92,7 +92,7 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command, std::set<UniqueStack> unique_stacks; for (const lldb::tid_t &tid : tids) { if (!BucketThread(tid, unique_stacks, result)) { - return false; + return; } } @@ -114,7 +114,7 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command, ThreadSP thread = process->GetThreadList().FindThreadByIndexID( representative_thread_id); if (!HandleOneThread(thread->GetID(), result)) { - return false; + return; } } } else { @@ -124,12 +124,11 @@ bool CommandObjectIterateOverThreads::DoExecute(Args &command, result.AppendMessage(""); if (!HandleOneThread(tid, result)) - return false; + return; ++idx; } } - return result.Succeeded(); } bool CommandObjectIterateOverThreads::BucketThread( @@ -167,7 +166,7 @@ bool CommandObjectIterateOverThreads::BucketThread( return true; } -bool CommandObjectMultipleThreads::DoExecute(Args &command, +void CommandObjectMultipleThreads::DoExecute(Args &command, CommandReturnObject &result) { Process &process = m_exe_ctx.GetProcessRef(); @@ -191,7 +190,7 @@ bool CommandObjectMultipleThreads::DoExecute(Args &command, if (!llvm::to_integer(command.GetArgumentAtIndex(i), thread_idx)) { result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); - return false; + return; } ThreadSP thread = process.GetThreadList().FindThreadByIndexID(thread_idx); @@ -199,12 +198,12 @@ bool CommandObjectMultipleThreads::DoExecute(Args &command, if (!thread) { result.AppendErrorWithFormat("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); - return false; + return; } tids.push_back(thread->GetID()); } } - return DoExecuteOnThreads(command, result, tids); + DoExecuteOnThreads(command, result, tids); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.h index c8f51eabc043..74d1136bab7f 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectThreadUtil.h @@ -54,7 +54,7 @@ public: ~CommandObjectIterateOverThreads() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; protected: // Override this to do whatever you need to do for one thread. @@ -84,7 +84,7 @@ public: const char *name, const char *help, const char *syntax, uint32_t flags); - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; protected: /// Method that handles the command after the main arguments have been parsed. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp index 52fb56ffc1fb..e0c74e29aaa6 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp @@ -103,11 +103,11 @@ public: ~CommandObjectTraceSave() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.size() != 1) { result.AppendError("a single path to a directory where the trace bundle " "will be created is required"); - return false; + return; } FileSpec bundle_dir(command[0].ref()); @@ -125,8 +125,6 @@ protected: } else { result.AppendError(toString(desc_file.takeError())); } - - return result.Succeeded(); } CommandOptions m_options; @@ -194,11 +192,11 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.size() != 1) { result.AppendError("a single path to a JSON file containing a the " "description of the trace bundle is required"); - return false; + return; } const FileSpec trace_description_file(command[0].ref()); @@ -210,7 +208,7 @@ protected: if (!trace_or_err) { result.AppendErrorWithFormat( "%s\n", llvm::toString(trace_or_err.takeError()).c_str()); - return false; + return; } if (m_options.m_verbose) { @@ -219,7 +217,6 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } CommandOptions m_options; @@ -276,7 +273,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Status error; // TODO: fill in the dumping code here! if (error.Success()) { @@ -284,7 +281,6 @@ protected: } else { result.AppendErrorWithFormat("%s\n", error.AsCString()); } - return result.Succeeded(); } CommandOptions m_options; @@ -345,12 +341,12 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Status error; if (command.empty()) { result.AppendError( "trace schema cannot be invoked without a plug-in as argument"); - return false; + return; } StringRef plugin_name(command[0].c_str()); @@ -376,7 +372,6 @@ protected: } else { result.AppendErrorWithFormat("%s\n", error.AsCString()); } - return result.Succeeded(); } CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp index e6dd63a6cb21..f76420f3cc68 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp @@ -276,7 +276,7 @@ public: Status *error = nullptr); protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; }; static const char *g_synth_addreader_instructions = @@ -389,18 +389,17 @@ private: bool Execute_PythonClass(Args &command, CommandReturnObject &result); protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { WarnOnPotentialUnquotedUnsignedType(command, result); if (m_options.handwrite_python) - return Execute_HandwritePython(command, result); + Execute_HandwritePython(command, result); else if (m_options.is_class_based) - return Execute_PythonClass(command, result); + Execute_PythonClass(command, result); else { result.AppendError("must either provide a children list, a Python class " "name, or use -P and type a Python class " "line-by-line"); - return false; } } @@ -649,13 +648,13 @@ pointers to floats. Nor will it change the default display for Afloat and Bfloa ~CommandObjectTypeFormatAdd() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc < 1) { result.AppendErrorWithFormat("%s takes one or more args.\n", m_cmd_name.c_str()); - return false; + return; } const Format format = m_format_options.GetFormat(); @@ -663,7 +662,7 @@ protected: m_command_options.m_custom_type_name.empty()) { result.AppendErrorWithFormat("%s needs a valid format.\n", m_cmd_name.c_str()); - return false; + return; } TypeFormatImplSP entry; @@ -688,14 +687,14 @@ protected: DataVisualization::Categories::GetCategory( ConstString(m_command_options.m_category), category_sp); if (!category_sp) - return false; + return; WarnOnPotentialUnquotedUnsignedType(command, result); for (auto &arg_entry : command.entries()) { if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); - return false; + return; } FormatterMatchType match_type = eFormatterMatchExact; @@ -705,14 +704,13 @@ protected: if (!typeRX.IsValid()) { result.AppendError( "regex format error (maybe this is not really a regex?)"); - return false; + return; } } category_sp->AddTypeFormat(arg_entry.ref(), match_type, entry); } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } }; @@ -828,12 +826,12 @@ public: protected: virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc != 1) { result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str()); - return false; + return; } const char *typeA = command.GetArgumentAtIndex(0); @@ -841,7 +839,7 @@ protected: if (!typeCS) { result.AppendError("empty typenames not allowed"); - return false; + return; } if (m_options.m_delete_all) { @@ -851,7 +849,7 @@ protected: return true; }); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + return; } bool delete_category = false; @@ -875,10 +873,8 @@ protected: if (delete_category || extra_deletion) { result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } else { result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA); - return false; } } }; @@ -942,7 +938,7 @@ public: protected: virtual void FormatterSpecificDeletion() {} - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (m_options.m_delete_all) { DataVisualization::Categories::ForEach( [this](const TypeCategoryImplSP &category_sp) -> bool { @@ -965,7 +961,6 @@ protected: FormatterSpecificDeletion(); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1077,7 +1072,7 @@ protected: return regex == nullptr || s == regex->GetText() || regex->Execute(s); } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); std::unique_ptr<RegularExpression> category_regex; @@ -1090,7 +1085,7 @@ protected: result.AppendErrorWithFormat( "syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); - return false; + return; } } @@ -1100,7 +1095,7 @@ protected: if (!formatter_regex->IsValid()) { result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); - return false; + return; } } @@ -1154,7 +1149,6 @@ protected: result.GetOutputStream().PutCString("no matching results found.\n"); result.SetStatus(eReturnStatusSuccessFinishNoResult); } - return result.Succeeded(); } }; @@ -1557,26 +1551,26 @@ Alternatively, the -o option can be used when providing a simple one-line Python (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"); } -bool CommandObjectTypeSummaryAdd::DoExecute(Args &command, +void CommandObjectTypeSummaryAdd::DoExecute(Args &command, CommandReturnObject &result) { WarnOnPotentialUnquotedUnsignedType(command, result); if (m_options.m_is_add_script) { #if LLDB_ENABLE_PYTHON - return Execute_ScriptSummary(command, result); + Execute_ScriptSummary(command, result); #else result.AppendError("python is disabled"); - return false; #endif + return; } - return Execute_StringSummary(command, result); + Execute_StringSummary(command, result); } static bool FixArrayTypeNameWithRegex(ConstString &type_name) { llvm::StringRef type_name_ref(type_name.GetStringRef()); - if (type_name_ref.endswith("[]")) { + if (type_name_ref.ends_with("[]")) { std::string type_name_str(type_name.GetCString()); type_name_str.resize(type_name_str.length() - 2); if (type_name_str.back() != ' ') @@ -1773,13 +1767,13 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc < 1) { result.AppendErrorWithFormat("%s takes 1 or more args.\n", m_cmd_name.c_str()); - return false; + return; } for (auto &entry : command.entries()) { @@ -1795,7 +1789,6 @@ protected: } result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1875,13 +1868,13 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { result.AppendErrorWithFormat("%s takes arguments and/or a language", m_cmd_name.c_str()); - return false; + return; } if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { @@ -1893,7 +1886,7 @@ protected: if (!typeCS) { result.AppendError("empty category name not allowed"); - return false; + return; } DataVisualization::Categories::Enable(typeCS); lldb::TypeCategoryImplSP cate; @@ -1909,7 +1902,6 @@ protected: DataVisualization::Categories::Enable(m_options.m_language); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -1943,13 +1935,13 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc < 1) { result.AppendErrorWithFormat("%s takes 1 or more arg.\n", m_cmd_name.c_str()); - return false; + return; } bool success = true; @@ -1961,17 +1953,15 @@ protected: if (!typeCS) { result.AppendError("empty category name not allowed"); - return false; + return; } if (!DataVisualization::Categories::Delete(typeCS)) success = false; // keep deleting even if we hit an error } if (success) { result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } else { result.AppendError("cannot delete one or more categories\n"); - return false; } } }; @@ -2052,13 +2042,13 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { result.AppendErrorWithFormat("%s takes arguments and/or a language", m_cmd_name.c_str()); - return false; + return; } if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { @@ -2071,7 +2061,7 @@ protected: if (!typeCS) { result.AppendError("empty category name not allowed"); - return false; + return; } DataVisualization::Categories::Disable(typeCS); } @@ -2081,7 +2071,6 @@ protected: DataVisualization::Categories::Disable(m_options.m_language); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -2117,7 +2106,7 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); std::unique_ptr<RegularExpression> regex; @@ -2128,12 +2117,12 @@ protected: if (!regex->IsValid()) { result.AppendErrorWithFormat( "syntax error in category regular expression '%s'", arg); - return false; + return; } } else if (argc != 0) { result.AppendErrorWithFormat("%s takes 0 or one arg.\n", m_cmd_name.c_str()); - return false; + return; } DataVisualization::Categories::ForEach( @@ -2157,7 +2146,6 @@ protected: }); result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } }; @@ -2171,8 +2159,6 @@ public: "Show a list of current filters.") {} }; -#if LLDB_ENABLE_PYTHON - // CommandObjectTypeSynthList class CommandObjectTypeSynthList @@ -2184,8 +2170,6 @@ public: "Show a list of current synthetic providers.") {} }; -#endif - // CommandObjectTypeFilterDelete class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { @@ -2197,8 +2181,6 @@ public: ~CommandObjectTypeFilterDelete() override = default; }; -#if LLDB_ENABLE_PYTHON - // CommandObjectTypeSynthDelete class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { @@ -2210,7 +2192,6 @@ public: ~CommandObjectTypeSynthDelete() override = default; }; -#endif // CommandObjectTypeFilterClear @@ -2222,7 +2203,6 @@ public: "Delete all existing filter.") {} }; -#if LLDB_ENABLE_PYTHON // CommandObjectTypeSynthClear class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { @@ -2393,7 +2373,6 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, return true; } -#endif #define LLDB_OPTIONS_type_filter_add #include "CommandOptions.inc" @@ -2579,19 +2558,19 @@ all children of my_foo as if no filter was defined:" ~CommandObjectTypeFilterAdd() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc < 1) { result.AppendErrorWithFormat("%s takes one or more args.\n", m_cmd_name.c_str()); - return false; + return; } if (m_options.m_expr_paths.empty()) { result.AppendErrorWithFormat("%s needs one or more children.\n", m_cmd_name.c_str()); - return false; + return; } TypeFilterImplSP entry(new TypeFilterImpl( @@ -2620,7 +2599,7 @@ protected: for (auto &arg_entry : command.entries()) { if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); - return false; + return; } ConstString typeCS(arg_entry.ref()); @@ -2628,12 +2607,11 @@ protected: m_options.m_regex ? eRegexFilter : eRegularFilter, m_options.m_category, &error)) { result.AppendError(error.AsCString()); - return false; + return; } } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); } }; @@ -2739,12 +2717,12 @@ public: return m_cmd_help_long; } - bool DoExecute(llvm::StringRef raw_command_line, + void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { if (raw_command_line.empty()) { result.AppendError( "type lookup cannot be invoked without a type name as argument"); - return false; + return; } auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); @@ -2756,7 +2734,7 @@ public: if (args.HasArgs()) if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx)) - return false; + return; ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); @@ -2836,7 +2814,6 @@ public: result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult); - return true; } }; @@ -2867,13 +2844,13 @@ public: ~CommandObjectFormatterInfo() override = default; protected: - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { TargetSP target_sp = GetDebugger().GetSelectedTarget(); Thread *thread = GetDefaultThread(); if (!thread) { result.AppendError("no default thread"); - return false; + return; } StackFrameSP frame_sp = @@ -2903,10 +2880,8 @@ protected: << ") " << command << "\n"; result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); } - return true; } else { result.AppendError("failed to evaluate expression"); - return false; } } @@ -2941,8 +2916,6 @@ public: ~CommandObjectTypeFormat() override = default; }; -#if LLDB_ENABLE_PYTHON - class CommandObjectTypeSynth : public CommandObjectMultiword { public: CommandObjectTypeSynth(CommandInterpreter &interpreter) @@ -2970,8 +2943,6 @@ public: ~CommandObjectTypeSynth() override = default; }; -#endif - class CommandObjectTypeFilter : public CommandObjectMultiword { public: CommandObjectTypeFilter(CommandInterpreter &interpreter) @@ -3056,10 +3027,8 @@ CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) CommandObjectSP(new CommandObjectTypeFormat(interpreter))); LoadSubCommand("summary", CommandObjectSP(new CommandObjectTypeSummary(interpreter))); -#if LLDB_ENABLE_PYTHON LoadSubCommand("synthetic", CommandObjectSP(new CommandObjectTypeSynth(interpreter))); -#endif LoadSubCommand("lookup", CommandObjectSP(new CommandObjectTypeLookup(interpreter))); } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.cpp index 9b3c9e67a1a7..f13ec18e240c 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.cpp @@ -22,8 +22,7 @@ CommandObjectVersion::CommandObjectVersion(CommandInterpreter &interpreter) CommandObjectVersion::~CommandObjectVersion() = default; -bool CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) { +void CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) { result.AppendMessageWithFormat("%s\n", lldb_private::GetVersion()); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.h index dce1a8d67b88..4ba081bf8706 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.h +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectVersion.h @@ -22,7 +22,7 @@ public: ~CommandObjectVersion() override; protected: - bool DoExecute(Args &args, CommandReturnObject &result) override; + void DoExecute(Args &args, CommandReturnObject &result) override; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp index a4929ea0d515..c80868d33905 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -207,7 +207,7 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { @@ -230,7 +230,7 @@ protected: if (num_watchpoints == 0) { result.AppendMessage("No watchpoints currently set."); result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } Stream &output_stream = result.GetOutputStream(); @@ -249,7 +249,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } const size_t size = wp_ids.size(); @@ -260,8 +260,6 @@ protected: result.SetStatus(eReturnStatusSuccessFinishNoResult); } } - - return result.Succeeded(); } private: @@ -297,10 +295,10 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) - return false; + return; std::unique_lock<std::recursive_mutex> lock; target->GetWatchpointList().GetListMutex(lock); @@ -311,7 +309,7 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to be enabled."); - return false; + return; } if (command.GetArgumentCount() == 0) { @@ -327,7 +325,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } int count = 0; @@ -338,8 +336,6 @@ protected: result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); result.SetStatus(eReturnStatusSuccessFinishNoResult); } - - return result.Succeeded(); } }; @@ -373,10 +369,10 @@ public: } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) - return false; + return; std::unique_lock<std::recursive_mutex> lock; target->GetWatchpointList().GetListMutex(lock); @@ -386,7 +382,7 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to be disabled."); - return false; + return; } if (command.GetArgumentCount() == 0) { @@ -405,7 +401,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } int count = 0; @@ -416,8 +412,6 @@ protected: result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); result.SetStatus(eReturnStatusSuccessFinishNoResult); } - - return result.Succeeded(); } }; @@ -489,10 +483,10 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) - return false; + return; std::unique_lock<std::recursive_mutex> lock; target->GetWatchpointList().GetListMutex(lock); @@ -503,7 +497,7 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to be deleted."); - return false; + return; } if (command.empty()) { @@ -519,7 +513,7 @@ protected: (uint64_t)num_watchpoints); } result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + return; } // Particular watchpoints selected; delete them. @@ -527,7 +521,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } int count = 0; @@ -537,8 +531,6 @@ protected: ++count; result.AppendMessageWithFormat("%d watchpoints deleted.\n", count); result.SetStatus(eReturnStatusSuccessFinishNoResult); - - return result.Succeeded(); } private: @@ -616,10 +608,10 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) - return false; + return; std::unique_lock<std::recursive_mutex> lock; target->GetWatchpointList().GetListMutex(lock); @@ -630,7 +622,7 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to be ignored."); - return false; + return; } if (command.GetArgumentCount() == 0) { @@ -645,7 +637,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } int count = 0; @@ -656,8 +648,6 @@ protected: result.AppendMessageWithFormat("%d watchpoints ignored.\n", count); result.SetStatus(eReturnStatusSuccessFinishNoResult); } - - return result.Succeeded(); } private: @@ -742,10 +732,10 @@ public: }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) - return false; + return; std::unique_lock<std::recursive_mutex> lock; target->GetWatchpointList().GetListMutex(lock); @@ -756,7 +746,7 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to be modified."); - return false; + return; } if (command.GetArgumentCount() == 0) { @@ -769,7 +759,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } int count = 0; @@ -784,8 +774,6 @@ protected: result.AppendMessageWithFormat("%d watchpoints modified.\n", count); result.SetStatus(eReturnStatusSuccessFinishNoResult); } - - return result.Succeeded(); } private: @@ -803,7 +791,7 @@ public: "Set a watchpoint on a variable. " "Use the '-w' option to specify the type of watchpoint and " "the '-s' option to specify the byte size to watch for. " - "If no '-w' option is specified, it defaults to write. " + "If no '-w' option is specified, it defaults to modify. " "If no '-s' option is specified, it defaults to the variable's " "byte size. " "Note that there are limited hardware resources for watchpoints. " @@ -866,7 +854,7 @@ protected: return variable_list.GetSize() - old_size; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = GetDebugger().GetSelectedTarget().get(); StackFrame *frame = m_exe_ctx.GetFramePtr(); @@ -875,12 +863,12 @@ protected: if (command.GetArgumentCount() <= 0) { result.AppendError("required argument missing; " "specify your program variable to watch for"); - return false; + return; } - // If no '-w' is specified, default to '-w write'. + // If no '-w' is specified, default to '-w modify'. if (!m_option_watchpoint.watch_type_specified) { - m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; + m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify; } // We passed the sanity check for the command. Proceed to set the @@ -895,7 +883,7 @@ protected: // A simple watch variable gesture allows only one argument. if (command.GetArgumentCount() != 1) { result.AppendError("specify exactly one variable to watch for"); - return false; + return; } // Things have checked out ok... @@ -930,9 +918,9 @@ protected: if (addr_type == eAddressTypeLoad) { // We're in business. // Find out the size of this variable. - size = m_option_watchpoint.watch_size == 0 + size = m_option_watchpoint.watch_size.GetCurrentValue() == 0 ? valobj_sp->GetByteSize().value_or(0) - : m_option_watchpoint.watch_size; + : m_option_watchpoint.watch_size.GetCurrentValue(); } compiler_type = valobj_sp->GetCompilerType(); } else { @@ -943,11 +931,27 @@ protected: result.AppendErrorWithFormat("unable to find any variable " "expression path that matches '%s'", command.GetArgumentAtIndex(0)); - return false; + return; } // Now it's time to create the watchpoint. - uint32_t watch_type = m_option_watchpoint.watch_type; + uint32_t watch_type = 0; + switch (m_option_watchpoint.watch_type) { + case OptionGroupWatchpoint::eWatchModify: + watch_type |= LLDB_WATCH_TYPE_MODIFY; + break; + case OptionGroupWatchpoint::eWatchRead: + watch_type |= LLDB_WATCH_TYPE_READ; + break; + case OptionGroupWatchpoint::eWatchReadWrite: + watch_type |= LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE; + break; + case OptionGroupWatchpoint::eWatchWrite: + watch_type |= LLDB_WATCH_TYPE_WRITE; + break; + case OptionGroupWatchpoint::eWatchInvalid: + break; + }; error.Clear(); WatchpointSP watch_sp = @@ -959,7 +963,7 @@ protected: addr, static_cast<uint64_t>(size), command.GetArgumentAtIndex(0)); if (const char *error_message = error.AsCString(nullptr)) result.AppendError(error_message); - return result.Succeeded(); + return; } watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0)); @@ -978,8 +982,6 @@ protected: watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); output_stream.EOL(); result.SetStatus(eReturnStatusSuccessFinishResult); - - return result.Succeeded(); } private: @@ -999,7 +1001,7 @@ public: "Use the '-l' option to specify the language of the expression. " "Use the '-w' option to specify the type of watchpoint and " "the '-s' option to specify the byte size to watch for. " - "If no '-w' option is specified, it defaults to write. " + "If no '-w' option is specified, it defaults to modify. " "If no '-s' option is specified, it defaults to the target's " "pointer byte size. " "Note that there are limited hardware resources for watchpoints. " @@ -1013,7 +1015,7 @@ public: R"( Examples: -(lldb) watchpoint set expression -w write -s 1 -- foo + 32 +(lldb) watchpoint set expression -w modify -s 1 -- foo + 32 Watches write access for the 1-byte region pointed to by the address 'foo + 32')"); @@ -1045,7 +1047,7 @@ Examples: Options *GetOptions() override { return &m_option_group; } protected: - bool DoExecute(llvm::StringRef raw_command, + void DoExecute(llvm::StringRef raw_command, CommandReturnObject &result) override { auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); m_option_group.NotifyOptionParsingStarting( @@ -1061,19 +1063,19 @@ protected: if (args.HasArgs()) if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx)) - return false; + return; // If no argument is present, issue an error message. There's no way to // set a watchpoint. if (raw_command.trim().empty()) { result.AppendError("required argument missing; specify an expression " "to evaluate into the address to watch for"); - return false; + return; } // If no '-w' is specified, default to '-w write'. if (!m_option_watchpoint.watch_type_specified) { - m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; + m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify; } // We passed the sanity check for the command. Proceed to set the @@ -1100,7 +1102,7 @@ protected: result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data()); if (valobj_sp && !valobj_sp->GetError().Success()) result.AppendError(valobj_sp->GetError().AsCString()); - return false; + return; } // Get the address to watch. @@ -1108,16 +1110,32 @@ protected: addr = valobj_sp->GetValueAsUnsigned(0, &success); if (!success) { result.AppendError("expression did not evaluate to an address"); - return false; + return; } - if (m_option_watchpoint.watch_size != 0) - size = m_option_watchpoint.watch_size; + if (m_option_watchpoint.watch_size.GetCurrentValue() != 0) + size = m_option_watchpoint.watch_size.GetCurrentValue(); else size = target->GetArchitecture().GetAddressByteSize(); // Now it's time to create the watchpoint. - uint32_t watch_type = m_option_watchpoint.watch_type; + uint32_t watch_type; + switch (m_option_watchpoint.watch_type) { + case OptionGroupWatchpoint::eWatchRead: + watch_type = LLDB_WATCH_TYPE_READ; + break; + case OptionGroupWatchpoint::eWatchWrite: + watch_type = LLDB_WATCH_TYPE_WRITE; + break; + case OptionGroupWatchpoint::eWatchModify: + watch_type = LLDB_WATCH_TYPE_MODIFY; + break; + case OptionGroupWatchpoint::eWatchReadWrite: + watch_type = LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE; + break; + default: + watch_type = LLDB_WATCH_TYPE_MODIFY; + } // Fetch the type from the value object, the type of the watched object is // the pointee type @@ -1141,8 +1159,6 @@ protected: if (error.AsCString(nullptr)) result.AppendError(error.AsCString()); } - - return result.Succeeded(); } private: diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index 37052ddd62c8..b1629ceab270 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -366,7 +366,7 @@ are no syntax errors may indicate that a function was declared but never called. }; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); @@ -374,7 +374,7 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to have commands added"); - return false; + return; } if (!m_options.m_function_name.empty()) { @@ -388,7 +388,7 @@ protected: if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -441,8 +441,6 @@ protected: } } } - - return result.Succeeded(); } private: @@ -475,7 +473,7 @@ public: ~CommandObjectWatchpointCommandDelete() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); @@ -483,20 +481,20 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist to have commands deleted"); - return false; + return; } if (command.GetArgumentCount() == 0) { result.AppendError( "No watchpoint specified from which to delete the commands"); - return false; + return; } std::vector<uint32_t> valid_wp_ids; if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -509,10 +507,9 @@ protected: wp->ClearCallback(); } else { result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id); - return false; + return; } } - return result.Succeeded(); } }; @@ -543,7 +540,7 @@ public: ~CommandObjectWatchpointCommandList() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); @@ -551,20 +548,20 @@ protected: if (num_watchpoints == 0) { result.AppendError("No watchpoints exist for which to list commands"); - return false; + return; } if (command.GetArgumentCount() == 0) { result.AppendError( "No watchpoint specified for which to list the commands"); - return false; + return; } std::vector<uint32_t> valid_wp_ids; if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids)) { result.AppendError("Invalid watchpoints specification."); - return false; + return; } result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -598,8 +595,6 @@ protected: } } } - - return result.Succeeded(); } }; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp index 85ad8ff5e071..b1c13d4df79e 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp @@ -34,11 +34,15 @@ Status CommandOptionsProcessLaunch::SetOptionValue( Status error; const int short_option = g_process_launch_options[option_idx].short_option; + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); switch (short_option) { case 's': // Stop at program entry point launch_info.GetFlags().Set(eLaunchFlagStopAtEntry); break; - + case 'm': // Stop at user entry point + target_sp->CreateBreakpointAtUserEntry(error); + break; case 'i': // STDIN for read only { FileAction action; @@ -89,8 +93,6 @@ Status CommandOptionsProcessLaunch::SetOptionValue( break; case 'a': { - TargetSP target_sp = - execution_context ? execution_context->GetTargetSP() : TargetSP(); PlatformSP platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP(); launch_info.GetArchitecture() = diff --git a/contrib/llvm-project/lldb/source/Commands/Options.td b/contrib/llvm-project/lldb/source/Commands/Options.td index 04830b8b990e..ed3167727bcd 100644 --- a/contrib/llvm-project/lldb/source/Commands/Options.td +++ b/contrib/llvm-project/lldb/source/Commands/Options.td @@ -8,6 +8,13 @@ let Command = "target modules dump symtab" in { Desc<"Do not demangle symbol names before showing them.">; } +let Command = "target modules dump separate debug info" in { + def tm_json : Option<"json", "j">, Group<1>, + Desc<"Output the details in JSON format.">; + def tm_errors_only : Option<"errors-only", "e">, Group<1>, + Desc<"Filter to show only debug info files with errors.">; +} + let Command = "help" in { def help_hide_aliases : Option<"hide-aliases", "a">, Desc<"Hide aliases in the command list.">; @@ -390,7 +397,7 @@ let Command = "expression" in { Arg<"Boolean">, Desc<"Persist expression result in a variable for subsequent use. " "Expression results will be labeled with $-prefixed variables, e.g. $0, " - "$1, etc. Defaults to true.">; + "$1, etc.">; } let Command = "frame diag" in { @@ -675,6 +682,10 @@ let Command = "platform shell" in { let Command = "process launch" in { def process_launch_stop_at_entry : Option<"stop-at-entry", "s">, Desc<"Stop at the entry point of the program when launching a process.">; + def process_launch_stop_at_user_entry : Option<"stop-at-user-entry", "m">, + Desc<"Stop at the user entry point when launching a process. For C based " + "languages this will be the 'main' function, but this might differ for " + "other languages.">; def process_launch_disable_aslr : Option<"disable-aslr", "A">, Arg<"Boolean">, Desc<"Set whether to disable address space layout randomization when launching a process.">; def process_launch_plugin : Option<"plugin", "P">, Arg<"Plugin">, @@ -1106,6 +1117,12 @@ let Command = "thread plan list" in { Desc<"Display thread plans for unreported threads">; } +let Command = "thread select" in { + def thread_select_thread_id : Option<"thread-id", "t">, Group<2>, + Arg<"ThreadID">, Completion<"ThreadID">, + Desc<"Provide a thread ID instead of a thread index.">; +} + let Command = "thread trace dump function calls" in { def thread_trace_dump_function_calls_file : Option<"file", "F">, Group<1>, Arg<"Filename">, diff --git a/contrib/llvm-project/lldb/source/Core/Address.cpp b/contrib/llvm-project/lldb/source/Core/Address.cpp index 189d50fe962a..19d34db44ea5 100644 --- a/contrib/llvm-project/lldb/source/Core/Address.cpp +++ b/contrib/llvm-project/lldb/source/Core/Address.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/Address.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Declaration.h" #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Module.h" @@ -28,6 +29,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" @@ -405,7 +407,7 @@ bool Address::GetDescription(Stream &s, Target &target, bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size, - bool all_ranges) const { + bool all_ranges, llvm::StringRef pattern) const { // If the section was nullptr, only load address is going to work unless we // are trying to deref a pointer SectionSP section_sp(GetSection()); @@ -501,7 +503,6 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, pointer_size = target->GetArchitecture().GetAddressByteSize(); else if (module_sp) pointer_size = module_sp->GetArchitecture().GetAddressByteSize(); - bool showed_info = false; if (section_sp) { SectionType sect_type = section_sp->GetType(); @@ -515,7 +516,16 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, if (symbol) { const char *symbol_name = symbol->GetName().AsCString(); if (symbol_name) { - s->PutCString(symbol_name); + llvm::StringRef ansi_prefix; + llvm::StringRef ansi_suffix; + if (target) { + ansi_prefix = + target->GetDebugger().GetRegexMatchAnsiPrefix(); + ansi_suffix = + target->GetDebugger().GetRegexMatchAnsiSuffix(); + } + s->PutCStringColorHighlighted(symbol_name, pattern, + ansi_prefix, ansi_suffix); addr_t delta = file_Addr - symbol->GetAddressRef().GetFileAddress(); if (delta) @@ -643,7 +653,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, pointer_sc.symbol != nullptr) { s->PutCString(": "); pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, - false, true, true); + false, true, true, pattern); } } } @@ -682,19 +692,22 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, // address. sc.DumpStopContext(s, exe_scope, *this, show_fullpaths, show_module, show_inlined_frames, - show_function_arguments, show_function_name); + show_function_arguments, show_function_name, + pattern); } else { // We found a symbol but it was in a different section so it // isn't the symbol we should be showing, just show the section // name + offset - Dump(s, exe_scope, DumpStyleSectionNameOffset); + Dump(s, exe_scope, DumpStyleSectionNameOffset, DumpStyleInvalid, + UINT32_MAX, false, pattern); } } } } } else { if (fallback_style != DumpStyleInvalid) - return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size, + false, pattern); return false; } break; @@ -715,7 +728,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, sc.symbol->GetAddressRef().GetSection() != GetSection()) sc.symbol = nullptr; } - sc.GetDescription(s, eDescriptionLevelBrief, target); + sc.GetDescription(s, eDescriptionLevelBrief, target, pattern); if (sc.block) { bool can_create = true; @@ -763,7 +776,8 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, } } else { if (fallback_style != DumpStyleInvalid) - return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size, + false, pattern); return false; } break; diff --git a/contrib/llvm-project/lldb/source/Core/CoreProperties.td b/contrib/llvm-project/lldb/source/Core/CoreProperties.td index 53bc586905a3..d89afc239276 100644 --- a/contrib/llvm-project/lldb/source/Core/CoreProperties.td +++ b/contrib/llvm-project/lldb/source/Core/CoreProperties.td @@ -4,7 +4,7 @@ let Definition = "modulelist" in { def EnableExternalLookup: Property<"enable-external-lookup", "Boolean">, Global, DefaultTrue, - Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched.">; + Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched. If all other methods fail there may be symbol-locator plugins that, if configured properly, will also attempt to acquire symbols. The debuginfod plugin defaults to the DEGUFINFOD_URLS environment variable which is configurable through the 'plugin.symbol-locator.debuginfod.server_urls' setting.">; def EnableBackgroundLookup: Property<"enable-background-lookup", "Boolean">, Global, DefaultFalse, @@ -65,6 +65,14 @@ let Definition = "debugger" in { DefaultEnumValue<"OptionValueString::eOptionEncodeCharacterEscapeSequences">, DefaultStringValue<"(lldb) ">, Desc<"The debugger command line prompt displayed for the user.">; + def PromptAnsiPrefix: Property<"prompt-ansi-prefix", "String">, + Global, + DefaultStringValue<"${ansi.faint}">, + Desc<"When in a color-enabled terminal, use the ANSI terminal code specified in this format immediately before the prompt.">; + def PromptAnsiSuffix: Property<"prompt-ansi-suffix", "String">, + Global, + DefaultStringValue<"${ansi.normal}">, + Desc<"When in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the prompt.">; def ScriptLanguage: Property<"script-lang", "Enum">, Global, DefaultEnumValue<"eScriptLanguageLua">, @@ -173,8 +181,8 @@ let Definition = "debugger" in { Desc<"If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true).">; def TabSize: Property<"tab-size", "UInt64">, Global, - DefaultUnsignedValue<4>, - Desc<"The tab size to use when indenting code in multi-line input mode (default: 4).">; + DefaultUnsignedValue<2>, + Desc<"The tab size to use when indenting code in multi-line input mode (default: 2).">; def EscapeNonPrintables: Property<"escape-non-printables", "Boolean">, Global, DefaultTrue, @@ -195,6 +203,18 @@ let Definition = "debugger" in { Global, DefaultStringValue<"${ansi.normal}">, Desc<"When displaying suggestion in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the suggestion.">; + def ShowRegexMatchAnsiPrefix: Property<"show-regex-match-ansi-prefix", "String">, + Global, + DefaultStringValue<"${ansi.fg.red}">, + Desc<"When displaying a regex match in a color-enabled terminal, use the ANSI terminal code specified in this format immediately before the match.">; + def ShowRegexMatchAnsiSuffix: Property<"show-regex-match-ansi-suffix", "String">, + Global, + DefaultStringValue<"${ansi.normal}">, + Desc<"When displaying a regex match in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the match.">; + def ShowDontUsePoHint: Property<"show-dont-use-po-hint", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, and object description was requested for a type that does not implement it, LLDB will print a hint telling the user to consider using p instead.">; def DWIMPrintVerbosity: Property<"dwim-print-verbosity", "Enum">, Global, DefaultEnumValue<"eDWIMPrintVerbosityNone">, diff --git a/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp b/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp index b29327db5ca3..a8127efc1df0 100644 --- a/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp +++ b/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp @@ -285,7 +285,7 @@ bool ConstStringTable::Encode(DataEncoder &encoder) { 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. + encoder.AppendU8(0); // Start the string table 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 == diff --git a/contrib/llvm-project/lldb/source/Core/Debugger.cpp b/contrib/llvm-project/lldb/source/Core/Debugger.cpp index f54108629185..97311b4716ac 100644 --- a/contrib/llvm-project/lldb/source/Core/Debugger.cpp +++ b/contrib/llvm-project/lldb/source/Core/Debugger.cpp @@ -16,12 +16,12 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamAsynchronousIO.h" -#include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Expression/REPL.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Host/Terminal.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -236,6 +236,13 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, // codes. SetPrompt(GetPrompt()); } else if (property_path == + g_debugger_properties[ePropertyPromptAnsiPrefix].name || + property_path == + g_debugger_properties[ePropertyPromptAnsiSuffix].name) { + // Prompt colors changed. Ping the prompt so it can reset the ansi + // terminal codes. + SetPrompt(GetPrompt()); + } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) { // use-source-cache changed. Wipe out the cache contents if it was // disabled. @@ -301,6 +308,18 @@ llvm::StringRef Debugger::GetPrompt() const { idx, g_debugger_properties[idx].default_cstr_value); } +llvm::StringRef Debugger::GetPromptAnsiPrefix() const { + const uint32_t idx = ePropertyPromptAnsiPrefix; + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); +} + +llvm::StringRef Debugger::GetPromptAnsiSuffix() const { + const uint32_t idx = ePropertyPromptAnsiSuffix; + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); +} + void Debugger::SetPrompt(llvm::StringRef p) { constexpr uint32_t idx = ePropertyPrompt; SetPropertyAtIndex(idx, p); @@ -434,6 +453,24 @@ llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const { idx, g_debugger_properties[idx].default_cstr_value); } +llvm::StringRef Debugger::GetRegexMatchAnsiPrefix() const { + const uint32_t idx = ePropertyShowRegexMatchAnsiPrefix; + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); +} + +llvm::StringRef Debugger::GetRegexMatchAnsiSuffix() const { + const uint32_t idx = ePropertyShowRegexMatchAnsiSuffix; + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); +} + +bool Debugger::GetShowDontUsePoHint() const { + const uint32_t idx = ePropertyShowDontUsePoHint; + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); +} + bool Debugger::GetUseSourceCache() const { const uint32_t idx = ePropertyUseSourceCache; return GetPropertyAtIndexAs<bool>( @@ -905,7 +942,7 @@ void Debugger::Clear() { for (TargetSP target_sp : m_target_list.Targets()) { if (target_sp) { if (ProcessSP process_sp = target_sp->GetProcessSP()) - process_sp->Finalize(); + process_sp->Finalize(false /* not destructing */); target_sp->Destroy(); } } @@ -923,15 +960,6 @@ void Debugger::Clear() { }); } -bool Debugger::GetCloseInputOnEOF() const { - // return m_input_comm.GetCloseOnEOF(); - return false; -} - -void Debugger::SetCloseInputOnEOF(bool b) { - // m_input_comm.SetCloseOnEOF(b); -} - bool Debugger::GetAsyncExecution() { return !m_command_interpreter_up->GetSynchronous(); } @@ -1275,17 +1303,17 @@ bool Debugger::InterruptRequested() { return GetCommandInterpreter().WasInterrupted(); } -Debugger::InterruptionReport::InterruptionReport(std::string function_name, - const llvm::formatv_object_base &payload) : - m_function_name(std::move(function_name)), - m_interrupt_time(std::chrono::system_clock::now()), - m_thread_id(llvm::get_threadid()) { +Debugger::InterruptionReport::InterruptionReport( + std::string function_name, const llvm::formatv_object_base &payload) + : m_function_name(std::move(function_name)), + m_interrupt_time(std::chrono::system_clock::now()), + m_thread_id(llvm::get_threadid()) { llvm::raw_string_ostream desc(m_description); desc << payload << "\n"; } void Debugger::ReportInterruption(const InterruptionReport &report) { - // For now, just log the description: + // For now, just log the description: Log *log = GetLog(LLDBLog::Host); LLDB_LOG(log, "Interruption: {0}", report.m_description); } diff --git a/contrib/llvm-project/lldb/source/Core/Disassembler.cpp b/contrib/llvm-project/lldb/source/Core/Disassembler.cpp index 104e9100e388..166b5fdf22f0 100644 --- a/contrib/llvm-project/lldb/source/Core/Disassembler.cpp +++ b/contrib/llvm-project/lldb/source/Core/Disassembler.cpp @@ -645,18 +645,29 @@ void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, instruction_control_flow_kind)); } + bool show_color = false; + if (exe_ctx) { + if (TargetSP target_sp = exe_ctx->GetTargetSP()) { + show_color = target_sp->GetDebugger().GetUseColor(); + } + } const size_t opcode_pos = ss.GetSizeOfLastLine(); + const std::string &opcode_name = + show_color ? m_markup_opcode_name : m_opcode_name; + const std::string &mnemonics = show_color ? m_markup_mnemonics : m_mnemonics; // The default opcode size of 7 characters is plenty for most architectures // but some like arm can pull out the occasional vqrshrun.s16. We won't get - // consistent column spacing in these cases, unfortunately. + // consistent column spacing in these cases, unfortunately. Also note that we + // need to directly use m_opcode_name here (instead of opcode_name) so we + // don't include color codes as characters. if (m_opcode_name.length() >= opcode_column_width) { opcode_column_width = m_opcode_name.length() + 1; } - ss.PutCString(m_opcode_name); + ss.PutCString(opcode_name); ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); - ss.PutCString(m_mnemonics); + ss.PutCString(mnemonics); if (!m_comment.empty()) { ss.FillLastLineToColumn( diff --git a/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp b/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp index cb76b118325b..986c9a181919 100644 --- a/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp +++ b/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp @@ -620,10 +620,17 @@ lldb::offset_t lldb_private::DumpDataExtractor( case 2: case 4: case 8: - s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, - (int)(2 * item_byte_size), (int)(2 * item_byte_size), - DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, - item_bit_offset)); + if (Target::GetGlobalProperties() + .ShowHexVariableValuesWithLeadingZeroes()) { + s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, + (int)(2 * item_byte_size), (int)(2 * item_byte_size), + DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset)); + } else { + s->Printf(wantsuppercase ? "0x%" PRIX64 : "0x%" PRIx64, + DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset)); + } break; default: { assert(item_bit_size == 0 && item_bit_offset == 0); diff --git a/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp b/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp index 2e5378f654a5..7871be6fc451 100644 --- a/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp +++ b/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp @@ -8,12 +8,12 @@ #include "lldb/Target/DynamicLoader.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Platform.h" @@ -188,7 +188,7 @@ static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr, ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( Process *process, llvm::StringRef name, UUID uuid, addr_t value, bool value_is_offset, bool force_symbol_search, bool notify, - bool set_address_in_target) { + bool set_address_in_target, bool allow_memory_image_last_resort) { ModuleSP memory_module_sp; ModuleSP module_sp; PlatformSP platform_sp = process->GetTarget().GetPlatform(); @@ -218,9 +218,9 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( if (!module_sp) { FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); module_spec.GetSymbolFileSpec() = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); ModuleSpec objfile_module_spec = - Symbols::LocateExecutableObjectFile(module_spec); + PluginManager::LocateExecutableObjectFile(module_spec); module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec(); if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) && FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) { @@ -231,10 +231,13 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( // If we haven't found a binary, or we don't have a SymbolFile, see // if there is an external search tool that can find it. if (!module_sp || !module_sp->GetSymbolFileFileSpec()) { - Symbols::DownloadObjectAndSymbolFile(module_spec, error, - force_symbol_search); + PluginManager::DownloadObjectAndSymbolFile(module_spec, error, + force_symbol_search); if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { module_sp = std::make_shared<Module>(module_spec); + } else if (force_symbol_search && error.AsCString("") && + error.AsCString("")[0] != '\0') { + target.GetDebugger().GetErrorStream() << error.AsCString(); } } @@ -245,7 +248,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( // If we couldn't find the binary anywhere else, as a last resort, // read it out of memory. - if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) { + if (allow_memory_image_last_resort && !module_sp.get() && + value != LLDB_INVALID_ADDRESS && !value_is_offset) { if (!memory_module_sp) memory_module_sp = ReadUnnamedMemoryModule(process, value, name); if (memory_module_sp) @@ -266,8 +270,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( if (value != LLDB_INVALID_ADDRESS) { LLDB_LOGF(log, "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading " - "binary UUID %s at %s 0x%" PRIx64, - uuid.GetAsString().c_str(), + "binary %s UUID %s at %s 0x%" PRIx64, + name.str().c_str(), uuid.GetAsString().c_str(), value_is_offset ? "offset" : "address", value); module_sp->SetLoadAddress(target, value, value_is_offset, changed); } else { @@ -275,8 +279,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( // offset 0. LLDB_LOGF(log, "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading " - "binary UUID %s at file address", - uuid.GetAsString().c_str()); + "binary %s UUID %s at file address", + name.str().c_str(), uuid.GetAsString().c_str()); module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, changed); } @@ -284,8 +288,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( // In-memory image, load at its true address, offset 0. LLDB_LOGF(log, "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary " - "UUID %s from memory at address 0x%" PRIx64, - uuid.GetAsString().c_str(), value); + "%s UUID %s from memory at address 0x%" PRIx64, + name.str().c_str(), uuid.GetAsString().c_str(), value); module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, changed); } @@ -297,10 +301,26 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( target.ModulesDidLoad(added_module); } } else { - LLDB_LOGF(log, "Unable to find binary with UUID %s and load it at " - "%s 0x%" PRIx64, - uuid.GetAsString().c_str(), - value_is_offset ? "offset" : "address", value); + if (force_symbol_search) { + Stream &s = target.GetDebugger().GetErrorStream(); + s.Printf("Unable to find file"); + if (!name.empty()) + s.Printf(" %s", name.str().c_str()); + if (uuid.IsValid()) + s.Printf(" with UUID %s", uuid.GetAsString().c_str()); + if (value != LLDB_INVALID_ADDRESS) { + if (value_is_offset) + s.Printf(" with slide 0x%" PRIx64, value); + else + s.Printf(" at address 0x%" PRIx64, value); + } + s.Printf("\n"); + } + LLDB_LOGF(log, + "Unable to find binary %s with UUID %s and load it at " + "%s 0x%" PRIx64, + name.str().c_str(), uuid.GetAsString().c_str(), + value_is_offset ? "offset" : "address", value); } return module_sp; diff --git a/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp b/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp index 753bee25de6d..d240b4d3b331 100644 --- a/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp +++ b/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/Address.h" #include "lldb/Core/DumpRegisterValue.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" diff --git a/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp b/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp index 00ab20243855..94986457552d 100644 --- a/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp +++ b/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp @@ -286,13 +286,6 @@ void FormatEntity::Entry::AppendText(const char *cstr) { return AppendText(llvm::StringRef(cstr)); } -Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { - entry.Clear(); - entry.type = Entry::Type::Root; - llvm::StringRef modifiable_format(format_str); - return ParseInternal(modifiable_format, entry, 0); -} - #define ENUM_TO_CSTR(eee) \ case FormatEntity::Entry::Type::eee: \ return #eee @@ -1252,9 +1245,10 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; - if ((ostype == llvm::Triple::FreeBSD) || - (ostype == llvm::Triple::Linux) || - (ostype == llvm::Triple::NetBSD)) { + if (ostype == llvm::Triple::FreeBSD || + ostype == llvm::Triple::Linux || + ostype == llvm::Triple::NetBSD || + ostype == llvm::Triple::OpenBSD) { format = "%" PRIu64; } } else { @@ -1991,8 +1985,8 @@ static const Definition *FindEntry(const llvm::StringRef &format_str, return parent; } -Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, - uint32_t depth) { +static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, + uint32_t depth) { Status error; while (!format.empty() && error.Success()) { const size_t non_special_chars = format.find_first_of("${}\\"); @@ -2017,7 +2011,7 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, case '{': { format = format.drop_front(); // Skip the '{' Entry scope_entry(Entry::Type::Scope); - error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); + error = ParseInternal(format, scope_entry, depth + 1); if (error.Fail()) return error; parent_entry.AppendEntry(std::move(scope_entry)); @@ -2467,3 +2461,10 @@ void FormatEntity::PrettyPrintFunctionArguments( out_stream.Printf("%s=<unavailable>", var_name); } } + +Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { + entry.Clear(); + entry.type = Entry::Type::Root; + llvm::StringRef modifiable_format(format_str); + return ParseInternal(modifiable_format, entry, 0); +} diff --git a/contrib/llvm-project/lldb/source/Core/IOHandler.cpp b/contrib/llvm-project/lldb/source/Core/IOHandler.cpp index 49f39f2ce492..695c2481e353 100644 --- a/contrib/llvm-project/lldb/source/Core/IOHandler.cpp +++ b/contrib/llvm-project/lldb/source/Core/IOHandler.cpp @@ -14,9 +14,9 @@ #include <string> #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Host/Config.h" #include "lldb/Host/File.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/Predicate.h" #include "lldb/Utility/Status.h" @@ -226,7 +226,7 @@ IOHandlerEditline::IOHandlerEditline( Debugger &debugger, IOHandler::Type type, const char *editline_name, // Used for saving history files llvm::StringRef prompt, llvm::StringRef continuation_prompt, - bool multi_line, bool color_prompts, uint32_t line_number_start, + bool multi_line, bool color, uint32_t line_number_start, IOHandlerDelegate &delegate) : IOHandlerEditline(debugger, type, FileSP(), // Inherit input from top input reader @@ -234,7 +234,7 @@ IOHandlerEditline::IOHandlerEditline( StreamFileSP(), // Inherit error from top input reader 0, // Flags editline_name, // Used for saving history files - prompt, continuation_prompt, multi_line, color_prompts, + prompt, continuation_prompt, multi_line, color, line_number_start, delegate) {} IOHandlerEditline::IOHandlerEditline( @@ -243,7 +243,7 @@ IOHandlerEditline::IOHandlerEditline( uint32_t flags, const char *editline_name, // Used for saving history files llvm::StringRef prompt, llvm::StringRef continuation_prompt, - bool multi_line, bool color_prompts, uint32_t line_number_start, + bool multi_line, bool color, uint32_t line_number_start, IOHandlerDelegate &delegate) : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags), #if LLDB_ENABLE_LIBEDIT @@ -251,8 +251,8 @@ IOHandlerEditline::IOHandlerEditline( #endif m_delegate(delegate), m_prompt(), m_continuation_prompt(), m_current_lines_ptr(nullptr), m_base_line_number(line_number_start), - m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line), - m_color_prompts(color_prompts), m_interrupt_exits(true) { + m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line), m_color(color), + m_interrupt_exits(true) { SetPrompt(prompt); #if LLDB_ENABLE_LIBEDIT @@ -262,9 +262,9 @@ IOHandlerEditline::IOHandlerEditline( m_input_sp && m_input_sp->GetIsRealTerminal(); if (use_editline) { - m_editline_up = std::make_unique<Editline>( - editline_name, GetInputFILE(), GetOutputFILE(), GetErrorFILE(), - GetOutputMutex(), m_color_prompts); + m_editline_up = std::make_unique<Editline>(editline_name, GetInputFILE(), + GetOutputFILE(), GetErrorFILE(), + GetOutputMutex()); m_editline_up->SetIsInputCompleteCallback( [this](Editline *editline, StringList &lines) { return this->IsInputCompleteCallback(editline, lines); @@ -278,10 +278,12 @@ IOHandlerEditline::IOHandlerEditline( m_editline_up->SetSuggestionCallback([this](llvm::StringRef line) { return this->SuggestionCallback(line); }); - m_editline_up->SetSuggestionAnsiPrefix(ansi::FormatAnsiTerminalCodes( - debugger.GetAutosuggestionAnsiPrefix())); - m_editline_up->SetSuggestionAnsiSuffix(ansi::FormatAnsiTerminalCodes( - debugger.GetAutosuggestionAnsiSuffix())); + if (m_color) { + m_editline_up->SetSuggestionAnsiPrefix(ansi::FormatAnsiTerminalCodes( + debugger.GetAutosuggestionAnsiPrefix())); + m_editline_up->SetSuggestionAnsiSuffix(ansi::FormatAnsiTerminalCodes( + debugger.GetAutosuggestionAnsiSuffix())); + } } // See if the delegate supports fixing indentation const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters(); @@ -474,8 +476,15 @@ bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) { m_prompt = std::string(prompt); #if LLDB_ENABLE_LIBEDIT - if (m_editline_up) + if (m_editline_up) { m_editline_up->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str()); + if (m_color) { + m_editline_up->SetPromptAnsiPrefix( + ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiPrefix())); + m_editline_up->SetPromptAnsiSuffix( + ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiSuffix())); + } + } #endif return true; } @@ -508,6 +517,21 @@ uint32_t IOHandlerEditline::GetCurrentLineIndex() const { return m_curr_line_idx; } +StringList IOHandlerEditline::GetCurrentLines() const { +#if LLDB_ENABLE_LIBEDIT + if (m_editline_up) + return m_editline_up->GetInputAsStringList(); +#endif + // When libedit is not used, the current lines can be gotten from + // `m_current_lines_ptr`, which is updated whenever a new line is processed. + // This doesn't happen when libedit is used, in which case + // `m_current_lines_ptr` is only updated when the full input is terminated. + + if (m_current_lines_ptr) + return *m_current_lines_ptr; + return StringList(); +} + bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) { m_current_lines_ptr = &lines; diff --git a/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp b/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp index 79d3da63059c..620e68a28510 100644 --- a/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -25,7 +25,6 @@ #include <string> #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectUpdater.h" #include "lldb/Host/File.h" #include "lldb/Utility/AnsiTerminal.h" @@ -3179,13 +3178,13 @@ public: m_debugger.GetListener(), llvm::StringRef(), &core_file_spec, false)); if (!process_sp) { - SetError("Unable to find process plug-in for core file!"); + SetError("Unknown core file format!"); return; } Status status = process_sp->LoadCore(); if (status.Fail()) { - SetError("Can't find plug-in for core file!"); + SetError("Unknown core file format!"); return; } } @@ -4615,30 +4614,48 @@ public: typedef std::shared_ptr<TreeDelegate> TreeDelegateSP; -class TreeItem { +struct TreeItemData { + TreeItemData(TreeItem *parent, TreeDelegate &delegate, + bool might_have_children, bool is_expanded) + : m_parent(parent), m_delegate(&delegate), + m_might_have_children(might_have_children), m_is_expanded(is_expanded) { + } + +protected: + TreeItem *m_parent; + TreeDelegate *m_delegate; + void *m_user_data = nullptr; + uint64_t m_identifier = 0; + std::string m_text; + int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for + // the root item + bool m_might_have_children; + bool m_is_expanded = false; +}; + +class TreeItem : public TreeItemData { public: TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children) - : m_parent(parent), m_delegate(delegate), m_children(), - m_might_have_children(might_have_children) { - if (m_parent == nullptr) - m_is_expanded = m_delegate.TreeDelegateExpandRootByDefault(); - } + : TreeItemData(parent, delegate, might_have_children, + parent == nullptr + ? delegate.TreeDelegateExpandRootByDefault() + : false), + m_children() {} + + TreeItem(const TreeItem &) = delete; + TreeItem &operator=(const TreeItem &rhs) = delete; - TreeItem &operator=(const TreeItem &rhs) { + TreeItem &operator=(TreeItem &&rhs) { if (this != &rhs) { - m_parent = rhs.m_parent; - m_delegate = rhs.m_delegate; - m_user_data = rhs.m_user_data; - m_identifier = rhs.m_identifier; - m_row_idx = rhs.m_row_idx; - m_children = rhs.m_children; - m_might_have_children = rhs.m_might_have_children; - m_is_expanded = rhs.m_is_expanded; + TreeItemData::operator=(std::move(rhs)); + AdoptChildren(rhs.m_children); } return *this; } - TreeItem(const TreeItem &) = default; + TreeItem(TreeItem &&rhs) : TreeItemData(std::move(rhs)) { + AdoptChildren(rhs.m_children); + } size_t GetDepth() const { if (m_parent) @@ -4650,18 +4667,28 @@ public: void ClearChildren() { m_children.clear(); } - void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); } + void Resize(size_t n, TreeDelegate &delegate, bool might_have_children) { + if (m_children.size() >= n) { + m_children.erase(m_children.begin() + n, m_children.end()); + return; + } + m_children.reserve(n); + std::generate_n(std::back_inserter(m_children), n - m_children.size(), + [&, parent = this]() { + return TreeItem(parent, delegate, might_have_children); + }); + } TreeItem &operator[](size_t i) { return m_children[i]; } void SetRowIndex(int row_idx) { m_row_idx = row_idx; } size_t GetNumChildren() { - m_delegate.TreeDelegateGenerateChildren(*this); + m_delegate->TreeDelegateGenerateChildren(*this); return m_children.size(); } - void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); } + void ItemWasSelected() { m_delegate->TreeDelegateItemSelected(*this); } void CalculateRowIndexes(int &row_idx) { SetRowIndex(row_idx); @@ -4728,7 +4755,7 @@ public: if (highlight) window.AttributeOn(A_REVERSE); - m_delegate.TreeDelegateDrawTreeItem(*this, window); + m_delegate->TreeDelegateDrawTreeItem(*this, window); if (highlight) window.AttributeOff(A_REVERSE); @@ -4812,16 +4839,13 @@ public: void SetMightHaveChildren(bool b) { m_might_have_children = b; } protected: - TreeItem *m_parent; - TreeDelegate &m_delegate; - void *m_user_data = nullptr; - uint64_t m_identifier = 0; - std::string m_text; - int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for - // the root item + void AdoptChildren(std::vector<TreeItem> &children) { + m_children = std::move(children); + for (auto &child : m_children) + child.m_parent = this; + } + std::vector<TreeItem> m_children; - bool m_might_have_children; - bool m_is_expanded = false; }; class TreeWindowDelegate : public WindowDelegate { @@ -5118,9 +5142,8 @@ public: m_stop_id = process_sp->GetStopID(); m_tid = thread_sp->GetID(); - TreeItem t(&item, *m_frame_delegate_sp, false); size_t num_frames = thread_sp->GetStackFrameCount(); - item.Resize(num_frames, t); + item.Resize(num_frames, *m_frame_delegate_sp, false); for (size_t i = 0; i < num_frames; ++i) { item[i].SetUserData(thread_sp.get()); item[i].SetIdentifier(i); @@ -5220,12 +5243,11 @@ public: std::make_shared<ThreadTreeDelegate>(m_debugger); } - TreeItem t(&item, *m_thread_delegate_sp, false); ThreadList &threads = process_sp->GetThreadList(); std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); ThreadSP selected_thread = threads.GetSelectedThread(); size_t num_threads = threads.GetSize(); - item.Resize(num_threads, t); + item.Resize(num_threads, *m_thread_delegate_sp, false); for (size_t i = 0; i < num_threads; ++i) { ThreadSP thread = threads.GetThreadAtIndex(i); item[i].SetIdentifier(thread->GetID()); @@ -5405,9 +5427,8 @@ public: if (!m_string_delegate_sp) m_string_delegate_sp = std::make_shared<TextTreeDelegate>(); - TreeItem details_tree_item(&item, *m_string_delegate_sp, false); - item.Resize(details.GetSize(), details_tree_item); + item.Resize(details.GetSize(), *m_string_delegate_sp, false); for (size_t i = 0; i < details.GetSize(); i++) { item[i].SetText(details.GetStringAtIndex(i)); } @@ -5449,10 +5470,9 @@ public: if (!m_breakpoint_location_delegate_sp) m_breakpoint_location_delegate_sp = std::make_shared<BreakpointLocationTreeDelegate>(m_debugger); - TreeItem breakpoint_location_tree_item( - &item, *m_breakpoint_location_delegate_sp, true); - item.Resize(breakpoint->GetNumLocations(), breakpoint_location_tree_item); + item.Resize(breakpoint->GetNumLocations(), + *m_breakpoint_location_delegate_sp, true); for (size_t i = 0; i < breakpoint->GetNumLocations(); i++) { item[i].SetIdentifier(i); item[i].SetUserData(breakpoint.get()); @@ -5496,9 +5516,8 @@ public: if (!m_breakpoint_delegate_sp) m_breakpoint_delegate_sp = std::make_shared<BreakpointTreeDelegate>(m_debugger); - TreeItem breakpoint_tree_item(&item, *m_breakpoint_delegate_sp, true); - item.Resize(breakpoints.GetSize(), breakpoint_tree_item); + item.Resize(breakpoints.GetSize(), *m_breakpoint_delegate_sp, true); for (size_t i = 0; i < breakpoints.GetSize(); i++) { item[i].SetIdentifier(i); } @@ -7033,7 +7052,7 @@ public: m_file_sp->DisplaySourceLines(curr_line + 1, column, 0, 0, &lineStream); StringRef line = lineStream.GetString(); - if (line.endswith("\n")) + if (line.ends_with("\n")) line = line.drop_back(); bool wasWritten = window.OutputColoredStringTruncated( 1, line, m_first_visible_column, is_pc_line); diff --git a/contrib/llvm-project/lldb/source/Core/Mangled.cpp b/contrib/llvm-project/lldb/source/Core/Mangled.cpp index d1973a9a8f7f..23ae3913093f 100644 --- a/contrib/llvm-project/lldb/source/Core/Mangled.cpp +++ b/contrib/llvm-project/lldb/source/Core/Mangled.cpp @@ -42,22 +42,40 @@ Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) { if (name.empty()) return Mangled::eManglingSchemeNone; - if (name.startswith("?")) + if (name.starts_with("?")) return Mangled::eManglingSchemeMSVC; - if (name.startswith("_R")) + if (name.starts_with("_R")) return Mangled::eManglingSchemeRustV0; - if (name.startswith("_D")) + if (name.starts_with("_D")) return Mangled::eManglingSchemeD; - if (name.startswith("_Z")) + if (name.starts_with("_Z")) return Mangled::eManglingSchemeItanium; // ___Z is a clang extension of block invocations - if (name.startswith("___Z")) + if (name.starts_with("___Z")) return Mangled::eManglingSchemeItanium; + // Swift's older style of mangling used "_T" as a mangling prefix. This can + // lead to false positives with other symbols that just so happen to start + // with "_T". To minimize the chance of that happening, we only return true + // for select old-style swift mangled names. The known cases are ObjC classes + // and protocols. Classes are either prefixed with "_TtC" or "_TtGC". + // Protocols are prefixed with "_TtP". + if (name.starts_with("_TtC") || name.starts_with("_TtGC") || + name.starts_with("_TtP")) + return Mangled::eManglingSchemeSwift; + + // Swift 4.2 used "$S" and "_$S". + // Swift 5 and onward uses "$s" and "_$s". + // Swift also uses "@__swiftmacro_" as a prefix for mangling filenames. + if (name.starts_with("$S") || name.starts_with("_$S") || + name.starts_with("$s") || name.starts_with("_$s") || + name.starts_with("@__swiftmacro_")) + return Mangled::eManglingSchemeSwift; + return Mangled::eManglingSchemeNone; } @@ -228,6 +246,7 @@ bool Mangled::GetRichManglingInfo(RichManglingContext &context, case eManglingSchemeRustV0: case eManglingSchemeD: + case eManglingSchemeSwift: // Rich demangling scheme is not supported return false; } @@ -265,6 +284,10 @@ ConstString Mangled::GetDemangledName() const { case eManglingSchemeD: demangled_name = GetDLangDemangledStr(m_mangled); break; + case eManglingSchemeSwift: + // Demangling a swift name requires the swift compiler. This is + // explicitly unsupported on llvm.org. + break; case eManglingSchemeNone: llvm_unreachable("eManglingSchemeNone was handled already"); } diff --git a/contrib/llvm-project/lldb/source/Core/Module.cpp b/contrib/llvm-project/lldb/source/Core/Module.cpp index 672d86496bde..c0574b724ace 100644 --- a/contrib/llvm-project/lldb/source/Core/Module.cpp +++ b/contrib/llvm-project/lldb/source/Core/Module.cpp @@ -23,11 +23,11 @@ #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/SymbolLocator.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Symtab.h" #include "lldb/Symbol/Type.h" @@ -233,12 +233,12 @@ Module::Module(const ModuleSpec &module_spec) } Module::Module(const FileSpec &file_spec, const ArchSpec &arch, - const ConstString *object_name, lldb::offset_t object_offset, + 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_object_mod_time(object_mod_time), m_file_has_changed(false), - m_first_file_changed_log(false) { + m_arch(arch), m_file(file_spec), m_object_name(object_name), + 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... { std::lock_guard<std::recursive_mutex> guard( @@ -246,9 +246,6 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch, GetModuleCollection().push_back(this); } - if (object_name) - m_object_name = *object_name; - Log *log(GetLog(LLDBLog::Object | LLDBLog::Modules)); if (log != nullptr) LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')", @@ -952,99 +949,9 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp, } } -void Module::FindTypes_Impl( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - if (SymbolFile *symbols = GetSymbolFile()) - symbols->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); -} - -void Module::FindTypesInNamespace(ConstString type_name, - const CompilerDeclContext &parent_decl_ctx, - size_t max_matches, TypeList &type_list) { - TypeMap types_map; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - FindTypes_Impl(type_name, parent_decl_ctx, max_matches, searched_symbol_files, - types_map); - if (types_map.GetSize()) { - SymbolContext sc; - sc.module_sp = shared_from_this(); - sc.SortTypeList(types_map, type_list); - } -} - -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); - if (type_list.GetSize()) - return type_list.GetTypeAtIndex(0); - return TypeSP(); -} - -void Module::FindTypes( - ConstString name, bool exact_match, size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeList &types) { - const char *type_name_cstr = name.GetCString(); - llvm::StringRef type_scope; - llvm::StringRef type_basename; - TypeClass type_class = eTypeClassAny; - TypeMap typesmap; - - if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename, - type_class)) { - // Check if "name" starts with "::" which means the qualified type starts - // from the root namespace and implies and exact match. The typenames we - // get back from clang do not start with "::" so we need to strip this off - // in order to get the qualified names to match - exact_match = type_scope.consume_front("::"); - - ConstString type_basename_const_str(type_basename); - FindTypes_Impl(type_basename_const_str, CompilerDeclContext(), max_matches, - searched_symbol_files, typesmap); - if (typesmap.GetSize()) - typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, - exact_match); - } else { - // The type is not in a namespace/class scope, just search for it by - // basename - if (type_class != eTypeClassAny && !type_basename.empty()) { - // The "type_name_cstr" will have been modified if we have a valid type - // class prefix (like "struct", "class", "union", "typedef" etc). - FindTypes_Impl(ConstString(type_basename), CompilerDeclContext(), - UINT_MAX, searched_symbol_files, typesmap); - typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, - exact_match); - } else { - FindTypes_Impl(name, CompilerDeclContext(), UINT_MAX, - searched_symbol_files, typesmap); - if (exact_match) { - typesmap.RemoveMismatchedTypes(type_scope, name, type_class, - exact_match); - } - } - } - if (typesmap.GetSize()) { - SymbolContext sc; - sc.module_sp = shared_from_this(); - sc.SortTypeList(typesmap, types); - } -} - -void Module::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - // If a scoped timer is needed, place it in a SymbolFile::FindTypes override. - // A timer here is too high volume for some cases, for example when calling - // FindTypes on each object file. +void Module::FindTypes(const TypeQuery &query, TypeResults &results) { if (SymbolFile *symbols = GetSymbolFile()) - symbols->FindTypes(pattern, languages, searched_symbol_files, types); + symbols->FindTypes(query, results); } static Debugger::DebuggerList @@ -1285,7 +1192,8 @@ ObjectFile *Module::GetObjectFile() { // those values that overwrite unspecified unknown values. m_arch.MergeFrom(m_objfile_sp->GetArchitecture()); } else { - ReportError("failed to load objfile for {0}", + ReportError("failed to load objfile for {0}\nDebugging will be " + "degraded for this module.", GetFileSpec().GetPath().c_str()); } } @@ -1316,7 +1224,7 @@ UnwindTable &Module::GetUnwindTable() { if (!m_unwind_table) { m_unwind_table.emplace(*this); if (!m_symfile_spec) - Symbols::DownloadSymbolFileAsync(GetUUID()); + SymbolLocator::DownloadSymbolFileAsync(GetUUID()); } return *m_unwind_table; } @@ -1446,7 +1354,7 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) { if (FileSystem::Instance().IsDirectory(file)) { std::string new_path(file.GetPath()); std::string old_path(obj_file->GetFileSpec().GetPath()); - if (llvm::StringRef(old_path).startswith(new_path)) { + if (llvm::StringRef(old_path).starts_with(new_path)) { // We specified the same bundle as the symbol file that we already // have return; diff --git a/contrib/llvm-project/lldb/source/Core/ModuleList.cpp b/contrib/llvm-project/lldb/source/Core/ModuleList.cpp index d0d0b2050e18..aa89c93c8d05 100644 --- a/contrib/llvm-project/lldb/source/Core/ModuleList.cpp +++ b/contrib/llvm-project/lldb/source/Core/ModuleList.cpp @@ -9,12 +9,12 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Host/FileSystem.h" #include "lldb/Interpreter/OptionValueFileSpec.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Property.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/TypeList.h" @@ -75,8 +75,7 @@ enum { } // namespace ModuleListProperties::ModuleListProperties() { - m_collection_sp = - std::make_shared<OptionValueProperties>(ConstString("symbols")); + m_collection_sp = std::make_shared<OptionValueProperties>("symbols"); m_collection_sp->Initialize(g_modulelist_properties); m_collection_sp->SetValueChangedCallback(ePropertySymLinkPaths, [this] { UpdateSymlinkMappings(); }); @@ -348,7 +347,7 @@ size_t ModuleList::RemoveOrphans(bool mandatory) { } size_t remove_count = 0; // Modules might hold shared pointers to other modules, so removing one - // module might make other other modules orphans. Keep removing modules until + // module might make other modules orphans. Keep removing modules until // there are no further modules that can be removed. bool made_progress = true; while (made_progress) { @@ -558,36 +557,21 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const { return module_sp; } -void ModuleList::FindTypes(Module *search_first, ConstString name, - bool name_is_fully_qualified, size_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeList &types) const { +void ModuleList::FindTypes(Module *search_first, const TypeQuery &query, + TypeResults &results) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - - collection::const_iterator pos, end = m_modules.end(); if (search_first) { - for (pos = m_modules.begin(); pos != end; ++pos) { - if (search_first == pos->get()) { - search_first->FindTypes(name, name_is_fully_qualified, max_matches, - searched_symbol_files, types); - - if (types.GetSize() >= max_matches) - return; - } - } - } - - for (pos = m_modules.begin(); pos != end; ++pos) { - // Search the module if the module is not equal to the one in the symbol - // context "sc". If "sc" contains a empty module shared pointer, then the - // comparison will always be true (valid_module_ptr != nullptr). - if (search_first != pos->get()) - (*pos)->FindTypes(name, name_is_fully_qualified, max_matches, - searched_symbol_files, types); - - if (types.GetSize() >= max_matches) + search_first->FindTypes(query, results); + if (results.Done(query)) return; } + for (const auto &module_sp : m_modules) { + if (search_first != module_sp.get()) { + module_sp->FindTypes(query, results); + if (results.Done(query)) + return; + } + } } bool ModuleList::FindSourceFile(const FileSpec &orig_spec, @@ -907,7 +891,7 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp, // Fixup the incoming path in case the path points to a valid file, yet the // arch or UUID (if one was passed in) don't match. ModuleSpec located_binary_modulespec = - Symbols::LocateExecutableObjectFile(module_spec); + PluginManager::LocateExecutableObjectFile(module_spec); // Don't look for the file if it appears to be the same one we already // checked for above... @@ -1079,3 +1063,11 @@ bool ModuleList::AnyOf( return false; } + + +void ModuleList::Swap(ModuleList &other) { + // scoped_lock locks both mutexes at once. + std::scoped_lock<std::recursive_mutex, std::recursive_mutex> lock( + m_modules_mutex, other.m_modules_mutex); + m_modules.swap(other.m_modules); +} diff --git a/contrib/llvm-project/lldb/source/Core/PluginManager.cpp b/contrib/llvm-project/lldb/source/Core/PluginManager.cpp index ac274112e53d..b428370d7f33 100644 --- a/contrib/llvm-project/lldb/source/Core/PluginManager.cpp +++ b/contrib/llvm-project/lldb/source/Core/PluginManager.cpp @@ -821,7 +821,7 @@ PluginManager::GetPlatformCreateCallbackForPluginName(llvm::StringRef name) { void PluginManager::AutoCompletePlatformName(llvm::StringRef name, CompletionRequest &request) { for (const auto &instance : GetPlatformInstances().GetInstances()) { - if (instance.name.startswith(name)) + if (instance.name.starts_with(name)) request.AddCompletion(instance.name); } } @@ -869,7 +869,7 @@ PluginManager::GetProcessCreateCallbackForPluginName(llvm::StringRef name) { void PluginManager::AutoCompleteProcessName(llvm::StringRef name, CompletionRequest &request) { for (const auto &instance : GetProcessInstances().GetInstances()) { - if (instance.name.startswith(name)) + if (instance.name.starts_with(name)) request.AddCompletion(instance.name, instance.description); } } @@ -1081,6 +1081,119 @@ PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) { return GetSymbolVendorInstances().GetCallbackAtIndex(idx); } +#pragma mark SymbolLocator + +struct SymbolLocatorInstance + : public PluginInstance<SymbolLocatorCreateInstance> { + SymbolLocatorInstance( + llvm::StringRef name, llvm::StringRef description, + CallbackType create_callback, + SymbolLocatorLocateExecutableObjectFile locate_executable_object_file, + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file, + SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file, + SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle, + DebuggerInitializeCallback debugger_init_callback) + : PluginInstance<SymbolLocatorCreateInstance>( + name, description, create_callback, debugger_init_callback), + locate_executable_object_file(locate_executable_object_file), + locate_executable_symbol_file(locate_executable_symbol_file), + download_object_symbol_file(download_object_symbol_file), + find_symbol_file_in_bundle(find_symbol_file_in_bundle) {} + + SymbolLocatorLocateExecutableObjectFile locate_executable_object_file; + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file; + SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file; + SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle; +}; +typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances; + +static SymbolLocatorInstances &GetSymbolLocatorInstances() { + static SymbolLocatorInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + llvm::StringRef name, llvm::StringRef description, + SymbolLocatorCreateInstance create_callback, + SymbolLocatorLocateExecutableObjectFile locate_executable_object_file, + SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file, + SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file, + SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle, + DebuggerInitializeCallback debugger_init_callback) { + return GetSymbolLocatorInstances().RegisterPlugin( + name, description, create_callback, locate_executable_object_file, + locate_executable_symbol_file, download_object_symbol_file, + find_symbol_file_in_bundle, debugger_init_callback); +} + +bool PluginManager::UnregisterPlugin( + SymbolLocatorCreateInstance create_callback) { + return GetSymbolLocatorInstances().UnregisterPlugin(create_callback); +} + +SymbolLocatorCreateInstance +PluginManager::GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx) { + return GetSymbolLocatorInstances().GetCallbackAtIndex(idx); +} + +ModuleSpec +PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) { + auto &instances = GetSymbolLocatorInstances().GetInstances(); + for (auto &instance : instances) { + if (instance.locate_executable_object_file) { + std::optional<ModuleSpec> result = + instance.locate_executable_object_file(module_spec); + if (result) + return *result; + } + } + return {}; +} + +FileSpec PluginManager::LocateExecutableSymbolFile( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { + auto &instances = GetSymbolLocatorInstances().GetInstances(); + for (auto &instance : instances) { + if (instance.locate_executable_symbol_file) { + std::optional<FileSpec> result = instance.locate_executable_symbol_file( + module_spec, default_search_paths); + if (result) + return *result; + } + } + return {}; +} + +bool PluginManager::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + Status &error, + bool force_lookup, + bool copy_executable) { + auto &instances = GetSymbolLocatorInstances().GetInstances(); + for (auto &instance : instances) { + if (instance.download_object_symbol_file) { + if (instance.download_object_symbol_file(module_spec, error, force_lookup, + copy_executable)) + return true; + } + } + return false; +} + +FileSpec PluginManager::FindSymbolFileInBundle(const FileSpec &symfile_bundle, + const UUID *uuid, + const ArchSpec *arch) { + auto &instances = GetSymbolLocatorInstances().GetInstances(); + for (auto &instance : instances) { + if (instance.find_symbol_file_in_bundle) { + std::optional<FileSpec> result = + instance.find_symbol_file_in_bundle(symfile_bundle, uuid, arch); + if (result) + return *result; + } + } + return {}; +} + #pragma mark Trace struct TraceInstance @@ -1422,6 +1535,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) { GetPlatformInstances().PerformDebuggerCallback(debugger); GetProcessInstances().PerformDebuggerCallback(debugger); GetSymbolFileInstances().PerformDebuggerCallback(debugger); + GetSymbolLocatorInstances().PerformDebuggerCallback(debugger); GetOperatingSystemInstances().PerformDebuggerCallback(debugger); GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger); GetTracePluginInstances().PerformDebuggerCallback(debugger); @@ -1549,6 +1663,7 @@ static constexpr llvm::StringLiteral kProcessPluginName("process"); static constexpr llvm::StringLiteral kTracePluginName("trace"); static constexpr llvm::StringLiteral kObjectFilePluginName("object-file"); static constexpr llvm::StringLiteral kSymbolFilePluginName("symbol-file"); +static constexpr llvm::StringLiteral kSymbolLocatorPluginName("symbol-locator"); static constexpr llvm::StringLiteral kJITLoaderPluginName("jit-loader"); static constexpr llvm::StringLiteral kStructuredDataPluginName("structured-data"); @@ -1597,6 +1712,20 @@ bool PluginManager::CreateSettingForProcessPlugin( description, is_global_property); } +lldb::OptionValuePropertiesSP +PluginManager::GetSettingForSymbolLocatorPlugin(Debugger &debugger, + llvm::StringRef setting_name) { + return GetSettingForPlugin(debugger, setting_name, kSymbolLocatorPluginName); +} + +bool PluginManager::CreateSettingForSymbolLocatorPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + llvm::StringRef description, bool is_global_property) { + return CreateSettingForPlugin(debugger, kSymbolLocatorPluginName, + "Settings for symbol locator plug-ins", + properties_sp, description, is_global_property); +} + bool PluginManager::CreateSettingForTracePlugin( Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property) { diff --git a/contrib/llvm-project/lldb/source/Core/Progress.cpp b/contrib/llvm-project/lldb/source/Core/Progress.cpp index 08be73f1470f..ea3f874916a9 100644 --- a/contrib/llvm-project/lldb/source/Core/Progress.cpp +++ b/contrib/llvm-project/lldb/source/Core/Progress.cpp @@ -30,10 +30,9 @@ Progress::~Progress() { // Make sure to always report progress completed when this object is // destructed so it indicates the progress dialog/activity should go away. std::lock_guard<std::mutex> guard(m_mutex); - if (!m_completed) { + if (!m_completed) m_completed = m_total; - ReportProgress(); - } + ReportProgress(); } void Progress::Increment(uint64_t amount, std::string update) { diff --git a/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp b/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp index 08c9b280b8cc..b68c9e11581b 100644 --- a/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp +++ b/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp @@ -72,7 +72,7 @@ bool RichManglingContext::IsCtorOrDtor() const { // We can only check for destructors here. auto base_name = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename(); - return base_name.startswith("~"); + return base_name.starts_with("~"); } case None: return false; diff --git a/contrib/llvm-project/lldb/source/Core/SearchFilter.cpp b/contrib/llvm-project/lldb/source/Core/SearchFilter.cpp index 4f9519b5cc9a..b3ff73bbf58f 100644 --- a/contrib/llvm-project/lldb/source/Core/SearchFilter.cpp +++ b/contrib/llvm-project/lldb/source/Core/SearchFilter.cpp @@ -471,13 +471,13 @@ SearchFilterSP SearchFilterByModule::CreateFromStructuredData( return nullptr; } - llvm::StringRef module; - success = modules_array->GetItemAtIndexAsString(0, module); - if (!success) { + std::optional<llvm::StringRef> maybe_module = + modules_array->GetItemAtIndexAsString(0); + if (!maybe_module) { error.SetErrorString("SFBM::CFSD: filter module item not a string."); return nullptr; } - FileSpec module_spec(module); + FileSpec module_spec(*maybe_module); return std::make_shared<SearchFilterByModule>(target_sp, module_spec); } @@ -596,14 +596,14 @@ SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData( FileSpecList modules; size_t num_modules = modules_array->GetSize(); for (size_t i = 0; i < num_modules; i++) { - llvm::StringRef module; - success = modules_array->GetItemAtIndexAsString(i, module); - if (!success) { + std::optional<llvm::StringRef> maybe_module = + modules_array->GetItemAtIndexAsString(i); + if (!maybe_module) { error.SetErrorStringWithFormat( "SFBM::CFSD: filter module item %zu not a string.", i); return nullptr; } - modules.EmplaceBack(module); + modules.EmplaceBack(*maybe_module); } return std::make_shared<SearchFilterByModuleList>(target_sp, modules); } @@ -644,14 +644,14 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( if (success) { size_t num_modules = modules_array->GetSize(); for (size_t i = 0; i < num_modules; i++) { - llvm::StringRef module; - success = modules_array->GetItemAtIndexAsString(i, module); - if (!success) { + std::optional<llvm::StringRef> maybe_module = + modules_array->GetItemAtIndexAsString(i); + if (!maybe_module) { error.SetErrorStringWithFormat( "SFBM::CFSD: filter module item %zu not a string.", i); return result_sp; } - modules.EmplaceBack(module); + modules.EmplaceBack(*maybe_module); } } @@ -666,14 +666,14 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( size_t num_cus = cus_array->GetSize(); FileSpecList cus; for (size_t i = 0; i < num_cus; i++) { - llvm::StringRef cu; - success = cus_array->GetItemAtIndexAsString(i, cu); - if (!success) { + std::optional<llvm::StringRef> maybe_cu = + cus_array->GetItemAtIndexAsString(i); + if (!maybe_cu) { error.SetErrorStringWithFormat( "SFBM::CFSD: filter CU item %zu not a string.", i); return nullptr; } - cus.EmplaceBack(cu); + cus.EmplaceBack(*maybe_cu); } return std::make_shared<SearchFilterByModuleListAndCU>( diff --git a/contrib/llvm-project/lldb/source/Core/Section.cpp b/contrib/llvm-project/lldb/source/Core/Section.cpp index 212b3119894f..9e98b59deb03 100644 --- a/contrib/llvm-project/lldb/source/Core/Section.cpp +++ b/contrib/llvm-project/lldb/source/Core/Section.cpp @@ -149,6 +149,8 @@ const char *Section::GetTypeAsCString() const { return "ctf"; case eSectionTypeOther: return "regular"; + case eSectionTypeSwiftModules: + return "swift-modules"; } return "unknown"; } @@ -455,6 +457,7 @@ bool Section::ContainsOnlyDebugInfo() const { case eSectionTypeDWARFAppleObjC: case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: + case eSectionTypeSwiftModules: return true; } return false; diff --git a/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp b/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp index 755a158a5359..7d8aae5d8ff6 100644 --- a/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp +++ b/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp @@ -23,6 +23,7 @@ #include <chrono> #include <cstring> #include <memory> +#include <shared_mutex> #include <cerrno> #include <cinttypes> @@ -155,6 +156,8 @@ size_t ThreadedCommunication::Read(void *dst, size_t dst_len, } bool ThreadedCommunication::StartReadThread(Status *error_ptr) { + std::lock_guard<std::mutex> lock(m_read_thread_mutex); + if (error_ptr) error_ptr->Clear(); @@ -189,6 +192,8 @@ bool ThreadedCommunication::StartReadThread(Status *error_ptr) { } bool ThreadedCommunication::StopReadThread(Status *error_ptr) { + std::lock_guard<std::mutex> lock(m_read_thread_mutex); + if (!m_read_thread.IsJoinable()) return true; @@ -199,13 +204,13 @@ bool ThreadedCommunication::StopReadThread(Status *error_ptr) { BroadcastEvent(eBroadcastBitReadThreadShouldExit, nullptr); - // error = m_read_thread.Cancel(); - Status error = m_read_thread.Join(nullptr); return error.Success(); } bool ThreadedCommunication::JoinReadThread(Status *error_ptr) { + std::lock_guard<std::mutex> lock(m_read_thread_mutex); + if (!m_read_thread.IsJoinable()) return true; diff --git a/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp b/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp index f5dd926cf050..72217117557f 100644 --- a/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp +++ b/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp @@ -30,6 +30,13 @@ class Property; using namespace lldb; using namespace lldb_private; +Properties::Properties() = default; + +Properties::Properties(const lldb::OptionValuePropertiesSP &collection_sp) + : m_collection_sp(collection_sp) {} + +Properties::~Properties() = default; + lldb::OptionValueSP Properties::GetPropertyValue(const ExecutionContext *exe_ctx, llvm::StringRef path, Status &error) const { diff --git a/contrib/llvm-project/lldb/source/Core/Value.cpp b/contrib/llvm-project/lldb/source/Core/Value.cpp index 5a2631ca501f..995cc934c820 100644 --- a/contrib/llvm-project/lldb/source/Core/Value.cpp +++ b/contrib/llvm-project/lldb/source/Core/Value.cpp @@ -98,7 +98,9 @@ void Value::AppendBytes(const void *bytes, int len) { } void Value::Dump(Stream *strm) { - m_value.GetValue(strm, true); + if (!strm) + return; + m_value.GetValue(*strm, true); strm->Printf(", value_type = %s, context = %p, context_type = %s", Value::GetValueTypeAsCString(m_value_type), m_context, Value::GetContextTypeAsCString(m_context_type)); @@ -572,7 +574,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, return error; } -Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { +Scalar &Value::ResolveValue(ExecutionContext *exe_ctx, Module *module) { const CompilerType &compiler_type = GetCompilerType(); if (compiler_type.IsValid()) { switch (m_value_type) { @@ -587,7 +589,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { { DataExtractor data; lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); - Status error(GetValueAsData(exe_ctx, data, nullptr)); + Status error(GetValueAsData(exe_ctx, data, module)); if (error.Success()) { Scalar scalar; if (compiler_type.GetValueAsScalar( diff --git a/contrib/llvm-project/lldb/source/Core/ValueObject.cpp b/contrib/llvm-project/lldb/source/Core/ValueObject.cpp index d60a1d6f7a10..b82e6082eebd 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObject.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObject.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/ValueObjectDynamicValue.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/Core/ValueObjectSyntheticFilter.h" +#include "lldb/Core/ValueObjectVTable.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/DataFormatters/DumpValueObjectOptions.h" #include "lldb/DataFormatters/FormatManager.h" @@ -218,10 +219,8 @@ bool ValueObject::UpdateFormatsIfNeeded() { SetValueFormat(DataVisualization::GetFormat(*this, eNoDynamicValues)); SetSummaryFormat( DataVisualization::GetSummaryFormat(*this, GetDynamicValueType())); -#if LLDB_ENABLE_PYTHON SetSyntheticChildren( DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType())); -#endif } return any_change; @@ -336,7 +335,7 @@ bool ValueObject::ResolveValue(Scalar &scalar) { { ExecutionContext exe_ctx(GetExecutionContextRef()); Value tmp_value(m_value); - scalar = tmp_value.ResolveValue(&exe_ctx); + scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get()); if (scalar.IsValid()) { const uint32_t bitfield_bit_size = GetBitfieldBitSize(); if (bitfield_bit_size) @@ -399,13 +398,16 @@ ValueObject::GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs, if (idxs.size() == 0) return GetSP(); ValueObjectSP root(GetSP()); + + size_t current_index = 0; for (size_t idx : idxs) { root = root->GetChildAtIndex(idx); if (!root) { if (index_of_error) - *index_of_error = idx; + *index_of_error = current_index; return root; } + current_index += 1; } return root; } @@ -415,13 +417,17 @@ lldb::ValueObjectSP ValueObject::GetChildAtIndexPath( if (idxs.size() == 0) return GetSP(); ValueObjectSP root(GetSP()); + + size_t current_index = 0; for (std::pair<size_t, bool> idx : idxs) { root = root->GetChildAtIndex(idx.first, idx.second); if (!root) { if (index_of_error) - *index_of_error = idx.first; + *index_of_error = current_index; return root; } + + current_index += 1; } return root; } @@ -440,23 +446,6 @@ ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) { return root; } -lldb::ValueObjectSP ValueObject::GetChildAtNamePath( - llvm::ArrayRef<std::pair<ConstString, bool>> names, - ConstString *name_of_error) { - if (names.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (std::pair<ConstString, bool> name : names) { - root = root->GetChildMemberWithName(name.first, name.second); - if (!root) { - if (name_of_error) - *name_of_error = name.first; - return root; - } - } - return root; -} - size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) { bool omit_empty_base_classes = true; return GetCompilerType().GetIndexOfChildWithName(name, @@ -1170,7 +1159,7 @@ bool ValueObject::DumpPrintableRepresentation( Stream &s, ValueObjectRepresentationStyle val_obj_display, Format custom_format, PrintableRepresentationSpecialCases special, bool do_dump_error) { - + // If the ValueObject has an error, we might end up dumping the type, which // is useful, but if we don't even have a type, then don't examine the object // further as that's not meaningful, only the error is. @@ -2123,7 +2112,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } - if (!temp_expression.startswith(">")) { + if (!temp_expression.starts_with(">")) { *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; @@ -2148,11 +2137,10 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( temp_expression = temp_expression.drop_front(); // skip . or > size_t next_sep_pos = temp_expression.find_first_of("-.[", 1); - ConstString child_name; if (next_sep_pos == llvm::StringRef::npos) // if no other separator just // expand this last layer { - child_name.SetString(temp_expression); + llvm::StringRef child_name = temp_expression; ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name); @@ -2220,8 +2208,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( } else // other layers do expand { llvm::StringRef next_separator = temp_expression.substr(next_sep_pos); - - child_name.SetString(temp_expression.slice(0, next_sep_pos)); + llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos); ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name); @@ -2614,34 +2601,30 @@ ValueObjectSP ValueObject::CreateConstantValue(ConstString name) { ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable( lldb::DynamicValueType dynValue, bool synthValue) { - ValueObjectSP result_sp(GetSP()); - + ValueObjectSP result_sp; switch (dynValue) { case lldb::eDynamicCanRunTarget: case lldb::eDynamicDontRunTarget: { - if (!result_sp->IsDynamic()) { - if (result_sp->GetDynamicValue(dynValue)) - result_sp = result_sp->GetDynamicValue(dynValue); - } + if (!IsDynamic()) + result_sp = GetDynamicValue(dynValue); } break; case lldb::eNoDynamicValues: { - if (result_sp->IsDynamic()) { - if (result_sp->GetStaticValue()) - result_sp = result_sp->GetStaticValue(); - } + if (IsDynamic()) + result_sp = GetStaticValue(); } break; } + if (!result_sp) + result_sp = GetSP(); + assert(result_sp); - if (synthValue) { - if (!result_sp->IsSynthetic()) { - if (result_sp->GetSyntheticValue()) - result_sp = result_sp->GetSyntheticValue(); - } - } else { - if (result_sp->IsSynthetic()) { - if (result_sp->GetNonSyntheticValue()) - result_sp = result_sp->GetNonSyntheticValue(); - } + bool is_synthetic = result_sp->IsSynthetic(); + if (synthValue && !is_synthetic) { + if (auto synth_sp = result_sp->GetSyntheticValue()) + return synth_sp; + } + if (!synthValue && is_synthetic) { + if (auto non_synth_sp = result_sp->GetNonSyntheticValue()) + return non_synth_sp; } return result_sp; @@ -2785,15 +2768,15 @@ ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) { ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) { // Only allow casts if the original type is equal or larger than the cast - // type. We don't know how to fetch more data for all the ConstResult types, + // type. We don't know how to fetch more data for all the ConstResult types, // so we can't guarantee this will work: Status error; CompilerType my_type = GetCompilerType(); - ExecutionContextScope *exe_scope + ExecutionContextScope *exe_scope = ExecutionContext(GetExecutionContextRef()) .GetBestExecutionContextScope(); - if (compiler_type.GetByteSize(exe_scope) + if (compiler_type.GetByteSize(exe_scope) <= GetCompilerType().GetByteSize(exe_scope)) { return DoCast(compiler_type); } @@ -3176,3 +3159,7 @@ ValueObjectSP ValueObject::Persist() { return persistent_var_sp->GetValueObject(); } + +lldb::ValueObjectSP ValueObject::GetVTable() { + return ValueObjectVTable::Create(*this); +} diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp index ad29d36ae08a..43bc532c4a04 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -41,7 +41,7 @@ public: return m_backend.GetIndexOfChildWithName(name); } - bool MightHaveChildren() override { return true; } + bool MightHaveChildren() override { return m_backend.MightHaveChildren(); } bool Update() override { return false; } }; @@ -163,8 +163,8 @@ bool ValueObjectSynthetic::UpdateValue() { return false; } - // regenerate the synthetic filter if our typename changes - // <rdar://problem/12424824> + // Regenerate the synthetic filter if our typename changes. When the (dynamic) + // type of an object changes, so does their synthetic filter of choice. ConstString new_parent_type_name = m_parent->GetTypeName(); if (new_parent_type_name != m_parent_type_name) { LLDB_LOGF(log, @@ -311,7 +311,7 @@ ValueObjectSynthetic::GetChildMemberWithName(llvm::StringRef name, bool can_create) { UpdateValueIfNeeded(); - uint32_t index = GetIndexOfChildWithName(ConstString(name)); + uint32_t index = GetIndexOfChildWithName(name); if (index == UINT32_MAX) return lldb::ValueObjectSP(); diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectVTable.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectVTable.cpp new file mode 100644 index 000000000000..177ae4167a1d --- /dev/null +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectVTable.cpp @@ -0,0 +1,274 @@ +//===-- ValueObjectVTable.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/ValueObjectVTable.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" + +using namespace lldb; +using namespace lldb_private; + +class ValueObjectVTableChild : public ValueObject { +public: + ValueObjectVTableChild(ValueObject &parent, uint32_t func_idx, + uint64_t addr_size) + : ValueObject(parent), m_func_idx(func_idx), m_addr_size(addr_size) { + SetFormat(eFormatPointer); + SetName(ConstString(llvm::formatv("[{0}]", func_idx).str())); + } + + ~ValueObjectVTableChild() override = default; + + std::optional<uint64_t> GetByteSize() override { return m_addr_size; }; + + size_t CalculateNumChildren(uint32_t max) override { return 0; }; + + ValueType GetValueType() const override { return eValueTypeVTableEntry; }; + + bool IsInScope() override { + if (ValueObject *parent = GetParent()) + return parent->IsInScope(); + return false; + }; + +protected: + bool UpdateValue() override { + SetValueIsValid(false); + m_value.Clear(); + ValueObject *parent = GetParent(); + if (!parent) { + m_error.SetErrorString("owning vtable object not valid"); + return false; + } + + addr_t parent_addr = parent->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + if (parent_addr == LLDB_INVALID_ADDRESS) { + m_error.SetErrorString("invalid vtable address"); + return false; + } + + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) { + m_error.SetErrorString("no process"); + return false; + } + + TargetSP target_sp = GetTargetSP(); + if (!target_sp) { + m_error.SetErrorString("no target"); + return false; + } + + // Each `vtable_entry_addr` points to the function pointer. + addr_t vtable_entry_addr = parent_addr + m_func_idx * m_addr_size; + addr_t vfunc_ptr = + process_sp->ReadPointerFromMemory(vtable_entry_addr, m_error); + if (m_error.Fail()) { + m_error.SetErrorStringWithFormat( + "failed to read virtual function entry 0x%16.16" PRIx64, + vtable_entry_addr); + return false; + } + + + // Set our value to be the load address of the function pointer in memory + // and our type to be the function pointer type. + m_value.SetValueType(Value::ValueType::LoadAddress); + m_value.GetScalar() = vtable_entry_addr; + + // See if our resolved address points to a function in the debug info. If + // it does, then we can report the type as a function prototype for this + // function. + Function *function = nullptr; + Address resolved_vfunc_ptr_address; + target_sp->ResolveLoadAddress(vfunc_ptr, resolved_vfunc_ptr_address); + if (resolved_vfunc_ptr_address.IsValid()) + function = resolved_vfunc_ptr_address.CalculateSymbolContextFunction(); + if (function) { + m_value.SetCompilerType(function->GetCompilerType().GetPointerType()); + } else { + // Set our value's compiler type to a generic function protoype so that + // it displays as a hex function pointer for the value and the summary + // will display the address description. + + // Get the original type that this vtable is based off of so we can get + // the language from it correctly. + ValueObject *val = parent->GetParent(); + auto type_system = target_sp->GetScratchTypeSystemForLanguage( + val ? val->GetObjectRuntimeLanguage() : eLanguageTypeC_plus_plus); + if (type_system) { + m_value.SetCompilerType( + (*type_system)->CreateGenericFunctionPrototype().GetPointerType()); + } else { + consumeError(type_system.takeError()); + } + } + + // Now read our value into m_data so that our we can use the default + // summary provider for C++ for function pointers which will get the + // address description for our function pointer. + if (m_error.Success()) { + const bool thread_and_frame_only_if_stopped = true; + ExecutionContext exe_ctx( + GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); + } + SetValueDidChange(true); + SetValueIsValid(true); + return true; + }; + + CompilerType GetCompilerTypeImpl() override { + return m_value.GetCompilerType(); + }; + + const uint32_t m_func_idx; + const uint64_t m_addr_size; + +private: + // For ValueObject only + ValueObjectVTableChild(const ValueObjectVTableChild &) = delete; + const ValueObjectVTableChild & + operator=(const ValueObjectVTableChild &) = delete; +}; + +ValueObjectSP ValueObjectVTable::Create(ValueObject &parent) { + return (new ValueObjectVTable(parent))->GetSP(); +} + +ValueObjectVTable::ValueObjectVTable(ValueObject &parent) + : ValueObject(parent) { + SetFormat(eFormatPointer); +} + +std::optional<uint64_t> ValueObjectVTable::GetByteSize() { + if (m_vtable_symbol) + return m_vtable_symbol->GetByteSize(); + return std::nullopt; +} + +size_t ValueObjectVTable::CalculateNumChildren(uint32_t max) { + if (UpdateValueIfNeeded(false)) + return m_num_vtable_entries <= max ? m_num_vtable_entries : max; + return 0; +} + +ValueType ValueObjectVTable::GetValueType() const { return eValueTypeVTable; } + +ConstString ValueObjectVTable::GetTypeName() { + if (m_vtable_symbol) + return m_vtable_symbol->GetName(); + return ConstString(); +} + +ConstString ValueObjectVTable::GetQualifiedTypeName() { return GetTypeName(); } + +ConstString ValueObjectVTable::GetDisplayTypeName() { + if (m_vtable_symbol) + return m_vtable_symbol->GetDisplayName(); + return ConstString(); +} + +bool ValueObjectVTable::IsInScope() { return GetParent()->IsInScope(); } + +ValueObject *ValueObjectVTable::CreateChildAtIndex(size_t idx, + bool synthetic_array_member, + int32_t synthetic_index) { + if (synthetic_array_member) + return nullptr; + return new ValueObjectVTableChild(*this, idx, m_addr_size); +} + +bool ValueObjectVTable::UpdateValue() { + m_error.Clear(); + m_flags.m_children_count_valid = false; + SetValueIsValid(false); + m_num_vtable_entries = 0; + ValueObject *parent = GetParent(); + if (!parent) { + m_error.SetErrorString("no parent object"); + return false; + } + + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) { + m_error.SetErrorString("no process"); + return false; + } + + const LanguageType language = parent->GetObjectRuntimeLanguage(); + LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(language); + + if (language_runtime == nullptr) { + m_error.SetErrorStringWithFormat( + "no language runtime support for the language \"%s\"", + Language::GetNameForLanguageType(language)); + return false; + } + + // Get the vtable information from the language runtime. + llvm::Expected<LanguageRuntime::VTableInfo> vtable_info_or_err = + language_runtime->GetVTableInfo(*parent, /*check_type=*/true); + if (!vtable_info_or_err) { + m_error = vtable_info_or_err.takeError(); + return false; + } + + TargetSP target_sp = GetTargetSP(); + const addr_t vtable_start_addr = + vtable_info_or_err->addr.GetLoadAddress(target_sp.get()); + + m_vtable_symbol = vtable_info_or_err->symbol; + if (!m_vtable_symbol) { + m_error.SetErrorStringWithFormat( + "no vtable symbol found containing 0x%" PRIx64, vtable_start_addr); + return false; + } + + // Now that we know it's a vtable, we update the object's state. + SetName(GetTypeName()); + + // Calculate the number of entries + if (!m_vtable_symbol->GetByteSizeIsValid()) { + m_error.SetErrorStringWithFormat( + "vtable symbol \"%s\" doesn't have a valid size", + m_vtable_symbol->GetMangled().GetDemangledName().GetCString()); + return false; + } + + m_addr_size = process_sp->GetAddressByteSize(); + const addr_t vtable_end_addr = + m_vtable_symbol->GetLoadAddress(target_sp.get()) + + m_vtable_symbol->GetByteSize(); + m_num_vtable_entries = (vtable_end_addr - vtable_start_addr) / m_addr_size; + + m_value.SetValueType(Value::ValueType::LoadAddress); + m_value.GetScalar() = parent->GetAddressOf(); + auto type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (type_system_or_err) { + m_value.SetCompilerType( + (*type_system_or_err)->GetBasicTypeFromAST(eBasicTypeUnsignedLong)); + } else { + consumeError(type_system_or_err.takeError()); + } + SetValueDidChange(true); + SetValueIsValid(true); + return true; +} + +CompilerType ValueObjectVTable::GetCompilerTypeImpl() { return CompilerType(); } + +ValueObjectVTable::~ValueObjectVTable() = default; diff --git a/contrib/llvm-project/lldb/source/DataFormatters/CXXFunctionPointer.cpp b/contrib/llvm-project/lldb/source/DataFormatters/CXXFunctionPointer.cpp index d7df280e56ef..6543433d17ff 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/CXXFunctionPointer.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/CXXFunctionPointer.cpp @@ -13,6 +13,7 @@ #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Stream.h" +#include "lldb/lldb-enumerations.h" #include <string> @@ -76,7 +77,10 @@ bool lldb_private::formatters::CXXFunctionPointerSummaryProvider( } } if (sstr.GetSize() > 0) { - stream.Printf("(%s)", sstr.GetData()); + if (valobj.GetValueType() == lldb::eValueTypeVTableEntry) + stream.PutCString(sstr.GetData()); + else + stream.Printf("(%s)", sstr.GetData()); return true; } else return false; diff --git a/contrib/llvm-project/lldb/source/DataFormatters/StringPrinter.cpp b/contrib/llvm-project/lldb/source/DataFormatters/StringPrinter.cpp index 4b57e87b4ccd..ab07c74fd185 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/StringPrinter.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/StringPrinter.cpp @@ -183,7 +183,7 @@ DecodedCharBuffer GetPrintableImpl<StringElementType::UTF8>( &buffer_for_conversion, buffer_end, &codepoint, llvm::strictConversion); assert(result == llvm::conversionOK && "Failed to convert legal utf8 sequence"); - (void)result; + UNUSED_IF_ASSERT_DISABLED(result); // The UTF8 helper always advances by the utf8 encoded length. const unsigned utf8_encoded_len = buffer_for_conversion - buffer; diff --git a/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp b/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp index 55635173cc8c..fd76bab95826 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp @@ -24,7 +24,7 @@ TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst) Enable(default_cs, First); } -void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) { +void TypeCategoryMap::Add(KeyType name, const TypeCategoryImplSP &entry) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); m_map[name] = entry; if (listener) @@ -45,7 +45,7 @@ bool TypeCategoryMap::Delete(KeyType name) { bool TypeCategoryMap::Enable(KeyType category_name, Position pos) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); - ValueSP category; + TypeCategoryImplSP category; if (!Get(category_name, category)) return false; return Enable(category, pos); @@ -53,13 +53,13 @@ bool TypeCategoryMap::Enable(KeyType category_name, Position pos) { bool TypeCategoryMap::Disable(KeyType category_name) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); - ValueSP category; + TypeCategoryImplSP category; if (!Get(category_name, category)) return false; return Disable(category); } -bool TypeCategoryMap::Enable(ValueSP category, Position pos) { +bool TypeCategoryMap::Enable(TypeCategoryImplSP category, Position pos) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); if (category.get()) { Position pos_w = pos; @@ -81,7 +81,7 @@ bool TypeCategoryMap::Enable(ValueSP category, Position pos) { return false; } -bool TypeCategoryMap::Disable(ValueSP category) { +bool TypeCategoryMap::Disable(TypeCategoryImplSP category) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); if (category.get()) { m_active_categories.remove_if(delete_matching_categories(category)); @@ -93,7 +93,7 @@ bool TypeCategoryMap::Disable(ValueSP category) { void TypeCategoryMap::EnableAllCategories() { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); - std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP()); + std::vector<TypeCategoryImplSP> sorted_categories(m_map.size(), TypeCategoryImplSP()); MapType::iterator iter = m_map.begin(), end = m_map.end(); for (; iter != end; ++iter) { if (iter->second->IsEnabled()) @@ -102,7 +102,7 @@ void TypeCategoryMap::EnableAllCategories() { if (pos >= sorted_categories.size()) { auto iter = std::find_if( sorted_categories.begin(), sorted_categories.end(), - [](const ValueSP &sp) -> bool { return sp.get() == nullptr; }); + [](const TypeCategoryImplSP &sp) -> bool { return sp.get() == nullptr; }); pos = std::distance(sorted_categories.begin(), iter); } sorted_categories.at(pos) = iter->second; @@ -130,7 +130,7 @@ void TypeCategoryMap::Clear() { listener->Changed(); } -bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) { +bool TypeCategoryMap::Get(KeyType name, TypeCategoryImplSP &entry) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); MapIterator iter = m_map.find(name); if (iter == m_map.end()) @@ -139,20 +139,6 @@ bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) { return true; } -bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) { - std::lock_guard<std::recursive_mutex> guard(m_map_mutex); - MapIterator iter = m_map.begin(); - MapIterator end = m_map.end(); - while (pos > 0) { - iter++; - pos--; - if (iter == end) - return false; - } - entry = iter->second; - return false; -} - bool TypeCategoryMap::AnyMatches( const FormattersMatchCandidate &candidate_type, TypeCategoryImpl::FormatCategoryItems items, bool only_enabled, diff --git a/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp b/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp index 5ee89fc0d5eb..409c452110bd 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp @@ -81,9 +81,9 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj, WritableDataBufferSP buffer_sp( new DataBufferHeap(max_len + 1, 0)); Address address(valobj->GetPointerValue()); - if (target_sp->ReadCStringFromMemory( - address, (char *)buffer_sp->GetBytes(), max_len, error) && - error.Success()) + target_sp->ReadCStringFromMemory( + address, (char *)buffer_sp->GetBytes(), max_len, error); + if (error.Success()) data.SetData(buffer_sp); } } @@ -161,13 +161,12 @@ bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj, if (!target_sp) return false; const ModuleList &images(target_sp->GetImages()); - TypeList types; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX, - searched_symbol_files, types); - if (types.Empty()) + TypeQuery query(m_enum_type.GetStringRef()); + TypeResults results; + images.FindTypes(nullptr, query, results); + if (results.GetTypeMap().Empty()) return false; - for (lldb::TypeSP type_sp : types.Types()) { + for (lldb::TypeSP type_sp : results.GetTypeMap().Types()) { if (!type_sp) continue; if ((type_sp->GetForwardCompilerType().GetTypeInfo() & diff --git a/contrib/llvm-project/lldb/source/DataFormatters/TypeSynthetic.cpp b/contrib/llvm-project/lldb/source/DataFormatters/TypeSynthetic.cpp index 2cca5d65f470..de042e474903 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/TypeSynthetic.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/TypeSynthetic.cpp @@ -84,6 +84,27 @@ std::string TypeFilterImpl::GetDescription() { return std::string(sstr.GetString()); } +SyntheticChildren::SyntheticChildren(const Flags &flags) : m_flags(flags) {} + +SyntheticChildren::~SyntheticChildren() = default; + +CXXSyntheticChildren::CXXSyntheticChildren( + const SyntheticChildren::Flags &flags, const char *description, + CreateFrontEndCallback callback) + : SyntheticChildren(flags), m_create_callback(std::move(callback)), + m_description(description ? description : "") {} + +CXXSyntheticChildren::~CXXSyntheticChildren() = default; + +bool SyntheticChildren::IsScripted() { return false; } + +std::string SyntheticChildren::GetDescription() { return ""; } + +SyntheticChildrenFrontEnd::AutoPointer +SyntheticChildren::GetFrontEnd(ValueObject &backend) { + return nullptr; +} + std::string CXXSyntheticChildren::GetDescription() { StreamString sstr; sstr.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)", diff --git a/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp b/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp index 4afcfa2e8e49..57dae0b2c71f 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp @@ -169,21 +169,49 @@ static lldb::Format GetItemFormatForFormat(lldb::Format format, } } -static size_t CalculateNumChildren( - CompilerType container_type, CompilerType element_type, - lldb_private::ExecutionContextScope *exe_scope = - nullptr // does not matter here because all we trade in are basic types - ) { - std::optional<uint64_t> container_size = - container_type.GetByteSize(exe_scope); - std::optional<uint64_t> element_size = element_type.GetByteSize(exe_scope); - - if (container_size && element_size && *element_size) { - if (*container_size % *element_size) - return 0; - return *container_size / *element_size; - } - return 0; +/// Calculates the number of elements stored in a container (with +/// element type 'container_elem_type') as if it had elements of type +/// 'element_type'. +/// +/// For example, a container of type +/// `uint8_t __attribute__((vector_size(16)))` has 16 elements. +/// But calling `CalculateNumChildren` with an 'element_type' +/// of `float` (4-bytes) will return `4` because we are interpreting +/// the byte-array as a `float32[]`. +/// +/// \param[in] container_elem_type The type of the elements stored +/// in the container we are calculating the children of. +/// +/// \param[in] num_elements Number of 'container_elem_type's our +/// container stores. +/// +/// \param[in] element_type The type of elements we interpret +/// container_type to contain for the purposes of calculating +/// the number of children. +/// +/// \returns The number of elements stored in a container of +/// type 'element_type'. Returns a std::nullopt if the +/// size of the container is not a multiple of 'element_type' +/// or if an error occurs. +static std::optional<size_t> +CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements, + CompilerType element_type) { + std::optional<uint64_t> container_elem_size = + container_elem_type.GetByteSize(/* exe_scope */ nullptr); + if (!container_elem_size) + return {}; + + auto container_size = *container_elem_size * num_elements; + + std::optional<uint64_t> element_size = + element_type.GetByteSize(/* exe_scope */ nullptr); + if (!element_size || !*element_size) + return {}; + + if (container_size % *element_size) + return {}; + + return container_size / *element_size; } namespace lldb_private { @@ -221,11 +249,14 @@ public: m_parent_format = m_backend.GetFormat(); CompilerType parent_type(m_backend.GetCompilerType()); CompilerType element_type; - parent_type.IsVectorType(&element_type); + uint64_t num_elements; + parent_type.IsVectorType(&element_type, &num_elements); m_child_type = ::GetCompilerTypeForFormat( m_parent_format, element_type, parent_type.GetTypeSystem().GetSharedPointer()); - m_num_children = ::CalculateNumChildren(parent_type, m_child_type); + m_num_children = + ::CalculateNumChildren(element_type, num_elements, m_child_type) + .value_or(0); m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type); return false; } diff --git a/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp b/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp index 93fcf0579be0..fe4928d4f43a 100644 --- a/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp +++ b/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp @@ -45,6 +45,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; // DWARFExpression constructor DWARFExpression::DWARFExpression() : m_data() {} diff --git a/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp b/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp index 5a4ba04bff04..0682746e448e 100644 --- a/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp +++ b/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp @@ -285,7 +285,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, .setRelocationModel(triple.isOSBinFormatMachO() ? llvm::Reloc::PIC_ : llvm::Reloc::Static) .setMCJITMemoryManager(std::make_unique<MemoryManager>(*this)) - .setOptLevel(llvm::CodeGenOpt::Less); + .setOptLevel(llvm::CodeGenOptLevel::Less); llvm::StringRef mArch; llvm::StringRef mCPU; @@ -419,7 +419,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, if (m_failed_lookups.size()) { StreamString ss; - ss.PutCString("Couldn't lookup symbols:\n"); + ss.PutCString("Couldn't look up symbols:\n"); bool emitNewLine = false; @@ -537,7 +537,7 @@ lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName( sect_type = lldb::eSectionTypeCode; else if (name.equals("__data") || name.equals(".data")) sect_type = lldb::eSectionTypeCode; - else if (name.startswith("__debug_") || name.startswith(".debug_")) { + else if (name.starts_with("__debug_") || name.starts_with(".debug_")) { const uint32_t name_idx = name[0] == '_' ? 8 : 7; llvm::StringRef dwarf_name(name.substr(name_idx)); switch (dwarf_name[0]) { @@ -596,7 +596,7 @@ lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName( default: break; } - } else if (name.startswith("__apple_") || name.startswith(".apple_")) + } else if (name.starts_with("__apple_") || name.starts_with(".apple_")) sect_type = lldb::eSectionTypeInvalid; else if (name.equals("__objc_imageinfo")) sect_type = lldb::eSectionTypeOther; diff --git a/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp b/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp index 36a8a74ed9ef..df0292270866 100644 --- a/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Expression/IRInterpreter.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/ValueObject.h" @@ -464,13 +465,16 @@ static const char *unsupported_operand_error = "Interpreter doesn't handle one of the expression's operands"; static const char *interpreter_internal_error = "Interpreter encountered an internal error"; +static const char *interrupt_error = + "Interrupted while interpreting expression"; static const char *bad_value_error = "Interpreter couldn't resolve a value during execution"; static const char *memory_allocation_error = "Interpreter couldn't allocate memory"; static const char *memory_write_error = "Interpreter couldn't write to memory"; static const char *memory_read_error = "Interpreter couldn't read from memory"; -static const char *infinite_loop_error = "Interpreter ran for too many cycles"; +static const char *timeout_error = + "Reached timeout while interpreting expression"; static const char *too_many_functions_error = "Interpreter doesn't handle modules with multiple function bodies."; @@ -683,7 +687,8 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::Status &error, lldb::addr_t stack_frame_bottom, lldb::addr_t stack_frame_top, - lldb_private::ExecutionContext &exe_ctx) { + lldb_private::ExecutionContext &exe_ctx, + lldb_private::Timeout<std::micro> timeout) { lldb_private::Log *log(GetLog(LLDBLog::Expressions)); if (log) { @@ -722,11 +727,36 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, frame.MakeArgument(&*ai, ptr); } - uint32_t num_insts = 0; - frame.Jump(&function.front()); - while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) { + lldb_private::Process *process = exe_ctx.GetProcessPtr(); + lldb_private::Target *target = exe_ctx.GetTargetPtr(); + + using clock = std::chrono::steady_clock; + + // Compute the time at which the timeout has been exceeded. + std::optional<clock::time_point> end_time; + if (timeout && timeout->count() > 0) + end_time = clock::now() + *timeout; + + while (frame.m_ii != frame.m_ie) { + // Timeout reached: stop interpreting. + if (end_time && clock::now() >= *end_time) { + error.SetErrorToGenericError(); + error.SetErrorString(timeout_error); + return false; + } + + // If we have access to the debugger we can honor an interrupt request. + if (target) { + if (INTERRUPT_REQUESTED(target->GetDebugger(), + "Interrupted in IR interpreting.")) { + error.SetErrorToGenericError(); + error.SetErrorString(interrupt_error); + return false; + } + } + const Instruction *inst = &*frame.m_ii; LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str()); @@ -1418,7 +1448,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, } // Make sure we have a valid process - if (!exe_ctx.GetProcessPtr()) { + if (!process) { error.SetErrorToGenericError(); error.SetErrorString("unable to get the process"); return false; @@ -1479,7 +1509,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, size_t dataSize = 0; bool Success = execution_unit.GetAllocSize(addr, dataSize); - (void)Success; + UNUSED_IF_ASSERT_DISABLED(Success); assert(Success && "unable to locate host data for transfer to device"); // Create the required buffer @@ -1524,11 +1554,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, return false; } - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + process->SetRunningUserExpression(true); // Execute the actual function call thread plan - lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan( - exe_ctx, call_plan_sp, options, diagnostics); + lldb::ExpressionResults res = + process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); // Check that the thread plan completed successfully if (res != lldb::ExpressionResults::eExpressionCompleted) { @@ -1537,7 +1567,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, return false; } - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + process->SetRunningUserExpression(false); // Void return type if (returnType->isVoidTy()) { @@ -1571,11 +1601,5 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, ++frame.m_ii; } - if (num_insts >= 4096) { - error.SetErrorToGenericError(); - error.SetErrorString(infinite_loop_error); - return false; - } - return false; } diff --git a/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp b/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp index 9d01bfcb7220..9c31cc84bf8f 100644 --- a/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp @@ -9,7 +9,6 @@ #include "lldb/Expression/LLVMUserExpression.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" @@ -120,7 +119,7 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp, interpreter_error, function_stack_bottom, - function_stack_top, exe_ctx); + function_stack_top, exe_ctx, options.GetTimeout()); if (!interpreter_error.Success()) { diagnostic_manager.Printf(eDiagnosticSeverityError, @@ -233,7 +232,7 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, eDiagnosticSeverityError, "Couldn't complete execution; the thread " "on which the expression was being run: 0x%" PRIx64 - " exited during its execution.", + " exited during its execution.", expr_thread_id); return execution_result; } else if (execution_result != lldb::eExpressionCompleted) { diff --git a/contrib/llvm-project/lldb/source/Expression/ObjectFileJIT.cpp b/contrib/llvm-project/lldb/source/Expression/ObjectFileJIT.cpp index 10fac9a9a445..9a839866096b 100644 --- a/contrib/llvm-project/lldb/source/Expression/ObjectFileJIT.cpp +++ b/contrib/llvm-project/lldb/source/Expression/ObjectFileJIT.cpp @@ -25,10 +25,6 @@ #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" -#ifndef __APPLE__ -#include "Utility/UuidCompatibility.h" -#endif - using namespace lldb; using namespace lldb_private; diff --git a/contrib/llvm-project/lldb/source/Expression/REPL.cpp b/contrib/llvm-project/lldb/source/Expression/REPL.cpp index 052714f0a670..a6a4ffb5e0af 100644 --- a/contrib/llvm-project/lldb/source/Expression/REPL.cpp +++ b/contrib/llvm-project/lldb/source/Expression/REPL.cpp @@ -9,10 +9,10 @@ #include "lldb/Expression/REPL.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Thread.h" @@ -497,7 +497,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { void REPL::IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request) { // Complete an LLDB command if the first character is a colon... - if (request.GetRawLine().startswith(":")) { + if (request.GetRawLine().starts_with(":")) { Debugger &debugger = m_target.GetDebugger(); // auto complete LLDB commands @@ -528,17 +528,15 @@ void REPL::IOHandlerComplete(IOHandler &io_handler, current_code.append(m_code.CopyList()); IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler); - const StringList *current_lines = editline.GetCurrentLines(); - if (current_lines) { - const uint32_t current_line_idx = editline.GetCurrentLineIndex(); - - if (current_line_idx < current_lines->GetSize()) { - for (uint32_t i = 0; i < current_line_idx; ++i) { - const char *line_cstr = current_lines->GetStringAtIndex(i); - if (line_cstr) { - current_code.append("\n"); - current_code.append(line_cstr); - } + StringList current_lines = editline.GetCurrentLines(); + const uint32_t current_line_idx = editline.GetCurrentLineIndex(); + + if (current_line_idx < current_lines.GetSize()) { + for (uint32_t i = 0; i < current_line_idx; ++i) { + const char *line_cstr = current_lines.GetStringAtIndex(i); + if (line_cstr) { + current_code.append("\n"); + current_code.append(line_cstr); } } } diff --git a/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp b/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp index 8e1cac7099dc..c181712a2f0b 100644 --- a/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp @@ -14,7 +14,6 @@ #include <string> #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" @@ -36,7 +35,6 @@ #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallUserExpression.h" -#include "lldb/Utility/ConstString.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" @@ -100,13 +98,12 @@ bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) { } lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject( - lldb::StackFrameSP frame_sp, ConstString const &object_name, Status &err) { + lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) { err.Clear(); if (!frame_sp) { - err.SetErrorStringWithFormat( - "Couldn't load '%s' because the context is incomplete", - object_name.AsCString()); + err.SetErrorStringWithFormatv( + "Couldn't load '{0}' because the context is incomplete", object_name); return {}; } @@ -114,7 +111,7 @@ lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject( lldb::ValueObjectSP valobj_sp; return frame_sp->GetValueForVariableExpressionPath( - object_name.GetStringRef(), lldb::eNoDynamicValues, + object_name, lldb::eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsNoFragileObjcIvar | StackFrame::eExpressionPathOptionsNoSyntheticChildren | @@ -123,7 +120,7 @@ lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject( } lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, - ConstString &object_name, + llvm::StringRef object_name, Status &err) { auto valobj_sp = GetObjectPointerValueObject(std::move(frame_sp), object_name, err); @@ -134,9 +131,9 @@ lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (ret == LLDB_INVALID_ADDRESS) { - err.SetErrorStringWithFormat( - "Couldn't load '%s' because its value couldn't be evaluated", - object_name.AsCString()); + err.SetErrorStringWithFormatv( + "Couldn't load '{0}' because its value couldn't be evaluated", + object_name); return LLDB_INVALID_ADDRESS; } @@ -256,7 +253,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, target->GetUserExpressionForLanguage(expr, full_prefix, language, desired_type, options, ctx_obj, error)); - if (error.Fail()) { + if (error.Fail() || !user_expression_sp) { LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==", error.AsCString()); return lldb::eExpressionSetupError; diff --git a/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp b/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp index d317c1cd6c15..d7a3c9d41d04 100644 --- a/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp +++ b/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp @@ -10,7 +10,6 @@ #include <sys/types.h> #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" diff --git a/contrib/llvm-project/lldb/source/Host/common/Editline.cpp b/contrib/llvm-project/lldb/source/Host/common/Editline.cpp index 544804db3879..ce707e530d00 100644 --- a/contrib/llvm-project/lldb/source/Host/common/Editline.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/Editline.cpp @@ -25,6 +25,7 @@ #include "lldb/Utility/Timeout.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Locale.h" #include "llvm/Support/Threading.h" using namespace lldb_private; @@ -52,10 +53,6 @@ int setupterm(char *term, int fildes, int *errret); /// https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf #define ESCAPE "\x1b" -/// Faint, decreased intensity or second colour. -#define ANSI_FAINT ESCAPE "[2m" -/// Normal colour or normal intensity (neither bold nor faint). -#define ANSI_UNFAINT ESCAPE "[0m" #define ANSI_CLEAR_BELOW ESCAPE "[J" #define ANSI_CLEAR_RIGHT ESCAPE "[K" #define ANSI_SET_COLUMN_N ESCAPE "[%dG" @@ -101,6 +98,10 @@ bool IsOnlySpaces(const EditLineStringType &content) { return true; } +static size_t ColumnWidth(llvm::StringRef str) { + return llvm::sys::locale::columnWidth(str); +} + static int GetOperation(HistoryOperation op) { // The naming used by editline for the history operations is counter // intuitive to how it's used in LLDB's editline implementation. @@ -328,14 +329,16 @@ std::string Editline::PromptForIndex(int line_index) { std::string continuation_prompt = prompt; if (m_set_continuation_prompt.length() > 0) { continuation_prompt = m_set_continuation_prompt; - // Ensure that both prompts are the same length through space padding - while (continuation_prompt.length() < prompt.length()) { - continuation_prompt += ' '; - } - while (prompt.length() < continuation_prompt.length()) { - prompt += ' '; - } + const size_t prompt_width = ColumnWidth(prompt); + const size_t cont_prompt_width = ColumnWidth(continuation_prompt); + const size_t padded_prompt_width = + std::max(prompt_width, cont_prompt_width); + if (prompt_width < padded_prompt_width) + prompt += std::string(padded_prompt_width - prompt_width, ' '); + else if (cont_prompt_width < padded_prompt_width) + continuation_prompt += + std::string(padded_prompt_width - cont_prompt_width, ' '); } if (use_line_numbers) { @@ -353,7 +356,7 @@ void Editline::SetCurrentLine(int line_index) { m_current_prompt = PromptForIndex(line_index); } -int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); } +size_t Editline::GetPromptWidth() { return ColumnWidth(PromptForIndex(0)); } bool Editline::IsEmacs() { const char *editor; @@ -424,15 +427,13 @@ void Editline::MoveCursor(CursorLocation from, CursorLocation to) { void Editline::DisplayInput(int firstIndex) { fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1); int line_count = (int)m_input_lines.size(); - const char *faint = m_color_prompts ? ANSI_FAINT : ""; - const char *unfaint = m_color_prompts ? ANSI_UNFAINT : ""; - for (int index = firstIndex; index < line_count; index++) { - fprintf(m_output_file, "%s" - "%s" - "%s" EditLineStringFormatSpec " ", - faint, PromptForIndex(index).c_str(), unfaint, - m_input_lines[index].c_str()); + fprintf(m_output_file, + "%s" + "%s" + "%s" EditLineStringFormatSpec " ", + m_prompt_ansi_prefix.c_str(), PromptForIndex(index).c_str(), + m_prompt_ansi_suffix.c_str(), m_input_lines[index].c_str()); if (index < line_count - 1) fprintf(m_output_file, "\n"); } @@ -441,7 +442,7 @@ void Editline::DisplayInput(int firstIndex) { int Editline::CountRowsForLine(const EditLineStringType &content) { std::string prompt = PromptForIndex(0); // Prompt width is constant during an edit session - int line_length = (int)(content.length() + prompt.length()); + int line_length = (int)(content.length() + ColumnWidth(prompt)); return (line_length / m_terminal_width) + 1; } @@ -541,14 +542,16 @@ unsigned char Editline::RecallHistory(HistoryOperation op) { int Editline::GetCharacter(EditLineGetCharType *c) { const LineInfoW *info = el_wline(m_editline); - // Paint a faint version of the desired prompt over the version libedit draws - // (will only be requested if colors are supported) + // Paint a ANSI formatted version of the desired prompt over the version + // libedit draws. (will only be requested if colors are supported) if (m_needs_prompt_repaint) { MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt); - fprintf(m_output_file, "%s" - "%s" - "%s", - ANSI_FAINT, Prompt(), ANSI_UNFAINT); + fprintf(m_output_file, + "%s" + "%s" + "%s", + m_prompt_ansi_prefix.c_str(), Prompt(), + m_prompt_ansi_suffix.c_str()); MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor); m_needs_prompt_repaint = false; } @@ -619,7 +622,7 @@ int Editline::GetCharacter(EditLineGetCharType *c) { } const char *Editline::Prompt() { - if (m_color_prompts) + if (!m_prompt_ansi_prefix.empty() || !m_prompt_ansi_suffix.empty()) m_needs_prompt_repaint = true; return m_current_prompt.c_str(); } @@ -940,12 +943,12 @@ PrintCompletion(FILE *output_file, } } -static void -DisplayCompletions(::EditLine *editline, FILE *output_file, - llvm::ArrayRef<CompletionResult::Completion> results) { +void Editline::DisplayCompletions( + Editline &editline, llvm::ArrayRef<CompletionResult::Completion> results) { assert(!results.empty()); - fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n"); + fprintf(editline.m_output_file, + "\n" ANSI_CLEAR_BELOW "Available completions:\n"); const size_t page_size = 40; bool all = false; @@ -957,7 +960,7 @@ DisplayCompletions(::EditLine *editline, FILE *output_file, const size_t max_len = longest->GetCompletion().size(); if (results.size() < page_size) { - PrintCompletion(output_file, results, max_len); + PrintCompletion(editline.m_output_file, results, max_len); return; } @@ -966,17 +969,31 @@ DisplayCompletions(::EditLine *editline, FILE *output_file, size_t remaining = results.size() - cur_pos; size_t next_size = all ? remaining : std::min(page_size, remaining); - PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len); + PrintCompletion(editline.m_output_file, results.slice(cur_pos, next_size), + max_len); cur_pos += next_size; if (cur_pos >= results.size()) break; - fprintf(output_file, "More (Y/n/a): "); - char reply = 'n'; - int got_char = el_getc(editline, &reply); - fprintf(output_file, "\n"); + fprintf(editline.m_output_file, "More (Y/n/a): "); + // The type for the output and the type for the parameter are different, + // to allow interoperability with older versions of libedit. The container + // for the reply must be as wide as what our implementation is using, + // but libedit may use a narrower type depending on the build + // configuration. + EditLineGetCharType reply = L'n'; + int got_char = el_wgetc(editline.m_editline, + reinterpret_cast<EditLineCharType *>(&reply)); + // Check for a ^C or other interruption. + if (editline.m_editor_status == EditorStatus::Interrupted) { + editline.m_editor_status = EditorStatus::Editing; + fprintf(editline.m_output_file, "^C\n"); + break; + } + + fprintf(editline.m_output_file, "\n"); if (got_char == -1 || reply == 'n') break; if (reply == 'a') @@ -1047,7 +1064,7 @@ unsigned char Editline::TabCommand(int ch) { return CC_REDISPLAY; } - DisplayCompletions(m_editline, m_output_file, results); + DisplayCompletions(*this, results); DisplayInput(); MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor); @@ -1081,13 +1098,9 @@ unsigned char Editline::TypedCharacter(int ch) { llvm::StringRef line(line_info->buffer, line_info->lastchar - line_info->buffer); - const char *ansi_prefix = - m_color_prompts ? m_suggestion_ansi_prefix.c_str() : ""; - const char *ansi_suffix = - m_color_prompts ? m_suggestion_ansi_suffix.c_str() : ""; - if (std::optional<std::string> to_add = m_suggestion_callback(line)) { - std::string to_add_color = ansi_prefix + to_add.value() + ansi_suffix; + std::string to_add_color = + m_suggestion_ansi_prefix + to_add.value() + m_suggestion_ansi_suffix; fputs(typed.c_str(), m_output_file); fputs(to_add_color.c_str(), m_output_file); size_t new_autosuggestion_size = line.size() + to_add->length(); @@ -1378,10 +1391,10 @@ Editline *Editline::InstanceFor(EditLine *editline) { Editline::Editline(const char *editline_name, FILE *input_file, FILE *output_file, FILE *error_file, - std::recursive_mutex &output_mutex, bool color_prompts) - : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), - m_input_file(input_file), m_output_file(output_file), - m_error_file(error_file), m_input_connection(fileno(input_file), false), + std::recursive_mutex &output_mutex) + : m_editor_status(EditorStatus::Complete), m_input_file(input_file), + m_output_file(output_file), m_error_file(error_file), + m_input_connection(fileno(input_file), false), m_output_mutex(output_mutex) { // Get a shared history instance m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; diff --git a/contrib/llvm-project/lldb/source/Host/common/File.cpp b/contrib/llvm-project/lldb/source/Host/common/File.cpp index 7c5d71d9426e..174feecf2de0 100644 --- a/contrib/llvm-project/lldb/source/Host/common/File.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/File.cpp @@ -219,7 +219,7 @@ size_t File::Printf(const char *format, ...) { size_t File::PrintfVarArg(const char *format, va_list args) { llvm::SmallString<0> s; if (VASprintf(s, format, args)) { - size_t written = s.size();; + size_t written = s.size(); Write(s.data(), written); return written; } @@ -247,15 +247,21 @@ uint32_t File::GetPermissions(Status &error) const { return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); } +bool NativeFile::IsValid() const { + std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex); + return DescriptorIsValidUnlocked() || StreamIsValidUnlocked(); +} + Expected<File::OpenOptions> NativeFile::GetOptions() const { return m_options; } int NativeFile::GetDescriptor() const { - if (DescriptorIsValid()) + if (ValueGuard descriptor_guard = DescriptorIsValid()) { return m_descriptor; + } // Don't open the file descriptor if we don't need to, just get it from the // stream if we have one. - if (StreamIsValid()) { + if (ValueGuard stream_guard = StreamIsValid()) { #if defined(_WIN32) return _fileno(m_stream); #else @@ -272,8 +278,9 @@ IOObject::WaitableHandle NativeFile::GetWaitableHandle() { } FILE *NativeFile::GetStream() { - if (!StreamIsValid()) { - if (DescriptorIsValid()) { + ValueGuard stream_guard = StreamIsValid(); + if (!stream_guard) { + if (ValueGuard descriptor_guard = DescriptorIsValid()) { auto mode = GetStreamOpenModeFromOptions(m_options); if (!mode) llvm::consumeError(mode.takeError()); @@ -282,9 +289,9 @@ FILE *NativeFile::GetStream() { // We must duplicate the file descriptor if we don't own it because when you // call fdopen, the stream will own the fd #ifdef _WIN32 - m_descriptor = ::_dup(GetDescriptor()); + m_descriptor = ::_dup(m_descriptor); #else - m_descriptor = dup(GetDescriptor()); + m_descriptor = dup(m_descriptor); #endif m_own_descriptor = true; } @@ -306,8 +313,11 @@ FILE *NativeFile::GetStream() { } Status NativeFile::Close() { + std::scoped_lock<std::mutex, std::mutex> lock(m_descriptor_mutex, m_stream_mutex); + Status error; - if (StreamIsValid()) { + + if (StreamIsValidUnlocked()) { if (m_own_stream) { if (::fclose(m_stream) == EOF) error.SetErrorToErrno(); @@ -322,15 +332,17 @@ Status NativeFile::Close() { } } } - if (DescriptorIsValid() && m_own_descriptor) { + + if (DescriptorIsValidUnlocked() && m_own_descriptor) { if (::close(m_descriptor) != 0) error.SetErrorToErrno(); } - m_descriptor = kInvalidDescriptor; + m_stream = kInvalidStream; - m_options = OpenOptions(0); m_own_stream = false; + m_descriptor = kInvalidDescriptor; m_own_descriptor = false; + m_options = OpenOptions(0); m_is_interactive = eLazyBoolCalculate; m_is_real_terminal = eLazyBoolCalculate; return error; @@ -374,7 +386,7 @@ Status NativeFile::GetFileSpec(FileSpec &file_spec) const { off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) { off_t result = 0; - if (DescriptorIsValid()) { + if (ValueGuard descriptor_guard = DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_SET); if (error_ptr) { @@ -383,7 +395,10 @@ off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) { else error_ptr->Clear(); } - } else if (StreamIsValid()) { + return result; + } + + if (ValueGuard stream_guard = StreamIsValid()) { result = ::fseek(m_stream, offset, SEEK_SET); if (error_ptr) { @@ -392,15 +407,17 @@ off_t NativeFile::SeekFromStart(off_t offset, Status *error_ptr) { else error_ptr->Clear(); } - } else if (error_ptr) { - error_ptr->SetErrorString("invalid file handle"); + return result; } + + if (error_ptr) + error_ptr->SetErrorString("invalid file handle"); return result; } off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) { off_t result = -1; - if (DescriptorIsValid()) { + if (ValueGuard descriptor_guard = DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_CUR); if (error_ptr) { @@ -409,7 +426,10 @@ off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) { else error_ptr->Clear(); } - } else if (StreamIsValid()) { + return result; + } + + if (ValueGuard stream_guard = StreamIsValid()) { result = ::fseek(m_stream, offset, SEEK_CUR); if (error_ptr) { @@ -418,15 +438,17 @@ off_t NativeFile::SeekFromCurrent(off_t offset, Status *error_ptr) { else error_ptr->Clear(); } - } else if (error_ptr) { - error_ptr->SetErrorString("invalid file handle"); + return result; } + + if (error_ptr) + error_ptr->SetErrorString("invalid file handle"); return result; } off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) { off_t result = -1; - if (DescriptorIsValid()) { + if (ValueGuard descriptor_guard = DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_END); if (error_ptr) { @@ -435,7 +457,10 @@ off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) { else error_ptr->Clear(); } - } else if (StreamIsValid()) { + return result; + } + + if (ValueGuard stream_guard = StreamIsValid()) { result = ::fseek(m_stream, offset, SEEK_END); if (error_ptr) { @@ -444,26 +469,32 @@ off_t NativeFile::SeekFromEnd(off_t offset, Status *error_ptr) { else error_ptr->Clear(); } - } else if (error_ptr) { - error_ptr->SetErrorString("invalid file handle"); } + + if (error_ptr) + error_ptr->SetErrorString("invalid file handle"); return result; } Status NativeFile::Flush() { Status error; - if (StreamIsValid()) { + if (ValueGuard stream_guard = StreamIsValid()) { if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) error.SetErrorToErrno(); - } else if (!DescriptorIsValid()) { - error.SetErrorString("invalid file handle"); + return error; + } + + { + ValueGuard descriptor_guard = DescriptorIsValid(); + if (!descriptor_guard) + error.SetErrorString("invalid file handle"); } return error; } Status NativeFile::Sync() { Status error; - if (DescriptorIsValid()) { + if (ValueGuard descriptor_guard = DescriptorIsValid()) { #ifdef _WIN32 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); if (err == 0) @@ -518,14 +549,18 @@ Status NativeFile::Read(void *buf, size_t &num_bytes) { #endif ssize_t bytes_read = -1; - if (DescriptorIsValid()) { - bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes); + if (ValueGuard descriptor_guard = DescriptorIsValid()) { + bytes_read = + llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes); if (bytes_read == -1) { error.SetErrorToErrno(); num_bytes = 0; } else num_bytes = bytes_read; - } else if (StreamIsValid()) { + return error; + } + + if (ValueGuard file_lock = StreamIsValid()) { bytes_read = ::fread(buf, 1, num_bytes, m_stream); if (bytes_read == 0) { @@ -536,10 +571,11 @@ Status NativeFile::Read(void *buf, size_t &num_bytes) { num_bytes = 0; } else num_bytes = bytes_read; - } else { - num_bytes = 0; - error.SetErrorString("invalid file handle"); + return error; } + + num_bytes = 0; + error.SetErrorString("invalid file handle"); return error; } @@ -577,7 +613,7 @@ Status NativeFile::Write(const void *buf, size_t &num_bytes) { #endif ssize_t bytes_written = -1; - if (DescriptorIsValid()) { + if (ValueGuard descriptor_guard = DescriptorIsValid()) { bytes_written = llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes); if (bytes_written == -1) { @@ -585,7 +621,10 @@ Status NativeFile::Write(const void *buf, size_t &num_bytes) { num_bytes = 0; } else num_bytes = bytes_written; - } else if (StreamIsValid()) { + return error; + } + + if (ValueGuard stream_guard = StreamIsValid()) { bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); if (bytes_written == 0) { @@ -596,12 +635,11 @@ Status NativeFile::Write(const void *buf, size_t &num_bytes) { num_bytes = 0; } else num_bytes = bytes_written; - - } else { - num_bytes = 0; - error.SetErrorString("invalid file handle"); + return error; } + num_bytes = 0; + error.SetErrorString("invalid file handle"); return error; } diff --git a/contrib/llvm-project/lldb/source/Host/common/Host.cpp b/contrib/llvm-project/lldb/source/Host/common/Host.cpp index 49eac0b0fa7b..f4cec97f5af6 100644 --- a/contrib/llvm-project/lldb/source/Host/common/Host.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/Host.cpp @@ -133,11 +133,7 @@ private: #endif // __linux__ #ifdef __linux__ -#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) -static __thread volatile sig_atomic_t g_usr1_called; -#else static thread_local volatile sig_atomic_t g_usr1_called; -#endif static void SigUsr1Handler(int) { g_usr1_called = 1; } #endif // __linux__ @@ -558,7 +554,7 @@ bool Host::IsInteractiveGraphicSession() { return false; } std::unique_ptr<Connection> Host::CreateDefaultConnection(llvm::StringRef url) { #if defined(_WIN32) - if (url.startswith("file://")) + if (url.starts_with("file://")) return std::unique_ptr<Connection>(new ConnectionGenericFile()); #endif return std::unique_ptr<Connection>(new ConnectionFileDescriptor()); diff --git a/contrib/llvm-project/lldb/source/Host/common/PseudoTerminal.cpp b/contrib/llvm-project/lldb/source/Host/common/PseudoTerminal.cpp index de49058beeb7..d53327973eb2 100644 --- a/contrib/llvm-project/lldb/source/Host/common/PseudoTerminal.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/PseudoTerminal.cpp @@ -123,7 +123,7 @@ std::string PseudoTerminal::GetSecondaryName() const { char buf[PATH_MAX]; buf[0] = '\0'; int r = ptsname_r(m_primary_fd, buf, sizeof(buf)); - (void)r; + UNUSED_IF_ASSERT_DISABLED(r); assert(r == 0); return buf; #if defined(__APPLE__) diff --git a/contrib/llvm-project/lldb/source/Host/common/Socket.cpp b/contrib/llvm-project/lldb/source/Host/common/Socket.cpp index 8ccb27fdd7f4..bd0c127a0895 100644 --- a/contrib/llvm-project/lldb/source/Host/common/Socket.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/Socket.cpp @@ -269,11 +269,6 @@ Status Socket::Write(const void *buf, size_t &num_bytes) { return error; } -Status Socket::PreDisconnect() { - Status error; - return error; -} - Status Socket::Close() { Status error; if (!IsValid() || !m_should_close_fd) diff --git a/contrib/llvm-project/lldb/source/Host/common/SocketAddress.cpp b/contrib/llvm-project/lldb/source/Host/common/SocketAddress.cpp index 3f47d32d4652..6a23c633e54b 100644 --- a/contrib/llvm-project/lldb/source/Host/common/SocketAddress.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/SocketAddress.cpp @@ -113,7 +113,8 @@ static socklen_t GetFamilyLength(sa_family_t family) { } socklen_t SocketAddress::GetLength() const { -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) return m_socket_addr.sa.sa_len; #else return GetFamilyLength(GetFamily()); @@ -128,7 +129,8 @@ sa_family_t SocketAddress::GetFamily() const { void SocketAddress::SetFamily(sa_family_t family) { m_socket_addr.sa.sa_family = family; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) m_socket_addr.sa.sa_len = GetFamilyLength(family); #endif } diff --git a/contrib/llvm-project/lldb/source/Core/StreamFile.cpp b/contrib/llvm-project/lldb/source/Host/common/StreamFile.cpp index 8aac0b6d6306..099980a0993c 100644 --- a/contrib/llvm-project/lldb/source/Core/StreamFile.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/StreamFile.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/StreamFile.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Host/FileSystem.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" diff --git a/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp index 0de4f2530bba..6a4aacc88f1e 100644 --- a/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp @@ -45,7 +45,6 @@ llvm::VersionTuple HostInfoNetBSD::GetOSVersion() { std::optional<std::string> HostInfoNetBSD::GetOSBuildString() { int mib[2] = {CTL_KERN, KERN_OSREV}; - char osrev_str[12]; int osrev = 0; size_t osrev_len = sizeof(osrev); diff --git a/contrib/llvm-project/lldb/source/Host/netbsd/HostNetBSD.cpp b/contrib/llvm-project/lldb/source/Host/netbsd/HostNetBSD.cpp index c47b96a5ceda..de8b2fd7cb0c 100644 --- a/contrib/llvm-project/lldb/source/Host/netbsd/HostNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Host/netbsd/HostNetBSD.cpp @@ -108,10 +108,11 @@ static bool GetNetBSDProcessCPUType(ProcessInstanceInfo &process_info) { auto buffer_sp = FileSystem::Instance().CreateDataBuffer( process_info.GetExecutableFile(), 0x20, 0); if (buffer_sp) { - uint8_t exe_class = llvm::object::getElfArchType( - {reinterpret_cast<char *>(buffer_sp->GetBytes()), - size_t(buffer_sp->GetByteSize())}) - .first; + uint8_t exe_class = + llvm::object::getElfArchType( + {reinterpret_cast<const char *>(buffer_sp->GetBytes()), + size_t(buffer_sp->GetByteSize())}) + .first; switch (exe_class) { case llvm::ELF::ELFCLASS32: diff --git a/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp b/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp index 43f22be51ef9..b30c7a83243c 100644 --- a/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp +++ b/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp @@ -20,19 +20,23 @@ using namespace lldb_private; llvm::VersionTuple HostInfoOpenBSD::GetOSVersion() { struct utsname un; - ::memset(&un, 0, sizeof(utsname)); - if (uname(&un) < 0) + ::memset(&un, 0, sizeof(un)); + if (::uname(&un) < 0) return llvm::VersionTuple(); - unsigned major, minor; - if (2 == sscanf(un.release, "%u.%u", &major, &minor)) + uint32_t major, minor; + int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32, &major, &minor); + switch (status) { + case 1: + return llvm::VersionTuple(major); + case 2: return llvm::VersionTuple(major, minor); + } return llvm::VersionTuple(); } std::optional<std::string> HostInfoOpenBSD::GetOSBuildString() { int mib[2] = {CTL_KERN, KERN_OSREV}; - char osrev_str[12]; uint32_t osrev = 0; size_t osrev_len = sizeof(osrev); diff --git a/contrib/llvm-project/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/contrib/llvm-project/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 825da09d7602..fceeff08ed9d 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -202,9 +202,6 @@ ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) { return eConnectionStatusSuccess; } - if (m_io_sp->GetFdType() == IOObject::eFDTypeSocket) - static_cast<Socket &>(*m_io_sp).PreDisconnect(); - // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is // quite likely because somebody is doing a blocking read on our file // descriptor. If that's the case, then send the "q" char to the command @@ -513,7 +510,7 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1); assert(bytes_read == 1); - (void)bytes_read; + UNUSED_IF_ASSERT_DISABLED(bytes_read); switch (c) { case 'q': LLDB_LOGF(log, diff --git a/contrib/llvm-project/lldb/source/Host/posix/DomainSocket.cpp b/contrib/llvm-project/lldb/source/Host/posix/DomainSocket.cpp index ddbd983abb81..9b44c2a8368e 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/DomainSocket.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/DomainSocket.cpp @@ -48,7 +48,8 @@ static bool SetSockAddr(llvm::StringRef name, const size_t name_offset, saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) saddr_un->sun_len = saddr_un_len; #endif diff --git a/contrib/llvm-project/lldb/source/Host/posix/MainLoopPosix.cpp b/contrib/llvm-project/lldb/source/Host/posix/MainLoopPosix.cpp index 5b50b450433e..5fe4d015251c 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/MainLoopPosix.cpp @@ -122,7 +122,7 @@ sigset_t MainLoopPosix::RunImpl::get_sigmask() { sigset_t sigmask; int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask); assert(ret == 0); - (void)ret; + UNUSED_IF_ASSERT_DISABLED(ret); for (const auto &sig : loop.m_signals) sigdelset(&sigmask, sig.first); @@ -299,7 +299,7 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, // Even if using kqueue, the signal handler will still be invoked, so it's // important to replace it with our "benign" handler. int ret = sigaction(signo, &new_action, &info.old_action); - (void)ret; + UNUSED_IF_ASSERT_DISABLED(ret); assert(ret == 0 && "sigaction failed"); #if HAVE_SYS_EVENT_H @@ -346,7 +346,7 @@ void MainLoopPosix::UnregisterSignal( int ret = pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr); assert(ret == 0); - (void)ret; + UNUSED_IF_ASSERT_DISABLED(ret); #if HAVE_SYS_EVENT_H struct kevent ev; diff --git a/contrib/llvm-project/lldb/source/Host/posix/PipePosix.cpp b/contrib/llvm-project/lldb/source/Host/posix/PipePosix.cpp index 5e4e8618fa4f..afd3fe39059a 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/PipePosix.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/PipePosix.cpp @@ -31,8 +31,8 @@ enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE // pipe2 is supported by a limited set of platforms // TODO: Add more platforms that support pipe2. -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ - defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) #define PIPE2_SUPPORTED 1 #else #define PIPE2_SUPPORTED 0 @@ -65,16 +65,21 @@ PipePosix::PipePosix(PipePosix &&pipe_posix) pipe_posix.ReleaseWriteFileDescriptor()} {} PipePosix &PipePosix::operator=(PipePosix &&pipe_posix) { + std::scoped_lock<std::mutex, std::mutex, std::mutex, std::mutex> guard( + m_read_mutex, m_write_mutex, pipe_posix.m_read_mutex, + pipe_posix.m_write_mutex); + PipeBase::operator=(std::move(pipe_posix)); - m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor(); - m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor(); + m_fds[READ] = pipe_posix.ReleaseReadFileDescriptorUnlocked(); + m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptorUnlocked(); return *this; } PipePosix::~PipePosix() { Close(); } Status PipePosix::CreateNew(bool child_processes_inherit) { - if (CanRead() || CanWrite()) + std::scoped_lock<std::mutex, std::mutex> guard(m_read_mutex, m_write_mutex); + if (CanReadUnlocked() || CanWriteUnlocked()) return Status(EINVAL, eErrorTypePOSIX); Status error; @@ -87,7 +92,7 @@ Status PipePosix::CreateNew(bool child_processes_inherit) { if (!child_processes_inherit) { if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) { error.SetErrorToErrno(); - Close(); + CloseUnlocked(); return error; } } @@ -103,7 +108,8 @@ Status PipePosix::CreateNew(bool child_processes_inherit) { } Status PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) { - if (CanRead() || CanWrite()) + std::scoped_lock<std::mutex, std::mutex> (m_read_mutex, m_write_mutex); + if (CanReadUnlocked() || CanWriteUnlocked()) return Status("Pipe is already opened"); Status error; @@ -140,7 +146,9 @@ Status PipePosix::CreateWithUniqueName(llvm::StringRef prefix, Status PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) { - if (CanRead() || CanWrite()) + std::scoped_lock<std::mutex, std::mutex> (m_read_mutex, m_write_mutex); + + if (CanReadUnlocked() || CanWriteUnlocked()) return Status("Pipe is already opened"); int flags = O_RDONLY | O_NONBLOCK; @@ -161,7 +169,8 @@ Status PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) { - if (CanRead() || CanWrite()) + std::lock_guard<std::mutex> guard(m_write_mutex); + if (CanReadUnlocked() || CanWriteUnlocked()) return Status("Pipe is already opened"); int flags = O_WRONLY | O_NONBLOCK; @@ -171,7 +180,7 @@ PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, using namespace std::chrono; const auto finish_time = Now() + timeout; - while (!CanWrite()) { + while (!CanWriteUnlocked()) { if (timeout != microseconds::zero()) { const auto dur = duration_cast<microseconds>(finish_time - Now()).count(); if (dur <= 0) @@ -196,25 +205,54 @@ PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, return Status(); } -int PipePosix::GetReadFileDescriptor() const { return m_fds[READ]; } +int PipePosix::GetReadFileDescriptor() const { + std::lock_guard<std::mutex> guard(m_read_mutex); + return GetReadFileDescriptorUnlocked(); +} + +int PipePosix::GetReadFileDescriptorUnlocked() const { + return m_fds[READ]; +} -int PipePosix::GetWriteFileDescriptor() const { return m_fds[WRITE]; } +int PipePosix::GetWriteFileDescriptor() const { + std::lock_guard<std::mutex> guard(m_write_mutex); + return GetWriteFileDescriptorUnlocked(); +} + +int PipePosix::GetWriteFileDescriptorUnlocked() const { + return m_fds[WRITE]; +} int PipePosix::ReleaseReadFileDescriptor() { + std::lock_guard<std::mutex> guard(m_read_mutex); + return ReleaseReadFileDescriptorUnlocked(); +} + +int PipePosix::ReleaseReadFileDescriptorUnlocked() { const int fd = m_fds[READ]; m_fds[READ] = PipePosix::kInvalidDescriptor; return fd; } int PipePosix::ReleaseWriteFileDescriptor() { + std::lock_guard<std::mutex> guard(m_write_mutex); + return ReleaseWriteFileDescriptorUnlocked(); +} + +int PipePosix::ReleaseWriteFileDescriptorUnlocked() { const int fd = m_fds[WRITE]; m_fds[WRITE] = PipePosix::kInvalidDescriptor; return fd; } void PipePosix::Close() { - CloseReadFileDescriptor(); - CloseWriteFileDescriptor(); + std::scoped_lock<std::mutex, std::mutex> guard(m_read_mutex, m_write_mutex); + CloseUnlocked(); +} + +void PipePosix::CloseUnlocked() { + CloseReadFileDescriptorUnlocked(); + CloseWriteFileDescriptorUnlocked(); } Status PipePosix::Delete(llvm::StringRef name) { @@ -222,22 +260,41 @@ Status PipePosix::Delete(llvm::StringRef name) { } bool PipePosix::CanRead() const { + std::lock_guard<std::mutex> guard(m_read_mutex); + return CanReadUnlocked(); +} + +bool PipePosix::CanReadUnlocked() const { return m_fds[READ] != PipePosix::kInvalidDescriptor; } bool PipePosix::CanWrite() const { + std::lock_guard<std::mutex> guard(m_write_mutex); + return CanWriteUnlocked(); +} + +bool PipePosix::CanWriteUnlocked() const { return m_fds[WRITE] != PipePosix::kInvalidDescriptor; } void PipePosix::CloseReadFileDescriptor() { - if (CanRead()) { + std::lock_guard<std::mutex> guard(m_read_mutex); + CloseReadFileDescriptorUnlocked(); +} +void PipePosix::CloseReadFileDescriptorUnlocked() { + if (CanReadUnlocked()) { close(m_fds[READ]); m_fds[READ] = PipePosix::kInvalidDescriptor; } } void PipePosix::CloseWriteFileDescriptor() { - if (CanWrite()) { + std::lock_guard<std::mutex> guard(m_write_mutex); + CloseWriteFileDescriptorUnlocked(); +} + +void PipePosix::CloseWriteFileDescriptorUnlocked() { + if (CanWriteUnlocked()) { close(m_fds[WRITE]); m_fds[WRITE] = PipePosix::kInvalidDescriptor; } @@ -246,11 +303,12 @@ void PipePosix::CloseWriteFileDescriptor() { Status PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) { + std::lock_guard<std::mutex> guard(m_read_mutex); bytes_read = 0; - if (!CanRead()) + if (!CanReadUnlocked()) return Status(EINVAL, eErrorTypePOSIX); - const int fd = GetReadFileDescriptor(); + const int fd = GetReadFileDescriptorUnlocked(); SelectHelper select_helper; select_helper.SetTimeout(timeout); @@ -278,11 +336,12 @@ Status PipePosix::ReadWithTimeout(void *buf, size_t size, } Status PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) { + std::lock_guard<std::mutex> guard(m_write_mutex); bytes_written = 0; - if (!CanWrite()) + if (!CanWriteUnlocked()) return Status(EINVAL, eErrorTypePOSIX); - const int fd = GetWriteFileDescriptor(); + const int fd = GetWriteFileDescriptorUnlocked(); SelectHelper select_helper; select_helper.SetTimeout(std::chrono::seconds(0)); select_helper.FDSetWrite(fd); diff --git a/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp b/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp index 40e54cd7f0e0..1a172a95aa14 100644 --- a/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -18,7 +18,8 @@ #include "lldb/Utility/Timer.h" #include "lldb/Version/Version.h" -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #endif @@ -77,7 +78,8 @@ llvm::Error SystemInitializerCommon::Initialize() { process_gdb_remote::ProcessGDBRemoteLog::Initialize(); -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) ProcessPOSIXLog::Initialize(); #endif #if defined(_WIN32) diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp index f6eaeacff81e..c5971b52f837 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp @@ -135,7 +135,7 @@ Options *CommandAlias::GetOptions() { return nullptr; } -bool CommandAlias::Execute(const char *args_string, +void CommandAlias::Execute(const char *args_string, CommandReturnObject &result) { llvm_unreachable("CommandAlias::Execute is not to be called"); } @@ -182,7 +182,7 @@ bool CommandAlias::IsDashDashCommand() { for (const auto &opt_entry : *GetOptionArguments()) { std::tie(opt, std::ignore, value) = opt_entry; if (opt == CommandInterpreter::g_argument && !value.empty() && - llvm::StringRef(value).endswith("--")) { + llvm::StringRef(value).ends_with("--")) { m_is_dashdash_alias = eLazyBoolYes; break; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp index f78fc728c898..e1275ce711fc 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp @@ -46,7 +46,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" @@ -128,8 +128,8 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger, bool synchronous_execution) : Broadcaster(debugger.GetBroadcasterManager(), CommandInterpreter::GetStaticBroadcasterClass().AsCString()), - Properties(OptionValuePropertiesSP( - new OptionValueProperties(ConstString("interpreter")))), + Properties( + OptionValuePropertiesSP(new OptionValueProperties("interpreter"))), IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), m_debugger(debugger), m_synchronous_execution(true), m_skip_lldbinit_files(false), m_skip_app_init_files(false), @@ -508,6 +508,11 @@ void CommandInterpreter::Initialize() { if (cmd_obj_sp) { AddAlias("history", cmd_obj_sp); } + + cmd_obj_sp = GetCommandSPExact("help"); + if (cmd_obj_sp) { + AddAlias("h", cmd_obj_sp); + } } void CommandInterpreter::Clear() { @@ -1227,36 +1232,11 @@ CommandObject * CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str, StringList *matches, StringList *descriptions) const { - CommandObject *command_obj = - GetCommandSP(cmd_str, false, true, matches, descriptions).get(); - - // If we didn't find an exact match to the command string in the commands, - // look in the aliases. - - if (command_obj) - return command_obj; - - command_obj = GetCommandSP(cmd_str, true, true, matches, descriptions).get(); - - if (command_obj) - return command_obj; - - // If there wasn't an exact match then look for an inexact one in just the - // commands - command_obj = GetCommandSP(cmd_str, false, false, nullptr).get(); - - // Finally, if there wasn't an inexact match among the commands, look for an - // inexact match in both the commands and aliases. - - if (command_obj) { - if (matches) - matches->AppendString(command_obj->GetCommandName()); - if (descriptions) - descriptions->AppendString(command_obj->GetHelp()); - return command_obj; - } - - return GetCommandSP(cmd_str, true, false, matches, descriptions).get(); + // Try to find a match among commands and aliases. Allowing inexact matches, + // but perferring exact matches. + return GetCommandSP(cmd_str, /*include_aliases=*/true, /*exact=*/false, + matches, descriptions) + .get(); } CommandObject *CommandInterpreter::GetUserCommandObject( @@ -1793,7 +1773,7 @@ CommandInterpreter::PreprocessToken(std::string &expr_str) { StreamString value_strm; const bool show_type = false; - scalar.GetValue(&value_strm, show_type); + scalar.GetValue(value_strm, show_type); size_t value_string_size = value_strm.GetSize(); if (value_string_size) { expr_str = value_strm.GetData(); diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp index 313d24f0657b..1ff9774a0da4 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp @@ -715,7 +715,7 @@ Thread *CommandObject::GetDefaultThread() { return nullptr; } -bool CommandObjectParsed::Execute(const char *args_string, +void CommandObjectParsed::Execute(const char *args_string, CommandReturnObject &result) { bool handled = false; Args cmd_args(args_string); @@ -746,18 +746,17 @@ bool CommandObjectParsed::Execute(const char *args_string, result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.", GetCommandName()); Cleanup(); - return false; + return; } - handled = DoExecute(cmd_args, result); + DoExecute(cmd_args, result); } } Cleanup(); } - return handled; } -bool CommandObjectRaw::Execute(const char *args_string, +void CommandObjectRaw::Execute(const char *args_string, CommandReturnObject &result) { bool handled = false; if (HasOverrideCallback()) { @@ -770,9 +769,8 @@ bool CommandObjectRaw::Execute(const char *args_string, } if (!handled) { if (CheckRequirements(result)) - handled = DoExecute(args_string, result); + DoExecute(args_string, result); Cleanup(); } - return handled; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp index ba2d3416e183..d13805a75ffb 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp @@ -61,7 +61,7 @@ int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s, for (const auto &enum_value : enum_values) { llvm::StringRef this_enum(enum_value.string_value); - if (this_enum.startswith(s)) + if (this_enum.starts_with(s)) return enum_value.value; } @@ -168,7 +168,6 @@ lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, std::optional<lldb::addr_t> OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s, Status *error_ptr) { - bool error_set = false; if (s.empty()) { if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", @@ -223,52 +222,40 @@ OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s, if (error_ptr) error_ptr->Clear(); return addr; - } else { - if (error_ptr) { - error_set = true; - error_ptr->SetErrorStringWithFormat( - "address expression \"%s\" resulted in a value whose type " - "can't be converted to an address: %s", - s.str().c_str(), valobj_sp->GetTypeName().GetCString()); - } } + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "address expression \"%s\" resulted in a value whose type " + "can't be converted to an address: %s", + s.str().c_str(), valobj_sp->GetTypeName().GetCString()); + return {}; + } - } else { - // Since the compiler can't handle things like "main + 12" we should try to - // do this for now. The compiler doesn't like adding offsets to function - // pointer types. - static RegularExpression g_symbol_plus_offset_regex( - "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); - - llvm::SmallVector<llvm::StringRef, 4> matches; - if (g_symbol_plus_offset_regex.Execute(sref, &matches)) { - uint64_t offset = 0; - std::string name = matches[1].str(); - std::string sign = matches[2].str(); - std::string str_offset = matches[3].str(); - if (!llvm::StringRef(str_offset).getAsInteger(0, offset)) { - Status error; - addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error); - if (addr != LLDB_INVALID_ADDRESS) { - if (sign[0] == '+') - return addr + offset; - else - return addr - offset; - } + // Since the compiler can't handle things like "main + 12" we should try to + // do this for now. The compiler doesn't like adding offsets to function + // pointer types. + static RegularExpression g_symbol_plus_offset_regex( + "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); + + llvm::SmallVector<llvm::StringRef, 4> matches; + if (g_symbol_plus_offset_regex.Execute(sref, &matches)) { + uint64_t offset = 0; + llvm::StringRef name = matches[1]; + llvm::StringRef sign = matches[2]; + llvm::StringRef str_offset = matches[3]; + if (!str_offset.getAsInteger(0, offset)) { + Status error; + addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); + if (addr != LLDB_INVALID_ADDRESS) { + if (sign[0] == '+') + return addr + offset; + return addr - offset; } } - - if (error_ptr) { - error_set = true; - error_ptr->SetErrorStringWithFormat( - "address expression \"%s\" evaluation failed", s.str().c_str()); - } } - if (error_ptr) { - if (!error_set) - error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", - s.str().c_str()); - } + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "address expression \"%s\" evaluation failed", s.str().c_str()); return {}; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp index c2f78d8c2dd1..d1ae916cd74b 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp @@ -28,41 +28,23 @@ static constexpr OptionEnumValueElement g_watch_type[] = { "Watch for write", }, { + OptionGroupWatchpoint::eWatchModify, + "modify", + "Watch for modifications", + }, + { OptionGroupWatchpoint::eWatchReadWrite, "read_write", "Watch for read/write", }, }; -static constexpr OptionEnumValueElement g_watch_size[] = { - { - 1, - "1", - "Watch for byte size of 1", - }, - { - 2, - "2", - "Watch for byte size of 2", - }, - { - 4, - "4", - "Watch for byte size of 4", - }, - { - 8, - "8", - "Watch for byte size of 8", - }, -}; - static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument, nullptr, OptionEnumValues(g_watch_type), 0, eArgTypeWatchType, "Specify the type of watching to perform."}, {LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument, - nullptr, OptionEnumValues(g_watch_size), 0, eArgTypeByteSize, + nullptr, {}, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}, {LLDB_OPT_SET_2, false, @@ -75,16 +57,6 @@ static constexpr OptionDefinition g_option_table[] = { eArgTypeLanguage, "Language of expression to run"}}; -bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) { - for (const auto& size : g_watch_size) { - if (0 == size.value) - break; - if (watch_size == size.value) - return true; - } - return false; -} - Status OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -115,8 +87,10 @@ OptionGroupWatchpoint::SetOptionValue(uint32_t option_idx, break; } case 's': - watch_size = (uint32_t)OptionArgParser::ToOptionEnum( - option_arg, g_option_table[option_idx].enum_values, 0, error); + error = watch_size.SetValueFromString(option_arg); + if (watch_size.GetCurrentValue() == 0) + error.SetErrorStringWithFormat("invalid --size option value '%s'", + option_arg.str().c_str()); break; default: @@ -130,7 +104,7 @@ void OptionGroupWatchpoint::OptionParsingStarting( ExecutionContext *execution_context) { watch_type_specified = false; watch_type = eWatchInvalid; - watch_size = 0; + watch_size.Clear(); language_type = eLanguageTypeUnknown; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp index 8d429b6bc9cf..fe1d8829c5ad 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValue.cpp @@ -15,6 +15,25 @@ using namespace lldb; using namespace lldb_private; +OptionValue::OptionValue(const OptionValue &other) { + std::lock_guard<std::mutex> lock(other.m_mutex); + + m_parent_wp = other.m_parent_wp; + m_callback = other.m_callback; + m_value_was_set = other.m_value_was_set; + +} + +OptionValue& OptionValue::operator=(const OptionValue &other) { + std::scoped_lock<std::mutex, std::mutex> lock(m_mutex, other.m_mutex); + + m_parent_wp = other.m_parent_wp; + m_callback = other.m_callback; + m_value_was_set = other.m_value_was_set; + + return *this; +} + Status OptionValue::SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef name, llvm::StringRef value) { @@ -252,12 +271,14 @@ const OptionValueUUID *OptionValue::GetAsUUID() const { } std::optional<bool> OptionValue::GetBooleanValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueBoolean *option_value = GetAsBoolean()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetBooleanValue(bool new_value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueBoolean *option_value = GetAsBoolean()) { option_value->SetCurrentValue(new_value); return true; @@ -266,12 +287,14 @@ bool OptionValue::SetBooleanValue(bool new_value) { } std::optional<char> OptionValue::GetCharValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueChar *option_value = GetAsChar()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetCharValue(char new_value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueChar *option_value = GetAsChar()) { option_value->SetCurrentValue(new_value); return true; @@ -280,12 +303,14 @@ bool OptionValue::SetCharValue(char new_value) { } std::optional<int64_t> OptionValue::GetEnumerationValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueEnumeration *option_value = GetAsEnumeration()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetEnumerationValue(int64_t value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueEnumeration *option_value = GetAsEnumeration()) { option_value->SetCurrentValue(value); return true; @@ -294,12 +319,14 @@ bool OptionValue::SetEnumerationValue(int64_t value) { } std::optional<FileSpec> OptionValue::GetFileSpecValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueFileSpec *option_value = GetAsFileSpec()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetFileSpecValue(FileSpec file_spec) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueFileSpec *option_value = GetAsFileSpec()) { option_value->SetCurrentValue(file_spec, false); return true; @@ -308,6 +335,7 @@ bool OptionValue::SetFileSpecValue(FileSpec file_spec) { } bool OptionValue::AppendFileSpecValue(FileSpec file_spec) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueFileSpecList *option_value = GetAsFileSpecList()) { option_value->AppendCurrentValue(file_spec); return true; @@ -316,18 +344,21 @@ bool OptionValue::AppendFileSpecValue(FileSpec file_spec) { } std::optional<FileSpecList> OptionValue::GetFileSpecListValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueFileSpecList *option_value = GetAsFileSpecList()) return option_value->GetCurrentValue(); return {}; } std::optional<lldb::Format> OptionValue::GetFormatValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueFormat *option_value = GetAsFormat()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetFormatValue(lldb::Format new_value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueFormat *option_value = GetAsFormat()) { option_value->SetCurrentValue(new_value); return true; @@ -336,12 +367,14 @@ bool OptionValue::SetFormatValue(lldb::Format new_value) { } std::optional<lldb::LanguageType> OptionValue::GetLanguageValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueLanguage *option_value = GetAsLanguage()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueLanguage *option_value = GetAsLanguage()) { option_value->SetCurrentValue(new_language); return true; @@ -350,24 +383,28 @@ bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) { } const FormatEntity::Entry *OptionValue::GetFormatEntity() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueFormatEntity *option_value = GetAsFormatEntity()) return &option_value->GetCurrentValue(); return nullptr; } const RegularExpression *OptionValue::GetRegexValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueRegex *option_value = GetAsRegex()) return option_value->GetCurrentValue(); return nullptr; } std::optional<int64_t> OptionValue::GetSInt64Value() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueSInt64 *option_value = GetAsSInt64()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetSInt64Value(int64_t new_value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueSInt64 *option_value = GetAsSInt64()) { option_value->SetCurrentValue(new_value); return true; @@ -376,12 +413,14 @@ bool OptionValue::SetSInt64Value(int64_t new_value) { } std::optional<llvm::StringRef> OptionValue::GetStringValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueString *option_value = GetAsString()) return option_value->GetCurrentValueAsRef(); return {}; } bool OptionValue::SetStringValue(llvm::StringRef new_value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueString *option_value = GetAsString()) { option_value->SetCurrentValue(new_value); return true; @@ -390,12 +429,14 @@ bool OptionValue::SetStringValue(llvm::StringRef new_value) { } std::optional<uint64_t> OptionValue::GetUInt64Value() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueUInt64 *option_value = GetAsUInt64()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetUInt64Value(uint64_t new_value) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueUInt64 *option_value = GetAsUInt64()) { option_value->SetCurrentValue(new_value); return true; @@ -404,12 +445,14 @@ bool OptionValue::SetUInt64Value(uint64_t new_value) { } std::optional<UUID> OptionValue::GetUUIDValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueUUID *option_value = GetAsUUID()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetUUIDValue(const UUID &uuid) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueUUID *option_value = GetAsUUID()) { option_value->SetCurrentValue(uuid); return true; @@ -418,12 +461,14 @@ bool OptionValue::SetUUIDValue(const UUID &uuid) { } std::optional<ArchSpec> OptionValue::GetArchSpecValue() const { + std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueArch *option_value = GetAsArch()) return option_value->GetCurrentValue(); return {}; } bool OptionValue::SetArchSpecValue(ArchSpec arch_spec) { + std::lock_guard<std::mutex> lock(m_mutex); if (OptionValueArch *option_value = GetAsArch()) { option_value->SetCurrentValue(arch_spec, false); return true; diff --git a/contrib/llvm-project/lldb/source/Interpreter/Options.cpp b/contrib/llvm-project/lldb/source/Interpreter/Options.cpp index acbde7660440..89fe69009d90 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/Options.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/Options.cpp @@ -636,7 +636,7 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, // upper level code will know this is a full match and add the " ". const OptionDefinition &opt = opt_defs[opt_defs_index]; llvm::StringRef long_option = opt.long_option; - if (cur_opt_str.startswith("--") && cur_opt_str != long_option) { + if (cur_opt_str.starts_with("--") && cur_opt_str != long_option) { request.AddCompletion("--" + long_option.str(), opt.usage_text); return true; } else @@ -652,7 +652,7 @@ bool Options::HandleOptionCompletion(CompletionRequest &request, if (cur_opt_str.consume_front("--")) { for (auto &def : opt_defs) { llvm::StringRef long_option(def.long_option); - if (long_option.startswith(cur_opt_str)) + if (long_option.starts_with(cur_opt_str)) request.AddCompletion("--" + long_option.str(), def.usage_text); } } @@ -890,8 +890,8 @@ static size_t FindArgumentIndexForOption(const Args &args, std::string long_opt = std::string(llvm::formatv("--{0}", long_option.definition->long_option)); for (const auto &entry : llvm::enumerate(args)) { - if (entry.value().ref().startswith(short_opt) || - entry.value().ref().startswith(long_opt)) + if (entry.value().ref().starts_with(short_opt) || + entry.value().ref().starts_with(long_opt)) return entry.index(); } diff --git a/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp index fb3fa74d0b97..8dd499ce819a 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -27,12 +27,9 @@ using namespace lldb; using namespace lldb_private; -ScriptInterpreter::ScriptInterpreter( - Debugger &debugger, lldb::ScriptLanguage script_lang, - lldb::ScriptedPlatformInterfaceUP scripted_platform_interface_up) - : m_debugger(debugger), m_script_lang(script_lang), - m_scripted_platform_interface_up( - std::move(scripted_platform_interface_up)) {} +ScriptInterpreter::ScriptInterpreter(Debugger &debugger, + lldb::ScriptLanguage script_lang) + : m_debugger(debugger), m_script_lang(script_lang) {} void ScriptInterpreter::CollectDataForBreakpointCommandCallback( std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, diff --git a/contrib/llvm-project/lldb/source/Interpreter/embedded_interpreter.py b/contrib/llvm-project/lldb/source/Interpreter/embedded_interpreter.py index fd2cc06bc286..a487592ef1ae 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/embedded_interpreter.py +++ b/contrib/llvm-project/lldb/source/Interpreter/embedded_interpreter.py @@ -1,4 +1,5 @@ import sys + if sys.version_info[0] < 3: import __builtin__ as builtins else: @@ -18,10 +19,10 @@ except AttributeError: have_readline = False else: have_readline = True - if 'libedit' in readline.__doc__: - readline.parse_and_bind('bind ^I rl_complete') + if "libedit" in readline.__doc__: + readline.parse_and_bind("bind ^I rl_complete") else: - readline.parse_and_bind('tab: complete') + readline.parse_and_bind("tab: complete") # When running one line, we might place the string to run in this string # in case it would be hard to correctly escape a string's contents @@ -34,7 +35,8 @@ def get_terminal_size(fd): import fcntl import termios import struct - hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) + + hw = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234")) except: hw = (0, 0) return hw @@ -46,7 +48,7 @@ class LLDBExit(SystemExit): def strip_and_check_exit(line): line = line.rstrip() - if line in ('exit', 'quit'): + if line in ("exit", "quit"): raise LLDBExit return line @@ -75,6 +77,7 @@ def run_python_interpreter(local_dict): if get_terminal_size(fd)[1] == 0: try: import termios + old = termios.tcgetattr(fd) if old[3] & termios.ECHO: # Need to turn off echoing and restore @@ -86,7 +89,8 @@ def run_python_interpreter(local_dict): code.interact( banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.", readfunc=readfunc_stdio, - local=local_dict) + local=local_dict, + ) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old) except: @@ -96,18 +100,20 @@ def run_python_interpreter(local_dict): code.interact( banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", readfunc=readfunc_stdio, - local=local_dict) + local=local_dict, + ) else: # We have a real interactive terminal code.interact( banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.", readfunc=readfunc, - local=local_dict) + local=local_dict, + ) except LLDBExit: pass except SystemExit as e: if e.code: - print('Script exited with code %s' % e.code) + print("Script exited with code %s" % e.code) def run_one_line(local_dict, input_string): @@ -127,4 +133,4 @@ def run_one_line(local_dict, input_string): pass except SystemExit as e: if e.code: - print('Script exited with code %s' % e.code) + print("Script exited with code %s" % e.code) diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h index 283306ed0f81..025a7a3fc368 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h @@ -46,7 +46,7 @@ public: // in other environments there can be a large number of different functions // involved in async traps. bool CallFrameAddressIsValid(lldb::addr_t cfa) override { - // Make sure the stack call frame addresses are are 8 byte aligned + // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) return false; // Not 8 byte aligned if (cfa == 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h index b3d4cba795f0..01d4af62fa6e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h @@ -49,7 +49,7 @@ public: // in other environments there can be a large number of different functions // involved in async traps. bool CallFrameAddressIsValid(lldb::addr_t cfa) override { - // Make sure the stack call frame addresses are are 8 byte aligned + // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) return false; // Not 8 byte aligned if (cfa == 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h index a77af75e57b8..c5ebd9717575 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.h @@ -37,7 +37,7 @@ public: bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; bool CallFrameAddressIsValid(lldb::addr_t cfa) override { - // Make sure the stack call frame addresses are are 4 byte aligned + // Make sure the stack call frame addresses are 4 byte aligned if (cfa & (4ull - 1ull)) return false; // Not 4 byte aligned if (cfa == 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.h b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.h index ce67b367d18f..65bc3e0b6298 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.h @@ -37,7 +37,7 @@ public: bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; bool CallFrameAddressIsValid(lldb::addr_t cfa) override { - // Make sure the stack call frame addresses are are 4 byte aligned + // Make sure the stack call frame addresses are 4 byte aligned if (cfa & (4ull - 1ull)) return false; // Not 4 byte aligned if (cfa == 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp new file mode 100644 index 000000000000..6395f5bb5bd9 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp @@ -0,0 +1,780 @@ +//===-- ABISysV_riscv.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 "ABISysV_riscv.h" + +#include <array> +#include <limits> + +#include "llvm/IR/DerivedTypes.h" + +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" + +#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString() +#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString() + +// The ABI is not a source of such information as size, offset, encoding, etc. +// of a register. Just provides correct dwarf and eh_frame numbers. + +#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \ + { \ + DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), 0, 0, \ + eEncodingInvalid, eFormatDefault, \ + {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \ + nullptr, nullptr, nullptr, \ + } + +#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \ + DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM) + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE_ADV(ABISysV_riscv, ABIRISCV) + +namespace { +namespace dwarf { +enum regnums { + zero, + ra, + sp, + gp, + tp, + t0, + t1, + t2, + fp, + s0 = fp, + s1, + a0, + a1, + a2, + a3, + a4, + a5, + a6, + a7, + s2, + s3, + s4, + s5, + s6, + s7, + s8, + s9, + s10, + s11, + t3, + t4, + t5, + t6, + pc +}; + +static const std::array<RegisterInfo, 33> g_register_infos = { + {DEFINE_REGISTER_STUB(zero, nullptr), + DEFINE_GENERIC_REGISTER_STUB(ra, nullptr, LLDB_REGNUM_GENERIC_RA), + DEFINE_GENERIC_REGISTER_STUB(sp, nullptr, LLDB_REGNUM_GENERIC_SP), + DEFINE_REGISTER_STUB(gp, nullptr), + DEFINE_REGISTER_STUB(tp, nullptr), + DEFINE_REGISTER_STUB(t0, nullptr), + DEFINE_REGISTER_STUB(t1, nullptr), + DEFINE_REGISTER_STUB(t2, nullptr), + DEFINE_GENERIC_REGISTER_STUB(fp, nullptr, LLDB_REGNUM_GENERIC_FP), + DEFINE_REGISTER_STUB(s1, nullptr), + DEFINE_GENERIC_REGISTER_STUB(a0, nullptr, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GENERIC_REGISTER_STUB(a1, nullptr, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GENERIC_REGISTER_STUB(a2, nullptr, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GENERIC_REGISTER_STUB(a3, nullptr, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GENERIC_REGISTER_STUB(a4, nullptr, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GENERIC_REGISTER_STUB(a5, nullptr, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GENERIC_REGISTER_STUB(a6, nullptr, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GENERIC_REGISTER_STUB(a7, nullptr, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_REGISTER_STUB(s2, nullptr), + DEFINE_REGISTER_STUB(s3, nullptr), + DEFINE_REGISTER_STUB(s4, nullptr), + DEFINE_REGISTER_STUB(s5, nullptr), + DEFINE_REGISTER_STUB(s6, nullptr), + DEFINE_REGISTER_STUB(s7, nullptr), + DEFINE_REGISTER_STUB(s8, nullptr), + DEFINE_REGISTER_STUB(s9, nullptr), + DEFINE_REGISTER_STUB(s10, nullptr), + DEFINE_REGISTER_STUB(s11, nullptr), + DEFINE_REGISTER_STUB(t3, nullptr), + DEFINE_REGISTER_STUB(t4, nullptr), + DEFINE_REGISTER_STUB(t5, nullptr), + DEFINE_REGISTER_STUB(t6, nullptr), + DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC)}}; +} // namespace dwarf +} // namespace + +const RegisterInfo *ABISysV_riscv::GetRegisterInfoArray(uint32_t &count) { + count = dwarf::g_register_infos.size(); + return dwarf::g_register_infos.data(); +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ + +ABISP +ABISysV_riscv::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { + llvm::Triple::ArchType machine = arch.GetTriple().getArch(); + + if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine) + return ABISP(); + + ABISysV_riscv *abi = new ABISysV_riscv(std::move(process_sp), + MakeMCRegisterInfo(arch)); + if (abi) + abi->SetIsRV64((llvm::Triple::riscv64 == machine) ? true : false); + return ABISP(abi); +} + +static inline size_t AugmentArgSize(bool is_rv64, size_t size_in_bytes) { + size_t word_size = is_rv64 ? 8 : 4; + return llvm::alignTo(size_in_bytes, word_size); +} + +static size_t +TotalArgsSizeInWords(bool is_rv64, + const llvm::ArrayRef<ABI::CallArgument> &args) { + size_t reg_size = is_rv64 ? 8 : 4; + size_t word_size = reg_size; + size_t total_size = 0; + for (const auto &arg : args) + total_size += + (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(is_rv64, + arg.size) + : reg_size) / + word_size; + + return total_size; +} + +bool ABISysV_riscv::PrepareTrivialCall(Thread &thread, addr_t sp, + addr_t func_addr, addr_t return_addr, + llvm::ArrayRef<addr_t> args) const { + // TODO: Implement + return false; +} + +bool ABISysV_riscv::PrepareTrivialCall( + Thread &thread, addr_t sp, addr_t pc, addr_t ra, llvm::Type &prototype, + llvm::ArrayRef<ABI::CallArgument> args) const { + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return false; + + uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + if (ra_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + if (sp_reg == LLDB_INVALID_REGNUM) + return false; + + Status error; + ProcessSP process = thread.GetProcess(); + if (!process) + return false; + + size_t reg_size = m_is_rv64 ? 8 : 4; + size_t word_size = reg_size; + // Push host data onto target. + for (const auto &arg : args) { + // Skip over target values. + if (arg.type == ABI::CallArgument::TargetValue) + continue; + + // Create space on the host stack for this data 4-byte aligned. + sp -= AugmentArgSize(m_is_rv64, arg.size); + + if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) < + arg.size || + error.Fail()) + return false; + + // Update the argument with the target pointer. + *const_cast<addr_t *>(&arg.value) = sp; + } + + // Make sure number of parameters matches prototype. + assert(prototype.getFunctionNumParams() == args.size()); + + const size_t num_args = args.size(); + const size_t regs_for_args_count = 8U; + const size_t num_args_in_regs = + num_args > regs_for_args_count ? regs_for_args_count : num_args; + + // Number of arguments passed on stack. + size_t args_size = TotalArgsSizeInWords(m_is_rv64, args); + auto on_stack = + args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count; + auto offset = on_stack * word_size; + + uint8_t reg_value[8]; + size_t reg_index = LLDB_REGNUM_GENERIC_ARG1; + + for (size_t i = 0; i < args_size; ++i) { + auto value = reinterpret_cast<const uint8_t *>(&args[i].value); + auto size = + ABI::CallArgument::TargetValue == args[i].type ? args[i].size : reg_size; + + // Pass arguments via registers. + if (i < num_args_in_regs) { + // copy value to register, padding if arg is smaller than register + auto end = size < reg_size ? size : reg_size; + memcpy(reg_value, value, end); + if (reg_size > end) + memset(reg_value + end, 0, reg_size - end); + + RegisterValue reg_val_obj(llvm::ArrayRef(reg_value, reg_size), + eByteOrderLittle); + if (!reg_ctx->WriteRegister( + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index), + reg_val_obj)) + return false; + + // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs + // But the "a" registers are sequential in the RISC-V register space + ++reg_index; + } + + if (reg_index < regs_for_args_count || size == 0) + continue; + + // Remaining arguments are passed on the stack. + if (process->WriteMemory(sp - offset, value, size, error) < size || + !error.Success()) + return false; + + offset -= AugmentArgSize(m_is_rv64, size); + } + + // Set stack pointer immediately below arguments. + sp -= on_stack * word_size; + + // Update registers with current function call state. + reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); + reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); + reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp); + + return true; +} + +bool ABISysV_riscv::GetArgumentValues(Thread &thread, ValueList &values) const { + // TODO: Implement + return false; +} + +Status ABISysV_riscv::SetReturnValueObject(StackFrameSP &frame_sp, + ValueObjectSP &new_value_sp) { + Status result; + if (!new_value_sp) { + result.SetErrorString("Empty value object for return value."); + return result; + } + + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { + result.SetErrorString("Null clang type for return value."); + return result; + } + + auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext(); + + bool is_signed = false; + if (!compiler_type.IsIntegerOrEnumerationType(is_signed) && + !compiler_type.IsPointerType()) { + result.SetErrorString("We don't support returning other types at present"); + return result; + } + + DataExtractor data; + size_t num_bytes = new_value_sp->GetData(data, result); + + if (result.Fail()) { + result.SetErrorStringWithFormat( + "Couldn't convert return value to raw data: %s", result.AsCString()); + return result; + } + + size_t reg_size = m_is_rv64 ? 8 : 4; + if (num_bytes <= 2 * reg_size) { + offset_t offset = 0; + uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); + + auto reg_info = + reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) { + result.SetErrorStringWithFormat("Couldn't write value to register %s", + reg_info->name); + return result; + } + + if (num_bytes <= reg_size) + return result; // Successfully written. + + // for riscv32, get the upper 32 bits from raw_value and write them + // for riscv64, get the next 64 bits from data and write them + if (4 == reg_size) + raw_value >>= 32; + else + raw_value = data.GetMaxU64(&offset, num_bytes - reg_size); + reg_info = + reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) { + result.SetErrorStringWithFormat("Couldn't write value to register %s", + reg_info->name); + } + + return result; + } + + result.SetErrorString( + "We don't support returning large integer values at present."); + return result; +} + +template <typename T> +static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) { + raw_value &= std::numeric_limits<T>::max(); + if (is_signed) + scalar = static_cast<typename std::make_signed<T>::type>(raw_value); + else + scalar = static_cast<T>(raw_value); +} + +static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value, + uint8_t size_in_bytes, bool is_signed) { + switch (size_in_bytes) { + default: + return false; + + case sizeof(uint64_t): + SetInteger<uint64_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint32_t): + SetInteger<uint32_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint16_t): + SetInteger<uint16_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint8_t): + SetInteger<uint8_t>(scalar, raw_value, is_signed); + break; + } + + return true; +} + +static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value, + uint8_t size_in_bytes) { + switch (size_in_bytes) { + default: + return false; + + case sizeof(uint64_t): + scalar = *reinterpret_cast<double *>(&raw_value); + break; + + case sizeof(uint32_t): + scalar = *reinterpret_cast<float *>(&raw_value); + break; + } + + return true; +} + +static ValueObjectSP GetValObjFromIntRegs(Thread &thread, + const RegisterContextSP ®_ctx, + llvm::Triple::ArchType machine, + uint32_t type_flags, + uint32_t byte_size) { + Value value; + ValueObjectSP return_valobj_sp; + auto reg_info_a0 = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + auto reg_info_a1 = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + uint64_t raw_value; + + switch (byte_size) { + case sizeof(uint32_t): + // Read a0 to get the arg + raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX; + break; + case sizeof(uint64_t): + // Read a0 to get the arg on riscv64, a0 and a1 on riscv32 + if (llvm::Triple::riscv32 == machine) { + raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX; + raw_value |= + (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) & UINT32_MAX) << 32U; + } else { + raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0); + } + break; + case 16: { + // Read a0 and a1 to get the arg on riscv64, not supported on riscv32 + if (llvm::Triple::riscv32 == machine) + return return_valobj_sp; + + // Create the ValueObjectSP here and return + std::unique_ptr<DataBufferHeap> heap_data_up( + new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = thread.GetProcess()->GetByteOrder(); + RegisterValue reg_value_a0, reg_value_a1; + if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) && + reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) { + Status error; + if (reg_value_a0.GetAsMemoryData(*reg_info_a0, + heap_data_up->GetBytes() + 0, 8, + byte_order, error) && + reg_value_a1.GetAsMemoryData(*reg_info_a1, + heap_data_up->GetBytes() + 8, 8, + byte_order, error)) { + value.SetBytes(heap_data_up.release(), byte_size); + return ValueObjectConstResult::Create( + thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); + } + } + break; + } + default: + return return_valobj_sp; + } + + if (type_flags & eTypeIsInteger) { + const bool is_signed = (type_flags & eTypeIsSigned) != 0; + if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed)) + return return_valobj_sp; + } else if (type_flags & eTypeIsFloat) { + if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size)) + return return_valobj_sp; + } else + return return_valobj_sp; + + value.SetValueType(Value::ValueType::Scalar); + return_valobj_sp = ValueObjectConstResult::Create( + thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); + return return_valobj_sp; +} + +static ValueObjectSP +GetValObjFromFPRegs(Thread &thread, const RegisterContextSP ®_ctx, + llvm::Triple::ArchType machine, uint32_t arch_fp_flags, + uint32_t type_flags, uint32_t byte_size) { + auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName("fa0"); + bool use_fp_regs = false; + ValueObjectSP return_valobj_sp; + + switch (arch_fp_flags) { + // fp return value in integer registers a0 and possibly a1 + case ArchSpec::eRISCV_float_abi_soft: + return_valobj_sp = + GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size); + return return_valobj_sp; + // fp return value in fp register fa0 (only float) + case ArchSpec::eRISCV_float_abi_single: + if (byte_size <= 4) + use_fp_regs = true; + break; + // fp return value in fp registers fa0 (float, double) + case ArchSpec::eRISCV_float_abi_double: + [[fallthrough]]; + // fp return value in fp registers fa0 (float, double, quad) + // not implemented; act like they're doubles + case ArchSpec::eRISCV_float_abi_quad: + if (byte_size <= 8) + use_fp_regs = true; + break; + } + + if (use_fp_regs) { + uint64_t raw_value; + Value value; + raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0); + if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size)) + return return_valobj_sp; + value.SetValueType(Value::ValueType::Scalar); + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); + } + // we should never reach this, but if we do, use the integer registers + return GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size); +} + +ValueObjectSP +ABISysV_riscv::GetReturnValueObjectSimple(Thread &thread, + CompilerType &compiler_type) const { + ValueObjectSP return_valobj_sp; + + if (!compiler_type) + return return_valobj_sp; + + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return return_valobj_sp; + + Value value; + value.SetCompilerType(compiler_type); + + const uint32_t type_flags = compiler_type.GetTypeInfo(); + const size_t byte_size = compiler_type.GetByteSize(&thread).value_or(0); + const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture(); + const llvm::Triple::ArchType machine = arch.GetMachine(); + + // Integer return type. + if (type_flags & eTypeIsInteger) { + return_valobj_sp = + GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size); + return return_valobj_sp; + } + // Pointer return type. + else if (type_flags & eTypeIsPointer) { + auto reg_info_a0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG1); + value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0); + value.SetValueType(Value::ValueType::Scalar); + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); + } + // Floating point return type. + else if (type_flags & eTypeIsFloat) { + uint32_t float_count = 0; + bool is_complex = false; + + if (compiler_type.IsFloatingPointType(float_count, is_complex) && + float_count == 1 && !is_complex) { + const uint32_t arch_fp_flags = + arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask; + return_valobj_sp = GetValObjFromFPRegs( + thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size); + return return_valobj_sp; + } + } + // Unsupported return type. + return return_valobj_sp; +} + +ValueObjectSP +ABISysV_riscv::GetReturnValueObjectImpl(lldb_private::Thread &thread, + llvm::Type &type) const { + Value value; + ValueObjectSP return_valobj_sp; + + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return return_valobj_sp; + + uint32_t type_flags = 0; + if (type.isIntegerTy()) + type_flags = eTypeIsInteger; + else if (type.isVoidTy()) + type_flags = eTypeIsPointer; + else if (type.isFloatTy()) + type_flags = eTypeIsFloat; + + const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT; + const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture(); + const llvm::Triple::ArchType machine = arch.GetMachine(); + + // Integer return type. + if (type_flags & eTypeIsInteger) { + return_valobj_sp = + GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size); + return return_valobj_sp; + } + // Pointer return type. + else if (type_flags & eTypeIsPointer) { + auto reg_info_a0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG1); + value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0); + value.SetValueType(Value::ValueType::Scalar); + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); + } + // Floating point return type. + else if (type_flags & eTypeIsFloat) { + const uint32_t arch_fp_flags = + arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask; + return_valobj_sp = GetValObjFromFPRegs( + thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size); + return return_valobj_sp; + } + // Unsupported return type. + return return_valobj_sp; +} + +ValueObjectSP ABISysV_riscv::GetReturnValueObjectImpl( + Thread &thread, CompilerType &return_compiler_type) const { + ValueObjectSP return_valobj_sp; + + if (!return_compiler_type) + return return_valobj_sp; + + ExecutionContext exe_ctx(thread.shared_from_this()); + return GetReturnValueObjectSimple(thread, return_compiler_type); +} + +bool ABISysV_riscv::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC; + uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP; + uint32_t ra_reg_num = LLDB_REGNUM_GENERIC_RA; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Define CFA as the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0); + + // Previous frame's pc is in ra + + row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true); + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("riscv function-entry unwind plan"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + + return true; +} + +bool ABISysV_riscv::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindGeneric); + + uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC; + uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Define the CFA as the current frame pointer value. + row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0); + row->SetOffset(0); + + int reg_size = 4; + if (m_is_rv64) + reg_size = 8; + + // Assume the ra reg (return pc) and caller's frame pointer + // have been spilled to stack already. + row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, reg_size * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, reg_size * -1, true); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("riscv default unwind plan"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + return true; +} + +bool ABISysV_riscv::RegisterIsVolatile(const RegisterInfo *reg_info) { + return !RegisterIsCalleeSaved(reg_info); +} + +bool ABISysV_riscv::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { + if (!reg_info) + return false; + + const char *name = reg_info->name; + ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture(); + uint32_t arch_flags = arch.GetFlags(); + // floating point registers are only callee saved when using + // F, D or Q hardware floating point ABIs + bool is_hw_fp = (arch_flags & ArchSpec::eRISCV_float_abi_mask) != 0; + + bool is_callee_saved = + llvm::StringSwitch<bool>(name) + // integer ABI names + .Cases("ra", "sp", "fp", true) + .Cases("s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", + true) + .Cases("s10", "s11", true) + // integer hardware names + .Cases("x1", "x2", "x8", "x9", "x18", "x19", "x20", "x21", "x22", + true) + .Cases("x23", "x24", "x25", "x26", "x27", true) + // floating point ABI names + .Cases("fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", + is_hw_fp) + .Cases("fs8", "fs9", "fs10", "fs11", is_hw_fp) + // floating point hardware names + .Cases("f8", "f9", "f18", "f19", "f20", "f21", "f22", "f23", is_hw_fp) + .Cases("f24", "f25", "f26", "f27", is_hw_fp) + .Default(false); + + return is_callee_saved; +} + +void ABISysV_riscv::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "System V ABI for RISCV targets", CreateInstance); +} + +void ABISysV_riscv::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +static uint32_t GetGenericNum(llvm::StringRef name) { + return llvm::StringSwitch<uint32_t>(name) + .Case("pc", LLDB_REGNUM_GENERIC_PC) + .Cases("ra", "x1", LLDB_REGNUM_GENERIC_RA) + .Cases("sp", "x2", LLDB_REGNUM_GENERIC_SP) + .Cases("fp", "s0", LLDB_REGNUM_GENERIC_FP) + .Case("a0", LLDB_REGNUM_GENERIC_ARG1) + .Case("a1", LLDB_REGNUM_GENERIC_ARG2) + .Case("a2", LLDB_REGNUM_GENERIC_ARG3) + .Case("a3", LLDB_REGNUM_GENERIC_ARG4) + .Case("a4", LLDB_REGNUM_GENERIC_ARG5) + .Case("a5", LLDB_REGNUM_GENERIC_ARG6) + .Case("a6", LLDB_REGNUM_GENERIC_ARG7) + .Case("a7", LLDB_REGNUM_GENERIC_ARG8) + .Default(LLDB_INVALID_REGNUM); +} + +void ABISysV_riscv::AugmentRegisterInfo( + std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) { + lldb_private::RegInfoBasedABI::AugmentRegisterInfo(regs); + + for (auto it : llvm::enumerate(regs)) { + // Set alt name for certain registers for convenience + if (it.value().name == "zero") + it.value().alt_name.SetCString("x0"); + else if (it.value().name == "ra") + it.value().alt_name.SetCString("x1"); + else if (it.value().name == "sp") + it.value().alt_name.SetCString("x2"); + else if (it.value().name == "gp") + it.value().alt_name.SetCString("x3"); + else if (it.value().name == "fp") + it.value().alt_name.SetCString("s0"); + else if (it.value().name == "s0") + it.value().alt_name.SetCString("x8"); + + // Set generic regnum so lldb knows what the PC, etc is + it.value().regnum_generic = GetGenericNum(it.value().name.GetStringRef()); + } +} diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h b/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h new file mode 100644 index 000000000000..d8cf008dbb0b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h @@ -0,0 +1,129 @@ +//===-- ABISysV_riscv.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 liblldb_ABISysV_riscv_h_ +#define liblldb_ABISysV_riscv_h_ + +// Other libraries and framework includes +#include "llvm/TargetParser/Triple.h" + +// Project includes +#include "lldb/Target/ABI.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/Flags.h" +#include "lldb/lldb-private.h" + +class ABISysV_riscv : public lldb_private::RegInfoBasedABI { +public: + ~ABISysV_riscv() override = default; + + size_t GetRedZoneSize() const override { return 0; } + + bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef<lldb::addr_t> args) const override; + + // Special thread plan for GDB style non-jit function calls. + bool + PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, lldb::addr_t returnAddress, + llvm::Type &prototype, + llvm::ArrayRef<ABI::CallArgument> args) const override; + + bool GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; + + lldb_private::Status + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override; + + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; + + // Specialized to work with llvm IR types. + lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, + llvm::Type &type) const override; + + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { + // The CFA must be 128 bit aligned, unless the E ABI is used + lldb_private::ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture(); + lldb_private::Flags arch_flags = arch.GetFlags(); + if (arch_flags.Test(lldb_private::ArchSpec::eRISCV_rve)) + return (cfa & 0x3ull) == 0; + return (cfa & 0xfull) == 0; + } + + void SetIsRV64(bool is_rv64) { m_is_rv64 = is_rv64; } + + bool CodeAddressIsValid(lldb::addr_t pc) override { + // Calls can use the least significant bit to store auxiliary information, + // so no strict check is done for alignment. + + lldb_private::ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture(); + + // <addr> & 2 set is a fault if C extension is not used. + lldb_private::Flags arch_flags(arch.GetFlags()); + if (!arch_flags.Test(lldb_private::ArchSpec::eRISCV_rvc) && (pc & 2)) + return false; + + // Make sure 64 bit addr_t only has lower 32 bits set on riscv32 + llvm::Triple::ArchType machine = arch.GetMachine(); + if (llvm::Triple::riscv32 == machine) + return (pc <= UINT32_MAX); + + return true; + } + + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + + static void Initialize(); + + static void Terminate(); + + static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, + const lldb_private::ArchSpec &arch); + + static llvm::StringRef GetPluginNameStatic() { return "sysv-riscv"; } + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + +protected: + void AugmentRegisterInfo( + std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) override; + + bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); + +private: + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + + using lldb_private::RegInfoBasedABI::RegInfoBasedABI; // Call CreateInstance + // instead. + bool m_is_rv64; // true if target is riscv64; false if target is riscv32 +}; + +#endif // liblldb_ABISysV_riscv_h_ diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h index 462317f17666..8c637b7671f6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.h @@ -52,7 +52,7 @@ public: // If we were to enforce 16-byte alignment, we also need to relax to 4-byte // alignment for non-darwin i386 targets. bool CallFrameAddressIsValid(lldb::addr_t cfa) override { - // Make sure the stack call frame addresses are are 4 byte aligned + // Make sure the stack call frame addresses are 4 byte aligned if (cfa & (4ull - 1ull)) return false; // Not 4 byte aligned if (cfa == 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp index 1b2b41ee8758..181ba4e7d877 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp @@ -8,7 +8,10 @@ #include "Plugins/Architecture/AArch64/ArchitectureAArch64.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" using namespace lldb_private; using namespace lldb; @@ -34,3 +37,88 @@ ArchitectureAArch64::Create(const ArchSpec &arch) { } return std::unique_ptr<Architecture>(new ArchitectureAArch64()); } + +static void +UpdateARM64SVERegistersInfos(DynamicRegisterInfo::reg_collection_range regs, + uint64_t vg) { + // SVE Z register size is vg x 8 bytes. + uint32_t z_reg_byte_size = vg * 8; + + // SVE vector length has changed, accordingly set size of Z, P and FFR + // registers. Also invalidate register offsets it will be recalculated + // after SVE register size update. + for (auto ® : regs) { + if (reg.value_regs == nullptr) { + if (reg.name[0] == 'z' && isdigit(reg.name[1])) + reg.byte_size = z_reg_byte_size; + else if (reg.name[0] == 'p' && isdigit(reg.name[1])) + reg.byte_size = vg; + else if (strcmp(reg.name, "ffr") == 0) + reg.byte_size = vg; + } + reg.byte_offset = LLDB_INVALID_INDEX32; + } +} + +static void +UpdateARM64SMERegistersInfos(DynamicRegisterInfo::reg_collection_range regs, + uint64_t svg) { + for (auto ® : regs) { + if (strcmp(reg.name, "za") == 0) { + // ZA is a register with size (svg*8) * (svg*8). A square essentially. + reg.byte_size = (svg * 8) * (svg * 8); + } + reg.byte_offset = LLDB_INVALID_INDEX32; + } +} + +bool ArchitectureAArch64::ReconfigureRegisterInfo(DynamicRegisterInfo ®_info, + DataExtractor ®_data, + RegisterContext ®_context + +) const { + // Once we start to reconfigure registers, we cannot read any of them. + // So we must read VG and SVG up front. + + const uint64_t fail_value = LLDB_INVALID_ADDRESS; + std::optional<uint64_t> vg_reg_value; + const RegisterInfo *vg_reg_info = reg_info.GetRegisterInfo("vg"); + if (vg_reg_info) { + uint32_t vg_reg_num = vg_reg_info->kinds[eRegisterKindLLDB]; + uint64_t reg_value = + reg_context.ReadRegisterAsUnsigned(vg_reg_num, fail_value); + if (reg_value != fail_value && reg_value <= 32) + vg_reg_value = reg_value; + } + + std::optional<uint64_t> svg_reg_value; + const RegisterInfo *svg_reg_info = reg_info.GetRegisterInfo("svg"); + if (svg_reg_info) { + uint32_t svg_reg_num = svg_reg_info->kinds[eRegisterKindLLDB]; + uint64_t reg_value = + reg_context.ReadRegisterAsUnsigned(svg_reg_num, fail_value); + if (reg_value != fail_value && reg_value <= 32) + svg_reg_value = reg_value; + } + + if (!vg_reg_value && !svg_reg_value) + return false; + + auto regs = reg_info.registers<DynamicRegisterInfo::reg_collection_range>(); + if (vg_reg_value) + UpdateARM64SVERegistersInfos(regs, *vg_reg_value); + if (svg_reg_value) + UpdateARM64SMERegistersInfos(regs, *svg_reg_value); + + // At this point if we have updated any registers, their offsets will all be + // invalid. If we did, we need to update them all. + reg_info.ConfigureOffsets(); + // From here we are able to read registers again. + + // Make a heap based buffer that is big enough to store all registers + reg_data.SetData( + std::make_shared<DataBufferHeap>(reg_info.GetRegisterDataByteSize(), 0)); + reg_data.SetByteOrder(reg_context.GetByteOrder()); + + return true; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h index da0b867fb1e9..ba409428c951 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h @@ -28,6 +28,17 @@ public: return &m_memory_tag_manager; } + bool + RegisterWriteCausesReconfigure(const llvm::StringRef name) const override { + // lldb treats svg as read only, so only vg can be written. This results in + // the SVE registers changing size. + return name == "vg"; + } + + bool ReconfigureRegisterInfo(DynamicRegisterInfo ®_info, + DataExtractor ®_data, + RegisterContext ®_context) const override; + private: static std::unique_ptr<Architecture> Create(const ArchSpec &arch); ArchitectureAArch64() = default; diff --git a/contrib/llvm-project/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp b/contrib/llvm-project/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp index bb44675e842e..81c72122cb7e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Architecture/Arm/ArchitectureArm.cpp @@ -51,7 +51,7 @@ void ArchitectureArm::OverrideStopInfo(Thread &thread) const { // stepping because the debugger stops regardless due to the BVR/BCR // triggering a stop. // - // It also means we can set breakpoints on instructions inside an an if/then + // It also means we can set breakpoints on instructions inside an if/then // block and correctly skip them if we use the BKPT instruction. The ARM and // Thumb BKPT instructions are unconditional even when executed in a Thumb IT // block. diff --git a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp index 09115cc670da..1628107170e7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -59,9 +60,11 @@ public: uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst) const; - void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string, - std::string &comments_string); + void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc, + std::string &inst_string, std::string &comments_string); void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); + void SetUseColor(bool use_color); + bool GetUseColor() const; bool CanBranch(llvm::MCInst &mc_inst) const; bool HasDelaySlot(llvm::MCInst &mc_inst) const; bool IsCall(llvm::MCInst &mc_inst) const; @@ -75,7 +78,8 @@ private: std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, std::unique_ptr<llvm::MCContext> &&context_up, std::unique_ptr<llvm::MCDisassembler> &&disasm_up, - std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up); + std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up, + std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up); std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up; std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up; @@ -84,6 +88,7 @@ private: std::unique_ptr<llvm::MCContext> m_context_up; std::unique_ptr<llvm::MCDisassembler> m_disasm_up; std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up; + std::unique_ptr<llvm::MCInstrAnalysis> m_instr_analysis_up; }; namespace x86 { @@ -562,7 +567,9 @@ public: if (m_opcode.GetData(data)) { std::string out_string; + std::string markup_out_string; std::string comment_string; + std::string markup_comment_string; DisassemblerScope disasm(*this, exe_ctx); if (disasm) { @@ -604,7 +611,14 @@ public: if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); - mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); + + const bool saved_use_color = mc_disasm_ptr->GetUseColor(); + mc_disasm_ptr->SetUseColor(false); + mc_disasm_ptr->PrintMCInst(inst, pc, out_string, comment_string); + mc_disasm_ptr->SetUseColor(true); + mc_disasm_ptr->PrintMCInst(inst, pc, markup_out_string, + markup_comment_string); + mc_disasm_ptr->SetUseColor(saved_use_color); if (!comment_string.empty()) { AppendComment(comment_string); @@ -669,6 +683,11 @@ public: m_opcode_name = matches[1].str(); m_mnemonics = matches[2].str(); } + matches.clear(); + if (s_regex.Execute(markup_out_string, &matches)) { + m_markup_opcode_name = matches[1].str(); + m_markup_mnemonics = matches[2].str(); + } } } } @@ -1287,11 +1306,17 @@ DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, if (!instr_printer_up) return Instance(); - return Instance( - new MCDisasmInstance(std::move(instr_info_up), std::move(reg_info_up), - std::move(subtarget_info_up), std::move(asm_info_up), - std::move(context_up), std::move(disasm_up), - std::move(instr_printer_up))); + instr_printer_up->setPrintBranchImmAsAddress(true); + + // Not all targets may have registered createMCInstrAnalysis(). + std::unique_ptr<llvm::MCInstrAnalysis> instr_analysis_up( + curr_target->createMCInstrAnalysis(instr_info_up.get())); + + return Instance(new MCDisasmInstance( + std::move(instr_info_up), std::move(reg_info_up), + std::move(subtarget_info_up), std::move(asm_info_up), + std::move(context_up), std::move(disasm_up), std::move(instr_printer_up), + std::move(instr_analysis_up))); } DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance( @@ -1301,13 +1326,15 @@ DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance( std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, std::unique_ptr<llvm::MCContext> &&context_up, std::unique_ptr<llvm::MCDisassembler> &&disasm_up, - std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up) + std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up, + std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up) : m_instr_info_up(std::move(instr_info_up)), m_reg_info_up(std::move(reg_info_up)), m_subtarget_info_up(std::move(subtarget_info_up)), m_asm_info_up(std::move(asm_info_up)), m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)), - m_instr_printer_up(std::move(instr_printer_up)) { + m_instr_printer_up(std::move(instr_printer_up)), + m_instr_analysis_up(std::move(instr_analysis_up)) { assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up && m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up); } @@ -1328,15 +1355,17 @@ uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst( } void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst( - llvm::MCInst &mc_inst, std::string &inst_string, + llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string, std::string &comments_string) { llvm::raw_string_ostream inst_stream(inst_string); llvm::raw_string_ostream comments_stream(comments_string); + inst_stream.enable_colors(m_instr_printer_up->getUseColor()); m_instr_printer_up->setCommentStream(comments_stream); - m_instr_printer_up->printInst(&mc_inst, 0, llvm::StringRef(), + m_instr_printer_up->printInst(&mc_inst, pc, llvm::StringRef(), *m_subtarget_info_up, inst_stream); m_instr_printer_up->setCommentStream(llvm::nulls()); + comments_stream.flush(); static std::string g_newlines("\r\n"); @@ -1363,8 +1392,18 @@ void DisassemblerLLVMC::MCDisasmInstance::SetStyle( } } +void DisassemblerLLVMC::MCDisasmInstance::SetUseColor(bool use_color) { + m_instr_printer_up->setUseColor(use_color); +} + +bool DisassemblerLLVMC::MCDisasmInstance::GetUseColor() const { + return m_instr_printer_up->getUseColor(); +} + bool DisassemblerLLVMC::MCDisasmInstance::CanBranch( llvm::MCInst &mc_inst) const { + if (m_instr_analysis_up) + return m_instr_analysis_up->mayAffectControlFlow(mc_inst, *m_reg_info_up); return m_instr_info_up->get(mc_inst.getOpcode()) .mayAffectControlFlow(mc_inst, *m_reg_info_up); } @@ -1375,6 +1414,8 @@ bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot( } bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const { + if (m_instr_analysis_up) + return m_instr_analysis_up->isCall(mc_inst); return m_instr_info_up->get(mc_inst.getOpcode()).isCall(); } @@ -1535,6 +1576,8 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, ArchSpec::eRISCV_float_abi_quad) features_str += "+f,+d,+q,"; // FIXME: how do we detect features such as `+a`, `+m`? + // Turn them on by default now, since everyone seems to use them + features_str += "+a,+m,"; } // We use m_disasm_up.get() to tell whether we are valid or not, so if this diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp new file mode 100644 index 000000000000..6d2e17d4eac6 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp @@ -0,0 +1,789 @@ +//===-- DynamicLoaderFreeBSDKernel.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/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/StreamFile.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/OperatingSystem.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" + +#include "DynamicLoaderFreeBSDKernel.h" +#include <memory> +#include <mutex> + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel) + +void DynamicLoaderFreeBSDKernel::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + DebuggerInit); +} + +void DynamicLoaderFreeBSDKernel::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef DynamicLoaderFreeBSDKernel::GetPluginDescriptionStatic() { + return "The Dynamic Loader Plugin For FreeBSD Kernel"; +} + +static bool is_kernel(Module *module) { + if (!module) + return false; + + ObjectFile *objfile = module->GetObjectFile(); + if (!objfile) + return false; + if (objfile->GetType() != ObjectFile::eTypeExecutable) + return false; + if (objfile->GetStrata() != ObjectFile::eStrataUnknown && + objfile->GetStrata() != ObjectFile::eStrataKernel) + return false; + + return true; +} + +static bool is_kmod(Module *module) { + if (!module) + return false; + if (!module->GetObjectFile()) + return false; + ObjectFile *objfile = module->GetObjectFile(); + if (objfile->GetType() != ObjectFile::eTypeObjectFile && + objfile->GetType() != ObjectFile::eTypeSharedLibrary) + return false; + + return true; +} + +static bool is_reloc(Module *module) { + if (!module) + return false; + if (!module->GetObjectFile()) + return false; + ObjectFile *objfile = module->GetObjectFile(); + if (objfile->GetType() != ObjectFile::eTypeObjectFile) + return false; + + return true; +} + +// Instantiate Function of the FreeBSD Kernel Dynamic Loader Plugin called when +// Register the Plugin +DynamicLoader * +DynamicLoaderFreeBSDKernel::CreateInstance(lldb_private::Process *process, + bool force) { + // Check the environment when the plugin is not force loaded + Module *exec = process->GetTarget().GetExecutableModulePointer(); + if (exec && !is_kernel(exec)) { + return nullptr; + } + if (!force) { + // Check if the target is kernel + const llvm::Triple &triple_ref = + process->GetTarget().GetArchitecture().GetTriple(); + if (!triple_ref.isOSFreeBSD()) { + return nullptr; + } + } + + // At this point we have checked the target is a FreeBSD kernel and all we + // have to do is to find the kernel address + const addr_t kernel_address = FindFreeBSDKernel(process); + + if (CheckForKernelImageAtAddress(process, kernel_address).IsValid()) + return new DynamicLoaderFreeBSDKernel(process, kernel_address); + + return nullptr; +} + +addr_t +DynamicLoaderFreeBSDKernel::FindFreeBSDKernel(lldb_private::Process *process) { + addr_t kernel_addr = process->GetImageInfoAddress(); + if (kernel_addr == LLDB_INVALID_ADDRESS) + kernel_addr = FindKernelAtLoadAddress(process); + return kernel_addr; +} + +// Get the kernel address if the kernel is not loaded with a slide +addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress( + lldb_private::Process *process) { + Module *exe_module = process->GetTarget().GetExecutableModulePointer(); + + if (!is_kernel(exe_module)) + return LLDB_INVALID_ADDRESS; + + ObjectFile *exe_objfile = exe_module->GetObjectFile(); + + if (!exe_objfile->GetBaseAddress().IsValid()) + return LLDB_INVALID_ADDRESS; + + if (CheckForKernelImageAtAddress( + process, exe_objfile->GetBaseAddress().GetFileAddress()) + .IsValid()) + return exe_objfile->GetBaseAddress().GetFileAddress(); + + return LLDB_INVALID_ADDRESS; +} + +// Read ELF header from memry and return +bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process, + lldb::addr_t addr, + llvm::ELF::Elf32_Ehdr &header, + bool *read_error) { + Status error; + if (read_error) + *read_error = false; + + if (process->ReadMemory(addr, &header, sizeof(header), error) != + sizeof(header)) { + if (read_error) + *read_error = true; + return false; + } + + if (!header.checkMagic()) + return false; + + return true; +} + +// Check the correctness of Kernel and return UUID +lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress( + Process *process, lldb::addr_t addr, bool *read_error) { + Log *log = GetLog(LLDBLog::DynamicLoader); + + if (addr == LLDB_INVALID_ADDRESS) { + if (read_error) + *read_error = true; + return UUID(); + } + + LLDB_LOGF(log, + "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: " + "looking for kernel binary at 0x%" PRIx64, + addr); + + llvm::ELF::Elf32_Ehdr header; + if (!ReadELFHeader(process, addr, header)) { + *read_error = true; + return UUID(); + } + + // Check header type + if (header.e_type != llvm::ELF::ET_EXEC) + return UUID(); + + ModuleSP memory_module_sp = + process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr); + + if (!memory_module_sp.get()) { + *read_error = true; + return UUID(); + } + + ObjectFile *exe_objfile = memory_module_sp->GetObjectFile(); + if (exe_objfile == nullptr) { + LLDB_LOGF(log, + "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress " + "found a binary at 0x%" PRIx64 + " but could not create an object file from memory", + addr); + return UUID(); + } + + // In here, I should check is_kernel for memory_module_sp + // However, the ReadModuleFromMemory reads wrong section so that this check + // will failed + ArchSpec kernel_arch(llvm::ELF::convertEMachineToArchName(header.e_machine)); + + if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch)) + process->GetTarget().SetArchitecture(kernel_arch); + + std::string uuid_str; + if (memory_module_sp->GetUUID().IsValid()) { + uuid_str = "with UUID "; + uuid_str += memory_module_sp->GetUUID().GetAsString(); + } else { + uuid_str = "and no LC_UUID found in load commands "; + } + LLDB_LOGF(log, + "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: " + "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s", + addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str()); + + return memory_module_sp->GetUUID(); +} + +void DynamicLoaderFreeBSDKernel::DebuggerInit( + lldb_private::Debugger &debugger) {} + +DynamicLoaderFreeBSDKernel::DynamicLoaderFreeBSDKernel(Process *process, + addr_t kernel_address) + : DynamicLoader(process), m_process(process), + m_linker_file_list_struct_addr(LLDB_INVALID_ADDRESS), + m_linker_file_head_addr(LLDB_INVALID_ADDRESS), + m_kernel_load_address(kernel_address), m_mutex() { + process->SetCanRunCode(false); +} + +DynamicLoaderFreeBSDKernel::~DynamicLoaderFreeBSDKernel() { Clear(true); } + +void DynamicLoaderFreeBSDKernel::Update() { + LoadKernelModules(); + SetNotificationBreakPoint(); +} + +// Create in memory Module at the load address +bool DynamicLoaderFreeBSDKernel::KModImageInfo::ReadMemoryModule( + lldb_private::Process *process) { + Log *log = GetLog(LLDBLog::DynamicLoader); + if (m_memory_module_sp) + return true; + if (m_load_address == LLDB_INVALID_ADDRESS) + return false; + + FileSpec file_spec(m_name); + + ModuleSP memory_module_sp; + + llvm::ELF::Elf32_Ehdr elf_eheader; + size_t size_to_read = 512; + + if (ReadELFHeader(process, m_load_address, elf_eheader)) { + if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) { + size_to_read = sizeof(llvm::ELF::Elf32_Ehdr) + + elf_eheader.e_phnum * elf_eheader.e_phentsize; + } else if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] == + llvm::ELF::ELFCLASS64) { + llvm::ELF::Elf64_Ehdr elf_eheader; + Status error; + if (process->ReadMemory(m_load_address, &elf_eheader, sizeof(elf_eheader), + error) == sizeof(elf_eheader)) + size_to_read = sizeof(llvm::ELF::Elf64_Ehdr) + + elf_eheader.e_phnum * elf_eheader.e_phentsize; + } + } + + memory_module_sp = + process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read); + + if (!memory_module_sp) + return false; + + bool this_is_kernel = is_kernel(memory_module_sp.get()); + + if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid()) + m_uuid = memory_module_sp->GetUUID(); + + m_memory_module_sp = memory_module_sp; + m_is_kernel = this_is_kernel; + + // The kernel binary is from memory + if (this_is_kernel) { + LLDB_LOGF(log, "KextImageInfo::ReadMemoryModule read the kernel binary out " + "of memory"); + + if (memory_module_sp->GetArchitecture().IsValid()) + process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture()); + } + + return true; +} + +bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule( + lldb_private::Process *process) { + Log *log = GetLog(LLDBLog::DynamicLoader); + + if (IsLoaded()) + return true; + + Target &target = process->GetTarget(); + + if (IsKernel() && m_uuid.IsValid()) { + Stream &s = target.GetDebugger().GetOutputStream(); + s.Printf("Kernel UUID: %s\n", m_uuid.GetAsString().c_str()); + s.Printf("Load Address: 0x%" PRIx64 "\n", m_load_address); + } + + // Test if the module is loaded into the taget, + // maybe the module is loaded manually by user by doing target module add + // So that we have to create the module manually + if (!m_module_sp) { + const ModuleList &target_images = target.GetImages(); + m_module_sp = target_images.FindModule(m_uuid); + + // Search in the file system + if (!m_module_sp) { + ModuleSpec module_spec(FileSpec(GetPath()), target.GetArchitecture()); + if (IsKernel()) { + Status error; + if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error, + true)) { + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) + m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(), + target.GetArchitecture()); + } + } + + if (!m_module_sp) + m_module_sp = target.GetOrCreateModule(module_spec, true); + if (IsKernel() && !m_module_sp) { + Stream &s = target.GetDebugger().GetOutputStream(); + s.Printf("WARNING: Unable to locate kernel binary on the debugger " + "system.\n"); + } + } + + if (m_module_sp) { + // If the file is not kernel or kmod, the target should be loaded once and + // don't reload again + if (!IsKernel() && !is_kmod(m_module_sp.get())) { + ModuleSP existing_module_sp = target.GetImages().FindModule(m_uuid); + if (existing_module_sp && + existing_module_sp->IsLoadedInTarget(&target)) { + LLDB_LOGF(log, + "'%s' with UUID %s is not a kmod or kernel, and is " + "already registered in target, not loading.", + m_name.c_str(), m_uuid.GetAsString().c_str()); + return true; + } + } + m_uuid = m_module_sp->GetUUID(); + + // or append to the images + target.GetImages().AppendIfNeeded(m_module_sp, false); + } + } + + // If this file is relocatable kernel module(x86_64), adjust it's + // section(PT_LOAD segment) and return Because the kernel module's load + // address is the text section. lldb cannot create full memory module upon + // relocatable file So what we do is to set the load address only. + if (is_kmod(m_module_sp.get()) && is_reloc(m_module_sp.get())) { + m_stop_id = process->GetStopID(); + bool changed = false; + m_module_sp->SetLoadAddress(target, m_load_address, true, changed); + return true; + } + + if (m_module_sp) + ReadMemoryModule(process); + + // Calculate the slides of in memory module + if (!m_memory_module_sp || !m_module_sp) { + m_module_sp.reset(); + return false; + } + + ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile(); + ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile(); + + if (!ondisk_object_file || !memory_object_file) + m_module_sp.reset(); + + // Find the slide address + addr_t fixed_slide = LLDB_INVALID_ADDRESS; + if (ObjectFileELF *memory_objfile_elf = + llvm::dyn_cast<ObjectFileELF>(memory_object_file)) { + addr_t load_address = memory_object_file->GetBaseAddress().GetFileAddress(); + + if (load_address != LLDB_INVALID_ADDRESS && + m_load_address != load_address) { + fixed_slide = m_load_address - load_address; + LLDB_LOGF(log, + "kmod %s in-memory LOAD vmaddr is not correct, using a " + "fixed slide of 0x%" PRIx64, + m_name.c_str(), fixed_slide); + } + } + + SectionList *ondisk_section_list = ondisk_object_file->GetSectionList(); + SectionList *memory_section_list = memory_object_file->GetSectionList(); + + if (memory_section_list && ondisk_object_file) { + const uint32_t num_ondisk_sections = ondisk_section_list->GetSize(); + uint32_t num_load_sections = 0; + + for (uint32_t section_idx = 0; section_idx < num_ondisk_sections; + ++section_idx) { + SectionSP on_disk_section_sp = + ondisk_section_list->GetSectionAtIndex(section_idx); + + if (!on_disk_section_sp) + continue; + if (fixed_slide != LLDB_INVALID_ADDRESS) { + target.SetSectionLoadAddress(on_disk_section_sp, + on_disk_section_sp->GetFileAddress() + + fixed_slide); + + } else { + const Section *memory_section = + memory_section_list + ->FindSectionByName(on_disk_section_sp->GetName()) + .get(); + if (memory_section) { + target.SetSectionLoadAddress(on_disk_section_sp, + memory_section->GetFileAddress()); + ++num_load_sections; + } + } + } + + if (num_load_sections) + m_stop_id = process->GetStopID(); + else + m_module_sp.reset(); + } else { + m_module_sp.reset(); + } + + if (IsLoaded() && m_module_sp && IsKernel()) { + Stream &s = target.GetDebugger().GetOutputStream(); + ObjectFile *kernel_object_file = m_module_sp->GetObjectFile(); + if (kernel_object_file) { + addr_t file_address = + kernel_object_file->GetBaseAddress().GetFileAddress(); + if (m_load_address != LLDB_INVALID_ADDRESS && + file_address != LLDB_INVALID_ADDRESS) { + s.Printf("Kernel slide 0x%" PRIx64 " in memory.\n", + m_load_address - file_address); + s.Printf("Loaded kernel file %s\n", + m_module_sp->GetFileSpec().GetPath().c_str()); + } + } + s.Flush(); + } + + return IsLoaded(); +} + +// This function is work for kernel file, others it wil reset load address and +// return false +bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingFileAddress( + lldb_private::Process *process) { + if (IsLoaded()) + return true; + + if (m_module_sp) { + bool changed = false; + if (m_module_sp->SetLoadAddress(process->GetTarget(), 0, true, changed)) + m_stop_id = process->GetStopID(); + } + + return false; +} + +// Get the head of found_list +bool DynamicLoaderFreeBSDKernel::ReadKmodsListHeader() { + std::lock_guard<decltype(m_mutex)> guard(m_mutex); + + if (m_linker_file_list_struct_addr.IsValid()) { + // Get tqh_first struct element from linker_files + Status error; + addr_t address = m_process->ReadPointerFromMemory( + m_linker_file_list_struct_addr.GetLoadAddress(&m_process->GetTarget()), + error); + if (address != LLDB_INVALID_ADDRESS && error.Success()) { + m_linker_file_head_addr = Address(address); + } else { + m_linker_file_list_struct_addr.Clear(); + return false; + } + + if (!m_linker_file_head_addr.IsValid() || + m_linker_file_head_addr.GetFileAddress() == 0) { + m_linker_file_list_struct_addr.Clear(); + return false; + } + } + return true; +} + +// Parse Kmod info in found_list +bool DynamicLoaderFreeBSDKernel::ParseKmods(Address linker_files_head_addr) { + std::lock_guard<decltype(m_mutex)> guard(m_mutex); + KModImageInfo::collection_type linker_files_list; + Log *log = GetLog(LLDBLog::DynamicLoader); + + if (!ReadAllKmods(linker_files_head_addr, linker_files_list)) + return false; + LLDB_LOGF( + log, + "Kmod-changed breakpoint hit, there are %zu kernel modules currently.\n", + linker_files_list.size()); + + ModuleList &modules = m_process->GetTarget().GetImages(); + ModuleList remove_modules; + ModuleList add_modules; + + for (ModuleSP module : modules.Modules()) { + if (is_kernel(module.get())) + continue; + if (is_kmod(module.get())) + remove_modules.AppendIfNeeded(module); + } + + m_process->GetTarget().ModulesDidUnload(remove_modules, false); + + for (KModImageInfo &image_info : linker_files_list) { + if (m_kld_name_to_uuid.find(image_info.GetName()) != + m_kld_name_to_uuid.end()) + image_info.SetUUID(m_kld_name_to_uuid[image_info.GetName()]); + bool failed_to_load = false; + if (!image_info.LoadImageUsingMemoryModule(m_process)) { + image_info.LoadImageUsingFileAddress(m_process); + failed_to_load = true; + } else { + m_linker_files_list.push_back(image_info); + m_kld_name_to_uuid[image_info.GetName()] = image_info.GetUUID(); + } + + if (!failed_to_load) + add_modules.AppendIfNeeded(image_info.GetModule()); + } + m_process->GetTarget().ModulesDidLoad(add_modules); + return true; +} + +// Read all kmod from a given arrays of list +bool DynamicLoaderFreeBSDKernel::ReadAllKmods( + Address linker_files_head_addr, + KModImageInfo::collection_type &kmods_list) { + + // Get offset of next member and load address symbol + static ConstString kld_off_address_symbol_name("kld_off_address"); + static ConstString kld_off_next_symbol_name("kld_off_next"); + static ConstString kld_off_filename_symbol_name("kld_off_filename"); + static ConstString kld_off_pathname_symbol_name("kld_off_pathname"); + const Symbol *kld_off_address_symbol = + m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType( + kld_off_address_symbol_name, eSymbolTypeData); + const Symbol *kld_off_next_symbol = + m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType( + kld_off_next_symbol_name, eSymbolTypeData); + const Symbol *kld_off_filename_symbol = + m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType( + kld_off_filename_symbol_name, eSymbolTypeData); + const Symbol *kld_off_pathname_symbol = + m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType( + kld_off_pathname_symbol_name, eSymbolTypeData); + + if (!kld_off_address_symbol || !kld_off_next_symbol || + !kld_off_filename_symbol || !kld_off_pathname_symbol) + return false; + + Status error; + const int32_t kld_off_address = m_process->ReadSignedIntegerFromMemory( + kld_off_address_symbol->GetAddress().GetLoadAddress( + &m_process->GetTarget()), + 4, 0, error); + if (error.Fail()) + return false; + const int32_t kld_off_next = m_process->ReadSignedIntegerFromMemory( + kld_off_next_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()), + 4, 0, error); + if (error.Fail()) + return false; + const int32_t kld_off_filename = m_process->ReadSignedIntegerFromMemory( + kld_off_filename_symbol->GetAddress().GetLoadAddress( + &m_process->GetTarget()), + 4, 0, error); + if (error.Fail()) + return false; + + const int32_t kld_off_pathname = m_process->ReadSignedIntegerFromMemory( + kld_off_pathname_symbol->GetAddress().GetLoadAddress( + &m_process->GetTarget()), + 4, 0, error); + if (error.Fail()) + return false; + + // Parse KMods + addr_t kld_load_addr(LLDB_INVALID_ADDRESS); + char kld_filename[255]; + char kld_pathname[255]; + addr_t current_kld = + linker_files_head_addr.GetLoadAddress(&m_process->GetTarget()); + + while (current_kld != 0) { + addr_t kld_filename_addr = + m_process->ReadPointerFromMemory(current_kld + kld_off_filename, error); + if (error.Fail()) + return false; + addr_t kld_pathname_addr = + m_process->ReadPointerFromMemory(current_kld + kld_off_pathname, error); + if (error.Fail()) + return false; + + m_process->ReadCStringFromMemory(kld_filename_addr, kld_filename, + sizeof(kld_filename), error); + if (error.Fail()) + return false; + m_process->ReadCStringFromMemory(kld_pathname_addr, kld_pathname, + sizeof(kld_pathname), error); + if (error.Fail()) + return false; + kld_load_addr = + m_process->ReadPointerFromMemory(current_kld + kld_off_address, error); + if (error.Fail()) + return false; + + kmods_list.emplace_back(); + KModImageInfo &kmod_info = kmods_list.back(); + kmod_info.SetName(kld_filename); + kmod_info.SetLoadAddress(kld_load_addr); + kmod_info.SetPath(kld_pathname); + + current_kld = + m_process->ReadPointerFromMemory(current_kld + kld_off_next, error); + if (kmod_info.GetName() == "kernel") + kmods_list.pop_back(); + if (error.Fail()) + return false; + } + + return true; +} + +// Read all kmods +void DynamicLoaderFreeBSDKernel::ReadAllKmods() { + std::lock_guard<decltype(m_mutex)> guard(m_mutex); + + if (ReadKmodsListHeader()) { + if (m_linker_file_head_addr.IsValid()) { + if (!ParseKmods(m_linker_file_head_addr)) + m_linker_files_list.clear(); + } + } +} + +// Load all Kernel Modules +void DynamicLoaderFreeBSDKernel::LoadKernelModules() { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules " + "Start loading Kernel Module"); + + // Initialize Kernel Image Information at the first time + if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) { + ModuleSP module_sp = m_process->GetTarget().GetExecutableModule(); + if (is_kernel(module_sp.get())) { + m_kernel_image_info.SetModule(module_sp); + m_kernel_image_info.SetIsKernel(true); + } + + // Set name for kernel + llvm::StringRef kernel_name("freebsd_kernel"); + module_sp = m_kernel_image_info.GetModule(); + if (module_sp.get() && module_sp->GetObjectFile() && + !module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty()) + kernel_name = module_sp->GetObjectFile() + ->GetFileSpec() + .GetFilename() + .GetStringRef(); + m_kernel_image_info.SetName(kernel_name.data()); + + if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) { + m_kernel_image_info.SetLoadAddress(m_kernel_load_address); + } + + // Build In memory Module + if (m_kernel_image_info.GetLoadAddress() != LLDB_INVALID_ADDRESS) { + // If the kernel is not loaded in the memory, use file to load + if (!m_kernel_image_info.LoadImageUsingMemoryModule(m_process)) + m_kernel_image_info.LoadImageUsingFileAddress(m_process); + } + } + + LoadOperatingSystemPlugin(false); + + if (!m_kernel_image_info.IsLoaded() || !m_kernel_image_info.GetModule()) { + m_kernel_image_info.Clear(); + return; + } + + static ConstString modlist_symbol_name("linker_files"); + + const Symbol *symbol = + m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType( + modlist_symbol_name, lldb::eSymbolTypeData); + + if (symbol) { + m_linker_file_list_struct_addr = symbol->GetAddress(); + ReadAllKmods(); + } else { + LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules " + "cannot file modlist symbol"); + } +} + +// Update symbol when use kldload by setting callback function on kldload +void DynamicLoaderFreeBSDKernel::SetNotificationBreakPoint() {} + +// Hook called when attach to a process +void DynamicLoaderFreeBSDKernel::DidAttach() { + PrivateInitialize(m_process); + Update(); +} + +// Hook called after attach to a process +void DynamicLoaderFreeBSDKernel::DidLaunch() { + PrivateInitialize(m_process); + Update(); +} + +// Clear all member except kernel address +void DynamicLoaderFreeBSDKernel::Clear(bool clear_process) { + std::lock_guard<decltype(m_mutex)> guard(m_mutex); + if (clear_process) + m_process = nullptr; + m_linker_file_head_addr.Clear(); + m_linker_file_list_struct_addr.Clear(); + m_kernel_image_info.Clear(); + m_linker_files_list.clear(); +} + +// Reinitialize class +void DynamicLoaderFreeBSDKernel::PrivateInitialize(Process *process) { + Clear(true); + m_process = process; +} + +ThreadPlanSP DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan( + lldb_private::Thread &thread, bool stop_others) { + Log *log = GetLog(LLDBLog::Step); + LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan is " + "not yet implemented."); + return {}; +} + +Status DynamicLoaderFreeBSDKernel::CanLoadImage() { + Status error("shared object cannot be loaded into kernel"); + return error; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h new file mode 100644 index 000000000000..d8656e9c49df --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h @@ -0,0 +1,171 @@ +//===-- DynamicLoaderFreeBSDKernel.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_DYNAMICLOADER_FREEBSD_KERNEL_DYNAMICLOADERFREEBSDKERNEL_H +#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_FREEBSD_KERNEL_DYNAMICLOADERFREEBSDKERNEL_H + +#include <mutex> +#include <string> +#include <vector> + +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/UUID.h" +#include "llvm/BinaryFormat/ELF.h" + +class DynamicLoaderFreeBSDKernel : public lldb_private::DynamicLoader { +public: + DynamicLoaderFreeBSDKernel(lldb_private::Process *process, + lldb::addr_t kernel_addr); + + ~DynamicLoaderFreeBSDKernel() override; + + // Static Functions + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "freebsd-kernel"; } + + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::DynamicLoader * + CreateInstance(lldb_private::Process *process, bool force); + + static void DebuggerInit(lldb_private::Debugger &debugger); + + static lldb::addr_t FindFreeBSDKernel(lldb_private::Process *process); + + // Hooks for time point that after attach to some proccess + void DidAttach() override; + + void DidLaunch() override; + + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others) override; + + lldb_private::Status CanLoadImage() override; + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + +protected: + class KModImageInfo { + public: + KModImageInfo() + : m_module_sp(), m_memory_module_sp(), m_uuid(), m_name(), m_path() {} + + void Clear() { + m_load_address = LLDB_INVALID_ADDRESS; + m_name.clear(); + m_uuid.Clear(); + m_module_sp.reset(); + m_memory_module_sp.reset(); + m_stop_id = UINT32_MAX; + m_path.clear(); + } + + void SetLoadAddress(lldb::addr_t load_address) { + m_load_address = load_address; + } + + lldb::addr_t GetLoadAddress() const { return m_load_address; } + + void SetUUID(const lldb_private::UUID uuid) { m_uuid = uuid; } + + lldb_private::UUID GetUUID() const { return m_uuid; } + + void SetName(const char *name) { m_name = name; } + + std::string GetName() const { return m_name; } + + void SetPath(const char *path) { m_path = path; } + + std::string GetPath() const { return m_path; } + + void SetModule(lldb::ModuleSP module) { m_module_sp = module; } + + lldb::ModuleSP GetModule() { return m_module_sp; } + + void SetIsKernel(bool is_kernel) { m_is_kernel = is_kernel; } + + bool IsKernel() const { return m_is_kernel; }; + + void SetStopID(uint32_t stop_id) { m_stop_id = stop_id; } + + uint32_t GetStopID() { return m_stop_id; } + + bool IsLoaded() const { return m_stop_id != UINT32_MAX; }; + + bool ReadMemoryModule(lldb_private::Process *process); + + bool LoadImageUsingMemoryModule(lldb_private::Process *process); + + bool LoadImageUsingFileAddress(lldb_private::Process *process); + + using collection_type = std::vector<KModImageInfo>; + + private: + lldb::ModuleSP m_module_sp; + lldb::ModuleSP m_memory_module_sp; + lldb::addr_t m_load_address = LLDB_INVALID_ADDRESS; + lldb_private::UUID m_uuid; + bool m_is_kernel = false; + std::string m_name; + std::string m_path; + uint32_t m_stop_id = UINT32_MAX; + }; + + void PrivateInitialize(lldb_private::Process *process); + + void Clear(bool clear_process); + + void Update(); + + void LoadKernelModules(); + + void ReadAllKmods(); + + bool ReadAllKmods(lldb_private::Address linker_files_head_address, + KModImageInfo::collection_type &kmods_list); + + bool ReadKmodsListHeader(); + + bool ParseKmods(lldb_private::Address linker_files_head_address); + + void SetNotificationBreakPoint(); + + static lldb_private::UUID + CheckForKernelImageAtAddress(lldb_private::Process *process, + lldb::addr_t address, + bool *read_error = nullptr); + + static lldb::addr_t FindKernelAtLoadAddress(lldb_private::Process *process); + + static bool ReadELFHeader(lldb_private::Process *process, + lldb::addr_t address, llvm::ELF::Elf32_Ehdr &header, + bool *read_error = nullptr); + + lldb_private::Process *m_process; + lldb_private::Address m_linker_file_list_struct_addr; + lldb_private::Address m_linker_file_head_addr; + lldb::addr_t m_kernel_load_address; + KModImageInfo m_kernel_image_info; + KModImageInfo::collection_type m_linker_files_list; + std::recursive_mutex m_mutex; + std::unordered_map<std::string, lldb_private::UUID> m_kld_name_to_uuid; + +private: + DynamicLoaderFreeBSDKernel(const DynamicLoaderFreeBSDKernel &) = delete; + + const DynamicLoaderFreeBSDKernel & + operator=(const DynamicLoaderFreeBSDKernel &) = delete; +}; + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index f20167b46d27..1a9c4593b1b4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -25,6 +25,32 @@ using namespace lldb; using namespace lldb_private; +const char *DYLDRendezvous::StateToCStr(RendezvousState state) { + switch (state) { + case DYLDRendezvous::eConsistent: + return "eConsistent"; + case DYLDRendezvous::eAdd: + return "eAdd"; + case DYLDRendezvous::eDelete: + return "eDelete"; + } + return "<invalid RendezvousState>"; +} + +const char *DYLDRendezvous::ActionToCStr(RendezvousAction action) { + switch (action) { + case DYLDRendezvous::RendezvousAction::eTakeSnapshot: + return "eTakeSnapshot"; + case DYLDRendezvous::RendezvousAction::eAddModules: + return "eAddModules"; + case DYLDRendezvous::RendezvousAction::eRemoveModules: + return "eRemoveModules"; + case DYLDRendezvous::RendezvousAction::eNoAction: + return "eNoAction"; + } + return "<invalid RendezvousAction>"; +} + DYLDRendezvous::DYLDRendezvous(Process *process) : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_executable_interpreter(false), m_current(), m_previous(), @@ -129,6 +155,13 @@ void DYLDRendezvous::UpdateExecutablePath() { } } +void DYLDRendezvous::Rendezvous::DumpToLog(Log *log, const char *label) { + LLDB_LOGF(log, "%s Rendezvous: version = %" PRIu64 ", map_addr = 0x%16.16" + PRIx64 ", brk = 0x%16.16" PRIx64 ", state = %" PRIu64 + " (%s), ldbase = 0x%16.16" PRIx64, label ? label : "", version, + map_addr, brk, state, StateToCStr((RendezvousState)state), ldbase); +} + bool DYLDRendezvous::Resolve() { Log *log = GetLog(LLDBLog::DynamicLoader); @@ -176,6 +209,9 @@ bool DYLDRendezvous::Resolve() { m_previous = m_current; m_current = info; + m_previous.DumpToLog(log, "m_previous"); + m_current.DumpToLog(log, "m_current "); + if (m_current.map_addr == 0) return false; @@ -217,6 +253,75 @@ DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { break; case eAdd: + // If the main executable or a shared library defines a publicly visible + // symbol named "_r_debug", then it will cause problems once the executable + // that contains the symbol is loaded into the process. The correct + // "_r_debug" structure is currently found by LLDB by looking through + // the .dynamic section in the main executable and finding the DT_DEBUG tag + // entry. + // + // An issue comes up if someone defines another publicly visible "_r_debug" + // struct in their program. Sample code looks like: + // + // #include <link.h> + // r_debug _r_debug; + // + // If code like this is in an executable or shared library, this creates a + // new "_r_debug" structure and it causes problems once the executable is + // loaded due to the way symbol lookups happen in linux: the shared library + // list from _r_debug.r_map will be searched for a symbol named "_r_debug" + // and the first match will be the new version that is used. The dynamic + // loader is always last in this list. So at some point the dynamic loader + // will start updating the copy of "_r_debug" that gets found first. The + // issue is that LLDB will only look at the copy that is pointed to by the + // DT_DEBUG entry, or the initial version from the ld.so binary. + // + // Steps that show the problem are: + // + // - LLDB finds the "_r_debug" structure via the DT_DEBUG entry in the + // .dynamic section and this points to the "_r_debug" in ld.so + // - ld.so uodates its copy of "_r_debug" with "state = eAdd" before it + // loads the dependent shared libraries for the main executable and + // any dependencies of all shared libraries from the executable's list + // and ld.so code calls the debugger notification function + // that LLDB has set a breakpoint on. + // - LLDB hits the breakpoint and the breakpoint has a callback function + // where we read the _r_debug.state (eAdd) state and we do nothing as the + // "eAdd" state indicates that the shared libraries are about to be added. + // - ld.so finishes loading the main executable and any dependent shared + // libraries and it will update the "_r_debug.state" member with a + // "eConsistent", but it now updates the "_r_debug" in the a.out program + // and it calls the debugger notification function. + // - lldb hits the notification breakpoint and checks the ld.so copy of + // "_r_debug.state" which still has a state of "eAdd", but LLDB needs to see a + // "eConsistent" state to trigger the shared libraries to get loaded into + // the debug session, but LLDB the ld.so _r_debug.state which still + // contains "eAdd" and doesn't do anyhing and library load is missed. + // The "_r_debug" in a.out has the state set correctly to "eConsistent" + // but LLDB is still looking at the "_r_debug" from ld.so. + // + // So if we detect two "eAdd" states in a row, we assume this is the issue + // and we now load shared libraries correctly and will emit a log message + // in the "log enable lldb dyld" log channel which states there might be + // multiple "_r_debug" structs causing problems. + // + // The correct solution is that no one should be adding a duplicate + // publicly visible "_r_debug" symbols to their binaries, but we have + // programs that are doing this already and since it can be done, we should + // be able to work with this and keep debug sessions working as expected. + // + // If a user includes the <link.h> file, they can just use the existing + // "_r_debug" structure as it is defined in this header file as "extern + // struct r_debug _r_debug;" and no local copies need to be made. + if (m_previous.state == eAdd) { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOG(log, "DYLDRendezvous::GetAction() found two eAdd states in a " + "row, check process for multiple \"_r_debug\" symbols. " + "Returning eAddModules to ensure shared libraries get loaded " + "correctly"); + return eAddModules; + } + return eNoAction; case eDelete: return eNoAction; } @@ -225,7 +330,9 @@ DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { } bool DYLDRendezvous::UpdateSOEntriesFromRemote() { - auto action = GetAction(); + const auto action = GetAction(); + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOG(log, "{0} action = {1}", LLVM_PRETTY_FUNCTION, ActionToCStr(action)); if (action == eNoAction) return false; @@ -263,7 +370,10 @@ bool DYLDRendezvous::UpdateSOEntriesFromRemote() { bool DYLDRendezvous::UpdateSOEntries() { m_added_soentries.clear(); m_removed_soentries.clear(); - switch (GetAction()) { + const auto action = GetAction(); + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOG(log, "{0} action = {1}", LLVM_PRETTY_FUNCTION, ActionToCStr(action)); + switch (action) { case eTakeSnapshot: m_soentries.clear(); return TakeSnapshot(m_soentries); @@ -372,7 +482,7 @@ bool DYLDRendezvous::RemoveSOEntriesFromRemote( // Only add shared libraries and not the executable. if (!SOEntryIsMainExecutable(entry)) { - auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry); + auto pos = llvm::find(m_soentries, entry); if (pos == m_soentries.end()) return false; @@ -439,6 +549,7 @@ bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) { switch (triple.getOS()) { case llvm::Triple::FreeBSD: case llvm::Triple::NetBSD: + case llvm::Triple::OpenBSD: return entry.file_spec == m_exe_file_spec; case llvm::Triple::Linux: if (triple.isAndroid()) @@ -600,16 +711,19 @@ bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field, target.GetImages().FindSymbolsWithNameAndType(ConstString(name), eSymbolTypeAny, list); if (list.IsEmpty()) - return false; + return false; Address address = list[0].symbol->GetAddress(); - addr_t addr = address.GetLoadAddress(&target); - if (addr == LLDB_INVALID_ADDRESS) - return false; + address.SetOffset(address.GetOffset() + field * sizeof(uint32_t)); + // Read from target memory as this allows us to try process memory and + // fallback to reading from read only sections from the object files. Here we + // are reading read only data from libpthread.so to find data in the thread + // specific area for the data we want and this won't be saved into process + // memory due to it being read only. Status error; - value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory( - addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error); + value = + target.ReadUnsignedIntegerFromMemory(address, sizeof(uint32_t), 0, error); if (error.Fail()) return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index fc1dd6921455..b8bdf78fbdfa 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -21,6 +21,7 @@ using lldb_private::LoadedModuleInfoList; namespace lldb_private { +class Log; class Process; } @@ -28,9 +29,81 @@ class Process; /// Interface to the runtime linker. /// /// A structure is present in a processes memory space which is updated by the -/// runtime liker each time a module is loaded or unloaded. This class +/// dynamic linker each time a module is loaded or unloaded. This class /// provides an interface to this structure and maintains a consistent /// snapshot of the currently loaded modules. +/// +/// In the dynamic loader sources, this structure has a type of "r_debug" and +/// the name of the structure us "_r_debug". The structure looks like: +/// +/// struct r_debug { +/// // Version number for this protocol. +/// int r_version; +/// // Head of the chain of loaded objects. +/// struct link_map *r_map; +/// // The address the debugger should set a breakpoint at in order to get +/// // notified when shared libraries are added or removed +/// uintptr_t r_brk; +/// // This state value describes the mapping change taking place when the +/// // 'r_brk' address is called. +/// enum { +/// RT_CONSISTENT, // Mapping change is complete. +/// RT_ADD, // Beginning to add a new object. +/// RT_DELETE, // Beginning to remove an object mapping. +/// } r_state; +/// // Base address the linker is loaded at. +/// uintptr_t r_ldbase; +/// }; +/// +/// The dynamic linker then defines a global variable using this type named +/// "_r_debug": +/// +/// r_debug _r_debug; +/// +/// The DYLDRendezvous class defines a local version of this structure named +/// DYLDRendezvous::Rendezvous. See the definition inside the class definition +/// for DYLDRendezvous. +/// +/// This structure can be located by looking through the .dynamic section in +/// the main executable and finding the DT_DEBUG tag entry. This value starts +/// out with a value of zero when the program first is initially loaded, but +/// the address of the "_r_debug" structure from ld.so is filled in by the +/// dynamic loader during program initialization code in ld.so prior to loading +/// or unloading and shared libraries. +/// +/// The dynamic loader will update this structure as shared libraries are +/// loaded and will call a specific function that LLDB knows to set a +/// breakpoint on (from _r_debug.r_brk) so LLDB will find out when shared +/// libraries are loaded or unloaded. Each time this breakpoint is hit, LLDB +/// looks at the contents of this structure and the contents tell LLDB what +/// needs to be done. +/// +/// Currently we expect the "state" in this structure to change as things +/// happen. +/// +/// When any shared libraries are loaded the following happens: +/// - _r_debug.r_map is updated with the new shared libraries. This is a +/// doubly linked list of "link_map *" entries. +/// - _r_debug.r_state is set to RT_ADD and the debugger notification +/// function is called notifying the debugger that shared libraries are +/// about to be added, but are not yet ready for use. +/// - Once the the shared libraries are fully loaded, _r_debug.r_state is set +/// to RT_CONSISTENT and the debugger notification function is called again +/// notifying the debugger that shared libraries are ready for use. +/// DYLDRendezvous must remember that the previous state was RT_ADD when it +/// receives a RT_CONSISTENT in order to know to add libraries +/// +/// When any shared libraries are unloaded the following happens: +/// - _r_debug.r_map is updated and the unloaded libraries are removed. +/// - _r_debug.r_state is set to RT_DELETE and the debugger notification +/// function is called notifying the debugger that shared libraries are +/// about to be removed. +/// - Once the the shared libraries are removed _r_debug.r_state is set to +/// RT_CONSISTENT and the debugger notification function is called again +/// notifying the debugger that shared libraries have been removed. +/// DYLDRendezvous must remember that the previous state was RT_DELETE when +/// it receives a RT_CONSISTENT in order to know to remove libraries +/// class DYLDRendezvous { // This structure is used to hold the contents of the debug rendezvous @@ -45,6 +118,8 @@ class DYLDRendezvous { lldb::addr_t ldbase = 0; Rendezvous() = default; + + void DumpToLog(lldb_private::Log *log, const char *label); }; /// Locates the address of the rendezvous structure. It updates @@ -126,8 +201,15 @@ public: /// Constants describing the state of the rendezvous. /// + /// These values are defined to match the r_debug.r_state enum from the + /// actual dynamic loader sources. + /// /// \see GetState(). - enum RendezvousState { eConsistent, eAdd, eDelete }; + enum RendezvousState { + eConsistent, // RT_CONSISTENT + eAdd, // RT_ADD + eDelete // RT_DELETE + }; /// Structure representing the shared objects currently loaded into the /// inferior process. @@ -276,6 +358,9 @@ protected: eRemoveModules }; + static const char *StateToCStr(RendezvousState state); + static const char *ActionToCStr(RendezvousAction action); + /// Returns the current action to be taken given the current and previous /// state RendezvousAction GetAction() const; diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index b4b38a88e1b9..9baf86da4dc7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -53,7 +53,8 @@ DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, process->GetTarget().GetArchitecture().GetTriple(); if (triple_ref.getOS() == llvm::Triple::FreeBSD || triple_ref.getOS() == llvm::Triple::Linux || - triple_ref.getOS() == llvm::Triple::NetBSD) + triple_ref.getOS() == llvm::Triple::NetBSD || + triple_ref.getOS() == llvm::Triple::OpenBSD) create = true; } @@ -337,29 +338,20 @@ bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { }; ModuleSP interpreter = LoadInterpreterModule(); - if (!interpreter) { - FileSpecList containingModules; + FileSpecList containingModules; + if (interpreter) + containingModules.Append(interpreter->GetFileSpec()); + else containingModules.Append( m_process->GetTarget().GetExecutableModulePointer()->GetFileSpec()); - dyld_break = target.CreateBreakpoint( - &containingModules, /*containingSourceFiles=*/nullptr, - DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC, - /*m_offset=*/0, - /*skip_prologue=*/eLazyBoolNo, - /*internal=*/true, - /*request_hardware=*/false); - } else { - FileSpecList containingModules; - containingModules.Append(interpreter->GetFileSpec()); - dyld_break = target.CreateBreakpoint( - &containingModules, /*containingSourceFiles=*/nullptr, - DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC, - /*m_offset=*/0, - /*skip_prologue=*/eLazyBoolNo, - /*internal=*/true, - /*request_hardware=*/false); - } + dyld_break = target.CreateBreakpoint( + &containingModules, /*containingSourceFiles=*/nullptr, + DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC, + /*m_offset=*/0, + /*skip_prologue=*/eLazyBoolNo, + /*internal=*/true, + /*request_hardware=*/false); } if (dyld_break->GetNumResolvedLocations() != 1) { @@ -420,6 +412,11 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { if (!m_rendezvous.Resolve()) return; + // The rendezvous class doesn't enumerate the main module, so track that + // ourselves here. + ModuleSP executable = GetTargetExecutable(); + m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); + DYLDRendezvous::iterator I; DYLDRendezvous::iterator E; @@ -441,6 +438,14 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { m_initial_modules_added = true; } for (; I != E; ++I) { + // Don't load a duplicate copy of ld.so if we have already loaded it + // earlier in LoadInterpreterModule. If we instead loaded then unloaded it + // later, the section information for ld.so would be removed. That + // information is required for placing breakpoints on Arm/Thumb systems. + if ((m_interpreter_module.lock() != nullptr) && + (I->base_addr == m_interpreter_base)) + continue; + ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (!module_sp.get()) @@ -454,15 +459,6 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { } else if (module_sp == interpreter_sp) { // Module already loaded. continue; - } else { - // If this is a duplicate instance of ld.so, unload it. We may end - // up with it if we load it via a different path than before - // (symlink vs real path). - // TODO: remove this once we either fix library matching or avoid - // loading the interpreter when setting the rendezvous breakpoint. - UnloadSections(module_sp); - loaded_modules.Remove(module_sp); - continue; } } @@ -727,41 +723,66 @@ lldb::addr_t DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) { + Log *log = GetLog(LLDBLog::DynamicLoader); auto it = m_loaded_modules.find(module_sp); - if (it == m_loaded_modules.end()) + if (it == m_loaded_modules.end()) { + LLDB_LOGF( + log, "GetThreadLocalData error: module(%s) not found in loaded modules", + module_sp->GetObjectName().AsCString()); return LLDB_INVALID_ADDRESS; + } addr_t link_map = it->second; - if (link_map == LLDB_INVALID_ADDRESS) + if (link_map == LLDB_INVALID_ADDRESS || link_map == 0) { + LLDB_LOGF(log, + "GetThreadLocalData error: invalid link map address=0x%" PRIx64, + link_map); return LLDB_INVALID_ADDRESS; + } const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo(); - if (!metadata.valid) + if (!metadata.valid) { + LLDB_LOGF(log, + "GetThreadLocalData error: fail to read thread info metadata"); return LLDB_INVALID_ADDRESS; + } + + LLDB_LOGF(log, + "GetThreadLocalData info: link_map=0x%" PRIx64 + ", thread info metadata: " + "modid_offset=0x%" PRIx32 ", dtv_offset=0x%" PRIx32 + ", tls_offset=0x%" PRIx32 ", dtv_slot_size=%" PRIx32 "\n", + link_map, metadata.modid_offset, metadata.dtv_offset, + metadata.tls_offset, metadata.dtv_slot_size); // Get the thread pointer. addr_t tp = thread->GetThreadPointer(); - if (tp == LLDB_INVALID_ADDRESS) + if (tp == LLDB_INVALID_ADDRESS) { + LLDB_LOGF(log, "GetThreadLocalData error: fail to read thread pointer"); return LLDB_INVALID_ADDRESS; + } // Find the module's modid. int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit int64_t modid = ReadUnsignedIntWithSizeInBytes( link_map + metadata.modid_offset, modid_size); - if (modid == -1) + if (modid == -1) { + LLDB_LOGF(log, "GetThreadLocalData error: fail to read modid"); return LLDB_INVALID_ADDRESS; + } // Lookup the DTV structure for this thread. addr_t dtv_ptr = tp + metadata.dtv_offset; addr_t dtv = ReadPointer(dtv_ptr); - if (dtv == LLDB_INVALID_ADDRESS) + if (dtv == LLDB_INVALID_ADDRESS) { + LLDB_LOGF(log, "GetThreadLocalData error: fail to read dtv"); return LLDB_INVALID_ADDRESS; + } // Find the TLS block for this module. addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid; addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset); - Log *log = GetLog(LLDBLog::DynamicLoader); LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::Performed TLS lookup: " "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 @@ -769,9 +790,10 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, module_sp->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block); - if (tls_block == LLDB_INVALID_ADDRESS) + if (tls_block == LLDB_INVALID_ADDRESS) { + LLDB_LOGF(log, "GetThreadLocalData error: fail to read tls_block"); return LLDB_INVALID_ADDRESS; - else + } else return tls_block + tls_file_addr; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 2826b102625f..5d109feb3d39 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -902,7 +902,6 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( // We want that 'to' is actually complete after this function so let's // tell the ASTImporter that 'to' was imported from 'from'. MapImported(from, to); - ASTImporter::Imported(from, to); Log *log = GetLog(LLDBLog::Expressions); @@ -1028,7 +1027,7 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, // Some decls shouldn't be tracked here because they were not created by // copying 'from' to 'to'. Just exit early for those. if (m_decls_to_ignore.count(to)) - return clang::ASTImporter::Imported(from, to); + return; // Transfer module ownership information. auto *from_source = llvm::dyn_cast_or_null<ClangExternalASTSourceCallbacks>( @@ -1081,12 +1080,6 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID) to_context_md->setOrigin(to, origin); - ImporterDelegateSP direct_completer = - m_main.GetDelegate(&to->getASTContext(), origin.ctx); - - if (direct_completer.get() != this) - direct_completer->ASTImporter::Imported(origin.decl, to); - LLDB_LOG(log, " [ClangASTImporter] Propagated origin " "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to " diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 5d7e1252038d..79dd306f7627 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -201,19 +201,17 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { LLDB_LOG(log, " CTD Searching namespace {0} in module {1}", item.second.GetName(), item.first->GetFileSpec().GetFilename()); - TypeList types; - ConstString name(decl->getName()); - item.first->FindTypesInNamespace(name, item.second, UINT32_MAX, types); - - for (uint32_t ti = 0, te = types.GetSize(); ti != te; ++ti) { - lldb::TypeSP type = types.GetTypeAtIndex(ti); - - if (!type) - continue; + // Create a type matcher using the CompilerDeclContext for the namespace + // as the context (item.second) and search for the name inside of this + // context. + TypeQuery query(item.second, name); + TypeResults results; + item.first->FindTypes(query, results); - CompilerType clang_type(type->GetFullCompilerType()); + for (const lldb::TypeSP &type_sp : results.GetTypeMap().Types()) { + CompilerType clang_type(type_sp->GetFullCompilerType()); if (!ClangUtil::IsClangType(clang_type)) continue; @@ -233,24 +231,15 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { } } } else { - TypeList types; - - ConstString name(decl->getName()); - const ModuleList &module_list = m_target->GetImages(); + // Create a type matcher using a CompilerDecl. Each TypeSystem class knows + // how to fill out a CompilerContext array using a CompilerDecl. + TypeQuery query(CompilerDecl(m_clang_ast_context, (void *)decl)); + TypeResults results; + module_list.FindTypes(nullptr, query, results); + for (const lldb::TypeSP &type_sp : results.GetTypeMap().Types()) { - bool exact_match = false; - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_list.FindTypes(nullptr, name, exact_match, UINT32_MAX, - searched_symbol_files, types); - - for (uint32_t ti = 0, te = types.GetSize(); ti != te; ++ti) { - lldb::TypeSP type = types.GetTypeAtIndex(ti); - - if (!type) - continue; - - CompilerType clang_type(type->GetFullCompilerType()); + CompilerType clang_type(type_sp->GetFullCompilerType()); if (!ClangUtil::IsClangType(clang_type)) continue; @@ -263,13 +252,6 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { TagDecl *candidate_tag_decl = const_cast<TagDecl *>(tag_type->getDecl()); - // We have found a type by basename and we need to make sure the decl - // contexts are the same before we can try to complete this type with - // another - if (!TypeSystemClang::DeclsAreEquivalent(const_cast<TagDecl *>(decl), - candidate_tag_decl)) - continue; - if (TypeSystemClang::GetCompleteDecl(&candidate_tag_decl->getASTContext(), candidate_tag_decl)) return candidate_tag_decl; @@ -589,8 +571,8 @@ bool ClangASTSource::IgnoreName(const ConstString name, // The ClangASTSource is not responsible for finding $-names. return name_string_ref.empty() || - (ignore_all_dollar_names && name_string_ref.startswith("$")) || - name_string_ref.startswith("_$"); + (ignore_all_dollar_names && name_string_ref.starts_with("$")) || + name_string_ref.starts_with("_$"); } void ClangASTSource::FindExternalVisibleDecls( @@ -614,41 +596,40 @@ void ClangASTSource::FindExternalVisibleDecls( if (context.m_found_type) return; - TypeList types; - const bool exact_match = true; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - if (module_sp && namespace_decl) - module_sp->FindTypesInNamespace(name, namespace_decl, 1, types); - else { - m_target->GetImages().FindTypes(module_sp.get(), name, exact_match, 1, - searched_symbol_files, types); + lldb::TypeSP type_sp; + TypeResults results; + if (module_sp && namespace_decl) { + // Match the name in the specified decl context. + TypeQuery query(namespace_decl, name, TypeQueryOptions::e_find_one); + module_sp->FindTypes(query, results); + type_sp = results.GetFirstType(); + } else { + // Match the exact name of the type at the root level. + TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match | + TypeQueryOptions::e_find_one); + m_target->GetImages().FindTypes(nullptr, query, results); + type_sp = results.GetFirstType(); } - if (size_t num_types = types.GetSize()) { - for (size_t ti = 0; ti < num_types; ++ti) { - lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); - - if (log) { - const char *name_string = type_sp->GetName().GetCString(); - - LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\": {1}", name, - (name_string ? name_string : "<anonymous>")); - } + if (type_sp) { + if (log) { + const char *name_string = type_sp->GetName().GetCString(); - CompilerType full_type = type_sp->GetFullCompilerType(); + LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\": {1}", name, + (name_string ? name_string : "<anonymous>")); + } - CompilerType copied_clang_type(GuardedCopyType(full_type)); + CompilerType full_type = type_sp->GetFullCompilerType(); - if (!copied_clang_type) { - LLDB_LOG(log, " CAS::FEVD - Couldn't export a type"); + CompilerType copied_clang_type(GuardedCopyType(full_type)); - continue; - } + if (!copied_clang_type) { + LLDB_LOG(log, " CAS::FEVD - Couldn't export a type"); + } else { context.AddTypeDecl(copied_clang_type); context.m_found_type = true; - break; } } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 6fbc0bb22f82..2d306b42760b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1369,7 +1369,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (!namespace_decl) SearchPersistenDecls(context, name); - if (name.GetStringRef().startswith("$") && !namespace_decl) { + if (name.GetStringRef().starts_with("$") && !namespace_decl) { if (name == "$__lldb_class") { LookUpLldbClass(context); return; @@ -1385,7 +1385,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } // any other $__lldb names should be weeded out now - if (name.GetStringRef().startswith("$__lldb")) + if (name.GetStringRef().starts_with("$__lldb")) return; // No ParserVars means we can't do register or variable lookup. @@ -1400,7 +1400,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( return; } - assert(name.GetStringRef().startswith("$")); + assert(name.GetStringRef().starts_with("$")); llvm::StringRef reg_name = name.GetStringRef().substr(1); if (m_parser_vars->m_exe_ctx.GetRegisterContext()) { diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index 9430ab5b0464..d8d519693f10 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -53,7 +53,7 @@ class ClangPersistentVariables; /// struct so that it can be passed to the JITted version of the IR. /// /// Fourth and finally, it "dematerializes" the struct after the JITted code -/// has has executed, placing the new values back where it found the old ones. +/// has executed, placing the new values back where it found the old ones. class ClangExpressionDeclMap : public ClangASTSource { public: /// Constructor diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index f3d6ea26b30d..574d661e2a21 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -71,7 +71,6 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/File.h" @@ -576,6 +575,7 @@ ClangExpressionParser::ClangExpressionParser( lang_opts.GNUMode = true; lang_opts.GNUKeywords = true; lang_opts.CPlusPlus11 = true; + lang_opts.BuiltinHeadersInSystemModules = true; // The Darwin libc expects this macro to be set. lang_opts.GNUCVersion = 40201; @@ -834,13 +834,13 @@ public: case CodeCompletionResult::RK_Declaration: return !( Result.Declaration->getIdentifier() && - Result.Declaration->getIdentifier()->getName().startswith(Filter)); + Result.Declaration->getIdentifier()->getName().starts_with(Filter)); case CodeCompletionResult::RK_Keyword: - return !StringRef(Result.Keyword).startswith(Filter); + return !StringRef(Result.Keyword).starts_with(Filter); case CodeCompletionResult::RK_Macro: - return !Result.Macro->getName().startswith(Filter); + return !Result.Macro->getName().starts_with(Filter); case CodeCompletionResult::RK_Pattern: - return !StringRef(Result.Pattern->getAsString()).startswith(Filter); + return !StringRef(Result.Pattern->getAsString()).starts_with(Filter); } // If we trigger this assert or the above switch yields a warning, then // CodeCompletionResult has been enhanced with more kinds of completion @@ -904,7 +904,7 @@ private: } // We also filter some internal lldb identifiers here. The user // shouldn't see these. - if (llvm::StringRef(ToInsert).startswith("$__lldb_")) + if (llvm::StringRef(ToInsert).starts_with("$__lldb_")) return std::nullopt; if (ToInsert.empty()) return std::nullopt; @@ -1078,13 +1078,14 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, // While parsing the Sema will call this consumer with the provided // completion suggestions. if (completion_consumer) { - auto main_file = source_mgr.getFileEntryForID(source_mgr.getMainFileID()); + auto main_file = + source_mgr.getFileEntryRefForID(source_mgr.getMainFileID()); auto &PP = m_compiler->getPreprocessor(); // Lines and columns start at 1 in Clang, but code completion positions are // indexed from 0, so we need to add 1 to the line and column here. ++completion_line; ++completion_column; - PP.SetCodeCompletionPoint(main_file, completion_line, completion_column); + PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column); } ASTConsumer *ast_transformer = diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 74c1212791be..68bdd96e8adb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -27,7 +27,6 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" @@ -873,7 +872,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, } lldb::addr_t ClangUserExpression::GetCppObjectPointer( - lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err) { + lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) { auto valobj_sp = GetObjectPointerValueObject(std::move(frame_sp), object_name, err); @@ -890,9 +889,9 @@ lldb::addr_t ClangUserExpression::GetCppObjectPointer( lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (ret == LLDB_INVALID_ADDRESS) { - err.SetErrorStringWithFormat( - "Couldn't load '%s' because its value couldn't be evaluated", - object_name.AsCString()); + err.SetErrorStringWithFormatv( + "Couldn't load '{0}' because its value couldn't be evaluated", + object_name); return LLDB_INVALID_ADDRESS; } @@ -911,19 +910,18 @@ bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, if (!frame_sp) return true; - ConstString object_name; - - if (m_in_cplusplus_method) { - object_name.SetCString("this"); - } else if (m_in_objectivec_method) { - object_name.SetCString("self"); - } else { + if (!m_in_cplusplus_method && !m_in_objectivec_method) { diagnostic_manager.PutString( eDiagnosticSeverityError, "need object pointer but don't know the language"); return false; } + static constexpr llvm::StringLiteral g_cplusplus_object_name("this"); + static constexpr llvm::StringLiteral g_objc_object_name("self"); + llvm::StringRef object_name = + m_in_cplusplus_method ? g_cplusplus_object_name : g_objc_object_name; + Status object_ptr_error; if (m_ctx_obj) { @@ -943,14 +941,14 @@ bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, } if (!object_ptr_error.Success()) { - exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf( - "warning: `%s' is not accessible (substituting 0). %s\n", - object_name.AsCString(), object_ptr_error.AsCString()); + exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Format( + "warning: `{0}' is not accessible (substituting 0). {1}\n", + object_name, object_ptr_error.AsCString()); object_ptr = 0; } if (m_in_objectivec_method) { - ConstString cmd_name("_cmd"); + static constexpr llvm::StringLiteral cmd_name("_cmd"); cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 0fbeff7f6143..7a8c095f6118 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -204,7 +204,7 @@ private: bool for_completion); lldb::addr_t GetCppObjectPointer(lldb::StackFrameSP frame, - ConstString &object_name, Status &err); + llvm::StringRef object_name, Status &err); /// Defines how the current expression should be wrapped. ClangExpressionSourceCode::WrapKind GetWrapKind() const; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 371605d427ad..56d6cf19ee4c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -17,7 +17,6 @@ #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Host/Host.h" #include "lldb/Target/ExecutionContext.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index 847dab6592b8..62443d1290dc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -72,7 +72,7 @@ bool CppModuleConfiguration::analyzeFile(const FileSpec &f, // path. Ignore subdirectories such as /c++/v1/experimental as those don't // need to be specified in the header search. if (libcpp_regex.match(f.GetPath()) && - parent_path(posix_dir, Style::posix).endswith("c++")) { + parent_path(posix_dir, Style::posix).ends_with("c++")) { if (!m_std_inc.TrySet(posix_dir)) return false; if (triple.str().empty()) diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp index cd7d1ff6148b..bc0f5993aad0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp @@ -273,7 +273,7 @@ protected: PointerType *GetI8PtrTy() { if (!m_i8ptr_ty) - m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext()); + m_i8ptr_ty = llvm::PointerType::getUnqual(m_module.getContext()); return m_i8ptr_ty; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 1b7e86bb187f..597873af8b2a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -154,9 +154,10 @@ clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { /// Returns true iff the mangled symbol is for a static guard variable. static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol, bool check_ms_abi = true) { - bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable + bool result = + mangled_symbol.starts_with("_ZGV"); // Itanium ABI guard variable if (check_ms_abi) - result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI + result |= mangled_symbol.ends_with("@4IA"); // Microsoft ABI return result; } @@ -404,7 +405,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, Type *ns_str_ty = ns_str->getType(); - Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); + Type *i8_ptr_ty = PointerType::getUnqual(m_module->getContext()); Type *i32_ty = Type::getInt32Ty(m_module->getContext()); Type *i8_ty = Type::getInt8Ty(m_module->getContext()); @@ -720,8 +721,9 @@ bool IRForTarget::RewriteObjCConstStrings() { static bool IsObjCSelectorRef(Value *value) { GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); - return !(!global_variable || !global_variable->hasName() || - !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")); + return !( + !global_variable || !global_variable->hasName() || + !global_variable->getName().starts_with("OBJC_SELECTOR_REFERENCES_")); } // This function does not report errors; its callers are responsible. @@ -801,11 +803,11 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { // is uint8_t* // Type *sel_type = StructType::get(m_module->getContext()); // Type *sel_ptr_type = PointerType::getUnqual(sel_type); - Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); + Type *sel_ptr_type = PointerType::getUnqual(m_module->getContext()); Type *type_array[1]; - type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); + type_array[0] = llvm::PointerType::getUnqual(m_module->getContext()); ArrayRef<Type *> srN_arg_types(type_array, 1); @@ -940,7 +942,7 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) { llvm::StringRef alloc_name = alloc->getName(); - if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) { + if (alloc_name.starts_with("$") && !alloc_name.starts_with("$__lldb")) { if (alloc_name.find_first_of("0123456789") == 1) { LLDB_LOG(log, "Rejecting a numeric persistent variable."); @@ -1017,7 +1019,7 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { const Type *value_type = nullptr; - if (name.startswith("$")) { + if (name.starts_with("$")) { // The $__lldb_expr_result name indicates the return value has allocated // as a static variable. Per the comment at // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static @@ -1223,7 +1225,7 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name, static_cast<void *>(DeclForGlobal(&global_var))); - if (global_name.startswith("OBJC_IVAR")) { + if (global_name.starts_with("OBJC_IVAR")) { if (!HandleSymbol(&global_var)) { m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C " "indirect ivar symbol {0}\n", @@ -1641,14 +1643,6 @@ bool IRForTarget::runOnModule(Module &llvm_module) { } } - llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); - - m_reloc_placeholder = new llvm::GlobalVariable( - (*m_module), int8_ty, false /* IsConstant */, - GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty), - "reloc_placeholder", nullptr /* InsertBefore */, - GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */); - //////////////////////////////////////////////////////////// // Replace $__lldb_expr_result with a persistent variable // diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h index eb93952e2b3c..a924187ba04c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -111,43 +111,6 @@ private: /// True on success; false otherwise. bool FixFunctionLinkage(llvm::Function &llvm_function); - /// A module-level pass to replace all function pointers with their - /// integer equivalents. - - /// The top-level pass implementation - /// - /// \param[in] llvm_function - /// The function currently being processed. - /// - /// \return - /// True on success; false otherwise. - bool HasSideEffects(llvm::Function &llvm_function); - - /// A function-level pass to check whether the function has side - /// effects. - - /// Get the address of a function, and a location to put the complete Value - /// of the function if one is available. - /// - /// \param[in] function - /// The function to find the location of. - /// - /// \param[out] ptr - /// The location of the function in the target. - /// - /// \param[out] name - /// The resolved name of the function (matters for intrinsics). - /// - /// \param[out] value_ptr - /// A variable to put the function's completed Value* in, or NULL - /// if the Value* shouldn't be stored anywhere. - /// - /// \return - /// The pointer. - LookupResult GetFunctionAddress(llvm::Function *function, uint64_t &ptr, - lldb_private::ConstString &name, - llvm::Constant **&value_ptr); - /// A function-level pass to take the generated global value /// $__lldb_expr_result and make it into a persistent variable. Also see /// ASTResultSynthesizer. @@ -170,30 +133,6 @@ public: private: clang::NamedDecl *DeclForGlobal(llvm::GlobalValue *global); - /// Set the constant result variable m_const_result to the provided - /// constant, assuming it can be evaluated. The result variable will be - /// reset to NULL later if the expression has side effects. - /// - /// \param[in] initializer - /// The constant initializer for the variable. - /// - /// \param[in] name - /// The name of the result variable. - /// - /// \param[in] type - /// The Clang type of the result variable. - void MaybeSetConstantResult(llvm::Constant *initializer, - lldb_private::ConstString name, - lldb_private::TypeFromParser type); - - /// If the IR represents a cast of a variable, set m_const_result to the - /// result of the cast. The result variable will be reset to - /// NULL latger if the expression has side effects. - /// - /// \param[in] type - /// The Clang type of the result variable. - void MaybeSetCastResult(lldb_private::TypeFromParser type); - /// The top-level pass implementation /// /// \param[in] llvm_function @@ -409,15 +348,9 @@ private: lldb_private::Stream &m_error_stream; /// The execution unit containing the IR being created. lldb_private::IRExecutionUnit &m_execution_unit; - /// If non-NULL, the store instruction that writes to the result variable. If - /// m_has_side_effects is true, this is NULL. - llvm::StoreInst *m_result_store = nullptr; /// True if the function's result in the AST is a pointer (see comments in /// ASTResultSynthesizer::SynthesizeBodyResult) bool m_result_is_pointer = false; - /// A placeholder that will be replaced by a pointer to the final location of - /// the static allocation. - llvm::GlobalVariable *m_reloc_placeholder = nullptr; class FunctionValueCache { public: @@ -454,13 +387,6 @@ private: FunctionValueCache &value_maker, FunctionValueCache &entry_instruction_finder, lldb_private::Stream &error_stream); - - /// Commit the allocation in m_data_allocator and use its final location to - /// replace m_reloc_placeholder. - /// - /// \return - /// True on success; false otherwise - bool CompleteDataAllocation(); }; #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRFORTARGET_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp index a67cc8e10c17..da59855a9f16 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp @@ -62,9 +62,9 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, clang::DeclContext *context = const_cast<DeclContext *>(m_decl_context); if (extern_c) { - context = LinkageSpecDecl::Create( - ast, context, SourceLocation(), SourceLocation(), - clang::LinkageSpecDecl::LanguageIDs::lang_c, false); + context = LinkageSpecDecl::Create(ast, context, SourceLocation(), + SourceLocation(), + clang::LinkageSpecLanguageIDs::C, false); // FIXME: The LinkageSpecDecl here should be added to m_decl_context. } diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp index 44070b422220..a09c89103b0e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp @@ -9,23 +9,14 @@ #include "InstrumentationRuntimeASan.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Expression/UserExpression.h" -#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" -#include "lldb/Target/InstrumentationRuntimeStopInfo.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" +#include "lldb/Target/Process.h" #include "lldb/Utility/RegularExpression.h" -#include "lldb/Utility/Stream.h" -#include "llvm/ADT/StringSwitch.h" +#include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h" using namespace lldb; using namespace lldb_private; @@ -69,173 +60,6 @@ bool InstrumentationRuntimeASan::CheckIfRuntimeIsValid( return symbol != nullptr; } -const char *address_sanitizer_retrieve_report_data_prefix = R"( -extern "C" -{ -int __asan_report_present(); -void *__asan_get_report_pc(); -void *__asan_get_report_bp(); -void *__asan_get_report_sp(); -void *__asan_get_report_address(); -const char *__asan_get_report_description(); -int __asan_get_report_access_type(); -size_t __asan_get_report_access_size(); -} -)"; - -const char *address_sanitizer_retrieve_report_data_command = R"( -struct { - int present; - int access_type; - void *pc; - void *bp; - void *sp; - void *address; - size_t access_size; - const char *description; -} t; - -t.present = __asan_report_present(); -t.access_type = __asan_get_report_access_type(); -t.pc = __asan_get_report_pc(); -t.bp = __asan_get_report_bp(); -t.sp = __asan_get_report_sp(); -t.address = __asan_get_report_address(); -t.access_size = __asan_get_report_access_size(); -t.description = __asan_get_report_description(); -t -)"; - -StructuredData::ObjectSP InstrumentationRuntimeASan::RetrieveReportData() { - ProcessSP process_sp = GetProcessSP(); - if (!process_sp) - return StructuredData::ObjectSP(); - - ThreadSP thread_sp = - process_sp->GetThreadList().GetExpressionExecutionThread(); - StackFrameSP frame_sp = - thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); - - if (!frame_sp) - return StructuredData::ObjectSP(); - - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetTryAllThreads(true); - options.SetStopOthers(true); - options.SetIgnoreBreakpoints(true); - options.SetTimeout(process_sp->GetUtilityExpressionTimeout()); - options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); - options.SetAutoApplyFixIts(false); - options.SetLanguage(eLanguageTypeObjC_plus_plus); - - ValueObjectSP return_value_sp; - ExecutionContext exe_ctx; - Status eval_error; - frame_sp->CalculateExecutionContext(exe_ctx); - ExpressionResults result = UserExpression::Evaluate( - exe_ctx, options, address_sanitizer_retrieve_report_data_command, "", - return_value_sp, eval_error); - if (result != eExpressionCompleted) { - StreamString ss; - ss << "cannot evaluate AddressSanitizer expression:\n"; - ss << eval_error.AsCString(); - Debugger::ReportWarning(ss.GetString().str(), - process_sp->GetTarget().GetDebugger().GetID()); - return StructuredData::ObjectSP(); - } - - int present = return_value_sp->GetValueForExpressionPath(".present") - ->GetValueAsUnsigned(0); - if (present != 1) - return StructuredData::ObjectSP(); - - addr_t pc = - return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0); - /* commented out because rdar://problem/18533301 - addr_t bp = - return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0); - addr_t sp = - return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0); - */ - addr_t address = return_value_sp->GetValueForExpressionPath(".address") - ->GetValueAsUnsigned(0); - addr_t access_type = - return_value_sp->GetValueForExpressionPath(".access_type") - ->GetValueAsUnsigned(0); - addr_t access_size = - return_value_sp->GetValueForExpressionPath(".access_size") - ->GetValueAsUnsigned(0); - addr_t description_ptr = - return_value_sp->GetValueForExpressionPath(".description") - ->GetValueAsUnsigned(0); - std::string description; - Status error; - process_sp->ReadCStringFromMemory(description_ptr, description, error); - - StructuredData::Dictionary *dict = new StructuredData::Dictionary(); - dict->AddStringItem("instrumentation_class", "AddressSanitizer"); - dict->AddStringItem("stop_type", "fatal_error"); - dict->AddIntegerItem("pc", pc); - /* commented out because rdar://problem/18533301 - dict->AddIntegerItem("bp", bp); - dict->AddIntegerItem("sp", sp); - */ - dict->AddIntegerItem("address", address); - dict->AddIntegerItem("access_type", access_type); - dict->AddIntegerItem("access_size", access_size); - dict->AddStringItem("description", description); - - return StructuredData::ObjectSP(dict); -} - -std::string -InstrumentationRuntimeASan::FormatDescription(StructuredData::ObjectSP report) { - std::string description = std::string(report->GetAsDictionary() - ->GetValueForKey("description") - ->GetAsString() - ->GetValue()); - return llvm::StringSwitch<std::string>(description) - .Case("heap-use-after-free", "Use of deallocated memory") - .Case("heap-buffer-overflow", "Heap buffer overflow") - .Case("stack-buffer-underflow", "Stack buffer underflow") - .Case("initialization-order-fiasco", "Initialization order problem") - .Case("stack-buffer-overflow", "Stack buffer overflow") - .Case("stack-use-after-return", "Use of stack memory after return") - .Case("use-after-poison", "Use of poisoned memory") - .Case("container-overflow", "Container overflow") - .Case("stack-use-after-scope", "Use of out-of-scope stack memory") - .Case("global-buffer-overflow", "Global buffer overflow") - .Case("unknown-crash", "Invalid memory access") - .Case("stack-overflow", "Stack space exhausted") - .Case("null-deref", "Dereference of null pointer") - .Case("wild-jump", "Jump to non-executable address") - .Case("wild-addr-write", "Write through wild pointer") - .Case("wild-addr-read", "Read from wild pointer") - .Case("wild-addr", "Access through wild pointer") - .Case("signal", "Deadly signal") - .Case("double-free", "Deallocation of freed memory") - .Case("new-delete-type-mismatch", - "Deallocation size different from allocation size") - .Case("bad-free", "Deallocation of non-allocated memory") - .Case("alloc-dealloc-mismatch", - "Mismatch between allocation and deallocation APIs") - .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size") - .Case("bad-__sanitizer_get_allocated_size", - "Invalid argument to __sanitizer_get_allocated_size") - .Case("param-overlap", - "Call to function disallowing overlapping memory ranges") - .Case("negative-size-param", "Negative size used when accessing memory") - .Case("bad-__sanitizer_annotate_contiguous_container", - "Invalid argument to __sanitizer_annotate_contiguous_container") - .Case("odr-violation", "Symbol defined in multiple translation units") - .Case( - "invalid-pointer-pair", - "Comparison or arithmetic on pointers from different memory regions") - // for unknown report codes just show the code - .Default("AddressSanitizer detected: " + description); -} - bool InstrumentationRuntimeASan::NotifyBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { @@ -248,32 +72,8 @@ bool InstrumentationRuntimeASan::NotifyBreakpointHit( ProcessSP process_sp = instance->GetProcessSP(); - if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) - return false; - - StructuredData::ObjectSP report = instance->RetrieveReportData(); - std::string description; - if (report) { - description = instance->FormatDescription(report); - } - // Make sure this is the right process - if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { - ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); - if (thread_sp) - thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo:: - CreateStopReasonWithInstrumentationData( - *thread_sp, description, report)); - - StreamFileSP stream_sp( - process_sp->GetTarget().GetDebugger().GetOutputStreamSP()); - if (stream_sp) { - stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " - "info -s' to get extended information about the " - "report.\n"); - } - return true; // Return true to stop the target - } else - return false; // Let target run + return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id, + break_loc_id); } void InstrumentationRuntimeASan::Activate() { @@ -284,29 +84,14 @@ void InstrumentationRuntimeASan::Activate() { if (!process_sp) return; - ConstString symbol_name("_ZN6__asanL7AsanDieEv"); - const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( - symbol_name, eSymbolTypeCode); - - if (symbol == nullptr) - return; + Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint( + GetRuntimeModuleSP(), process_sp, ConstString("_ZN6__asanL7AsanDieEv")); - if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) + if (!breakpoint) return; - Target &target = process_sp->GetTarget(); - addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); - - if (symbol_address == LLDB_INVALID_ADDRESS) - return; - - const bool internal = true; - const bool hardware = false; const bool sync = false; - Breakpoint *breakpoint = - process_sp->GetTarget() - .CreateBreakpoint(symbol_address, internal, hardware) - .get(); + breakpoint->SetCallback(InstrumentationRuntimeASan::NotifyBreakpointHit, this, sync); breakpoint->SetBreakpointKind("address-sanitizer-report"); @@ -316,12 +101,13 @@ void InstrumentationRuntimeASan::Activate() { } void InstrumentationRuntimeASan::Deactivate() { - if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) { - ProcessSP process_sp = GetProcessSP(); - if (process_sp) { - process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); - SetBreakpointID(LLDB_INVALID_BREAK_ID); - } - } SetActive(false); + + if (GetBreakpointID() == LLDB_INVALID_BREAK_ID) + return; + + if (ProcessSP process_sp = GetProcessSP()) { + process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); + SetBreakpointID(LLDB_INVALID_BREAK_ID); + } } diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h index 83a88cf7f89f..177959d7126b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.h @@ -10,9 +10,6 @@ #define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASAN_INSTRUMENTATIONRUNTIMEASAN_H #include "lldb/Target/InstrumentationRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/lldb-private.h" namespace lldb_private { @@ -51,10 +48,6 @@ private: StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - - StructuredData::ObjectSP RetrieveReportData(); - - std::string FormatDescription(StructuredData::ObjectSP report); }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp new file mode 100644 index 000000000000..d84cd36d7ce1 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp @@ -0,0 +1,120 @@ +//===-- InstrumentationRuntimeASanLibsanitizers.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 "InstrumentationRuntimeASanLibsanitizers.h" + +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/RegularExpression.h" + +#include "Plugins/InstrumentationRuntime/Utility/ReportRetriever.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(InstrumentationRuntimeASanLibsanitizers) + +lldb::InstrumentationRuntimeSP +InstrumentationRuntimeASanLibsanitizers::CreateInstance( + const lldb::ProcessSP &process_sp) { + return InstrumentationRuntimeSP( + new InstrumentationRuntimeASanLibsanitizers(process_sp)); +} + +void InstrumentationRuntimeASanLibsanitizers::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), + "AddressSanitizer instrumentation runtime plugin for Libsanitizers.", + CreateInstance, GetTypeStatic); +} + +void InstrumentationRuntimeASanLibsanitizers::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb::InstrumentationRuntimeType +InstrumentationRuntimeASanLibsanitizers::GetTypeStatic() { + return eInstrumentationRuntimeTypeLibsanitizersAsan; +} + +InstrumentationRuntimeASanLibsanitizers:: + ~InstrumentationRuntimeASanLibsanitizers() { + Deactivate(); +} + +const RegularExpression & +InstrumentationRuntimeASanLibsanitizers::GetPatternForRuntimeLibrary() { + static RegularExpression regex( + llvm::StringRef("libsystem_sanitizers\\.dylib")); + return regex; +} + +bool InstrumentationRuntimeASanLibsanitizers::CheckIfRuntimeIsValid( + const lldb::ModuleSP module_sp) { + const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType( + ConstString("__asan_abi_init"), lldb::eSymbolTypeAny); + + return symbol != nullptr; +} + +bool InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit( + void *baton, StoppointCallbackContext *context, user_id_t break_id, + user_id_t break_loc_id) { + assert(baton && "null baton"); + if (!baton) + return false; + + InstrumentationRuntimeASanLibsanitizers *const instance = + static_cast<InstrumentationRuntimeASanLibsanitizers *>(baton); + + ProcessSP process_sp = instance->GetProcessSP(); + + return ReportRetriever::NotifyBreakpointHit(process_sp, context, break_id, + break_loc_id); +} + +void InstrumentationRuntimeASanLibsanitizers::Activate() { + if (IsActive()) + return; + + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) + return; + + Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint( + GetRuntimeModuleSP(), process_sp, + ConstString("_Z22raise_sanitizers_error23sanitizer_error_context")); + + if (!breakpoint) + return; + + const bool sync = false; + + breakpoint->SetCallback( + InstrumentationRuntimeASanLibsanitizers::NotifyBreakpointHit, this, sync); + breakpoint->SetBreakpointKind("address-sanitizer-report"); + SetBreakpointID(breakpoint->GetID()); + + SetActive(true); +} + +void InstrumentationRuntimeASanLibsanitizers::Deactivate() { + SetActive(false); + + if (GetBreakpointID() == LLDB_INVALID_BREAK_ID) + return; + + if (ProcessSP process_sp = GetProcessSP()) { + process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); + SetBreakpointID(LLDB_INVALID_BREAK_ID); + } +} diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.h b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.h new file mode 100644 index 000000000000..abb445a9dd67 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.h @@ -0,0 +1,52 @@ +//===-- InstrumentationRuntimeASanLibsanitizers.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_INSTRUMENTATIONRUNTIME_ASANLIBSANITIZERS_INSTRUMENTATIONRUNTIMEASANLIBSANITIZERS_H +#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASANLIBSANITIZERS_INSTRUMENTATIONRUNTIMEASANLIBSANITIZERS_H + +#include "lldb/Target/InstrumentationRuntime.h" + +class InstrumentationRuntimeASanLibsanitizers + : public lldb_private::InstrumentationRuntime { +public: + ~InstrumentationRuntimeASanLibsanitizers() override; + + static lldb::InstrumentationRuntimeSP + CreateInstance(const lldb::ProcessSP &process_sp); + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "Libsanitizers-ASan"; } + + static lldb::InstrumentationRuntimeType GetTypeStatic(); + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + virtual lldb::InstrumentationRuntimeType GetType() { return GetTypeStatic(); } + +private: + InstrumentationRuntimeASanLibsanitizers(const lldb::ProcessSP &process_sp) + : lldb_private::InstrumentationRuntime(process_sp) {} + + const lldb_private::RegularExpression &GetPatternForRuntimeLibrary() override; + + bool CheckIfRuntimeIsValid(const lldb::ModuleSP module_sp) override; + + void Activate() override; + + void Deactivate(); + + static bool + NotifyBreakpointHit(void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, lldb::user_id_t break_loc_id); +}; + +#endif // LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_ASANLIBSANITIZERS_INSTRUMENTATIONRUNTIMEASANLIBSANITIZERS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp index 8a5db3335266..2a35256a6fb0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp @@ -14,9 +14,9 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp index 2e3c053b97bc..1c58922e8d36 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp @@ -14,9 +14,9 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp new file mode 100644 index 000000000000..ff58c4cababa --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp @@ -0,0 +1,252 @@ +//===-- ReportRetriever.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 "ReportRetriever.h" + +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Target/InstrumentationRuntimeStopInfo.h" + +using namespace lldb; +using namespace lldb_private; + +const char *address_sanitizer_retrieve_report_data_prefix = R"( +extern "C" +{ +int __asan_report_present(); +void *__asan_get_report_pc(); +void *__asan_get_report_bp(); +void *__asan_get_report_sp(); +void *__asan_get_report_address(); +const char *__asan_get_report_description(); +int __asan_get_report_access_type(); +size_t __asan_get_report_access_size(); +} +)"; + +const char *address_sanitizer_retrieve_report_data_command = R"( +struct { + int present; + int access_type; + void *pc; + void *bp; + void *sp; + void *address; + size_t access_size; + const char *description; +} t; + +t.present = __asan_report_present(); +t.access_type = __asan_get_report_access_type(); +t.pc = __asan_get_report_pc(); +t.bp = __asan_get_report_bp(); +t.sp = __asan_get_report_sp(); +t.address = __asan_get_report_address(); +t.access_size = __asan_get_report_access_size(); +t.description = __asan_get_report_description(); +t +)"; + +StructuredData::ObjectSP +ReportRetriever::RetrieveReportData(const ProcessSP process_sp) { + if (!process_sp) + return StructuredData::ObjectSP(); + + ThreadSP thread_sp = + process_sp->GetThreadList().GetExpressionExecutionThread(); + + if (!thread_sp) + return StructuredData::ObjectSP(); + + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); + + if (!frame_sp) + return StructuredData::ObjectSP(); + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetTryAllThreads(true); + options.SetStopOthers(true); + options.SetIgnoreBreakpoints(true); + options.SetTimeout(process_sp->GetUtilityExpressionTimeout()); + options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); + options.SetAutoApplyFixIts(false); + options.SetLanguage(eLanguageTypeObjC_plus_plus); + + ValueObjectSP return_value_sp; + ExecutionContext exe_ctx; + Status eval_error; + frame_sp->CalculateExecutionContext(exe_ctx); + ExpressionResults result = UserExpression::Evaluate( + exe_ctx, options, address_sanitizer_retrieve_report_data_command, "", + return_value_sp, eval_error); + if (result != eExpressionCompleted) { + StreamString ss; + ss << "cannot evaluate AddressSanitizer expression:\n"; + ss << eval_error.AsCString(); + Debugger::ReportWarning(ss.GetString().str(), + process_sp->GetTarget().GetDebugger().GetID()); + return StructuredData::ObjectSP(); + } + + int present = return_value_sp->GetValueForExpressionPath(".present") + ->GetValueAsUnsigned(0); + if (present != 1) + return StructuredData::ObjectSP(); + + addr_t pc = + return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0); + addr_t bp = + return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0); + addr_t sp = + return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0); + addr_t address = return_value_sp->GetValueForExpressionPath(".address") + ->GetValueAsUnsigned(0); + addr_t access_type = + return_value_sp->GetValueForExpressionPath(".access_type") + ->GetValueAsUnsigned(0); + addr_t access_size = + return_value_sp->GetValueForExpressionPath(".access_size") + ->GetValueAsUnsigned(0); + addr_t description_ptr = + return_value_sp->GetValueForExpressionPath(".description") + ->GetValueAsUnsigned(0); + std::string description; + Status error; + process_sp->ReadCStringFromMemory(description_ptr, description, error); + + auto dict = std::make_shared<StructuredData::Dictionary>(); + if (!dict) + return StructuredData::ObjectSP(); + + dict->AddStringItem("instrumentation_class", "AddressSanitizer"); + dict->AddStringItem("stop_type", "fatal_error"); + dict->AddIntegerItem("pc", pc); + dict->AddIntegerItem("bp", bp); + dict->AddIntegerItem("sp", sp); + dict->AddIntegerItem("address", address); + dict->AddIntegerItem("access_type", access_type); + dict->AddIntegerItem("access_size", access_size); + dict->AddStringItem("description", description); + + return StructuredData::ObjectSP(dict); +} + +std::string +ReportRetriever::FormatDescription(StructuredData::ObjectSP report) { + std::string description = std::string(report->GetAsDictionary() + ->GetValueForKey("description") + ->GetAsString() + ->GetValue()); + return llvm::StringSwitch<std::string>(description) + .Case("heap-use-after-free", "Use of deallocated memory") + .Case("heap-buffer-overflow", "Heap buffer overflow") + .Case("stack-buffer-underflow", "Stack buffer underflow") + .Case("initialization-order-fiasco", "Initialization order problem") + .Case("stack-buffer-overflow", "Stack buffer overflow") + .Case("stack-use-after-return", "Use of stack memory after return") + .Case("use-after-poison", "Use of poisoned memory") + .Case("container-overflow", "Container overflow") + .Case("stack-use-after-scope", "Use of out-of-scope stack memory") + .Case("global-buffer-overflow", "Global buffer overflow") + .Case("unknown-crash", "Invalid memory access") + .Case("stack-overflow", "Stack space exhausted") + .Case("null-deref", "Dereference of null pointer") + .Case("wild-jump", "Jump to non-executable address") + .Case("wild-addr-write", "Write through wild pointer") + .Case("wild-addr-read", "Read from wild pointer") + .Case("wild-addr", "Access through wild pointer") + .Case("signal", "Deadly signal") + .Case("double-free", "Deallocation of freed memory") + .Case("new-delete-type-mismatch", + "Deallocation size different from allocation size") + .Case("bad-free", "Deallocation of non-allocated memory") + .Case("alloc-dealloc-mismatch", + "Mismatch between allocation and deallocation APIs") + .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size") + .Case("bad-__sanitizer_get_allocated_size", + "Invalid argument to __sanitizer_get_allocated_size") + .Case("param-overlap", + "Call to function disallowing overlapping memory ranges") + .Case("negative-size-param", "Negative size used when accessing memory") + .Case("bad-__sanitizer_annotate_contiguous_container", + "Invalid argument to __sanitizer_annotate_contiguous_container") + .Case("odr-violation", "Symbol defined in multiple translation units") + .Case( + "invalid-pointer-pair", + "Comparison or arithmetic on pointers from different memory regions") + // for unknown report codes just show the code + .Default("AddressSanitizer detected: " + description); +} + +bool ReportRetriever::NotifyBreakpointHit(ProcessSP process_sp, + StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) { + // Make sure this is the right process + if (!process_sp || process_sp != context->exe_ctx_ref.GetProcessSP()) + return false; + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + + StructuredData::ObjectSP report = RetrieveReportData(process_sp); + if (!report || report->GetType() != lldb::eStructuredDataTypeDictionary) + return false; + + std::string description = FormatDescription(report); + + if (ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP()) + thread_sp->SetStopInfo( + InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( + *thread_sp, description, report)); + + if (StreamFileSP stream_sp = StreamFileSP( + process_sp->GetTarget().GetDebugger().GetOutputStreamSP())) + stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " + "info -s' to get extended information about the " + "report.\n"); + + return true; // Return true to stop the target +} + +Breakpoint *ReportRetriever::SetupBreakpoint(ModuleSP module_sp, + ProcessSP process_sp, + ConstString symbol_name) { + if (!module_sp || !process_sp) + return nullptr; + + const Symbol *symbol = + module_sp->FindFirstSymbolWithNameAndType(symbol_name, eSymbolTypeCode); + + if (symbol == nullptr) + return nullptr; + + if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) + return nullptr; + + Target &target = process_sp->GetTarget(); + addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); + + if (symbol_address == LLDB_INVALID_ADDRESS) + return nullptr; + + const bool internal = true; + const bool hardware = false; + + Breakpoint *breakpoint = + process_sp->GetTarget() + .CreateBreakpoint(symbol_address, internal, hardware) + .get(); + + return breakpoint; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h new file mode 100644 index 000000000000..a45339a5809c --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.h @@ -0,0 +1,34 @@ +//===-- ReportRetriever.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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/Process.h" + +#ifndef LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_REPORTRETRIEVER_H +#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_REPORTRETRIEVER_H + +namespace lldb_private { + +class ReportRetriever { +private: + static StructuredData::ObjectSP + RetrieveReportData(const lldb::ProcessSP process_sp); + + static std::string FormatDescription(StructuredData::ObjectSP report); + +public: + static bool NotifyBreakpointHit(lldb::ProcessSP process_sp, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + static Breakpoint *SetupBreakpoint(lldb::ModuleSP, lldb::ProcessSP, + ConstString); +}; +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_REPORTRETRIEVER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 97d401028d45..73763d9cf3b8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -91,8 +91,8 @@ enum { class PluginProperties : public Properties { public: - static ConstString GetSettingName() { - return ConstString(JITLoaderGDB::GetPluginNameStatic()); + static llvm::StringRef GetSettingName() { + return JITLoaderGDB::GetPluginNameStatic(); } PluginProperties() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index e780cd8285c4..314a4aca8d26 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -54,18 +54,6 @@ public: if (!clang_ast_context) return; - std::shared_ptr<ClangASTImporter> clang_ast_importer; - auto *state = target_sp->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC_plus_plus); - if (state) { - auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state); - clang_ast_importer = persistent_vars->GetClangASTImporter(); - } - - if (!clang_ast_importer) { - return; - } - const char *const isa_name("__isa"); const CompilerType isa_type = clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 3d709e3d6759..586cc08a6f12 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -45,6 +45,7 @@ #include "LibCxxVariant.h" #include "LibStdcpp.h" #include "MSVCUndecoratedNameParser.h" +#include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; @@ -332,14 +333,12 @@ bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) { // If we can't parse the incoming name, then just check that it contains path. if (m_parse_error) return m_full.GetStringRef().contains(path); - + llvm::StringRef identifier; llvm::StringRef context; std::string path_str = path.str(); - bool success - = CPlusPlusLanguage::ExtractContextAndIdentifier(path_str.c_str(), - context, - identifier); + bool success = CPlusPlusLanguage::ExtractContextAndIdentifier( + path_str.c_str(), context, identifier); if (!success) return m_full.GetStringRef().contains(path); @@ -372,7 +371,7 @@ bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) { return false; if (haystack.empty() || !isalnum(haystack.back())) return true; - + return false; } @@ -388,7 +387,7 @@ bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) { return true; } -bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path, +bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path, ConstString demangled) const { MethodName demangled_name(demangled); return demangled_name.ContainsPath(path); @@ -467,7 +466,7 @@ protected: } void trySubstitute(llvm::StringRef From, llvm::StringRef To) { - if (!llvm::StringRef(currentParserPos(), this->numLeft()).startswith(From)) + if (!llvm::StringRef(currentParserPos(), this->numLeft()).starts_with(From)) return; // We found a match. Append unmodified input up to this point. @@ -981,6 +980,57 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::unordered_map iterator synthetic children", "^std::__[[:alnum:]]+::__hash_map_(const_)?iterator<.+>$", stl_synth_flags, true); + // Chrono duration typedefs + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::nanoseconds", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} ns"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::microseconds", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} µs"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::milliseconds", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} ms"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::seconds", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} s"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::minutes", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren | + eTypeOptionHideValue, + "${var.__rep_} min"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::hours", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} h"))); + + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::days", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren | + eTypeOptionHideValue, + "${var.__rep_} days"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::weeks", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren | + eTypeOptionHideValue, + "${var.__rep_} weeks"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::months", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren | + eTypeOptionHideValue, + "${var.__rep_} months"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::years", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren | + eTypeOptionHideValue, + "${var.__rep_} years"))); + cpp_category_sp->AddTypeSummary( + "^std::__[[:alnum:]]+::chrono::seconds", eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} s"))); } static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { @@ -1009,7 +1059,7 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact, std_string_summary_sp); cpp_category_sp->AddTypeSummary("std::basic_string<char>", - eFormatterMatchRegex, std_string_summary_sp); + eFormatterMatchExact, std_string_summary_sp); cpp_category_sp->AddTypeSummary( "std::basic_string<char,std::char_traits<char>,std::allocator<char> >", eFormatterMatchExact, std_string_summary_sp); @@ -1104,6 +1154,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider"))); + cpp_category_sp->AddTypeSynthetic( + "^std::variant<.+>$", eFormatterMatchRegex, + SyntheticChildrenSP(new ScriptedSyntheticChildren( + stl_synth_flags, + "lldb.formatters.cpp.gnu_libstdcpp.VariantSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); @@ -1148,6 +1203,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { TypeSummaryImplSP(new ScriptSummaryFormat( stl_summary_flags, "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); + cpp_category_sp->AddTypeSummary( + "^std::variant<.+>$", eFormatterMatchRegex, + TypeSummaryImplSP(new ScriptSummaryFormat( + stl_summary_flags, + "lldb.formatters.cpp.gnu_libstdcpp.VariantSummaryProvider"))); AddCXXSynthetic( cpp_category_sp, @@ -1356,7 +1416,8 @@ CPlusPlusLanguage::GetHardcodedSummaries() { lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider")); if (CompilerType CT = valobj.GetCompilerType(); - CT.IsFunctionPointerType() || CT.IsMemberFunctionPointerType()) { + CT.IsFunctionPointerType() || CT.IsMemberFunctionPointerType() || + valobj.GetValueType() == lldb::eValueTypeVTableEntry) { return formatter_sp; } return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index 7712a60b7795..623d481bf117 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -103,6 +103,8 @@ public: return lldb::eLanguageTypeC_plus_plus; } + llvm::StringRef GetUserEntryPointName() const override { return "main"; } + std::unique_ptr<TypeScavenger> GetTypeScavenger() override; lldb::TypeCategoryImplSP GetFormatters() override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index cd3ac92ae4a8..2876efc5c41a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -38,7 +38,7 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: - ConstString GetDataContainerMemberName(); + llvm::StringRef GetDataContainerMemberName(); // The lifetime of a ValueObject and all its derivative ValueObjects // (children, clones, etc.) is managed by a ClusterManager. These @@ -66,12 +66,14 @@ GenericBitsetFrontEnd::GenericBitsetFrontEnd(ValueObject &valobj, StdLib stdlib) } } -ConstString GenericBitsetFrontEnd::GetDataContainerMemberName() { +llvm::StringRef GenericBitsetFrontEnd::GetDataContainerMemberName() { + static constexpr llvm::StringLiteral s_libcxx_case("__first_"); + static constexpr llvm::StringLiteral s_libstdcpp_case("_M_w"); switch (m_stdlib) { case StdLib::LibCxx: - return ConstString("__first_"); + return s_libcxx_case; case StdLib::LibStdcpp: - return ConstString("_M_w"); + return s_libstdcpp_case; } llvm_unreachable("Unknown StdLib enum"); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 14776cdf8081..ff7043bdf97f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -84,7 +84,7 @@ static bool isStdTemplate(ConstString type_name, llvm::StringRef type) { // The type name may be prefixed with `std::__<inline-namespace>::`. if (name.consume_front("std::")) consumeInlineNamespace(name); - return name.consume_front(type) && name.startswith("<"); + return name.consume_front(type) && name.starts_with("<"); } static bool isUnorderedMap(ConstString type_name) { @@ -162,10 +162,27 @@ lldb::ValueObjectSP lldb_private::formatters:: if (!node_sp || error.Fail()) return nullptr; - value_sp = node_sp->GetChildMemberWithName("__value_"); hash_sp = node_sp->GetChildMemberWithName("__hash_"); - if (!value_sp || !hash_sp) + if (!hash_sp) return nullptr; + + value_sp = node_sp->GetChildMemberWithName("__value_"); + if (!value_sp) { + // clang-format off + // Since D101206 (ba79fb2e1f), libc++ wraps the `__value_` in an + // anonymous union. + // Child 0: __hash_node_base base class + // Child 1: __hash_ + // Child 2: anonymous union + // clang-format on + auto anon_union_sp = node_sp->GetChildAtIndex(2); + if (!anon_union_sp) + return nullptr; + + value_sp = anon_union_sp->GetChildMemberWithName("__value_"); + if (!value_sp) + return nullptr; + } } m_elements_cache.push_back( {value_sp.get(), hash_sp->GetValueAsUnsigned(0)}); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index c65bb9b6bc9b..23af50fdb712 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -377,9 +377,16 @@ lldb::ValueObjectSP LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { if (idx == 0) return m_ptr_obj->GetSP(); - if (idx == 1) - return m_obj_obj->GetSP(); - + if (idx == 1) { + if (m_ptr_obj && !m_obj_obj) { + Status error; + ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); + if (error.Success()) + m_obj_obj = obj_obj->Clone(ConstString("object")).get(); + } + if (m_obj_obj) + return m_obj_obj->GetSP(); + } return lldb::ValueObjectSP(); } @@ -397,14 +404,7 @@ bool LibStdcppSharedPtrSyntheticFrontEnd::Update() { return false; m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get(); - - if (m_ptr_obj) { - Status error; - ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); - if (error.Success()) { - m_obj_obj = obj_obj->Clone(ConstString("object")).get(); - } - } + m_obj_obj = nullptr; return false; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp index aef7cbac603f..f1bfeae5099b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp @@ -69,9 +69,9 @@ bool LibStdcppTupleSyntheticFrontEnd::Update() { for (size_t i = 0; i < child_count; ++i) { ValueObjectSP child_sp = current_child->GetChildAtIndex(i); llvm::StringRef name_str = child_sp->GetName().GetStringRef(); - if (name_str.startswith("std::_Tuple_impl<")) { + if (name_str.starts_with("std::_Tuple_impl<")) { next_child_sp = child_sp; - } else if (name_str.startswith("std::_Head_base<")) { + } else if (name_str.starts_with("std::_Head_base<")) { ValueObjectSP value_sp = child_sp->GetChildMemberWithName("_M_head_impl"); if (value_sp) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp index 7174e9102e1b..a84d641b57bc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp @@ -108,14 +108,7 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { if (del_obj) m_del_obj = del_obj->Clone(ConstString("deleter")).get(); } - - if (m_ptr_obj) { - Status error; - ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); - if (error.Success()) { - m_obj_obj = obj_obj->Clone(ConstString("object")).get(); - } - } + m_obj_obj = nullptr; return false; } @@ -128,8 +121,17 @@ LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { return m_ptr_obj->GetSP(); if (idx == 1 && m_del_obj) return m_del_obj->GetSP(); - if (idx == 2 && m_obj_obj) - return m_obj_obj->GetSP(); + if (idx == 2) { + if (m_ptr_obj && !m_obj_obj) { + Status error; + ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); + if (error.Success()) { + m_obj_obj = obj_obj->Clone(ConstString("object")).get(); + } + } + if (m_obj_obj) + return m_obj_obj->GetSP(); + } return lldb::ValueObjectSP(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 374ac763ab18..f1a7e04bc9d1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -237,7 +237,8 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider( if (!process_sp) return false; - ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); + AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>( + ObjCLanguageRuntime::Get(*process_sp)); if (!runtime) return false; @@ -264,20 +265,56 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider( do { if (class_name == "NSIndexSet" || class_name == "NSMutableIndexSet") { + // Foundation version 2000 added a bitmask if the index set fit in 64 bits + // and a Tagged Pointer version if the bitmask is small enough to fit in + // the tagged pointer payload. + // It also changed the layout (but not the size) of the set descriptor. + + // First check whether this is a tagged pointer. The bitmask will be in + // the payload of the tagged pointer. + uint64_t payload; + if (runtime->GetFoundationVersion() >= 2000 + && descriptor->GetTaggedPointerInfo(nullptr, nullptr, &payload)) { + count = llvm::popcount(payload); + break; + } + // The first 32 bits describe the index set in all cases: Status error; uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory( - valobj_addr + ptr_size, 4, 0, error); + valobj_addr + ptr_size, 4, 0, error); if (error.Fail()) return false; - // this means the set is empty - count = 0 - if ((mode & 1) == 1) { - count = 0; - break; + // Now check if the index is held in a bitmask in the object: + if (runtime->GetFoundationVersion() >= 2000) { + // The first two bits are "isSingleRange" and "isBitfield". If this is + // a bitfield we handle it here, otherwise set mode appropriately and + // the rest of the treatment is in common. + if ((mode & 2) == 2) { + // The bitfield is a 64 bit uint at the beginning of the data var. + uint64_t bitfield = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + 2 * ptr_size, 8, 0, error); + if (error.Fail()) + return false; + count = llvm::popcount(bitfield); + break; + } + // It wasn't a bitfield, so read the isSingleRange from its new loc: + if ((mode & 1) == 1) + mode = 1; // this means the set only has one range + else + mode = 2; // this means the set has multiple ranges + } else { + // this means the set is empty - count = 0 + if ((mode & 1) == 1) { + count = 0; + break; + } + + if ((mode & 2) == 2) + mode = 1; // this means the set only has one range + else + mode = 2; // this means the set has multiple ranges } - if ((mode & 2) == 2) - mode = 1; // this means the set only has one range - else - mode = 2; // this means the set has multiple ranges if (mode == 1) { count = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + 3 * ptr_size, ptr_size, 0, error); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp index 2e927eb8d856..5ae0751cb065 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -37,7 +37,7 @@ NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Prefix( bool NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Match( ConstString class_name) { - return class_name.GetStringRef().startswith(m_prefix.GetStringRef()); + return class_name.GetStringRef().starts_with(m_prefix.GetStringRef()); } NSDictionary_Additionals::AdditionalFormatterMatching::Full::Full(ConstString n) @@ -78,7 +78,8 @@ static CompilerType GetLLDBNSPairType(TargetSP target_sp) { if (!compiler_type) { compiler_type = scratch_ts_sp->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, - g_lldb_autogen_nspair, clang::TTK_Struct, lldb::eLanguageTypeC); + g_lldb_autogen_nspair, llvm::to_underlying(clang::TagTypeKind::Struct), + lldb::eLanguageTypeC); if (compiler_type) { TypeSystemClang::StartTagDeclarationDefinition(compiler_type); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp index 82b037129c24..742ae7b14945 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -81,9 +81,9 @@ ObjCLanguage::MethodName::Create(llvm::StringRef name, bool strict) { // Figure out type Type type = eTypeUnspecified; - if (name.startswith("+[")) + if (name.starts_with("+[")) type = eTypeClassMethod; - else if (name.startswith("-[")) + else if (name.starts_with("-[")) type = eTypeInstanceMethod; // If there's no type and it's strict, this is invalid diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h index bb8057846bb7..a50f4b036108 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h @@ -127,6 +127,8 @@ public: return lldb::eLanguageTypeObjC; } + llvm::StringRef GetUserEntryPointName() const override { return "main"; } + // Get all possible names for a method. Examples: // If method_name is "+[NSString(my_additions) myStringWithCString:]" // variant_names[0] => "+[NSString myStringWithCString:]" diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h index b7c71b5dbb1c..1beab9348eb7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h @@ -27,6 +27,8 @@ public: return lldb::eLanguageTypeObjC_plus_plus; } + llvm::StringRef GetUserEntryPointName() const override { return "main"; } + llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; } bool IsSourceFile(llvm::StringRef file_path) const override; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index c2488eaa9f5b..300ecc8e8ed5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -34,6 +34,9 @@ using namespace lldb; using namespace lldb_private; static ConstString g_this = ConstString("this"); +// Artificial coroutine-related variables emitted by clang. +static ConstString g_promise = ConstString("__promise"); +static ConstString g_coro_frame = ConstString("__coro_frame"); char CPPLanguageRuntime::ID = 0; @@ -41,7 +44,7 @@ CPPLanguageRuntime::CPPLanguageRuntime(Process *process) : LanguageRuntime(process) {} bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) { - return name == g_this; + return name == g_this || name == g_promise || name == g_coro_frame; } bool CPPLanguageRuntime::GetObjectDescription(Stream &str, @@ -217,7 +220,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( llvm::StringRef vtable_name(symbol->GetName().GetStringRef()); bool found_expected_start_string = - vtable_name.startswith("vtable for std::__1::__function::__func<"); + vtable_name.starts_with("vtable for std::__1::__function::__func<"); if (!found_expected_start_string) return optional_info; @@ -274,7 +277,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( } // Case 4 or 5 - if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for") && + if (symbol && !symbol->GetName().GetStringRef().starts_with("vtable for") && !contains_lambda_identifier(first_template_parameter) && !has_invoke) { optional_info.callable_case = LibCppStdFunctionCallableCase::FreeOrMemberFunction; @@ -309,7 +312,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( lldb::FunctionSP func_sp = vtable_cu->FindFunction([name_to_use](const FunctionSP &f) { auto name = f->GetName().GetStringRef(); - if (name.startswith(name_to_use) && name.contains("operator")) + if (name.starts_with(name_to_use) && name.contains("operator")) return true; return false; @@ -370,7 +373,7 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, // step into the wrapped callable. // bool found_expected_start_string = - function_name.startswith("std::__1::function<"); + function_name.starts_with("std::__1::function<"); if (!found_expected_start_string) return ret_plan_sp; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 711a696ff9b4..47b1db16f1e9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -54,134 +54,237 @@ bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) { check_objc); } -TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( - ValueObject &in_value, lldb::addr_t original_ptr, - lldb::addr_t vtable_load_addr) { - if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) { - // Find the symbol that contains the "vtable_load_addr" address - Address vtable_addr; - Target &target = m_process->GetTarget(); - if (!target.GetSectionLoadList().IsEmpty()) { - if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, - vtable_addr)) { - // See if we have cached info for this type already - TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr); - if (type_info) - return type_info; - - SymbolContext sc; - target.GetImages().ResolveSymbolContextForAddress( - vtable_addr, eSymbolContextSymbol, sc); - Symbol *symbol = sc.symbol; - if (symbol != nullptr) { - const char *name = - symbol->GetMangled().GetDemangledName().AsCString(); - if (name && strstr(name, vtable_demangled_prefix) == name) { - Log *log = GetLog(LLDBLog::Object); - LLDB_LOGF(log, - "0x%16.16" PRIx64 - ": static-type = '%s' has vtable symbol '%s'\n", - original_ptr, in_value.GetTypeName().GetCString(), name); - // We are a C++ class, that's good. Get the class name and look it - // up: - const char *class_name = name + strlen(vtable_demangled_prefix); - // We know the class name is absolute, so tell FindTypes that by - // prefixing it with the root namespace: - std::string lookup_name("::"); - lookup_name.append(class_name); - - type_info.SetName(class_name); - const bool exact_match = true; - TypeList class_types; - - // First look in the module that the vtable symbol came from and - // look for a single exact match. - llvm::DenseSet<SymbolFile *> searched_symbol_files; - if (sc.module_sp) - sc.module_sp->FindTypes(ConstString(lookup_name), exact_match, 1, - searched_symbol_files, class_types); - - // If we didn't find a symbol, then move on to the entire module - // list in the target and get as many unique matches as possible - if (class_types.Empty()) - target.GetImages().FindTypes(nullptr, ConstString(lookup_name), - exact_match, UINT32_MAX, - searched_symbol_files, class_types); - - lldb::TypeSP type_sp; - if (class_types.Empty()) { - LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n", - original_ptr); - return TypeAndOrName(); +TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo( + ValueObject &in_value, const VTableInfo &vtable_info) { + if (vtable_info.addr.IsSectionOffset()) { + // See if we have cached info for this type already + TypeAndOrName type_info = GetDynamicTypeInfo(vtable_info.addr); + if (type_info) + return type_info; + + if (vtable_info.symbol) { + Log *log = GetLog(LLDBLog::Object); + llvm::StringRef symbol_name = + vtable_info.symbol->GetMangled().GetDemangledName().GetStringRef(); + LLDB_LOGF(log, + "0x%16.16" PRIx64 + ": static-type = '%s' has vtable symbol '%s'\n", + in_value.GetPointerValue(), + in_value.GetTypeName().GetCString(), + symbol_name.str().c_str()); + // We are a C++ class, that's good. Get the class name and look it + // up: + llvm::StringRef class_name = symbol_name; + class_name.consume_front(vtable_demangled_prefix); + // We know the class name is absolute, so tell FindTypes that by + // prefixing it with the root namespace: + std::string lookup_name("::"); + lookup_name.append(class_name.data(), class_name.size()); + + type_info.SetName(class_name); + ConstString const_lookup_name(lookup_name); + TypeList class_types; + ModuleSP module_sp = vtable_info.symbol->CalculateSymbolContextModule(); + // First look in the module that the vtable symbol came from and + // look for a single exact match. + TypeResults results; + TypeQuery query(const_lookup_name.GetStringRef(), + TypeQueryOptions::e_exact_match | + TypeQueryOptions::e_find_one); + if (module_sp) { + module_sp->FindTypes(query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + class_types.Insert(type_sp); + } + + // If we didn't find a symbol, then move on to the entire module + // list in the target and get as many unique matches as possible + if (class_types.Empty()) { + query.SetFindOne(false); + m_process->GetTarget().GetImages().FindTypes(nullptr, query, results); + for (const auto &type_sp : results.GetTypeMap().Types()) + class_types.Insert(type_sp); + } + + lldb::TypeSP type_sp; + if (class_types.Empty()) { + LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n", + in_value.GetPointerValue()); + return TypeAndOrName(); + } + if (class_types.GetSize() == 1) { + type_sp = class_types.GetTypeAtIndex(0); + if (type_sp) { + if (TypeSystemClang::IsCXXClassType( + type_sp->GetForwardCompilerType())) { + LLDB_LOGF( + log, + "0x%16.16" PRIx64 + ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 + "}, type-name='%s'\n", + in_value.GetPointerValue(), in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); + type_info.SetTypeSP(type_sp); + } + } + } else { + size_t i; + if (log) { + for (i = 0; i < class_types.GetSize(); i++) { + type_sp = class_types.GetTypeAtIndex(i); + if (type_sp) { + LLDB_LOGF( + log, + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types: uid={0x%" PRIx64 "}, type-name='%s'\n", + in_value.GetPointerValue(), + in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); } - if (class_types.GetSize() == 1) { - type_sp = class_types.GetTypeAtIndex(0); - if (type_sp) { - if (TypeSystemClang::IsCXXClassType( - type_sp->GetForwardCompilerType())) { - LLDB_LOGF( - log, - "0x%16.16" PRIx64 - ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 - "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); - type_info.SetTypeSP(type_sp); - } - } - } else { - size_t i; - if (log) { - for (i = 0; i < class_types.GetSize(); i++) { - type_sp = class_types.GetTypeAtIndex(i); - if (type_sp) { - LLDB_LOGF( - log, - "0x%16.16" PRIx64 - ": static-type = '%s' has multiple matching dynamic " - "types: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); - } - } - } - - for (i = 0; i < class_types.GetSize(); i++) { - type_sp = class_types.GetTypeAtIndex(i); - if (type_sp) { - if (TypeSystemClang::IsCXXClassType( - type_sp->GetForwardCompilerType())) { - LLDB_LOGF( - log, - "0x%16.16" PRIx64 ": static-type = '%s' has multiple " - "matching dynamic types, picking " - "this one: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); - type_info.SetTypeSP(type_sp); - } - } - } - - if (log) { - LLDB_LOGF(log, - "0x%16.16" PRIx64 - ": static-type = '%s' has multiple matching dynamic " - "types, didn't find a C++ match\n", - original_ptr, in_value.GetTypeName().AsCString()); - } + } + } + + for (i = 0; i < class_types.GetSize(); i++) { + type_sp = class_types.GetTypeAtIndex(i); + if (type_sp) { + if (TypeSystemClang::IsCXXClassType( + type_sp->GetForwardCompilerType())) { + LLDB_LOGF( + log, + "0x%16.16" PRIx64 ": static-type = '%s' has multiple " + "matching dynamic types, picking " + "this one: uid={0x%" PRIx64 "}, type-name='%s'\n", + in_value.GetPointerValue(), + in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); + type_info.SetTypeSP(type_sp); } - if (type_info) - SetDynamicTypeInfo(vtable_addr, type_info); - return type_info; } } + + if (log) { + LLDB_LOGF(log, + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types, didn't find a C++ match\n", + in_value.GetPointerValue(), + in_value.GetTypeName().AsCString()); + } } + if (type_info) + SetDynamicTypeInfo(vtable_info.addr, type_info); + return type_info; } } return TypeAndOrName(); } +llvm::Error ItaniumABILanguageRuntime::TypeHasVTable(CompilerType type) { + // Check to make sure the class has a vtable. + CompilerType original_type = type; + if (type.IsPointerOrReferenceType()) { + CompilerType pointee_type = type.GetPointeeType(); + if (pointee_type) + type = pointee_type; + } + + // Make sure this is a class or a struct first by checking the type class + // bitfield that gets returned. + if ((type.GetTypeClass() & (eTypeClassStruct | eTypeClassClass)) == 0) { + return llvm::createStringError(std::errc::invalid_argument, + "type \"%s\" is not a class or struct or a pointer to one", + original_type.GetTypeName().AsCString("<invalid>")); + } + + // Check if the type has virtual functions by asking it if it is polymorphic. + if (!type.IsPolymorphicClass()) { + return llvm::createStringError(std::errc::invalid_argument, + "type \"%s\" doesn't have a vtable", + type.GetTypeName().AsCString("<invalid>")); + } + return llvm::Error::success(); +} + +// This function can accept both pointers or references to classes as well as +// instances of classes. If you are using this function during dynamic type +// detection, only valid ValueObjects that return true to +// CouldHaveDynamicValue(...) should call this function and \a check_type +// should be set to false. This function is also used by ValueObjectVTable +// and is can pass in instances of classes which is not suitable for dynamic +// type detection, these cases should pass true for \a check_type. +llvm::Expected<LanguageRuntime::VTableInfo> + ItaniumABILanguageRuntime::GetVTableInfo(ValueObject &in_value, + bool check_type) { + + CompilerType type = in_value.GetCompilerType(); + if (check_type) { + if (llvm::Error err = TypeHasVTable(type)) + return std::move(err); + } + ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process == nullptr) + return llvm::createStringError(std::errc::invalid_argument, + "invalid process"); + + AddressType address_type; + lldb::addr_t original_ptr = LLDB_INVALID_ADDRESS; + if (type.IsPointerOrReferenceType()) + original_ptr = in_value.GetPointerValue(&address_type); + else + original_ptr = in_value.GetAddressOf(/*scalar_is_load_address=*/true, + &address_type); + if (original_ptr == LLDB_INVALID_ADDRESS || address_type != eAddressTypeLoad) + return llvm::createStringError(std::errc::invalid_argument, + "failed to get the address of the value"); + + Status error; + lldb::addr_t vtable_load_addr = + process->ReadPointerFromMemory(original_ptr, error); + + if (!error.Success() || vtable_load_addr == LLDB_INVALID_ADDRESS) + return llvm::createStringError(std::errc::invalid_argument, + "failed to read vtable pointer from memory at 0x%" PRIx64, + original_ptr); + + // The vtable load address can have authentication bits with + // AArch64 targets on Darwin. + vtable_load_addr = process->FixDataAddress(vtable_load_addr); + + // Find the symbol that contains the "vtable_load_addr" address + Address vtable_addr; + if (!process->GetTarget().ResolveLoadAddress(vtable_load_addr, vtable_addr)) + return llvm::createStringError(std::errc::invalid_argument, + "failed to resolve vtable pointer 0x%" + PRIx64 "to a section", vtable_load_addr); + + // Check our cache first to see if we already have this info + { + std::lock_guard<std::mutex> locker(m_mutex); + auto pos = m_vtable_info_map.find(vtable_addr); + if (pos != m_vtable_info_map.end()) + return pos->second; + } + + Symbol *symbol = vtable_addr.CalculateSymbolContextSymbol(); + if (symbol == nullptr) + return llvm::createStringError(std::errc::invalid_argument, + "no symbol found for 0x%" PRIx64, + vtable_load_addr); + llvm::StringRef name = symbol->GetMangled().GetDemangledName().GetStringRef(); + if (name.starts_with(vtable_demangled_prefix)) { + VTableInfo info = {vtable_addr, symbol}; + std::lock_guard<std::mutex> locker(m_mutex); + auto pos = m_vtable_info_map[vtable_addr] = info; + return info; + } + return llvm::createStringError(std::errc::invalid_argument, + "symbol found that contains 0x%" PRIx64 " is not a vtable symbol", + vtable_load_addr); +} + bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &dynamic_address, @@ -198,33 +301,23 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( class_type_or_name.Clear(); value_type = Value::ValueType::Scalar; - // Only a pointer or reference type can have a different dynamic and static - // type: if (!CouldHaveDynamicValue(in_value)) return false; - // First job, pull out the address at 0 offset from the object. - AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); - if (original_ptr == LLDB_INVALID_ADDRESS) - return false; - - ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == nullptr) - return false; - - Status error; - const lldb::addr_t vtable_address_point = - process->ReadPointerFromMemory(original_ptr, error); - - if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) + // Check if we have a vtable pointer in this value. If we don't it will + // return an error, else it will return a valid resolved address. We don't + // want GetVTableInfo to check the type since we accept void * as a possible + // dynamic type and that won't pass the type check. We already checked the + // type above in CouldHaveDynamicValue(...). + llvm::Expected<VTableInfo> vtable_info_or_err = + GetVTableInfo(in_value, /*check_type=*/false); + if (!vtable_info_or_err) { + llvm::consumeError(vtable_info_or_err.takeError()); return false; + } - class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, - vtable_address_point); + const VTableInfo &vtable_info = vtable_info_or_err.get(); + class_type_or_name = GetTypeInfo(in_value, vtable_info); if (!class_type_or_name) return false; @@ -244,22 +337,27 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( } // The offset_to_top is two pointers above the vtable pointer. - const uint32_t addr_byte_size = process->GetAddressByteSize(); + Target &target = m_process->GetTarget(); + const addr_t vtable_load_addr = vtable_info.addr.GetLoadAddress(&target); + if (vtable_load_addr == LLDB_INVALID_ADDRESS) + return false; + const uint32_t addr_byte_size = m_process->GetAddressByteSize(); const lldb::addr_t offset_to_top_location = - vtable_address_point - 2 * addr_byte_size; + vtable_load_addr - 2 * addr_byte_size; // Watch for underflow, offset_to_top_location should be less than - // vtable_address_point - if (offset_to_top_location >= vtable_address_point) + // vtable_load_addr + if (offset_to_top_location >= vtable_load_addr) return false; - const int64_t offset_to_top = process->ReadSignedIntegerFromMemory( + Status error; + const int64_t offset_to_top = m_process->ReadSignedIntegerFromMemory( offset_to_top_location, addr_byte_size, INT64_MIN, error); if (offset_to_top == INT64_MIN) return false; // So the dynamic type is a value that starts at offset_to_top above // the original address. - lldb::addr_t dynamic_addr = original_ptr + offset_to_top; - if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress( + lldb::addr_t dynamic_addr = in_value.GetPointerValue() + offset_to_top; + if (!m_process->GetTarget().ResolveLoadAddress( dynamic_addr, dynamic_address)) { dynamic_address.SetRawAddress(dynamic_addr); } @@ -339,7 +437,7 @@ public: ~CommandObjectMultiwordItaniumABI_Demangle() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { bool demangled_any = false; bool error_any = false; for (auto &entry : command.entries()) { @@ -352,7 +450,7 @@ protected: // on behalf of the user. This is the moral equivalent of the -_/-n // options to c++filt auto name = entry.ref(); - if (name.startswith("__Z")) + if (name.starts_with("__Z")) name = name.drop_front(); Mangled mangled(name); @@ -372,7 +470,6 @@ protected: error_any ? lldb::eReturnStatusFailed : (demangled_any ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult)); - return result.Succeeded(); } }; @@ -516,7 +613,7 @@ bool ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop( return false; uint64_t break_site_id = stop_reason->GetValue(); - return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint( + return m_process->GetBreakpointSiteList().StopPointSiteContainsBreakpoint( break_site_id, m_cxx_exception_bp_sp->GetID()); } @@ -583,10 +680,10 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread( ValueObjectSP exception = ValueObject::CreateValueObjectFromData( "exception", exception_isw.GetAsData(m_process->GetByteOrder()), exe_ctx, voidstar); - ValueObjectSP dyn_exception + ValueObjectSP dyn_exception = exception->GetDynamicValue(eDynamicDontRunTarget); // If we succeed in making a dynamic value, return that: - if (dyn_exception) + if (dyn_exception) return dyn_exception; return exception; @@ -594,7 +691,7 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread( TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo( const lldb_private::Address &vtable_addr) { - std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex); + std::lock_guard<std::mutex> locker(m_mutex); DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr); if (pos == m_dynamic_type_map.end()) return TypeAndOrName(); @@ -604,6 +701,6 @@ TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo( void ItaniumABILanguageRuntime::SetDynamicTypeInfo( const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) { - std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex); + std::lock_guard<std::mutex> locker(m_mutex); m_dynamic_type_map[vtable_addr] = type_info; } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index ca8d5ab1a93a..0f7e73cfee07 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -47,6 +47,10 @@ public: return runtime->isA(&ID); } + + llvm::Expected<LanguageRuntime::VTableInfo> + GetVTableInfo(ValueObject &in_value, bool check_type) override; + bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, @@ -71,7 +75,7 @@ public: bool catch_bp, bool throw_bp) override; lldb::SearchFilterSP CreateExceptionSearchFilter() override; - + lldb::ValueObjectSP GetExceptionObjectForThread( lldb::ThreadSP thread_sp) override; @@ -89,24 +93,33 @@ protected: private: typedef std::map<lldb_private::Address, TypeAndOrName> DynamicTypeCache; + typedef std::map<lldb_private::Address, VTableInfo> VTableInfoCache; ItaniumABILanguageRuntime(Process *process) : // Call CreateInstance instead. - lldb_private::CPPLanguageRuntime(process), m_cxx_exception_bp_sp(), - m_dynamic_type_map(), m_dynamic_type_map_mutex() {} + lldb_private::CPPLanguageRuntime(process) {} lldb::BreakpointSP m_cxx_exception_bp_sp; DynamicTypeCache m_dynamic_type_map; - std::mutex m_dynamic_type_map_mutex; + VTableInfoCache m_vtable_info_map; + std::mutex m_mutex; - TypeAndOrName GetTypeInfoFromVTableAddress(ValueObject &in_value, - lldb::addr_t original_ptr, - lldb::addr_t vtable_addr); + TypeAndOrName GetTypeInfo(ValueObject &in_value, + const VTableInfo &vtable_info); TypeAndOrName GetDynamicTypeInfo(const lldb_private::Address &vtable_addr); void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info); + + // Check if a compiler type has a vtable. + // + // If the compiler type is a pointer or a reference, this function will check + // if the pointee type has a vtable, else it will check the type passed in. + // + // Returns an error if the type of the value doesn't have a vtable with an + // explanation why, or returns an Error::success() if the type has a vtable. + llvm::Error TypeHasVTable(CompilerType compiler_type); }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index d298af92ba5e..920a5eba20ab 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -77,7 +77,7 @@ protected: void GetIVarInformation(); private: - static const uint32_t RW_REALIZED = (1 << 31); + static const uint32_t RW_REALIZED = (1u << 31); struct objc_class_t { ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass. @@ -173,7 +173,8 @@ private: } bool Read(Process *process, lldb::addr_t addr, - lldb::addr_t relative_method_lists_base_addr, bool, bool); + lldb::addr_t relative_selector_base_addr, bool is_small, + bool has_direct_sel); }; struct ivar_list_t { diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 2764a2aa39fa..5d7c5f38d180 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -311,8 +311,8 @@ public: const bool isSynthesizedAccessorStub = false; const bool isImplicitlyDeclared = true; const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = - clang::ObjCMethodDecl::None; + const clang::ObjCImplementationControl impControl = + clang::ObjCImplementationControl::None; const bool HasRelatedResultType = false; const bool for_expression = true; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 80c7bd071d6b..f08f9f0f815d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -445,7 +445,7 @@ bool AppleObjCRuntime::ExceptionBreakpointsExplainStop( return false; uint64_t break_site_id = stop_reason->GetValue(); - return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint( + return m_process->GetBreakpointSiteList().StopPointSiteContainsBreakpoint( break_site_id, m_objc_exception_bp_sp->GetID()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 65f00f5e4d02..93168c23f354 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -161,7 +161,7 @@ AppleObjCRuntimeV1::CreateObjectChecker(std::string name, " \n", name.c_str()); assert(strformatsize < (int)sizeof(buf->contents)); - (void)strformatsize; + UNUSED_IF_ASSERT_DISABLED(strformatsize); return GetTargetRef().CreateUtilityFunction(buf->contents, std::move(name), eLanguageTypeC, exe_ctx); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index d5357b94d68e..dc492ac0f06d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -917,7 +917,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { std::unique_ptr<RegularExpression> regex_up; switch (command.GetArgumentCount()) { case 0: @@ -929,14 +929,14 @@ protected: result.AppendError( "invalid argument - please provide a valid regular expression"); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } break; } default: { result.AppendError("please provide 0 or 1 arguments"); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } } @@ -997,11 +997,10 @@ protected: } } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); - return true; + return; } result.AppendError("current process has no Objective-C runtime loaded"); result.SetStatus(lldb::eReturnStatusFailed); - return false; } CommandOptions m_options; @@ -1034,11 +1033,11 @@ public: ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default; protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { if (command.GetArgumentCount() == 0) { result.AppendError("this command requires arguments"); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } Process *process = m_exe_ctx.GetProcessPtr(); @@ -1048,7 +1047,7 @@ protected: if (!objc_runtime) { result.AppendError("current process has no Objective-C runtime loaded"); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = @@ -1056,7 +1055,7 @@ protected: if (!tagged_ptr_vendor) { result.AppendError("current process has no tagged pointer support"); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } for (size_t i = 0; i < command.GetArgumentCount(); i++) { @@ -1071,7 +1070,7 @@ protected: result.AppendErrorWithFormatv( "could not convert '{0}' to a valid address\n", arg_str); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } if (!tagged_ptr_vendor->IsPossibleTaggedPointer(arg_addr)) { @@ -1084,7 +1083,7 @@ protected: result.AppendErrorWithFormatv( "could not get class descriptor for {0:x16}\n", arg_addr); result.SetStatus(lldb::eReturnStatusFailed); - return false; + return; } uint64_t info_bits = 0; @@ -1106,7 +1105,6 @@ protected: } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); - return true; } }; @@ -1399,7 +1397,7 @@ public: return *this; } - const element operator*() const { + element operator*() const { if (m_index == -1) { // TODO find a way to make this an error, but not an assert return element(); @@ -2643,7 +2641,7 @@ static bool DoesProcessHaveSharedCache(Process &process) { return true; // this should not happen llvm::StringRef platform_plugin_name_sr = platform_sp->GetPluginName(); - if (platform_plugin_name_sr.endswith("-simulator")) + if (platform_plugin_name_sr.ends_with("-simulator")) return false; return true; @@ -2733,13 +2731,13 @@ lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); llvm::StringRef class_prefix("OBJC_CLASS_$_"); - if (name_strref.startswith(ivar_prefix)) { + if (name_strref.starts_with(ivar_prefix)) { llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size()); std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.'); - if (class_and_ivar.first.size() && class_and_ivar.second.size()) { + if (!class_and_ivar.first.empty() && !class_and_ivar.second.empty()) { const ConstString class_name_cs(class_and_ivar.first); ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs); @@ -2766,7 +2764,7 @@ lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { ivar_func); } } - } else if (name_strref.startswith(class_prefix)) { + } else if (name_strref.starts_with(class_prefix)) { llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size()); const ConstString class_name_cs(class_skipped_prefix); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 678865ecd918..c9d0b3a907b5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -65,12 +65,12 @@ public: return ObjCRuntimeVersions::eAppleObjC_V2; } - size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, + size_t GetByteOffsetForIvar(CompilerType &parent_ast_type, const char *ivar_name) override; void UpdateISAToDescriptorMapIfNeeded() override; - ClassDescriptorSP GetClassDescriptor(ValueObject &in_value) override; + ClassDescriptorSP GetClassDescriptor(ValueObject &valobj) override; ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index 940e66afa0c0..2b8adeae10d1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -13,7 +13,6 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 2cc5319c84bb..ca582cb1d5a4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -81,13 +81,13 @@ AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx, clang::QualType AppleObjCTypeEncodingParser::BuildStruct( TypeSystemClang &ast_ctx, StringLexer &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, _C_STRUCT_B, _C_STRUCT_E, - clang::TTK_Struct); + llvm::to_underlying(clang::TagTypeKind::Struct)); } clang::QualType AppleObjCTypeEncodingParser::BuildUnion( TypeSystemClang &ast_ctx, StringLexer &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, _C_UNION_B, _C_UNION_E, - clang::TTK_Union); + llvm::to_underlying(clang::TagTypeKind::Union)); } clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index 547a1f6db976..4093cbdd955f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -333,7 +333,7 @@ AppleThreadPlanStepThroughDirectDispatch::DoPlanExplainsStop(Event *event_ptr) { if (site_sp->IsBreakpointAtThisSite(break_sp->GetID())) { // If we aren't the only one with a breakpoint on this site, then we // should just stop and return control to the user. - if (site_sp->GetNumberOfOwners() > 1) { + if (site_sp->GetNumberOfConstituents() > 1) { SetPlanComplete(true); return false; } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp index 214642f654e2..ba52444f0c2f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -10,7 +10,6 @@ #include "ObjCLanguageRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" -#include "lldb/Core/MappedHash.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/ValueObject.h" @@ -140,17 +139,10 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { if (!module_sp) return TypeSP(); - const bool exact_match = true; - const uint32_t max_matches = UINT32_MAX; - TypeList types; - - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files, - types); - - for (uint32_t i = 0; i < types.GetSize(); ++i) { - TypeSP type_sp(types.GetTypeAtIndex(i)); - + TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match); + TypeResults results; + module_sp->FindTypes(query, results); + for (const TypeSP &type_sp : results.GetTypeMap().Types()) { if (TypeSystemClang::IsObjCObjectOrInterfaceType( type_sp->GetForwardCompilerType())) { if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) { diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 957ecc223405..7aa5b8d81890 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -10,7 +10,6 @@ #if defined(_WIN32) || defined(__ANDROID__) // Defines from ar, missing on Windows -#define ARMAG "!<arch>\n" #define SARMAG 8 #define ARFMAG "`\n" @@ -32,9 +31,11 @@ typedef struct ar_hdr { #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" +#include "llvm/Object/Archive.h" #include "llvm/Support/MemoryBuffer.h" using namespace lldb; @@ -49,158 +50,19 @@ ObjectContainerBSDArchive::Object::Object() : ar_name() {} void ObjectContainerBSDArchive::Object::Clear() { ar_name.Clear(); modification_time = 0; - uid = 0; - gid = 0; - mode = 0; size = 0; file_offset = 0; file_size = 0; } -lldb::offset_t ObjectContainerBSDArchive::Object::ExtractFromThin( - const DataExtractor &data, lldb::offset_t offset, - llvm::StringRef stringTable) { - size_t ar_name_len = 0; - std::string str; - char *err; - - // File header - // - // The common format is as follows. - // - // Offset Length Name Format - // 0 16 File name ASCII right padded with spaces (no spaces - // allowed in file name) - // 16 12 File mod Decimal as cstring right padded with - // spaces - // 28 6 Owner ID Decimal as cstring right padded with - // spaces - // 34 6 Group ID Decimal as cstring right padded with - // spaces - // 40 8 File mode Octal as cstring right padded with - // spaces - // 48 10 File byte size Decimal as cstring right padded with - // spaces - // 58 2 File magic 0x60 0x0A - - // Make sure there is enough data for the file header and bail if not - if (!data.ValidOffsetForDataOfSize(offset, 60)) - return LLDB_INVALID_OFFSET; - - str.assign((const char *)data.GetData(&offset, 16), 16); - if (!(llvm::StringRef(str).startswith("//") || stringTable.empty())) { - // Strip off any trailing spaces. - const size_t last_pos = str.find_last_not_of(' '); - if (last_pos != std::string::npos) { - if (last_pos + 1 < 16) - str.erase(last_pos + 1); - } - int start = strtoul(str.c_str() + 1, &err, 10); - int end = stringTable.find('\n', start); - str.assign(stringTable.data() + start, end - start - 1); - ar_name.SetCString(str.c_str()); - } - - str.assign((const char *)data.GetData(&offset, 12), 12); - modification_time = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 6), 6); - uid = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 6), 6); - gid = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 8), 8); - mode = strtoul(str.c_str(), &err, 8); - - str.assign((const char *)data.GetData(&offset, 10), 10); - size = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 2), 2); - if (str == ARFMAG) { - file_offset = offset; - file_size = size - ar_name_len; - return offset; - } - return LLDB_INVALID_OFFSET; -} - -lldb::offset_t -ObjectContainerBSDArchive::Object::Extract(const DataExtractor &data, - lldb::offset_t offset) { - size_t ar_name_len = 0; - std::string str; - char *err; - - // File header - // - // The common format is as follows. - // - // Offset Length Name Format - // 0 16 File name ASCII right padded with spaces (no spaces - // allowed in file name) - // 16 12 File mod Decimal as cstring right padded with - // spaces - // 28 6 Owner ID Decimal as cstring right padded with - // spaces - // 34 6 Group ID Decimal as cstring right padded with - // spaces - // 40 8 File mode Octal as cstring right padded with - // spaces - // 48 10 File byte size Decimal as cstring right padded with - // spaces - // 58 2 File magic 0x60 0x0A - - // Make sure there is enough data for the file header and bail if not - if (!data.ValidOffsetForDataOfSize(offset, 60)) - return LLDB_INVALID_OFFSET; - - str.assign((const char *)data.GetData(&offset, 16), 16); - if (llvm::StringRef(str).startswith("#1/")) { - // If the name is longer than 16 bytes, or contains an embedded space then - // it will use this format where the length of the name is here and the - // name characters are after this header. - ar_name_len = strtoul(str.c_str() + 3, &err, 10); - } else { - // Strip off any trailing spaces. - const size_t last_pos = str.find_last_not_of(' '); - if (last_pos != std::string::npos) { - if (last_pos + 1 < 16) - str.erase(last_pos + 1); - } - ar_name.SetCString(str.c_str()); - } - - str.assign((const char *)data.GetData(&offset, 12), 12); - modification_time = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 6), 6); - uid = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 6), 6); - gid = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 8), 8); - mode = strtoul(str.c_str(), &err, 8); - - str.assign((const char *)data.GetData(&offset, 10), 10); - size = strtoul(str.c_str(), &err, 10); - - str.assign((const char *)data.GetData(&offset, 2), 2); - if (str == ARFMAG) { - if (ar_name_len > 0) { - const void *ar_name_ptr = data.GetData(&offset, ar_name_len); - // Make sure there was enough data for the string value and bail if not - if (ar_name_ptr == nullptr) - return LLDB_INVALID_OFFSET; - str.assign((const char *)ar_name_ptr, ar_name_len); - ar_name.SetCString(str.c_str()); - } - file_offset = offset; - file_size = size - ar_name_len; - return offset; - } - return LLDB_INVALID_OFFSET; +void ObjectContainerBSDArchive::Object::Dump() const { + printf("name = \"%s\"\n", ar_name.GetCString()); + printf("mtime = 0x%8.8" PRIx32 "\n", modification_time); + printf("size = 0x%8.8" PRIx32 " (%" PRIu32 ")\n", size, size); + printf("file_offset = 0x%16.16" PRIx64 " (%" PRIu64 ")\n", file_offset, + file_offset); + printf("file_size = 0x%16.16" PRIx64 " (%" PRIu64 ")\n\n", file_size, + file_size); } ObjectContainerBSDArchive::Archive::Archive(const lldb_private::ArchSpec &arch, @@ -211,72 +73,79 @@ ObjectContainerBSDArchive::Archive::Archive(const lldb_private::ArchSpec &arch, : m_arch(arch), m_modification_time(time), m_file_offset(file_offset), m_objects(), m_data(data), m_archive_type(archive_type) {} +Log *l = GetLog(LLDBLog::Object); ObjectContainerBSDArchive::Archive::~Archive() = default; size_t ObjectContainerBSDArchive::Archive::ParseObjects() { DataExtractor &data = m_data; - std::string str; - lldb::offset_t offset = 0; - str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG); - if (str == ARMAG) { - Object obj; - do { - offset = obj.Extract(data, offset); - if (offset == LLDB_INVALID_OFFSET) - break; - size_t obj_idx = m_objects.size(); - m_objects.push_back(obj); - // Insert all of the C strings out of order for now... - m_object_name_to_index_map.Append(obj.ar_name, obj_idx); - offset += obj.file_size; - obj.Clear(); - } while (data.ValidOffset(offset)); - - // Now sort all of the object name pointers - m_object_name_to_index_map.Sort(); - } else if (str == ThinArchiveMagic) { - Object obj; - size_t obj_idx; - - // Retrieve symbol table - offset = obj.ExtractFromThin(data, offset, ""); - if (offset == LLDB_INVALID_OFFSET) - return m_objects.size(); - obj_idx = m_objects.size(); - m_objects.push_back(obj); - // Insert all of the C strings out of order for now... - m_object_name_to_index_map.Append(obj.ar_name, obj_idx); - offset += obj.file_size; - obj.Clear(); - // Retrieve string table - offset = obj.ExtractFromThin(data, offset, ""); - if (offset == LLDB_INVALID_OFFSET) - return m_objects.size(); - obj_idx = m_objects.size(); - m_objects.push_back(obj); - // Insert all of the C strings out of order for now... - m_object_name_to_index_map.Append(obj.ar_name, obj_idx); - // Extract string table - llvm::StringRef strtab((const char *)data.GetData(&offset, obj.size), - obj.size); + std::unique_ptr<llvm::MemoryBuffer> mem_buffer = + llvm::MemoryBuffer::getMemBuffer( + llvm::StringRef((const char *)data.GetDataStart(), + data.GetByteSize()), + llvm::StringRef(), + /*RequiresNullTerminator=*/false); + + auto exp_ar = llvm::object::Archive::create(mem_buffer->getMemBufferRef()); + if (!exp_ar) { + LLDB_LOG_ERROR(l, exp_ar.takeError(), "failed to create archive: {0}"); + return 0; + } + auto llvm_archive = std::move(exp_ar.get()); + + llvm::Error iter_err = llvm::Error::success(); + Object obj; + for (const auto &child: llvm_archive->children(iter_err)) { obj.Clear(); + auto exp_name = child.getName(); + if (exp_name) { + obj.ar_name = ConstString(exp_name.get()); + } else { + LLDB_LOG_ERROR(l, exp_name.takeError(), + "failed to get archive object name: {0}"); + continue; + } + + auto exp_mtime = child.getLastModified(); + if (exp_mtime) { + obj.modification_time = + std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::time_point_cast<std::chrono::seconds>( + exp_mtime.get()).time_since_epoch()).count(); + } else { + LLDB_LOG_ERROR(l, exp_mtime.takeError(), + "failed to get archive object time: {0}"); + continue; + } - // Retrieve object files - do { - offset = obj.ExtractFromThin(data, offset, strtab); - if (offset == LLDB_INVALID_OFFSET) - break; - obj_idx = m_objects.size(); - m_objects.push_back(obj); - // Insert all of the C strings out of order for now... - m_object_name_to_index_map.Append(obj.ar_name, obj_idx); - obj.Clear(); - } while (data.ValidOffset(offset)); - - // Now sort all of the object name pointers - m_object_name_to_index_map.Sort(); + auto exp_size = child.getRawSize(); + if (exp_size) { + obj.size = exp_size.get(); + } else { + LLDB_LOG_ERROR(l, exp_size.takeError(), + "failed to get archive object size: {0}"); + continue; + } + + obj.file_offset = child.getDataOffset(); + + auto exp_file_size = child.getSize(); + if (exp_file_size) { + obj.file_size = exp_file_size.get(); + } else { + LLDB_LOG_ERROR(l, exp_file_size.takeError(), + "failed to get archive object file size: {0}"); + continue; + } + m_object_name_to_index_map.Append(obj.ar_name, m_objects.size()); + m_objects.push_back(obj); + } + if (iter_err) { + LLDB_LOG_ERROR(l, std::move(iter_err), + "failed to iterate over archive objects: {0}"); } + // Now sort all of the object name pointers + m_object_name_to_index_map.Sort(); return m_objects.size(); } @@ -462,20 +331,21 @@ ObjectContainer *ObjectContainerBSDArchive::CreateInstance( ArchiveType ObjectContainerBSDArchive::MagicBytesMatch(const DataExtractor &data) { uint32_t offset = 0; - const char *armag = (const char *)data.PeekData(offset, sizeof(ar_hdr)); + const char *armag = (const char *)data.PeekData(offset, + sizeof(ar_hdr) + SARMAG); if (armag == nullptr) return ArchiveType::Invalid; - if (::strncmp(armag, ARMAG, SARMAG) == 0) { - armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG; - if (strncmp(armag, ARFMAG, 2) == 0) - return ArchiveType::Archive; - } else if (::strncmp(armag, ThinArchiveMagic, strlen(ThinArchiveMagic)) == - 0) { - armag += offsetof(struct ar_hdr, ar_fmag) + strlen(ThinArchiveMagic); - if (strncmp(armag, ARFMAG, 2) == 0) { - return ArchiveType::ThinArchive; - } - } + ArchiveType result = ArchiveType::Invalid; + if (strncmp(armag, ArchiveMagic, SARMAG) == 0) + result = ArchiveType::Archive; + else if (strncmp(armag, ThinArchiveMagic, SARMAG) == 0) + result = ArchiveType::ThinArchive; + else + return ArchiveType::Invalid; + + armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG; + if (strncmp(armag, ARFMAG, 2) == 0) + return result; return ArchiveType::Invalid; } @@ -540,7 +410,8 @@ ObjectFileSP ObjectContainerBSDArchive::GetObjectFile(const FileSpec *file) { std::shared_ptr<DataBuffer> child_data_sp = FileSystem::Instance().CreateDataBuffer(child, file_size, file_offset); - if (child_data_sp->GetByteSize() != object->file_size) + if (!child_data_sp || + child_data_sp->GetByteSize() != object->file_size) return ObjectFileSP(); lldb::offset_t data_offset = 0; return ObjectFile::FindPlugin( @@ -622,7 +493,7 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications( std::chrono::seconds(object->modification_time)); spec.GetObjectName() = object->ar_name; spec.SetObjectOffset(object_file_offset); - spec.SetObjectSize(file_size - object_file_offset); + spec.SetObjectSize(object->file_size); spec.GetObjectModificationTime() = object_mod_time; } } diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index 1e2ffce3e5e2..fbecd1d27063 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -93,15 +93,6 @@ protected: /// Object modification time in the archive. uint32_t modification_time = 0; - /// Object user id in the archive. - uint16_t uid = 0; - - /// Object group id in the archive. - uint16_t gid = 0; - - /// Object octal file permissions in the archive. - uint16_t mode = 0; - /// Object size in bytes in the archive. uint32_t size = 0; @@ -110,6 +101,8 @@ protected: /// Length of the object data. lldb::offset_t file_size = 0; + + void Dump() const; }; class Archive { diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp index 4f9661eb0cdf..2dc71d85777c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp @@ -158,7 +158,7 @@ ParseFileset(DataExtractor &data, mach_header header, if (lc.cmd == LC_FILESET_ENTRY) { fileset_entry_command entry; data.CopyData(load_cmd_offset, sizeof(fileset_entry_command), &entry); - lldb::offset_t entry_id_offset = load_cmd_offset + entry.entry_id; + lldb::offset_t entry_id_offset = load_cmd_offset + entry.entry_id.offset; const char *id = data.GetCStr(&entry_id_offset); entries.emplace_back(entry.vmaddr + slide, entry.fileoff, std::string(id)); diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp index b0afe0394622..d40f87b1a7b4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" +#include "lldb/lldb-defines.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Endian.h" @@ -119,7 +120,7 @@ static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) { uint32_t age; bool success = to_integer(age_str, age, 16); assert(success); - (void)success; + UNUSED_IF_ASSERT_DISABLED(success); data.age = age; // On non-windows, the age field should always be zero, so we don't include to diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp index 03c454bf3efa..a7ad5d27b237 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp @@ -271,9 +271,9 @@ void ObjectFileCOFF::ParseSymtab(lldb_private::Symtab &symtab) { const auto COFFSymRef = m_object->getCOFFSymbol(SymRef); Expected<StringRef> NameOrErr = SymRef.getName(); - if (auto error = NameOrErr.takeError()) { - LLDB_LOG(log, "ObjectFileCOFF: failed to get symbol name: {0}", - llvm::fmt_consume(std::move(error))); + if (!NameOrErr) { + LLDB_LOG_ERROR(log, NameOrErr.takeError(), + "ObjectFileCOFF: failed to get symbol name: {0}"); continue; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 700af84a14c0..43ab87f08e19 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -935,6 +935,16 @@ lldb_private::Address ObjectFileELF::GetEntryPointAddress() { } Address ObjectFileELF::GetBaseAddress() { + if (GetType() == ObjectFile::eTypeObjectFile) { + for (SectionHeaderCollIter I = std::next(m_section_headers.begin()); + I != m_section_headers.end(); ++I) { + const ELFSectionHeaderInfo &header = *I; + if (header.sh_flags & SHF_ALLOC) + return Address(GetSectionList()->FindSectionByID(SectionIndex(I)), 0); + } + return LLDB_INVALID_ADDRESS; + } + for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) { const ELFProgramHeader &H = EnumPHdr.value(); if (H.p_type != PT_LOAD) @@ -1679,6 +1689,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) { .Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink) .Case(".gosymtab", eSectionTypeGoSymtab) .Case(".text", eSectionTypeCode) + .Case(".swift_ast", eSectionTypeSwiftModules) .Default(eSectionTypeOther); } @@ -1763,7 +1774,12 @@ class VMAddressProvider { VMRange GetVMRange(const ELFSectionHeader &H) { addr_t Address = H.sh_addr; addr_t Size = H.sh_flags & SHF_ALLOC ? H.sh_size : 0; - if (ObjectType == ObjectFile::Type::eTypeObjectFile && Segments.empty() && (H.sh_flags & SHF_ALLOC)) { + + // When this is a debug file for relocatable file, the address is all zero + // and thus needs to use accumulate method + if ((ObjectType == ObjectFile::Type::eTypeObjectFile || + (ObjectType == ObjectFile::Type::eTypeDebugInfo && H.sh_addr == 0)) && + Segments.empty() && (H.sh_flags & SHF_ALLOC)) { NextVMAddress = llvm::alignTo(NextVMAddress, std::max<addr_t>(H.sh_addralign, 1)); Address = NextVMAddress; @@ -3453,10 +3469,28 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() { case llvm::ELF::ET_EXEC: // 2 - Executable file - // TODO: is there any way to detect that an executable is a kernel - // related executable by inspecting the program headers, section headers, - // symbols, or any other flag bits??? - return eStrataUser; + { + SectionList *section_list = GetSectionList(); + if (section_list) { + static ConstString loader_section_name(".interp"); + SectionSP loader_section = + section_list->FindSectionByName(loader_section_name); + if (loader_section) { + char buffer[256]; + size_t read_size = + ReadSectionData(loader_section.get(), 0, buffer, sizeof(buffer)); + + // We compare the content of .interp section + // It will contains \0 when counting read_size, so the size needs to + // decrease by one + llvm::StringRef loader_name(buffer, read_size - 1); + llvm::StringRef freebsd_kernel_loader_name("/red/herring"); + if (loader_name.equals(freebsd_kernel_loader_name)) + return eStrataKernel; + } + } + return eStrataUser; + } case llvm::ELF::ET_DYN: // 3 - Shared object file diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp index c396cb061c01..50d1b563f469 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp @@ -8,6 +8,7 @@ #include "MinidumpFileBuilder.h" +#include "Plugins/Process/minidump/RegisterContextMinidump_ARM64.h" #include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h" #include "lldb/Core/Module.h" @@ -293,7 +294,7 @@ Status MinidumpFileBuilder::AddModuleList(Target &target) { } uint16_t read_register_u16_raw(RegisterContext *reg_ctx, - const std::string ®_name) { + llvm::StringRef reg_name) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); if (!reg_info) return 0; @@ -305,7 +306,7 @@ uint16_t read_register_u16_raw(RegisterContext *reg_ctx, } uint32_t read_register_u32_raw(RegisterContext *reg_ctx, - const std::string ®_name) { + llvm::StringRef reg_name) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); if (!reg_info) return 0; @@ -317,7 +318,7 @@ uint32_t read_register_u32_raw(RegisterContext *reg_ctx, } uint64_t read_register_u64_raw(RegisterContext *reg_ctx, - const std::string ®_name) { + llvm::StringRef reg_name) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); if (!reg_info) return 0; @@ -329,25 +330,42 @@ uint64_t read_register_u64_raw(RegisterContext *reg_ctx, } llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx, - const std::string ®_name) { + llvm::StringRef reg_name) { return static_cast<llvm::support::ulittle16_t>( read_register_u16_raw(reg_ctx, reg_name)); } llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx, - const std::string ®_name) { + llvm::StringRef reg_name) { return static_cast<llvm::support::ulittle32_t>( read_register_u32_raw(reg_ctx, reg_name)); } llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx, - const std::string ®_name) { + llvm::StringRef reg_name) { return static_cast<llvm::support::ulittle64_t>( read_register_u64_raw(reg_ctx, reg_name)); } +void read_register_u128(RegisterContext *reg_ctx, llvm::StringRef reg_name, + uint8_t *dst) { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); + if (reg_info) { + lldb_private::RegisterValue reg_value; + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + Status error; + uint32_t bytes_copied = reg_value.GetAsMemoryData( + *reg_info, dst, 16, lldb::ByteOrder::eByteOrderLittle, error); + if (bytes_copied == 16) + return; + } + } + // If anything goes wrong, then zero out the register value. + memset(dst, 0, 16); +} + lldb_private::minidump::MinidumpContext_x86_64 -GetThreadContext_64(RegisterContext *reg_ctx) { +GetThreadContext_x86_64(RegisterContext *reg_ctx) { lldb_private::minidump::MinidumpContext_x86_64 thread_context = {}; thread_context.p1_home = {}; thread_context.context_flags = static_cast<uint32_t>( @@ -381,6 +399,71 @@ GetThreadContext_64(RegisterContext *reg_ctx) { return thread_context; } +minidump::RegisterContextMinidump_ARM64::Context +GetThreadContext_ARM64(RegisterContext *reg_ctx) { + minidump::RegisterContextMinidump_ARM64::Context thread_context = {}; + thread_context.context_flags = static_cast<uint32_t>( + minidump::RegisterContextMinidump_ARM64::Flags::ARM64_Flag | + minidump::RegisterContextMinidump_ARM64::Flags::Integer | + minidump::RegisterContextMinidump_ARM64::Flags::FloatingPoint); + char reg_name[16]; + for (uint32_t i = 0; i < 31; ++i) { + snprintf(reg_name, sizeof(reg_name), "x%u", i); + thread_context.x[i] = read_register_u64(reg_ctx, reg_name); + } + // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt + // name set to "x31" + thread_context.x[31] = read_register_u64(reg_ctx, "sp"); + thread_context.pc = read_register_u64(reg_ctx, "pc"); + thread_context.cpsr = read_register_u32(reg_ctx, "cpsr"); + thread_context.fpsr = read_register_u32(reg_ctx, "fpsr"); + thread_context.fpcr = read_register_u32(reg_ctx, "fpcr"); + for (uint32_t i = 0; i < 32; ++i) { + snprintf(reg_name, sizeof(reg_name), "v%u", i); + read_register_u128(reg_ctx, reg_name, &thread_context.v[i * 16]); + } + return thread_context; +} + +class ArchThreadContexts { + llvm::Triple::ArchType m_arch; + union { + lldb_private::minidump::MinidumpContext_x86_64 x86_64; + lldb_private::minidump::RegisterContextMinidump_ARM64::Context arm64; + }; + +public: + ArchThreadContexts(llvm::Triple::ArchType arch) : m_arch(arch) {} + + bool prepareRegisterContext(RegisterContext *reg_ctx) { + switch (m_arch) { + case llvm::Triple::ArchType::x86_64: + x86_64 = GetThreadContext_x86_64(reg_ctx); + return true; + case llvm::Triple::ArchType::aarch64: + arm64 = GetThreadContext_ARM64(reg_ctx); + return true; + default: + break; + } + return false; + } + + const void *data() const { return &x86_64; } + + size_t size() const { + switch (m_arch) { + case llvm::Triple::ArchType::x86_64: + return sizeof(x86_64); + case llvm::Triple::ArchType::aarch64: + return sizeof(arm64); + default: + break; + } + return 0; + } +}; + // Function returns start and size of the memory region that contains // memory location pointed to by the current stack pointer. llvm::Expected<std::pair<addr_t, addr_t>> @@ -434,11 +517,20 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) { return error; } RegisterContext *reg_ctx = reg_ctx_sp.get(); - auto thread_context = GetThreadContext_64(reg_ctx); - uint64_t rsp = read_register_u64_raw(reg_ctx, "rsp"); - auto expected_address_range = findStackHelper(process_sp, rsp); + Target &target = process_sp->GetTarget(); + const ArchSpec &arch = target.GetArchitecture(); + ArchThreadContexts thread_context(arch.GetMachine()); + if (!thread_context.prepareRegisterContext(reg_ctx)) { + error.SetErrorStringWithFormat( + "architecture %s not supported.", + arch.GetTriple().getArchName().str().c_str()); + return error; + } + uint64_t sp = reg_ctx->GetSP(); + auto expected_address_range = findStackHelper(process_sp, sp); if (!expected_address_range) { + consumeError(expected_address_range.takeError()); error.SetErrorString("Unable to get the stack address."); return error; } @@ -468,13 +560,13 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) { LocationDescriptor thread_context_memory_locator; thread_context_memory_locator.DataSize = - static_cast<llvm::support::ulittle32_t>(sizeof(thread_context)); + static_cast<llvm::support::ulittle32_t>(thread_context.size()); thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>( size_before + thread_stream_size + helper_data.GetByteSize()); + // Cache thie thread context memory so we can reuse for exceptions. + m_tid_to_reg_ctx[thread_sp->GetID()] = thread_context_memory_locator; - helper_data.AppendData( - &thread_context, - sizeof(lldb_private::minidump::MinidumpContext_x86_64)); + helper_data.AppendData(thread_context.data(), thread_context.size()); llvm::minidump::Thread t; t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); @@ -492,108 +584,76 @@ Status MinidumpFileBuilder::AddThreadList(const lldb::ProcessSP &process_sp) { return Status(); } -Status MinidumpFileBuilder::AddException(const lldb::ProcessSP &process_sp) { - Status error; +void MinidumpFileBuilder::AddExceptions(const lldb::ProcessSP &process_sp) { lldb_private::ThreadList thread_list = process_sp->GetThreadList(); const uint32_t num_threads = thread_list.GetSize(); - uint32_t stop_reason_thread_idx = 0; - for (stop_reason_thread_idx = 0; stop_reason_thread_idx < num_threads; - ++stop_reason_thread_idx) { - ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx)); + for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx)); StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); - - if (stop_info_sp && stop_info_sp->IsValid()) - break; - } - - if (stop_reason_thread_idx == num_threads) { - error.SetErrorString("No stop reason thread found."); - return error; + bool add_exception = false; + if (stop_info_sp) { + switch (stop_info_sp->GetStopReason()) { + case eStopReasonSignal: + case eStopReasonException: + add_exception = true; + break; + default: + break; + } + } + if (add_exception) { + constexpr size_t minidump_exception_size = + sizeof(llvm::minidump::ExceptionStream); + AddDirectory(StreamType::Exception, minidump_exception_size); + StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); + RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); + Exception exp_record = {}; + exp_record.ExceptionCode = + static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue()); + exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0); + exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0); + exp_record.ExceptionAddress = reg_ctx_sp->GetPC(); + exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0); + exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); + // exp_record.ExceptionInformation; + + ExceptionStream exp_stream; + exp_stream.ThreadId = + static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); + exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); + exp_stream.ExceptionRecord = exp_record; + auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID()); + if (Iter != m_tid_to_reg_ctx.end()) { + exp_stream.ThreadContext = Iter->second; + } else { + exp_stream.ThreadContext.DataSize = 0; + exp_stream.ThreadContext.RVA = 0; + } + m_data.AppendData(&exp_stream, minidump_exception_size); + } } - - constexpr size_t minidump_exception_size = - sizeof(llvm::minidump::ExceptionStream); - AddDirectory(StreamType::Exception, minidump_exception_size); - size_t size_before = GetCurrentDataEndOffset(); - - ThreadSP thread_sp(thread_list.GetThreadAtIndex(stop_reason_thread_idx)); - RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); - RegisterContext *reg_ctx = reg_ctx_sp.get(); - auto thread_context = GetThreadContext_64(reg_ctx); - StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); - - DataBufferHeap helper_data; - - LocationDescriptor thread_context_memory_locator; - thread_context_memory_locator.DataSize = - static_cast<llvm::support::ulittle32_t>(sizeof(thread_context)); - thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>( - size_before + minidump_exception_size + helper_data.GetByteSize()); - - helper_data.AppendData( - &thread_context, sizeof(lldb_private::minidump::MinidumpContext_x86_64)); - - Exception exp_record = {}; - exp_record.ExceptionCode = - static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue()); - exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0); - exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0); - exp_record.ExceptionAddress = read_register_u64(reg_ctx, "rip"); - exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0); - exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); - // exp_record.ExceptionInformation; - - ExceptionStream exp_stream; - exp_stream.ThreadId = - static_cast<llvm::support::ulittle32_t>(thread_sp->GetID()); - exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0); - exp_stream.ExceptionRecord = exp_record; - exp_stream.ThreadContext = thread_context_memory_locator; - - m_data.AppendData(&exp_stream, minidump_exception_size); - m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize()); - return error; } lldb_private::Status -MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp) { +MinidumpFileBuilder::AddMemoryList(const lldb::ProcessSP &process_sp, + lldb::SaveCoreStyle core_style) { Status error; - + Process::CoreFileMemoryRanges core_ranges; + error = process_sp->CalculateCoreFileSaveRanges(core_style, core_ranges); if (error.Fail()) { error.SetErrorString("Process doesn't support getting memory region info."); return error; } - // Get interesting addresses - std::vector<size_t> interesting_addresses; - auto thread_list = process_sp->GetThreadList(); - for (size_t i = 0; i < thread_list.GetSize(); ++i) { - ThreadSP thread_sp(thread_list.GetThreadAtIndex(i)); - RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); - RegisterContext *reg_ctx = reg_ctx_sp.get(); - - interesting_addresses.push_back(read_register_u64(reg_ctx, "rsp")); - interesting_addresses.push_back(read_register_u64(reg_ctx, "rip")); - } - DataBufferHeap helper_data; std::vector<MemoryDescriptor> mem_descriptors; - - std::set<addr_t> visited_region_base_addresses; - for (size_t interesting_address : interesting_addresses) { - MemoryRegionInfo range_info; - error = process_sp->GetMemoryRegionInfo(interesting_address, range_info); - // Skip failed memory region requests or any regions with no permissions. - if (error.Fail() || range_info.GetLLDBPermissions() == 0) - continue; - const addr_t addr = range_info.GetRange().GetRangeBase(); - // Skip any regions we have already saved out. - if (visited_region_base_addresses.insert(addr).second == false) - continue; - const addr_t size = range_info.GetRange().GetByteSize(); - if (size == 0) + for (const auto &core_range : core_ranges) { + // Skip empty memory regions or any regions with no permissions. + if (core_range.range.empty() || core_range.lldb_permissions == 0) continue; + const addr_t addr = core_range.range.start(); + const addr_t size = core_range.range.size(); auto data_up = std::make_unique<DataBufferHeap>(size, 0); const size_t bytes_read = process_sp->ReadMemory(addr, data_up->GetBytes(), size, error); diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h index f4017fb66384..b2e984191983 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h @@ -17,6 +17,7 @@ #define LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H #include <cstddef> +#include <map> #include "lldb/Target/Target.h" #include "lldb/Utility/DataBufferHeap.h" @@ -59,12 +60,11 @@ public: // at the moment of core saving. Contains information about thread // contexts. lldb_private::Status AddThreadList(const lldb::ProcessSP &process_sp); - // Add Exception stream, this contains information about the exception - // that stopped the process. In case no thread made exception it return - // failed status. - lldb_private::Status AddException(const lldb::ProcessSP &process_sp); + // Add Exception streams for any threads that stopped with exceptions. + void AddExceptions(const lldb::ProcessSP &process_sp); // Add MemoryList stream, containing dumps of important memory segments - lldb_private::Status AddMemoryList(const lldb::ProcessSP &process_sp); + lldb_private::Status AddMemoryList(const lldb::ProcessSP &process_sp, + lldb::SaveCoreStyle core_style); // Add MiscInfo stream, mainly providing ProcessId void AddMiscInfo(const lldb::ProcessSP &process_sp); // Add informative files about a Linux process @@ -87,6 +87,11 @@ private: // Main data buffer consisting of data without the minidump header and // directories lldb_private::DataBufferHeap m_data; + + // More that one place can mention the register thread context locations, + // so when we emit the thread contents, remember where it is so we don't have + // to duplicate it in the exception data. + std::map<lldb::tid_t, llvm::minidump::LocationDescriptor> m_tid_to_reg_ctx; }; #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp index 17b37afe557d..fe609c7f3d20 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp @@ -57,10 +57,9 @@ bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp, const lldb_private::FileSpec &outfile, lldb::SaveCoreStyle &core_style, lldb_private::Status &error) { - if (core_style != SaveCoreStyle::eSaveCoreStackOnly) { - error.SetErrorString("Only stack minidumps supported yet."); - return false; - } + // Set default core style if it isn't set. + if (core_style == SaveCoreStyle::eSaveCoreUnspecified) + core_style = SaveCoreStyle::eSaveCoreStackOnly; if (!process_sp) return false; @@ -79,19 +78,16 @@ bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp, builder.AddMiscInfo(process_sp); - if (target.GetArchitecture().GetMachine() == llvm::Triple::ArchType::x86_64) { - error = builder.AddThreadList(process_sp); - if (error.Fail()) - return false; + error = builder.AddThreadList(process_sp); + if (error.Fail()) + return false; - error = builder.AddException(process_sp); - if (error.Fail()) - return false; + // Add any exceptions but only if there are any in any threads. + builder.AddExceptions(process_sp); - error = builder.AddMemoryList(process_sp); - if (error.Fail()) - return false; - } + error = builder.AddMemoryList(process_sp, core_style); + if (error.Fail()) + return false; if (target.GetArchitecture().GetTriple().getOS() == llvm::Triple::OSType::Linux) { diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp index a3b91fc37dac..f0832dbf0734 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -179,7 +179,7 @@ ObjectFilePDB::loadPDBFile(std::string PdbPath, llvm::StringRef Path = Buffer->getBufferIdentifier(); auto Stream = std::make_unique<llvm::MemoryBufferByteStream>( - std::move(Buffer), llvm::support::little); + std::move(Buffer), llvm::endianness::little); auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator); if (auto EC = File->parseFileHeaders()) { diff --git a/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 9560ae108f3e..81ee7e328b6c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -74,47 +74,71 @@ llvm::StringRef OperatingSystemPython::GetPluginDescriptionStatic() { OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process, const FileSpec &python_module_path) : OperatingSystem(process), m_thread_list_valobj_sp(), m_register_info_up(), - m_interpreter(nullptr), m_python_object_sp() { + m_interpreter(nullptr), m_script_object_sp() { if (!process) return; TargetSP target_sp = process->CalculateTarget(); if (!target_sp) return; m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); - if (m_interpreter) { - - std::string os_plugin_class_name( - python_module_path.GetFilename().AsCString("")); - if (!os_plugin_class_name.empty()) { - LoadScriptOptions options; - char python_module_path_cstr[PATH_MAX]; - python_module_path.GetPath(python_module_path_cstr, - sizeof(python_module_path_cstr)); - Status error; - if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options, - error)) { - // Strip the ".py" extension if there is one - size_t py_extension_pos = os_plugin_class_name.rfind(".py"); - if (py_extension_pos != std::string::npos) - os_plugin_class_name.erase(py_extension_pos); - // Add ".OperatingSystemPlugIn" to the module name to get a string like - // "modulename.OperatingSystemPlugIn" - os_plugin_class_name += ".OperatingSystemPlugIn"; - StructuredData::ObjectSP object_sp = - m_interpreter->OSPlugin_CreatePluginObject( - os_plugin_class_name.c_str(), process->CalculateProcess()); - if (object_sp && object_sp->IsValid()) - m_python_object_sp = object_sp; - } - } + if (!m_interpreter) + return; + + std::string os_plugin_class_name( + python_module_path.GetFilename().AsCString("")); + if (os_plugin_class_name.empty()) + return; + + LoadScriptOptions options; + char python_module_path_cstr[PATH_MAX]; + python_module_path.GetPath(python_module_path_cstr, + sizeof(python_module_path_cstr)); + Status error; + if (!m_interpreter->LoadScriptingModule(python_module_path_cstr, options, + error)) + return; + + // Strip the ".py" extension if there is one + size_t py_extension_pos = os_plugin_class_name.rfind(".py"); + if (py_extension_pos != std::string::npos) + os_plugin_class_name.erase(py_extension_pos); + // Add ".OperatingSystemPlugIn" to the module name to get a string like + // "modulename.OperatingSystemPlugIn" + os_plugin_class_name += ".OperatingSystemPlugIn"; + + auto operating_system_interface = + m_interpreter->CreateOperatingSystemInterface(); + if (!operating_system_interface) + // FIXME: We should pass an Status& to raise the error to the user. + // return llvm::createStringError( + // llvm::inconvertibleErrorCode(), + // "Failed to create scripted thread interface."); + return; + + ExecutionContext exe_ctx(process); + auto obj_or_err = operating_system_interface->CreatePluginObject( + os_plugin_class_name, exe_ctx, nullptr); + + if (!obj_or_err) { + llvm::consumeError(obj_or_err.takeError()); + return; } + + StructuredData::GenericSP owned_script_object_sp = *obj_or_err; + if (!owned_script_object_sp->IsValid()) + // return llvm::createStringError(llvm::inconvertibleErrorCode(), + // "Created script object is invalid."); + return; + + m_script_object_sp = owned_script_object_sp; + m_operating_system_interface_sp = operating_system_interface; } OperatingSystemPython::~OperatingSystemPython() = default; DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { if (m_register_info_up == nullptr) { - if (!m_interpreter || !m_python_object_sp) + if (!m_interpreter || !m_operating_system_interface_sp) return nullptr; Log *log = GetLog(LLDBLog::OS); @@ -124,7 +148,7 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { m_process->GetID()); StructuredData::DictionarySP dictionary = - m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp); + m_operating_system_interface_sp->GetRegisterInfo(); if (!dictionary) return nullptr; @@ -140,27 +164,11 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, ThreadList &core_thread_list, ThreadList &new_thread_list) { - if (!m_interpreter || !m_python_object_sp) + if (!m_interpreter || !m_operating_system_interface_sp) return false; Log *log = GetLog(LLDBLog::OS); - // First thing we have to do is to try to get the API lock, and the - // interpreter lock. We're going to change the thread content of the process, - // and we're going to use python, which requires the API lock to do it. We - // need the interpreter lock to make sure thread_info_dict stays alive. - // - // If someone already has the API lock, that is ok, we just want to avoid - // external code from making new API calls while this call is happening. - // - // This is a recursive lock so we can grant it to any Python code called on - // the stack below us. - Target &target = m_process->GetTarget(); - std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(), - std::defer_lock); - (void)api_lock.try_lock(); // See above. - auto interpreter_lock = m_interpreter->AcquireInterpreterLock(); - LLDB_LOGF(log, "OperatingSystemPython::UpdateThreadList() fetching thread " "data from python for pid %" PRIu64, @@ -170,7 +178,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, // the lldb_private::Process subclass, no memory threads will be in this // list. StructuredData::ArraySP threads_list = - m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp); + m_operating_system_interface_sp->GetThreadInfo(); const uint32_t num_cores = core_thread_list.GetSize(false); @@ -281,28 +289,12 @@ RegisterContextSP OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, addr_t reg_data_addr) { RegisterContextSP reg_ctx_sp; - if (!m_interpreter || !m_python_object_sp || !thread) + if (!m_interpreter || !m_script_object_sp || !thread) return reg_ctx_sp; if (!IsOperatingSystemPluginThread(thread->shared_from_this())) return reg_ctx_sp; - // First thing we have to do is to try to get the API lock, and the - // interpreter lock. We're going to change the thread content of the process, - // and we're going to use python, which requires the API lock to do it. We - // need the interpreter lock to make sure thread_info_dict stays alive. - // - // If someone already has the API lock, that is ok, we just want to avoid - // external code from making new API calls while this call is happening. - // - // This is a recursive lock so we can grant it to any Python code called on - // the stack below us. - Target &target = m_process->GetTarget(); - std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(), - std::defer_lock); - (void)api_lock.try_lock(); // See above. - auto interpreter_lock = m_interpreter->AcquireInterpreterLock(); - Log *log = GetLog(LLDBLog::Thread); if (reg_data_addr != LLDB_INVALID_ADDRESS) { @@ -324,11 +316,11 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, ") fetching register data from python", thread->GetID(), thread->GetProtocolID()); - StructuredData::StringSP reg_context_data = - m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp, - thread->GetID()); + std::optional<std::string> reg_context_data = + m_operating_system_interface_sp->GetRegisterContextForTID( + thread->GetID()); if (reg_context_data) { - std::string value = std::string(reg_context_data->GetValue()); + std::string value = *reg_context_data; DataBufferSP data_sp(new DataBufferHeap(value.c_str(), value.length())); if (data_sp->GetByteSize()) { RegisterContextMemory *reg_ctx_memory = new RegisterContextMemory( @@ -347,6 +339,7 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, "OperatingSystemPython::CreateRegisterContextForThread (tid " "= 0x%" PRIx64 ") forcing a dummy register context", thread->GetID()); + Target &target = m_process->GetTarget(); reg_ctx_sp = std::make_shared<RegisterContextDummy>( *thread, 0, target.GetArchitecture().GetAddressByteSize()); } @@ -372,26 +365,11 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid, ", context = 0x%" PRIx64 ") fetching register data from python", tid, context); - if (m_interpreter && m_python_object_sp) { - // First thing we have to do is to try to get the API lock, and the - // interpreter lock. We're going to change the thread content of the - // process, and we're going to use python, which requires the API lock to - // do it. We need the interpreter lock to make sure thread_info_dict stays - // alive. - // - // If someone already has the API lock, that is ok, we just want to avoid - // external code from making new API calls while this call is happening. - // - // This is a recursive lock so we can grant it to any Python code called on - // the stack below us. - Target &target = m_process->GetTarget(); - std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(), - std::defer_lock); - (void)api_lock.try_lock(); // See above. - auto interpreter_lock = m_interpreter->AcquireInterpreterLock(); + if (m_interpreter && m_script_object_sp) { StructuredData::DictionarySP thread_info_dict = - m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context); + m_operating_system_interface_sp->CreateThread(tid, context); + std::vector<bool> core_used_map; if (thread_info_dict) { ThreadList core_threads(m_process); diff --git a/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h index 7800cf03af8e..90973acde3eb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h +++ b/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h @@ -62,7 +62,7 @@ public: protected: bool IsValid() const { - return m_python_object_sp && m_python_object_sp->IsValid(); + return m_script_object_sp && m_script_object_sp->IsValid(); } lldb::ThreadSP CreateThreadFromThreadInfo( @@ -75,8 +75,9 @@ protected: lldb::ValueObjectSP m_thread_list_valobj_sp; std::unique_ptr<lldb_private::DynamicRegisterInfo> m_register_info_up; - lldb_private::ScriptInterpreter *m_interpreter; - lldb_private::StructuredData::ObjectSP m_python_object_sp; + lldb_private::ScriptInterpreter *m_interpreter = nullptr; + lldb::OperatingSystemInterfaceSP m_operating_system_interface_sp = nullptr; + lldb_private::StructuredData::GenericSP m_script_object_sp = nullptr; }; #endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 7abc71a1c53f..d7584be2b95e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -206,7 +206,7 @@ CompilerType PlatformFreeBSD::GetSiginfoType(const llvm::Triple &triple) { CompilerType sigval_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t", - clang::TTK_Union, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(sigval_type); ast->AddFieldToRecordType(sigval_type, "sival_int", int_type, lldb::eAccessPublic, 0); @@ -217,7 +217,7 @@ CompilerType PlatformFreeBSD::GetSiginfoType(const llvm::Triple &triple) { // siginfo_t CompilerType siginfo_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t", - clang::TTK_Struct, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(siginfo_type); ast->AddFieldToRecordType(siginfo_type, "si_signo", int_type, lldb::eAccessPublic, 0); @@ -239,7 +239,7 @@ CompilerType PlatformFreeBSD::GetSiginfoType(const llvm::Triple &triple) { // union used to hold the signal data CompilerType union_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", - clang::TTK_Union, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(union_type); ast->AddFieldToRecordType( diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index 393519d708d3..ce81aab55706 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -228,7 +228,7 @@ CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) { CompilerType sigval_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t", - clang::TTK_Union, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(sigval_type); ast->AddFieldToRecordType(sigval_type, "sival_int", int_type, lldb::eAccessPublic, 0); @@ -238,7 +238,7 @@ CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) { CompilerType ptrace_option_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", - clang::TTK_Union, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(ptrace_option_type); ast->AddFieldToRecordType(ptrace_option_type, "_pe_other_pid", pid_type, lldb::eAccessPublic, 0); @@ -249,13 +249,13 @@ CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) { // siginfo_t CompilerType siginfo_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t", - clang::TTK_Union, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(siginfo_type); // struct _ksiginfo CompilerType ksiginfo_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", - clang::TTK_Struct, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(ksiginfo_type); ast->AddFieldToRecordType(ksiginfo_type, "_signo", int_type, lldb::eAccessPublic, 0); @@ -272,7 +272,7 @@ CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) { // union used to hold the signal data CompilerType union_type = ast->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", - clang::TTK_Union, lldb::eLanguageTypeC); + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); ast->StartTagDeclarationDefinition(union_type); ast->AddFieldToRecordType( diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 1e91f2ccd198..b4f1b76c39db 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -949,7 +949,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, uint32_t image_token) { const addr_t image_addr = process->GetImagePtrFromToken(image_token); - if (image_addr == LLDB_INVALID_ADDRESS) + if (image_addr == LLDB_INVALID_IMAGE_TOKEN) return Status("Invalid image token"); StreamString expr; diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp index 72a039d18872..460f5560573d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp @@ -36,7 +36,7 @@ class PluginProperties : public Properties { public: PluginProperties() { m_collection_sp = std::make_shared<OptionValueProperties>( - ConstString(PlatformQemuUser::GetPluginNameStatic())); + PlatformQemuUser::GetPluginNameStatic()); m_collection_sp->Initialize(g_platformqemuuser_properties); } @@ -89,8 +89,8 @@ void PlatformQemuUser::Terminate() { } void PlatformQemuUser::DebuggerInitialize(Debugger &debugger) { - if (!PluginManager::GetSettingForPlatformPlugin( - debugger, ConstString(GetPluginNameStatic()))) { + if (!PluginManager::GetSettingForPlatformPlugin(debugger, + GetPluginNameStatic())) { PluginManager::CreateSettingForPlatformPlugin( debugger, GetGlobalProperties().GetValueProperties(), "Properties for the qemu-user platform plugin.", @@ -162,9 +162,18 @@ lldb::ProcessSP PlatformQemuUser::DebugProcess(ProcessLaunchInfo &launch_info, Target &target, Status &error) { Log *log = GetLog(LLDBLog::Platform); + // If platform.plugin.qemu-user.emulator-path is set, use it. FileSpec qemu = GetGlobalProperties().GetEmulatorPath(); - if (!qemu) - qemu.SetPath(("qemu-" + GetGlobalProperties().GetArchitecture()).str()); + // If platform.plugin.qemu-user.emulator-path is not set, build the + // executable name from platform.plugin.qemu-user.architecture. + if (!qemu) { + llvm::StringRef arch = GetGlobalProperties().GetArchitecture(); + // If platform.plugin.qemu-user.architecture is not set, build the + // executable name from the target Triple's ArchName + if (arch.empty()) + arch = target.GetArchitecture().GetTriple().getArchName(); + qemu.SetPath(("qemu-" + arch).str()); + } FileSystem::Instance().ResolveExecutableLocation(qemu); llvm::SmallString<0> socket_model, socket_path; diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 053d79b8c3b5..88f1ad15b6b4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -15,7 +15,6 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -29,10 +28,12 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/FormatAdapters.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" +#include <mutex> #include <optional> using namespace lldb; @@ -42,6 +43,11 @@ using namespace lldb_private::platform_gdb_server; LLDB_PLUGIN_DEFINE_ADV(PlatformRemoteGDBServer, PlatformGDB) static bool g_initialized = false; +// UnixSignals does not store the signal names or descriptions itself. +// It holds onto StringRefs. Becaue we may get signal information dynamically +// from the remote, these strings need persistent storage client-side. +static std::mutex g_signal_string_mutex; +static llvm::StringSet<> g_signal_string_storage; void PlatformRemoteGDBServer::Initialize() { Platform::Initialize(); @@ -750,8 +756,18 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { if (object_sp && object_sp->IsValid()) description = std::string(object_sp->GetStringValue()); - remote_signals_sp->AddSignal(signo, name.str().c_str(), suppress, stop, - notify, description.c_str()); + llvm::StringRef name_backed, description_backed; + { + std::lock_guard<std::mutex> guard(g_signal_string_mutex); + name_backed = + g_signal_string_storage.insert(name).first->getKeyData(); + if (!description.empty()) + description_backed = + g_signal_string_storage.insert(description).first->getKeyData(); + } + + remote_signals_sp->AddSignal(signo, name_backed, suppress, stop, notify, + description_backed); return true; }); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp index 84a009be50bf..19e0986ace31 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp @@ -69,7 +69,7 @@ NativeProcessFreeBSD::Manager::Launch(ProcessLaunchInfo &launch_info, int wstatus; ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); assert(wpid == pid); - (void)wpid; + UNUSED_IF_ASSERT_DISABLED(wpid); if (!WIFSTOPPED(wstatus)) { LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", WaitStatus::Decode(wstatus)); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp index 30eace1ba94f..0019b4d65f15 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp @@ -10,7 +10,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Target/DynamicLoader.h" -#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" +#include "Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h" #include "ProcessFreeBSDKernel.h" #include "ThreadFreeBSDKernel.h" @@ -267,7 +267,7 @@ Status ProcessFreeBSDKernel::DoLoadCore() { DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() { if (m_dyld_up.get() == nullptr) m_dyld_up.reset(DynamicLoader::FindPlugin( - this, DynamicLoaderStatic::GetPluginNameStatic())); + this, DynamicLoaderFreeBSDKernel::GetPluginNameStatic())); return m_dyld_up.get(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 26c562bd4790..451bb4866037 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -379,6 +379,29 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { SetState(StateType::eStateStopped, true); } +Status NativeProcessNetBSD::StopProcess(lldb::pid_t pid) { +#ifdef PT_STOP + return PtraceWrapper(PT_STOP, pid); +#else + Log *log = GetLog(POSIXLog::Ptrace); + Status error; + int ret; + + errno = 0; + ret = kill(pid, SIGSTOP); + + if (ret == -1) + error.SetErrorToErrno(); + + LLDB_LOG(log, "kill({0}, SIGSTOP)", pid); + + if (error.Fail()) + LLDB_LOG(log, "kill() failed: {0}", error); + + return error; +#endif +} + Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, int *result) { Log *log = GetLog(POSIXLog::Ptrace); @@ -531,7 +554,7 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { return ret; } -Status NativeProcessNetBSD::Halt() { return PtraceWrapper(PT_STOP, GetID()); } +Status NativeProcessNetBSD::Halt() { return StopProcess(GetID()); } Status NativeProcessNetBSD::Detach() { Status error; @@ -555,9 +578,7 @@ Status NativeProcessNetBSD::Signal(int signo) { return error; } -Status NativeProcessNetBSD::Interrupt() { - return PtraceWrapper(PT_STOP, GetID()); -} +Status NativeProcessNetBSD::Interrupt() { return StopProcess(GetID()); } Status NativeProcessNetBSD::Kill() { Log *log = GetLog(POSIXLog::Process); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 86724fdd5b7e..f3d07651384f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -88,6 +88,7 @@ public: // Interface used by NativeRegisterContext-derived classes. static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, int data = 0, int *result = nullptr); + static Status StopProcess(lldb::pid_t pid); llvm::Expected<std::string> SaveCore(llvm::StringRef path_hint) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 0a1f34ec6b4e..32c71d87c7f5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -9,7 +9,6 @@ #include "InferiorCallPOSIX.h" #include "lldb/Core/Address.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Host/Config.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h index 817dca336de7..8b5393ca1888 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h @@ -152,6 +152,8 @@ struct user_sve_header { uint16_t reserved; }; +using user_za_header = user_sve_header; + /* Definitions for user_sve_header.flags: */ const uint16_t ptrace_regs_mask = 1 << 0; const uint16_t ptrace_regs_fpsimd = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NetBSDSignals.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NetBSDSignals.h index e6740a304a02..94bad7c19a49 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NetBSDSignals.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NetBSDSignals.h @@ -1,4 +1,4 @@ -//===-- NetBSDSignals.h ----------------------------------------*- C++ -*-===// +//===-- NetBSDSignals.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. diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp index ba089190bd22..a160c87db6cf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp @@ -1,10 +1,10 @@ -//===-- RegisterContextNetBSD_i386.cpp -------------------------*- C++ -*-===// +//===-- RegisterContextNetBSD_i386.cpp --------------------------*- 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 // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #include "RegisterContextNetBSD_i386.h" #include "RegisterContextPOSIX_x86.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h index b7b8d33b7c37..6f9787506013 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h @@ -1,4 +1,4 @@ -//===-- RegisterContextNetBSD_x86_64.h -------------------------*- C++ -*-===// +//===-- RegisterContextNetBSD_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. diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index d306c818e89f..50e25568f2ae 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -43,6 +43,10 @@ bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const { return m_register_info_up->IsSVEReg(reg); } +bool RegisterContextPOSIX_arm64::IsSME(unsigned reg) const { + return m_register_info_up->IsSMEReg(reg); +} + bool RegisterContextPOSIX_arm64::IsPAuth(unsigned reg) const { return m_register_info_up->IsPAuthReg(reg); } @@ -51,6 +55,10 @@ bool RegisterContextPOSIX_arm64::IsTLS(unsigned reg) const { return m_register_info_up->IsTLSReg(reg); } +bool RegisterContextPOSIX_arm64::IsMTE(unsigned reg) const { + return m_register_info_up->IsMTEReg(reg); +} + RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( lldb_private::Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index 6a935274fc40..b1226b25b4be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -56,12 +56,17 @@ protected: bool IsSVE(unsigned reg) const; bool IsPAuth(unsigned reg) const; bool IsTLS(unsigned reg) const; + bool IsSME(unsigned reg) const; + bool IsMTE(unsigned reg) const; bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); } bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); } bool IsSVEVG(unsigned reg) const { return m_register_info_up->IsSVERegVG(reg); } + bool IsSMEZA(unsigned reg) const { + return m_register_info_up->IsSMERegZA(reg); + } uint32_t GetRegNumSVEZ0() const { return m_register_info_up->GetRegNumSVEZ0(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp new file mode 100644 index 000000000000..51553817921f --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp @@ -0,0 +1,202 @@ +//===-- RegisterFlagsLinux_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 "RegisterFlagsLinux_arm64.h" +#include "lldb/lldb-private-types.h" + +// This file is built on all systems because it is used by native processes and +// core files, so we manually define the needed HWCAP values here. + +#define HWCAP_FPHP (1ULL << 9) +#define HWCAP_ASIMDHP (1ULL << 10) +#define HWCAP_DIT (1ULL << 24) +#define HWCAP_SSBS (1ULL << 28) + +#define HWCAP2_BTI (1ULL << 17) +#define HWCAP2_MTE (1ULL << 18) +#define HWCAP2_AFP (1ULL << 20) +#define HWCAP2_EBF16 (1ULL << 32) + +using namespace lldb_private; + +LinuxArm64RegisterFlags::Fields +LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) { + (void)hwcap; + (void)hwcap2; + // Represents the pseudo register that lldb-server builds, which itself + // matches the architectural register SCVR. The fields match SVCR in the Arm + // manual. + return { + {"ZA", 1}, + {"SM", 0}, + }; +} + +LinuxArm64RegisterFlags::Fields +LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) { + (void)hwcap; + (void)hwcap2; + // Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed + // to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines + // used to build the value. + return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT. + {"TCF_ASYNC", 2}, + {"TCF_SYNC", 1}, + {"TAGGED_ADDR_ENABLE", 0}}; +} + +LinuxArm64RegisterFlags::Fields +LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) { + std::vector<RegisterFlags::Field> fpcr_fields{ + {"AHP", 26}, {"DN", 25}, {"FZ", 24}, {"RMode", 22, 23}, + // Bits 21-20 are "Stride" which is unused in AArch64 state. + }; + + // FEAT_FP16 is indicated by the presence of FPHP (floating point half + // precision) and ASIMDHP (Advanced SIMD half precision) features. + if ((hwcap & HWCAP_FPHP) && (hwcap & HWCAP_ASIMDHP)) + fpcr_fields.push_back({"FZ16", 19}); + + // Bits 18-16 are "Len" which is unused in AArch64 state. + + fpcr_fields.push_back({"IDE", 15}); + + // Bit 14 is unused. + if (hwcap2 & HWCAP2_EBF16) + fpcr_fields.push_back({"EBF", 13}); + + fpcr_fields.push_back({"IXE", 12}); + fpcr_fields.push_back({"UFE", 11}); + fpcr_fields.push_back({"OFE", 10}); + fpcr_fields.push_back({"DZE", 9}); + fpcr_fields.push_back({"IOE", 8}); + // Bits 7-3 reserved. + + if (hwcap2 & HWCAP2_AFP) { + fpcr_fields.push_back({"NEP", 2}); + fpcr_fields.push_back({"AH", 1}); + fpcr_fields.push_back({"FIZ", 0}); + } + + return fpcr_fields; +} + +LinuxArm64RegisterFlags::Fields +LinuxArm64RegisterFlags::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) { + // fpsr's contents are constant. + (void)hwcap; + (void)hwcap2; + + return { + // Bits 31-28 are N/Z/C/V, only used by AArch32. + {"QC", 27}, + // Bits 26-8 reserved. + {"IDC", 7}, + // Bits 6-5 reserved. + {"IXC", 4}, + {"UFC", 3}, + {"OFC", 2}, + {"DZC", 1}, + {"IOC", 0}, + }; +} + +LinuxArm64RegisterFlags::Fields +LinuxArm64RegisterFlags::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) { + // The fields here are a combination of the Arm manual's SPSR_EL1, + // plus a few changes where Linux has decided not to make use of them at all, + // or at least not from userspace. + + // Status bits that are always present. + std::vector<RegisterFlags::Field> cpsr_fields{ + {"N", 31}, {"Z", 30}, {"C", 29}, {"V", 28}, + // Bits 27-26 reserved. + }; + + if (hwcap2 & HWCAP2_MTE) + cpsr_fields.push_back({"TCO", 25}); + if (hwcap & HWCAP_DIT) + cpsr_fields.push_back({"DIT", 24}); + + // UAO and PAN are bits 23 and 22 and have no meaning for userspace so + // are treated as reserved by the kernel. + + cpsr_fields.push_back({"SS", 21}); + cpsr_fields.push_back({"IL", 20}); + // Bits 19-14 reserved. + + // Bit 13, ALLINT, requires FEAT_NMI that isn't relevant to userspace, and we + // can't detect either, don't show this field. + if (hwcap & HWCAP_SSBS) + cpsr_fields.push_back({"SSBS", 12}); + if (hwcap2 & HWCAP2_BTI) + cpsr_fields.push_back({"BTYPE", 10, 11}); + + cpsr_fields.push_back({"D", 9}); + cpsr_fields.push_back({"A", 8}); + cpsr_fields.push_back({"I", 7}); + cpsr_fields.push_back({"F", 6}); + // Bit 5 reserved + // Called "M" in the ARMARM. + cpsr_fields.push_back({"nRW", 4}); + // This is a 4 bit field M[3:0] in the ARMARM, we split it into parts. + cpsr_fields.push_back({"EL", 2, 3}); + // Bit 1 is unused and expected to be 0. + cpsr_fields.push_back({"SP", 0}); + + return cpsr_fields; +} + +void LinuxArm64RegisterFlags::DetectFields(uint64_t hwcap, uint64_t hwcap2) { + for (auto ® : m_registers) + reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2)); + m_has_detected = true; +} + +void LinuxArm64RegisterFlags::UpdateRegisterInfo(const RegisterInfo *reg_info, + uint32_t num_regs) { + assert(m_has_detected && + "Must call DetectFields before updating register info."); + + // Register names will not be duplicated, so we do not want to compare against + // one if it has already been found. Each time we find one, we erase it from + // this list. + std::vector<std::pair<llvm::StringRef, const RegisterFlags *>> + search_registers; + for (const auto ® : m_registers) { + // It is possible that a register is all extension dependent fields, and + // none of them are present. + if (reg.m_flags.GetFields().size()) + search_registers.push_back({reg.m_name, ®.m_flags}); + } + + // Walk register information while there are registers we know need + // to be updated. Example: + // Register information: [a, b, c, d] + // To be patched: [b, c] + // * a != b, a != c, do nothing and move on. + // * b == b, patch b, new patch list is [c], move on. + // * c == c, patch c, patch list is empty, exit early without looking at d. + for (uint32_t idx = 0; idx < num_regs && search_registers.size(); + ++idx, ++reg_info) { + auto reg_it = std::find_if( + search_registers.cbegin(), search_registers.cend(), + [reg_info](auto reg) { return reg.first == reg_info->name; }); + + if (reg_it != search_registers.end()) { + // Attach the field information. + reg_info->flags_type = reg_it->second; + // We do not expect to see this name again so don't look for it again. + search_registers.erase(reg_it); + } + } + + // We do not assert that search_registers is empty here, because it may + // contain registers from optional extensions that are not present on the + // current target. +}
\ No newline at end of file diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h new file mode 100644 index 000000000000..660bef08700f --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h @@ -0,0 +1,86 @@ +//===-- RegisterFlagsLinux_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_UTILITY_REGISTERFLAGSLINUX_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSLINUX_ARM64_H + +#include "lldb/Target/RegisterFlags.h" +#include "llvm/ADT/StringRef.h" +#include <functional> + +namespace lldb_private { + +struct RegisterInfo; + +/// This class manages the storage and detection of register field information +/// for Arm64 Linux registers. The same register may have different fields on +/// different CPUs. This class abstracts out the field detection process so we +/// can use it on live processes and core files. +/// +/// The general way to use this class is: +/// * Make an instance somewhere that will last as long as the debug session +/// (because your final register info will point to this instance). +/// * Read hardware capabilities from a core note, binary, prctl, etc. +/// * Pass those to DetectFields. +/// * Call UpdateRegisterInfo with your RegisterInfo to add pointers +/// to the detected fields for all registers listed in this class. +/// +/// This must be done in that order, and you should ensure that if multiple +/// threads will reference the information, a mutex is used to make sure only +/// one calls DetectFields. +class LinuxArm64RegisterFlags { +public: + /// For the registers listed in this class, detect which fields are + /// present. Must be called before UpdateRegisterInfos. + /// If called more than once, fields will be redetected each time from + /// scratch. If you do not have access to hwcap, just pass 0 for each one, you + /// will only get unconditional fields. + void DetectFields(uint64_t hwcap, uint64_t hwcap2); + + /// Add the field information of any registers named in this class, + /// to the relevant RegisterInfo instances. Note that this will be done + /// with a pointer to the instance of this class that you call this on, so + /// the lifetime of that instance must be at least that of the register info. + void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs); + + /// Returns true if field detection has been run at least once. + bool HasDetected() const { return m_has_detected; } + +private: + using Fields = std::vector<RegisterFlags::Field>; + using DetectorFn = std::function<Fields(uint64_t, uint64_t)>; + + static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2); + static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2); + static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2); + static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2); + static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2); + + struct RegisterEntry { + RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector) + : m_name(name), m_flags(std::string(name) + "_flags", size, {{"", 0}}), + m_detector(detector) {} + + llvm::StringRef m_name; + RegisterFlags m_flags; + DetectorFn m_detector; + } m_registers[5] = { + RegisterEntry("cpsr", 4, DetectCPSRFields), + RegisterEntry("fpsr", 4, DetectFPSRFields), + RegisterEntry("fpcr", 4, DetectFPCRFields), + RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields), + RegisterEntry("svcr", 8, DetectSVCRFields), + }; + + // Becomes true once field detection has been run for all registers. + bool m_has_detected = false; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSLINUX_ARM64_H
\ No newline at end of file diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index af5bbda7bfcf..054b7d9b2ec5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -79,7 +79,20 @@ static lldb_private::RegisterInfo g_register_infos_mte[] = { DEFINE_EXTENSION_REG(mte_ctrl)}; static lldb_private::RegisterInfo g_register_infos_tls[] = { - DEFINE_EXTENSION_REG(tpidr)}; + DEFINE_EXTENSION_REG(tpidr), + // Only present when SME is present + DEFINE_EXTENSION_REG(tpidr2)}; + +static lldb_private::RegisterInfo g_register_infos_sme[] = { + DEFINE_EXTENSION_REG(svcr), + DEFINE_EXTENSION_REG(svg), + // 16 is a default size we will change later. + {"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, + KIND_ALL_INVALID, nullptr, nullptr, nullptr}}; + +static lldb_private::RegisterInfo g_register_infos_sme2[] = { + {"zt0", nullptr, 64, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, + KIND_ALL_INVALID, nullptr, nullptr, nullptr}}; // Number of register sets provided by this context. enum { @@ -87,8 +100,11 @@ enum { k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1, k_num_sve_registers = sve_ffr - sve_vg + 1, k_num_mte_register = 1, - k_num_tls_register = 1, + // Number of TLS registers is dynamic so it is not listed here. k_num_pauth_register = 2, + // SME2's ZT0 will also be added to this set if present. So this number is + // only for SME1 registers. + k_num_sme_register = 3, k_num_register_sets_default = 2, k_num_register_sets = 3 }; @@ -193,8 +209,10 @@ static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = { static const lldb_private::RegisterSet g_reg_set_mte_arm64 = { "MTE Control Register", "mte", k_num_mte_register, nullptr}; -static const lldb_private::RegisterSet g_reg_set_tls_arm64 = { - "Thread Local Storage Registers", "tls", k_num_tls_register, nullptr}; +// The size of the TLS set is dynamic, so not listed here. + +static const lldb_private::RegisterSet g_reg_set_sme_arm64 = { + "Scalable Matrix Extension Registers", "sme", k_num_sme_register, nullptr}; RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets) @@ -212,7 +230,7 @@ RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( // dynamic register set like MTE, Pointer Authentication regset then we need // to create dynamic register infos and regset array. Push back all optional // register infos and regset and calculate register offsets accordingly. - if (m_opt_regsets.AllSet(eRegsetMaskSVE)) { + if (m_opt_regsets.AnySet(eRegsetMaskSVE | eRegsetMaskSSVE)) { m_register_info_p = g_register_infos_arm64_sve_le; m_register_info_count = sve_ffr + 1; m_per_regset_regnum_range[m_register_set_count++] = @@ -236,9 +254,12 @@ RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( if (m_opt_regsets.AllSet(eRegsetMaskMTE)) AddRegSetMTE(); - // tpidr is always present, but in future there will be others so this is - // done as a dynamic set. - AddRegSetTLS(); + // The TLS set always contains tpidr but only has tpidr2 when SME is + // present. + AddRegSetTLS(m_opt_regsets.AllSet(eRegsetMaskSSVE)); + + if (m_opt_regsets.AnySet(eRegsetMaskSSVE)) + AddRegSetSME(m_opt_regsets.AnySet(eRegsetMaskZT)); m_register_info_count = m_dynamic_reg_infos.size(); m_register_info_p = m_dynamic_reg_infos.data(); @@ -323,22 +344,70 @@ void RegisterInfoPOSIX_arm64::AddRegSetMTE() { m_dynamic_reg_sets.back().registers = m_mte_regnum_collection.data(); } -void RegisterInfoPOSIX_arm64::AddRegSetTLS() { +void RegisterInfoPOSIX_arm64::AddRegSetTLS(bool has_tpidr2) { uint32_t tls_regnum = m_dynamic_reg_infos.size(); - m_tls_regnum_collection.push_back(tls_regnum); - m_dynamic_reg_infos.push_back(g_register_infos_tls[0]); - m_dynamic_reg_infos[tls_regnum].byte_offset = - m_dynamic_reg_infos[tls_regnum - 1].byte_offset + - m_dynamic_reg_infos[tls_regnum - 1].byte_size; - m_dynamic_reg_infos[tls_regnum].kinds[lldb::eRegisterKindLLDB] = tls_regnum; + uint32_t num_regs = has_tpidr2 ? 2 : 1; + for (uint32_t i = 0; i < num_regs; i++) { + m_tls_regnum_collection.push_back(tls_regnum + i); + m_dynamic_reg_infos.push_back(g_register_infos_tls[i]); + m_dynamic_reg_infos[tls_regnum + i].byte_offset = + m_dynamic_reg_infos[tls_regnum + i - 1].byte_offset + + m_dynamic_reg_infos[tls_regnum + i - 1].byte_size; + m_dynamic_reg_infos[tls_regnum + i].kinds[lldb::eRegisterKindLLDB] = + tls_regnum + i; + } m_per_regset_regnum_range[m_register_set_count] = - std::make_pair(tls_regnum, tls_regnum + 1); - m_dynamic_reg_sets.push_back(g_reg_set_tls_arm64); + std::make_pair(tls_regnum, m_dynamic_reg_infos.size()); + m_dynamic_reg_sets.push_back( + {"Thread Local Storage Registers", "tls", num_regs, nullptr}); m_dynamic_reg_sets.back().registers = m_tls_regnum_collection.data(); } -uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) { +void RegisterInfoPOSIX_arm64::AddRegSetSME(bool has_zt) { + const uint32_t first_sme_regnum = m_dynamic_reg_infos.size(); + uint32_t sme_regnum = first_sme_regnum; + + for (uint32_t i = 0; i < k_num_sme_register; ++i, ++sme_regnum) { + m_sme_regnum_collection.push_back(sme_regnum); + m_dynamic_reg_infos.push_back(g_register_infos_sme[i]); + m_dynamic_reg_infos[sme_regnum].byte_offset = + m_dynamic_reg_infos[sme_regnum - 1].byte_offset + + m_dynamic_reg_infos[sme_regnum - 1].byte_size; + m_dynamic_reg_infos[sme_regnum].kinds[lldb::eRegisterKindLLDB] = sme_regnum; + } + + lldb_private::RegisterSet sme_regset = g_reg_set_sme_arm64; + + if (has_zt) { + m_sme_regnum_collection.push_back(sme_regnum); + m_dynamic_reg_infos.push_back(g_register_infos_sme2[0]); + m_dynamic_reg_infos[sme_regnum].byte_offset = + m_dynamic_reg_infos[sme_regnum - 1].byte_offset + + m_dynamic_reg_infos[sme_regnum - 1].byte_size; + m_dynamic_reg_infos[sme_regnum].kinds[lldb::eRegisterKindLLDB] = sme_regnum; + + sme_regset.num_registers += 1; + } + + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(first_sme_regnum, m_dynamic_reg_infos.size()); + m_dynamic_reg_sets.push_back(sme_regset); + m_dynamic_reg_sets.back().registers = m_sme_regnum_collection.data(); + + // When vg is written during streaming mode, svg will also change, as vg and + // svg in this state are both showing the streaming vector length. + // We model this as vg invalidating svg. In non-streaming mode this doesn't + // happen but to keep things simple we will invalidate svg anyway. + // + // This must be added now, rather than when vg is defined because SME is a + // dynamic set that may or may not be present. + static uint32_t vg_invalidates[] = {sme_regnum + 1 /*svg*/, + LLDB_INVALID_REGNUM}; + m_dynamic_reg_infos[GetRegNumSVEVG()].invalidate_regs = vg_invalidates; +} + +uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLengthSVE(uint32_t sve_vq) { // sve_vq contains SVE Quad vector length in context of AArch64 SVE. // SVE register infos if enabled cannot be disabled by selecting sve_vq = 0. // Also if an invalid or previously set vector length is passed to this @@ -402,6 +471,20 @@ uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) { return m_vector_reg_vq; } +void RegisterInfoPOSIX_arm64::ConfigureVectorLengthZA(uint32_t za_vq) { + if (!VectorSizeIsValid(za_vq) || m_za_reg_vq == za_vq) + return; + + m_za_reg_vq = za_vq; + + // For SVE changes, we replace m_register_info_p completely. ZA is in a + // dynamic set and is just 1 register so we make an exception to const here. + lldb_private::RegisterInfo *non_const_reginfo = + const_cast<lldb_private::RegisterInfo *>(m_register_info_p); + non_const_reginfo[m_sme_regnum_collection[2]].byte_size = + (za_vq * 16) * (za_vq * 16); +} + bool RegisterInfoPOSIX_arm64::IsSVEReg(unsigned reg) const { if (m_vector_reg_vq > eVectorQuadwordAArch64) return (sve_vg <= reg && reg <= sve_ffr); @@ -421,6 +504,16 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) const { return sve_vg == reg; } +bool RegisterInfoPOSIX_arm64::IsSMERegZA(unsigned reg) const { + return reg == m_sme_regnum_collection[2]; +} + +bool RegisterInfoPOSIX_arm64::IsSMERegZT(unsigned reg) const { + // ZT0 is part of the SME register set only if SME2 is present. + return m_sme_regnum_collection.size() >= 4 && + reg == m_sme_regnum_collection[3]; +} + bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const { return llvm::is_contained(pauth_regnum_collection, reg); } @@ -433,6 +526,10 @@ bool RegisterInfoPOSIX_arm64::IsTLSReg(unsigned reg) const { return llvm::is_contained(m_tls_regnum_collection, reg); } +bool RegisterInfoPOSIX_arm64::IsSMEReg(unsigned reg) const { + return llvm::is_contained(m_sme_regnum_collection, reg); +} + uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; } uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; } @@ -443,6 +540,10 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; } uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; } +uint32_t RegisterInfoPOSIX_arm64::GetRegNumSMESVG() const { + return m_sme_regnum_collection[1]; +} + uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const { return m_register_info_p[pauth_regnum_collection[0]].byte_offset; } @@ -454,3 +555,7 @@ uint32_t RegisterInfoPOSIX_arm64::GetMTEOffset() const { uint32_t RegisterInfoPOSIX_arm64::GetTLSOffset() const { return m_register_info_p[m_tls_regnum_collection[0]].byte_offset; } + +uint32_t RegisterInfoPOSIX_arm64::GetSMEOffset() const { + return m_register_info_p[m_sme_regnum_collection[0]].byte_offset; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h index 20cfe732c6c2..3b8171042c73 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -15,7 +15,7 @@ #include "lldb/lldb-private.h" #include <map> -enum class SVEState { Unknown, Disabled, FPSIMD, Full }; +enum class SVEState : uint8_t { Unknown, Disabled, FPSIMD, Full, Streaming }; class RegisterInfoPOSIX_arm64 : public lldb_private::RegisterInfoAndSetInterface { @@ -26,9 +26,12 @@ public: enum { eRegsetMaskDefault = 0, eRegsetMaskSVE = 1, - eRegsetMaskPAuth = 2, - eRegsetMaskMTE = 4, - eRegsetMaskTLS = 8, + eRegsetMaskSSVE = 2, + eRegsetMaskPAuth = 4, + eRegsetMaskMTE = 8, + eRegsetMaskTLS = 16, + eRegsetMaskZA = 32, + eRegsetMaskZT = 64, eRegsetMaskDynamic = ~1, }; @@ -103,9 +106,13 @@ public: void AddRegSetMTE(); - void AddRegSetTLS(); + void AddRegSetTLS(bool has_tpidr2); - uint32_t ConfigureVectorLength(uint32_t sve_vq); + void AddRegSetSME(bool has_zt); + + uint32_t ConfigureVectorLengthSVE(uint32_t sve_vq); + + void ConfigureVectorLengthZA(uint32_t za_vq); bool VectorSizeIsValid(uint32_t vq) { // coverity[unsigned_compare] @@ -114,10 +121,13 @@ public: return false; } - bool IsSVEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskSVE); } - bool IsPAuthEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); } - bool IsMTEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskMTE); } - bool IsTLSEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskTLS); } + bool IsSVEPresent() const { return m_opt_regsets.AnySet(eRegsetMaskSVE); } + bool IsSSVEPresent() const { return m_opt_regsets.AnySet(eRegsetMaskSSVE); } + bool IsZAPresent() const { return m_opt_regsets.AnySet(eRegsetMaskZA); } + bool IsZTPresent() const { return m_opt_regsets.AnySet(eRegsetMaskZT); } + bool IsPAuthPresent() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); } + bool IsMTEPresent() const { return m_opt_regsets.AnySet(eRegsetMaskMTE); } + bool IsTLSPresent() const { return m_opt_regsets.AnySet(eRegsetMaskTLS); } bool IsSVEReg(unsigned reg) const; bool IsSVEZReg(unsigned reg) const; @@ -126,15 +136,20 @@ public: bool IsPAuthReg(unsigned reg) const; bool IsMTEReg(unsigned reg) const; bool IsTLSReg(unsigned reg) const; + bool IsSMEReg(unsigned reg) const; + bool IsSMERegZA(unsigned reg) const; + bool IsSMERegZT(unsigned reg) const; uint32_t GetRegNumSVEZ0() const; uint32_t GetRegNumSVEFFR() const; uint32_t GetRegNumFPCR() const; uint32_t GetRegNumFPSR() const; uint32_t GetRegNumSVEVG() const; + uint32_t GetRegNumSMESVG() const; uint32_t GetPAuthOffset() const; uint32_t GetMTEOffset() const; uint32_t GetTLSOffset() const; + uint32_t GetSMEOffset() const; private: typedef std::map<uint32_t, std::vector<lldb_private::RegisterInfo>> @@ -143,7 +158,10 @@ private: per_vq_register_infos m_per_vq_reg_infos; uint32_t m_vector_reg_vq = eVectorQuadwordAArch64; + uint32_t m_za_reg_vq = eVectorQuadwordAArch64; + // In normal operation this is const. Only when SVE or SME registers change + // size is it either replaced or the content modified. const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; @@ -162,6 +180,7 @@ private: std::vector<uint32_t> pauth_regnum_collection; std::vector<uint32_t> m_mte_regnum_collection; std::vector<uint32_t> m_tls_regnum_collection; + std::vector<uint32_t> m_sme_regnum_collection; }; #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h index 39428bdd0a08..b111d8f62d1f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64_with_base.h @@ -71,15 +71,6 @@ nullptr, nullptr, \ } -// Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR_WITH_BASE(reg, alt, kind1, kind2, kind3, kind4) \ - { \ - #reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, \ - {kind1, kind2, kind3, kind4, x86_64_with_base::lldb_##reg}, nullptr, \ - nullptr, nullptr, \ - } - #define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ { \ #name, nullptr, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ @@ -224,8 +215,8 @@ static RegisterInfo g_register_infos_x86_64_with_base[] = { DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(fs_base, nullptr, dwarf_fs_base_x86_64, dwarf_fs_base_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gs_base, nullptr, dwarf_gs_base_x86_64, dwarf_gs_base_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs_base,nullptr, dwarf_fs_base_x86_64, dwarf_fs_base_x86_64, LLDB_REGNUM_GENERIC_TP, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs_base,nullptr, dwarf_gs_base_x86_64, dwarf_gs_base_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index d60e6250c7c0..565941d3168f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -491,14 +491,13 @@ static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, uint64_t exc_sub_sub_code) { // Try hardware watchpoint. if (target) { + // LWP_TODO: We need to find the WatchpointResource that matches + // the address, and evaluate its Watchpoints. + // The exc_sub_code indicates the data break address. lldb::WatchpointSP wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired watchpoint - // in the exception data. Set the hardware index if that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); } } @@ -511,10 +510,6 @@ static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, process_sp->GetBreakpointSiteList().FindByAddress( (lldb::addr_t)exc_sub_code); if (bp_sp && bp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired breakpoint - // in the exception data. Set the hardware index if that's the case. - if (exc_data_count >= 3) - bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithBreakpointSiteID(thread, bp_sp->GetID()); } @@ -674,6 +669,9 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( case llvm::Triple::thumb: if (exc_code == 0x102) // EXC_ARM_DA_DEBUG { + // LWP_TODO: We need to find the WatchpointResource that matches + // the address, and evaluate its Watchpoints. + // It's a watchpoint, then, if the exc_sub_code indicates a // known/enabled data break address from our watchpoint list. lldb::WatchpointSP wp_sp; @@ -681,11 +679,6 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( wp_sp = target->GetWatchpointList().FindByAddress( (lldb::addr_t)exc_sub_code); if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); } else { @@ -755,6 +748,9 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( } if (exc_code == 0x102) // EXC_ARM_DA_DEBUG { + // LWP_TODO: We need to find the WatchpointResource that matches + // the address, and evaluate its Watchpoints. + // It's a watchpoint, then, if the exc_sub_code indicates a // known/enabled data break address from our watchpoint list. lldb::WatchpointSP wp_sp; @@ -762,11 +758,6 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( wp_sp = target->GetWatchpointList().FindByAddress( (lldb::addr_t)exc_sub_code); if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index bfb59eceb2d0..7723009787f7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -53,7 +53,7 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp, bool can_connect) { lldb::ProcessSP process_sp; if (crash_file && !can_connect) { - // Read enough data for a ELF32 header or ELF64 header Note: Here we care + // Read enough data for an ELF32 header or ELF64 header Note: Here we care // about e_type field only, so it is safe to ignore possible presence of // the header extension. const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); @@ -108,7 +108,7 @@ ProcessElfCore::~ProcessElfCore() { // make sure all of the broadcaster cleanup goes as planned. If we destruct // this class, then Process::~Process() might have problems trying to fully // destroy the broadcaster. - Finalize(); + Finalize(true /* destructing */); } lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( @@ -131,7 +131,7 @@ lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( m_core_aranges.Append(range_entry); } } - // Keep a separate map of permissions that that isn't coalesced so all ranges + // Keep a separate map of permissions that isn't coalesced so all ranges // are maintained. const uint32_t permissions = ((header.p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) | @@ -832,7 +832,7 @@ llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) { for (const auto ¬e : notes) { // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so // match on the initial part of the string. - if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD")) + if (!llvm::StringRef(note.info.n_name).starts_with("OpenBSD")) continue; switch (note.info.n_type) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 38abd8f8f2b1..07501c10ec3c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -9,6 +9,9 @@ #include "RegisterContextPOSIXCore_arm64.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#include "Plugins/Process/Utility/AuxVector.h" +#include "Plugins/Process/Utility/RegisterFlagsLinux_arm64.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/RegisterValue.h" @@ -23,8 +26,13 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch, llvm::ArrayRef<CoreNote> notes) { Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault; + DataExtractor ssve_data = + getRegset(notes, arch.GetTriple(), AARCH64_SSVE_Desc); + if (ssve_data.GetByteSize() >= sizeof(sve::user_sve_header)) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSSVE); + DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc); - if (sve_data.GetByteSize() > sizeof(sve::user_sve_header)) + if (sve_data.GetByteSize() >= sizeof(sve::user_sve_header)) opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); // Pointer Authentication register set data is based on struct @@ -40,6 +48,22 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch, if (tls_data.GetByteSize() >= sizeof(uint64_t)) opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS); + DataExtractor za_data = getRegset(notes, arch.GetTriple(), AARCH64_ZA_Desc); + // Nothing if ZA is not present, just the header if it is disabled. + if (za_data.GetByteSize() >= sizeof(sve::user_za_header)) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZA); + + DataExtractor mte_data = getRegset(notes, arch.GetTriple(), AARCH64_MTE_Desc); + if (mte_data.GetByteSize() >= sizeof(uint64_t)) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE); + + DataExtractor zt_data = getRegset(notes, arch.GetTriple(), AARCH64_ZT_Desc); + // Although ZT0 can be in a disabled state like ZA can, the kernel reports + // its content as 0s in that state. Therefore even a disabled ZT0 will have + // a note containing those 0s. ZT0 is a 512 bit / 64 byte register. + if (zt_data.GetByteSize() >= 64) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZT); + auto register_info_up = std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets); return std::unique_ptr<RegisterContextCorePOSIX_arm64>( @@ -51,6 +75,23 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info, const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm64(thread, std::move(register_info)) { + ::memset(&m_sme_pseudo_regs, 0, sizeof(m_sme_pseudo_regs)); + + ProcessElfCore *process = + static_cast<ProcessElfCore *>(thread.GetProcess().get()); + if (process->GetArchitecture().GetTriple().getOS() == llvm::Triple::Linux) { + AuxVector aux_vec(process->GetAuxvData()); + std::optional<uint64_t> auxv_at_hwcap = + aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP); + std::optional<uint64_t> auxv_at_hwcap2 = + aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP2); + + m_linux_register_flags.DetectFields(auxv_at_hwcap.value_or(0), + auxv_at_hwcap2.value_or(0)); + m_linux_register_flags.UpdateRegisterInfo(GetRegisterInfo(), + GetRegisterCount()); + } + m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr_data.SetByteOrder(gpregset.GetByteOrder()); @@ -59,15 +100,32 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( m_register_info_up->GetTargetArchitecture().GetTriple(); m_fpr_data = getRegset(notes, target_triple, FPR_Desc); - if (m_register_info_up->IsSVEEnabled()) + if (m_register_info_up->IsSSVEPresent()) { + m_sve_data = getRegset(notes, target_triple, AARCH64_SSVE_Desc); + lldb::offset_t flags_offset = 12; + uint16_t flags = m_sve_data.GetU32(&flags_offset); + if ((flags & sve::ptrace_regs_mask) == sve::ptrace_regs_sve) + m_sve_state = SVEState::Streaming; + } + + if (m_sve_state != SVEState::Streaming && m_register_info_up->IsSVEPresent()) m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc); - if (m_register_info_up->IsPAuthEnabled()) + if (m_register_info_up->IsPAuthPresent()) m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc); - if (m_register_info_up->IsTLSEnabled()) + if (m_register_info_up->IsTLSPresent()) m_tls_data = getRegset(notes, target_triple, AARCH64_TLS_Desc); + if (m_register_info_up->IsZAPresent()) + m_za_data = getRegset(notes, target_triple, AARCH64_ZA_Desc); + + if (m_register_info_up->IsMTEPresent()) + m_mte_data = getRegset(notes, target_triple, AARCH64_MTE_Desc); + + if (m_register_info_up->IsZTPresent()) + m_zt_data = getRegset(notes, target_triple, AARCH64_ZT_Desc); + ConfigureRegisterContext(); } @@ -95,15 +153,18 @@ void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() { if (m_sve_data.GetByteSize() > sizeof(sve::user_sve_header)) { uint64_t sve_header_field_offset = 8; m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset); - sve_header_field_offset = 12; - uint16_t sve_header_flags_field = - m_sve_data.GetU16(&sve_header_field_offset); - if ((sve_header_flags_field & sve::ptrace_regs_mask) == - sve::ptrace_regs_fpsimd) - m_sve_state = SVEState::FPSIMD; - else if ((sve_header_flags_field & sve::ptrace_regs_mask) == - sve::ptrace_regs_sve) - m_sve_state = SVEState::Full; + + if (m_sve_state != SVEState::Streaming) { + sve_header_field_offset = 12; + uint16_t sve_header_flags_field = + m_sve_data.GetU16(&sve_header_field_offset); + if ((sve_header_flags_field & sve::ptrace_regs_mask) == + sve::ptrace_regs_fpsimd) + m_sve_state = SVEState::FPSIMD; + else if ((sve_header_flags_field & sve::ptrace_regs_mask) == + sve::ptrace_regs_sve) + m_sve_state = SVEState::Full; + } if (!sve::vl_valid(m_sve_vector_length)) { m_sve_state = SVEState::Disabled; @@ -113,8 +174,25 @@ void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() { m_sve_state = SVEState::Disabled; if (m_sve_state != SVEState::Disabled) - m_register_info_up->ConfigureVectorLength( + m_register_info_up->ConfigureVectorLengthSVE( sve::vq_from_vl(m_sve_vector_length)); + + if (m_sve_state == SVEState::Streaming) + m_sme_pseudo_regs.ctrl_reg |= 1; + + if (m_za_data.GetByteSize() >= sizeof(sve::user_za_header)) { + lldb::offset_t vlen_offset = 8; + uint16_t svl = m_za_data.GetU16(&vlen_offset); + m_sme_pseudo_regs.svg_reg = svl / 8; + m_register_info_up->ConfigureVectorLengthZA(svl / 16); + + // If there is register data then ZA is active. The size of the note may be + // misleading here so we use the size field of the embedded header. + lldb::offset_t size_offset = 0; + uint32_t size = m_za_data.GetU32(&size_offset); + if (size > sizeof(sve::user_za_header)) + m_sme_pseudo_regs.ctrl_reg |= 1 << 1; + } } uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset( @@ -124,7 +202,8 @@ uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset( if (m_sve_state == SVEState::FPSIMD) { const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; sve_reg_offset = sve::ptrace_fpsimd_offset + (reg - GetRegNumSVEZ0()) * 16; - } else if (m_sve_state == SVEState::Full) { + } else if (m_sve_state == SVEState::Full || + m_sve_state == SVEState::Streaming) { uint32_t sve_z0_offset = GetGPRSize() + 16; sve_reg_offset = sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset; @@ -140,11 +219,9 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, offset = reg_info->byte_offset; if (offset + reg_info->byte_size <= GetGPRSize()) { - uint64_t v = m_gpr_data.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) { - value = v; - return true; - } + value.SetFromMemoryData(*reg_info, m_gpr_data.GetDataStart() + offset, + reg_info->byte_size, lldb::eByteOrderLittle, error); + return error.Success(); } const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; @@ -163,19 +240,19 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, } } else { // FPSR and FPCR will be located right after Z registers in - // SVEState::FPSIMD while in SVEState::Full they will be located at the - // end of register data after an alignment correction based on currently - // selected vector length. + // SVEState::FPSIMD while in SVEState::Full/SVEState::Streaming they will + // be located at the end of register data after an alignment correction + // based on currently selected vector length. uint32_t sve_reg_num = LLDB_INVALID_REGNUM; if (reg == GetRegNumFPSR()) { sve_reg_num = reg; - if (m_sve_state == SVEState::Full) + if (m_sve_state == SVEState::Full || m_sve_state == SVEState::Streaming) offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_vector_length)); else if (m_sve_state == SVEState::FPSIMD) offset = sve::ptrace_fpsimd_offset + (32 * 16); } else if (reg == GetRegNumFPCR()) { sve_reg_num = reg; - if (m_sve_state == SVEState::Full) + if (m_sve_state == SVEState::Full || m_sve_state == SVEState::Streaming) offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_vector_length)); else if (m_sve_state == SVEState::FPSIMD) offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4; @@ -217,6 +294,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, error); } break; case SVEState::Full: + case SVEState::Streaming: offset = CalculateSVEOffset(reg_info); assert(offset < m_sve_data.GetByteSize()); value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset), @@ -237,6 +315,59 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, assert(offset < m_tls_data.GetByteSize()); value.SetFromMemoryData(*reg_info, m_tls_data.GetDataStart() + offset, reg_info->byte_size, lldb::eByteOrderLittle, error); + } else if (IsMTE(reg)) { + offset = reg_info->byte_offset - m_register_info_up->GetMTEOffset(); + assert(offset < m_mte_data.GetByteSize()); + value.SetFromMemoryData(*reg_info, m_mte_data.GetDataStart() + offset, + reg_info->byte_size, lldb::eByteOrderLittle, error); + } else if (IsSME(reg)) { + // If you had SME in the process, active or otherwise, there will at least + // be a ZA header. No header, no SME at all. + if (m_za_data.GetByteSize() < sizeof(sve::user_za_header)) + return false; + + if (m_register_info_up->IsSMERegZA(reg)) { + // Don't use the size of the note to tell whether ZA is enabled. There may + // be non-register padding data after the header. Use the embedded + // header's size field instead. + lldb::offset_t size_offset = 0; + uint32_t size = m_za_data.GetU32(&size_offset); + bool za_enabled = size > sizeof(sve::user_za_header); + + size_t za_note_size = m_za_data.GetByteSize(); + // For a disabled ZA we fake a value of all 0s. + if (!za_enabled) { + uint64_t svl = m_sme_pseudo_regs.svg_reg * 8; + za_note_size = sizeof(sve::user_za_header) + (svl * svl); + } + + const uint8_t *src = nullptr; + std::vector<uint8_t> disabled_za_data; + + if (za_enabled) + src = m_za_data.GetDataStart(); + else { + disabled_za_data.resize(za_note_size); + std::fill(disabled_za_data.begin(), disabled_za_data.end(), 0); + src = disabled_za_data.data(); + } + + value.SetFromMemoryData(*reg_info, src + sizeof(sve::user_za_header), + reg_info->byte_size, lldb::eByteOrderLittle, + error); + } else if (m_register_info_up->IsSMERegZT(reg)) { + value.SetFromMemoryData(*reg_info, m_zt_data.GetDataStart(), + reg_info->byte_size, lldb::eByteOrderLittle, + error); + } else { + offset = reg_info->byte_offset - m_register_info_up->GetSMEOffset(); + assert(offset < sizeof(m_sme_pseudo_regs)); + // Host endian since these values are derived instead of being read from a + // core file note. + value.SetFromMemoryData( + *reg_info, reinterpret_cast<uint8_t *>(&m_sme_pseudo_regs) + offset, + reg_info->byte_size, lldb_private::endian::InlHostByteOrder(), error); + } } else return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index 5e0e29f0de7f..38e958851dfe 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -11,6 +11,7 @@ #include "Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" +#include "Plugins/Process/Utility/RegisterFlagsLinux_arm64.h" #include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" @@ -58,10 +59,24 @@ private: lldb_private::DataExtractor m_sve_data; lldb_private::DataExtractor m_pac_data; lldb_private::DataExtractor m_tls_data; + lldb_private::DataExtractor m_za_data; + lldb_private::DataExtractor m_mte_data; + lldb_private::DataExtractor m_zt_data; - SVEState m_sve_state; + SVEState m_sve_state = SVEState::Unknown; uint16_t m_sve_vector_length = 0; + // These are pseudo registers derived from the values in SSVE and ZA data. + struct __attribute__((packed)) sme_pseudo_regs { + uint64_t ctrl_reg; + uint64_t svg_reg; + }; + static_assert(sizeof(sme_pseudo_regs) == 16); + + struct sme_pseudo_regs m_sme_pseudo_regs; + + lldb_private::LinuxArm64RegisterFlags m_linux_register_flags; + const uint8_t *GetSVEBuffer(uint64_t offset = 0); void ConfigureRegisterContext(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h index 3d53a5795ef3..12aa5f72371c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -119,6 +119,18 @@ constexpr RegsetDesc AARCH64_SVE_Desc[] = { {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SVE}, }; +constexpr RegsetDesc AARCH64_SSVE_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SSVE}, +}; + +constexpr RegsetDesc AARCH64_ZA_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_ZA}, +}; + +constexpr RegsetDesc AARCH64_ZT_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_ZT}, +}; + constexpr RegsetDesc AARCH64_PAC_Desc[] = { {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK}, }; @@ -127,6 +139,11 @@ constexpr RegsetDesc AARCH64_TLS_Desc[] = { {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_TLS}, }; +constexpr RegsetDesc AARCH64_MTE_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, + llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL}, +}; + constexpr RegsetDesc PPC_VMX_Desc[] = { {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 7daf003fec7b..8a47eed3d7cb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -13,7 +13,6 @@ #include <future> #include <sys/stat.h> -#include "lldb/Core/StreamFile.h" #include "lldb/Host/Config.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c6503129685a..ad72b3d121e6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1265,7 +1265,14 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { if (!value.getAsInteger(0, pointer_byte_size)) ++num_keys_decoded; } else if (name.equals("addressing_bits")) { - if (!value.getAsInteger(0, m_addressing_bits)) + if (!value.getAsInteger(0, m_low_mem_addressing_bits)) { + ++num_keys_decoded; + } + } else if (name.equals("high_mem_addressing_bits")) { + if (!value.getAsInteger(0, m_high_mem_addressing_bits)) + ++num_keys_decoded; + } else if (name.equals("low_mem_addressing_bits")) { + if (!value.getAsInteger(0, m_low_mem_addressing_bits)) ++num_keys_decoded; } else if (name.equals("os_version") || name.equals("version")) // Older debugserver binaries used @@ -1407,11 +1414,19 @@ GDBRemoteCommunicationClient::GetHostArchitecture() { return m_host_arch; } -uint32_t GDBRemoteCommunicationClient::GetAddressingBits() { +AddressableBits GDBRemoteCommunicationClient::GetAddressableBits() { + AddressableBits addressable_bits; if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); - return m_addressing_bits; + + if (m_low_mem_addressing_bits == m_high_mem_addressing_bits) + addressable_bits.SetAddressableBits(m_low_mem_addressing_bits); + else + addressable_bits.SetAddressableBits(m_low_mem_addressing_bits, + m_high_mem_addressing_bits); + return addressable_bits; } + seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); @@ -2634,10 +2649,12 @@ size_t GDBRemoteCommunicationClient::QueryGDBServer( return 0; for (size_t i = 0, count = array->GetSize(); i < count; ++i) { - StructuredData::Dictionary *element = nullptr; - if (!array->GetItemAtIndexAsDictionary(i, element)) + std::optional<StructuredData::Dictionary *> maybe_element = + array->GetItemAtIndexAsDictionary(i); + if (!maybe_element) continue; + StructuredData::Dictionary *element = *maybe_element; uint16_t port = 0; if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port"))) @@ -4025,7 +4042,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( return; } else { llvm::StringRef response_str(response.GetStringRef()); - if (response_str.startswith("qSymbol:")) { + if (response_str.starts_with("qSymbol:")) { response.SetFilePos(strlen("qSymbol:")); std::string symbol_name; if (response.GetHexByteString(symbol_name)) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 6cf5de68911b..866b0773d86d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -19,6 +19,7 @@ #include <vector> #include "lldb/Host/File.h" +#include "lldb/Utility/AddressableBits.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/ProcessInfo.h" @@ -237,7 +238,7 @@ public: ArchSpec GetSystemArchitecture(); - uint32_t GetAddressingBits(); + lldb_private::AddressableBits GetAddressableBits(); bool GetHostname(std::string &s); @@ -580,7 +581,8 @@ protected: lldb::tid_t m_curr_tid_run = LLDB_INVALID_THREAD_ID; uint32_t m_num_supported_hardware_watchpoints = 0; - uint32_t m_addressing_bits = 0; + uint32_t m_low_mem_addressing_bits = 0; + uint32_t m_high_mem_addressing_bits = 0; ArchSpec m_host_arch; std::string m_host_distribution_id; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index a3477caea7d8..5d4a537befeb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -9,7 +9,6 @@ #include "GDBRemoteCommunicationHistory.h" // Other libraries and framework includes -#include "lldb/Core/StreamFile.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Log.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 4efc454967a1..3d37bb226a65 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -595,6 +595,8 @@ static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo ®_info) { return "arg7"; case LLDB_REGNUM_GENERIC_ARG8: return "arg8"; + case LLDB_REGNUM_GENERIC_TP: + return "tp"; default: return ""; } @@ -631,7 +633,7 @@ static void WriteRegisterValueInHexFixedWidth( } else { // Zero-out any unreadable values. if (reg_info.byte_size > 0) { - std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0'); + std::vector<uint8_t> zeros(reg_info.byte_size, '\0'); AppendHexValue(response, zeros.data(), zeros.size(), false); } } @@ -2304,7 +2306,7 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Build the reginfos response. StreamGDBRemote response; - RegisterValue reg_value(ArrayRef(m_reg_bytes, reg_size), + RegisterValue reg_value(ArrayRef<uint8_t>(m_reg_bytes, reg_size), m_current_process->GetArchitecture().GetByteOrder()); Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { @@ -3092,6 +3094,12 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { continue; } + if (reg_info->flags_type) { + response.IndentMore(); + reg_info->flags_type->ToXML(response); + response.IndentLess(); + } + response.Indent(); response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" regnum=\"%d\" ", @@ -3111,6 +3119,9 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { if (!format.empty()) response << "format=\"" << format << "\" "; + if (reg_info->flags_type) + response << "type=\"" << reg_info->flags_type->GetID() << "\" "; + const char *const register_set_name = reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); if (register_set_name) @@ -3910,7 +3921,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qSaveCore( std::string path_hint; StringRef packet_str{packet.GetStringRef()}; - assert(packet_str.startswith("qSaveCore")); + assert(packet_str.starts_with("qSaveCore")); if (packet_str.consume_front("qSaveCore;")) { for (auto x : llvm::split(packet_str, ';')) { if (x.consume_front("path-hint:")) @@ -3936,7 +3947,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QNonStop( Log *log = GetLog(LLDBLog::Process); StringRef packet_str{packet.GetStringRef()}; - assert(packet_str.startswith("QNonStop:")); + assert(packet_str.starts_with("QNonStop:")); packet_str.consume_front("QNonStop:"); if (packet_str == "0") { if (m_non_stop) @@ -4295,7 +4306,7 @@ lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg, std::string host_port = url_arg.str(); // If host_and_port starts with ':', default the host to be "localhost" and // expect the remainder to be the port. - if (url_arg.startswith(":")) + if (url_arg.starts_with(":")) host_port.insert(0, "localhost"); // Try parsing the (preprocessed) argument as host:port pair. diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 4ffa7faa4942..391abdae2752 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -500,7 +500,7 @@ GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo( auto dictionary = std::make_shared<StructuredData::Dictionary>(); dictionary->AddIntegerItem("signo", signo); - dictionary->AddStringItem("name", signals->GetSignalAsCString(signo)); + dictionary->AddStringItem("name", signals->GetSignalAsStringRef(signo)); bool suppress, stop, notify; signals->GetSignalInfo(signo, suppress, stop, notify); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index e8606ddae567..e9bd65fad150 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -8,6 +8,12 @@ #include "GDBRemoteRegisterContext.h" +#include "ProcessGDBRemote.h" +#include "ProcessGDBRemoteLog.h" +#include "ThreadGDBRemote.h" +#include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" +#include "lldb/Core/Architecture.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataBufferHeap.h" @@ -15,11 +21,6 @@ #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/StreamString.h" -#include "ProcessGDBRemote.h" -#include "ProcessGDBRemoteLog.h" -#include "ThreadGDBRemote.h" -#include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_ehframe_Registers.h" #include "lldb/Utility/StringExtractorGDBRemote.h" #include <memory> @@ -227,7 +228,9 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info) { SetAllRegisterValid(true); return true; } else if (buffer_sp->GetByteSize() > 0) { - for (auto x : llvm::enumerate(m_reg_info_sp->registers())) { + for (auto x : llvm::enumerate( + m_reg_info_sp->registers< + DynamicRegisterInfo::reg_collection_const_range>())) { const struct RegisterInfo ®info = x.value(); m_reg_valid[x.index()] = (reginfo.byte_offset + reginfo.byte_size <= @@ -373,14 +376,8 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, if (dst == nullptr) return false; - // Code below is specific to AArch64 target in SVE state - // If vector granule (vg) register is being written then thread's - // register context reconfiguration is triggered on success. - bool do_reconfigure_arm64_sve = false; - const ArchSpec &arch = process->GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetTriple().isAArch64()) - if (strcmp(reg_info->name, "vg") == 0) - do_reconfigure_arm64_sve = true; + const bool should_reconfigure_registers = + RegisterWriteCausesReconfigure(reg_info->name); if (data.CopyByteOrderedData(data_offset, // src offset reg_info->byte_size, // src length @@ -400,10 +397,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())})) { - SetAllRegisterValid(false); + if (should_reconfigure_registers) + ReconfigureRegisterInfo(); - if (do_reconfigure_arm64_sve) - AArch64SVEReconfigure(); + InvalidateAllRegisters(); return true; } @@ -434,9 +431,6 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, } else { // This is an actual register, write it success = SetPrimordialRegister(reg_info, gdb_comm); - - if (success && do_reconfigure_arm64_sve) - AArch64SVEReconfigure(); } // Check if writing this register will invalidate any other register @@ -450,6 +444,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, false); } + if (success && should_reconfigure_registers && + ReconfigureRegisterInfo()) + InvalidateAllRegisters(); + return success; } } else { @@ -760,58 +758,20 @@ uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber( return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num); } -bool GDBRemoteRegisterContext::AArch64SVEReconfigure() { - if (!m_reg_info_sp) - return false; - - const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg"); - if (!reg_info) - return false; - - uint64_t fail_value = LLDB_INVALID_ADDRESS; - uint32_t vg_reg_num = reg_info->kinds[eRegisterKindLLDB]; - uint64_t vg_reg_value = ReadRegisterAsUnsigned(vg_reg_num, fail_value); - - if (vg_reg_value != fail_value && vg_reg_value <= 32) { - const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("p0"); - if (!reg_info || vg_reg_value == reg_info->byte_size) - return false; - - if (m_reg_info_sp->UpdateARM64SVERegistersInfos(vg_reg_value)) { - // Make a heap based buffer that is big enough to store all registers - m_reg_data.SetData(std::make_shared<DataBufferHeap>( - m_reg_info_sp->GetRegisterDataByteSize(), 0)); - m_reg_data.SetByteOrder(GetByteOrder()); - - InvalidateAllRegisters(); - - return true; - } - } - - return false; +bool GDBRemoteRegisterContext::RegisterWriteCausesReconfigure( + const llvm::StringRef name) { + ExecutionContext exe_ctx(CalculateThread()); + const Architecture *architecture = + exe_ctx.GetProcessRef().GetTarget().GetArchitecturePlugin(); + return architecture && architecture->RegisterWriteCausesReconfigure(name); } -bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) { - // SVE Z register size is vg x 8 bytes. - uint32_t z_reg_byte_size = vg * 8; - - // SVE vector length has changed, accordingly set size of Z, P and FFR - // registers. Also invalidate register offsets it will be recalculated - // after SVE register size update. - for (auto ® : m_regs) { - if (reg.value_regs == nullptr) { - if (reg.name[0] == 'z' && isdigit(reg.name[1])) - reg.byte_size = z_reg_byte_size; - else if (reg.name[0] == 'p' && isdigit(reg.name[1])) - reg.byte_size = vg; - else if (strcmp(reg.name, "ffr") == 0) - reg.byte_size = vg; - } - reg.byte_offset = LLDB_INVALID_INDEX32; - } - - // Re-calculate register offsets - ConfigureOffsets(); - return true; +bool GDBRemoteRegisterContext::ReconfigureRegisterInfo() { + ExecutionContext exe_ctx(CalculateThread()); + const Architecture *architecture = + exe_ctx.GetProcessRef().GetTarget().GetArchitecturePlugin(); + if (architecture) + return architecture->ReconfigureRegisterInfo(*(m_reg_info_sp.get()), + m_reg_data, *this); + return false; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index d185cb5aede1..6a90f911353f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -38,7 +38,8 @@ public: ~GDBRemoteDynamicRegisterInfo() override = default; - bool UpdateARM64SVERegistersInfos(uint64_t vg); + void UpdateARM64SVERegistersInfos(uint64_t vg); + void UpdateARM64SMERegistersInfos(uint64_t svg); }; class GDBRemoteRegisterContext : public RegisterContext { @@ -77,7 +78,9 @@ public: uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; - bool AArch64SVEReconfigure(); + bool RegisterWriteCausesReconfigure(const llvm::StringRef name) override; + + bool ReconfigureRegisterInfo() override; protected: friend class ThreadGDBRemote; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index b6f146fd872e..316be471df92 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -24,11 +24,11 @@ #include <sys/types.h> #include "lldb/Breakpoint/Watchpoint.h" +#include "lldb/Breakpoint/WatchpointResource.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" @@ -36,6 +36,7 @@ #include "lldb/Host/HostThread.h" #include "lldb/Host/PosixApi.h" #include "lldb/Host/PseudoTerminal.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/XML.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -48,7 +49,6 @@ #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/Property.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" @@ -129,8 +129,8 @@ enum { class PluginProperties : public Properties { public: - static ConstString GetSettingName() { - return ConstString(ProcessGDBRemote::GetPluginNameStatic()); + static llvm::StringRef GetSettingName() { + return ProcessGDBRemote::GetPluginNameStatic(); } PluginProperties() : Properties() { @@ -303,7 +303,7 @@ ProcessGDBRemote::~ProcessGDBRemote() { // make sure all of the broadcaster cleanup goes as planned. If we destruct // this class, then Process::~Process() might have problems trying to fully // destroy the broadcaster. - Finalize(); + Finalize(true /* destructing */); // The general Finalize is going to try to destroy the process and that // SHOULD shut down the async thread. However, if we don't kill it it will @@ -899,11 +899,8 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { process_arch.GetTriple().getTriple()); } - if (int addressable_bits = m_gdb_comm.GetAddressingBits()) { - lldb::addr_t address_mask = ~((1ULL << addressable_bits) - 1); - SetCodeAddressMask(address_mask); - SetDataAddressMask(address_mask); - } + AddressableBits addressable_bits = m_gdb_comm.GetAddressableBits(); + addressable_bits.SetProcessMasks(*this); if (process_arch.IsValid()) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); @@ -1001,10 +998,11 @@ void ProcessGDBRemote::LoadStubBinaries() { const bool force_symbol_search = true; const bool notify = true; const bool set_address_in_target = true; + const bool allow_memory_image_last_resort = false; DynamicLoader::LoadBinaryWithUUIDAndAddress( this, "", standalone_uuid, standalone_value, standalone_value_is_offset, force_symbol_search, notify, - set_address_in_target); + set_address_in_target, allow_memory_image_last_resort); } } @@ -1033,10 +1031,12 @@ void ProcessGDBRemote::LoadStubBinaries() { const bool force_symbol_search = true; const bool set_address_in_target = true; + const bool allow_memory_image_last_resort = false; // Second manually load this binary into the Target. DynamicLoader::LoadBinaryWithUUIDAndAddress( this, llvm::StringRef(), uuid, addr, value_is_slide, - force_symbol_search, notify, set_address_in_target); + force_symbol_search, notify, set_address_in_target, + allow_memory_image_last_resort); } } } @@ -1612,6 +1612,22 @@ bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) { return false; } +void ProcessGDBRemote::ParseExpeditedRegisters( + ExpeditedRegisterMap &expedited_register_map, ThreadSP thread_sp) { + ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); + RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); + + for (const auto &pair : expedited_register_map) { + StringExtractor reg_value_extractor(pair.second); + WritableDataBufferSP buffer_sp( + new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0)); + reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); + uint32_t lldb_regnum = gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindProcessPlugin, pair.first); + gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); + } +} + ThreadSP ProcessGDBRemote::SetThreadStopInfo( lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map, uint8_t signo, const std::string &thread_name, const std::string &reason, @@ -1642,35 +1658,24 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( } ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); - RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); + RegisterContextSP reg_ctx_sp(gdb_thread->GetRegisterContext()); - gdb_reg_ctx_sp->InvalidateIfNeeded(true); + reg_ctx_sp->InvalidateIfNeeded(true); auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); if (iter != m_thread_ids.end()) SetThreadPc(thread_sp, iter - m_thread_ids.begin()); - for (const auto &pair : expedited_register_map) { - StringExtractor reg_value_extractor(pair.second); - WritableDataBufferSP buffer_sp( - new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0)); - reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); - uint32_t lldb_regnum = gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( - eRegisterKindProcessPlugin, pair.first); - gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); - } - - // AArch64 SVE specific code below calls AArch64SVEReconfigure to update - // SVE register sizes and offsets if value of VG register has changed - // since last stop. - const ArchSpec &arch = GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetTriple().isAArch64()) { - GDBRemoteRegisterContext *reg_ctx_sp = - static_cast<GDBRemoteRegisterContext *>( - gdb_thread->GetRegisterContext().get()); + ParseExpeditedRegisters(expedited_register_map, thread_sp); - if (reg_ctx_sp) - reg_ctx_sp->AArch64SVEReconfigure(); + if (reg_ctx_sp->ReconfigureRegisterInfo()) { + // Now we have changed the offsets of all the registers, so the values + // will be corrupted. + reg_ctx_sp->InvalidateAllRegisters(); + // Expedited registers values will never contain registers that would be + // resized by a reconfigure. So we are safe to continue using these + // values. + ParseExpeditedRegisters(expedited_register_map, thread_sp); } thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); @@ -1785,30 +1790,38 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( // disable/step/re-enable it, so one of the valid watchpoint // addresses should be provided as \a wp_addr. StringExtractor desc_extractor(description.c_str()); + // FIXME NativeThreadLinux::SetStoppedByWatchpoint sends this + // up as + // <address within wp range> <wp hw index> <actual accessed addr> + // but this is not reading the <wp hw index>. Seems like it + // wouldn't work on MIPS, where that third field is important. addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); - uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); watch_id_t watch_id = LLDB_INVALID_WATCH_ID; bool silently_continue = false; - WatchpointSP wp_sp; + WatchpointResourceSP wp_resource_sp; if (wp_hit_addr != LLDB_INVALID_ADDRESS) { - wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); + wp_resource_sp = + m_watchpoint_resource_list.FindByAddress(wp_hit_addr); // On MIPS, \a wp_hit_addr outside the range of a watched // region means we should silently continue, it is a false hit. ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); - if (!wp_sp && core >= ArchSpec::kCore_mips_first && + if (!wp_resource_sp && core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) silently_continue = true; } - if (!wp_sp && wp_addr != LLDB_INVALID_ADDRESS) - wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); - if (wp_sp) { - wp_sp->SetHardwareIndex(wp_index); - watch_id = wp_sp->GetID(); - } - if (watch_id == LLDB_INVALID_WATCH_ID) { + if (!wp_resource_sp && wp_addr != LLDB_INVALID_ADDRESS) + wp_resource_sp = m_watchpoint_resource_list.FindByAddress(wp_addr); + if (!wp_resource_sp) { Log *log(GetLog(GDBRLog::Watchpoints)); LLDB_LOGF(log, "failed to find watchpoint"); + watch_id = LLDB_INVALID_SITE_ID; + } else { + // LWP_TODO: This is hardcoding a single Watchpoint in a + // Resource, need to add + // StopInfo::CreateStopReasonWithWatchpointResource which + // represents all watchpoints that were tripped at this stop. + watch_id = wp_resource_sp->GetConstituentAtIndex(0)->GetID(); } thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( *thread_sp, watch_id, silently_continue)); @@ -1926,24 +1939,23 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( lldb::ThreadSP ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { - static ConstString g_key_tid("tid"); - static ConstString g_key_name("name"); - static ConstString g_key_reason("reason"); - static ConstString g_key_metype("metype"); - static ConstString g_key_medata("medata"); - static ConstString g_key_qaddr("qaddr"); - static ConstString g_key_dispatch_queue_t("dispatch_queue_t"); - static ConstString g_key_associated_with_dispatch_queue( + static constexpr llvm::StringLiteral g_key_tid("tid"); + static constexpr llvm::StringLiteral g_key_name("name"); + static constexpr llvm::StringLiteral g_key_reason("reason"); + static constexpr llvm::StringLiteral g_key_metype("metype"); + static constexpr llvm::StringLiteral g_key_medata("medata"); + static constexpr llvm::StringLiteral g_key_qaddr("qaddr"); + static constexpr llvm::StringLiteral g_key_dispatch_queue_t( + "dispatch_queue_t"); + static constexpr llvm::StringLiteral g_key_associated_with_dispatch_queue( "associated_with_dispatch_queue"); - static ConstString g_key_queue_name("qname"); - static ConstString g_key_queue_kind("qkind"); - static ConstString g_key_queue_serial_number("qserialnum"); - static ConstString g_key_registers("registers"); - static ConstString g_key_memory("memory"); - static ConstString g_key_address("address"); - static ConstString g_key_bytes("bytes"); - static ConstString g_key_description("description"); - static ConstString g_key_signal("signal"); + static constexpr llvm::StringLiteral g_key_queue_name("qname"); + static constexpr llvm::StringLiteral g_key_queue_kind("qkind"); + static constexpr llvm::StringLiteral g_key_queue_serial_number("qserialnum"); + static constexpr llvm::StringLiteral g_key_registers("registers"); + static constexpr llvm::StringLiteral g_key_memory("memory"); + static constexpr llvm::StringLiteral g_key_description("description"); + static constexpr llvm::StringLiteral g_key_signal("signal"); // Stop with signal and thread info lldb::tid_t tid = LLDB_INVALID_THREAD_ID; @@ -1971,7 +1983,7 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { &thread_dispatch_qaddr, &queue_vars_valid, &associated_with_dispatch_queue, &dispatch_queue_t, &queue_name, &queue_kind, &queue_serial_number]( - ConstString key, + llvm::StringRef key, StructuredData::Object *object) -> bool { if (key == g_key_tid) { // thread in big endian hex @@ -2029,10 +2041,10 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { if (registers_dict) { registers_dict->ForEach( - [&expedited_register_map](ConstString key, + [&expedited_register_map](llvm::StringRef key, StructuredData::Object *object) -> bool { uint32_t reg; - if (llvm::to_integer(key.AsCString(), reg)) + if (llvm::to_integer(key, reg)) expedited_register_map[reg] = std::string(object->GetStringValue()); return true; // Keep iterating through all array items @@ -2089,7 +2101,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { switch (stop_type) { case 'T': case 'S': { - // This is a bit of a hack, but is is required. If we did exec, we need to + // This is a bit of a hack, but it is required. If we did exec, we need to // clear our thread lists and also know to rebuild our dynamic register // info before we lookup and threads and populate the expedited register // values so we need to know this right away so we can cleanup and update @@ -2122,6 +2134,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { QueueKind queue_kind = eQueueKindUnknown; uint64_t queue_serial_number = 0; ExpeditedRegisterMap expedited_register_map; + AddressableBits addressable_bits; while (stop_packet.GetNameColonValue(key, value)) { if (key.compare("metype") == 0) { // exception type in big endian hex @@ -2232,19 +2245,15 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS; value.getAsInteger(16, wp_addr); - WatchpointSP wp_sp = - GetTarget().GetWatchpointList().FindByAddress(wp_addr); - uint32_t wp_index = LLDB_INVALID_INDEX32; - - if (wp_sp) - wp_index = wp_sp->GetHardwareIndex(); + WatchpointResourceSP wp_resource_sp = + m_watchpoint_resource_list.FindByAddress(wp_addr); // Rewrite gdb standard watch/rwatch/awatch to // "reason:watchpoint" + "description:ADDR", // which is parsed in SetThreadStopInfo. reason = "watchpoint"; StreamString ostr; - ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); + ostr.Printf("%" PRIu64, wp_addr); description = std::string(ostr.GetString()); } else if (key.compare("library") == 0) { auto error = LoadModules(); @@ -2269,9 +2278,17 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { } else if (key.compare("addressing_bits") == 0) { uint64_t addressing_bits; if (!value.getAsInteger(0, addressing_bits)) { - addr_t address_mask = ~((1ULL << addressing_bits) - 1); - SetCodeAddressMask(address_mask); - SetDataAddressMask(address_mask); + addressable_bits.SetAddressableBits(addressing_bits); + } + } else if (key.compare("low_mem_addressing_bits") == 0) { + uint64_t addressing_bits; + if (!value.getAsInteger(0, addressing_bits)) { + addressable_bits.SetLowmemAddressableBits(addressing_bits); + } + } else if (key.compare("high_mem_addressing_bits") == 0) { + uint64_t addressing_bits; + if (!value.getAsInteger(0, addressing_bits)) { + addressable_bits.SetHighmemAddressableBits(addressing_bits); } } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { uint32_t reg = UINT32_MAX; @@ -2300,6 +2317,8 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { } } + addressable_bits.SetProcessMasks(*this); + ThreadSP thread_sp = SetThreadStopInfo( tid, expedited_register_map, signo, thread_name, reason, description, exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid, @@ -2358,8 +2377,10 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) { Status error; if (m_public_state.GetValue() == eStateAttaching) { - // We are being asked to halt during an attach. We need to just close our - // file handle and debugserver will go away, and we can be done... + // We are being asked to halt during an attach. We used to just close our + // file handle and debugserver will go away, but with remote proxies, it + // is better to send a positive signal, so let's send the interrupt first... + caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); m_gdb_comm.Disconnect(); } else caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); @@ -3094,100 +3115,182 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { } // Pre-requisite: wp != NULL. -static GDBStoppointType GetGDBStoppointType(Watchpoint *wp) { - assert(wp); - bool watch_read = wp->WatchpointRead(); - bool watch_write = wp->WatchpointWrite(); - - // watch_read and watch_write cannot both be false. - assert(watch_read || watch_write); - if (watch_read && watch_write) +static GDBStoppointType +GetGDBStoppointType(const WatchpointResourceSP &wp_res_sp) { + assert(wp_res_sp); + bool read = wp_res_sp->WatchpointResourceRead(); + bool write = wp_res_sp->WatchpointResourceWrite(); + + assert((read || write) && + "WatchpointResource type is neither read nor write"); + if (read && write) return eWatchpointReadWrite; - else if (watch_read) + else if (read) return eWatchpointRead; - else // Must be watch_write, then. + else return eWatchpointWrite; } -Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { +Status ProcessGDBRemote::EnableWatchpoint(WatchpointSP wp_sp, bool notify) { Status error; - if (wp) { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log(GetLog(GDBRLog::Watchpoints)); - LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (wp->IsEnabled()) { - LLDB_LOGF(log, - "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); - return error; - } + if (!wp_sp) { + error.SetErrorString("No watchpoint specified"); + return error; + } + user_id_t watchID = wp_sp->GetID(); + addr_t addr = wp_sp->GetLoadAddress(); + Log *log(GetLog(GDBRLog::Watchpoints)); + LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); + if (wp_sp->IsEnabled()) { + LLDB_LOGF(log, + "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); + return error; + } - GDBStoppointType type = GetGDBStoppointType(wp); - // Pass down an appropriate z/Z packet... - if (m_gdb_comm.SupportsGDBStoppointPacket(type)) { - if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, - wp->GetByteSize(), - GetInterruptTimeout()) == 0) { - wp->SetEnabled(true, notify); - return error; - } else - error.SetErrorString("sending gdb watchpoint packet failed"); - } else - error.SetErrorString("watchpoints not supported"); + bool read = wp_sp->WatchpointRead(); + bool write = wp_sp->WatchpointWrite() || wp_sp->WatchpointModify(); + size_t size = wp_sp->GetByteSize(); + + // New WatchpointResources needed to implement this Watchpoint. + std::vector<WatchpointResourceSP> resources; + + // LWP_TODO: Break up the user's request into pieces that can be watched + // given the capabilities of the target cpu / stub software. + // As a default, breaking the watched region up into target-pointer-sized, + // aligned, groups. + // + // Beyond the default, a stub can / should inform us of its capabilities, + // e.g. a stub that can do AArch64 power-of-2 MASK watchpoints. + // + // And the cpu may have unique capabilities. AArch64 BAS watchpoints + // can watch any sequential bytes in a doubleword, but Intel watchpoints + // can only watch 1, 2, 4, 8 bytes within a doubleword. + WatchpointResourceSP wp_res_sp = + std::make_shared<WatchpointResource>(addr, size, read, write); + resources.push_back(wp_res_sp); + + // LWP_TODO: Now that we know the WP Resources needed to implement this + // Watchpoint, we need to look at currently allocated Resources in the + // Process and if they match, or are within the same memory granule, or + // overlapping memory ranges, then we need to combine them. e.g. one + // Watchpoint watching 1 byte at 0x1002 and a second watchpoint watching 1 + // byte at 0x1003, they must use the same hardware watchpoint register + // (Resource) to watch them. + + // This may mean that an existing resource changes its type (read to + // read+write) or address range it is watching, in which case the old + // watchpoint needs to be disabled and the new Resource addr/size/type + // watchpoint enabled. + + // If we modify a shared Resource to accomodate this newly added Watchpoint, + // and we are unable to set all of the Resources for it in the inferior, we + // will return an error for this Watchpoint and the shared Resource should + // be restored. e.g. this Watchpoint requires three Resources, one which + // is shared with another Watchpoint. We extend the shared Resouce to + // handle both Watchpoints and we try to set two new ones. But if we don't + // have sufficient watchpoint register for all 3, we need to show an error + // for creating this Watchpoint and we should reset the shared Resource to + // its original configuration because it is no longer shared. + + bool set_all_resources = true; + std::vector<WatchpointResourceSP> succesfully_set_resources; + for (const auto &wp_res_sp : resources) { + addr_t addr = wp_res_sp->GetLoadAddress(); + size_t size = wp_res_sp->GetByteSize(); + GDBStoppointType type = GetGDBStoppointType(wp_res_sp); + if (!m_gdb_comm.SupportsGDBStoppointPacket(type) || + m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, size, + GetInterruptTimeout())) { + set_all_resources = false; + break; + } else { + succesfully_set_resources.push_back(wp_res_sp); + } + } + if (set_all_resources) { + wp_sp->SetEnabled(true, notify); + for (const auto &wp_res_sp : resources) { + // LWP_TODO: If we expanded/reused an existing Resource, + // it's already in the WatchpointResourceList. + wp_res_sp->AddConstituent(wp_sp); + m_watchpoint_resource_list.Add(wp_res_sp); + } + return error; } else { - error.SetErrorString("Watchpoint argument was NULL."); + // We failed to allocate one of the resources. Unset all + // of the new resources we did successfully set in the + // process. + for (const auto &wp_res_sp : succesfully_set_resources) { + addr_t addr = wp_res_sp->GetLoadAddress(); + size_t size = wp_res_sp->GetByteSize(); + GDBStoppointType type = GetGDBStoppointType(wp_res_sp); + m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size, + GetInterruptTimeout()); + } + error.SetErrorString("Setting one of the watchpoint resources failed"); } - if (error.Success()) - error.SetErrorToGenericError(); return error; } -Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { +Status ProcessGDBRemote::DisableWatchpoint(WatchpointSP wp_sp, bool notify) { Status error; - if (wp) { - user_id_t watchID = wp->GetID(); + if (!wp_sp) { + error.SetErrorString("Watchpoint argument was NULL."); + return error; + } + + user_id_t watchID = wp_sp->GetID(); + + Log *log(GetLog(GDBRLog::Watchpoints)); - Log *log(GetLog(GDBRLog::Watchpoints)); + addr_t addr = wp_sp->GetLoadAddress(); - addr_t addr = wp->GetLoadAddress(); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + watchID, (uint64_t)addr); + if (!wp_sp->IsEnabled()) { LLDB_LOGF(log, "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64, + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr); + // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling + // attempt might come from the user-supplied actions, we'll route it in + // order for the watchpoint object to intelligently process this action. + wp_sp->SetEnabled(false, notify); + return error; + } - if (!wp->IsEnabled()) { - LLDB_LOGF(log, - "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", - watchID, (uint64_t)addr); - // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling - // attempt might come from the user-supplied actions, we'll route it in - // order for the watchpoint object to intelligently process this action. - wp->SetEnabled(false, notify); - return error; - } + if (wp_sp->IsHardware()) { + bool disabled_all = true; - if (wp->IsHardware()) { - GDBStoppointType type = GetGDBStoppointType(wp); - // Pass down an appropriate z/Z packet... - if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, - wp->GetByteSize(), - GetInterruptTimeout()) == 0) { - wp->SetEnabled(false, notify); - return error; - } else - error.SetErrorString("sending gdb watchpoint packet failed"); + std::vector<WatchpointResourceSP> unused_resources; + for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) { + if (wp_res_sp->ConstituentsContains(wp_sp)) { + GDBStoppointType type = GetGDBStoppointType(wp_res_sp); + addr_t addr = wp_res_sp->GetLoadAddress(); + size_t size = wp_res_sp->GetByteSize(); + if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size, + GetInterruptTimeout())) { + disabled_all = false; + } else { + wp_res_sp->RemoveConstituent(wp_sp); + if (wp_res_sp->GetNumberOfConstituents() == 0) + unused_resources.push_back(wp_res_sp); + } + } } - // TODO: clear software watchpoints if we implement them - } else { - error.SetErrorString("Watchpoint argument was NULL."); + for (auto &wp_res_sp : unused_resources) + m_watchpoint_resource_list.Remove(wp_res_sp->GetID()); + + wp_sp->SetEnabled(false, notify); + if (!disabled_all) + error.SetErrorString("Failure disabling one of the watchpoint locations"); } - if (error.Success()) - error.SetErrorToGenericError(); return error; } @@ -3368,23 +3471,20 @@ void ProcessGDBRemote::MonitorDebugserverProcess( if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached) { - char error_str[1024]; - if (signo) { - const char *signal_cstr = - process_sp->GetUnixSignals()->GetSignalAsCString(signo); - if (signal_cstr) - ::snprintf(error_str, sizeof(error_str), - DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); + StreamString stream; + if (signo == 0) + stream.Format(DEBUGSERVER_BASENAME " died with an exit status of {0:x8}", + exit_status); + else { + llvm::StringRef signal_name = + process_sp->GetUnixSignals()->GetSignalAsStringRef(signo); + const char *format_str = DEBUGSERVER_BASENAME " died with signal {0}"; + if (!signal_name.empty()) + stream.Format(format_str, signal_name); else - ::snprintf(error_str, sizeof(error_str), - DEBUGSERVER_BASENAME " died with signal %i", signo); - } else { - ::snprintf(error_str, sizeof(error_str), - DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", - exit_status); + stream.Format(format_str, signo); } - - process_sp->SetExitStatus(-1, error_str); + process_sp->SetExitStatus(-1, stream.GetString()); } // Debugserver has exited we need to let our ProcessGDBRemote know that it no // longer has a debugserver instance @@ -4372,7 +4472,7 @@ bool ParseRegisters( // and a simple type. Just in case, look for that too (setting both // does no harm). if (!gdb_type.empty() && !(encoding_set || format_set)) { - if (llvm::StringRef(gdb_type).startswith("int")) { + if (llvm::StringRef(gdb_type).starts_with("int")) { reg_info.format = eFormatHex; reg_info.encoding = eEncodingUint; } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { @@ -4382,7 +4482,7 @@ bool ParseRegisters( reg_info.format = eFormatFloat; reg_info.encoding = eEncodingIEEE754; } else if (gdb_type == "aarch64v" || - llvm::StringRef(gdb_type).startswith("vec") || + llvm::StringRef(gdb_type).starts_with("vec") || gdb_type == "i387_ext" || gdb_type == "uint128") { // lldb doesn't handle 128-bit uints correctly (for ymm*h), so // treat them as vector (similarly to xmm/ymm) @@ -5169,7 +5269,7 @@ public: Options *GetOptions() override { return &m_option_group; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { ProcessGDBRemote *process = @@ -5191,14 +5291,13 @@ public: num_packets, max_send, max_recv, k_recv_amount, json, output_stream_sp ? *output_stream_sp : result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } } else { result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); } result.SetStatus(eReturnStatusFailed); - return false; } protected: @@ -5218,16 +5317,15 @@ public: ~CommandObjectProcessGDBRemotePacketHistory() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) { process->DumpPluginHistory(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } result.SetStatus(eReturnStatusFailed); - return false; } }; @@ -5245,14 +5343,14 @@ public: ~CommandObjectProcessGDBRemotePacketXferSize() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { result.AppendErrorWithFormat("'%s' takes an argument to specify the max " "amount to be transferred when " "reading/writing", m_cmd_name.c_str()); - return false; + return; } ProcessGDBRemote *process = @@ -5264,11 +5362,10 @@ public: if (errno == 0 && user_specified_max != 0) { process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } } result.SetStatus(eReturnStatusFailed); - return false; } }; @@ -5289,13 +5386,13 @@ public: ~CommandObjectProcessGDBRemotePacketSend() override = default; - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { result.AppendErrorWithFormat( "'%s' takes a one or more packet content arguments", m_cmd_name.c_str()); - return false; + return; } ProcessGDBRemote *process = @@ -5321,7 +5418,6 @@ public: output_strm.Printf("response: %s\n", response.GetStringRef().data()); } } - return true; } }; @@ -5338,12 +5434,12 @@ public: ~CommandObjectProcessGDBRemotePacketMonitor() override = default; - bool DoExecute(llvm::StringRef command, + void DoExecute(llvm::StringRef command, CommandReturnObject &result) override { if (command.empty()) { result.AppendErrorWithFormat("'%s' takes a command string argument", m_cmd_name.c_str()); - return false; + return; } ProcessGDBRemote *process = @@ -5367,7 +5463,6 @@ public: else output_strm.Printf("response: %s\n", response.GetStringRef().data()); } - return true; } }; @@ -5447,16 +5542,12 @@ void ProcessGDBRemote::DidForkSwitchHardwareTraps(bool enable) { }); } - WatchpointList &wps = GetTarget().GetWatchpointList(); - size_t wp_count = wps.GetSize(); - for (size_t i = 0; i < wp_count; ++i) { - WatchpointSP wp = wps.GetByIndex(i); - if (wp->IsEnabled()) { - GDBStoppointType type = GetGDBStoppointType(wp.get()); - m_gdb_comm.SendGDBStoppointTypePacket(type, enable, wp->GetLoadAddress(), - wp->GetByteSize(), - GetInterruptTimeout()); - } + for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) { + addr_t addr = wp_res_sp->GetLoadAddress(); + size_t size = wp_res_sp->GetByteSize(); + GDBStoppointType type = GetGDBStoppointType(wp_res_sp); + m_gdb_comm.SendGDBStoppointTypePacket(type, enable, addr, size, + GetInterruptTimeout()); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index f0ead4c38c23..c1ea1cc79055 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -158,9 +158,11 @@ public: Status DisableBreakpointSite(BreakpointSite *bp_site) override; // Process Watchpoints - Status EnableWatchpoint(Watchpoint *wp, bool notify = true) override; + Status EnableWatchpoint(lldb::WatchpointSP wp_sp, + bool notify = true) override; - Status DisableWatchpoint(Watchpoint *wp, bool notify = true) override; + Status DisableWatchpoint(lldb::WatchpointSP wp_sp, + bool notify = true) override; std::optional<uint32_t> GetWatchpointSlotCount() override; @@ -470,6 +472,9 @@ private: void DidForkSwitchSoftwareBreakpoints(bool enable); void DidForkSwitchHardwareTraps(bool enable); + void ParseExpeditedRegisters(ExpeditedRegisterMap &expedited_register_map, + lldb::ThreadSP thread_sp); + // Lists of register fields generated from the remote's target XML. // Pointers to these RegisterFlags will be set in the register info passed // back to the upper levels of lldb. Doing so is safe because this class will diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td index d4c3c8b94b7e..520dad062e09 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td @@ -3,7 +3,11 @@ include "../../../../include/lldb/Core/PropertiesBase.td" let Definition = "processgdbremote" in { def PacketTimeout: Property<"packet-timeout", "UInt64">, Global, +#ifdef LLDB_SANITIZED + DefaultUnsignedValue<60>, +#else DefaultUnsignedValue<5>, +#endif Desc<"Specify the default packet timeout in seconds.">; def TargetDefinitionFile: Property<"target-definition-file", "FileSpec">, Global, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index 99d0b54c40f9..b72307c7e4b9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -166,7 +166,7 @@ ProcessMinidump::~ProcessMinidump() { // make sure all of the broadcaster cleanup goes as planned. If we destruct // this class, then Process::~Process() might have problems trying to fully // destroy the broadcaster. - Finalize(); + Finalize(true /* destructing */); } void ProcessMinidump::Initialize() { @@ -795,12 +795,12 @@ public: Options *GetOptions() override { return &m_option_group; } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc > 0) { result.AppendErrorWithFormat("'%s' take no arguments, only options", m_cmd_name.c_str()); - return false; + return; } SetDefaultOptionsIfNoneAreSet(); @@ -904,9 +904,7 @@ public: DumpTextStream(StreamType::FacebookThreadName, "Facebook Thread Name"); if (DumpFacebookLogcat()) - DumpTextStream(StreamType::FacebookLogcat, - "Facebook Logcat"); - return true; + DumpTextStream(StreamType::FacebookLogcat, "Facebook Logcat"); } }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h index 8ae751095c04..58cf8d62fb86 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h @@ -67,13 +67,14 @@ public: uint8_t v[32 * 16]; // 32 128-bit floating point registers }; -protected: enum class Flags : uint32_t { ARM64_Flag = 0x80000000, Integer = ARM64_Flag | 0x00000002, FloatingPoint = ARM64_Flag | 0x00000004, LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ FloatingPoint) }; + +protected: Context m_regs; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h index 9592d335eff7..4dffc4f9db0e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h @@ -99,7 +99,7 @@ struct MinidumpContext_x86_32 { // The next field is included with // MinidumpContext_x86_32_Flags::ExtendedRegisters - // It contains vector (MMX/SSE) registers. It it laid out in the + // It contains vector (MMX/SSE) registers. It is laid out in the // format used by the fxsave and fsrstor instructions, so it includes // a copy of the x87 floating-point registers as well. See FXSAVE in // "Intel Architecture Software Developer's Manual, Volume 2." diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index e99a2a08bd50..66f861350d14 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -108,10 +108,18 @@ ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp, ExecutionContext exe_ctx(target_sp, /*get_process=*/false); // Create process script object - StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject( + auto obj_or_err = GetInterface().CreatePluginObject( m_scripted_metadata.GetClassName(), exe_ctx, m_scripted_metadata.GetArgsSP()); + if (!obj_or_err) { + llvm::consumeError(obj_or_err.takeError()); + error.SetErrorString("Failed to create script object."); + return; + } + + StructuredData::GenericSP object_sp = *obj_or_err; + if (!object_sp || !object_sp->IsValid()) { error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", __FUNCTION__, @@ -122,11 +130,17 @@ ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp, ScriptedProcess::~ScriptedProcess() { Clear(); + // If the interface is not valid, we can't call Finalize(). When that happens + // it means that the Scripted Process instanciation failed and the + // CreateProcess function returns a nullptr, so no one besides this class + // should have access to that bogus process object. + if (!m_interface_up) + return; // We need to call finalize on the process before destroying ourselves to // make sure all of the broadcaster cleanup goes as planned. If we destruct // this class, then Process::~Process() might have problems trying to fully // destroy the broadcaster. - Finalize(); + Finalize(true /* destructing */); } void ScriptedProcess::Initialize() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp index 684375957d24..88a4ca3b0389 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -56,14 +56,18 @@ ScriptedThread::Create(ScriptedProcess &process, } ExecutionContext exe_ctx(process); - StructuredData::GenericSP owned_script_object_sp = - scripted_thread_interface->CreatePluginObject( - thread_class_name, exe_ctx, process.m_scripted_metadata.GetArgsSP(), - script_object); + auto obj_or_err = scripted_thread_interface->CreatePluginObject( + thread_class_name, exe_ctx, process.m_scripted_metadata.GetArgsSP(), + script_object); - if (!owned_script_object_sp) + if (!obj_or_err) { + llvm::consumeError(obj_or_err.takeError()); return llvm::createStringError(llvm::inconvertibleErrorCode(), "Failed to create script object."); + } + + StructuredData::GenericSP owned_script_object_sp = *obj_or_err; + if (!owned_script_object_sp->IsValid()) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Created script object is invalid."); @@ -172,8 +176,9 @@ bool ScriptedThread::LoadArtificialStackFrames() { StackFrameListSP frames = GetStackFrameList(); for (size_t idx = 0; idx < arr_size; idx++) { - StructuredData::Dictionary *dict; - if (!arr_sp->GetItemAtIndexAsDictionary(idx, dict) || !dict) + std::optional<StructuredData::Dictionary *> maybe_dict = + arr_sp->GetItemAtIndexAsDictionary(idx); + if (!maybe_dict) return ScriptedInterface::ErrorWithMessage<bool>( LLVM_PRETTY_FUNCTION, llvm::Twine( @@ -181,6 +186,7 @@ bool ScriptedThread::LoadArtificialStackFrames() { llvm::Twine(idx) + llvm::Twine(") from stackframe array.")) .str(), error, LLDBLog::Thread); + StructuredData::Dictionary *dict = *maybe_dict; lldb::addr_t pc; if (!dict->GetValueForKeyAsInteger("pc", pc)) diff --git a/contrib/llvm-project/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp b/contrib/llvm-project/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp index aeb54ef9ee24..067768537c06 100644 --- a/contrib/llvm-project/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/RegisterTypeBuilder/RegisterTypeBuilderClang.cpp @@ -60,7 +60,8 @@ CompilerType RegisterTypeBuilderClang::GetRegisterType( fields_type = type_system->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, - register_type_name, clang::TTK_Struct, lldb::eLanguageTypeC); + register_type_name, llvm::to_underlying(clang::TagTypeKind::Struct), + lldb::eLanguageTypeC); type_system->StartTagDeclarationDefinition(fields_type); // We assume that RegisterFlags has padded and sorted the fields diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp index be573cfba610..f50bc61279d0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -11,7 +11,7 @@ #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/Stream.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp index bec90b2038e1..7aeee6e40395 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp @@ -9,7 +9,6 @@ #include "ScriptInterpreterNone.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StringList.h" @@ -27,17 +26,19 @@ ScriptInterpreterNone::ScriptInterpreterNone(Debugger &debugger) ScriptInterpreterNone::~ScriptInterpreterNone() = default; +static const char *no_interpreter_err_msg = + "error: Embedded script interpreter unavailable. LLDB was built without " + "scripting language support.\n"; + bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command, CommandReturnObject *, const ExecuteScriptOptions &) { - m_debugger.GetErrorStream().PutCString( - "error: there is no embedded script interpreter in this mode.\n"); + m_debugger.GetErrorStream().PutCString(no_interpreter_err_msg); return false; } void ScriptInterpreterNone::ExecuteInterpreterLoop() { - m_debugger.GetErrorStream().PutCString( - "error: there is no embedded script interpreter in this mode.\n"); + m_debugger.GetErrorStream().PutCString(no_interpreter_err_msg); } void ScriptInterpreterNone::Initialize() { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp new file mode 100644 index 000000000000..c162c7367c65 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.cpp @@ -0,0 +1,82 @@ +//===-- ScriptedThreadPythonInterface.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/Host/Config.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "../lldb-python.h" + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "OperatingSystemPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +OperatingSystemPythonInterface::OperatingSystemPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : OperatingSystemInterface(), ScriptedThreadPythonInterface(interpreter) {} + +llvm::Expected<StructuredData::GenericSP> +OperatingSystemPythonInterface::CreatePluginObject( + llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr, + exe_ctx.GetProcessSP()); +} + +StructuredData::DictionarySP +OperatingSystemPythonInterface::CreateThread(lldb::tid_t tid, + lldb::addr_t context) { + Status error; + StructuredData::DictionarySP dict = Dispatch<StructuredData::DictionarySP>( + "create_thread", error, tid, context); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, + error)) + return {}; + + return dict; +} + +StructuredData::ArraySP OperatingSystemPythonInterface::GetThreadInfo() { + Status error; + StructuredData::ArraySP arr = + Dispatch<StructuredData::ArraySP>("get_thread_info", error); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, + error)) + return {}; + + return arr; +} + +StructuredData::DictionarySP OperatingSystemPythonInterface::GetRegisterInfo() { + return ScriptedThreadPythonInterface::GetRegisterInfo(); +} + +std::optional<std::string> +OperatingSystemPythonInterface::GetRegisterContextForTID(lldb::tid_t tid) { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_register_data", error, tid); + + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + return obj->GetAsString()->GetValue().str(); +} + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h new file mode 100644 index 000000000000..da7bbf13b1d5 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/OperatingSystemPythonInterface.h @@ -0,0 +1,48 @@ +//===-- OperatingSystemPythonInterface.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_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedThreadPythonInterface.h" +#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h" +#include <optional> + +namespace lldb_private { +class OperatingSystemPythonInterface + : virtual public OperatingSystemInterface, + virtual public ScriptedThreadPythonInterface { +public: + OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>({"get_thread_info"}); + } + + StructuredData::DictionarySP CreateThread(lldb::tid_t tid, + lldb::addr_t context) override; + + StructuredData::ArraySP GetThreadInfo() override; + + StructuredData::DictionarySP GetRegisterInfo() override; + + std::optional<std::string> GetRegisterContextForTID(lldb::tid_t tid) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp index a0c55874c70a..9ba4731032bd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.cpp @@ -14,10 +14,10 @@ #if LLDB_ENABLE_PYTHON // LLDB Python header must be included first -#include "lldb-python.h" +#include "../lldb-python.h" -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" #include "ScriptedPlatformPythonInterface.h" using namespace lldb; @@ -29,29 +29,15 @@ ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {} -StructuredData::GenericSP ScriptedPlatformPythonInterface::CreatePluginObject( +llvm::Expected<StructuredData::GenericSP> +ScriptedPlatformPythonInterface::CreatePluginObject( llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { - if (class_name.empty()) - return {}; - - StructuredDataImpl args_impl(args_sp); - std::string error_string; - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - lldb::ExecutionContextRefSP exe_ctx_ref_sp = + ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx); - - PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), - exe_ctx_ref_sp, args_impl, error_string); - - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); - - return m_object_instance_sp; + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); } StructuredData::DictionarySP ScriptedPlatformPythonInterface::ListProcesses() { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h index 1e3ad9962325..0842d3a00342 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPlatformPythonInterface.h @@ -6,15 +6,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H #include "lldb/Host/Config.h" #if LLDB_ENABLE_PYTHON #include "ScriptedPythonInterface.h" -#include "lldb/Interpreter/ScriptedPlatformInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h" namespace lldb_private { class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, @@ -22,12 +22,18 @@ class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, public: ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter); - StructuredData::GenericSP + llvm::Expected<StructuredData::GenericSP> CreatePluginObject(const llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>( + {"list_processes", "attach_to_process", "launch_process", + "kill_process"}); + } + StructuredData::DictionarySP ListProcesses() override; StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override; @@ -41,4 +47,4 @@ public: } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp index 019924fa1971..e86b34d6b930 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp @@ -9,7 +9,7 @@ #include "lldb/Host/Config.h" #if LLDB_ENABLE_PYTHON // LLDB Python header must be included first -#include "lldb-python.h" +#include "../lldb-python.h" #endif #include "lldb/Target/Process.h" #include "lldb/Utility/Log.h" @@ -18,8 +18,8 @@ #if LLDB_ENABLE_PYTHON -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedThreadPythonInterface.h" #include <optional> @@ -33,29 +33,15 @@ ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {} -StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( +llvm::Expected<StructuredData::GenericSP> +ScriptedProcessPythonInterface::CreatePluginObject( llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { - if (class_name.empty()) - return {}; - - StructuredDataImpl args_impl(args_sp); - std::string error_string; - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - lldb::ExecutionContextRefSP exe_ctx_ref_sp = + ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx); - - PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), - exe_ctx_ref_sp, args_impl, error_string); - - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); - - return m_object_instance_sp; + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); } StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { @@ -199,7 +185,7 @@ ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { lldb::ScriptedThreadInterfaceSP ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { - return std::make_shared<ScriptedThreadPythonInterface>(m_interpreter); + return m_interpreter.CreateScriptedThreadInterface(); } StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h index ff03eab07648..c75caa9340f2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.h @@ -6,15 +6,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H #include "lldb/Host/Config.h" #if LLDB_ENABLE_PYTHON #include "ScriptedPythonInterface.h" -#include "lldb/Interpreter/ScriptedProcessInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h" #include <optional> namespace lldb_private { @@ -23,12 +23,17 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface, public: ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter); - StructuredData::GenericSP + llvm::Expected<StructuredData::GenericSP> CreatePluginObject(const llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>( + {"read_memory_at_address", "is_alive", "get_scripted_thread_plugin"}); + } + StructuredData::DictionarySP GetCapabilities() override; Status Attach(const ProcessAttachInfo &attach_info) override; @@ -68,4 +73,4 @@ private: } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp index 1e36a81fde54..6f22503b279c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -13,9 +13,9 @@ #if LLDB_ENABLE_PYTHON // LLDB Python header must be included first -#include "lldb-python.h" +#include "../lldb-python.h" -#include "ScriptInterpreterPythonImpl.h" +#include "../ScriptInterpreterPythonImpl.h" #include "ScriptedPythonInterface.h" #include <optional> diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h index 4d0645d18aca..163659234466 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H #if LLDB_ENABLE_PYTHON @@ -18,12 +18,12 @@ #include <utility> #include "lldb/Host/Config.h" -#include "lldb/Interpreter/ScriptedInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedInterface.h" #include "lldb/Utility/DataBufferHeap.h" -#include "PythonDataObjects.h" -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" +#include "../PythonDataObjects.h" +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" namespace lldb_private { class ScriptInterpreterPythonImpl; @@ -32,6 +32,196 @@ public: ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); ~ScriptedPythonInterface() override = default; + enum class AbstractMethodCheckerCases { + eNotImplemented, + eNotAllocated, + eNotCallable, + eValid + }; + + llvm::Expected<std::map<llvm::StringLiteral, AbstractMethodCheckerCases>> + CheckAbstractMethodImplementation( + const python::PythonDictionary &class_dict) const { + + using namespace python; + + std::map<llvm::StringLiteral, AbstractMethodCheckerCases> checker; +#define SET_ERROR_AND_CONTINUE(method_name, error) \ + { \ + checker[method_name] = error; \ + continue; \ + } + + for (const llvm::StringLiteral &method_name : GetAbstractMethods()) { + if (!class_dict.HasKey(method_name)) + SET_ERROR_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotImplemented) + auto callable_or_err = class_dict.GetItem(method_name); + if (!callable_or_err) + SET_ERROR_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotAllocated) + if (!PythonCallable::Check(callable_or_err.get().get())) + SET_ERROR_AND_CONTINUE(method_name, + AbstractMethodCheckerCases::eNotCallable) + checker[method_name] = AbstractMethodCheckerCases::eValid; + } + +#undef HANDLE_ERROR + + return checker; + } + + template <typename... Args> + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, + StructuredData::Generic *script_obj, Args... args) { + using namespace python; + using Locker = ScriptInterpreterPythonImpl::Locker; + + auto create_error = [](std::string message) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), message); + }; + + bool has_class_name = !class_name.empty(); + bool has_interpreter_dict = + !(llvm::StringRef(m_interpreter.GetDictionaryName()).empty()); + if (!has_class_name && !has_interpreter_dict && !script_obj) { + if (!has_class_name) + return create_error("Missing script class name."); + else if (!has_interpreter_dict) + return create_error("Invalid script interpreter dictionary."); + else + return create_error("Missing scripting object."); + } + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + PythonObject result = {}; + + if (script_obj) { + result = PythonObject(PyRefType::Borrowed, + static_cast<PyObject *>(script_obj->GetValue())); + } else { + auto dict = + PythonModule::MainModule().ResolveName<python::PythonDictionary>( + m_interpreter.GetDictionaryName()); + if (!dict.IsAllocated()) + return create_error( + llvm::formatv("Could not find interpreter dictionary: %s", + m_interpreter.GetDictionaryName())); + + auto init = + PythonObject::ResolveNameWithDictionary<python::PythonCallable>( + class_name, dict); + if (!init.IsAllocated()) + return create_error(llvm::formatv("Could not find script class: %s", + class_name.data())); + + std::tuple<Args...> original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + std::string error_string; + llvm::Expected<PythonCallable::ArgInfo> arg_info = init.GetArgInfo(); + if (!arg_info) { + llvm::handleAllErrors( + arg_info.takeError(), + [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, + [&](const llvm::ErrorInfoBase &E) { + error_string.append(E.message()); + }); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + error_string); + } + + llvm::Expected<PythonObject> expected_return_object = + create_error("Resulting object is not initialized."); + + std::apply( + [&init, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = init(args...); + }, + transformed_args); + + if (!expected_return_object) + return expected_return_object.takeError(); + result = expected_return_object.get(); + } + + if (!result.IsValid()) + return create_error("Resulting object is not a valid Python Object."); + if (!result.HasAttribute("__class__")) + return create_error("Resulting object doesn't have '__class__' member."); + + PythonObject obj_class = result.GetAttributeValue("__class__"); + if (!obj_class.IsValid()) + return create_error("Resulting class object is not a valid."); + if (!obj_class.HasAttribute("__name__")) + return create_error( + "Resulting object class doesn't have '__name__' member."); + PythonString obj_class_name = + obj_class.GetAttributeValue("__name__").AsType<PythonString>(); + + PythonObject object_class_mapping_proxy = + obj_class.GetAttributeValue("__dict__"); + if (!obj_class.HasAttribute("__dict__")) + return create_error( + "Resulting object class doesn't have '__dict__' member."); + + PythonCallable dict_converter = PythonModule::BuiltinsModule() + .ResolveName("dict") + .AsType<PythonCallable>(); + if (!dict_converter.IsAllocated()) + return create_error( + "Python 'builtins' module doesn't have 'dict' class."); + + PythonDictionary object_class_dict = + dict_converter(object_class_mapping_proxy).AsType<PythonDictionary>(); + if (!object_class_dict.IsAllocated()) + return create_error("Coudn't create dictionary from resulting object " + "class mapping proxy object."); + + auto checker_or_err = CheckAbstractMethodImplementation(object_class_dict); + if (!checker_or_err) + return checker_or_err.takeError(); + + for (const auto &method_checker : *checker_or_err) + switch (method_checker.second) { + case AbstractMethodCheckerCases::eNotImplemented: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} not implemented.", + obj_class_name.GetString(), method_checker.first); + break; + case AbstractMethodCheckerCases::eNotAllocated: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} not allocated.", + obj_class_name.GetString(), method_checker.first); + break; + case AbstractMethodCheckerCases::eNotCallable: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} not callable.", + obj_class_name.GetString(), method_checker.first); + break; + case AbstractMethodCheckerCases::eValid: + LLDB_LOG(GetLog(LLDBLog::Script), + "Abstract method {0}.{1} implemented & valid.", + obj_class_name.GetString(), method_checker.first); + break; + } + + for (const auto &method_checker : *checker_or_err) + if (method_checker.second != AbstractMethodCheckerCases::eValid) + return create_error( + llvm::formatv("Abstract method {0}.{1} missing. Enable lldb " + "script log for more details.", + obj_class_name.GetString(), method_checker.first)); + + m_object_instance_sp = StructuredData::GenericSP( + new StructuredPythonObject(std::move(result))); + return m_object_instance_sp; + } + protected: template <typename T = StructuredData::ObjectSP> T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { @@ -83,10 +273,6 @@ protected: PythonObject py_return = std::move(expected_return_object.get()); - if (!py_return.IsAllocated()) - return ErrorWithMessage<T>(caller_signature, "Returned object is null.", - error); - // Now that we called the python method with the transformed arguments, // we need to interate again over both the original and transformed // parameter pack, and transform back the parameter that were passed in @@ -97,6 +283,8 @@ protected: caller_signature, "Couldn't re-assign reference and pointer arguments.", error); + if (!py_return.IsAllocated()) + return {}; return ExtractValueFromPythonObject<T>(py_return, error); } @@ -122,6 +310,18 @@ protected: return python::SWIGBridge::ToSWIGWrapper(arg); } + python::PythonObject Transform(const StructuredDataImpl &arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ExecutionContextRefSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { return python::SWIGBridge::ToSWIGWrapper(arg); } @@ -146,7 +346,6 @@ protected: original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); } - void ReverseTransform(bool &original_arg, python::PythonObject transformed_arg, Status &error) { python::PythonBoolean boolean_arg = python::PythonBoolean( @@ -254,4 +453,4 @@ ScriptedPythonInterface::ExtractValueFromPythonObject< } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp index 5603a1541314..18e268527eb2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.cpp @@ -13,10 +13,10 @@ #if LLDB_ENABLE_PYTHON // LLDB Python header must be included first -#include "lldb-python.h" +#include "../lldb-python.h" -#include "SWIGPythonBridge.h" -#include "ScriptInterpreterPythonImpl.h" +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" #include "ScriptedThreadPythonInterface.h" #include <optional> @@ -29,37 +29,15 @@ ScriptedThreadPythonInterface::ScriptedThreadPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedThreadInterface(), ScriptedPythonInterface(interpreter) {} -StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( +llvm::Expected<StructuredData::GenericSP> +ScriptedThreadPythonInterface::CreatePluginObject( const llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { - if (class_name.empty() && !script_obj) - return {}; - - StructuredDataImpl args_impl(args_sp); - std::string error_string; - - Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - PythonObject ret_val; - - if (!script_obj) { - lldb::ExecutionContextRefSP exe_ctx_ref_sp = - std::make_shared<ExecutionContextRef>(exe_ctx); - ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), - exe_ctx_ref_sp, args_impl, error_string); - } else - ret_val = PythonObject(PyRefType::Borrowed, - static_cast<PyObject *>(script_obj->GetValue())); - - if (!ret_val) - return {}; - - m_object_instance_sp = - StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); - - return m_object_instance_sp; + ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + StructuredDataImpl sd_impl(args_sp); + return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, + exe_ctx_ref_sp, sd_impl); } lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h index eac4941f8814..5676f7f1d675 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPythonInterface.h @@ -6,15 +6,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H #include "lldb/Host/Config.h" #if LLDB_ENABLE_PYTHON #include "ScriptedPythonInterface.h" -#include "lldb/Interpreter/ScriptedProcessInterface.h" +#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h" #include <optional> namespace lldb_private { @@ -23,11 +23,16 @@ class ScriptedThreadPythonInterface : public ScriptedThreadInterface, public: ScriptedThreadPythonInterface(ScriptInterpreterPythonImpl &interpreter); - StructuredData::GenericSP + llvm::Expected<StructuredData::GenericSP> CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; + llvm::SmallVector<llvm::StringLiteral> GetAbstractMethods() const override { + return llvm::SmallVector<llvm::StringLiteral>( + {"get_stop_reason", "get_register_context"}); + } + lldb::tid_t GetThreadID() override; std::optional<std::string> GetName() override; @@ -49,4 +54,4 @@ public: } // namespace lldb_private #endif // LLDB_ENABLE_PYTHON -#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDTHREADPYTHONINTERFACE_H +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index eee2f6f5d43f..ea0a1cdff40f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -71,7 +71,9 @@ Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { } static bool python_is_finalizing() { -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13) || (PY_MAJOR_VERSION > 3) + return Py_IsFinalizing(); +#elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 return _Py_Finalizing != nullptr; #else return _Py_IsFinalizing(); @@ -661,6 +663,20 @@ bool PythonDictionary::Check(PyObject *py_obj) { return PyDict_Check(py_obj); } +bool PythonDictionary::HasKey(const llvm::Twine &key) const { + if (!IsValid()) + return false; + + PythonString key_object(key.isSingleStringRef() ? key.getSingleStringRef() + : key.str()); + + if (int res = PyDict_Contains(m_py_obj, key_object.get()) > 0) + return res; + + PyErr_Print(); + return false; +} + uint32_t PythonDictionary::GetSize() const { if (IsValid()) return PyDict_Size(m_py_obj); @@ -1344,7 +1360,7 @@ llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { FileSP file_sp; if (borrowed) { - // In this case we we don't need to retain the python + // In this case we don't need to retain the python // object at all. file_sp = std::make_shared<NativeFile>(fd, options.get(), false); } else { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 012f16e95e77..82eee76e42b2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -562,6 +562,8 @@ public: static bool Check(PyObject *py_obj); + bool HasKey(const llvm::Twine &key) const; + uint32_t GetSize() const; PythonList GetKeys() const; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 630ab293cf93..7cdd5577919b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -116,12 +116,6 @@ public: // callbacks. Although these are scripting-language specific, their definition // depends on the public API. - static python::PythonObject LLDBSwigPythonCreateScriptedObject( - const char *python_class_name, const char *session_dictionary_name, - lldb::ExecutionContextRefSP exe_ctx_sp, - const lldb_private::StructuredDataImpl &args_impl, - std::string &error_string); - static llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 55b7a73712c4..ef7a2c128a22 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -14,12 +14,14 @@ // LLDB Python header must be included first #include "lldb-python.h" +#include "Interfaces/OperatingSystemPythonInterface.h" +#include "Interfaces/ScriptedPlatformPythonInterface.h" +#include "Interfaces/ScriptedProcessPythonInterface.h" +#include "Interfaces/ScriptedThreadPythonInterface.h" #include "PythonDataObjects.h" #include "PythonReadline.h" #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" -#include "ScriptedPlatformPythonInterface.h" -#include "ScriptedProcessPythonInterface.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFrame.h" @@ -177,18 +179,31 @@ private: return; #endif +// `PyEval_ThreadsInitialized` was deprecated in Python 3.9 and removed in +// Python 3.13. It has been returning `true` always since Python 3.7. +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) || (PY_MAJOR_VERSION < 3) if (PyEval_ThreadsInitialized()) { +#else + if (true) { +#endif Log *log = GetLog(LLDBLog::Script); m_was_already_initialized = true; m_gil_state = PyGILState_Ensure(); LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n", m_gil_state == PyGILState_UNLOCKED ? "un" : ""); + +// `PyEval_InitThreads` was deprecated in Python 3.9 and removed in +// Python 3.13. +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) || (PY_MAJOR_VERSION < 3) return; } // InitThreads acquires the GIL if it hasn't been called before. PyEval_InitThreads(); +#else + } +#endif } PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; @@ -412,8 +427,6 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_active_io_handler(eIOHandlerNone), m_session_is_active(false), m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { - m_scripted_platform_interface_up = - std::make_unique<ScriptedPlatformPythonInterface>(*this); m_dictionary_name.append("_dict"); StreamString run_string; @@ -582,10 +595,6 @@ void ScriptInterpreterPythonImpl::LeaveSession() { // up believing we have no thread state and PyImport_AddModule will crash if // that is the case - since that seems to only happen when destroying the // SBDebugger, we can make do without clearing up stdout and stderr - - // rdar://problem/11292882 - // When the current thread state is NULL, PyThreadState_Get() issues a fatal - // error. if (PyThreadState_GetDict()) { PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { @@ -1519,6 +1528,16 @@ ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() { return std::make_unique<ScriptedProcessPythonInterface>(*this); } +ScriptedThreadInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() { + return std::make_shared<ScriptedThreadPythonInterface>(*this); +} + +OperatingSystemInterfaceSP +ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() { + return std::make_shared<OperatingSystemPythonInterface>(*this); +} + StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject( ScriptObject obj) { @@ -1530,159 +1549,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject( return py_obj.CreateStructuredObject(); } -StructuredData::GenericSP -ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( - const char *class_name, lldb::ProcessSP process_sp) { - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!process_sp) - return StructuredData::GenericSP(); - - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - PythonObject ret_val = SWIGBridge::LLDBSWIGPythonCreateOSPlugin( - class_name, m_dictionary_name.c_str(), process_sp); - - return StructuredData::GenericSP( - new StructuredPythonObject(std::move(ret_val))); -} - -StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( - StructuredData::ObjectSP os_plugin_object_sp) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected<PythonObject> expected_py_return = - implementor.CallMethod("get_register_info"); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); - return result_dict.CreateStructuredDictionary(); - } - return StructuredData::DictionarySP(); -} - -StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( - StructuredData::ObjectSP os_plugin_object_sp) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected<PythonObject> expected_py_return = - implementor.CallMethod("get_thread_info"); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonList result_list(PyRefType::Borrowed, py_return.get()); - return result_list.CreateStructuredArray(); - } - return StructuredData::ArraySP(); -} - -StructuredData::StringSP -ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( - StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected<PythonObject> expected_py_return = - implementor.CallMethod("get_register_data", tid); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonBytes result(PyRefType::Borrowed, py_return.get()); - return result.CreateStructuredString(); - } - return {}; -} - -StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( - StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, - lldb::addr_t context) { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!os_plugin_object_sp) - return {}; - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return {}; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)generic->GetValue()); - - if (!implementor.IsAllocated()) - return {}; - - llvm::Expected<PythonObject> expected_py_return = - implementor.CallMethod("create_thread", tid, context); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return {}; - } - - PythonObject py_return = std::move(expected_py_return.get()); - - if (py_return.get()) { - PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); - return result_dict.CreateStructuredDictionary(); - } - return StructuredData::DictionarySP(); -} - StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( const char *class_name, const StructuredDataImpl &args_data, std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) { @@ -1783,7 +1649,7 @@ lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( bool ScriptInterpreterPythonImpl::ScriptedThreadPlanGetStopDescription( - StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream, + StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream, bool &script_error) { StructuredData::Generic *generic = nullptr; if (implementor_sp) @@ -2442,24 +2308,11 @@ ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName( } PythonObject py_return = std::move(expected_py_return.get()); + if (!py_return.IsAllocated() || !PythonString::Check(py_return.get())) + return {}; - ConstString ret_val; - bool got_string = false; - std::string buffer; - - if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { - PythonString py_string(PyRefType::Borrowed, py_return.get()); - llvm::StringRef return_data(py_string.GetString()); - if (!return_data.empty()) { - buffer.assign(return_data.data(), return_data.size()); - got_string = true; - } - } - - if (got_string) - ret_val.SetCStringWithLength(buffer.c_str(), buffer.size()); - - return ret_val; + PythonString type_name(PyRefType::Borrowed, py_return.get()); + return ConstString(type_name.GetString()); } bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 01db6c520300..a33499816d8d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -134,23 +134,9 @@ public: lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override; - StructuredData::GenericSP - OSPlugin_CreatePluginObject(const char *class_name, - lldb::ProcessSP process_sp) override; - - StructuredData::DictionarySP - OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; - StructuredData::ArraySP - OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; - - StructuredData::StringSP - OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, - lldb::tid_t thread_id) override; - - StructuredData::DictionarySP - OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, - lldb::tid_t tid, lldb::addr_t context) override; + lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() override; StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, diff --git a/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp index a5818915773c..c46dc54c912e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -32,6 +32,8 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" +#include "llvm/ADT/StringMap.h" + #define DARWIN_LOG_TYPE_VALUE "DarwinLog" using namespace lldb; @@ -117,8 +119,8 @@ enum { class StructuredDataDarwinLogProperties : public Properties { public: - static ConstString &GetSettingName() { - static ConstString g_setting_name("darwin-log"); + static llvm::StringRef GetSettingName() { + static constexpr llvm::StringLiteral g_setting_name("darwin-log"); return g_setting_name; } @@ -183,21 +185,20 @@ public: std::function<FilterRuleSP(bool accept, size_t attribute_index, const std::string &op_arg, Status &error)>; - static void RegisterOperation(ConstString operation, + static void RegisterOperation(llvm::StringRef operation, const OperationCreationFunc &creation_func) { GetCreationFuncMap().insert(std::make_pair(operation, creation_func)); } static FilterRuleSP CreateRule(bool match_accepts, size_t attribute, - ConstString operation, + llvm::StringRef operation, const std::string &op_arg, Status &error) { // Find the creation func for this type of filter rule. auto map = GetCreationFuncMap(); auto find_it = map.find(operation); if (find_it == map.end()) { - error.SetErrorStringWithFormat("unknown filter operation \"" - "%s\"", - operation.GetCString()); + error.SetErrorStringWithFormatv("unknown filter operation \"{0}\"", + operation); return FilterRuleSP(); } @@ -217,7 +218,7 @@ public: dict_p->AddStringItem("attribute", s_filter_attributes[m_attribute_index]); // Indicate the type of the rule. - dict_p->AddStringItem("type", GetOperationType().GetCString()); + dict_p->AddStringItem("type", GetOperationType()); // Let the rule add its own specific details here. DoSerialization(*dict_p); @@ -227,10 +228,10 @@ public: virtual void Dump(Stream &stream) const = 0; - ConstString GetOperationType() const { return m_operation; } + llvm::StringRef GetOperationType() const { return m_operation; } protected: - FilterRule(bool accept, size_t attribute_index, ConstString operation) + FilterRule(bool accept, size_t attribute_index, llvm::StringRef operation) : m_accept(accept), m_attribute_index(attribute_index), m_operation(operation) {} @@ -243,7 +244,7 @@ protected: } private: - using CreationFuncMap = std::map<ConstString, OperationCreationFunc>; + using CreationFuncMap = llvm::StringMap<OperationCreationFunc>; static CreationFuncMap &GetCreationFuncMap() { static CreationFuncMap s_map; @@ -252,7 +253,8 @@ private: const bool m_accept; const size_t m_attribute_index; - const ConstString m_operation; + // The lifetime of m_operation should be static. + const llvm::StringRef m_operation; }; using FilterRules = std::vector<FilterRuleSP>; @@ -296,8 +298,8 @@ private: return FilterRuleSP(new RegexFilterRule(accept, attribute_index, op_arg)); } - static ConstString StaticGetOperation() { - static ConstString s_operation("regex"); + static llvm::StringRef StaticGetOperation() { + static constexpr llvm::StringLiteral s_operation("regex"); return s_operation; } @@ -341,8 +343,8 @@ private: new ExactMatchFilterRule(accept, attribute_index, op_arg)); } - static ConstString StaticGetOperation() { - static ConstString s_operation("match"); + static llvm::StringRef StaticGetOperation() { + static constexpr llvm::StringLiteral s_operation("match"); return s_operation; } @@ -701,7 +703,7 @@ private: // add filter spec auto rule_sp = FilterRule::CreateRule( - accept, attribute_index, ConstString(operation), + accept, attribute_index, operation, std::string(rule_text.substr(operation_end_pos + 1)), error); if (rule_sp && error.Success()) @@ -764,7 +766,7 @@ protected: result.AppendWarning(stream.GetString()); } - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { // First off, set the global sticky state of enable/disable based on this // command execution. s_is_explicitly_enabled = m_enable; @@ -788,14 +790,14 @@ protected: if (!process_sp) { // No active process, so there is nothing more to do right now. result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } // If the process is no longer alive, we can't do this now. We'll catch it // the next time the process is started up. if (!process_sp->IsAlive()) { result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; + return; } // Get the plugin for the process. @@ -836,7 +838,6 @@ protected: // one this command is setup to do. plugin.SetEnabled(m_enable); } - return result.Succeeded(); } Options *GetOptions() override { @@ -859,7 +860,7 @@ public: "plugin structured-data darwin-log status") {} protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { + void DoExecute(Args &command, CommandReturnObject &result) override { auto &stream = result.GetOutputStream(); // Figure out if we've got a process. If so, we can tell if DarwinLog is @@ -889,7 +890,7 @@ protected: if (!options_sp) { // Nothing more to do. result.SetStatus(eReturnStatusSuccessFinishResult); - return true; + return; } // Print filter rules @@ -922,7 +923,6 @@ protected: options_sp->GetFallthroughAccepts() ? "accept" : "reject"); result.SetStatus(eReturnStatusSuccessFinishResult); - return true; } }; @@ -1254,8 +1254,6 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, return; } - const ConstString logging_module_name = ConstString(logging_module_cstr); - // We need to see libtrace in the list of modules before we can enable // tracing for the target process. bool found_logging_support_module = false; @@ -1266,7 +1264,7 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, auto &file_spec = module_sp->GetFileSpec(); found_logging_support_module = - (file_spec.GetFilename() == logging_module_name); + (file_spec.GetFilename() == logging_module_cstr); if (found_logging_support_module) break; } @@ -1276,8 +1274,7 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, "StructuredDataDarwinLog::%s logging module %s " "has not yet been loaded, can't set a breakpoint " "yet (process uid %u)", - __FUNCTION__, logging_module_name.AsCString(), - process.GetUniqueID()); + __FUNCTION__, logging_module_cstr, process.GetUniqueID()); return; } @@ -1287,8 +1284,7 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, LLDB_LOGF(log, "StructuredDataDarwinLog::%s post-init hook breakpoint " "set for logging module %s (process uid %u)", - __FUNCTION__, logging_module_name.AsCString(), - process.GetUniqueID()); + __FUNCTION__, logging_module_cstr, process.GetUniqueID()); // We need to try the enable here as well, which will succeed in the event // that we're attaching to (rather than launching) the process and the diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index cd52233cc8cc..729d6af02402 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -448,15 +448,6 @@ void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, // TODO } -void SymbolFileBreakpad::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) {} - -void SymbolFileBreakpad::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {} - void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { Log *log = GetLog(LLDBLog::Symbols); Module &module = *m_objfile_sp->GetModule(); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 4a01a64202ee..214fbdd3ff3a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -118,15 +118,6 @@ public: void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) override; - void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override { return llvm::make_error<llvm::StringError>( diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h new file mode 100644 index 000000000000..c1016b2af0c6 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h @@ -0,0 +1,203 @@ +//===-- CTFTypes.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_SYMBOLFILE_CTF_CTFTYPES_H +#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_CTF_CTFTYPES_H + +#include "lldb/lldb-types.h" +#include "llvm/ADT/StringRef.h" + +namespace lldb_private { + +struct CTFType { + enum Kind : uint32_t { + eUnknown = 0, + eInteger = 1, + eFloat = 2, + ePointer = 3, + eArray = 4, + eFunction = 5, + eStruct = 6, + eUnion = 7, + eEnum = 8, + eForward = 9, + eTypedef = 10, + eVolatile = 11, + eConst = 12, + eRestrict = 13, + eSlice = 14, + }; + + Kind kind; + lldb::user_id_t uid; + llvm::StringRef name; + + CTFType(Kind kind, lldb::user_id_t uid, llvm::StringRef name) + : kind(kind), uid(uid), name(name) {} +}; + +struct CTFInteger : public CTFType { + CTFInteger(lldb::user_id_t uid, llvm::StringRef name, uint32_t bits, + uint32_t encoding) + : CTFType(eInteger, uid, name), bits(bits), encoding(encoding) {} + + static bool classof(const CTFType *T) { return T->kind == eInteger; } + + uint32_t bits; + uint32_t encoding; +}; + +struct CTFModifier : public CTFType { +protected: + CTFModifier(Kind kind, lldb::user_id_t uid, uint32_t type) + : CTFType(kind, uid, ""), type(type) {} + + static bool classof(const CTFType *T) { + return T->kind == ePointer || T->kind == eConst || T->kind == eVolatile || + T->kind == eRestrict; + } + +public: + uint32_t type; +}; + +struct CTFPointer : public CTFModifier { + CTFPointer(lldb::user_id_t uid, uint32_t type) + : CTFModifier(ePointer, uid, type) {} + + static bool classof(const CTFType *T) { return T->kind == ePointer; } +}; + +struct CTFConst : public CTFModifier { + CTFConst(lldb::user_id_t uid, uint32_t type) + : CTFModifier(eConst, uid, type) {} + + static bool classof(const CTFType *T) { return T->kind == eConst; } +}; + +struct CTFVolatile : public CTFModifier { + CTFVolatile(lldb::user_id_t uid, uint32_t type) + : CTFModifier(eVolatile, uid, type) {} + + static bool classof(const CTFType *T) { return T->kind == eVolatile; } +}; + +struct CTFRestrict : public CTFModifier { + CTFRestrict(lldb::user_id_t uid, uint32_t type) + : CTFModifier(eRestrict, uid, type) {} + static bool classof(const CTFType *T) { return T->kind == eRestrict; } +}; + +struct CTFTypedef : public CTFType { + CTFTypedef(lldb::user_id_t uid, llvm::StringRef name, uint32_t type) + : CTFType(eTypedef, uid, name), type(type) {} + + static bool classof(const CTFType *T) { return T->kind == eTypedef; } + + uint32_t type; +}; + +struct CTFArray : public CTFType { + CTFArray(lldb::user_id_t uid, llvm::StringRef name, uint32_t type, + uint32_t index, uint32_t nelems) + : CTFType(eArray, uid, name), type(type), index(index), nelems(nelems) {} + + static bool classof(const CTFType *T) { return T->kind == eArray; } + + uint32_t type; + uint32_t index; + uint32_t nelems; +}; + +struct CTFEnum : public CTFType { + struct Value { + Value(llvm::StringRef name, uint32_t value) : name(name), value(value){}; + llvm::StringRef name; + uint32_t value; + }; + + CTFEnum(lldb::user_id_t uid, llvm::StringRef name, uint32_t nelems, + uint32_t size, std::vector<Value> values) + : CTFType(eEnum, uid, name), nelems(nelems), size(size), + values(std::move(values)) { + assert(this->values.size() == nelems); + } + + static bool classof(const CTFType *T) { return T->kind == eEnum; } + + uint32_t nelems; + uint32_t size; + std::vector<Value> values; +}; + +struct CTFFunction : public CTFType { + CTFFunction(lldb::user_id_t uid, llvm::StringRef name, uint32_t nargs, + uint32_t return_type, std::vector<uint32_t> args, bool variadic) + : CTFType(eFunction, uid, name), nargs(nargs), return_type(return_type), + args(std::move(args)), variadic(variadic) {} + + static bool classof(const CTFType *T) { return T->kind == eFunction; } + + uint32_t nargs; + uint32_t return_type; + + std::vector<uint32_t> args; + bool variadic = false; +}; + +struct CTFRecord : public CTFType { +public: + struct Field { + Field(llvm::StringRef name, uint32_t type, uint64_t offset) + : name(name), type(type), offset(offset) {} + + llvm::StringRef name; + uint32_t type; + uint64_t offset; + }; + + CTFRecord(Kind kind, lldb::user_id_t uid, llvm::StringRef name, + uint32_t nfields, uint32_t size, std::vector<Field> fields) + : CTFType(kind, uid, name), nfields(nfields), size(size), + fields(std::move(fields)) {} + + static bool classof(const CTFType *T) { + return T->kind == eStruct || T->kind == eUnion; + } + + uint32_t nfields; + uint32_t size; + std::vector<Field> fields; +}; + +struct CTFStruct : public CTFRecord { + CTFStruct(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields, + uint32_t size, std::vector<Field> fields) + : CTFRecord(eStruct, uid, name, nfields, size, std::move(fields)){}; + + static bool classof(const CTFType *T) { return T->kind == eStruct; } +}; + +struct CTFUnion : public CTFRecord { + CTFUnion(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields, + uint32_t size, std::vector<Field> fields) + : CTFRecord(eUnion, uid, name, nfields, size, std::move(fields)){}; + + static bool classof(const CTFType *T) { return T->kind == eUnion; } +}; + +struct CTFForward : public CTFType { + CTFForward(lldb::user_id_t uid, llvm::StringRef name) + : CTFType(eForward, uid, name) {} + + static bool classof(const CTFType *T) { return T->kind == eForward; } +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_CTF_CTFTYPES_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 88926baa7a6e..d192944bb9d0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -10,7 +10,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamBuffer.h" #include "lldb/Host/Config.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" @@ -26,6 +25,7 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/StreamBuffer.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "llvm/Support/MemoryBuffer.h" @@ -317,31 +317,27 @@ uint32_t GetVLen(uint32_t data) { static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); } -static clang::TagTypeKind TranslateRecordKind(SymbolFileCTF::TypeKind type) { +static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) { switch (type) { - case SymbolFileCTF::TypeKind::eStruct: - return clang::TTK_Struct; - case SymbolFileCTF::TypeKind::eUnion: - return clang::TTK_Union; + case CTFType::Kind::eStruct: + return clang::TagTypeKind::Struct; + case CTFType::Kind::eUnion: + return clang::TagTypeKind::Union; default: lldbassert(false && "Invalid record kind!"); - return clang::TTK_Struct; + return clang::TagTypeKind::Struct; } } -llvm::Expected<TypeSP> SymbolFileCTF::ParseInteger(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name) { - const uint32_t vdata = m_data.GetU32(&offset); - const uint32_t bits = GetBits(vdata); - const uint32_t encoding = GetEncoding(vdata); - - lldb::BasicType basic_type = TypeSystemClang::GetBasicTypeEnumeration(name); +llvm::Expected<TypeSP> +SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) { + lldb::BasicType basic_type = + TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name); if (basic_type == eBasicTypeInvalid) return llvm::make_error<llvm::StringError>( llvm::formatv("unsupported integer type: no corresponding basic clang " "type for '{0}'", - name), + ctf_integer.name), llvm::inconvertibleErrorCode()); CompilerType compiler_type = m_ast->GetBasicType(basic_type); @@ -353,104 +349,98 @@ llvm::Expected<TypeSP> SymbolFileCTF::ParseInteger(lldb::offset_t &offset, return llvm::make_error<llvm::StringError>( llvm::formatv( "Found compiler type for '{0}' but it's not an integer type: {1}", - name, compiler_type.GetDisplayTypeName().GetStringRef()), + ctf_integer.name, + compiler_type.GetDisplayTypeName().GetStringRef()), llvm::inconvertibleErrorCode()); // Make sure the signing matches between the CTF and the compiler type. - const bool type_is_signed = (encoding & IntEncoding::eSigned); + const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned); if (compiler_type_is_signed != type_is_signed) return llvm::make_error<llvm::StringError>( llvm::formatv("Found integer compiler type for {0} but compiler type " "is {1} and {0} is {2}", - name, compiler_type_is_signed ? "signed" : "unsigned", + ctf_integer.name, + compiler_type_is_signed ? "signed" : "unsigned", type_is_signed ? "signed" : "unsigned"), llvm::inconvertibleErrorCode()); } Declaration decl; - return MakeType(uid, ConstString(name), GetBytes(bits), nullptr, - LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, - compiler_type, lldb_private::Type::ResolveState::Full); + return MakeType(ctf_integer.uid, ConstString(ctf_integer.name), + GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, decl, compiler_type, + lldb_private::Type::ResolveState::Full); } llvm::Expected<lldb::TypeSP> -SymbolFileCTF::ParseModifierType(lldb::offset_t &offset, lldb::user_id_t uid, - uint32_t kind, uint32_t type) { - TypeSP ref_type = GetTypeForUID(type); +SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) { + Type *ref_type = ResolveTypeUID(ctf_modifier.type); if (!ref_type) return llvm::make_error<llvm::StringError>( - llvm::formatv("Could not find modified type: {0}", type), + llvm::formatv("Could not find modified type: {0}", ctf_modifier.type), llvm::inconvertibleErrorCode()); CompilerType compiler_type; - switch (kind) { - case TypeKind::ePointer: + switch (ctf_modifier.kind) { + case CTFType::ePointer: compiler_type = ref_type->GetFullCompilerType().GetPointerType(); break; - case TypeKind::eConst: + case CTFType::eConst: compiler_type = ref_type->GetFullCompilerType().AddConstModifier(); break; - case TypeKind::eVolatile: + case CTFType::eVolatile: compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier(); break; - case TypeKind::eRestrict: + case CTFType::eRestrict: compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier(); break; default: return llvm::make_error<llvm::StringError>( - llvm::formatv("ParseModifierType called with unsupported kind: {0}", - kind), + llvm::formatv("ParseModifier called with unsupported kind: {0}", + ctf_modifier.kind), llvm::inconvertibleErrorCode()); } Declaration decl; - return MakeType(uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, + return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, compiler_type, lldb_private::Type::ResolveState::Full); } -llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseTypedef(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t type) { - TypeSP underlying_type = GetTypeForUID(type); +llvm::Expected<lldb::TypeSP> +SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) { + Type *underlying_type = ResolveTypeUID(ctf_typedef.type); if (!underlying_type) return llvm::make_error<llvm::StringError>( - llvm::formatv("Could not find typedef underlying type: {0}", type), + llvm::formatv("Could not find typedef underlying type: {0}", + ctf_typedef.type), llvm::inconvertibleErrorCode()); CompilerType target_ast_type = underlying_type->GetFullCompilerType(); clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl(); CompilerType ast_typedef = target_ast_type.CreateTypedef( - name.data(), m_ast->CreateDeclContext(decl_ctx), 0); + ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0); Declaration decl; - return MakeType(uid, ConstString(name), 0, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ast_typedef, - lldb_private::Type::ResolveState::Full); + return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ast_typedef, lldb_private::Type::ResolveState::Full); } -llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseArray(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name) { - ctf_array_t ctf_array; - ctf_array.contents = m_data.GetU32(&offset); - ctf_array.index = m_data.GetU32(&offset); - ctf_array.nelems = m_data.GetU32(&offset); - - TypeSP element_type = GetTypeForUID(ctf_array.contents); +llvm::Expected<lldb::TypeSP> +SymbolFileCTF::CreateArray(const CTFArray &ctf_array) { + Type *element_type = ResolveTypeUID(ctf_array.type); if (!element_type) return llvm::make_error<llvm::StringError>( - llvm::formatv("Could not find array element type: {0}", - ctf_array.contents), + llvm::formatv("Could not find array element type: {0}", ctf_array.type), llvm::inconvertibleErrorCode()); std::optional<uint64_t> element_size = element_type->GetByteSize(nullptr); if (!element_size) return llvm::make_error<llvm::StringError>( llvm::formatv("could not get element size of type: {0}", - ctf_array.contents), + ctf_array.type), llvm::inconvertibleErrorCode()); uint64_t size = ctf_array.nelems * *element_size; @@ -460,149 +450,256 @@ llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseArray(lldb::offset_t &offset, /*is_gnu_vector*/ false); Declaration decl; - return MakeType(uid, ConstString(), size, nullptr, LLDB_INVALID_UID, + return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, compiler_type, lldb_private::Type::ResolveState::Full); } -llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseEnum(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t elements, - uint32_t size) { +llvm::Expected<lldb::TypeSP> +SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) { Declaration decl; CompilerType enum_type = m_ast->CreateEnumerationType( - name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl, - m_ast->GetBasicType(eBasicTypeInt), + ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), + decl, m_ast->GetBasicType(eBasicTypeInt), /*is_scoped=*/false); - for (uint32_t i = 0; i < elements; ++i) { - ctf_enum_t ctf_enum; - ctf_enum.name = m_data.GetU32(&offset); - ctf_enum.value = m_data.GetU32(&offset); - - llvm::StringRef value_name = ReadString(ctf_enum.name); - const uint32_t value = ctf_enum.value; - + for (const CTFEnum::Value &value : ctf_enum.values) { Declaration value_decl; - m_ast->AddEnumerationValueToEnumerationType(enum_type, value_decl, - value_name.data(), value, size); + m_ast->AddEnumerationValueToEnumerationType( + enum_type, value_decl, value.name.data(), value.value, ctf_enum.size); } + TypeSystemClang::CompleteTagDeclarationDefinition(enum_type); - return MakeType(uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, + return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, enum_type, lldb_private::Type::ResolveState::Full); } llvm::Expected<lldb::TypeSP> -SymbolFileCTF::ParseFunction(lldb::offset_t &offset, lldb::user_id_t uid, - llvm::StringRef name, uint32_t num_args, - uint32_t type) { +SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) { std::vector<CompilerType> arg_types; - arg_types.reserve(num_args); - - bool is_variadic = false; - for (uint32_t i = 0; i < num_args; ++i) { - const uint32_t arg_uid = m_data.GetU32(&offset); - - // If the last argument is 0, this is a variadic function. - if (arg_uid == 0) { - is_variadic = true; - break; - } - - if (TypeSP arg_type = GetTypeForUID(arg_uid)) + for (uint32_t arg : ctf_function.args) { + if (Type *arg_type = ResolveTypeUID(arg)) arg_types.push_back(arg_type->GetFullCompilerType()); } - // If the number of arguments is odd, a single uint32_t of padding is inserted - // to maintain alignment. - if (num_args % 2 == 1) - m_data.GetU32(&offset); - - TypeSP ret_type = GetTypeForUID(type); + Type *ret_type = ResolveTypeUID(ctf_function.return_type); if (!ret_type) return llvm::make_error<llvm::StringError>( - llvm::formatv("Could not find function return type: {0}", type), + llvm::formatv("Could not find function return type: {0}", + ctf_function.return_type), llvm::inconvertibleErrorCode()); CompilerType func_type = m_ast->CreateFunctionType( ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(), - is_variadic, 0, clang::CallingConv::CC_C); + ctf_function.variadic, 0, clang::CallingConv::CC_C); Declaration decl; - return MakeType(uid, ConstString(name), 0, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, func_type, + return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, lldb_private::Type::ResolveState::Full); } llvm::Expected<lldb::TypeSP> -SymbolFileCTF::ParseRecord(lldb::offset_t &offset, lldb::user_id_t uid, - llvm::StringRef name, uint32_t kind, uint32_t fields, - uint32_t size) { - const clang::TagTypeKind tag_kind = - TranslateRecordKind(static_cast<TypeKind>(kind)); - - CompilerType union_type = - m_ast->CreateRecordType(nullptr, OptionalClangModuleID(), eAccessPublic, - name.data(), tag_kind, eLanguageTypeC); - - m_ast->StartTagDeclarationDefinition(union_type); - for (uint32_t i = 0; i < fields; ++i) { - ctf_member_t ctf_member; - ctf_member.name = m_data.GetU32(&offset); - ctf_member.type = m_data.GetU32(&offset); - ctf_member.offset = m_data.GetU16(&offset); - ctf_member.padding = m_data.GetU16(&offset); - - llvm::StringRef member_name = ReadString(ctf_member.name); - const uint32_t member_type_uid = ctf_member.type; - - if (TypeSP member_type = GetTypeForUID(member_type_uid)) { - const uint32_t member_size = - member_type->GetByteSize(nullptr).value_or(0); - TypeSystemClang::AddFieldToRecordType(union_type, member_name, - member_type->GetFullCompilerType(), - eAccessPublic, member_size); +SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) { + const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind); + CompilerType record_type = m_ast->CreateRecordType( + nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(), + llvm::to_underlying(tag_kind), eLanguageTypeC); + m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record; + Declaration decl; + return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size, + nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, + decl, record_type, lldb_private::Type::ResolveState::Forward); +} + +bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) { + // Check if we have a CTF type for the given incomplete compiler type. + auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType()); + if (it == m_compiler_types.end()) + return false; + + const CTFType *ctf_type = it->second; + assert(ctf_type && "m_compiler_types should only contain valid CTF types"); + + // We only support resolving record types. + assert(llvm::isa<CTFRecord>(ctf_type)); + + // Cast to the appropriate CTF type. + const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type); + + // If any of the fields are incomplete, we cannot complete the type. + for (const CTFRecord::Field &field : ctf_record->fields) { + if (!ResolveTypeUID(field.type)) { + LLDB_LOG(GetLog(LLDBLog::Symbols), + "Cannot complete type {0} because field {1} is incomplete", + ctf_type->uid, field.type); + return false; } } - m_ast->CompleteTagDeclarationDefinition(union_type); + // Complete the record type. + m_ast->StartTagDeclarationDefinition(compiler_type); + for (const CTFRecord::Field &field : ctf_record->fields) { + Type *field_type = ResolveTypeUID(field.type); + assert(field_type && "field must be complete"); + const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0); + TypeSystemClang::AddFieldToRecordType(compiler_type, field.name, + field_type->GetFullCompilerType(), + eAccessPublic, field_size); + } + m_ast->CompleteTagDeclarationDefinition(compiler_type); + + // Now that the compiler type is complete, we don't need to remember it + // anymore and can remove the CTF record type. + m_compiler_types.erase(compiler_type.GetOpaqueQualType()); + m_ctf_types.erase(ctf_type->uid); + + return true; +} + +llvm::Expected<lldb::TypeSP> +SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) { + CompilerType forward_compiler_type = m_ast->CreateRecordType( + nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name, + llvm::to_underlying(clang::TagTypeKind::Struct), eLanguageTypeC); Declaration decl; - return MakeType(uid, ConstString(name), size, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, union_type, - lldb_private::Type::ResolveState::Full); + return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, + forward_compiler_type, Type::ResolveState::Forward); +} + +llvm::Expected<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) { + if (!ctf_type) + return llvm::make_error<llvm::StringError>( + "cannot create type for unparsed type", llvm::inconvertibleErrorCode()); + + switch (ctf_type->kind) { + case CTFType::Kind::eInteger: + return CreateInteger(*static_cast<CTFInteger *>(ctf_type)); + case CTFType::Kind::eConst: + case CTFType::Kind::ePointer: + case CTFType::Kind::eRestrict: + case CTFType::Kind::eVolatile: + return CreateModifier(*static_cast<CTFModifier *>(ctf_type)); + case CTFType::Kind::eTypedef: + return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type)); + case CTFType::Kind::eArray: + return CreateArray(*static_cast<CTFArray *>(ctf_type)); + case CTFType::Kind::eEnum: + return CreateEnum(*static_cast<CTFEnum *>(ctf_type)); + case CTFType::Kind::eFunction: + return CreateFunction(*static_cast<CTFFunction *>(ctf_type)); + case CTFType::Kind::eStruct: + case CTFType::Kind::eUnion: + return CreateRecord(*static_cast<CTFRecord *>(ctf_type)); + case CTFType::Kind::eForward: + return CreateForward(*static_cast<CTFForward *>(ctf_type)); + case CTFType::Kind::eUnknown: + case CTFType::Kind::eFloat: + case CTFType::Kind::eSlice: + return llvm::make_error<llvm::StringError>( + llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})", + ctf_type->uid, ctf_type->name, ctf_type->kind), + llvm::inconvertibleErrorCode()); + } } -llvm::Expected<TypeSP> SymbolFileCTF::ParseType( - lldb::offset_t &offset, lldb::user_id_t uid, llvm::StringRef name, - uint32_t kind, uint32_t variable_length, uint32_t type, uint32_t size) { +llvm::Expected<std::unique_ptr<CTFType>> +SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) { + ctf_stype_t ctf_stype; + ctf_stype.name = m_data.GetU32(&offset); + ctf_stype.info = m_data.GetU32(&offset); + ctf_stype.size = m_data.GetU32(&offset); + + llvm::StringRef name = ReadString(ctf_stype.name); + const uint32_t kind = GetKind(ctf_stype.info); + const uint32_t variable_length = GetVLen(ctf_stype.info); + const uint32_t type = ctf_stype.GetType(); + const uint32_t size = ctf_stype.GetSize(); + switch (kind) { - case TypeKind::eInteger: - return ParseInteger(offset, uid, name); + case TypeKind::eInteger: { + const uint32_t vdata = m_data.GetU32(&offset); + const uint32_t bits = GetBits(vdata); + const uint32_t encoding = GetEncoding(vdata); + return std::make_unique<CTFInteger>(uid, name, bits, encoding); + } case TypeKind::eConst: + return std::make_unique<CTFConst>(uid, type); case TypeKind::ePointer: + return std::make_unique<CTFPointer>(uid, type); case TypeKind::eRestrict: + return std::make_unique<CTFRestrict>(uid, type); case TypeKind::eVolatile: - return ParseModifierType(offset, uid, kind, type); + return std::make_unique<CTFVolatile>(uid, type); case TypeKind::eTypedef: - return ParseTypedef(offset, uid, name, type); - case TypeKind::eArray: - return ParseArray(offset, uid, name); - case TypeKind::eEnum: - return ParseEnum(offset, uid, name, variable_length, size); - case TypeKind::eFunction: - return ParseFunction(offset, uid, name, variable_length, size); + return std::make_unique<CTFTypedef>(uid, name, type); + case TypeKind::eArray: { + const uint32_t type = m_data.GetU32(&offset); + const uint32_t index = m_data.GetU32(&offset); + const uint32_t nelems = m_data.GetU32(&offset); + return std::make_unique<CTFArray>(uid, name, type, index, nelems); + } + case TypeKind::eEnum: { + std::vector<CTFEnum::Value> values; + for (uint32_t i = 0; i < variable_length; ++i) { + const uint32_t value_name = m_data.GetU32(&offset); + const uint32_t value = m_data.GetU32(&offset); + values.emplace_back(ReadString(value_name), value); + } + return std::make_unique<CTFEnum>(uid, name, variable_length, size, values); + } + case TypeKind::eFunction: { + std::vector<uint32_t> args; + bool variadic = false; + for (uint32_t i = 0; i < variable_length; ++i) { + const uint32_t arg_uid = m_data.GetU32(&offset); + // If the last argument is 0, this is a variadic function. + if (arg_uid == 0) { + variadic = true; + break; + } + args.push_back(arg_uid); + } + // If the number of arguments is odd, a single uint32_t of padding is + // inserted to maintain alignment. + if (variable_length % 2 == 1) + m_data.GetU32(&offset); + return std::make_unique<CTFFunction>(uid, name, variable_length, type, args, + variadic); + } case TypeKind::eStruct: - case TypeKind::eUnion: - return ParseRecord(offset, uid, name, kind, variable_length, size); - case TypeKind::eFloat: + case TypeKind::eUnion: { + std::vector<CTFRecord::Field> fields; + for (uint32_t i = 0; i < variable_length; ++i) { + const uint32_t field_name = m_data.GetU32(&offset); + const uint32_t type = m_data.GetU32(&offset); + uint64_t field_offset = 0; + if (size < g_ctf_field_threshold) { + field_offset = m_data.GetU16(&offset); + m_data.GetU16(&offset); // Padding + } else { + const uint32_t offset_hi = m_data.GetU32(&offset); + const uint32_t offset_lo = m_data.GetU32(&offset); + field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo); + } + fields.emplace_back(ReadString(field_name), type, field_offset); + } + return std::make_unique<CTFRecord>(static_cast<CTFType::Kind>(kind), uid, + name, variable_length, size, fields); + } case TypeKind::eForward: - case TypeKind::eSlice: + return std::make_unique<CTFForward>(uid, name); case TypeKind::eUnknown: + return std::make_unique<CTFType>(static_cast<CTFType::Kind>(kind), uid, + name); + case TypeKind::eFloat: + case TypeKind::eSlice: offset += (variable_length * sizeof(uint32_t)); break; } + return llvm::make_error<llvm::StringError>( llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})", name, kind, variable_length), @@ -627,46 +724,24 @@ size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) { lldb::user_id_t type_uid = 1; while (type_offset < type_offset_end) { - ctf_stype_t ctf_stype; - ctf_stype.name = m_data.GetU32(&type_offset); - ctf_stype.info = m_data.GetU32(&type_offset); - ctf_stype.size = m_data.GetU32(&type_offset); - - llvm::StringRef name = ReadString(ctf_stype.name); - const uint32_t kind = GetKind(ctf_stype.info); - const uint32_t variable_length = GetVLen(ctf_stype.info); - const uint32_t type = ctf_stype.GetType(); - const uint32_t size = ctf_stype.GetSize(); - - TypeSP type_sp; - llvm::Expected<TypeSP> type_or_error = ParseType( - type_offset, type_uid, name, kind, variable_length, type, size); - if (!type_or_error) { + llvm::Expected<std::unique_ptr<CTFType>> type_or_error = + ParseType(type_offset, type_uid); + if (type_or_error) { + m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error); + } else { LLDB_LOG_ERROR(log, type_or_error.takeError(), "Failed to parse type {1} at offset {2}: {0}", type_uid, type_offset); - } else { - type_sp = *type_or_error; - if (log) { - StreamString ss; - type_sp->Dump(&ss, true); - LLDB_LOGV(log, "Adding type {0}: {1}", type_uid, - llvm::StringRef(ss.GetString()).rtrim()); - } } - - AddTypeForUID(type_uid++, type_sp); + type_uid++; } - if (log) { - size_t skipped_types = 0; - for (auto &type : m_types) { - if (!type) - skipped_types++; - } - LLDB_LOG(log, "Parsed {0} CTF types ({1} skipped)", m_types.size(), - skipped_types); - } + LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size()); + + for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) + ResolveTypeUID(uid); + + LLDB_LOG(log, "Created {0} CTF types", m_types.size()); return m_types.size(); } @@ -725,12 +800,12 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { break; } - TypeSP arg_type = GetTypeForUID(arg_uid); + Type *arg_type = ResolveTypeUID(arg_uid); arg_types.push_back(arg_type->GetFullCompilerType()); } if (symbol) { - TypeSP ret_type = GetTypeForUID(ret_uid); + Type *ret_type = ResolveTypeUID(ret_uid); AddressRange func_range = AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(), GetObjectFile()->GetModule()->GetSectionList()); @@ -744,7 +819,7 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { MakeType(function_type_uid, symbol->GetName(), 0, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, lldb_private::Type::ResolveState::Full); - AddTypeForUID(function_type_uid, type_sp); + m_types[function_type_uid] = type_sp; // Create function. lldb::user_id_t func_uid = m_functions.size(); @@ -814,7 +889,6 @@ size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) { if (Symbol *symbol = symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx)) { - Variable::RangeList ranges; ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize()); @@ -906,42 +980,58 @@ void SymbolFileCTF::AddSymbols(Symtab &symtab) { // We rely on the existing symbol table to map symbols to type. } -void SymbolFileCTF::AddTypeForUID(lldb::user_id_t type_uid, lldb::TypeSP type) { - assert(type_uid == m_types.size() + 1); - m_types.emplace_back(type); -} +lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { + auto type_it = m_types.find(type_uid); + if (type_it != m_types.end()) + return type_it->second.get(); -TypeSP SymbolFileCTF::GetTypeForUID(lldb::user_id_t type_uid) { - if (type_uid > m_types.size()) - return {}; + auto ctf_type_it = m_ctf_types.find(type_uid); + if (ctf_type_it == m_ctf_types.end()) + return nullptr; + + CTFType *ctf_type = ctf_type_it->second.get(); + assert(ctf_type && "m_ctf_types should only contain valid CTF types"); + + Log *log = GetLog(LLDBLog::Symbols); - if (type_uid < 1) + llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type); + if (!type_or_error) { + LLDB_LOG_ERROR(log, type_or_error.takeError(), + "Failed to create type for {1}: {0}", ctf_type->uid); return {}; + } - return m_types[type_uid - 1]; -} + TypeSP type_sp = *type_or_error; -lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { - return GetTypeForUID(type_uid).get(); -} + if (log) { + StreamString ss; + type_sp->Dump(&ss, true); + LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(), + llvm::StringRef(ss.GetString()).rtrim()); + } -void SymbolFileCTF::FindTypes( - lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) { + m_types[type_uid] = type_sp; - searched_symbol_files.clear(); - searched_symbol_files.insert(this); + // Except for record types which we'll need to complete later, we don't need + // the CTF type anymore. + if (!isa<CTFRecord>(ctf_type)) + m_ctf_types.erase(type_uid); - size_t matches = 0; - for (TypeSP type_sp : m_types) { - if (matches == max_matches) - break; + return type_sp.get(); +} + +void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) { + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) + return; + + ConstString name = match.GetTypeBasename(); + for (TypeSP type_sp : GetTypeList().Types()) { if (type_sp && type_sp->GetName() == name) { - types.Insert(type_sp); - matches++; + results.InsertUnique(type_sp); + if (results.Done(match)) + return; } } } @@ -952,7 +1042,7 @@ void SymbolFileCTF::FindTypesByRegex( ParseTypes(*m_comp_unit_sp); size_t matches = 0; - for (TypeSP type_sp : m_types) { + for (TypeSP type_sp : GetTypeList().Types()) { if (matches == max_matches) break; if (type_sp && regex.Execute(type_sp->GetName())) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index bdd6dcdc3fda..f111937dbd6e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -13,6 +13,7 @@ #include <optional> #include <vector> +#include "CTFTypes.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolFile.h" @@ -85,9 +86,6 @@ public: lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::TypeSP GetTypeForUID(lldb::user_id_t type_uid); - void AddTypeForUID(lldb::user_id_t type_uid, lldb::TypeSP type); - Type *ResolveTypeUID(lldb::user_id_t type_uid) override; std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, @@ -95,7 +93,7 @@ public: return std::nullopt; } - bool CompleteType(CompilerType &compiler_type) override { return false; } + bool CompleteType(CompilerType &compiler_type) override; uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, lldb::SymbolContextItem resolve_scope, @@ -107,12 +105,8 @@ public: lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override {} - void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); @@ -216,60 +210,18 @@ private: uint32_t GetSize() const { return size; } }; - struct ctf_member_t { - uint32_t name; - uint32_t type; - uint16_t offset; - uint16_t padding; - }; - - struct ctf_array_t { - uint32_t contents; - uint32_t index; - uint32_t nelems; - }; - - struct ctf_enum_t { - uint32_t name; - int32_t value; - }; - - llvm::Expected<lldb::TypeSP> ParseType(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, uint32_t kind, - uint32_t variable_length, - uint32_t type, uint32_t size); + llvm::Expected<std::unique_ptr<CTFType>> ParseType(lldb::offset_t &offset, + lldb::user_id_t uid); - llvm::Expected<lldb::TypeSP> ParseInteger(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name); - - llvm::Expected<lldb::TypeSP> ParseModifierType(lldb::offset_t &offset, - lldb::user_id_t uid, - uint32_t kind, uint32_t type); - - llvm::Expected<lldb::TypeSP> ParseTypedef(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t type); - - llvm::Expected<lldb::TypeSP> - ParseArray(lldb::offset_t &offset, lldb::user_id_t uid, llvm::StringRef name); - - llvm::Expected<lldb::TypeSP> ParseEnum(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t elements, uint32_t size); - - llvm::Expected<lldb::TypeSP> ParseFunction(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t num_args, uint32_t type); - - llvm::Expected<lldb::TypeSP> ParseRecord(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, uint32_t kind, - uint32_t fields, uint32_t size); + llvm::Expected<lldb::TypeSP> CreateType(CTFType *ctf_type); + llvm::Expected<lldb::TypeSP> CreateInteger(const CTFInteger &ctf_integer); + llvm::Expected<lldb::TypeSP> CreateModifier(const CTFModifier &ctf_modifier); + llvm::Expected<lldb::TypeSP> CreateTypedef(const CTFTypedef &ctf_typedef); + llvm::Expected<lldb::TypeSP> CreateArray(const CTFArray &ctf_array); + llvm::Expected<lldb::TypeSP> CreateEnum(const CTFEnum &ctf_enum); + llvm::Expected<lldb::TypeSP> CreateFunction(const CTFFunction &ctf_function); + llvm::Expected<lldb::TypeSP> CreateRecord(const CTFRecord &ctf_record); + llvm::Expected<lldb::TypeSP> CreateForward(const CTFForward &ctf_forward); llvm::StringRef ReadString(lldb::offset_t offset) const; @@ -288,12 +240,24 @@ private: lldb::CompUnitSP m_comp_unit_sp; std::optional<ctf_header_t> m_header; - std::vector<lldb::TypeSP> m_types; + + /// Parsed CTF types. + llvm::DenseMap<lldb::user_id_t, std::unique_ptr<CTFType>> m_ctf_types; + + /// Parsed LLDB types. + llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types; + + /// To complete types, we need a way to map (imcomplete) compiler types back + /// to parsed CTF types. + llvm::DenseMap<lldb::opaque_compiler_type_t, const CTFType *> + m_compiler_types; + std::vector<lldb::FunctionSP> m_functions; std::vector<lldb::VariableSP> m_variables; static constexpr uint16_t g_ctf_magic = 0xcff1; static constexpr uint8_t g_ctf_version = 4; + static constexpr uint16_t g_ctf_field_threshold = 0x2000; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 34fb98b5a9b6..33537df4f507 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -18,6 +18,7 @@ using namespace lldb_private; using namespace lldb; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( Module &module, DWARFDataExtractor apple_names, @@ -50,13 +51,20 @@ std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( extract_and_check(apple_namespaces_table_up); extract_and_check(apple_types_table_up); extract_and_check(apple_objc_table_up); + assert(apple_names.GetByteSize() == 0 || apple_names.GetSharedDataBuffer()); + assert(apple_namespaces.GetByteSize() == 0 || + apple_namespaces.GetSharedDataBuffer()); + assert(apple_types.GetByteSize() == 0 || apple_types.GetSharedDataBuffer()); + assert(apple_objc.GetByteSize() == 0 || apple_objc.GetSharedDataBuffer()); if (apple_names_table_up || apple_namespaces_table_up || apple_types_table_up || apple_objc_table_up) return std::make_unique<AppleDWARFIndex>( module, std::move(apple_names_table_up), std::move(apple_namespaces_table_up), std::move(apple_types_table_up), - std::move(apple_objc_table_up)); + std::move(apple_objc_table_up), apple_names.GetSharedDataBuffer(), + apple_namespaces.GetSharedDataBuffer(), + apple_types.GetSharedDataBuffer(), apple_objc.GetSharedDataBuffer()); return nullptr; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h index 6b948e079895..73de75b583bd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -12,7 +12,8 @@ #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" -namespace lldb_private { +namespace lldb_private::plugin { +namespace dwarf { class AppleDWARFIndex : public DWARFIndex { public: static std::unique_ptr<AppleDWARFIndex> @@ -24,11 +25,19 @@ public: std::unique_ptr<llvm::AppleAcceleratorTable> apple_names, std::unique_ptr<llvm::AppleAcceleratorTable> apple_namespaces, std::unique_ptr<llvm::AppleAcceleratorTable> apple_types, - std::unique_ptr<llvm::AppleAcceleratorTable> apple_objc) + std::unique_ptr<llvm::AppleAcceleratorTable> apple_objc, + lldb::DataBufferSP apple_names_storage, + lldb::DataBufferSP apple_namespaces_storage, + lldb::DataBufferSP apple_types_storage, + lldb::DataBufferSP apple_objc_storage) : DWARFIndex(module), m_apple_names_up(std::move(apple_names)), m_apple_namespaces_up(std::move(apple_namespaces)), m_apple_types_up(std::move(apple_types)), - m_apple_objc_up(std::move(apple_objc)) {} + m_apple_objc_up(std::move(apple_objc)), + m_apple_names_storage(apple_names_storage), + m_apple_namespaces_storage(apple_namespaces_storage), + m_apple_types_storage(apple_types_storage), + m_apple_objc_storage(apple_objc_storage) {} void Preload() override {} @@ -66,6 +75,14 @@ private: std::unique_ptr<llvm::AppleAcceleratorTable> m_apple_namespaces_up; std::unique_ptr<llvm::AppleAcceleratorTable> m_apple_types_up; std::unique_ptr<llvm::AppleAcceleratorTable> m_apple_objc_up; + /// The following storage variables hold the data that the apple accelerator + /// tables tables above point to. + /// { + lldb::DataBufferSP m_apple_names_storage; + lldb::DataBufferSP m_apple_namespaces_storage; + lldb::DataBufferSP m_apple_types_storage; + lldb::DataBufferSP m_apple_objc_storage; + /// } /// Search for entries whose name is `name` in `table`, calling `callback` for /// each match. If `search_for_tag` is provided, ignore entries whose tag is @@ -77,6 +94,7 @@ private: std::optional<dw_tag_t> search_for_tag = std::nullopt, std::optional<uint32_t> search_for_qualhash = std::nullopt); }; -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_APPLEDWARFINDEX_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp index 88a5e6027557..163e9f4c081c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -14,6 +14,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; void llvm::format_provider<DIERef>::format(const DIERef &ref, raw_ostream &OS, StringRef Style) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h index b5a5cfe263f7..ad443aacb46e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -14,6 +14,8 @@ #include <cassert> #include <optional> +namespace lldb_private::plugin { +namespace dwarf { /// Identifies a DWARF debug info entry within a given Module. It contains three /// "coordinates": /// - file_index: identifies the separate stand alone debug info file @@ -93,7 +95,7 @@ public: /// \return /// Returns a valid DIERef if decoding succeeded, std::nullopt if there was /// unsufficient or invalid values that were decoded. - static std::optional<DIERef> Decode(const lldb_private::DataExtractor &data, + static std::optional<DIERef> Decode(const DataExtractor &data, lldb::offset_t *offset_ptr); /// Encode this object into a data encoder object. @@ -103,7 +105,7 @@ public: /// \param encoder /// A data encoder object that serialized bytes will be encoded into. /// - void Encode(lldb_private::DataEncoder &encoder) const; + void Encode(DataEncoder &encoder) const; static constexpr uint64_t k_die_offset_bit_size = DW_DIE_OFFSET_MAX_BITSIZE; static constexpr uint64_t k_file_index_bit_size = @@ -131,10 +133,13 @@ private: static_assert(sizeof(DIERef) == 8); typedef std::vector<DIERef> DIEArray; +} // namespace dwarf +} // namespace lldb_private::plugin namespace llvm { -template<> struct format_provider<DIERef> { - static void format(const DIERef &ref, raw_ostream &OS, StringRef Style); +template <> struct format_provider<lldb_private::plugin::dwarf::DIERef> { + static void format(const lldb_private::plugin::dwarf::DIERef &ref, + raw_ostream &OS, StringRef Style); }; } // namespace llvm diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp index a68b7cd110eb..409e9bb37ab2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp @@ -9,6 +9,7 @@ #include "DWARFASTParser.h" #include "DWARFAttribute.h" #include "DWARFDIE.h" +#include "SymbolFileDWARF.h" #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/SymbolFile.h" @@ -18,6 +19,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; std::optional<SymbolFile::ArrayInfo> DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, @@ -99,6 +101,30 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, return array_info; } +Type *DWARFASTParser::GetTypeForDIE(const DWARFDIE &die) { + if (!die) + return nullptr; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (!dwarf) + return nullptr; + + DWARFAttributes attributes = die.GetAttributes(); + if (attributes.Size() == 0) + return nullptr; + + DWARFFormValue type_die_form; + for (size_t i = 0; i < attributes.Size(); ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + + if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) + return dwarf->ResolveTypeUID(form_value.Reference(), true); + } + + return nullptr; +} + AccessType DWARFASTParser::GetAccessTypeFromDWARF(uint32_t dwarf_accessibility) { switch (dwarf_accessibility) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 18825ae060b1..66db396279e0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -17,53 +17,63 @@ #include "lldb/lldb-enumerations.h" #include <optional> -class DWARFDIE; namespace lldb_private { class CompileUnit; class ExecutionContext; } + +namespace lldb_private::plugin { +namespace dwarf { +class DWARFDIE; class SymbolFileDWARF; class DWARFASTParser { public: + enum class Kind { DWARFASTParserClang }; + DWARFASTParser(Kind kind) : m_kind(kind) {} + virtual ~DWARFASTParser() = default; - virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, + virtual lldb::TypeSP ParseTypeFromDWARF(const SymbolContext &sc, const DWARFDIE &die, bool *type_is_new_ptr) = 0; - virtual lldb_private::ConstString - ConstructDemangledNameFromDWARF(const DWARFDIE &die) = 0; + virtual ConstString ConstructDemangledNameFromDWARF(const DWARFDIE &die) = 0; - virtual lldb_private::Function * - ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, - const DWARFDIE &die, - const lldb_private::AddressRange &range) = 0; + virtual Function *ParseFunctionFromDWARF(CompileUnit &comp_unit, + const DWARFDIE &die, + const AddressRange &range) = 0; - virtual bool - CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, - lldb_private::CompilerType &compiler_type) = 0; + virtual bool CompleteTypeFromDWARF(const DWARFDIE &die, Type *type, + CompilerType &compiler_type) = 0; - virtual lldb_private::CompilerDecl - GetDeclForUIDFromDWARF(const DWARFDIE &die) = 0; + virtual CompilerDecl GetDeclForUIDFromDWARF(const DWARFDIE &die) = 0; - virtual lldb_private::CompilerDeclContext + virtual CompilerDeclContext GetDeclContextForUIDFromDWARF(const DWARFDIE &die) = 0; - virtual lldb_private::CompilerDeclContext + virtual CompilerDeclContext GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) = 0; virtual void EnsureAllDIEsInDeclContextHaveBeenParsed( - lldb_private::CompilerDeclContext decl_context) = 0; + CompilerDeclContext decl_context) = 0; - virtual lldb_private::ConstString - GetDIEClassTemplateParams(const DWARFDIE &die) = 0; + virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0; - static std::optional<lldb_private::SymbolFile::ArrayInfo> + static std::optional<SymbolFile::ArrayInfo> ParseChildArrayInfo(const DWARFDIE &parent_die, - const lldb_private::ExecutionContext *exe_ctx = nullptr); + const ExecutionContext *exe_ctx = nullptr); + + lldb_private::Type *GetTypeForDIE(const DWARFDIE &die); static lldb::AccessType GetAccessTypeFromDWARF(uint32_t dwarf_accessibility); + + Kind GetKind() const { return m_kind; } + +private: + const Kind m_kind; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index a3ade51e1fe5..334876620249 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -31,6 +31,7 @@ #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/Language.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" @@ -60,8 +61,11 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; + DWARFASTParserClang::DWARFASTParserClang(TypeSystemClang &ast) - : m_ast(ast), m_die_to_decl_ctx(), m_decl_ctx_to_die() {} + : DWARFASTParser(Kind::DWARFASTParserClang), m_ast(ast), + m_die_to_decl_ctx(), m_decl_ctx_to_die() {} DWARFASTParserClang::~DWARFASTParserClang() = default; @@ -130,6 +134,14 @@ static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) { return lldb::ModuleSP(); } +// Returns true if the given artificial field name should be ignored when +// parsing the DWARF. +static bool ShouldIgnoreArtificialField(llvm::StringRef FieldName) { + return FieldName.starts_with("_vptr$") + // gdb emit vtable pointer as "_vptr.classname" + || FieldName.starts_with("_vptr."); +} + TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, const DWARFDIE &die, Log *log) { @@ -140,17 +152,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, // If this type comes from a Clang module, recursively look in the // DWARF section of the .pcm file in the module cache. Clang // generates DWO skeleton units as breadcrumbs to find them. - llvm::SmallVector<CompilerContext, 4> decl_context; - die.GetDeclContext(decl_context); - TypeMap pcm_types; + std::vector<lldb_private::CompilerContext> die_context = die.GetDeclContext(); + TypeQuery query(die_context, TypeQueryOptions::e_module_search | + TypeQueryOptions::e_find_one); + TypeResults results; // The type in the Clang module must have the same language as the current CU. - LanguageSet languages; - languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, - searched_symbol_files, pcm_types); - if (pcm_types.Empty()) { + query.AddLanguage(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())); + clang_module_sp->FindTypes(query, results); + TypeSP pcm_type_sp = results.GetTypeMap().FirstType(); + if (!pcm_type_sp) { // Since this type is defined in one of the Clang modules imported // by this symbol file, search all of them. Instead of calling // sym_file->FindTypes(), which would return this again, go straight @@ -159,24 +170,20 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, // Well-formed clang modules never form cycles; guard against corrupted // ones by inserting the current file. - searched_symbol_files.insert(&sym_file); + results.AlreadySearched(&sym_file); sym_file.ForEachExternalModule( - *sc.comp_unit, searched_symbol_files, [&](Module &module) { - module.GetSymbolFile()->FindTypes(decl_context, languages, - searched_symbol_files, pcm_types); - return pcm_types.GetSize(); + *sc.comp_unit, results.GetSearchedSymbolFiles(), [&](Module &module) { + module.FindTypes(query, results); + pcm_type_sp = results.GetTypeMap().FirstType(); + return !pcm_type_sp; }); } - if (!pcm_types.GetSize()) + if (!pcm_type_sp) return TypeSP(); // We found a real definition for this type in the Clang module, so lets use // it and cache the fact that we found a complete type for this die. - TypeSP pcm_type_sp = pcm_types.GetTypeAtIndex(0); - if (!pcm_type_sp) - return TypeSP(); - lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType(); lldb_private::CompilerType type = GetClangASTImporter().CopyType(m_ast, pcm_type); @@ -296,6 +303,10 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { byte_size = form_value.Unsigned(); break; + case DW_AT_alignment: + alignment = form_value.Unsigned(); + break; + case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break; @@ -519,6 +530,33 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, return UpdateSymbolContextScopeForType(sc, die, type_sp); } +static std::optional<uint32_t> +ExtractDataMemberLocation(DWARFDIE const &die, DWARFFormValue const &form_value, + ModuleSP module_sp) { + // With DWARF 3 and later, if the value is an integer constant, + // this form value is the offset in bytes from the beginning of + // the containing entity. + if (!form_value.BlockData()) + return form_value.Unsigned(); + + Value initialValue(0); + Value memberOffset(0); + const DWARFDataExtractor &debug_info_data = die.GetData(); + uint32_t block_length = form_value.Unsigned(); + uint32_t block_offset = + form_value.BlockData() - debug_info_data.GetDataStart(); + if (!DWARFExpression::Evaluate( + nullptr, // ExecutionContext * + nullptr, // RegisterContext * + module_sp, DataExtractor(debug_info_data, block_offset, block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, memberOffset, + nullptr)) { + return {}; + } + + return memberOffset.ResolveValue(nullptr).UInt(); +} + lldb::TypeSP DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, const DWARFDIE &die, @@ -805,9 +843,9 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, CompilerType enumerator_clang_type; CompilerType clang_type; - clang_type = - CompilerType(m_ast.weak_from_this(), - dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + clang_type = CompilerType( + m_ast.weak_from_this(), + dwarf->GetForwardDeclDIEToCompilerType().lookup(die.GetDIE())); if (!clang_type) { if (attrs.type.IsValid()) { Type *enumerator_type = @@ -890,8 +928,9 @@ ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) { return clang::CC_C; } -TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs) { +TypeSP +DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs) { Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); SymbolFileDWARF *dwarf = die.GetDWARF(); @@ -1000,16 +1039,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, } if (class_opaque_type) { - // If accessibility isn't set to anything valid, assume public - // for now... - if (attrs.accessibility == eAccessNone) - attrs.accessibility = eAccessPublic; - clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType( class_opaque_type, attrs.name.GetCString(), clang_type, - attrs.accessibility, attrs.is_artificial, is_variadic, - attrs.is_objc_direct_call); + attrs.is_artificial, is_variadic, attrs.is_objc_direct_call); type_handled = objc_method_decl != nullptr; if (type_handled) { LinkDeclContextToDIE(objc_method_decl, die); @@ -1023,7 +1056,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, } } } else if (is_cxx_method) { - // Look at the parent of this DIE and see if is is a class or + // Look at the parent of this DIE and see if it is a class or // struct and see if this is actually a C++ method Type *class_type = dwarf->ResolveType(decl_ctx_die); if (class_type) { @@ -1116,14 +1149,15 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, // Neither GCC 4.2 nor clang++ currently set a valid // accessibility in the DWARF for C++ methods... // Default to public for now... - if (attrs.accessibility == eAccessNone) - attrs.accessibility = eAccessPublic; + const auto accessibility = attrs.accessibility == eAccessNone + ? eAccessPublic + : attrs.accessibility; clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), attrs.mangled_name, - clang_type, attrs.accessibility, attrs.is_virtual, + clang_type, accessibility, attrs.is_virtual, is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, attrs.is_artificial); @@ -1171,16 +1205,17 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, class_type->GetFullCompilerType(); // The type for this DIE should have been filled in the - // function call above + // function call above. Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { return type_ptr->shared_from_this(); } - // FIXME This is fixing some even uglier behavior but we - // really need to - // uniq the methods of each class as well as the class - // itself. <rdar://problem/11240464> + // The previous comment isn't actually true if the class wasn't + // resolved using the current method's parent DIE as source + // data. We need to ensure that we look up the method correctly + // in the class and then link the method's DIE to the unique + // CXXMethodDecl appropriately. type_handled = true; } } @@ -1405,26 +1440,9 @@ void DWARFASTParserClang::ParseInheritance( encoding_form = form_value; break; case DW_AT_data_member_location: - if (form_value.BlockData()) { - Value initialValue(0); - Value memberOffset(0); - const DWARFDataExtractor &debug_info_data = die.GetData(); - uint32_t block_length = form_value.Unsigned(); - uint32_t block_offset = - form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate( - nullptr, nullptr, module_sp, - DataExtractor(debug_info_data, block_offset, block_length), - die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, - memberOffset, nullptr)) { - member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); - } - } else { - // With DWARF 3 and later, if the value is an integer constant, - // this form value is the offset in bytes from the beginning of - // the containing entity. - member_byte_offset = form_value.Unsigned(); - } + if (auto maybe_offset = + ExtractDataMemberLocation(die, form_value, module_sp)) + member_byte_offset = *maybe_offset; break; case DW_AT_accessibility: @@ -1624,13 +1642,13 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, int tag_decl_kind = -1; AccessType default_accessibility = eAccessNone; if (tag == DW_TAG_structure_type) { - tag_decl_kind = clang::TTK_Struct; + tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Struct); default_accessibility = eAccessPublic; } else if (tag == DW_TAG_union_type) { - tag_decl_kind = clang::TTK_Union; + tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Union); default_accessibility = eAccessPublic; } else if (tag == DW_TAG_class_type) { - tag_decl_kind = clang::TTK_Class; + tag_decl_kind = llvm::to_underlying(clang::TagTypeKind::Class); default_accessibility = eAccessPrivate; } @@ -1749,11 +1767,11 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, } } assert(tag_decl_kind != -1); - (void)tag_decl_kind; + UNUSED_IF_ASSERT_DISABLED(tag_decl_kind); bool clang_type_was_created = false; - clang_type = - CompilerType(m_ast.weak_from_this(), - dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + clang_type = CompilerType( + m_ast.weak_from_this(), + dwarf->GetForwardDeclDIEToCompilerType().lookup(die.GetDIE())); if (!clang_type) { clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); @@ -1851,17 +1869,21 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, die.GetOffset(), attrs.name.GetCString()); } - // If the byte size of the record is specified then overwrite the size - // that would be computed by Clang. This is only needed as LLDB's - // TypeSystemClang is always in C++ mode, but some compilers such as - // GCC and Clang give empty structs a size of 0 in C mode (in contrast to - // the size of 1 for empty structs that would be computed in C++ mode). - if (attrs.byte_size) { + // Setting authority byte size and alignment for empty structures. + // + // If the byte size or alignmenet of the record is specified then + // overwrite the ones that would be computed by Clang. + // This is only needed as LLDB's TypeSystemClang is always in C++ mode, + // but some compilers such as GCC and Clang give empty structs a size of 0 + // in C mode (in contrast to the size of 1 for empty structs that would be + // computed in C++ mode). + if (attrs.byte_size || attrs.alignment) { clang::RecordDecl *record_decl = TypeSystemClang::GetAsRecordDecl(clang_type); if (record_decl) { ClangASTImporter::LayoutInfo layout; - layout.bit_size = *attrs.byte_size * 8; + layout.bit_size = attrs.byte_size.value_or(0) * 8; + layout.alignment = attrs.alignment.value_or(0) * 8; GetClangASTImporter().SetRecordLayout(record_decl, layout); } } @@ -1883,16 +1905,16 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // the SymbolFile virtual function // "SymbolFileDWARF::CompleteType(Type *)" When the definition // needs to be defined. - assert(!dwarf->GetForwardDeclClangTypeToDie().count( + assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count( ClangUtil::RemoveFastQualifiers(clang_type) .GetOpaqueQualType()) && "Type already in the forward declaration map!"); // Can't assume m_ast.GetSymbolFile() is actually a // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple // binaries. - dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = + dwarf->GetForwardDeclDIEToCompilerType()[die.GetDIE()] = clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie().try_emplace( + dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace( ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), *die.GetDIERef()); m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); @@ -1916,7 +1938,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); if (record_decl) record_decl->setArgPassingRestrictions( - clang::RecordDecl::APK_CannotPassInRegs); + clang::RecordArgPassingKind::CannotPassInRegs); } return type_sp; } @@ -2200,6 +2222,9 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, if (layout_info.bit_size == 0) layout_info.bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + if (layout_info.alignment == 0) + layout_info.alignment = + die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8; clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); @@ -2273,7 +2298,7 @@ CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) { clang::Decl *clang_decl = GetClangDeclForDIE(die); if (clang_decl != nullptr) return m_ast.GetCompilerDecl(clang_decl); - return CompilerDecl(); + return {}; } CompilerDeclContext @@ -2281,7 +2306,7 @@ DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) { clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die); if (clang_decl_ctx) return m_ast.CreateDeclContext(clang_decl_ctx); - return CompilerDeclContext(); + return {}; } CompilerDeclContext @@ -2290,7 +2315,7 @@ DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) { GetClangDeclContextContainingDIE(die, nullptr); if (clang_decl_ctx) return m_ast.CreateDeclContext(clang_decl_ctx); - return CompilerDeclContext(); + return {}; } size_t DWARFASTParserClang::ParseChildEnumerators( @@ -2464,27 +2489,6 @@ DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, } namespace { -/// Parsed form of all attributes that are relevant for parsing type members. -struct MemberAttributes { - explicit MemberAttributes(const DWARFDIE &die, const DWARFDIE &parent_die, - ModuleSP module_sp); - const char *name = nullptr; - /// Indicates how many bits into the word (according to the host endianness) - /// the low-order bit of the field starts. Can be negative. - int64_t bit_offset = 0; - /// Indicates the size of the field in bits. - size_t bit_size = 0; - uint64_t data_bit_offset = UINT64_MAX; - AccessType accessibility = eAccessNone; - std::optional<uint64_t> byte_size; - std::optional<DWARFFormValue> const_value_form; - DWARFFormValue encoding_form; - /// Indicates the byte offset of the word from the base address of the - /// structure. - uint32_t member_byte_offset; - bool is_artificial = false; -}; - /// Parsed form of all attributes that are relevant for parsing Objective-C /// properties. struct PropertyAttributes { @@ -2495,13 +2499,126 @@ struct PropertyAttributes { /// \see clang::ObjCPropertyAttribute uint32_t prop_attributes = 0; }; + +struct DiscriminantValue { + explicit DiscriminantValue(const DWARFDIE &die, ModuleSP module_sp); + + uint32_t byte_offset; + uint32_t byte_size; + DWARFFormValue type_ref; +}; + +struct VariantMember { + explicit VariantMember(DWARFDIE &die, ModuleSP module_sp); + bool IsDefault() const; + + std::optional<uint32_t> discr_value; + DWARFFormValue type_ref; + ConstString variant_name; + uint32_t byte_offset; + ConstString GetName() const; +}; + +struct VariantPart { + explicit VariantPart(const DWARFDIE &die, const DWARFDIE &parent_die, + ModuleSP module_sp); + + std::vector<VariantMember> &members(); + + DiscriminantValue &discriminant(); + +private: + std::vector<VariantMember> _members; + DiscriminantValue _discriminant; +}; + } // namespace -MemberAttributes::MemberAttributes(const DWARFDIE &die, - const DWARFDIE &parent_die, - ModuleSP module_sp) { - member_byte_offset = (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX; +ConstString VariantMember::GetName() const { return this->variant_name; } + +bool VariantMember::IsDefault() const { return !discr_value; } + +VariantMember::VariantMember(DWARFDIE &die, lldb::ModuleSP module_sp) { + assert(die.Tag() == llvm::dwarf::DW_TAG_variant); + this->discr_value = + die.GetAttributeValueAsOptionalUnsigned(DW_AT_discr_value); + + for (auto child_die : die.children()) { + switch (child_die.Tag()) { + case llvm::dwarf::DW_TAG_member: { + DWARFAttributes attributes = child_die.GetAttributes(); + for (std::size_t i = 0; i < attributes.Size(); ++i) { + DWARFFormValue form_value; + const dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_name: + variant_name = ConstString(form_value.AsCString()); + break; + case DW_AT_type: + type_ref = form_value; + break; + + case DW_AT_data_member_location: + if (auto maybe_offset = + ExtractDataMemberLocation(die, form_value, module_sp)) + byte_offset = *maybe_offset; + break; + + default: + break; + } + } + } + break; + } + default: + break; + } + break; + } +} + +DiscriminantValue::DiscriminantValue(const DWARFDIE &die, ModuleSP module_sp) { + auto referenced_die = die.GetReferencedDIE(DW_AT_discr); + DWARFAttributes attributes = referenced_die.GetAttributes(); + for (std::size_t i = 0; i < attributes.Size(); ++i) { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_type: + type_ref = form_value; + break; + case DW_AT_data_member_location: + if (auto maybe_offset = + ExtractDataMemberLocation(die, form_value, module_sp)) + byte_offset = *maybe_offset; + break; + default: + break; + } + } + } +} + +VariantPart::VariantPart(const DWARFDIE &die, const DWARFDIE &parent_die, + lldb::ModuleSP module_sp) + : _members(), _discriminant(die, module_sp) { + for (auto child : die.children()) { + if (child.Tag() == llvm::dwarf::DW_TAG_variant) { + _members.push_back(VariantMember(child, module_sp)); + } + } +} + +std::vector<VariantMember> &VariantPart::members() { return this->_members; } + +DiscriminantValue &VariantPart::discriminant() { return this->_discriminant; } + +DWARFASTParserClang::MemberAttributes::MemberAttributes( + const DWARFDIE &die, const DWARFDIE &parent_die, ModuleSP module_sp) { DWARFAttributes attributes = die.GetAttributes(); for (size_t i = 0; i < attributes.Size(); ++i) { const dw_attr_t attr = attributes.AttributeAtIndex(i); @@ -2530,28 +2647,9 @@ MemberAttributes::MemberAttributes(const DWARFDIE &die, data_bit_offset = form_value.Unsigned(); break; case DW_AT_data_member_location: - if (form_value.BlockData()) { - Value initialValue(0); - Value memberOffset(0); - const DWARFDataExtractor &debug_info_data = die.GetData(); - uint32_t block_length = form_value.Unsigned(); - uint32_t block_offset = - form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate( - nullptr, // ExecutionContext * - nullptr, // RegisterContext * - module_sp, - DataExtractor(debug_info_data, block_offset, block_length), - die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, - memberOffset, nullptr)) { - member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); - } - } else { - // With DWARF 3 and later, if the value is an integer constant, - // this form value is the offset in bytes from the beginning of - // the containing entity. - member_byte_offset = form_value.Unsigned(); - } + if (auto maybe_offset = + ExtractDataMemberLocation(die, form_value, module_sp)) + member_byte_offset = *maybe_offset; break; case DW_AT_accessibility: @@ -2561,6 +2659,9 @@ MemberAttributes::MemberAttributes(const DWARFDIE &die, case DW_AT_artificial: is_artificial = form_value.Boolean(); break; + case DW_AT_declaration: + is_declaration = form_value.Boolean(); + break; default: break; } @@ -2739,13 +2840,51 @@ llvm::Expected<llvm::APInt> DWARFASTParserClang::ExtractIntFromFormValue( return result; } +void DWARFASTParserClang::CreateStaticMemberVariable( + const DWARFDIE &die, const MemberAttributes &attrs, + const lldb_private::CompilerType &class_clang_type) { + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + assert(die.Tag() == DW_TAG_member || die.Tag() == DW_TAG_variable); + + Type *var_type = die.ResolveTypeUID(attrs.encoding_form.Reference()); + + if (!var_type) + return; + + auto accessibility = + attrs.accessibility == eAccessNone ? eAccessPublic : attrs.accessibility; + + CompilerType ct = var_type->GetForwardCompilerType(); + clang::VarDecl *v = TypeSystemClang::AddVariableToRecordType( + class_clang_type, attrs.name, ct, accessibility); + if (!v) { + LLDB_LOG(log, "Failed to add variable to the record type"); + return; + } + + bool unused; + // TODO: Support float/double static members as well. + if (!ct.IsIntegerOrEnumerationType(unused) || !attrs.const_value_form) + return; + + llvm::Expected<llvm::APInt> const_value_or_err = + ExtractIntFromFormValue(ct, *attrs.const_value_form); + if (!const_value_or_err) { + LLDB_LOG_ERROR(log, const_value_or_err.takeError(), + "Failed to add const value to variable {1}: {0}", + v->getQualifiedNameAsString()); + return; + } + + TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err); +} + void DWARFASTParserClang::ParseSingleMember( const DWARFDIE &die, const DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info, FieldInfo &last_field_info) { - Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); // This function can only parse DW_TAG_member. assert(die.Tag() == DW_TAG_member); @@ -2757,49 +2896,22 @@ void DWARFASTParserClang::ParseSingleMember( const uint64_t parent_bit_size = parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8; - // FIXME: Remove the workarounds below and make this const. - MemberAttributes attrs(die, parent_die, module_sp); - - const bool class_is_objc_object_or_interface = - TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type); - - // FIXME: Make Clang ignore Objective-C accessibility for expressions - if (class_is_objc_object_or_interface) - attrs.accessibility = eAccessNone; + const MemberAttributes attrs(die, parent_die, module_sp); - // Handle static members, which is any member that doesn't have a bit or a - // byte member offset. + // Handle static members, which are typically members without + // locations. However, GCC doesn't emit DW_AT_data_member_location + // for any union members (regardless of linkage). + // Non-normative text pre-DWARFv5 recommends marking static + // data members with an DW_AT_external flag. Clang emits this consistently + // whereas GCC emits it only for static data members if not part of an + // anonymous namespace. The flag that is consistently emitted for static + // data members is DW_AT_declaration, so we check it instead. + // The following block is only necessary to support DWARFv4 and earlier. + // Starting with DWARFv5, static data members are marked DW_AT_variable so we + // can consistently detect them on both GCC and Clang without below heuristic. if (attrs.member_byte_offset == UINT32_MAX && - attrs.data_bit_offset == UINT64_MAX) { - Type *var_type = die.ResolveTypeUID(attrs.encoding_form.Reference()); - - if (var_type) { - if (attrs.accessibility == eAccessNone) - attrs.accessibility = eAccessPublic; - CompilerType ct = var_type->GetForwardCompilerType(); - clang::VarDecl *v = TypeSystemClang::AddVariableToRecordType( - class_clang_type, attrs.name, ct, attrs.accessibility); - if (!v) { - LLDB_LOG(log, "Failed to add variable to the record type"); - return; - } - - bool unused; - // TODO: Support float/double static members as well. - if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused)) - return; - - llvm::Expected<llvm::APInt> const_value_or_err = - ExtractIntFromFormValue(ct, *attrs.const_value_form); - if (!const_value_or_err) { - LLDB_LOG_ERROR(log, const_value_or_err.takeError(), - "Failed to add const value to variable {1}: {0}", - v->getQualifiedNameAsString()); - return; - } - - TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err); - } + attrs.data_bit_offset == UINT64_MAX && attrs.is_declaration) { + CreateStaticMemberVariable(die, attrs, class_clang_type); return; } @@ -2822,8 +2934,9 @@ void DWARFASTParserClang::ParseSingleMember( const uint64_t word_width = 32; CompilerType member_clang_type = member_type->GetLayoutCompilerType(); - if (attrs.accessibility == eAccessNone) - attrs.accessibility = default_accessibility; + const auto accessibility = attrs.accessibility == eAccessNone + ? default_accessibility + : attrs.accessibility; uint64_t field_bit_offset = (attrs.member_byte_offset == UINT32_MAX ? 0 @@ -2837,12 +2950,13 @@ void DWARFASTParserClang::ParseSingleMember( if (attrs.data_bit_offset != UINT64_MAX) { this_field_info.bit_offset = attrs.data_bit_offset; } else { - if (!attrs.byte_size) - attrs.byte_size = member_type->GetByteSize(nullptr); + auto byte_size = attrs.byte_size; + if (!byte_size) + byte_size = member_type->GetByteSize(nullptr); ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); if (objfile->GetByteOrder() == eByteOrderLittle) { - this_field_info.bit_offset += attrs.byte_size.value_or(0) * 8; + this_field_info.bit_offset += byte_size.value_or(0) * 8; this_field_info.bit_offset -= (attrs.bit_offset + attrs.bit_size); } else { this_field_info.bit_offset += attrs.bit_offset; @@ -2881,7 +2995,7 @@ void DWARFASTParserClang::ParseSingleMember( // unnamed bitfields if we have a new enough clang. bool detect_unnamed_bitfields = true; - if (class_is_objc_object_or_interface) + if (TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type)) detect_unnamed_bitfields = die.GetCU()->Supports_unnamed_objc_bitfields(); @@ -2913,7 +3027,7 @@ void DWARFASTParserClang::ParseSingleMember( class_clang_type, llvm::StringRef(), m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), - attrs.accessibility, unnamed_field_info->bit_size); + accessibility, unnamed_field_info->bit_size); layout_info.field_offsets.insert(std::make_pair( unnamed_bitfield_decl, unnamed_field_info->bit_offset)); @@ -2937,11 +3051,9 @@ void DWARFASTParserClang::ParseSingleMember( // in our AST. Clang will re-create those articial members and they would // otherwise just overlap in the layout with the FieldDecls we add here. // This needs to be done after updating FieldInfo which keeps track of where - // field start/end so we don't later try to fill the the space of this + // field start/end so we don't later try to fill the space of this // artificial member with (unnamed bitfield) padding. - // FIXME: This check should verify that this is indeed an artificial member - // we are supposed to ignore. - if (attrs.is_artificial) { + if (attrs.is_artificial && ShouldIgnoreArtificialField(attrs.name)) { last_field_info.SetIsArtificial(true); return; } @@ -2950,12 +3062,10 @@ void DWARFASTParserClang::ParseSingleMember( member_clang_type.GetCompleteType(); { - // Older versions of clang emit array[0] and array[1] in the - // same way (<rdar://problem/12566646>). If the current field - // is at the end of the structure, then there is definitely no - // room for extra elements and we override the type to - // array[0]. - + // Older versions of clang emit the same DWARF for array[0] and array[1]. If + // the current field is at the end of the structure, then there is + // definitely no room for extra elements and we override the type to + // array[0]. This was fixed by f454dfb6b5af. CompilerType member_array_element_type; uint64_t member_array_size; bool member_array_is_incomplete; @@ -2987,7 +3097,7 @@ void DWARFASTParserClang::ParseSingleMember( TypeSystemClang::RequireCompleteType(member_clang_type); clang::FieldDecl *field_decl = TypeSystemClang::AddFieldToRecordType( - class_clang_type, attrs.name, member_clang_type, attrs.accessibility, + class_clang_type, attrs.name, member_clang_type, accessibility, attrs.bit_size); m_ast.SetMetadataAsUserID(field_decl, die.GetID()); @@ -3022,6 +3132,17 @@ bool DWARFASTParserClang::ParseChildMembers( ParseObjCProperty(die, parent_die, class_clang_type, delayed_properties); break; + case DW_TAG_variant_part: + if (die.GetCU()->GetDWARFLanguageType() == eLanguageTypeRust) { + ParseRustVariantPart(die, parent_die, class_clang_type, + default_accessibility, layout_info); + } + break; + + case DW_TAG_variable: { + const MemberAttributes attrs(die, parent_die, module_sp); + CreateStaticMemberVariable(die, attrs, class_clang_type); + } break; case DW_TAG_member: ParseSingleMember(die, parent_die, class_clang_type, default_accessibility, layout_info, last_field_info); @@ -3167,30 +3288,6 @@ size_t DWARFASTParserClang::ParseChildParameters( return arg_idx; } -Type *DWARFASTParserClang::GetTypeForDIE(const DWARFDIE &die) { - if (!die) - return nullptr; - - SymbolFileDWARF *dwarf = die.GetDWARF(); - if (!dwarf) - return nullptr; - - DWARFAttributes attributes = die.GetAttributes(); - if (attributes.Size() == 0) - return nullptr; - - DWARFFormValue type_die_form; - for (size_t i = 0; i < attributes.Size(); ++i) { - dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - - if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) - return dwarf->ResolveTypeUID(form_value.Reference(), true); - } - - return nullptr; -} - clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) { if (!die) return nullptr; @@ -3566,7 +3663,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( // Make sure this is a declaration and not a concrete instance by looking // for DW_AT_declaration set to 1. Sometimes concrete function instances are // placed inside the class definitions and shouldn't be included in the list - // of things are are tracking here. + // of things that are tracking here. if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) != 1) return; @@ -3729,3 +3826,77 @@ bool DWARFASTParserClang::ShouldCreateUnnamedBitfield( return true; } + +void DWARFASTParserClang::ParseRustVariantPart( + DWARFDIE &die, const DWARFDIE &parent_die, CompilerType &class_clang_type, + const lldb::AccessType default_accesibility, + ClangASTImporter::LayoutInfo &layout_info) { + assert(die.Tag() == llvm::dwarf::DW_TAG_variant_part); + assert(SymbolFileDWARF::GetLanguage(*die.GetCU()) == + LanguageType::eLanguageTypeRust); + + ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); + + VariantPart variants(die, parent_die, module_sp); + + auto discriminant_type = + die.ResolveTypeUID(variants.discriminant().type_ref.Reference()); + + auto decl_context = m_ast.GetDeclContextForType(class_clang_type); + + auto inner_holder = m_ast.CreateRecordType( + decl_context, OptionalClangModuleID(), lldb::eAccessPublic, + std::string( + llvm::formatv("{0}$Inner", class_clang_type.GetTypeName(false))), + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeRust); + m_ast.StartTagDeclarationDefinition(inner_holder); + m_ast.SetIsPacked(inner_holder); + + for (auto member : variants.members()) { + + auto has_discriminant = !member.IsDefault(); + + auto member_type = die.ResolveTypeUID(member.type_ref.Reference()); + + auto field_type = m_ast.CreateRecordType( + m_ast.GetDeclContextForType(inner_holder), OptionalClangModuleID(), + lldb::eAccessPublic, + std::string(llvm::formatv("{0}$Variant", member.GetName())), + llvm::to_underlying(clang::TagTypeKind::Struct), + lldb::eLanguageTypeRust); + + m_ast.StartTagDeclarationDefinition(field_type); + auto offset = member.byte_offset; + + if (has_discriminant) { + m_ast.AddFieldToRecordType( + field_type, "$discr$", discriminant_type->GetFullCompilerType(), + lldb::eAccessPublic, variants.discriminant().byte_offset); + offset += discriminant_type->GetByteSize(nullptr).value_or(0); + } + + m_ast.AddFieldToRecordType(field_type, "value", + member_type->GetFullCompilerType(), + lldb::eAccessPublic, offset * 8); + + m_ast.CompleteTagDeclarationDefinition(field_type); + + auto name = has_discriminant + ? llvm::formatv("$variant${0}", member.discr_value.value()) + : std::string("$variant$"); + + auto variant_decl = + m_ast.AddFieldToRecordType(inner_holder, llvm::StringRef(name), + field_type, default_accesibility, 0); + + layout_info.field_offsets.insert({variant_decl, 0}); + } + + auto inner_field = m_ast.AddFieldToRecordType(class_clang_type, + llvm::StringRef("$variants$"), + inner_holder, eAccessPublic, 0); + + m_ast.CompleteTagDeclarationDefinition(inner_holder); + + layout_info.field_offsets.insert({inner_field, 0}); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 042075b7df5f..3e28e54d6220 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -31,45 +31,51 @@ namespace lldb_private { class CompileUnit; } +namespace lldb_private::plugin { +namespace dwarf { class DWARFDebugInfoEntry; class SymbolFileDWARF; +} // namespace dwarf +} // namespace lldb_private::plugin struct ParsedDWARFTypeAttributes; -class DWARFASTParserClang : public DWARFASTParser { +class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser { public: DWARFASTParserClang(lldb_private::TypeSystemClang &ast); ~DWARFASTParserClang() override; // DWARFASTParser interface. - lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - bool *type_is_new_ptr) override; + lldb::TypeSP + ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + bool *type_is_new_ptr) override; - lldb_private::ConstString - ConstructDemangledNameFromDWARF(const DWARFDIE &die) override; + lldb_private::ConstString ConstructDemangledNameFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; lldb_private::Function * ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, - const DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &die, const lldb_private::AddressRange &func_range) override; bool - CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Type *type, lldb_private::CompilerType &compiler_type) override; - lldb_private::CompilerDecl - GetDeclForUIDFromDWARF(const DWARFDIE &die) override; + lldb_private::CompilerDecl GetDeclForUIDFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; void EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) override; - lldb_private::CompilerDeclContext - GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override; + lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; - lldb_private::CompilerDeclContext - GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override; + lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; lldb_private::ClangASTImporter &GetClangASTImporter(); @@ -85,9 +91,9 @@ public: /// DWARFFormValue with the bit width of the given integer type. /// Returns an error if the value in the DWARFFormValue does not fit /// into the given integer type or the integer type isn't supported. - llvm::Expected<llvm::APInt> - ExtractIntFromFormValue(const lldb_private::CompilerType &int_type, - const DWARFFormValue &form_value) const; + llvm::Expected<llvm::APInt> ExtractIntFromFormValue( + const lldb_private::CompilerType &int_type, + const lldb_private::plugin::dwarf::DWARFFormValue &form_value) const; /// Returns the template parameters of a class DWARFDIE as a string. /// @@ -99,8 +105,8 @@ public: /// \return A string, including surrounding '<>', of the template parameters. /// If the DIE's name already has '<>', returns an empty ConstString because /// it's assumed that the caller is using the DIE name anyway. - lldb_private::ConstString - GetDIEClassTemplateParams(const DWARFDIE &die) override; + lldb_private::ConstString GetDIEClassTemplateParams( + const lldb_private::plugin::dwarf::DWARFDIE &die) override; protected: /// Protected typedefs and members. @@ -108,14 +114,19 @@ protected: class DelayedAddObjCClassProperty; typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> + typedef llvm::DenseMap< + const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, + clang::DeclContext *> DIEToDeclContextMap; - typedef std::multimap<const clang::DeclContext *, const DWARFDIE> + typedef std::multimap<const clang::DeclContext *, + const lldb_private::plugin::dwarf::DWARFDIE> DeclContextToDIEMap; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, - lldb_private::OptionalClangModuleID> + typedef llvm::DenseMap< + const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, + lldb_private::OptionalClangModuleID> DIEToModuleMap; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> + typedef llvm::DenseMap< + const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *, clang::Decl *> DIEToDeclMap; lldb_private::TypeSystemClang &m_ast; @@ -126,11 +137,14 @@ protected: std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; /// @} - clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); + clang::DeclContext * + GetDeclContextForBlock(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); + clang::BlockDecl * + ResolveBlockDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die); + clang::NamespaceDecl * + ResolveNamespaceDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); /// Returns the namespace decl that a DW_TAG_imported_declaration imports. /// @@ -141,82 +155,99 @@ protected: /// 'die' imports. If the imported entity is not a namespace /// or another import declaration, returns nullptr. If an error /// occurs, returns nullptr. - clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die); + clang::NamespaceDecl *ResolveImportedDeclarationDIE( + const lldb_private::plugin::dwarf::DWARFDIE &die); - bool ParseTemplateDIE(const DWARFDIE &die, + bool ParseTemplateDIE(const lldb_private::plugin::dwarf::DWARFDIE &die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); bool ParseTemplateParameterInfos( - const DWARFDIE &parent_die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); - std::string GetCPlusPlusQualifiedName(const DWARFDIE &die); + std::string + GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die); bool ParseChildMembers( - const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::CompilerType &class_compiler_type, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, - std::vector<DWARFDIE> &member_function_dies, + std::vector<lldb_private::plugin::dwarf::DWARFDIE> &member_function_dies, DelayedPropertyList &delayed_properties, const lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t ParseChildParameters(clang::DeclContext *containing_decl_ctx, - const DWARFDIE &parent_die, bool skip_artificial, - bool &is_static, bool &is_variadic, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + bool skip_artificial, bool &is_static, bool &is_variadic, bool &has_template_params, std::vector<lldb_private::CompilerType> &function_args, std::vector<clang::ParmVarDecl *> &function_param_decls, unsigned &type_quals); - size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type, - bool is_signed, uint32_t enumerator_byte_size, - const DWARFDIE &parent_die); + size_t ParseChildEnumerators( + lldb_private::CompilerType &compiler_type, bool is_signed, + uint32_t enumerator_byte_size, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die); /// Parse a structure, class, or union type DIE. - lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); - - lldb_private::Type *GetTypeForDIE(const DWARFDIE &die); + lldb::TypeSP + ParseStructureLikeDIE(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); - clang::Decl *GetClangDeclForDIE(const DWARFDIE &die); + clang::Decl * + GetClangDeclForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::DeclContext *GetClangDeclContextForDIE(const DWARFDIE &die); + clang::DeclContext * + GetClangDeclContextForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die); - clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die, - DWARFDIE *decl_ctx_die); - lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die); + clang::DeclContext *GetClangDeclContextContainingDIE( + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::plugin::dwarf::DWARFDIE *decl_ctx_die); + lldb_private::OptionalClangModuleID + GetOwningClangModule(const lldb_private::plugin::dwarf::DWARFDIE &die); - bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die, - const DWARFDIE &dst_class_die, - lldb_private::Type *class_type, - std::vector<DWARFDIE> &failures); + bool CopyUniqueClassMethodTypes( + const lldb_private::plugin::dwarf::DWARFDIE &src_class_die, + const lldb_private::plugin::dwarf::DWARFDIE &dst_class_die, + lldb_private::Type *class_type, + std::vector<lldb_private::plugin::dwarf::DWARFDIE> &failures); - clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die); + clang::DeclContext *GetCachedClangDeclContextForDIE( + const lldb_private::plugin::dwarf::DWARFDIE &die); - void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, const DWARFDIE &die); + void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, + const lldb_private::plugin::dwarf::DWARFDIE &die); - void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die); + void LinkDeclToDIE(clang::Decl *decl, + const lldb_private::plugin::dwarf::DWARFDIE &die); /// If \p type_sp is valid, calculate and set its symbol context scope, and /// update the type list for its backing symbol file. /// /// Returns \p type_sp. - lldb::TypeSP - UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, lldb::TypeSP type_sp); + lldb::TypeSP UpdateSymbolContextScopeForType( + const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp); /// Follow Clang Module Skeleton CU references to find a type definition. - lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - lldb_private::Log *log); + lldb::TypeSP + ParseTypeFromClangModule(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Log *log); // Return true if this type is a declaration to a type in an external // module. - lldb::ModuleSP GetModuleForType(const DWARFDIE &die); + lldb::ModuleSP + GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die); + + static bool classof(const DWARFASTParser *Parser) { + return Parser->GetKind() == Kind::DWARFASTParserClang; + } private: struct FieldInfo { @@ -240,6 +271,30 @@ private: } }; + /// Parsed form of all attributes that are relevant for parsing type members. + struct MemberAttributes { + explicit MemberAttributes( + const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + lldb::ModuleSP module_sp); + const char *name = nullptr; + /// Indicates how many bits into the word (according to the host endianness) + /// the low-order bit of the field starts. Can be negative. + int64_t bit_offset = 0; + /// Indicates the size of the field in bits. + size_t bit_size = 0; + uint64_t data_bit_offset = UINT64_MAX; + lldb::AccessType accessibility = lldb::eAccessNone; + std::optional<uint64_t> byte_size; + std::optional<lldb_private::plugin::dwarf::DWARFFormValue> const_value_form; + lldb_private::plugin::dwarf::DWARFFormValue encoding_form; + /// Indicates the byte offset of the word from the base address of the + /// structure. + uint32_t member_byte_offset = UINT32_MAX; + bool is_artificial = false; + bool is_declaration = false; + }; + /// Returns 'true' if we should create an unnamed bitfield /// and add it to the parser's current AST. /// @@ -268,33 +323,57 @@ private: /// created property. /// \param delayed_properties The list of delayed properties that the result /// will be appended to. - void ParseObjCProperty(const DWARFDIE &die, const DWARFDIE &parent_die, - const lldb_private::CompilerType &class_clang_type, - DelayedPropertyList &delayed_properties); + void + ParseObjCProperty(const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + const lldb_private::CompilerType &class_clang_type, + DelayedPropertyList &delayed_properties); void - ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die, + ParseSingleMember(const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info, FieldInfo &last_field_info); - bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type, + /// If the specified 'die' represents a static data member, creates + /// a 'clang::VarDecl' for it and attaches it to specified parent + /// 'class_clang_type'. + /// + /// \param[in] die The member declaration we want to create a + /// clang::VarDecl for. + /// + /// \param[in] attrs The parsed attributes for the specified 'die'. + /// + /// \param[in] class_clang_type The parent RecordType of the static + /// member this function will create. + void CreateStaticMemberVariable( + const lldb_private::plugin::dwarf::DWARFDIE &die, + const MemberAttributes &attrs, + const lldb_private::CompilerType &class_clang_type); + + bool CompleteRecordType(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Type *type, lldb_private::CompilerType &clang_type); - bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type, + bool CompleteEnumType(const lldb_private::plugin::dwarf::DWARFDIE &die, + lldb_private::Type *type, lldb_private::CompilerType &clang_type); - lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP + ParseTypeModifier(const lldb_private::SymbolContext &sc, + const lldb_private::plugin::dwarf::DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParseSubroutine(const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParseArrayType(const DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); - lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die, - const ParsedDWARFTypeAttributes &attrs); + lldb::TypeSP + ParsePointerToMemberType(const lldb_private::plugin::dwarf::DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs); /// Parses a DW_TAG_inheritance DIE into a base/super class. /// @@ -311,19 +390,37 @@ private: /// \param layout_info The layout information that will be updated for C++ /// base classes with the base offset. void ParseInheritance( - const DWARFDIE &die, const DWARFDIE &parent_die, + const lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, const lldb_private::CompilerType class_clang_type, const lldb::AccessType default_accessibility, const lldb::ModuleSP &module_sp, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, lldb_private::ClangASTImporter::LayoutInfo &layout_info); + + /// Parses DW_TAG_variant_part DIE into a structure that encodes all variants + /// Note that this is currently being emitted by rustc and not Clang + /// \param die DW_TAG_variant_part DIE to parse + /// \param parent_die The parent DW_TAG_structure_type to parse + /// \param class_clang_type The Rust struct representing parent_die. + /// \param default_accesibility The default accessibility that is given to + /// base classes if they don't have an explicit accessibility set + /// \param layout_info The layout information that will be updated for + // base classes with the base offset + void + ParseRustVariantPart(lldb_private::plugin::dwarf::DWARFDIE &die, + const lldb_private::plugin::dwarf::DWARFDIE &parent_die, + lldb_private::CompilerType &class_clang_type, + const lldb::AccessType default_accesibility, + lldb_private::ClangASTImporter::LayoutInfo &layout_info); }; /// Parsed form of all attributes that are relevant for type reconstruction. /// Some attributes are relevant for all kinds of types (declaration), while /// others are only meaningful to a specific type (is_virtual) struct ParsedDWARFTypeAttributes { - explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); + explicit ParsedDWARFTypeAttributes( + const lldb_private::plugin::dwarf::DWARFDIE &die); lldb::AccessType accessibility = lldb::eAccessNone; bool is_artificial = false; @@ -340,14 +437,15 @@ struct ParsedDWARFTypeAttributes { const char *mangled_name = nullptr; lldb_private::ConstString name; lldb_private::Declaration decl; - DWARFDIE object_pointer; - DWARFFormValue abstract_origin; - DWARFFormValue containing_type; - DWARFFormValue signature; - DWARFFormValue specification; - DWARFFormValue type; + lldb_private::plugin::dwarf::DWARFDIE object_pointer; + lldb_private::plugin::dwarf::DWARFFormValue abstract_origin; + lldb_private::plugin::dwarf::DWARFFormValue containing_type; + lldb_private::plugin::dwarf::DWARFFormValue signature; + lldb_private::plugin::dwarf::DWARFFormValue specification; + lldb_private::plugin::dwarf::DWARFFormValue type; lldb::LanguageType class_language = lldb::eLanguageTypeUnknown; std::optional<uint64_t> byte_size; + std::optional<uint64_t> alignment; size_t calling_convention = llvm::dwarf::DW_CC_normal; uint32_t bit_stride = 0; uint32_t byte_stride = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp index 00b56537ae2b..3d35775e081e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -11,6 +11,7 @@ #include "DWARFDebugInfo.h" using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; DWARFAttributes::DWARFAttributes() : m_infos() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h index 90e12fa02493..e05ccc980d92 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h @@ -14,6 +14,8 @@ #include "llvm/ADT/SmallVector.h" #include <vector> +namespace lldb_private::plugin { +namespace dwarf { class DWARFUnit; class DWARFAttribute { @@ -31,6 +33,7 @@ public: form = m_form; val = m_value; } + protected: dw_attr_t m_attr; dw_form_t m_form; @@ -72,5 +75,7 @@ protected: typedef llvm::SmallVector<AttributeValue, 8> collection; collection m_infos; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFATTRIBUTE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp index 37a917c3a766..3a3b05acd26d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -18,6 +18,7 @@ #include <optional> using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; std::optional<DIERef> DWARFBaseDIE::GetDIERef() const { if (!IsValid()) @@ -35,7 +36,7 @@ dw_tag_t DWARFBaseDIE::Tag() const { } const char *DWARFBaseDIE::GetTagAsCString() const { - return lldb_private::DW_TAG_value_to_name(Tag()); + return DW_TAG_value_to_name(Tag()); } const char *DWARFBaseDIE::GetAttributeValueAsString(const dw_attr_t attr, @@ -120,6 +121,8 @@ DWARFAttributes DWARFBaseDIE::GetAttributes(Recurse recurse) const { return DWARFAttributes(); } +namespace lldb_private::plugin { +namespace dwarf { bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) { return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU(); } @@ -127,6 +130,8 @@ bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) { bool operator!=(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) { return !(lhs == rhs); } +} // namespace dwarf +} // namespace lldb_private::plugin const DWARFDataExtractor &DWARFBaseDIE::GetData() const { // Clients must check if this DIE is valid before calling this function. diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 8bcf807ad163..75c822703cd8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -15,6 +15,8 @@ #include "llvm/Support/Error.h" #include <optional> +namespace lldb_private::plugin { +namespace dwarf { class DIERef; class DWARFASTParser; class DWARFAttributes; @@ -78,7 +80,7 @@ public: // correct section data. // // Clients must validate that this object is valid before calling this. - const lldb_private::DWARFDataExtractor &GetData() const; + const DWARFDataExtractor &GetData() const; // Accessing information about a DIE dw_tag_t Tag() const; @@ -124,5 +126,7 @@ protected: bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs); bool operator!=(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs); +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFBASEDIE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index f839a59bf6c3..ec4c297cf7e1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -16,6 +16,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; void DWARFCompileUnit::Dump(Stream *s) const { s->Format( diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index ab3017ba0ffc..dd130977d4b1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -12,11 +12,17 @@ #include "DWARFUnit.h" #include "llvm/Support/Error.h" +namespace llvm { +class DWARFAbbreviationDeclarationSet; +} // namespace llvm + +namespace lldb_private::plugin { +namespace dwarf { class DWARFCompileUnit : public DWARFUnit { public: void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override; - void Dump(lldb_private::Stream *s) const override; + void Dump(Stream *s) const override; static bool classof(const DWARFUnit *unit) { return !unit->IsTypeUnit(); } @@ -27,7 +33,7 @@ public: private: DWARFCompileUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs, + const llvm::DWARFAbbreviationDeclarationSet &abbrevs, DIERef::Section section, bool is_dwo) : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {} @@ -36,5 +42,7 @@ private: friend class DWARFUnit; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFCOMPILEUNIT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp index f72dad88e157..e3872dc626be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -13,6 +13,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; static DWARFDataExtractor LoadSection(SectionList *section_list, SectionType section_type) { @@ -141,7 +142,10 @@ llvm::DWARFContext &DWARFContext::GetAsLLVM() { AddSection("debug_line_str", getOrLoadLineStrData()); AddSection("debug_cu_index", getOrLoadCuIndexData()); AddSection("debug_tu_index", getOrLoadTuIndexData()); - + if (isDwo()) { + AddSection("debug_info.dwo", getOrLoadDebugInfoData()); + AddSection("debug_types.dwo", getOrLoadDebugTypesData()); + } m_llvm_context = llvm::DWARFContext::create(section_map, addr_size); } return *m_llvm_context; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h index 7df776b5f514..87c6eb209337 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h @@ -16,7 +16,8 @@ #include <memory> #include <optional> -namespace lldb_private { +namespace lldb_private::plugin { +namespace dwarf { class DWARFContext { private: SectionList *m_main_section_list; @@ -78,6 +79,7 @@ public: llvm::DWARFContext &GetAsLLVM(); }; -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index b31c5dcac918..bed68f45426f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -18,6 +18,7 @@ using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; namespace { @@ -372,47 +373,97 @@ std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const { return result; } -void DWARFDIE::GetDeclContext( - llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const { +std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const { + std::vector<lldb_private::CompilerContext> context; const dw_tag_t tag = Tag(); if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) - return; + return context; DWARFDIE parent = GetParent(); if (parent) - parent.GetDeclContext(context); + context = parent.GetDeclContext(); + auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { + context.push_back({kind, ConstString(name)}); + }; switch (tag) { case DW_TAG_module: - context.push_back({CompilerContextKind::Module, ConstString(GetName())}); + push_ctx(CompilerContextKind::Module, GetName()); break; case DW_TAG_namespace: - context.push_back({CompilerContextKind::Namespace, ConstString(GetName())}); + push_ctx(CompilerContextKind::Namespace, GetName()); break; case DW_TAG_structure_type: - context.push_back({CompilerContextKind::Struct, ConstString(GetName())}); + push_ctx(CompilerContextKind::Struct, GetName()); break; case DW_TAG_union_type: - context.push_back({CompilerContextKind::Union, ConstString(GetName())}); + push_ctx(CompilerContextKind::Union, GetName()); break; case DW_TAG_class_type: - context.push_back({CompilerContextKind::Class, ConstString(GetName())}); + push_ctx(CompilerContextKind::Class, GetName()); break; case DW_TAG_enumeration_type: - context.push_back({CompilerContextKind::Enum, ConstString(GetName())}); + push_ctx(CompilerContextKind::Enum, GetName()); break; case DW_TAG_subprogram: - context.push_back( - {CompilerContextKind::Function, ConstString(GetPubname())}); + push_ctx(CompilerContextKind::Function, GetPubname()); break; case DW_TAG_variable: - context.push_back( - {CompilerContextKind::Variable, ConstString(GetPubname())}); + push_ctx(CompilerContextKind::Variable, GetPubname()); break; case DW_TAG_typedef: - context.push_back({CompilerContextKind::Typedef, ConstString(GetName())}); + push_ctx(CompilerContextKind::Typedef, GetName()); + break; + default: + break; + } + return context; +} + +std::vector<lldb_private::CompilerContext> +DWARFDIE::GetTypeLookupContext() const { + std::vector<lldb_private::CompilerContext> context; + // If there is no name, then there is no need to look anything up for this + // DIE. + const char *name = GetName(); + if (!name || !name[0]) + return context; + const dw_tag_t tag = Tag(); + if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) + return context; + DWARFDIE parent = GetParent(); + if (parent) + context = parent.GetTypeLookupContext(); + auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { + context.push_back({kind, ConstString(name)}); + }; + switch (tag) { + case DW_TAG_namespace: + push_ctx(CompilerContextKind::Namespace, name); + break; + case DW_TAG_structure_type: + push_ctx(CompilerContextKind::Struct, name); + break; + case DW_TAG_union_type: + push_ctx(CompilerContextKind::Union, name); + break; + case DW_TAG_class_type: + push_ctx(CompilerContextKind::Class, name); + break; + case DW_TAG_enumeration_type: + push_ctx(CompilerContextKind::Enum, name); + break; + case DW_TAG_variable: + push_ctx(CompilerContextKind::Variable, GetPubname()); + break; + case DW_TAG_typedef: + push_ctx(CompilerContextKind::Typedef, name); + break; + case DW_TAG_base_type: + push_ctx(CompilerContextKind::Builtin, name); break; default: break; } + return context; } DWARFDIE diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 031ea26ad405..511ca62d0197 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -13,6 +13,8 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/iterator_range.h" +namespace lldb_private::plugin { +namespace dwarf { class DWARFDIE : public DWARFBaseDIE { public: class child_iterator; @@ -31,14 +33,14 @@ public: const char *GetPubname() const; using DWARFBaseDIE::GetName; - void GetName(lldb_private::Stream &s) const; + void GetName(Stream &s) const; - void AppendTypeName(lldb_private::Stream &s) const; + void AppendTypeName(Stream &s) const; - lldb_private::Type *ResolveType() const; + Type *ResolveType() const; // Resolve a type by UID using this DIE's DWARF file - lldb_private::Type *ResolveTypeUID(const DWARFDIE &die) const; + Type *ResolveTypeUID(const DWARFDIE &die) const; // Functions for obtaining DIE relations and references @@ -71,9 +73,21 @@ public: std::vector<DWARFDIE> GetDeclContextDIEs() const; /// Return this DIE's decl context as it is needed to look up types - /// in Clang's -gmodules debug info format. - void GetDeclContext( - llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const; + /// in Clang modules. This context will include any modules or functions that + /// the type is declared in so an exact module match can be efficiently made. + std::vector<CompilerContext> GetDeclContext() const; + + /// Get a context to a type so it can be looked up. + /// + /// This function uses the current DIE to fill in a CompilerContext array + /// that is suitable for type lookup for comparison to a TypeQuery's compiler + /// context (TypeQuery::GetContextRef()). If this DIE represents a named type, + /// it should fill out the compiler context with the type itself as the last + /// entry. The declaration context should be above the type and stop at an + /// appropriate time, like either the translation unit or at a function + /// context. This is designed to allow users to efficiently look for types + /// using a full or partial CompilerContext array. + std::vector<CompilerContext> GetTypeLookupContext() const; // Getting attribute values from the DIE. // @@ -88,7 +102,7 @@ public: std::optional<int> &decl_file, std::optional<int> &decl_line, std::optional<int> &decl_column, std::optional<int> &call_file, std::optional<int> &call_line, std::optional<int> &call_column, - lldb_private::DWARFExpressionList *frame_base) const; + DWARFExpressionList *frame_base) const; /// The range of all the children of this DIE. llvm::iterator_range<child_iterator> children() const; @@ -126,5 +140,7 @@ public: return *this; } }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDIE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h index b9526b079c1e..41b8e9ad0217 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h @@ -33,6 +33,6 @@ public: llvm::DWARFDataExtractor GetAsLLVMDWARF() const; llvm::DataExtractor GetAsLLVM() const; }; -} +} // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDATAEXTRACTOR_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp deleted file mode 100644 index 0cd53463ee65..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//===-- DWARFDebugAbbrev.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 "DWARFDebugAbbrev.h" -#include "DWARFDataExtractor.h" -#include "DWARFFormValue.h" -#include "lldb/Utility/Stream.h" - -using namespace lldb; -using namespace lldb_private; - -// DWARFDebugAbbrev constructor -DWARFDebugAbbrev::DWARFDebugAbbrev() - : m_abbrevCollMap(), m_prev_abbr_offset_pos(m_abbrevCollMap.end()) {} - -// DWARFDebugAbbrev::Parse() -llvm::Error DWARFDebugAbbrev::parse(const DWARFDataExtractor &data) { - llvm::DataExtractor llvm_data = data.GetAsLLVM(); - lldb::offset_t offset = 0; - - while (llvm_data.isValidOffset(offset)) { - uint32_t initial_cu_offset = offset; - DWARFAbbreviationDeclarationSet abbrevDeclSet; - - llvm::Error error = abbrevDeclSet.extract(llvm_data, &offset); - if (error) - return error; - - m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet; - } - m_prev_abbr_offset_pos = m_abbrevCollMap.end(); - return llvm::ErrorSuccess(); -} - -// DWARFDebugAbbrev::GetAbbreviationDeclarationSet() -const DWARFAbbreviationDeclarationSet * -DWARFDebugAbbrev::GetAbbreviationDeclarationSet( - dw_offset_t cu_abbr_offset) const { - DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end(); - DWARFAbbreviationDeclarationCollMapConstIter pos; - if (m_prev_abbr_offset_pos != end && - m_prev_abbr_offset_pos->first == cu_abbr_offset) - return &(m_prev_abbr_offset_pos->second); - else { - pos = m_abbrevCollMap.find(cu_abbr_offset); - m_prev_abbr_offset_pos = pos; - } - - if (pos != m_abbrevCollMap.end()) - return &(pos->second); - return nullptr; -} - -// DWARFDebugAbbrev::GetUnsupportedForms() -void DWARFDebugAbbrev::GetUnsupportedForms( - std::set<dw_form_t> &invalid_forms) const { - for (const auto &pair : m_abbrevCollMap) - for (const auto &decl : pair.second) - for (const auto &attr : decl.attributes()) - if (!DWARFFormValue::FormIsSupported(attr.Form)) - invalid_forms.insert(attr.Form); -} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h deleted file mode 100644 index 0a579e34b001..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h +++ /dev/null @@ -1,46 +0,0 @@ -//===-- DWARFDebugAbbrev.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_SYMBOLFILE_DWARF_DWARFDEBUGABBREV_H -#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGABBREV_H - -#include "DWARFDefines.h" -#include "lldb/lldb-private.h" - -#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" - -#include <map> - -using DWARFAbbreviationDeclaration = llvm::DWARFAbbreviationDeclaration; -using DWARFAbbreviationDeclarationSet = llvm::DWARFAbbreviationDeclarationSet; - -typedef std::map<dw_offset_t, DWARFAbbreviationDeclarationSet> - DWARFAbbreviationDeclarationCollMap; -typedef DWARFAbbreviationDeclarationCollMap::iterator - DWARFAbbreviationDeclarationCollMapIter; -typedef DWARFAbbreviationDeclarationCollMap::const_iterator - DWARFAbbreviationDeclarationCollMapConstIter; - -class DWARFDebugAbbrev { -public: - DWARFDebugAbbrev(); - const DWARFAbbreviationDeclarationSet * - GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const; - /// Extract all abbreviations for a particular compile unit. Returns - /// llvm::ErrorSuccess() on success, and an appropriate llvm::Error object - /// otherwise. - llvm::Error parse(const lldb_private::DWARFDataExtractor &data); - void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; - -protected: - DWARFAbbreviationDeclarationCollMap m_abbrevCollMap; - mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos; -}; - -#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGABBREV_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp index 03cbfd28ae74..8461b94abca6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp @@ -13,6 +13,7 @@ #include <cassert> using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; DWARFDebugArangeSet::DWARFDebugArangeSet() : m_offset(DW_INVALID_OFFSET), m_next_offset(DW_INVALID_OFFSET) {} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h index 3c8633eaa3cc..ecdbe953f58b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h @@ -13,6 +13,8 @@ #include <cstdint> #include <vector> +namespace lldb_private::plugin { +namespace dwarf { class DWARFDebugArangeSet { public: struct Header { @@ -42,7 +44,7 @@ public: DWARFDebugArangeSet(); void Clear(); void SetOffset(uint32_t offset) { m_offset = offset; } - llvm::Error extract(const lldb_private::DWARFDataExtractor &data, + llvm::Error extract(const DWARFDataExtractor &data, lldb::offset_t *offset_ptr); dw_offset_t FindAddress(dw_addr_t address) const; size_t NumDescriptors() const { return m_arange_descriptors.size(); } @@ -62,5 +64,7 @@ protected: Header m_header; DescriptorColl m_arange_descriptors; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGARANGESET_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index b38dd2b88c9d..da73891f6665 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -15,6 +15,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; // Constructor DWARFDebugAranges::DWARFDebugAranges() : m_aranges() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h index 5ff37e400c88..99e2108b85c6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h @@ -13,10 +13,11 @@ #include "lldb/Utility/RangeMap.h" #include "llvm/Support/Error.h" +namespace lldb_private::plugin { +namespace dwarf { class DWARFDebugAranges { protected: - typedef lldb_private::RangeDataVector<dw_addr_t, uint32_t, dw_offset_t> - RangeToDIE; + typedef RangeDataVector<dw_addr_t, uint32_t, dw_offset_t> RangeToDIE; public: typedef RangeToDIE::Entry Range; @@ -26,14 +27,14 @@ public: void Clear() { m_aranges.Clear(); } - void extract(const lldb_private::DWARFDataExtractor &debug_aranges_data); + void extract(const DWARFDataExtractor &debug_aranges_data); // Use append range multiple times and then call sort void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc); void Sort(bool minimize); - void Dump(lldb_private::Log *log) const; + void Dump(Log *log) const; dw_offset_t FindAddress(dw_addr_t address) const; @@ -50,5 +51,7 @@ public: protected: RangeToDIE m_aranges; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGARANGES_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 9a33d6338b87..553b6a4c551d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -27,10 +27,10 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; // Constructor -DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, - lldb_private::DWARFContext &context) +DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, DWARFContext &context) : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {} const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index c990ac9fbe58..d5e48f312ea0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -19,20 +19,18 @@ #include "lldb/lldb-private.h" #include "llvm/Support/Error.h" -namespace lldb_private { +namespace lldb_private::plugin { +namespace dwarf { class DWARFContext; -} class DWARFDebugInfo { public: - typedef dw_offset_t (*Callback)(SymbolFileDWARF *dwarf2Data, - DWARFUnit *cu, + typedef dw_offset_t (*Callback)(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu, DWARFDebugInfoEntry *die, const dw_offset_t next_offset, const uint32_t depth, void *userData); - explicit DWARFDebugInfo(SymbolFileDWARF &dwarf, - lldb_private::DWARFContext &context); + explicit DWARFDebugInfo(SymbolFileDWARF &dwarf, DWARFContext &context); size_t GetNumUnits(); DWARFUnit *GetUnitAtIndex(size_t idx); @@ -58,7 +56,7 @@ protected: typedef std::vector<DWARFUnitSP> UnitColl; SymbolFileDWARF &m_dwarf; - lldb_private::DWARFContext &m_context; + DWARFContext &m_context; llvm::once_flag m_units_once_flag; UnitColl m_units; @@ -80,5 +78,7 @@ private: DWARFDebugInfo(const DWARFDebugInfo &) = delete; const DWARFDebugInfo &operator=(const DWARFDebugInfo &) = delete; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFO_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index a08637aef066..1b0fefedf983 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -22,7 +22,6 @@ #include "lldb/Utility/StreamString.h" #include "DWARFCompileUnit.h" -#include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDebugRanges.h" @@ -32,8 +31,11 @@ #include "SymbolFileDWARF.h" #include "SymbolFileDWARFDwo.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" + using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; extern int g_verbose; // Extract a debug info entry for a given DWARFUnit from the data @@ -48,16 +50,12 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, lldbassert(abbr_idx <= UINT16_MAX); m_abbr_idx = abbr_idx; - // assert (fixed_form_sizes); // For best performance this should be - // specified! - if (m_abbr_idx == 0) { m_tag = llvm::dwarf::DW_TAG_null; m_has_children = false; return true; // NULL debug tag entry } - lldb::offset_t offset = *offset_ptr; const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); if (abbrevDecl == nullptr) { cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( @@ -72,137 +70,18 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, m_tag = abbrevDecl->getTag(); m_has_children = abbrevDecl->hasChildren(); // Skip all data in the .debug_info or .debug_types for the attributes - dw_form_t form; for (const auto &attribute : abbrevDecl->attributes()) { - form = attribute.Form; - std::optional<uint8_t> fixed_skip_size = - DWARFFormValue::GetFixedSize(form, cu); - if (fixed_skip_size) - offset += *fixed_skip_size; - else { - bool form_is_indirect = false; - do { - form_is_indirect = false; - uint32_t form_size = 0; - switch (form) { - // Blocks if inlined data that have a length field and the data bytes - // inlined in the .debug_info/.debug_types - case DW_FORM_exprloc: - case DW_FORM_block: - form_size = data.GetULEB128(&offset); - break; - case DW_FORM_block1: - form_size = data.GetU8_unchecked(&offset); - break; - case DW_FORM_block2: - form_size = data.GetU16_unchecked(&offset); - break; - case DW_FORM_block4: - form_size = data.GetU32_unchecked(&offset); - break; - - // Inlined NULL terminated C-strings - case DW_FORM_string: - data.GetCStr(&offset); - break; - - // Compile unit address sized values - case DW_FORM_addr: - form_size = cu->GetAddressByteSize(); - break; - case DW_FORM_ref_addr: - if (cu->GetVersion() <= 2) - form_size = cu->GetAddressByteSize(); - else - form_size = 4; - break; - - // 0 sized form - case DW_FORM_flag_present: - form_size = 0; - break; - - // 1 byte values - case DW_FORM_addrx1: - case DW_FORM_data1: - case DW_FORM_flag: - case DW_FORM_ref1: - case DW_FORM_strx1: - form_size = 1; - break; - - // 2 byte values - case DW_FORM_addrx2: - case DW_FORM_data2: - case DW_FORM_ref2: - case DW_FORM_strx2: - form_size = 2; - break; - - // 3 byte values - case DW_FORM_addrx3: - case DW_FORM_strx3: - form_size = 3; - break; + if (DWARFFormValue::SkipValue(attribute.Form, data, offset_ptr, cu)) + continue; - // 4 byte values - case DW_FORM_addrx4: - case DW_FORM_data4: - case DW_FORM_ref4: - case DW_FORM_strx4: - form_size = 4; - break; - - // 8 byte values - case DW_FORM_data8: - case DW_FORM_ref8: - case DW_FORM_ref_sig8: - form_size = 8; - break; - - // signed or unsigned LEB 128 values - case DW_FORM_addrx: - case DW_FORM_loclistx: - case DW_FORM_rnglistx: - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - case DW_FORM_GNU_addr_index: - case DW_FORM_GNU_str_index: - case DW_FORM_strx: - data.Skip_LEB128(&offset); - break; - - case DW_FORM_indirect: - form_is_indirect = true; - form = static_cast<dw_form_t>(data.GetULEB128(&offset)); - break; - - case DW_FORM_strp: - case DW_FORM_line_strp: - case DW_FORM_sec_offset: - data.GetU32(&offset); - break; - - case DW_FORM_implicit_const: - form_size = 0; - break; - - default: - cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug " - "and " - "attach the file at the start of this error message", - (uint64_t)m_offset, (unsigned)form); - *offset_ptr = m_offset; - return false; - } - offset += form_size; - - } while (form_is_indirect); - } + cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug " + "and " + "attach the file at the start of this error message", + (uint64_t)m_offset, (unsigned)attribute.Form); + *offset_ptr = m_offset; + return false; } - *offset_ptr = offset; return true; } @@ -810,12 +689,13 @@ lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { return GetOffset() + llvm::getULEB128Size(m_abbr_idx); } -const DWARFAbbreviationDeclaration * +const llvm::DWARFAbbreviationDeclaration * DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const { if (!cu) return nullptr; - const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); + const llvm::DWARFAbbreviationDeclarationSet *abbrev_set = + cu->GetAbbreviations(); if (!abbrev_set) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index c2ea40065232..c19fa7428549 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -14,7 +14,6 @@ #include "DWARFAttribute.h" #include "DWARFBaseDIE.h" -#include "DWARFDebugAbbrev.h" #include "DWARFDebugRanges.h" #include <map> #include <optional> @@ -23,6 +22,8 @@ #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +namespace lldb_private::plugin { +namespace dwarf { class DWARFDeclContext; #define DIE_SIBLING_IDX_BITSIZE 31 @@ -48,8 +49,8 @@ public: void BuildFunctionAddressRangeTable(DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const; - bool Extract(const lldb_private::DWARFDataExtractor &data, - const DWARFUnit *cu, lldb::offset_t *offset_ptr); + bool Extract(const DWARFDataExtractor &data, const DWARFUnit *cu, + lldb::offset_t *offset_ptr); using Recurse = DWARFBaseDIE::Recurse; DWARFAttributes GetAttributes(DWARFUnit *cu, @@ -105,13 +106,15 @@ public: const char *GetPubname(const DWARFUnit *cu) const; - bool GetDIENamesAndRanges( - DWARFUnit *cu, const char *&name, const char *&mangled, - DWARFRangeList &rangeList, std::optional<int> &decl_file, - std::optional<int> &decl_line, std::optional<int> &decl_column, - std::optional<int> &call_file, std::optional<int> &call_line, - std::optional<int> &call_column, - lldb_private::DWARFExpressionList *frame_base = nullptr) const; + bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name, + const char *&mangled, DWARFRangeList &rangeList, + std::optional<int> &decl_file, + std::optional<int> &decl_line, + std::optional<int> &decl_column, + std::optional<int> &call_file, + std::optional<int> &call_line, + std::optional<int> &call_column, + DWARFExpressionList *frame_base = nullptr) const; const llvm::DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const; @@ -191,5 +194,7 @@ private: void GetAttributes(DWARFUnit *cu, DWARFAttributes &attrs, Recurse recurse, uint32_t curr_depth) const; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp index 19c6448c4e74..2cd84bc55b75 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -15,6 +15,7 @@ using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; DWARFDebugMacroHeader DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h index cbf762458331..67d1cde8d5de 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -17,11 +17,11 @@ #include "lldb/lldb-types.h" namespace lldb_private { - class DWARFDataExtractor; +} -} // namespace lldb_private - +namespace lldb_private::plugin { +namespace dwarf { class SymbolFileDWARF; class DWARFDebugMacroHeader { @@ -33,15 +33,14 @@ public: }; static DWARFDebugMacroHeader - ParseHeader(const lldb_private::DWARFDataExtractor &debug_macro_data, + ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset); bool OffsetIs64Bit() const { return m_offset_is_64_bit; } private: - static void - SkipOperandTable(const lldb_private::DWARFDataExtractor &debug_macro_data, - lldb::offset_t *offset); + static void SkipOperandTable(const DWARFDataExtractor &debug_macro_data, + lldb::offset_t *offset); uint16_t m_version = 0; bool m_offset_is_64_bit = false; @@ -50,12 +49,14 @@ private: class DWARFDebugMacroEntry { public: - static void - ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data, - const lldb_private::DWARFDataExtractor &debug_str_data, - const bool offset_is_64_bit, lldb::offset_t *sect_offset, - SymbolFileDWARF *sym_file_dwarf, - lldb_private::DebugMacrosSP &debug_macros_sp); + static void ReadMacroEntries(const DWARFDataExtractor &debug_macro_data, + const DWARFDataExtractor &debug_str_data, + const bool offset_is_64_bit, + lldb::offset_t *sect_offset, + SymbolFileDWARF *sym_file_dwarf, + DebugMacrosSP &debug_macros_sp); }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGMACRO_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 0b5bb23a4981..fd8f4e12ff77 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -11,6 +11,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index 2e06cd5daf6f..a04fcf59d5bf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -12,21 +12,23 @@ #include "lldb/Core/dwarf.h" #include <map> +namespace lldb_private::plugin { +namespace dwarf { class DWARFUnit; -namespace lldb_private { class DWARFContext; -} class DWARFDebugRanges { public: DWARFDebugRanges(); - void Extract(lldb_private::DWARFContext &context); + void Extract(DWARFContext &context); DWARFRangeList FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset) const; protected: std::map<dw_offset_t, DWARFRangeList> m_range_map; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGRANGES_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp index 393de0038e65..44421c0eda3e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp @@ -7,8 +7,26 @@ //===----------------------------------------------------------------------===// #include "DWARFDeclContext.h" +#include "llvm/Support/raw_ostream.h" using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; + +/// Returns the name of `entry` if it has one, or the appropriate "anonymous +/// {namespace, class, struct, union}". +static const char *GetName(DWARFDeclContext::Entry entry) { + if (entry.name != nullptr) + return entry.name; + if (entry.tag == DW_TAG_namespace) + return "(anonymous namespace)"; + if (entry.tag == DW_TAG_class_type) + return "(anonymous class)"; + if (entry.tag == DW_TAG_structure_type) + return "(anonymous struct)"; + if (entry.tag == DW_TAG_union_type) + return "(anonymous union)"; + return "(anonymous)"; +} const char *DWARFDeclContext::GetQualifiedName() const { if (m_qualified_name.empty()) { @@ -25,26 +43,10 @@ const char *DWARFDeclContext::GetQualifiedName() const { m_qualified_name.append(m_entries[0].name); } } else { - collection::const_reverse_iterator pos; - collection::const_reverse_iterator begin = m_entries.rbegin(); - collection::const_reverse_iterator end = m_entries.rend(); - for (pos = begin; pos != end; ++pos) { - if (pos != begin) - m_qualified_name.append("::"); - if (pos->name == nullptr) { - if (pos->tag == DW_TAG_namespace) - m_qualified_name.append("(anonymous namespace)"); - else if (pos->tag == DW_TAG_class_type) - m_qualified_name.append("(anonymous class)"); - else if (pos->tag == DW_TAG_structure_type) - m_qualified_name.append("(anonymous struct)"); - else if (pos->tag == DW_TAG_union_type) - m_qualified_name.append("(anonymous union)"); - else - m_qualified_name.append("(anonymous)"); - } else - m_qualified_name.append(pos->name); - } + llvm::raw_string_ostream string_stream(m_qualified_name); + llvm::interleave( + llvm::reverse(m_entries), string_stream, + [&](auto entry) { string_stream << GetName(entry); }, "::"); } } } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 13e3dfb70c0c..a20a862d3402 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -16,6 +16,8 @@ #include <string> #include <vector> +namespace lldb_private::plugin { +namespace dwarf { // DWARFDeclContext // // A class that represents a declaration context all the way down to a @@ -68,8 +70,8 @@ public: // Same as GetQualifiedName, but the life time of the returned string will // be that of the LLDB session. - lldb_private::ConstString GetQualifiedNameAsConstString() const { - return lldb_private::ConstString(GetQualifiedName()); + ConstString GetQualifiedNameAsConstString() const { + return ConstString(GetQualifiedName()); } void Clear() { @@ -82,5 +84,7 @@ protected: collection m_entries; mutable std::string m_qualified_name; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp index 4e99a295ce50..9a88aed85e97 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -12,7 +12,8 @@ #include <cstring> #include <string> -namespace lldb_private { +namespace lldb_private::plugin { +namespace dwarf { const char *DW_TAG_value_to_name(uint32_t val) { static char invalid[100]; @@ -88,4 +89,5 @@ const char *DW_LNS_value_to_name(uint32_t val) { return llvmstr.data(); } -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h index 2afdbb47381a..3ed92cc203bf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h @@ -12,7 +12,8 @@ #include "lldb/Core/dwarf.h" #include <cstdint> -namespace lldb_private { +namespace lldb_private::plugin { +namespace dwarf { typedef uint32_t DRC_class; // Holds DRC_* class bitfields @@ -30,6 +31,7 @@ const char *DW_LANG_value_to_name(uint32_t val); const char *DW_LNS_value_to_name(uint32_t val); -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEFINES_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 6ca17dcf47ff..0a7029a55c04 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -22,6 +22,7 @@ class DWARFUnit; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; void DWARFFormValue::Clear() { m_unit = nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 2a8843c1a0d4..445749a6aac3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -13,6 +13,8 @@ #include <cstddef> #include <optional> +namespace lldb_private::plugin { +namespace dwarf { class DWARFUnit; class SymbolFileDWARF; class DWARFDIE; @@ -51,9 +53,8 @@ public: ValueType &ValueRef() { return m_value; } void SetValue(const ValueType &val) { m_value = val; } - void Dump(lldb_private::Stream &s) const; - bool ExtractValue(const lldb_private::DWARFDataExtractor &data, - lldb::offset_t *offset_ptr); + void Dump(Stream &s) const; + bool ExtractValue(const DWARFDataExtractor &data, lldb::offset_t *offset_ptr); const uint8_t *BlockData() const; static std::optional<uint8_t> GetFixedSize(dw_form_t form, const DWARFUnit *u); @@ -68,10 +69,10 @@ public: const char *AsCString() const; dw_addr_t Address() const; bool IsValid() const { return m_form != 0; } - bool SkipValue(const lldb_private::DWARFDataExtractor &debug_info_data, + bool SkipValue(const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr) const; static bool SkipValue(const dw_form_t form, - const lldb_private::DWARFDataExtractor &debug_info_data, + const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr, const DWARFUnit *unit); static bool IsBlockForm(const dw_form_t form); static bool IsDataForm(const dw_form_t form); @@ -84,7 +85,9 @@ protected: // It may be different from compile unit where m_value refers to. const DWARFUnit *m_unit = nullptr; // Unit for this form dw_form_t m_form = dw_form_t(0); // Form for this value - ValueType m_value; // Contains all data for the form + ValueType m_value; // Contains all data for the form }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFFORMVALUE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp index 779b52481b85..b1c323b101ce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -17,6 +17,7 @@ using namespace lldb_private; using namespace lldb; +using namespace lldb_private::plugin::dwarf; DWARFIndex::~DWARFIndex() = default; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h index 13fe96dae2aa..9aadeddbb217 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -17,10 +17,11 @@ #include "lldb/Core/Module.h" #include "lldb/Target/Statistics.h" +namespace lldb_private::plugin { +namespace dwarf { class DWARFDeclContext; class DWARFDIE; -namespace lldb_private { class DWARFIndex { public: DWARFIndex(Module &module) : m_module(module) {} @@ -102,6 +103,7 @@ protected: void ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const; }; -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFINDEX_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp index 87af7177ca95..4f3a3f544653 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp @@ -13,6 +13,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; void DWARFTypeUnit::Dump(Stream *s) const { s->Format("{0:x16}: Type Unit: length = {1:x8}, version = {2:x4}, " diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h index 5e4d48ab285a..7b58c632c6c5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h @@ -12,11 +12,17 @@ #include "DWARFUnit.h" #include "llvm/Support/Error.h" +namespace llvm { +class DWARFAbbreviationDeclarationSet; +} // namespace llvm + +namespace lldb_private::plugin { +namespace dwarf { class DWARFTypeUnit : public DWARFUnit { public: void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override {} - void Dump(lldb_private::Stream *s) const override; + void Dump(Stream *s) const override; uint64_t GetTypeHash() { return m_header.GetTypeHash(); } @@ -27,11 +33,13 @@ public: private: DWARFTypeUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs, + const llvm::DWARFAbbreviationDeclarationSet &abbrevs, DIERef::Section section, bool is_dwo) : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {} friend class DWARFUnit; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFTYPEUNIT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 749ffcb094ec..0e2f4d45543b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -13,6 +13,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Object/Error.h" @@ -27,12 +28,13 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; extern int g_verbose; DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs, + const llvm::DWARFAbbreviationDeclarationSet &abbrevs, DIERef::Section section, bool is_dwo) : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs), m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo), @@ -200,8 +202,8 @@ DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs) rhs.m_cu = nullptr; } -DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=( - DWARFUnit::ScopedExtractDIEs &&rhs) { +DWARFUnit::ScopedExtractDIEs & +DWARFUnit::ScopedExtractDIEs::operator=(DWARFUnit::ScopedExtractDIEs &&rhs) { m_cu = rhs.m_cu; rhs.m_cu = nullptr; m_clear_dies = rhs.m_clear_dies; @@ -310,9 +312,9 @@ void DWARFUnit::ExtractDIEsRWLocked() { } if (!m_die_array.empty()) { - // The last die cannot have children (if it did, it wouldn't be the last one). - // This only makes a difference for malformed dwarf that does not have a - // terminating null die. + // The last die cannot have children (if it did, it wouldn't be the last + // one). This only makes a difference for malformed dwarf that does not have + // a terminating null die. m_die_array.back().SetHasChildren(false); if (m_first_die) { @@ -435,7 +437,8 @@ size_t DWARFUnit::GetDebugInfoSize() const { return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); } -const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { +const llvm::DWARFAbbreviationDeclarationSet * +DWARFUnit::GetAbbreviations() const { return m_abbrevs; } @@ -718,7 +721,7 @@ void DWARFUnit::ParseProducerInfo() { llvm::SmallVector<llvm::StringRef, 3> matches; if (g_swiftlang_version_regex.Execute(producer, &matches)) { - m_producer_version.tryParse(matches[1]); + m_producer_version.tryParse(matches[1]); m_producer = eProducerSwift; } else if (producer.contains("clang")) { if (g_clang_version_regex.Execute(producer, &matches)) @@ -806,7 +809,7 @@ removeHostnameFromPathname(llvm::StringRef path_from_dwarf) { // check whether we have a windows path, and so the first character is a // drive-letter not a hostname. if (host.size() == 1 && llvm::isAlpha(host[0]) && - (path.startswith("\\") || path.startswith("/"))) + (path.starts_with("\\") || path.starts_with("/"))) return path_from_dwarf; return path; @@ -875,10 +878,37 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { return *m_func_aranges_up; } +llvm::Error DWARFUnitHeader::ApplyIndexEntry( + const llvm::DWARFUnitIndex::Entry *index_entry) { + // We should only be calling this function when the index entry is not set and + // we have a valid one to set it to. + assert(index_entry); + assert(!m_index_entry); + + if (m_abbr_offset) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Package unit with a non-zero abbreviation offset"); + + auto *unit_contrib = index_entry->getContribution(); + if (!unit_contrib || unit_contrib->getLength32() != m_length + 4) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Inconsistent DWARF package unit index"); + + auto *abbr_entry = index_entry->getContribution(llvm::DW_SECT_ABBREV); + if (!abbr_entry) + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "DWARF package index missing abbreviation column"); + + m_abbr_offset = abbr_entry->getOffset(); + m_index_entry = index_entry; + return llvm::Error::success(); +} + llvm::Expected<DWARFUnitHeader> DWARFUnitHeader::extract(const DWARFDataExtractor &data, - DIERef::Section section, - lldb_private::DWARFContext &context, + DIERef::Section section, DWARFContext &context, lldb::offset_t *offset_ptr) { DWARFUnitHeader header; header.m_offset = *offset_ptr; @@ -903,42 +933,6 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, header.m_type_offset = data.GetDWARFOffset(offset_ptr); } - if (context.isDwo()) { - const llvm::DWARFUnitIndex *Index; - if (header.IsTypeUnit()) { - Index = &context.GetAsLLVM().getTUIndex(); - if (*Index) - header.m_index_entry = Index->getFromHash(header.m_type_hash); - } else { - Index = &context.GetAsLLVM().getCUIndex(); - if (*Index && header.m_version >= 5 && header.m_dwo_id) - header.m_index_entry = Index->getFromHash(*header.m_dwo_id); - } - if (!header.m_index_entry) - header.m_index_entry = Index->getFromOffset(header.m_offset); - } - - if (header.m_index_entry) { - if (header.m_abbr_offset) { - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "Package unit with a non-zero abbreviation offset"); - } - auto *unit_contrib = header.m_index_entry->getContribution(); - if (!unit_contrib || unit_contrib->getLength32() != header.m_length + 4) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Inconsistent DWARF package unit index"); - } - auto *abbr_entry = - header.m_index_entry->getContribution(llvm::DW_SECT_ABBREV); - if (!abbr_entry) { - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "DWARF package index missing abbreviation column"); - } - header.m_abbr_offset = abbr_entry->getOffset(); - } - bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version); bool addr_size_OK = (header.m_addr_size == 2) || (header.m_addr_size == 4) || @@ -968,12 +962,31 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, DIERef::Section section, lldb::offset_t *offset_ptr) { assert(debug_info.ValidOffset(*offset_ptr)); - auto expected_header = DWARFUnitHeader::extract( - debug_info, section, dwarf.GetDWARFContext(), offset_ptr); + DWARFContext &context = dwarf.GetDWARFContext(); + auto expected_header = + DWARFUnitHeader::extract(debug_info, section, context, offset_ptr); if (!expected_header) return expected_header.takeError(); - const DWARFDebugAbbrev *abbr = dwarf.DebugAbbrev(); + if (context.isDwo()) { + const llvm::DWARFUnitIndex::Entry *entry = nullptr; + const llvm::DWARFUnitIndex &index = expected_header->IsTypeUnit() + ? context.GetAsLLVM().getTUIndex() + : context.GetAsLLVM().getCUIndex(); + if (index) { + if (expected_header->IsTypeUnit()) + entry = index.getFromHash(expected_header->GetTypeHash()); + else if (auto dwo_id = expected_header->GetDWOId()) + entry = index.getFromHash(*dwo_id); + } + if (!entry) + entry = index.getFromOffset(expected_header->GetOffset()); + if (entry) + if (llvm::Error err = expected_header->ApplyIndexEntry(entry)) + return std::move(err); + } + + const llvm::DWARFDebugAbbrev *abbr = dwarf.DebugAbbrev(); if (!abbr) return llvm::make_error<llvm::object::GenericBinaryError>( "No debug_abbrev data"); @@ -985,8 +998,12 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, return llvm::make_error<llvm::object::GenericBinaryError>( "Abbreviation offset for unit is not valid"); - const DWARFAbbreviationDeclarationSet *abbrevs = - abbr->GetAbbreviationDeclarationSet(expected_header->GetAbbrOffset()); + llvm::Expected<const llvm::DWARFAbbreviationDeclarationSet *> abbrevs_or_err = + abbr->getAbbreviationDeclarationSet(expected_header->GetAbbrOffset()); + if (!abbrevs_or_err) + return abbrevs_or_err.takeError(); + + const llvm::DWARFAbbreviationDeclarationSet *abbrevs = *abbrevs_or_err; if (!abbrevs) return llvm::make_error<llvm::object::GenericBinaryError>( "No abbrev exists at the specified offset."); @@ -1071,22 +1088,20 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { return ranges; } -llvm::Expected<DWARFRangeList> -DWARFUnit::FindRnglistFromIndex(uint32_t index) { +llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) { llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index); if (!maybe_offset) return maybe_offset.takeError(); return FindRnglistFromOffset(*maybe_offset); } - bool DWARFUnit::HasAny(llvm::ArrayRef<dw_tag_t> tags) { ExtractUnitDIEIfNeeded(); if (m_dwo) return m_dwo->HasAny(tags); - for (const auto &die: m_die_array) { - for (const auto tag: tags) { + for (const auto &die : m_die_array) { + for (const auto tag : tags) { if (tag == die.Tag()) return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index bc55b093e894..3f528e913d8c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -13,11 +13,14 @@ #include "DWARFDebugInfoEntry.h" #include "lldb/Utility/XcodeSDK.h" #include "lldb/lldb-enumerations.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/Support/RWMutex.h" #include <atomic> #include <optional> +namespace lldb_private::plugin { +namespace dwarf { class DWARFUnit; class DWARFCompileUnit; class NameToDIE; @@ -73,23 +76,25 @@ public: return m_unit_type == llvm::dwarf::DW_UT_type || m_unit_type == llvm::dwarf::DW_UT_split_type; } - uint32_t GetNextUnitOffset() const { return m_offset + m_length + 4; } + dw_offset_t GetNextUnitOffset() const { return m_offset + m_length + 4; } - static llvm::Expected<DWARFUnitHeader> - extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section, - lldb_private::DWARFContext &dwarf_context, - lldb::offset_t *offset_ptr); + llvm::Error ApplyIndexEntry(const llvm::DWARFUnitIndex::Entry *index_entry); + + static llvm::Expected<DWARFUnitHeader> extract(const DWARFDataExtractor &data, + DIERef::Section section, + DWARFContext &dwarf_context, + lldb::offset_t *offset_ptr); }; -class DWARFUnit : public lldb_private::UserID { +class DWARFUnit : public UserID { using die_iterator_range = llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>; public: static llvm::Expected<DWARFUnitSP> extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid, - const lldb_private::DWARFDataExtractor &debug_info, - DIERef::Section section, lldb::offset_t *offset_ptr); + const DWARFDataExtractor &debug_info, DIERef::Section section, + lldb::offset_t *offset_ptr); virtual ~DWARFUnit(); bool IsDWOUnit() { return m_is_dwo; } @@ -101,6 +106,7 @@ public: class ScopedExtractDIEs { DWARFUnit *m_cu; + public: bool m_clear_dies = false; ScopedExtractDIEs(DWARFUnit &cu); @@ -112,8 +118,8 @@ public: }; ScopedExtractDIEs ExtractDIEsScoped(); - bool Verify(lldb_private::Stream *s) const; - virtual void Dump(lldb_private::Stream *s) const = 0; + bool Verify(Stream *s) const; + virtual void Dump(Stream *s) const = 0; /// Get the data that contains the DIE information for this unit. /// /// This will return the correct bytes that contain the data for @@ -122,7 +128,7 @@ public: /// /// \return /// The correct data for the DIE information in this unit. - const lldb_private::DWARFDataExtractor &GetData() const; + const DWARFDataExtractor &GetData() const; /// Get the size in bytes of the unit header. /// @@ -151,9 +157,9 @@ public: // Size of the CU data (without initial length and without header). size_t GetDebugInfoSize() const; // Size of the CU data incl. header but without initial length. - uint32_t GetLength() const { return m_header.GetLength(); } + dw_offset_t GetLength() const { return m_header.GetLength(); } uint16_t GetVersion() const { return m_header.GetVersion(); } - const DWARFAbbreviationDeclarationSet *GetAbbreviations() const; + const llvm::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.value_or(0); } @@ -207,10 +213,10 @@ public: bool GetIsOptimized(); - const lldb_private::FileSpec &GetCompilationDirectory(); - const lldb_private::FileSpec &GetAbsolutePath(); - lldb_private::FileSpec GetFile(size_t file_idx); - lldb_private::FileSpec::Style GetPathStyle(); + const FileSpec &GetCompilationDirectory(); + const FileSpec &GetAbsolutePath(); + FileSpec GetFile(size_t file_idx); + FileSpec::Style GetPathStyle(); SymbolFileDWARFDwo *GetDwoSymbolFile(); @@ -224,7 +230,9 @@ public: uint8_t GetUnitType() const { return m_header.GetUnitType(); } bool IsTypeUnit() const { return m_header.IsTypeUnit(); } /// Note that this check only works for DWARF5+. - bool IsSkeletonUnit() const { return GetUnitType() == llvm::dwarf::DW_UT_skeleton; } + bool IsSkeletonUnit() const { + return GetUnitType() == llvm::dwarf::DW_UT_skeleton; + } std::optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const; @@ -256,9 +264,9 @@ public: /// Return the location table for parsing the given location list data. The /// format is chosen according to the unit type. Never returns null. std::unique_ptr<llvm::DWARFLocationTable> - GetLocationTable(const lldb_private::DataExtractor &data) const; + GetLocationTable(const DataExtractor &data) const; - lldb_private::DWARFDataExtractor GetLocationData() const; + DWARFDataExtractor GetLocationData() const; /// Returns true if any DIEs in the unit match any DW_TAG values in \a tags. /// @@ -269,7 +277,6 @@ public: /// True if any DIEs match any tag in \a tags, false otherwise. bool HasAny(llvm::ArrayRef<dw_tag_t> tags); - /// Get the fission .dwo file specific error for this compile unit. /// /// The skeleton compile unit only can have a DWO error. Any other type @@ -278,7 +285,7 @@ public: /// \returns /// A valid DWO error if there is a problem with anything in the /// locating or parsing inforamtion in the .dwo file - const lldb_private::Status &GetDwoError() const { return m_dwo_error; } + const Status &GetDwoError() const { return m_dwo_error; } /// Set the fission .dwo file specific error for this compile unit. /// @@ -286,16 +293,16 @@ public: /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other /// .dwo errors can be stored in each compile unit so the issues can be /// communicated to the user. - void SetDwoError(const lldb_private::Status &error) { m_dwo_error = error; } + void SetDwoError(const Status &error) { m_dwo_error = error; } protected: DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, - const DWARFAbbreviationDeclarationSet &abbrevs, + const llvm::DWARFAbbreviationDeclarationSet &abbrevs, DIERef::Section section, bool is_dwo); llvm::Error ExtractHeader(SymbolFileDWARF &dwarf, - const lldb_private::DWARFDataExtractor &data, + const DWARFDataExtractor &data, lldb::offset_t *offset_ptr); // Get the DWARF unit DWARF debug information entry. Parse the single DIE @@ -318,12 +325,12 @@ protected: const std::optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable(); - lldb_private::DWARFDataExtractor GetRnglistData() const; + DWARFDataExtractor GetRnglistData() const; SymbolFileDWARF &m_dwarf; std::shared_ptr<DWARFUnit> m_dwo; DWARFUnitHeader m_header; - const DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr; + const llvm::DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr; void *m_user_data = nullptr; // The compile unit debug information entry item DWARFDebugInfoEntry::collection m_die_array; @@ -345,12 +352,12 @@ protected: DWARFProducer m_producer = eProducerInvalid; llvm::VersionTuple m_producer_version; std::optional<uint64_t> m_language_type; - lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; - std::optional<lldb_private::FileSpec> m_comp_dir; - std::optional<lldb_private::FileSpec> m_file_spec; - std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base. - dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base. - dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base. + LazyBool m_is_optimized = eLazyBoolCalculate; + std::optional<FileSpec> m_comp_dir; + std::optional<FileSpec> m_file_spec; + std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base. + dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base. + dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base. std::optional<uint64_t> m_gnu_addr_base; std::optional<uint64_t> m_gnu_ranges_base; @@ -371,7 +378,7 @@ protected: /// If we get an error when trying to load a .dwo file, save that error here. /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found /// but DWO ID doesn't match, etc. - lldb_private::Status m_dwo_error; + Status m_dwo_error; private: void ParseProducerInfo(); @@ -387,5 +394,7 @@ private: DWARFUnit(const DWARFUnit &) = delete; const DWARFUnit &operator=(const DWARFUnit &) = delete; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index af2d6c554140..7c253553d57b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -18,6 +18,7 @@ using namespace lldb_private; using namespace lldb; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, @@ -36,19 +37,29 @@ llvm::DenseSet<dw_offset_t> DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { llvm::DenseSet<dw_offset_t> result; for (const DebugNames::NameIndex &ni : debug_names) { - for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu) + const uint32_t num_cus = ni.getCUCount(); + for (uint32_t cu = 0; cu < num_cus; ++cu) result.insert(ni.getCUOffset(cu)); + const uint32_t num_tus = ni.getLocalTUCount(); + for (uint32_t tu = 0; tu < num_tus; ++tu) + result.insert(ni.getLocalTUOffset(tu)); } return result; } std::optional<DIERef> DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) { - std::optional<uint64_t> cu_offset = entry.getCUOffset(); - if (!cu_offset) - return std::nullopt; + // Look for a DWARF unit offset (CU offset or local TU offset) as they are + // both offsets into the .debug_info section. + std::optional<uint64_t> unit_offset = entry.getCUOffset(); + if (!unit_offset) { + unit_offset = entry.getLocalTUOffset(); + if (!unit_offset) + return std::nullopt; + } - DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset); + DWARFUnit *cu = + m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *unit_offset); if (!cu) return std::nullopt; @@ -128,8 +139,19 @@ void DebugNamesDWARFIndex::GetGlobalVariables( DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) { uint64_t cu_offset = cu.GetOffset(); bool found_entry_for_cu = false; - for (const DebugNames::NameIndex &ni: *m_debug_names_up) { - for (DebugNames::NameTableEntry nte: ni) { + for (const DebugNames::NameIndex &ni : *m_debug_names_up) { + // Check if this name index contains an entry for the given CU. + bool cu_matches = false; + for (uint32_t i = 0; i < ni.getCUCount(); ++i) { + if (ni.getCUOffset(i) == cu_offset) { + cu_matches = true; + break; + } + } + if (!cu_matches) + continue; + + for (DebugNames::NameTableEntry nte : ni) { uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { @@ -227,7 +249,7 @@ void DebugNamesDWARFIndex::GetNamespaces( ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) { for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name.GetStringRef())) { - dwarf::Tag entry_tag = entry.tag(); + lldb_private::dwarf::Tag entry_tag = entry.tag(); if (entry_tag == DW_TAG_namespace || entry_tag == DW_TAG_imported_declaration) { if (!ProcessEntry(entry, callback)) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h index abbd700f1603..7ce630a56137 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -17,7 +17,8 @@ #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include <optional> -namespace lldb_private { +namespace lldb_private::plugin { +namespace dwarf { class DebugNamesDWARFIndex : public DWARFIndex { public: static llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> @@ -89,6 +90,7 @@ private: static llvm::DenseSet<dw_offset_t> GetUnits(const DebugNames &debug_names); }; -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DEBUGNAMESDWARFINDEX_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index 57b962ff60df..16ff5f7d4842 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -28,6 +28,7 @@ using namespace lldb_private; using namespace lldb; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; void ManualDWARFIndex::Index() { if (m_indexed) @@ -654,7 +655,7 @@ void ManualDWARFIndex::IndexSet::Encode(DataEncoder &encoder) const { // Now that all strings have been gathered, we will emit the string table. strtab.Encode(encoder); - // Followed the the symbol table data. + // Followed by the symbol table data. encoder.AppendData(index_encoder.GetData()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index d95cf501face..0126e587e52d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -13,10 +13,11 @@ #include "Plugins/SymbolFile/DWARF/NameToDIE.h" #include "llvm/ADT/DenseSet.h" +namespace lldb_private::plugin { +namespace dwarf { class DWARFDebugInfo; class SymbolFileDWARFDwo; -namespace lldb_private { class ManualDWARFIndex : public DWARFIndex { public: ManualDWARFIndex(Module &module, SymbolFileDWARF &dwarf, @@ -173,6 +174,7 @@ private: IndexSet m_set; bool m_indexed = false; }; -} // namespace lldb_private +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_MANUALDWARFINDEX_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index 89e628f5eaf1..44d90648700c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -20,6 +20,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; void NameToDIE::Finalize() { m_map.Sort(std::less<DIERef>()); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h index 61df1a628ab5..90eac1fa3733 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -16,6 +16,8 @@ #include "lldb/Core/dwarf.h" #include "lldb/lldb-defines.h" +namespace lldb_private::plugin { +namespace dwarf { class DWARFUnit; class NameToDIE { @@ -24,18 +26,18 @@ public: ~NameToDIE() = default; - void Dump(lldb_private::Stream *s); + void Dump(Stream *s); - void Insert(lldb_private::ConstString name, const DIERef &die_ref); + void Insert(ConstString name, const DIERef &die_ref); void Append(const NameToDIE &other); void Finalize(); - bool Find(lldb_private::ConstString name, + bool Find(ConstString name, llvm::function_ref<bool(DIERef ref)> callback) const; - bool Find(const lldb_private::RegularExpression ®ex, + bool Find(const RegularExpression ®ex, llvm::function_ref<bool(DIERef ref)> callback) const; /// \a unit must be the skeleton unit if possible, not GetNonSkeletonUnit(). @@ -44,8 +46,7 @@ public: llvm::function_ref<bool(DIERef ref)> callback) const; void - ForEach(std::function<bool(lldb_private::ConstString name, - const DIERef &die_ref)> const + ForEach(std::function<bool(ConstString name, const DIERef &die_ref)> const &callback) const; /// Decode a serialized version of this object from data. @@ -61,9 +62,8 @@ public: /// All strings in cache files are put into string tables for efficiency /// and cache file size reduction. Strings are stored as uint32_t string /// table offsets in the cache data. - bool Decode(const lldb_private::DataExtractor &data, - lldb::offset_t *offset_ptr, - const lldb_private::StringTableReader &strtab); + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + const StringTableReader &strtab); /// Encode this object into a data encoder object. /// @@ -76,8 +76,7 @@ public: /// All strings in cache files are put into string tables for efficiency /// and cache file size reduction. Strings are stored as uint32_t string /// table offsets in the cache data. - void Encode(lldb_private::DataEncoder &encoder, - lldb_private::ConstStringTable &strtab) const; + void Encode(DataEncoder &encoder, ConstStringTable &strtab) const; /// Used for unit testing the encoding and decoding. bool operator==(const NameToDIE &rhs) const; @@ -87,7 +86,9 @@ public: void Clear() { m_map.Clear(); } protected: - lldb_private::UniqueCStringMap<DIERef> m_map; + UniqueCStringMap<DIERef> m_map; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_NAMETODIE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 6e5482dba9d2..505ea29ca4d4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Format.h" #include "llvm/Support/Threading.h" #include "lldb/Core/Module.h" @@ -18,13 +19,13 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/Utility/Timer.h" #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" @@ -45,7 +46,6 @@ #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/LineTable.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeMap.h" @@ -59,7 +59,6 @@ #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" #include "DWARFCompileUnit.h" -#include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDebugMacro.h" @@ -75,6 +74,7 @@ #include "SymbolFileDWARFDwo.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" @@ -98,6 +98,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; LLDB_PLUGIN_DEFINE(SymbolFileDWARF) @@ -115,8 +116,8 @@ enum { class PluginProperties : public Properties { public: - static ConstString GetSettingName() { - return ConstString(SymbolFileDWARF::GetPluginNameStatic()); + static llvm::StringRef GetSettingName() { + return SymbolFileDWARF::GetPluginNameStatic(); } PluginProperties() { @@ -131,15 +132,19 @@ public: } // namespace +bool IsStructOrClassTag(llvm::dwarf::Tag Tag) { + return Tag == llvm::dwarf::Tag::DW_TAG_class_type || + Tag == llvm::dwarf::Tag::DW_TAG_structure_type; +} + static PluginProperties &GetGlobalPluginProperties() { static PluginProperties g_settings; return g_settings; } static const llvm::DWARFDebugLine::LineTable * -ParseLLVMLineTable(lldb_private::DWARFContext &context, - llvm::DWARFDebugLine &line, dw_offset_t line_offset, - dw_offset_t unit_offset) { +ParseLLVMLineTable(DWARFContext &context, llvm::DWARFDebugLine &line, + dw_offset_t line_offset, dw_offset_t unit_offset) { Log *log = GetLog(DWARFLog::DebugInfo); llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVMDWARF(); @@ -160,7 +165,7 @@ ParseLLVMLineTable(lldb_private::DWARFContext &context, return *line_table; } -static bool ParseLLVMLineTablePrologue(lldb_private::DWARFContext &context, +static bool ParseLLVMLineTablePrologue(DWARFContext &context, llvm::DWARFDebugLine::Prologue &prologue, dw_offset_t line_offset, dw_offset_t unit_offset) { @@ -210,17 +215,24 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, FileSpec::Style style, llvm::StringRef compile_dir = {}) { FileSpecList support_files; - size_t first_file = 0; - if (prologue.getVersion() <= 4) { - // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure - // support file list indices match those we get from the debug info and line - // tables. + + // Handle the case where there are no files first to avoid having to special + // case this later. + if (prologue.FileNames.empty()) + return support_files; + + // Before DWARF v5, the line table indexes were one based. + const bool is_one_based = prologue.getVersion() < 5; + const size_t file_names = prologue.FileNames.size(); + const size_t first_file_idx = is_one_based ? 1 : 0; + const size_t last_file_idx = is_one_based ? file_names : file_names - 1; + + // Add a dummy entry to ensure the support file list indices match those we + // get from the debug info and line tables. + if (is_one_based) support_files.Append(FileSpec()); - first_file = 1; - } - const size_t number_of_files = prologue.FileNames.size(); - for (size_t idx = first_file; idx <= number_of_files; ++idx) { + for (size_t idx = first_file_idx; idx <= last_file_idx; ++idx) { std::string remapped_file; if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) { if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path))) @@ -229,8 +241,15 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, remapped_file = std::move(*file_path); } + Checksum checksum; + if (prologue.ContentTypes.HasMD5) { + const llvm::DWARFDebugLine::FileNameEntry &file_name_entry = + prologue.getFileNameEntry(idx); + checksum = file_name_entry.Checksum; + } + // Unconditionally add an entry, so the indices match up. - support_files.EmplaceBack(remapped_file, style); + support_files.EmplaceBack(remapped_file, style, checksum); } return support_files; @@ -512,6 +531,21 @@ bool SymbolFileDWARF::SupportedVersion(uint16_t version) { return version >= 2 && version <= 5; } +static std::set<dw_form_t> +GetUnsupportedForms(llvm::DWARFDebugAbbrev *debug_abbrev) { + if (!debug_abbrev) + return {}; + + std::set<dw_form_t> unsupported_forms; + for (const auto &[_, decl_set] : *debug_abbrev) + for (const auto &decl : decl_set) + for (const auto &attr : decl.attributes()) + if (!DWARFFormValue::FormIsSupported(attr.Form)) + unsupported_forms.insert(attr.Form); + + return unsupported_forms; +} + uint32_t SymbolFileDWARF::CalculateAbilities() { uint32_t abilities = 0; if (m_objfile_sp != nullptr) { @@ -540,20 +574,16 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { if (section) debug_abbrev_file_size = section->GetFileSize(); - DWARFDebugAbbrev *abbrev = DebugAbbrev(); - if (abbrev) { - std::set<dw_form_t> invalid_forms; - abbrev->GetUnsupportedForms(invalid_forms); - if (!invalid_forms.empty()) { - StreamString error; - error.Printf("unsupported DW_FORM value%s:", - invalid_forms.size() > 1 ? "s" : ""); - for (auto form : invalid_forms) - error.Printf(" %#x", form); - m_objfile_sp->GetModule()->ReportWarning( - "{0}", error.GetString().str().c_str()); - return 0; - } + llvm::DWARFDebugAbbrev *abbrev = DebugAbbrev(); + std::set<dw_form_t> unsupported_forms = GetUnsupportedForms(abbrev); + if (!unsupported_forms.empty()) { + StreamString error; + error.Printf("unsupported DW_FORM value%s:", + unsupported_forms.size() > 1 ? "s" : ""); + for (auto form : unsupported_forms) + error.Printf(" %#x", form); + m_objfile_sp->GetModule()->ReportWarning("{0}", error.GetString()); + return 0; } section = @@ -615,7 +645,7 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, m_objfile_sp->ReadSectionData(section_sp.get(), data); } -DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { +llvm::DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (m_abbr) return m_abbr.get(); @@ -623,8 +653,9 @@ DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (debug_abbrev_data.GetByteSize() == 0) return nullptr; - auto abbr = std::make_unique<DWARFDebugAbbrev>(); - llvm::Error error = abbr->parse(debug_abbrev_data); + auto abbr = + std::make_unique<llvm::DWARFDebugAbbrev>(debug_abbrev_data.GetAsLLVM()); + llvm::Error error = abbr->parse(); if (error) { Log *log = GetLog(DWARFLog::DebugInfo); LLDB_LOG_ERROR(log, std::move(error), @@ -1441,6 +1472,17 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { return CompilerDeclContext(); } +std::vector<CompilerContext> +SymbolFileDWARF::GetCompilerContextForUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + // Anytime we have a lldb::user_id_t, we must get the DIE by calling + // SymbolFileDWARF::GetDIE(). See comments inside the + // SymbolFileDWARF::GetDIE() for details. + if (DWARFDIE die = GetDIE(type_uid)) + return die.GetDeclContext(); + return {}; +} + Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling @@ -1508,11 +1550,11 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, // This function is used when SymbolFileDWARFDebugMap owns a bunch of // SymbolFileDWARF objects to detect if this DWARF file is the one that can // resolve a compiler_type. -bool SymbolFileDWARF::HasForwardDeclForClangType( +bool SymbolFileDWARF::HasForwardDeclForCompilerType( const CompilerType &compiler_type) { CompilerType compiler_type_no_qualifiers = ClangUtil::RemoveFastQualifiers(compiler_type); - if (GetForwardDeclClangTypeToDie().count( + if (GetForwardDeclCompilerTypeToDIE().count( compiler_type_no_qualifiers.GetOpaqueQualType())) { return true; } @@ -1540,9 +1582,9 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { // We have a struct/union/class/enum that needs to be fully resolved. CompilerType compiler_type_no_qualifiers = ClangUtil::RemoveFastQualifiers(compiler_type); - auto die_it = GetForwardDeclClangTypeToDie().find( + auto die_it = GetForwardDeclCompilerTypeToDIE().find( compiler_type_no_qualifiers.GetOpaqueQualType()); - if (die_it == GetForwardDeclClangTypeToDie().end()) { + if (die_it == GetForwardDeclCompilerTypeToDIE().end()) { // We have already resolved this type... return true; } @@ -1553,7 +1595,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { // declaration map in case anyone child members or other types require this // type to get resolved. The type will get resolved when all of the calls // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done. - GetForwardDeclClangTypeToDie().erase(die_it); + GetForwardDeclCompilerTypeToDIE().erase(die_it); Type *type = GetDIEToType().lookup(dwarf_die.GetDIE()); @@ -1729,38 +1771,129 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile()) return dwp_sp; - const char *comp_dir = nullptr; FileSpec dwo_file(dwo_name); FileSystem::Instance().Resolve(dwo_file); - if (dwo_file.IsRelative()) { - comp_dir = cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, - nullptr); - if (!comp_dir) { - unit.SetDwoError(Status::createWithFormat( - "unable to locate relative .dwo debug file \"{0}\" for " - "skeleton DIE {1:x16} without valid DW_AT_comp_dir " - "attribute", - dwo_name, cu_die.GetOffset())); - return nullptr; + bool found = false; + + const FileSpecList &debug_file_search_paths = + Target::GetDefaultDebugFileSearchPaths(); + size_t num_search_paths = debug_file_search_paths.GetSize(); + + // It's relative, e.g. "foo.dwo", but we just to happen to be right next to + // it. Or it's absolute. + found = FileSystem::Instance().Exists(dwo_file); + + const char *comp_dir = + cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr); + if (!found) { + // It could be a relative path that also uses DW_AT_COMP_DIR. + if (comp_dir) { + dwo_file.SetFile(comp_dir, FileSpec::Style::native); + if (!dwo_file.IsRelative()) { + FileSystem::Instance().Resolve(dwo_file); + dwo_file.AppendPathComponent(dwo_name); + found = FileSystem::Instance().Exists(dwo_file); + } else { + FileSpecList dwo_paths; + + // if DW_AT_comp_dir is relative, it should be relative to the location + // of the executable, not to the location from which the debugger was + // launched. + FileSpec relative_to_binary = dwo_file; + relative_to_binary.PrependPathComponent( + m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef()); + FileSystem::Instance().Resolve(relative_to_binary); + relative_to_binary.AppendPathComponent(dwo_name); + dwo_paths.Append(relative_to_binary); + + // Or it's relative to one of the user specified debug directories. + for (size_t idx = 0; idx < num_search_paths; ++idx) { + FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); + dirspec.AppendPathComponent(comp_dir); + FileSystem::Instance().Resolve(dirspec); + if (!FileSystem::Instance().IsDirectory(dirspec)) + continue; + + dirspec.AppendPathComponent(dwo_name); + dwo_paths.Append(dirspec); + } + + size_t num_possible = dwo_paths.GetSize(); + for (size_t idx = 0; idx < num_possible && !found; ++idx) { + FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx); + if (FileSystem::Instance().Exists(dwo_spec)) { + dwo_file = dwo_spec; + found = true; + } + } + } + } else { + Log *log = GetLog(LLDBLog::Symbols); + LLDB_LOGF(log, + "unable to locate relative .dwo debug file \"%s\" for " + "skeleton DIE 0x%016" PRIx64 " without valid DW_AT_comp_dir " + "attribute", + dwo_name, cu_die.GetOffset()); + } + } + + if (!found) { + // Try adding the DW_AT_dwo_name ( e.g. "c/d/main-main.dwo"), and just the + // filename ("main-main.dwo") to binary dir and search paths. + FileSpecList dwo_paths; + FileSpec dwo_name_spec(dwo_name); + llvm::StringRef filename_only = dwo_name_spec.GetFilename(); + + FileSpec binary_directory( + m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef()); + FileSystem::Instance().Resolve(binary_directory); + + if (dwo_name_spec.IsRelative()) { + FileSpec dwo_name_binary_directory(binary_directory); + dwo_name_binary_directory.AppendPathComponent(dwo_name); + dwo_paths.Append(dwo_name_binary_directory); + } + + FileSpec filename_binary_directory(binary_directory); + filename_binary_directory.AppendPathComponent(filename_only); + dwo_paths.Append(filename_binary_directory); + + for (size_t idx = 0; idx < num_search_paths; ++idx) { + FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); + FileSystem::Instance().Resolve(dirspec); + if (!FileSystem::Instance().IsDirectory(dirspec)) + continue; + + FileSpec dwo_name_dirspec(dirspec); + dwo_name_dirspec.AppendPathComponent(dwo_name); + dwo_paths.Append(dwo_name_dirspec); + + FileSpec filename_dirspec(dirspec); + filename_dirspec.AppendPathComponent(filename_only); + dwo_paths.Append(filename_dirspec); } - dwo_file.SetFile(comp_dir, FileSpec::Style::native); - if (dwo_file.IsRelative()) { - // if DW_AT_comp_dir is relative, it should be relative to the location - // of the executable, not to the location from which the debugger was - // launched. - dwo_file.PrependPathComponent( - m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef()); + size_t num_possible = dwo_paths.GetSize(); + for (size_t idx = 0; idx < num_possible && !found; ++idx) { + FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx); + if (FileSystem::Instance().Exists(dwo_spec)) { + dwo_file = dwo_spec; + found = true; + } } - FileSystem::Instance().Resolve(dwo_file); - dwo_file.AppendPathComponent(dwo_name); } - if (!FileSystem::Instance().Exists(dwo_file)) { + if (!found) { + FileSpec error_dwo_path(dwo_name); + FileSystem::Instance().Resolve(error_dwo_path); + if (error_dwo_path.IsRelative() && comp_dir != nullptr) { + error_dwo_path.PrependPathComponent(comp_dir); + FileSystem::Instance().Resolve(error_dwo_path); + } unit.SetDwoError(Status::createWithFormat( "unable to locate .dwo debug file \"{0}\" for skeleton DIE " "{1:x16}", - dwo_file.GetPath().c_str(), cu_die.GetOffset())); + error_dwo_path.GetPath().c_str(), cu_die.GetOffset())); if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) { GetObjectFile()->GetModule()->ReportWarning( @@ -1849,7 +1982,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // (corresponding to .dwo) so we simply skip it. if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" && llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath()) - .endswith(dwo_module_spec.GetFileSpec().GetPath())) { + .ends_with(dwo_module_spec.GetFileSpec().GetPath())) { continue; } @@ -2331,7 +2464,7 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, // ...But if we are only checking root decl contexts, confirm that the // 'die' is a top-level context. if (only_root_namespaces) - return die.GetParent().Tag() == dwarf::DW_TAG_compile_unit; + return die.GetParent().Tag() == llvm::dwarf::DW_TAG_compile_unit; return true; } @@ -2463,178 +2596,157 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } } -void SymbolFileDWARF::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // Make sure we haven't already searched this SymbolFile before. - if (!searched_symbol_files.insert(this).second) - return; - - Log *log = GetLog(DWARFLog::Lookups); +/// Split a name up into a basename and template parameters. +static bool SplitTemplateParams(llvm::StringRef fullname, + llvm::StringRef &basename, + llvm::StringRef &template_params) { + auto it = fullname.find('<'); + if (it == llvm::StringRef::npos) { + basename = fullname; + template_params = llvm::StringRef(); + return false; + } + basename = fullname.slice(0, it); + template_params = fullname.slice(it, fullname.size()); + return true; +} - if (log) { - if (parent_decl_ctx) - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " - "{1:p} (\"{2}\"), max_matches={3}, type_list)", - name.GetCString(), static_cast<const void *>(&parent_decl_ctx), - parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches); - else - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " - "NULL, max_matches={1}, type_list)", - name.GetCString(), max_matches); +static bool UpdateCompilerContextForSimpleTemplateNames(TypeQuery &match) { + // We need to find any names in the context that have template parameters + // and strip them so the context can be matched when -gsimple-template-names + // is being used. Returns true if any of the context items were updated. + bool any_context_updated = false; + for (auto &context : match.GetContextRef()) { + llvm::StringRef basename, params; + if (SplitTemplateParams(context.name.GetStringRef(), basename, params)) { + context.name = ConstString(basename); + any_context_updated = true; + } } + return any_context_updated; +} +void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) { - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) return; - // Unlike FindFunctions(), FindTypes() following cannot produce false - // positives. - - const llvm::StringRef name_ref = name.GetStringRef(); - auto name_bracket_index = name_ref.find('<'); - m_index->GetTypes(name, [&](DWARFDIE die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - return true; // The containing decl contexts don't match + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - Type *matching_type = ResolveType(die, true, true); - if (!matching_type) - return true; + bool have_index_match = false; + m_index->GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) { + // Check the language, but only if we have a language filter. + if (query.HasLanguage()) { + if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU()))) + return true; // Keep iterating over index types, language mismatch. + } - // With -gsimple-template-names, a templated type's DW_AT_name will not - // contain the template parameters. Make sure that if the original query - // didn't contain a '<', we filter out entries with template parameters. - if (name_bracket_index == llvm::StringRef::npos && - matching_type->IsTemplateType()) - return true; + // Check the context matches + std::vector<lldb_private::CompilerContext> die_context; + if (query.GetModuleSearch()) + die_context = die.GetDeclContext(); + else + die_context = die.GetTypeLookupContext(); + assert(!die_context.empty()); + if (!query.ContextMatches(die_context)) + return true; // Keep iterating over index types, context mismatch. - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - return types.GetSize() < max_matches; + // Try to resolve the type. + if (Type *matching_type = ResolveType(die, true, true)) { + if (matching_type->IsTemplateType()) { + // We have to watch out for case where we lookup a type by basename and + // it matches a template with simple template names. Like looking up + // "Foo" and if we have simple template names then we will match + // "Foo<int>" and "Foo<double>" because all the DWARF has is "Foo" in + // the accelerator tables. The main case we see this in is when the + // expression parser is trying to parse "Foo<int>" and it will first do + // a lookup on just "Foo". We verify the type basename matches before + // inserting the type in the results. + auto CompilerTypeBasename = + matching_type->GetForwardCompilerType().GetTypeName(true); + if (CompilerTypeBasename != query.GetTypeBasename()) + return true; // Keep iterating over index types, basename mismatch. + } + have_index_match = true; + results.InsertUnique(matching_type->shared_from_this()); + } + return !results.Done(query); // Keep iterating if we aren't done. }); + if (results.Done(query)) + return; + // With -gsimple-template-names, a templated type's DW_AT_name will not // contain the template parameters. Try again stripping '<' and anything // after, filtering out entries with template parameters that don't match. - if (types.GetSize() < max_matches) { - if (name_bracket_index != llvm::StringRef::npos) { - const llvm::StringRef name_no_template_params = - name_ref.slice(0, name_bracket_index); - const llvm::StringRef template_params = - name_ref.slice(name_bracket_index, name_ref.size()); - m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - return true; // The containing decl contexts don't match - - const llvm::StringRef base_name = GetTypeForDIE(die)->GetBaseName().AsCString(); - auto it = base_name.find('<'); - // If the candidate qualified name doesn't have '<', it doesn't have - // template params to compare. - if (it == llvm::StringRef::npos) - return true; - - // Filter out non-matching instantiations by comparing template params. - const llvm::StringRef base_name_template_params = - base_name.slice(it, base_name.size()); - - if (template_params != base_name_template_params) - return true; - - Type *matching_type = ResolveType(die, true, true); - if (!matching_type) - return true; + if (!have_index_match) { + // Create a type matcher with a compiler context that is tuned for + // -gsimple-template-names. We will use this for the index lookup and the + // context matching, but will use the original "match" to insert matches + // into if things match. The "match_simple" has a compiler context with + // all template parameters removed to allow the names and context to match. + // The UpdateCompilerContextForSimpleTemplateNames(...) will return true if + // it trims any context items down by removing template parameter names. + TypeQuery query_simple(query); + if (UpdateCompilerContextForSimpleTemplateNames(query_simple)) { + + // Copy our match's context and update the basename we are looking for + // so we can use this only to compare the context correctly. + m_index->GetTypes(query_simple.GetTypeBasename(), [&](DWARFDIE die) { + // Check the language, but only if we have a language filter. + if (query.HasLanguage()) { + if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU()))) + return true; // Keep iterating over index types, language mismatch. + } - // We found a type pointer, now find the shared pointer form our type - // list. - types.InsertUnique(matching_type->shared_from_this()); - return types.GetSize() < max_matches; + // Check the context matches + std::vector<lldb_private::CompilerContext> die_context; + if (query.GetModuleSearch()) + die_context = die.GetDeclContext(); + else + die_context = die.GetTypeLookupContext(); + assert(!die_context.empty()); + if (!query_simple.ContextMatches(die_context)) + return true; // Keep iterating over index types, context mismatch. + + // Try to resolve the type. + if (Type *matching_type = ResolveType(die, true, true)) { + ConstString name = matching_type->GetQualifiedName(); + // We have found a type that still might not match due to template + // parameters. If we create a new TypeQuery that uses the new type's + // fully qualified name, we can find out if this type matches at all + // context levels. We can't use just the "match_simple" context + // because all template parameters were stripped off. The fully + // qualified name of the type will have the template parameters and + // will allow us to make sure it matches correctly. + TypeQuery die_query(name.GetStringRef(), + TypeQueryOptions::e_exact_match); + if (!query.ContextMatches(die_query.GetContextRef())) + return true; // Keep iterating over index types, context mismatch. + + results.InsertUnique(matching_type->shared_from_this()); + } + return !results.Done(query); // Keep iterating if we aren't done. }); + if (results.Done(query)) + return; } } // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by // dsymutil. - if (types.GetSize() < max_matches) { - UpdateExternalModuleListIfNeeded(); - - for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) - if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) - sym_file->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); - } + UpdateExternalModuleListIfNeeded(); - if (log && types.GetSize()) { - if (parent_decl_ctx) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " - "= {1:p} (\"{2}\"), max_matches={3}, type_list) => {4}", - name.GetCString(), static_cast<const void *>(&parent_decl_ctx), - parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches, - types.GetSize()); - } else { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " - "= NULL, max_matches={1}, type_list) => {2}", - name.GetCString(), max_matches, types.GetSize()); + for (const auto &pair : m_external_type_modules) { + if (ModuleSP external_module_sp = pair.second) { + external_module_sp->FindTypes(query, results); + if (results.Done(query)) + return; } } } -void SymbolFileDWARF::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - // Make sure we haven't already searched this SymbolFile before. - if (!searched_symbol_files.insert(this).second) - return; - - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (pattern.empty()) - return; - - ConstString name = pattern.back().name; - - if (!name) - return; - - m_index->GetTypes(name, [&](DWARFDIE die) { - if (!languages[GetLanguageFamily(*die.GetCU())]) - return true; - - llvm::SmallVector<CompilerContext, 4> die_context; - die.GetDeclContext(die_context); - if (!contextMatches(die_context, pattern)) - return true; - - if (Type *matching_type = ResolveType(die, true, true)) { - // We found a type pointer, now find the shared pointer form our type - // list. - types.InsertUnique(matching_type->shared_from_this()); - } - return true; - }); - - // Next search through the reachable Clang modules. This only applies for - // DWARF objects compiled with -gmodules that haven't been processed by - // dsymutil. - UpdateExternalModuleListIfNeeded(); - - for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) - external_module_sp->FindTypes(pattern, languages, searched_symbol_files, - types); -} - CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx, @@ -2820,29 +2932,18 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( m_index->GetCompleteObjCClass( type_name, must_be_implementation, [&](DWARFDIE type_die) { - bool try_resolving_type = false; - // Don't try and resolve the DIE we are looking for with the DIE // itself! - if (type_die != die) { - switch (type_die.Tag()) { - case DW_TAG_class_type: - case DW_TAG_structure_type: - try_resolving_type = true; - break; - default: - break; - } - } - if (!try_resolving_type) + if (type_die == die || !IsStructOrClassTag(type_die.Tag())) return true; if (must_be_implementation && - type_die.Supports_DW_AT_APPLE_objc_complete_type()) - try_resolving_type = type_die.GetAttributeValueAsUnsigned( + type_die.Supports_DW_AT_APPLE_objc_complete_type()) { + const bool try_resolving_type = type_die.GetAttributeValueAsUnsigned( DW_AT_APPLE_objc_complete_type, 0); - if (!try_resolving_type) - return true; + if (!try_resolving_type) + return true; + } Type *resolved_type = ResolveType(type_die, false, true); if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) @@ -2993,43 +3094,20 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { template_params = dwarf_ast->GetDIEClassTemplateParams(die); } - m_index->GetTypes(GetDWARFDeclContext(die), [&](DWARFDIE type_die) { + const DWARFDeclContext die_dwarf_decl_ctx = GetDWARFDeclContext(die); + m_index->GetTypes(die_dwarf_decl_ctx, [&](DWARFDIE type_die) { // Make sure type_die's language matches the type system we are // looking for. We don't want to find a "Foo" type from Java if we // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. if (type_system && !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) return true; - bool try_resolving_type = false; - // Don't try and resolve the DIE we are looking for with the DIE - // itself! const dw_tag_t type_tag = type_die.Tag(); - // Make sure the tags match - if (type_tag == tag) { - // The tags match, lets try resolving this type - try_resolving_type = true; - } else { - // The tags don't match, but we need to watch our for a forward - // declaration for a struct and ("struct foo") ends up being a - // class ("class foo { ... };") or vice versa. - switch (type_tag) { - case DW_TAG_class_type: - // We had a "class foo", see if we ended up with a "struct foo - // { ... };" - try_resolving_type = (tag == DW_TAG_structure_type); - break; - case DW_TAG_structure_type: - // We had a "struct foo", see if we ended up with a "class foo - // { ... };" - try_resolving_type = (tag == DW_TAG_class_type); - break; - default: - // Tags don't match, don't event try to resolve using this type - // whose name matches.... - break; - } - } + // Resolve the type if both have the same tag or {class, struct} tags. + const bool try_resolving_type = + type_tag == tag || + (IsStructOrClassTag(type_tag) && IsStructOrClassTag(tag)); if (!try_resolving_type) { if (log) { @@ -3057,7 +3135,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { } // Make sure the decl contexts match all the way up - if (GetDWARFDeclContext(die) != type_dwarf_decl_ctx) + if (die_dwarf_decl_ctx != type_dwarf_decl_ctx) return true; Type *resolved_type = ResolveType(type_die, false); @@ -3437,9 +3515,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, } // Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g. - // for static constexpr member variables -- DW_AT_const_value will be - // present in the class declaration and DW_AT_location in the DIE defining - // the member. + // for static constexpr member variables -- DW_AT_const_value and + // DW_AT_location will both be present in the DIE defining the member. bool location_is_const_value_data = const_value_form.IsValid() && !location_form.IsValid(); @@ -4129,6 +4206,72 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { clang->Dump(s.AsRawOstream()); } +bool SymbolFileDWARF::GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) { + StructuredData::Array separate_debug_info_files; + DWARFDebugInfo &info = DebugInfo(); + const size_t num_cus = info.GetNumUnits(); + for (size_t cu_idx = 0; cu_idx < num_cus; cu_idx++) { + DWARFUnit *unit = info.GetUnitAtIndex(cu_idx); + DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(unit); + if (dwarf_cu == nullptr) + continue; + + // Check if this is a DWO unit by checking if it has a DWO ID. + // NOTE: it seems that `DWARFUnit::IsDWOUnit` is always false? + if (!dwarf_cu->GetDWOId().has_value()) + continue; + + StructuredData::DictionarySP dwo_data = + std::make_shared<StructuredData::Dictionary>(); + const uint64_t dwo_id = dwarf_cu->GetDWOId().value(); + dwo_data->AddIntegerItem("dwo_id", dwo_id); + + if (const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly()) { + const char *dwo_name = GetDWOName(*dwarf_cu, *die.GetDIE()); + if (dwo_name) { + dwo_data->AddStringItem("dwo_name", dwo_name); + } else { + dwo_data->AddStringItem("error", "missing dwo name"); + } + + const char *comp_dir = die.GetDIE()->GetAttributeValueAsString( + dwarf_cu, DW_AT_comp_dir, nullptr); + if (comp_dir) { + dwo_data->AddStringItem("comp_dir", comp_dir); + } + } else { + dwo_data->AddStringItem( + "error", + llvm::formatv("unable to get unit DIE for DWARFUnit at {0:x}", + dwarf_cu->GetOffset()) + .str()); + } + + // If we have a DWO symbol file, that means we were able to successfully + // load it. + SymbolFile *dwo_symfile = dwarf_cu->GetDwoSymbolFile(); + if (dwo_symfile) { + dwo_data->AddStringItem( + "resolved_dwo_path", + dwo_symfile->GetObjectFile()->GetFileSpec().GetPath()); + } else { + dwo_data->AddStringItem("error", + dwarf_cu->GetDwoError().AsCString("unknown")); + } + dwo_data->AddBooleanItem("loaded", dwo_symfile != nullptr); + if (!errors_only || dwo_data->HasKey("error")) + separate_debug_info_files.AddItem(dwo_data); + } + + d.AddStringItem("type", "dwo"); + d.AddStringItem("symfile", GetMainObjectFile()->GetFileSpec().GetPath()); + d.AddItem("separate-debug-info-files", + std::make_shared<StructuredData::Array>( + std::move(separate_debug_info_files))); + return true; +} + SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == nullptr) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); @@ -4147,9 +4290,10 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() { module_spec.GetSymbolFileSpec() = FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp"); + module_spec.GetUUID() = m_objfile_sp->GetUUID(); FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dwp_filespec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); if (FileSystem::Instance().Exists(dwp_filespec)) { DataBufferSP dwp_file_data_sp; lldb::offset_t dwp_file_data_offset = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 191a5abcf265..78819edd0062 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -30,6 +30,7 @@ #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Flags.h" #include "lldb/Utility/RangeMap.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private.h" #include "DWARFContext.h" @@ -38,10 +39,17 @@ #include "DWARFIndex.h" #include "UniqueDWARFASTType.h" +class DWARFASTParserClang; + +namespace llvm { +class DWARFDebugAbbrev; +} // namespace llvm + +namespace lldb_private::plugin { +namespace dwarf { // Forward Declarations for this DWARF plugin class DebugMapModule; class DWARFCompileUnit; -class DWARFDebugAbbrev; class DWARFDebugAranges; class DWARFDebugInfo; class DWARFDebugInfoEntry; @@ -53,11 +61,10 @@ class DWARFTypeUnit; class SymbolFileDWARFDebugMap; class SymbolFileDWARFDwo; class SymbolFileDWARFDwp; -class UserID; #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1) -class SymbolFileDWARF : public lldb_private::SymbolFileCommon { +class SymbolFileDWARF : public SymbolFileCommon { /// LLVM RTTI support. static char ID; @@ -75,26 +82,24 @@ public: friend class DebugMapModule; friend class DWARFCompileUnit; friend class DWARFDIE; - friend class DWARFASTParserClang; + friend class DWARFASTParser; // Static Functions static void Initialize(); static void Terminate(); - static void DebuggerInitialize(lldb_private::Debugger &debugger); + static void DebuggerInitialize(Debugger &debugger); static llvm::StringRef GetPluginNameStatic() { return "dwarf"; } static llvm::StringRef GetPluginDescriptionStatic(); - static lldb_private::SymbolFile * - CreateInstance(lldb::ObjectFileSP objfile_sp); + static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFileDWARF(lldb::ObjectFileSP objfile_sp, - lldb_private::SectionList *dwo_section_list); + SymbolFileDWARF(lldb::ObjectFileSP objfile_sp, SectionList *dwo_section_list); ~SymbolFileDWARF() override; @@ -104,118 +109,95 @@ public: // Compile Unit function calls - lldb::LanguageType - ParseLanguage(lldb_private::CompileUnit &comp_unit) override; + lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override; - lldb_private::XcodeSDK - ParseXcodeSDK(lldb_private::CompileUnit &comp_unit) override; + XcodeSDK ParseXcodeSDK(CompileUnit &comp_unit) override; - size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override; + size_t ParseFunctions(CompileUnit &comp_unit) override; - bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override; + bool ParseLineTable(CompileUnit &comp_unit) override; - bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + bool ParseDebugMacros(CompileUnit &comp_unit) override; - bool ForEachExternalModule( - lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &, - llvm::function_ref<bool(lldb_private::Module &)>) override; + bool ForEachExternalModule(CompileUnit &, llvm::DenseSet<SymbolFile *> &, + llvm::function_ref<bool(Module &)>) override; - bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, - lldb_private::FileSpecList &support_files) override; + bool ParseSupportFiles(CompileUnit &comp_unit, + FileSpecList &support_files) override; - bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override; + bool ParseIsOptimized(CompileUnit &comp_unit) override; - size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; + size_t ParseTypes(CompileUnit &comp_unit) override; - bool ParseImportedModules( - const lldb_private::SymbolContext &sc, - std::vector<lldb_private::SourceModule> &imported_modules) override; + bool + ParseImportedModules(const SymbolContext &sc, + std::vector<SourceModule> &imported_modules) override; - size_t ParseBlocksRecursive(lldb_private::Function &func) override; + size_t ParseBlocksRecursive(Function &func) override; - size_t - ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; + size_t ParseVariablesForContext(const SymbolContext &sc) override; - lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - std::optional<ArrayInfo> GetDynamicArrayInfoForUID( - lldb::user_id_t type_uid, - const lldb_private::ExecutionContext *exe_ctx) override; + std::optional<ArrayInfo> + GetDynamicArrayInfoForUID(lldb::user_id_t type_uid, + const ExecutionContext *exe_ctx) override; - bool CompleteType(lldb_private::CompilerType &compiler_type) override; + bool CompleteType(CompilerType &compiler_type) override; - lldb_private::Type *ResolveType(const DWARFDIE &die, - bool assert_not_being_parsed = true, - bool resolve_function_context = false); + Type *ResolveType(const DWARFDIE &die, bool assert_not_being_parsed = true, + bool resolve_function_context = false); - lldb_private::CompilerDecl GetDeclForUID(lldb::user_id_t uid) override; + CompilerDecl GetDeclForUID(lldb::user_id_t uid) override; - lldb_private::CompilerDeclContext - GetDeclContextForUID(lldb::user_id_t uid) override; + CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override; - lldb_private::CompilerDeclContext - GetDeclContextContainingUID(lldb::user_id_t uid) override; + CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override; - void - ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; + std::vector<CompilerContext> + GetCompilerContextForUID(lldb::user_id_t uid) override; - uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContext &sc) override; + void ParseDeclsForContext(CompilerDeclContext decl_ctx) override; - lldb_private::Status - CalculateFrameVariableError(lldb_private::StackFrame &frame) override; + uint32_t ResolveSymbolContext(const Address &so_addr, + lldb::SymbolContextItem resolve_scope, + SymbolContext &sc) override; - uint32_t ResolveSymbolContext( - const lldb_private::SourceLocationSpec &src_location_spec, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + Status CalculateFrameVariableError(StackFrame &frame) override; - void - FindGlobalVariables(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - lldb_private::VariableList &variables) override; + uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + SymbolContextList &sc_list) override; - void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + void FindGlobalVariables(ConstString name, + const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, - lldb_private::VariableList &variables) override; + VariableList &variables) override; - void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - bool include_inlines, - lldb_private::SymbolContextList &sc_list) override; + void FindGlobalVariables(const RegularExpression ®ex, uint32_t max_matches, + VariableList &variables) override; - void FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, - lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, + bool include_inlines, SymbolContextList &sc_list) override; - void GetMangledNamesForFunction( - const std::string &scope_qualified_name, - std::vector<lldb_private::ConstString> &mangled_names) override; + void FindFunctions(const RegularExpression ®ex, bool include_inlines, + SymbolContextList &sc_list) override; void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; + GetMangledNamesForFunction(const std::string &scope_qualified_name, + std::vector<ConstString> &mangled_names) override; - void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, - lldb_private::LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; - void GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, + TypeList &type_list) override; llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; - lldb_private::CompilerDeclContext - FindNamespace(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - bool only_root_namespaces) override; + CompilerDeclContext FindNamespace(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) override; void PreloadSymbols() override; @@ -224,7 +206,7 @@ public: // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } - DWARFDebugAbbrev *DebugAbbrev(); + llvm::DWARFDebugAbbrev *DebugAbbrev(); DWARFDebugInfo &DebugInfo(); @@ -235,25 +217,22 @@ public: DWARFDIE GetDeclContextDIEContainingDIE(const DWARFDIE &die); - bool - HasForwardDeclForClangType(const lldb_private::CompilerType &compiler_type); + bool HasForwardDeclForCompilerType(const CompilerType &compiler_type); - lldb_private::CompileUnit * - GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu); + CompileUnit *GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu); - virtual void GetObjCMethods(lldb_private::ConstString class_name, + virtual void GetObjCMethods(ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback); bool Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu); - lldb_private::DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset); + DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset); static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die); - lldb::ModuleSP GetExternalModule(lldb_private::ConstString name); + lldb::ModuleSP GetExternalModule(ConstString name); - typedef std::map<lldb_private::ConstString, lldb::ModuleSP> - ExternalTypeModuleMap; + typedef std::map<ConstString, lldb::ModuleSP> ExternalTypeModuleMap; /// Return the list of Clang modules imported by this SymbolFile. const ExternalTypeModuleMap &getExternalTypeModules() const { @@ -271,22 +250,26 @@ public: /// If this is a DWARF object with a single CU, return its DW_AT_dwo_id. std::optional<uint64_t> GetDWOId(); - static bool - DIEInDeclContext(const lldb_private::CompilerDeclContext &parent_decl_ctx, - const DWARFDIE &die, bool only_root_namespaces = false); + static bool DIEInDeclContext(const CompilerDeclContext &parent_decl_ctx, + const DWARFDIE &die, + bool only_root_namespaces = false); - std::vector<std::unique_ptr<lldb_private::CallEdge>> - ParseCallEdgesInFunction(lldb_private::UserID func_id) override; + std::vector<std::unique_ptr<CallEdge>> + ParseCallEdgesInFunction(UserID func_id) override; - void Dump(lldb_private::Stream &s) override; + void Dump(Stream &s) override; - void DumpClangAST(lldb_private::Stream &s) override; + void DumpClangAST(Stream &s) override; - lldb_private::DWARFContext &GetDWARFContext() { return m_context; } + /// List separate dwo files. + bool GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) override; + + DWARFContext &GetDWARFContext() { return m_context; } const std::shared_ptr<SymbolFileDWARFDwo> &GetDwpSymbolFile(); - lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx); + FileSpec GetFile(DWARFUnit &unit, size_t file_idx); static llvm::Expected<lldb::TypeSystemSP> GetTypeSystem(DWARFUnit &unit); @@ -294,12 +277,11 @@ public: // CompilerDecl related functions - static lldb_private::CompilerDecl GetDecl(const DWARFDIE &die); + static CompilerDecl GetDecl(const DWARFDIE &die); - static lldb_private::CompilerDeclContext GetDeclContext(const DWARFDIE &die); + static CompilerDeclContext GetDeclContext(const DWARFDIE &die); - static lldb_private::CompilerDeclContext - GetContainingDeclContext(const DWARFDIE &die); + static CompilerDeclContext GetContainingDeclContext(const DWARFDIE &die); static DWARFDeclContext GetDWARFDeclContext(const DWARFDIE &die); @@ -309,142 +291,152 @@ public: /// Same as GetLanguage() but reports all C++ versions as C++ (no version). static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit); - lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override { + StatsDuration::Duration GetDebugInfoParseTime() override { return m_parse_time; } - lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override; + StatsDuration::Duration GetDebugInfoIndexTime() override; - lldb_private::StatsDuration &GetDebugInfoParseTimeRef() { - return m_parse_time; - } + StatsDuration &GetDebugInfoParseTimeRef() { return m_parse_time; } virtual lldb::offset_t - GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, + GetVendorDWARFOpcodeSize(const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op) const { return LLDB_INVALID_OFFSET; } - virtual bool - ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes, - lldb::offset_t &offset, - std::vector<lldb_private::Value> &stack) const { + virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, + lldb::offset_t &offset, + std::vector<Value> &stack) const { return false; } - lldb_private::ConstString ConstructFunctionDemangledName(const DWARFDIE &die); + ConstString ConstructFunctionDemangledName(const DWARFDIE &die); std::optional<uint64_t> GetFileIndex() const { return m_file_index; } void SetFileIndex(std::optional<uint64_t> file_index) { m_file_index = file_index; } -protected: - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> - DIEToTypePtr; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> - DIEToVariableSP; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, Type *> DIEToTypePtr; + + virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; } + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> - DIEToClangType; - typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE; + DIEToCompilerType; + + virtual DIEToCompilerType &GetForwardDeclDIEToCompilerType() { + return m_forward_decl_die_to_compiler_type; + } + + typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> + CompilerTypeToDIE; + + virtual CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() { + return m_forward_decl_compiler_type_to_die; + } + + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> + DIEToVariableSP; + + virtual DIEToVariableSP &GetDIEToVariable() { return m_die_to_variable_sp; } + + virtual UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap(); + + bool ClassOrStructIsVirtual(const DWARFDIE &die); + SymbolFileDWARFDebugMap *GetDebugMapSymfile(); + + virtual lldb::TypeSP + FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die); + + virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( + const DWARFDIE &die, ConstString type_name, bool must_be_implementation); + + Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + + Type *ResolveTypeUID(const DWARFDIE &die, bool assert_not_being_parsed); + + Type *ResolveTypeUID(const DIERef &die_ref); + +protected: SymbolFileDWARF(const SymbolFileDWARF &) = delete; const SymbolFileDWARF &operator=(const SymbolFileDWARF &) = delete; virtual void LoadSectionData(lldb::SectionType sect_type, - lldb_private::DWARFDataExtractor &data); + DWARFDataExtractor &data); - bool DeclContextMatchesThisSymbolFile( - const lldb_private::CompilerDeclContext &decl_ctx); + bool DeclContextMatchesThisSymbolFile(const CompilerDeclContext &decl_ctx); uint32_t CalculateNumCompileUnits() override; lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb_private::TypeList &GetTypeList() override; + TypeList &GetTypeList() override; lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu); - virtual DWARFCompileUnit * - GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); + virtual DWARFCompileUnit *GetDWARFCompileUnit(CompileUnit *comp_unit); DWARFUnit *GetNextUnparsedDWARFCompileUnit(DWARFUnit *prev_cu); - bool GetFunction(const DWARFDIE &die, lldb_private::SymbolContext &sc); + bool GetFunction(const DWARFDIE &die, SymbolContext &sc); - lldb_private::Function *ParseFunction(lldb_private::CompileUnit &comp_unit, - const DWARFDIE &die); + Function *ParseFunction(CompileUnit &comp_unit, const DWARFDIE &die); - size_t ParseBlocksRecursive(lldb_private::CompileUnit &comp_unit, - lldb_private::Block *parent_block, + size_t ParseBlocksRecursive(CompileUnit &comp_unit, Block *parent_block, const DWARFDIE &die, lldb::addr_t subprogram_low_pc, uint32_t depth); - size_t ParseTypes(const lldb_private::SymbolContext &sc, const DWARFDIE &die, + size_t ParseTypes(const SymbolContext &sc, const DWARFDIE &die, bool parse_siblings, bool parse_children); - lldb::TypeSP ParseType(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, bool *type_is_new); + lldb::TypeSP ParseType(const SymbolContext &sc, const DWARFDIE &die, + bool *type_is_new); bool ParseSupportFiles(DWARFUnit &dwarf_cu, const lldb::ModuleSP &module, - lldb_private::FileSpecList &support_files); - - lldb_private::Type *ResolveTypeUID(const DWARFDIE &die, - bool assert_not_being_parsed); - - lldb_private::Type *ResolveTypeUID(const DIERef &die_ref); + FileSpecList &support_files); - lldb::VariableSP ParseVariableDIE(const lldb_private::SymbolContext &sc, + lldb::VariableSP ParseVariableDIE(const SymbolContext &sc, const DWARFDIE &die, const lldb::addr_t func_low_pc); - lldb::VariableSP ParseVariableDIECached(const lldb_private::SymbolContext &sc, + lldb::VariableSP ParseVariableDIECached(const SymbolContext &sc, const DWARFDIE &die); - void - ParseAndAppendGlobalVariable(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, - lldb_private::VariableList &cc_variable_list); + void ParseAndAppendGlobalVariable(const SymbolContext &sc, + const DWARFDIE &die, + VariableList &cc_variable_list); - size_t ParseVariablesInFunctionContext(const lldb_private::SymbolContext &sc, + size_t ParseVariablesInFunctionContext(const SymbolContext &sc, const DWARFDIE &die, const lldb::addr_t func_low_pc); - size_t ParseVariablesInFunctionContextRecursive( - const lldb_private::SymbolContext &sc, const DWARFDIE &die, - lldb::addr_t func_low_pc, DIEArray &accumulator); + size_t ParseVariablesInFunctionContextRecursive(const SymbolContext &sc, + const DWARFDIE &die, + lldb::addr_t func_low_pc, + DIEArray &accumulator); - size_t PopulateBlockVariableList(lldb_private::VariableList &variable_list, - const lldb_private::SymbolContext &sc, + size_t PopulateBlockVariableList(VariableList &variable_list, + const SymbolContext &sc, llvm::ArrayRef<DIERef> variable_dies, lldb::addr_t func_low_pc); DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die, DIEArray &&variable_dies); - bool ClassOrStructIsVirtual(const DWARFDIE &die); - // Given a die_offset, figure out the symbol context representing that die. bool ResolveFunction(const DWARFDIE &die, bool include_inlines, - lldb_private::SymbolContextList &sc_list); + SymbolContextList &sc_list); /// Resolve functions and (possibly) blocks for the given file address and a /// compile unit. The compile unit comes from the sc argument and it must be /// set. The results of the lookup (if any) are written back to the symbol /// context. void ResolveFunctionAndBlock(lldb::addr_t file_vm_addr, bool lookup_block, - lldb_private::SymbolContext &sc); + SymbolContext &sc); - virtual lldb::TypeSP - FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die); - - 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); + Symbol *GetObjCClassSymbol(ConstString objc_class_name); lldb::TypeSP GetTypeForDIE(const DWARFDIE &die, bool resolve_function_context = false); @@ -453,8 +445,6 @@ protected: m_debug_map_module_wp = module_sp; } - SymbolFileDWARFDebugMap *GetDebugMapSymfile(); - DWARFDIE FindBlockContainingSpecification(const DIERef &func_die_ref, dw_offset_t spec_block_die_offset); @@ -463,16 +453,13 @@ protected: FindBlockContainingSpecification(const DWARFDIE &die, dw_offset_t spec_block_die_offset); - virtual UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap(); - bool DIEDeclContextsMatch(const DWARFDIE &die1, const DWARFDIE &die2); - bool ClassContainsSelector(const DWARFDIE &class_die, - lldb_private::ConstString selector); + bool ClassContainsSelector(const DWARFDIE &class_die, ConstString selector); /// Parse call site entries (DW_TAG_call_site), including any nested call site /// parameters (DW_TAG_call_site_parameter). - std::vector<std::unique_ptr<lldb_private::CallEdge>> + std::vector<std::unique_ptr<CallEdge>> CollectCallEdges(lldb::ModuleSP module, DWARFDIE function_die); /// If this symbol file is linked to by a debug map (see @@ -482,48 +469,34 @@ protected: /// needed, on success and LLDB_INVALID_ADDRESS otherwise. lldb::addr_t FixupAddress(lldb::addr_t file_addr); - bool FixupAddress(lldb_private::Address &addr); + bool FixupAddress(Address &addr); - typedef llvm::SetVector<lldb_private::Type *> TypeSet; + typedef llvm::SetVector<Type *> TypeSet; void GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, dw_offset_t max_die_offset, uint32_t type_mask, TypeSet &type_set); - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, - lldb_private::Variable *> + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, Variable *> GlobalVariableMap; GlobalVariableMap &GetGlobalAranges(); void UpdateExternalModuleListIfNeeded(); - virtual DIEToTypePtr &GetDIEToType() { return m_die_to_type; } - - virtual DIEToVariableSP &GetDIEToVariable() { return m_die_to_variable_sp; } - - virtual DIEToClangType &GetForwardDeclDieToClangType() { - return m_forward_decl_die_to_clang_type; - } - - virtual ClangTypeToDIE &GetForwardDeclClangTypeToDie() { - return m_forward_decl_clang_type_to_die; - } - void BuildCuTranslationTable(); std::optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx); void FindDwpSymbolFile(); - const lldb_private::FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); + const FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); - void InitializeFirstCodeAddressRecursive( - const lldb_private::SectionList §ion_list); + void InitializeFirstCodeAddressRecursive(const SectionList §ion_list); void InitializeFirstCodeAddress(); - void GetCompileOptions( - std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) override; + void + GetCompileOptions(std::unordered_map<lldb::CompUnitSP, Args> &args) override; lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; @@ -531,22 +504,21 @@ protected: llvm::once_flag m_dwp_symfile_once_flag; std::shared_ptr<SymbolFileDWARFDwo> m_dwp_symfile; - lldb_private::DWARFContext m_context; + DWARFContext m_context; llvm::once_flag m_info_once_flag; std::unique_ptr<DWARFDebugInfo> m_info; - std::unique_ptr<DWARFDebugAbbrev> m_abbr; + std::unique_ptr<llvm::DWARFDebugAbbrev> m_abbr; std::unique_ptr<GlobalVariableMap> m_global_aranges_up; - typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP> - DebugMacrosMap; + typedef std::unordered_map<lldb::offset_t, DebugMacrosSP> DebugMacrosMap; DebugMacrosMap m_debug_macros_map; ExternalTypeModuleMap m_external_type_modules; - std::unique_ptr<lldb_private::DWARFIndex> m_index; + std::unique_ptr<DWARFIndex> m_index; bool m_fetched_external_modules : 1; - lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; + LazyBool m_supports_DW_AT_APPLE_objc_complete_type; typedef std::set<DIERef> DIERefSet; typedef llvm::StringMap<DIERefSet> NameToOffsetMap; @@ -555,10 +527,9 @@ protected: UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; - DIEToClangType m_forward_decl_die_to_clang_type; - ClangTypeToDIE m_forward_decl_clang_type_to_die; - llvm::DenseMap<dw_offset_t, lldb_private::FileSpecList> - m_type_unit_support_files; + DIEToCompilerType m_forward_decl_die_to_compiler_type; + CompilerTypeToDIE m_forward_decl_compiler_type_to_die; + llvm::DenseMap<dw_offset_t, FileSpecList> m_type_unit_support_files; std::vector<uint32_t> m_lldb_cu_to_dwarf_unit; /// DWARF does not provide a good way for traditional (concatenating) linkers /// to invalidate debug info describing dead-stripped code. These linkers will @@ -567,7 +538,7 @@ protected: /// Try to filter out this debug info by comparing it to the lowest code /// address in the module. lldb::addr_t m_first_code_address = LLDB_INVALID_ADDRESS; - lldb_private::StatsDuration m_parse_time; + StatsDuration m_parse_time; std::atomic_flag m_dwo_warning_issued = ATOMIC_FLAG_INIT; /// If this DWARF file a .DWO file or a DWARF .o file on mac when /// no dSYM file is being used, this file index will be set to a @@ -575,5 +546,7 @@ protected: /// an index that identifies the .DWO or .o file. std::optional<uint64_t> m_file_index; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARF_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index bb66fbadfb64..e5b59460cb85 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -18,13 +18,11 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Utility/RangeMap.h" #include "lldb/Utility/RegularExpression.h" -#include "lldb/Utility/Timer.h" #include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/Timer.h" //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT -#if defined(DEBUG_OSO_DMAP) -#include "lldb/Core/StreamFile.h" -#endif #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" @@ -45,6 +43,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; char SymbolFileDWARFDebugMap::ID; @@ -169,11 +168,13 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( return file_range_map; } +namespace lldb_private::plugin { +namespace dwarf { class DebugMapModule : public Module { public: DebugMapModule(const ModuleSP &exe_module_sp, uint32_t cu_idx, const FileSpec &file_spec, const ArchSpec &arch, - const ConstString *object_name, off_t object_offset, + ConstString object_name, off_t object_offset, const llvm::sys::TimePoint<> object_mod_time) : Module(file_spec, arch, object_name, object_offset, object_mod_time), m_exe_module_wp(exe_module_sp), m_cu_idx(cu_idx) {} @@ -225,6 +226,8 @@ protected: ModuleWP m_exe_module_wp; const uint32_t m_cu_idx; }; +} // namespace dwarf +} // namespace lldb_private::plugin void SymbolFileDWARFDebugMap::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), @@ -462,7 +465,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( .c_str()); comp_unit_info->oso_sp->module_sp = std::make_shared<DebugMapModule>( obj_file->GetModule(), GetCompUnitInfoIndex(comp_unit_info), oso_file, - oso_arch, oso_object ? &oso_object : nullptr, 0, + oso_arch, oso_object, 0, oso_object ? comp_unit_info->oso_mod_time : llvm::sys::TimePoint<>()); if (oso_object && !comp_unit_info->oso_sp->module_sp->GetObjectFile() && @@ -800,7 +803,7 @@ bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) { bool success = false; if (compiler_type) { ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - if (oso_dwarf->HasForwardDeclForClangType(compiler_type)) { + if (oso_dwarf->HasForwardDeclForCompilerType(compiler_type)) { oso_dwarf->CompleteType(compiler_type); success = true; return true; @@ -1224,27 +1227,12 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( return TypeSP(); } -void SymbolFileDWARFDebugMap::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { +void SymbolFileDWARFDebugMap::FindTypes(const TypeQuery &query, + TypeResults &results) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); - return types.GetSize() >= max_matches; - }); -} - -void SymbolFileDWARFDebugMap::FindTypes( - llvm::ArrayRef<CompilerContext> context, LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - LLDB_SCOPED_TIMER(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(context, languages, searched_symbol_files, types); - return false; + oso_dwarf->FindTypes(query, results); + return !results.Done(query); // Keep iterating if we aren't done. }); } @@ -1274,6 +1262,43 @@ void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) { }); } +bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo( + lldb_private::StructuredData::Dictionary &d, bool errors_only) { + StructuredData::Array separate_debug_info_files; + const uint32_t cu_count = GetNumCompileUnits(); + for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) { + const auto &info = m_compile_unit_infos[cu_idx]; + StructuredData::DictionarySP oso_data = + std::make_shared<StructuredData::Dictionary>(); + oso_data->AddStringItem("so_file", info.so_file.GetPath()); + oso_data->AddStringItem("oso_path", info.oso_path); + oso_data->AddIntegerItem("oso_mod_time", + (uint32_t)llvm::sys::toTimeT(info.oso_mod_time)); + + bool loaded_successfully = false; + if (GetModuleByOSOIndex(cu_idx)) { + // If we have a valid pointer to the module, we successfully + // loaded the oso if there are no load errors. + if (!info.oso_load_error.Fail()) { + loaded_successfully = true; + } + } + if (!loaded_successfully) { + oso_data->AddStringItem("error", info.oso_load_error.AsCString()); + } + oso_data->AddBooleanItem("loaded", loaded_successfully); + if (!errors_only || oso_data->HasKey("error")) + separate_debug_info_files.AddItem(oso_data); + } + + d.AddStringItem("type", "oso"); + d.AddStringItem("symfile", GetMainObjectFile()->GetFileSpec().GetPath()); + d.AddItem("separate-debug-info-files", + std::make_shared<StructuredData::Array>( + std::move(separate_debug_info_files))); + return true; +} + lldb::CompUnitSP SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) { if (oso_dwarf) { @@ -1340,19 +1365,25 @@ void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, CompilerDeclContext SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid) { const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); - SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); - if (oso_dwarf) + if (SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx)) return oso_dwarf->GetDeclContextForUID(type_uid); - return CompilerDeclContext(); + return {}; } CompilerDeclContext SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid) { const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); - SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); - if (oso_dwarf) + if (SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx)) return oso_dwarf->GetDeclContextContainingUID(type_uid); - return CompilerDeclContext(); + return {}; +} + +std::vector<CompilerContext> +SymbolFileDWARFDebugMap::GetCompilerContextForUID(lldb::user_id_t type_uid) { + const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); + if (SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx)) + return oso_dwarf->GetCompilerContextForUID(type_uid); + return {}; } void SymbolFileDWARFDebugMap::ParseDeclsForContext( diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 881fd4c45ff0..cd0a4bb6e41c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -19,13 +19,18 @@ #include <vector> #include "UniqueDWARFASTType.h" +#include "lldb/Utility/StructuredData.h" +class DWARFASTParserClang; + +namespace lldb_private::plugin { +namespace dwarf { class SymbolFileDWARF; class DWARFCompileUnit; class DWARFDebugAranges; class DWARFDeclContext; -class SymbolFileDWARFDebugMap : public lldb_private::SymbolFileCommon { +class SymbolFileDWARFDebugMap : public SymbolFileCommon { /// LLVM RTTI support. static char ID; @@ -47,8 +52,7 @@ public: static llvm::StringRef GetPluginDescriptionStatic(); - static lldb_private::SymbolFile * - CreateInstance(lldb::ObjectFileSP objfile_sp); + static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors SymbolFileDWARFDebugMap(lldb::ObjectFileSP objfile_sp); @@ -58,110 +62,92 @@ public: void InitializeObject() override; // Compile Unit function calls - lldb::LanguageType - ParseLanguage(lldb_private::CompileUnit &comp_unit) override; - lldb_private::XcodeSDK - ParseXcodeSDK(lldb_private::CompileUnit &comp_unit) override; + lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override; + XcodeSDK ParseXcodeSDK(CompileUnit &comp_unit) override; llvm::SmallSet<lldb::LanguageType, 4> - ParseAllLanguages(lldb_private::CompileUnit &comp_unit) override; - size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override; - bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override; - bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; - - bool ForEachExternalModule( - lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &, - llvm::function_ref<bool(lldb_private::Module &)>) override; - - bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, - lldb_private::FileSpecList &support_files) override; - - bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override; - - size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; - - bool ParseImportedModules( - const lldb_private::SymbolContext &sc, - std::vector<lldb_private::SourceModule> &imported_modules) override; - size_t ParseBlocksRecursive(lldb_private::Function &func) override; - size_t - ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; - - lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - std::optional<ArrayInfo> GetDynamicArrayInfoForUID( - lldb::user_id_t type_uid, - const lldb_private::ExecutionContext *exe_ctx) override; - - lldb_private::CompilerDeclContext - GetDeclContextForUID(lldb::user_id_t uid) override; - lldb_private::CompilerDeclContext - GetDeclContextContainingUID(lldb::user_id_t uid) override; - void - ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; + ParseAllLanguages(CompileUnit &comp_unit) override; + size_t ParseFunctions(CompileUnit &comp_unit) override; + bool ParseLineTable(CompileUnit &comp_unit) override; + bool ParseDebugMacros(CompileUnit &comp_unit) override; + + bool ForEachExternalModule(CompileUnit &, llvm::DenseSet<SymbolFile *> &, + llvm::function_ref<bool(Module &)>) override; + + bool ParseSupportFiles(CompileUnit &comp_unit, + FileSpecList &support_files) override; + + bool ParseIsOptimized(CompileUnit &comp_unit) override; + + size_t ParseTypes(CompileUnit &comp_unit) override; + + bool + ParseImportedModules(const SymbolContext &sc, + std::vector<SourceModule> &imported_modules) override; + size_t ParseBlocksRecursive(Function &func) override; + size_t ParseVariablesForContext(const SymbolContext &sc) override; + + Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + std::optional<ArrayInfo> + GetDynamicArrayInfoForUID(lldb::user_id_t type_uid, + const ExecutionContext *exe_ctx) override; - bool CompleteType(lldb_private::CompilerType &compiler_type) override; - uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, + CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override; + CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override; + std::vector<CompilerContext> + GetCompilerContextForUID(lldb::user_id_t uid) override; + void ParseDeclsForContext(CompilerDeclContext decl_ctx) override; + + bool CompleteType(CompilerType &compiler_type) override; + uint32_t ResolveSymbolContext(const Address &so_addr, + lldb::SymbolContextItem resolve_scope, + SymbolContext &sc) override; + uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContext &sc) override; - uint32_t ResolveSymbolContext( - const lldb_private::SourceLocationSpec &src_location_spec, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + SymbolContextList &sc_list) override; - lldb_private::Status - CalculateFrameVariableError(lldb_private::StackFrame &frame) override; + Status CalculateFrameVariableError(StackFrame &frame) override; - void - FindGlobalVariables(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - lldb_private::VariableList &variables) override; - void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + void FindGlobalVariables(ConstString name, + const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, - lldb_private::VariableList &variables) override; - void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - bool include_inlines, - lldb_private::SymbolContextList &sc_list) override; - void FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, - lldb_private::SymbolContextList &sc_list) override; - void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - void - FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> context, - lldb_private::LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - lldb_private::CompilerDeclContext - FindNamespace(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - bool only_root_namespaces) override; - void GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; - std::vector<std::unique_ptr<lldb_private::CallEdge>> - ParseCallEdgesInFunction(lldb_private::UserID func_id) override; - - void DumpClangAST(lldb_private::Stream &s) override; + VariableList &variables) override; + void FindGlobalVariables(const RegularExpression ®ex, uint32_t max_matches, + VariableList &variables) override; + void FindFunctions(const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, + bool include_inlines, SymbolContextList &sc_list) override; + void FindFunctions(const RegularExpression ®ex, bool include_inlines, + SymbolContextList &sc_list) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; + CompilerDeclContext FindNamespace(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + bool only_root_namespaces) override; + void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, + TypeList &type_list) override; + std::vector<std::unique_ptr<CallEdge>> + ParseCallEdgesInFunction(UserID func_id) override; + + void DumpClangAST(Stream &s) override; + + /// List separate oso files. + bool GetSeparateDebugInfo(StructuredData::Dictionary &d, + bool errors_only) override; // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } // Statistics overrides. - lldb_private::ModuleList GetDebugInfoModules() override; + ModuleList GetDebugInfoModules() override; - void GetCompileOptions( - std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) override; + void + GetCompileOptions(std::unordered_map<lldb::CompUnitSP, Args> &args) override; protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; friend class DebugMapModule; - friend class DWARFASTParserClang; + friend class ::DWARFASTParserClang; friend class DWARFCompileUnit; friend class SymbolFileDWARF; struct OSOInfo { @@ -172,16 +158,15 @@ protected: typedef std::shared_ptr<OSOInfo> OSOInfoSP; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, - lldb::addr_t> + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap; // Class specific types struct CompileUnitInfo { - lldb_private::FileSpec so_file; - lldb_private::ConstString oso_path; + FileSpec so_file; + ConstString oso_path; llvm::sys::TimePoint<> oso_mod_time; - lldb_private::Status oso_load_error; + Status oso_load_error; OSOInfoSP oso_sp; /// The compile units that an object file contains. llvm::SmallVector<lldb::CompUnitSP, 2> compile_units_sps; @@ -223,28 +208,26 @@ protected: static SymbolFileDWARF *GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file); - bool GetFileSpecForSO(uint32_t oso_idx, lldb_private::FileSpec &file_spec); + bool GetFileSpecForSO(uint32_t oso_idx, FileSpec &file_spec); - CompileUnitInfo *GetCompUnitInfo(const lldb_private::SymbolContext &sc); - CompileUnitInfo *GetCompUnitInfo(const lldb_private::CompileUnit &comp_unit); + CompileUnitInfo *GetCompUnitInfo(const SymbolContext &sc); + CompileUnitInfo *GetCompUnitInfo(const CompileUnit &comp_unit); - size_t GetCompUnitInfosForModule(const lldb_private::Module *oso_module, + size_t GetCompUnitInfosForModule(const Module *oso_module, std::vector<CompileUnitInfo *> &cu_infos); - lldb_private::Module * - GetModuleByCompUnitInfo(CompileUnitInfo *comp_unit_info); + Module *GetModuleByCompUnitInfo(CompileUnitInfo *comp_unit_info); - lldb_private::Module *GetModuleByOSOIndex(uint32_t oso_idx); + Module *GetModuleByOSOIndex(uint32_t oso_idx); - lldb_private::ObjectFile * - GetObjectFileByCompUnitInfo(CompileUnitInfo *comp_unit_info); + ObjectFile *GetObjectFileByCompUnitInfo(CompileUnitInfo *comp_unit_info); - lldb_private::ObjectFile *GetObjectFileByOSOIndex(uint32_t oso_idx); + ObjectFile *GetObjectFileByOSOIndex(uint32_t oso_idx); uint32_t GetCompUnitInfoIndex(const CompileUnitInfo *comp_unit_info); - SymbolFileDWARF *GetSymbolFile(const lldb_private::SymbolContext &sc); - SymbolFileDWARF *GetSymbolFile(const lldb_private::CompileUnit &comp_unit); + SymbolFileDWARF *GetSymbolFile(const SymbolContext &sc); + SymbolFileDWARF *GetSymbolFile(const CompileUnit &comp_unit); SymbolFileDWARF *GetSymbolFileByCompUnitInfo(CompileUnitInfo *comp_unit_info); @@ -275,11 +258,11 @@ protected: static int SymbolContainsSymbolWithID(lldb::user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info); - void PrivateFindGlobalVariables( - lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - const std::vector<uint32_t> &name_symbol_indexes, uint32_t max_matches, - lldb_private::VariableList &variables); + void + PrivateFindGlobalVariables(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + const std::vector<uint32_t> &name_symbol_indexes, + uint32_t max_matches, VariableList &variables); void SetCompileUnit(SymbolFileDWARF *oso_dwarf, const lldb::CompUnitSP &cu_sp); @@ -297,8 +280,7 @@ protected: bool Supports_DW_AT_APPLE_objc_complete_type(SymbolFileDWARF *skip_dwarf_oso); lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, lldb_private::ConstString type_name, - bool must_be_implementation); + const DWARFDIE &die, ConstString type_name, bool must_be_implementation); UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() { return m_unique_ast_type_map; @@ -329,19 +311,16 @@ protected: lldb::addr_t m_oso_file_addr = LLDB_INVALID_ADDRESS; }; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> - DebugMap; + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> DebugMap; // Member Variables std::bitset<kNumFlags> m_flags; std::vector<CompileUnitInfo> m_compile_unit_infos; std::vector<uint32_t> m_func_indexes; // Sorted by address std::vector<uint32_t> m_glob_indexes; - std::map<std::pair<lldb_private::ConstString, llvm::sys::TimePoint<>>, - OSOInfoSP> - m_oso_map; + std::map<std::pair<ConstString, llvm::sys::TimePoint<>>, OSOInfoSP> m_oso_map; UniqueDWARFASTTypeMap m_unique_ast_type_map; - lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type; + LazyBool m_supports_DW_AT_APPLE_objc_complete_type; DebugMap m_debug_map; // When an object file from the debug map gets parsed in @@ -365,7 +344,7 @@ protected: /// \return /// Returns true if \a addr was converted to be an executable /// section/offset address, false otherwise. - bool LinkOSOAddress(lldb_private::Address &addr); + bool LinkOSOAddress(Address &addr); /// Convert a .o file "file address" to an executable "file address". /// @@ -396,12 +375,13 @@ protected: /// Returns a valid line table full of linked addresses, or NULL /// if none of the line table addresses exist in the main /// executable. - lldb_private::LineTable * - LinkOSOLineTable(SymbolFileDWARF *oso_symfile, - lldb_private::LineTable *line_table); + LineTable *LinkOSOLineTable(SymbolFileDWARF *oso_symfile, + LineTable *line_table); size_t AddOSOARanges(SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges); }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARFDEBUGMAP_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index 78c3c19684e1..ca698a84a914 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -21,6 +21,7 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; char SymbolFileDWARFDwo::ID; @@ -98,14 +99,14 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() { return GetBaseSymbolFile().GetDIEToVariable(); } -SymbolFileDWARF::DIEToClangType & -SymbolFileDWARFDwo::GetForwardDeclDieToClangType() { - return GetBaseSymbolFile().GetForwardDeclDieToClangType(); +SymbolFileDWARF::DIEToCompilerType & +SymbolFileDWARFDwo::GetForwardDeclDIEToCompilerType() { + return GetBaseSymbolFile().GetForwardDeclDIEToCompilerType(); } -SymbolFileDWARF::ClangTypeToDIE & -SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() { - return GetBaseSymbolFile().GetForwardDeclClangTypeToDie(); +SymbolFileDWARF::CompilerTypeToDIE & +SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() { + return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE(); } void SymbolFileDWARFDwo::GetObjCMethods( @@ -141,3 +142,10 @@ SymbolFileDWARFDwo::GetDIE(const DIERef &die_ref) { return DebugInfo().GetDIE(die_ref); return GetBaseSymbolFile().GetDIE(die_ref); } + +void SymbolFileDWARFDwo::FindGlobalVariables( + ConstString name, const CompilerDeclContext &parent_decl_ctx, + uint32_t max_matches, VariableList &variables) { + GetBaseSymbolFile().FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index e98ea49d939b..9f5950e51b0c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -12,6 +12,8 @@ #include "SymbolFileDWARF.h" #include <optional> +namespace lldb_private::plugin { +namespace dwarf { class SymbolFileDWARFDwo : public SymbolFileDWARF { /// LLVM RTTI support. static char ID; @@ -32,7 +34,7 @@ public: DWARFCompileUnit *GetDWOCompileUnitForHash(uint64_t hash); - void GetObjCMethods(lldb_private::ConstString class_name, + void GetObjCMethods(ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) override; llvm::Expected<lldb::TypeSystemSP> @@ -41,33 +43,37 @@ public: DWARFDIE GetDIE(const DIERef &die_ref) override; - lldb::offset_t - GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, - const lldb::offset_t data_offset, - const uint8_t op) const override; + lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) const override; - bool ParseVendorDWARFOpcode( - uint8_t op, const lldb_private::DataExtractor &opcodes, - lldb::offset_t &offset, - std::vector<lldb_private::Value> &stack) const override; + bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, + lldb::offset_t &offset, + std::vector<Value> &stack) const override; + + void FindGlobalVariables(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + uint32_t max_matches, + VariableList &variables) override; protected: DIEToTypePtr &GetDIEToType() override; DIEToVariableSP &GetDIEToVariable() override; - DIEToClangType &GetForwardDeclDieToClangType() override; + DIEToCompilerType &GetForwardDeclDIEToCompilerType() override; - ClangTypeToDIE &GetForwardDeclClangTypeToDie() override; + CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override; UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override; lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) override; - lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, lldb_private::ConstString type_name, - bool must_be_implementation) override; + lldb::TypeSP + FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE &die, + ConstString type_name, + bool must_be_implementation) override; SymbolFileDWARF &GetBaseSymbolFile() const { return m_base_symbol_file; } @@ -77,5 +83,7 @@ protected: SymbolFileDWARF &m_base_symbol_file; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARFDWO_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 22a921cf6138..223518f0ae82 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Declaration.h" using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, const lldb_private::Declaration &decl, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index 0947d1e581c5..bf3cbae55e5c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -16,13 +16,15 @@ #include "DWARFDIE.h" #include "lldb/Core/Declaration.h" +namespace lldb_private::plugin { +namespace dwarf { class UniqueDWARFASTType { public: // Constructors and Destructors UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {} UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die, - const lldb_private::Declaration &decl, int32_t byte_size) + const Declaration &decl, int32_t byte_size) : m_type_sp(type_sp), m_die(die), m_declaration(decl), m_byte_size(byte_size) {} @@ -44,7 +46,7 @@ public: lldb::TypeSP m_type_sp; DWARFDIE m_die; - lldb_private::Declaration m_declaration; + Declaration m_declaration; int32_t m_byte_size = -1; }; @@ -60,7 +62,7 @@ public: m_collection.push_back(entry); } - bool Find(const DWARFDIE &die, const lldb_private::Declaration &decl, + bool Find(const DWARFDIE &die, const Declaration &decl, const int32_t byte_size, UniqueDWARFASTType &entry) const; protected: @@ -74,14 +76,12 @@ public: ~UniqueDWARFASTTypeMap() = default; - void Insert(lldb_private::ConstString name, - const UniqueDWARFASTType &entry) { + void Insert(ConstString name, const UniqueDWARFASTType &entry) { m_collection[name.GetCString()].Append(entry); } - bool Find(lldb_private::ConstString name, const DWARFDIE &die, - const lldb_private::Declaration &decl, const int32_t byte_size, - UniqueDWARFASTType &entry) const { + bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl, + const int32_t byte_size, UniqueDWARFASTType &entry) const { const char *unique_name_cstr = name.GetCString(); collection::const_iterator pos = m_collection.find(unique_name_cstr); if (pos != m_collection.end()) { @@ -95,5 +95,7 @@ protected: typedef llvm::DenseMap<const char *, UniqueDWARFASTTypeList> collection; collection m_collection; }; +} // namespace dwarf +} // namespace lldb_private::plugin #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_UNIQUEDWARFASTTYPE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index 06cb720b1e9f..25d04f999ad6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -236,7 +236,7 @@ CompileUnitIndex::GetMainSourceFile(const CompilandIndexItem &item) const { llvm::cantFail( TypeDeserializer::deserializeAs<StringIdRecord>(file_cvt, file_name)); - llvm::sys::path::Style style = working_dir.String.startswith("/") + llvm::sys::path::Style style = working_dir.String.starts_with("/") ? llvm::sys::path::Style::posix : llvm::sys::path::Style::windows; if (llvm::sys::path::is_absolute(file_name.String, style)) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 9623daa416bb..75adf7302f00 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -10,10 +10,10 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" -#include "lldb/Core/StreamBuffer.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/StreamBuffer.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index c7ff25e904ab..b79d3e63f72b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -99,18 +99,18 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) { switch (cr.Kind) { case TypeRecordKind::Class: - return clang::TTK_Class; + return clang::TagTypeKind::Class; case TypeRecordKind::Struct: - return clang::TTK_Struct; + return clang::TagTypeKind::Struct; case TypeRecordKind::Union: - return clang::TTK_Union; + return clang::TagTypeKind::Union; case TypeRecordKind::Interface: - return clang::TTK_Interface; + return clang::TagTypeKind::Interface; case TypeRecordKind::Enum: - return clang::TTK_Enum; + return clang::TagTypeKind::Enum; default: lldbassert(false && "Invalid tag record kind!"); - return clang::TTK_Struct; + return clang::TagTypeKind::Struct; } } @@ -608,16 +608,17 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id, return {}; clang::TagTypeKind ttk = TranslateUdtKind(record); - lldb::AccessType access = - (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic; + lldb::AccessType access = (ttk == clang::TagTypeKind::Class) + ? lldb::eAccessPrivate + : lldb::eAccessPublic; ClangASTMetadata metadata; metadata.SetUserID(toOpaqueUid(id)); metadata.SetIsDynamicCXXType(false); - CompilerType ct = - m_clang.CreateRecordType(context, OptionalClangModuleID(), access, uname, - ttk, lldb::eLanguageTypeC_plus_plus, &metadata); + CompilerType ct = m_clang.CreateRecordType( + context, OptionalClangModuleID(), access, uname, llvm::to_underlying(ttk), + lldb::eLanguageTypeC_plus_plus, &metadata); lldbassert(ct.IsValid()); @@ -1263,9 +1264,9 @@ void PdbAstBuilder::ParseNamespace(clang::DeclContext &context) { clang::NamespaceDecl *ns = llvm::cast<clang::NamespaceDecl>(context); llvm::StringRef ns_name = ns->getName(); - if (ns_name.startswith(qname)) { + if (ns_name.starts_with(qname)) { ns_name = ns_name.drop_front(qname.size()); - if (ns_name.startswith("::")) + if (ns_name.starts_with("::")) GetOrCreateType(tid); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp index c45db174e534..f28509acbf79 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -9,7 +9,6 @@ #include "PdbFPOProgramToDWARFExpression.h" #include "CodeViewRegisterMapping.h" -#include "lldb/Core/StreamBuffer.h" #include "lldb/Symbol/PostfixExpression.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Stream.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index f14fb32621b3..ad0801339936 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -14,8 +14,6 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamBuffer.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" @@ -1381,7 +1379,7 @@ bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, for (llvm::StringRef f : cci->m_file_list) { FileSpec::Style style = - f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows; + f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows; FileSpec spec(f, style); support_files.Append(spec); } @@ -1719,24 +1717,33 @@ void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) {} -void SymbolFileNativePDB::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (!name) +void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query, + lldb_private::TypeResults &results) { + + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) return; - searched_symbol_files.clear(); - searched_symbol_files.insert(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // There is an assumption 'name' is not a regex - FindTypesByName(name.GetStringRef(), max_matches, types); -} + std::vector<TypeIndex> matches = + m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef()); -void SymbolFileNativePDB::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {} + for (TypeIndex type_idx : matches) { + TypeSP type_sp = GetOrCreateType(type_idx); + if (!type_sp) + continue; + + // We resolved a type. Get the fully qualified name to ensure it matches. + ConstString name = type_sp->GetQualifiedName(); + TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match); + if (query.ContextMatches(type_match.GetContextRef())) { + results.InsertUnique(type_sp); + if (results.Done(query)) + return; + } + } +} void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, uint32_t max_matches, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index bf64cd330c1f..9d0458cf7ebf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -140,14 +140,8 @@ public: std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id); - void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index cf3868d077c3..fab3ca989c0e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -356,14 +356,14 @@ UdtRecordCompleter::AddMember(TypeSystemClang &clang, Member *field, case Member::Struct: case Member::Union: { clang::TagTypeKind kind = field->kind == Member::Struct - ? clang::TagTypeKind::TTK_Struct - : clang::TagTypeKind::TTK_Union; + ? clang::TagTypeKind::Struct + : clang::TagTypeKind::Union; ClangASTMetadata metadata; metadata.SetUserID(pdb->anonymous_id); metadata.SetIsDynamicCXXType(false); CompilerType record_ct = clang.CreateRecordType( - parent_decl_ctx, OptionalClangModuleID(), lldb::eAccessPublic, "", kind, - lldb::eLanguageTypeC_plus_plus, &metadata); + parent_decl_ctx, OptionalClangModuleID(), lldb::eAccessPublic, "", + llvm::to_underlying(kind), lldb::eLanguageTypeC_plus_plus, &metadata); TypeSystemClang::StartTagDeclarationDefinition(record_ct); ClangASTImporter::LayoutInfo layout; clang::DeclContext *decl_ctx = clang.GetDeclContextForType(record_ct); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 5efa5bccb85f..e915bff9e4a4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -49,13 +49,13 @@ using namespace llvm::pdb; static int TranslateUdtKind(PDB_UdtType pdb_kind) { switch (pdb_kind) { case PDB_UdtType::Class: - return clang::TTK_Class; + return llvm::to_underlying(clang::TagTypeKind::Class); case PDB_UdtType::Struct: - return clang::TTK_Struct; + return llvm::to_underlying(clang::TagTypeKind::Struct); case PDB_UdtType::Union: - return clang::TTK_Union; + return llvm::to_underlying(clang::TagTypeKind::Union); case PDB_UdtType::Interface: - return clang::TTK_Interface; + return llvm::to_underlying(clang::TagTypeKind::Interface); } llvm_unreachable("unsuported PDB UDT type"); } @@ -1387,9 +1387,9 @@ void PDBASTParser::AddRecordBases( auto is_virtual = base->isVirtualBaseClass(); std::unique_ptr<clang::CXXBaseSpecifier> base_spec = - m_ast.CreateBaseClassSpecifier(base_comp_type.GetOpaqueQualType(), - access, is_virtual, - record_kind == clang::TTK_Class); + m_ast.CreateBaseClassSpecifier( + base_comp_type.GetOpaqueQualType(), access, is_virtual, + record_kind == llvm::to_underlying(clang::TagTypeKind::Class)); lldbassert(base_spec); base_classes.push_back(std::move(base_spec)); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 94023737b2a2..95add31385df 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -9,11 +9,11 @@ #include "PDBLocationToDWARFExpression.h" #include "lldb/Core/Section.h" -#include "lldb/Core/StreamBuffer.h" #include "lldb/Core/dwarf.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/Variable.h" #include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/StreamBuffer.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 78eabc35ebf9..9e1cd8360660 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1446,24 +1446,6 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.Finalize(); } -void SymbolFilePDB::FindTypes( - lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (!name) - return; - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return; - - searched_symbol_files.clear(); - searched_symbol_files.insert(this); - - // There is an assumption 'name' is not a regex - FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); -} - void SymbolFilePDB::DumpClangAST(Stream &s) { auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); @@ -1536,26 +1518,24 @@ void SymbolFilePDB::FindTypesByRegex( } } -void SymbolFilePDB::FindTypesByName( - llvm::StringRef name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, lldb_private::TypeMap &types) { +void SymbolFilePDB::FindTypes(const lldb_private::TypeQuery &query, + lldb_private::TypeResults &type_results) { + + // Make sure we haven't already searched this SymbolFile before. + if (type_results.AlreadySearched(this)) + return; + + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + std::unique_ptr<IPDBEnumSymbols> results; - if (name.empty()) + llvm::StringRef basename = query.GetTypeBasename().GetStringRef(); + if (basename.empty()) return; results = m_global_scope_up->findAllChildren(PDB_SymType::None); if (!results) return; - uint32_t matches = 0; - while (auto result = results->getNext()) { - if (max_matches > 0 && matches >= max_matches) - break; - - if (MSVCUndecoratedNameParser::DropScope( - result->getRawSymbol().getName()) != name) - continue; switch (result->getSymTag()) { case PDB_SymType::Enum: @@ -1568,28 +1548,29 @@ void SymbolFilePDB::FindTypesByName( continue; } + if (MSVCUndecoratedNameParser::DropScope( + result->getRawSymbol().getName()) != basename) + continue; + // This should cause the type to get cached and stored in the `m_types` // lookup. if (!ResolveTypeUID(result->getSymIndexId())) continue; - if (parent_decl_ctx.IsValid() && - GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx) - continue; - auto iter = m_types.find(result->getSymIndexId()); if (iter == m_types.end()) continue; - types.Insert(iter->second); - ++matches; + // We resolved a type. Get the fully qualified name to ensure it matches. + ConstString name = iter->second->GetQualifiedName(); + TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match); + if (query.ContextMatches(type_match.GetContextRef())) { + type_results.InsertUnique(iter->second); + if (type_results.Done(query)) + return; + } } } -void SymbolFilePDB::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) {} - void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, uint32_t type_mask, TypeCollection &type_collection) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 5b98c6e8b486..01851f1418f3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -134,19 +134,8 @@ public: std::vector<lldb_private::ConstString> &mangled_names) override; void AddSymbols(lldb_private::Symtab &symtab) override; - - void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, - lldb_private::LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); diff --git a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp index 8c52df5f2a0a..9f32d252b22f 100644 --- a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp @@ -1,4 +1,4 @@ -//===-- LocateSymbolFileMacOSX.cpp ----------------------------------------===// +//===-- SymbolLocatorDebugSymbols.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,37 +6,48 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Symbol/LocateSymbolFile.h" +#include "SymbolLocatorDebugSymbols.h" -#include <dirent.h> -#include <dlfcn.h> -#include <pwd.h> - -#include <CoreFoundation/CoreFoundation.h> - -#include "Host/macosx/cfcpp/CFCBundle.h" -#include "Host/macosx/cfcpp/CFCData.h" -#include "Host/macosx/cfcpp/CFCReleaser.h" -#include "Host/macosx/cfcpp/CFCString.h" +#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/Endian.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" -#include "mach/machine.h" -#include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/ThreadPool.h" + +#include "Host/macosx/cfcpp/CFCBundle.h" +#include "Host/macosx/cfcpp/CFCData.h" +#include "Host/macosx/cfcpp/CFCReleaser.h" +#include "Host/macosx/cfcpp/CFCString.h" + +#include "mach/machine.h" + +#include <CoreFoundation/CoreFoundation.h> + +#include <cstring> +#include <dirent.h> +#include <dlfcn.h> +#include <optional> +#include <pwd.h> using namespace lldb; using namespace lldb_private; @@ -46,14 +57,37 @@ static CFURLRef (*g_dlsym_DBGCopyFullDSYMURLForUUID)( static CFDictionaryRef (*g_dlsym_DBGCopyDSYMPropertyLists)(CFURLRef dsym_url) = nullptr; -int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, - ModuleSpec &return_module_spec) { +LLDB_PLUGIN_DEFINE(SymbolLocatorDebugSymbols) + +SymbolLocatorDebugSymbols::SymbolLocatorDebugSymbols() : SymbolLocator() {} + +void SymbolLocatorDebugSymbols::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, + LocateExecutableObjectFile, LocateExecutableSymbolFile, + DownloadObjectAndSymbolFile, FindSymbolFileInBundle); +} + +void SymbolLocatorDebugSymbols::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef SymbolLocatorDebugSymbols::GetPluginDescriptionStatic() { + return "DebugSymbols symbol locator."; +} + +SymbolLocator *SymbolLocatorDebugSymbols::CreateInstance() { + return new SymbolLocatorDebugSymbols(); +} + +std::optional<ModuleSpec> SymbolLocatorDebugSymbols::LocateExecutableObjectFile( + const ModuleSpec &module_spec) { Log *log = GetLog(LLDBLog::Host); if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled."); - return 0; + return {}; } - + ModuleSpec return_module_spec; return_module_spec = module_spec; return_module_spec.GetFileSpec().Clear(); return_module_spec.GetSymbolFileSpec().Clear(); @@ -79,7 +113,7 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { - return items_found; + return {}; } if (uuid && uuid->IsValid()) { @@ -119,8 +153,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, FileSystem::Instance().Resolve(dsym_filespec); if (FileSystem::Instance().IsDirectory(dsym_filespec)) { - dsym_filespec = - Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch); + dsym_filespec = PluginManager::FindSymbolFileInBundle( + dsym_filespec, uuid, arch); ++items_found; } else { ++items_found; @@ -286,12 +320,14 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, } } - return items_found; + if (items_found) + return return_module_spec; + + return {}; } -FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, - const lldb_private::UUID *uuid, - const ArchSpec *arch) { +std::optional<FileSpec> SymbolLocatorDebugSymbols::FindSymbolFileInBundle( + const FileSpec &dsym_bundle_fspec, const UUID *uuid, const ArchSpec *arch) { std::string dsym_bundle_path = dsym_bundle_fspec.GetPath(); llvm::SmallString<128> buffer(dsym_bundle_path); llvm::sys::path::append(buffer, "Contents", "Resources", "DWARF"); @@ -328,9 +364,436 @@ FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, return {}; } +static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, + const ArchSpec *arch, + const lldb_private::UUID *uuid) { + ModuleSpecList module_specs; + if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) { + ModuleSpec spec; + for (size_t i = 0; i < module_specs.GetSize(); ++i) { + bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); + UNUSED_IF_ASSERT_DISABLED(got_spec); + assert(got_spec); + if ((uuid == nullptr || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && + (arch == nullptr || + (spec.GetArchitecturePtr() && + spec.GetArchitecture().IsCompatibleMatch(*arch)))) { + return true; + } + } + } + return false; +} + +// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid, +// return true if there is a matching dSYM bundle next to the exec_fspec, +// and return that value in dsym_fspec. +// If there is a .dSYM.yaa compressed archive next to the exec_fspec, +// call through PluginManager::DownloadObjectAndSymbolFile to download the +// expanded/uncompressed dSYM and return that filepath in dsym_fspec. +static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec, + const FileSpec &exec_fspec, + FileSpec &dsym_fspec) { + ConstString filename = exec_fspec.GetFilename(); + FileSpec dsym_directory = exec_fspec; + dsym_directory.RemoveLastPathComponent(); + + std::string dsym_filename = filename.AsCString(); + dsym_filename += ".dSYM"; + dsym_directory.AppendPathComponent(dsym_filename); + dsym_directory.AppendPathComponent("Contents"); + dsym_directory.AppendPathComponent("Resources"); + dsym_directory.AppendPathComponent("DWARF"); + + if (FileSystem::Instance().Exists(dsym_directory)) { + + // See if the binary name exists in the dSYM DWARF + // subdir. + dsym_fspec = dsym_directory; + dsym_fspec.AppendPathComponent(filename.AsCString()); + if (FileSystem::Instance().Exists(dsym_fspec) && + FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(), + mod_spec.GetUUIDPtr())) { + return true; + } + + // See if we have "../CF.framework" - so we'll look for + // CF.framework.dSYM/Contents/Resources/DWARF/CF + // We need to drop the last suffix after '.' to match + // 'CF' in the DWARF subdir. + std::string binary_name(filename.AsCString()); + auto last_dot = binary_name.find_last_of('.'); + if (last_dot != std::string::npos) { + binary_name.erase(last_dot); + dsym_fspec = dsym_directory; + dsym_fspec.AppendPathComponent(binary_name); + if (FileSystem::Instance().Exists(dsym_fspec) && + FileAtPathContainsArchAndUUID(dsym_fspec, + mod_spec.GetArchitecturePtr(), + mod_spec.GetUUIDPtr())) { + return true; + } + } + } + + // See if we have a .dSYM.yaa next to this executable path. + FileSpec dsym_yaa_fspec = exec_fspec; + dsym_yaa_fspec.RemoveLastPathComponent(); + std::string dsym_yaa_filename = filename.AsCString(); + dsym_yaa_filename += ".dSYM.yaa"; + dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename); + + if (FileSystem::Instance().Exists(dsym_yaa_fspec)) { + ModuleSpec mutable_mod_spec = mod_spec; + Status error; + if (PluginManager::DownloadObjectAndSymbolFile(mutable_mod_spec, error, + true) && + FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) { + dsym_fspec = mutable_mod_spec.GetSymbolFileSpec(); + return true; + } + } + + return false; +} + +// Given a ModuleSpec with a FileSpec and optionally uuid/architecture +// filled in, look for a .dSYM bundle next to that binary. Returns true +// if a .dSYM bundle is found, and that path is returned in the dsym_fspec +// FileSpec. +// +// This routine looks a few directory layers above the given exec_path - +// exec_path might be /System/Library/Frameworks/CF.framework/CF and the +// dSYM might be /System/Library/Frameworks/CF.framework.dSYM. +// +// If there is a .dSYM.yaa compressed archive found next to the binary, +// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM +static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, + FileSpec &dsym_fspec) { + Log *log = GetLog(LLDBLog::Host); + const FileSpec &exec_fspec = module_spec.GetFileSpec(); + if (exec_fspec) { + if (::LookForDsymNextToExecutablePath(module_spec, exec_fspec, + dsym_fspec)) { + if (log) { + LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); + } + return true; + } else { + FileSpec parent_dirs = exec_fspec; + + // Remove the binary name from the FileSpec + parent_dirs.RemoveLastPathComponent(); + + // Add a ".dSYM" name to each directory component of the path, + // stripping off components. e.g. we may have a binary like + // /S/L/F/Foundation.framework/Versions/A/Foundation and + // /S/L/F/Foundation.framework.dSYM + // + // so we'll need to start with + // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the + // "A", and if that doesn't exist, strip off the "A" and try it again + // with "Versions", etc., until we find a dSYM bundle or we've + // stripped off enough path components that there's no need to + // continue. + + for (int i = 0; i < 4; i++) { + // Does this part of the path have a "." character - could it be a + // bundle's top level directory? + const char *fn = parent_dirs.GetFilename().AsCString(); + if (fn == nullptr) + break; + if (::strchr(fn, '.') != nullptr) { + if (::LookForDsymNextToExecutablePath(module_spec, parent_dirs, + dsym_fspec)) { + if (log) { + LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", + dsym_fspec.GetPath().c_str()); + } + return true; + } + } + parent_dirs.RemoveLastPathComponent(); + } + } + } + dsym_fspec.Clear(); + return false; +} + +static int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, + ModuleSpec &return_module_spec) { + Log *log = GetLog(LLDBLog::Host); + if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { + LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled."); + return 0; + } + + return_module_spec = module_spec; + return_module_spec.GetFileSpec().Clear(); + return_module_spec.GetSymbolFileSpec().Clear(); + + const UUID *uuid = module_spec.GetUUIDPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + + int items_found = 0; + + if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || + g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { + void *handle = dlopen( + "/System/Library/PrivateFrameworks/DebugSymbols.framework/DebugSymbols", + RTLD_LAZY | RTLD_LOCAL); + if (handle) { + g_dlsym_DBGCopyFullDSYMURLForUUID = + (CFURLRef(*)(CFUUIDRef, CFURLRef))dlsym(handle, + "DBGCopyFullDSYMURLForUUID"); + g_dlsym_DBGCopyDSYMPropertyLists = (CFDictionaryRef(*)(CFURLRef))dlsym( + handle, "DBGCopyDSYMPropertyLists"); + } + } + + if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || + g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { + return items_found; + } + + if (uuid && uuid->IsValid()) { + // Try and locate the dSYM file using DebugSymbols first + llvm::ArrayRef<uint8_t> module_uuid = uuid->GetBytes(); + if (module_uuid.size() == 16) { + CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes( + NULL, module_uuid[0], module_uuid[1], module_uuid[2], module_uuid[3], + module_uuid[4], module_uuid[5], module_uuid[6], module_uuid[7], + module_uuid[8], module_uuid[9], module_uuid[10], module_uuid[11], + module_uuid[12], module_uuid[13], module_uuid[14], module_uuid[15])); + + if (module_uuid_ref.get()) { + CFCReleaser<CFURLRef> exec_url; + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + if (exec_fspec) { + char exec_cf_path[PATH_MAX]; + if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path))) + exec_url.reset(::CFURLCreateFromFileSystemRepresentation( + NULL, (const UInt8 *)exec_cf_path, strlen(exec_cf_path), + FALSE)); + } + + CFCReleaser<CFURLRef> dsym_url(g_dlsym_DBGCopyFullDSYMURLForUUID( + module_uuid_ref.get(), exec_url.get())); + char path[PATH_MAX]; + + if (dsym_url.get()) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for the dSYM", + path, uuid->GetAsString().c_str()); + FileSpec dsym_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(dsym_filespec); + + if (FileSystem::Instance().IsDirectory(dsym_filespec)) { + dsym_filespec = PluginManager::FindSymbolFileInBundle( + dsym_filespec, uuid, arch); + ++items_found; + } else { + ++items_found; + } + return_module_spec.GetSymbolFileSpec() = dsym_filespec; + } + + bool success = false; + if (log) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for an exec file", + path, uuid->GetAsString().c_str()); + } + } + + CFCReleaser<CFDictionaryRef> dict( + g_dlsym_DBGCopyDSYMPropertyLists(dsym_url.get())); + CFDictionaryRef uuid_dict = NULL; + if (dict.get()) { + CFCString uuid_cfstr(uuid->GetAsString().c_str()); + uuid_dict = static_cast<CFDictionaryRef>( + ::CFDictionaryGetValue(dict.get(), uuid_cfstr.get())); + } + + // Check to see if we have the file on the local filesystem. + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + ModuleSpec exe_spec; + exe_spec.GetFileSpec() = module_spec.GetFileSpec(); + exe_spec.GetUUID() = module_spec.GetUUID(); + ModuleSP module_sp; + module_sp.reset(new Module(exe_spec)); + if (module_sp && module_sp->GetObjectFile() && + module_sp->MatchesModuleSpec(exe_spec)) { + success = true; + return_module_spec.GetFileSpec() = module_spec.GetFileSpec(); + LLDB_LOGF(log, "using original binary filepath %s for UUID %s", + module_spec.GetFileSpec().GetPath().c_str(), + uuid->GetAsString().c_str()); + ++items_found; + } + } + + // Check if the requested image is in our shared cache. + if (!success) { + SharedCacheImageInfo image_info = HostInfo::GetSharedCacheImageInfo( + module_spec.GetFileSpec().GetPath()); + + // If we found it and it has the correct UUID, let's proceed with + // creating a module from the memory contents. + if (image_info.uuid && (!module_spec.GetUUID() || + module_spec.GetUUID() == image_info.uuid)) { + success = true; + return_module_spec.GetFileSpec() = module_spec.GetFileSpec(); + LLDB_LOGF(log, + "using binary from shared cache for filepath %s for " + "UUID %s", + module_spec.GetFileSpec().GetPath().c_str(), + uuid->GetAsString().c_str()); + ++items_found; + } + } + + // Use the DBGSymbolRichExecutable filepath if present + if (!success && uuid_dict) { + CFStringRef exec_cf_path = + static_cast<CFStringRef>(::CFDictionaryGetValue( + uuid_dict, CFSTR("DBGSymbolRichExecutable"))); + if (exec_cf_path && ::CFStringGetFileSystemRepresentation( + exec_cf_path, path, sizeof(path))) { + LLDB_LOGF(log, "plist bundle has exec path of %s for UUID %s", + path, uuid->GetAsString().c_str()); + ++items_found; + FileSpec exec_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(exec_filespec); + if (FileSystem::Instance().Exists(exec_filespec)) { + success = true; + return_module_spec.GetFileSpec() = exec_filespec; + } + } + } + + // Look next to the dSYM for the binary file. + if (!success) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + char *dsym_extension_pos = ::strstr(path, ".dSYM"); + if (dsym_extension_pos) { + *dsym_extension_pos = '\0'; + LLDB_LOGF(log, + "Looking for executable binary next to dSYM " + "bundle with name with name %s", + path); + FileSpec file_spec(path); + FileSystem::Instance().Resolve(file_spec); + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + using namespace llvm::sys::fs; + switch (get_file_type(file_spec.GetPath())) { + + case file_type::directory_file: // Bundle directory? + { + CFCBundle bundle(path); + CFCReleaser<CFURLRef> bundle_exe_url( + bundle.CopyExecutableURL()); + if (bundle_exe_url.get()) { + if (::CFURLGetFileSystemRepresentation(bundle_exe_url.get(), + true, (UInt8 *)path, + sizeof(path) - 1)) { + FileSpec bundle_exe_file_spec(path); + FileSystem::Instance().Resolve(bundle_exe_file_spec); + if (ObjectFile::GetModuleSpecifications( + bundle_exe_file_spec, 0, 0, module_specs) && + module_specs.FindMatchingModuleSpec( + module_spec, matched_module_spec)) + + { + ++items_found; + return_module_spec.GetFileSpec() = bundle_exe_file_spec; + LLDB_LOGF(log, + "Executable binary %s next to dSYM is " + "compatible; using", + path); + } + } + } + } break; + + case file_type::fifo_file: // Forget pipes + case file_type::socket_file: // We can't process socket files + case file_type::file_not_found: // File doesn't exist... + case file_type::status_error: + break; + + case file_type::type_unknown: + case file_type::regular_file: + case file_type::symlink_file: + case file_type::block_file: + case file_type::character_file: + if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, + module_specs) && + module_specs.FindMatchingModuleSpec(module_spec, + matched_module_spec)) + + { + ++items_found; + return_module_spec.GetFileSpec() = file_spec; + LLDB_LOGF(log, + "Executable binary %s next to dSYM is " + "compatible; using", + path); + } + break; + } + } + } + } + } + } + } + } + + return items_found; +} + +std::optional<FileSpec> SymbolLocatorDebugSymbols::LocateExecutableSymbolFile( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + const UUID *uuid = module_spec.GetUUIDPtr(); + + LLDB_SCOPED_TIMERF( + "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", + exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>", + arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); + + FileSpec symbol_fspec; + ModuleSpec dsym_module_spec; + // First try and find the dSYM in the same directory as the executable or in + // an appropriate parent directory + if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) { + // We failed to easily find the dSYM above, so use DebugSymbols + LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec); + } else { + dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; + } + + return dsym_module_spec.GetSymbolFileSpec(); +} + static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, ModuleSpec &module_spec, - Status &error) { + Status &error, + const std::string &command) { Log *log = GetLog(LLDBLog::Host); bool success = false; if (uuid_dict != NULL && CFGetTypeID(uuid_dict) == CFDictionaryGetTypeID()) { @@ -342,7 +805,10 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, CFSTR("DBGError")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { - error.SetErrorString(str); + std::string errorstr = command; + errorstr += ":\n"; + errorstr += str; + error.SetErrorString(errorstr); } } @@ -553,9 +1019,9 @@ static FileSpec GetDsymForUUIDExecutable() { return g_dsymForUUID_executable; } -bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, - Status &error, bool force_lookup, - bool copy_executable) { +bool SymbolLocatorDebugSymbols::DownloadObjectAndSymbolFile( + ModuleSpec &module_spec, Status &error, bool force_lookup, + bool copy_executable) { const UUID *uuid_ptr = module_spec.GetUUIDPtr(); const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); @@ -652,7 +1118,8 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, CFCString uuid_cfstr(uuid_str.c_str()); CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue(plist.get(), uuid_cfstr.get()); - return GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec, error); + return GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec, error, + command.GetData()); } if (const CFIndex num_values = ::CFDictionaryGetCount(plist.get())) { @@ -661,13 +1128,14 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]); if (num_values == 1) { - return GetModuleSpecInfoFromUUIDDictionary(values[0], module_spec, error); + return GetModuleSpecInfoFromUUIDDictionary(values[0], module_spec, error, + command.GetData()); } for (CFIndex i = 0; i < num_values; ++i) { ModuleSpec curr_module_spec; if (GetModuleSpecInfoFromUUIDDictionary(values[i], curr_module_spec, - error)) { + error, command.GetData())) { if (module_spec.GetArchitecture().IsCompatibleMatch( curr_module_spec.GetArchitecture())) { module_spec = curr_module_spec; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h new file mode 100644 index 000000000000..efbe68bc5dae --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h @@ -0,0 +1,68 @@ +//===-- SymbolLocatorDebugSymbols.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_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H +#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H + +#include "lldb/Symbol/SymbolLocator.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class SymbolLocatorDebugSymbols : public SymbolLocator { +public: + SymbolLocatorDebugSymbols(); + + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "DebugSymbols"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::SymbolLocator *CreateInstance(); + + /// PluginInterface protocol. + /// \{ + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + /// \} + + // Locate the executable file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional<ModuleSpec> + LocateExecutableObjectFile(const ModuleSpec &module_spec); + + // Locate the symbol file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional<FileSpec> + LocateExecutableSymbolFile(const ModuleSpec &module_spec, + const FileSpecList &default_search_paths); + + // Locate the object and symbol file given a module specification. + // + // Locating the file can try to download the file from a corporate build + // repository, or using any other means necessary to locate both the + // unstripped object file and the debug symbols. The force_lookup argument + // controls whether the external program is called unconditionally to find + // the symbol file, or if the user's settings are checked to see if they've + // enabled the external program before calling. + static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + Status &error, bool force_lookup, + bool copy_executable); + + static std::optional<FileSpec> + FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec, const UUID *uuid, + const ArchSpec *arch); +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp new file mode 100644 index 000000000000..111be6be3652 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp @@ -0,0 +1,142 @@ +//===-- SymbolLocatorDebuginfod.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 "SymbolLocatorDebuginfod.h" + +#include "lldb/Core/PluginManager.h" +#include "lldb/Utility/Args.h" + +#include "llvm/Debuginfod/Debuginfod.h" +#include "llvm/Debuginfod/HTTPClient.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(SymbolLocatorDebuginfod) + +namespace { + +#define LLDB_PROPERTIES_symbollocatordebuginfod +#include "SymbolLocatorDebuginfodProperties.inc" + +enum { +#define LLDB_PROPERTIES_symbollocatordebuginfod +#include "SymbolLocatorDebuginfodPropertiesEnum.inc" +}; + +class PluginProperties : public Properties { +public: + static llvm::StringRef GetSettingName() { + return SymbolLocatorDebuginfod::GetPluginNameStatic(); + } + + PluginProperties() { + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); + m_collection_sp->Initialize(g_symbollocatordebuginfod_properties); + + // We need to read the default value first to read the environment variable. + llvm::SmallVector<llvm::StringRef> urls = llvm::getDefaultDebuginfodUrls(); + Args arg_urls{urls}; + m_collection_sp->SetPropertyAtIndexFromArgs(ePropertyServerURLs, arg_urls); + + m_collection_sp->SetValueChangedCallback( + ePropertyServerURLs, [this] { ServerURLsChangedCallback(); }); + } + + Args GetDebugInfoDURLs() const { + Args urls; + m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyServerURLs, urls); + return urls; + } + +private: + void ServerURLsChangedCallback() { + m_server_urls = GetDebugInfoDURLs(); + llvm::SmallVector<llvm::StringRef> dbginfod_urls; + llvm::for_each(m_server_urls, [&](const auto &obj) { + dbginfod_urls.push_back(obj.ref()); + }); + llvm::setDefaultDebuginfodUrls(dbginfod_urls); + } + // Storage for the StringRef's used within the Debuginfod library. + Args m_server_urls; +}; + +} // namespace + +static PluginProperties &GetGlobalPluginProperties() { + static PluginProperties g_settings; + return g_settings; +} + +SymbolLocatorDebuginfod::SymbolLocatorDebuginfod() : SymbolLocator() {} + +void SymbolLocatorDebuginfod::Initialize() { + static llvm::once_flag g_once_flag; + + llvm::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, + LocateExecutableObjectFile, LocateExecutableSymbolFile, nullptr, + nullptr, SymbolLocatorDebuginfod::DebuggerInitialize); + llvm::HTTPClient::initialize(); + }); +} + +void SymbolLocatorDebuginfod::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForSymbolLocatorPlugin( + debugger, PluginProperties::GetSettingName())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForSymbolLocatorPlugin( + debugger, GetGlobalPluginProperties().GetValueProperties(), + "Properties for the Debuginfod Symbol Locator plug-in.", + is_global_setting); + } +} + +void SymbolLocatorDebuginfod::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); + llvm::HTTPClient::cleanup(); +} + +llvm::StringRef SymbolLocatorDebuginfod::GetPluginDescriptionStatic() { + return "Debuginfod symbol locator."; +} + +SymbolLocator *SymbolLocatorDebuginfod::CreateInstance() { + return new SymbolLocatorDebuginfod(); +} + +static std::optional<FileSpec> GetFileForModule( + const ModuleSpec &module_spec, + std::function<llvm::Expected<std::string>(llvm::object::BuildIDRef)> + PullFromServer) { + if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) + return {}; + const UUID &module_uuid = module_spec.GetUUID(); + if (module_uuid.IsValid() && llvm::canUseDebuginfod()) { + llvm::object::BuildID build_id(module_uuid.GetBytes()); + llvm::Expected<std::string> result = PullFromServer(build_id); + if (result) + return FileSpec(*result); + // An error here should be logged as a failure in the Debuginfod library, + // so just consume it here + consumeError(result.takeError()); + } + return {}; +} + +std::optional<ModuleSpec> SymbolLocatorDebuginfod::LocateExecutableObjectFile( + const ModuleSpec &module_spec) { + return GetFileForModule(module_spec, llvm::getCachedOrDownloadExecutable); +} + +std::optional<FileSpec> SymbolLocatorDebuginfod::LocateExecutableSymbolFile( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { + return GetFileForModule(module_spec, llvm::getCachedOrDownloadDebuginfo); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.h b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.h new file mode 100644 index 000000000000..0ea79fa1df2a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.h @@ -0,0 +1,54 @@ +//===-- SymbolLocatorDebuginfod.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_SYMBOLLOCATOR_DEBUGINFOD_SYMBOLLOCATORDEBUGINFOD_H +#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGINFOD_SYMBOLLOCATORDEBUGINFOD_H + +#include "lldb/Core/Debugger.h" +#include "lldb/Symbol/SymbolLocator.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class SymbolLocatorDebuginfod : public SymbolLocator { +public: + SymbolLocatorDebuginfod(); + + static void Initialize(); + static void Terminate(); + static void DebuggerInitialize(Debugger &debugger); + + static llvm::StringRef GetPluginNameStatic() { return "debuginfod"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::SymbolLocator *CreateInstance(); + + /// PluginInterface protocol. + /// \{ + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + /// \} + + // Locate the executable file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional<ModuleSpec> + LocateExecutableObjectFile(const ModuleSpec &module_spec); + + // Locate the symbol file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional<FileSpec> + LocateExecutableSymbolFile(const ModuleSpec &module_spec, + const FileSpecList &default_search_paths); +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGINFOD_SYMBOLLOCATORDEBUGINFOD_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td new file mode 100644 index 000000000000..1c668b001a16 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td @@ -0,0 +1,7 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "symbollocatordebuginfod" in { + def ServerURLs : Property<"server_urls", "Array">, + ElementType<"String">, + Desc<"An ordered list of Debuginfod server URLs to query for symbols. This defaults to the contents of the DEBUGINFOD_URLS environment variable.">; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp new file mode 100644 index 000000000000..ed014f99fdb5 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp @@ -0,0 +1,239 @@ +//===-- SymbolLocatorDefault.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 "SymbolLocatorDefault.h" + +#include <cstring> +#include <optional> + +#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timer.h" +#include "lldb/Utility/UUID.h" + +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ThreadPool.h" + +// From MacOSX system header "mach/machine.h" +typedef int cpu_type_t; +typedef int cpu_subtype_t; + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(SymbolLocatorDefault) + +SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {} + +void SymbolLocatorDefault::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, + LocateExecutableObjectFile, LocateExecutableSymbolFile, + DownloadObjectAndSymbolFile); +} + +void SymbolLocatorDefault::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef SymbolLocatorDefault::GetPluginDescriptionStatic() { + return "Default symbol locator."; +} + +SymbolLocator *SymbolLocatorDefault::CreateInstance() { + return new SymbolLocatorDefault(); +} + +std::optional<ModuleSpec> SymbolLocatorDefault::LocateExecutableObjectFile( + const ModuleSpec &module_spec) { + const FileSpec &exec_fspec = module_spec.GetFileSpec(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + const UUID *uuid = module_spec.GetUUIDPtr(); + LLDB_SCOPED_TIMERF( + "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", + exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>", + arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); + + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + if (exec_fspec && + ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) && + module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { + ModuleSpec result; + result.GetFileSpec() = exec_fspec; + return result; + } + + return {}; +} + +// Keep "symbols.enable-external-lookup" description in sync with this function. +std::optional<FileSpec> SymbolLocatorDefault::LocateExecutableSymbolFile( + const ModuleSpec &module_spec, const FileSpecList &default_search_paths) { + + FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); + if (symbol_file_spec.IsAbsolute() && + FileSystem::Instance().Exists(symbol_file_spec)) + return symbol_file_spec; + + Progress progress(llvm::formatv( + "Locating external symbol file for {0}", + module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"))); + + FileSpecList debug_file_search_paths = default_search_paths; + + // Add module directory. + FileSpec module_file_spec = module_spec.GetFileSpec(); + // We keep the unresolved pathname if it fails. + FileSystem::Instance().ResolveSymbolicLink(module_file_spec, + module_file_spec); + + ConstString file_dir = module_file_spec.GetDirectory(); + { + FileSpec file_spec(file_dir.AsCString(".")); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } + + if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { + + // Add current working directory. + { + FileSpec file_spec("."); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } + +#ifndef _WIN32 +#if defined(__NetBSD__) + // Add /usr/libdata/debug directory. + { + FileSpec file_spec("/usr/libdata/debug"); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } +#else + // Add /usr/lib/debug directory. + { + FileSpec file_spec("/usr/lib/debug"); + FileSystem::Instance().Resolve(file_spec); + debug_file_search_paths.AppendIfUnique(file_spec); + } +#endif +#endif // _WIN32 + } + + std::string uuid_str; + const UUID &module_uuid = module_spec.GetUUID(); + if (module_uuid.IsValid()) { + // Some debug files are stored in the .build-id directory like this: + // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug + uuid_str = module_uuid.GetAsString(""); + std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(), + ::tolower); + uuid_str.insert(2, 1, '/'); + uuid_str = uuid_str + ".debug"; + } + + size_t num_directories = debug_file_search_paths.GetSize(); + for (size_t idx = 0; idx < num_directories; ++idx) { + FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); + FileSystem::Instance().Resolve(dirspec); + if (!FileSystem::Instance().IsDirectory(dirspec)) + continue; + + std::vector<std::string> files; + std::string dirname = dirspec.GetPath(); + + if (!uuid_str.empty()) + files.push_back(dirname + "/.build-id/" + uuid_str); + if (symbol_file_spec.GetFilename()) { + files.push_back(dirname + "/" + + symbol_file_spec.GetFilename().GetCString()); + files.push_back(dirname + "/.debug/" + + symbol_file_spec.GetFilename().GetCString()); + + // Some debug files may stored in the module directory like this: + // /usr/lib/debug/usr/lib/library.so.debug + if (!file_dir.IsEmpty()) + files.push_back(dirname + file_dir.AsCString() + "/" + + symbol_file_spec.GetFilename().GetCString()); + } + + const uint32_t num_files = files.size(); + for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { + const std::string &filename = files[idx_file]; + FileSpec file_spec(filename); + FileSystem::Instance().Resolve(file_spec); + + if (llvm::sys::fs::equivalent(file_spec.GetPath(), + module_file_spec.GetPath())) + continue; + + if (FileSystem::Instance().Exists(file_spec)) { + lldb_private::ModuleSpecList specs; + const size_t num_specs = + ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); + ModuleSpec mspec; + bool valid_mspec = false; + if (num_specs == 2) { + // Special case to handle both i386 and i686 from ObjectFilePECOFF + ModuleSpec mspec2; + if (specs.GetModuleSpecAtIndex(0, mspec) && + specs.GetModuleSpecAtIndex(1, mspec2) && + mspec.GetArchitecture().GetTriple().isCompatibleWith( + mspec2.GetArchitecture().GetTriple())) { + valid_mspec = true; + } + } + if (!valid_mspec) { + assert(num_specs <= 1 && + "Symbol Vendor supports only a single architecture"); + if (num_specs == 1) { + if (specs.GetModuleSpecAtIndex(0, mspec)) { + valid_mspec = true; + } + } + } + if (valid_mspec) { + // Skip the uuids check if module_uuid is invalid. For example, + // this happens for *.dwp files since at the moment llvm-dwp + // doesn't output build ids, nor does binutils dwp. + if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) + return file_spec; + } + } + } + } + + return {}; +} + +bool SymbolLocatorDefault::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + Status &error, + bool force_lookup, + bool copy_executable) { + return false; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h new file mode 100644 index 000000000000..7bf0a2ad4a5b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h @@ -0,0 +1,64 @@ +//===-- SymbolLocatorDefault.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_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H +#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H + +#include "lldb/Symbol/SymbolLocator.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class SymbolLocatorDefault : public SymbolLocator { +public: + SymbolLocatorDefault(); + + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "Default"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::SymbolLocator *CreateInstance(); + + /// PluginInterface protocol. + /// \{ + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + /// \} + + // Locate the executable file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional<ModuleSpec> + LocateExecutableObjectFile(const ModuleSpec &module_spec); + + // Locate the symbol file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional<FileSpec> + LocateExecutableSymbolFile(const ModuleSpec &module_spec, + const FileSpecList &default_search_paths); + + // Locate the object and symbol file given a module specification. + // + // Locating the file can try to download the file from a corporate build + // repository, or using any other means necessary to locate both the + // unstripped object file and the debug symbols. The force_lookup argument + // controls whether the external program is called unconditionally to find + // the symbol file, or if the user's settings are checked to see if they've + // enabled the external program before calling. + static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + Status &error, bool force_lookup, + bool copy_executable); +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index 55a663bb1b96..b5fe35d71032 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -16,7 +16,6 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/Host.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" @@ -87,7 +86,7 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, module_spec.GetUUID() = uuid; FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dsym_fspec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); if (!dsym_fspec) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp index 0f8d3108998d..6393363db51f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp @@ -16,7 +16,6 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/Host.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" @@ -87,7 +86,7 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP &module_sp, module_spec.GetUUID() = uuid; FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dsym_fspec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); if (!dsym_fspec) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp index 91b10ea64535..f8a9389c0ff9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp @@ -17,7 +17,6 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/Host.h" -#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" @@ -87,7 +86,7 @@ SymbolVendorWasm::CreateInstance(const lldb::ModuleSP &module_sp, FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec sym_fspec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); if (!sym_fspec) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h index 254baaf3e673..82714dea3fcd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h @@ -105,7 +105,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; TraceIntelPT &m_trace; CommandOptions m_options; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp index bcac731713bb..72e9948ffe81 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp @@ -48,8 +48,8 @@ enum { #include "TraceIntelPTPropertiesEnum.inc" }; -ConstString TraceIntelPT::PluginProperties::GetSettingName() { - return ConstString(TraceIntelPT::GetPluginNameStatic()); +llvm::StringRef TraceIntelPT::PluginProperties::GetSettingName() { + return TraceIntelPT::GetPluginNameStatic(); } TraceIntelPT::PluginProperties::PluginProperties() : Properties() { @@ -60,14 +60,14 @@ TraceIntelPT::PluginProperties::PluginProperties() : Properties() { uint64_t TraceIntelPT::PluginProperties::GetInfiniteDecodingLoopVerificationThreshold() { const uint32_t idx = ePropertyInfiniteDecodingLoopVerificationThreshold; - return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_traceintelpt_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<uint64_t>( + idx, g_traceintelpt_properties[idx].default_uint_value); } uint64_t TraceIntelPT::PluginProperties::GetExtremelyLargeDecodingThreshold() { const uint32_t idx = ePropertyExtremelyLargeDecodingThreshold; - return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_traceintelpt_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<uint64_t>( + idx, g_traceintelpt_properties[idx].default_uint_value); } TraceIntelPT::PluginProperties &TraceIntelPT::GetGlobalProperties() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h index 20faabdce790..da9cefe9ed95 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h @@ -26,7 +26,7 @@ public: /// Properties to be used with the `settings` command. class PluginProperties : public Properties { public: - static ConstString GetSettingName(); + static llvm::StringRef GetSettingName(); PluginProperties(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp index e183e592986a..bd9cca675f2d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp @@ -103,10 +103,11 @@ TraceIntelPTBundleLoader::CreateEmptyProcess(lldb::pid_t pid, ParsedProcess parsed_process; parsed_process.target_sp = target_sp; - ProcessSP process_sp = target_sp->CreateProcess( - /*listener*/ nullptr, "trace", - /*crash_file*/ nullptr, - /*can_connect*/ false); + // This should instead try to directly create an instance of ProcessTrace. + // ProcessSP process_sp = target_sp->CreateProcess( + // /*listener*/ nullptr, "trace", + // /*crash_file*/ nullptr, + // /*can_connect*/ false); process_sp->SetID(static_cast<lldb::pid_t>(pid)); @@ -285,7 +286,7 @@ StringRef TraceIntelPTBundleLoader::GetSchema() { "tscPerfZeroConversion"?: { // Values used to convert between TSCs and nanoseconds. See the time_zero // section in https://man7.org/linux/man-pages/man2/perf_event_open.2.html - // for for information. + // for information. "timeMult": integer, "timeShift": integer, diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp index 33d05ee2ac13..ee8970fb4de2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp @@ -62,7 +62,7 @@ CommandObjectThreadTraceExportCTF::CommandOptions::GetDefinitions() { return llvm::ArrayRef(g_thread_trace_export_ctf_options); } -bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, +void CommandObjectThreadTraceExportCTF::DoExecute(Args &command, CommandReturnObject &result) { const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace(); Process *process = m_exe_ctx.GetProcessPtr(); @@ -78,7 +78,6 @@ bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, result.AppendErrorWithFormatv( "Thread index {0} is out of range (valid values are 1 - {1}).\n", tid, num_threads); - return false; } else { auto do_work = [&]() -> Error { Expected<TraceCursorSP> cursor = trace_sp->CreateNewCursor(*thread); @@ -91,9 +90,6 @@ bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, if (llvm::Error err = do_work()) { result.AppendErrorWithFormat("%s\n", toString(std::move(err)).c_str()); - return false; - } else { - return true; } } } diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h index c9f02a372ded..1a034e87cfb6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h @@ -48,7 +48,7 @@ public: Options *GetOptions() override { return &m_options; } protected: - bool DoExecute(Args &command, CommandReturnObject &result) override; + void DoExecute(Args &command, CommandReturnObject &result) override; CommandOptions m_options; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/docs/htr.rst b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/docs/htr.rst index 1341cf5f0c80..beee14dce25a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/docs/htr.rst +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/docs/htr.rst @@ -21,7 +21,7 @@ Concepts **Pass:** A transformation applied to a *layer* that generates a new *layer* that is a more summarized, consolidated representation of the trace data. A pass merges instructions/blocks based on its specific purpose - for example, a pass designed to summarize a processor trace by function calls would merge all the blocks of a function into a single block representing the entire function. -The image below illusrates the transformation of a trace's representation (HTR) +The image below illustrates the transformation of a trace's representation (HTR) .. image:: media/htr-example.png diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c7430882adb5..503cbedce982 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -56,8 +56,8 @@ #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/ExecutionContext.h" @@ -86,6 +86,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; +using namespace lldb_private::plugin::dwarf; using namespace clang; using llvm::StringSwitch; @@ -2293,12 +2294,13 @@ CompilerType TypeSystemClang::CreateArrayType(const CompilerType &element_type, llvm::APInt ap_element_count(64, element_count); if (element_count == 0) { - return GetType(ast.getIncompleteArrayType( - ClangUtil::GetQualType(element_type), clang::ArrayType::Normal, 0)); + return GetType( + ast.getIncompleteArrayType(ClangUtil::GetQualType(element_type), + clang::ArraySizeModifier::Normal, 0)); } else { return GetType(ast.getConstantArrayType( ClangUtil::GetQualType(element_type), ap_element_count, nullptr, - clang::ArrayType::Normal, 0)); + clang::ArraySizeModifier::Normal, 0)); } } } @@ -2318,8 +2320,9 @@ CompilerType TypeSystemClang::CreateStructForIdentifier( return type; } - type = CreateRecordType(nullptr, OptionalClangModuleID(), lldb::eAccessPublic, - type_name, clang::TTK_Struct, lldb::eLanguageTypeC); + type = CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, type_name, + llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC); StartTagDeclarationDefinition(type); for (const auto &field : type_fields) AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, @@ -2458,89 +2461,6 @@ void TypeSystemClang::DumpDeclHiearchy(clang::Decl *decl) { } } -bool TypeSystemClang::DeclsAreEquivalent(clang::Decl *lhs_decl, - clang::Decl *rhs_decl) { - if (lhs_decl && rhs_decl) { - // Make sure the decl kinds match first - const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind(); - const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind(); - - if (lhs_decl_kind == rhs_decl_kind) { - // Now check that the decl contexts kinds are all equivalent before we - // have to check any names of the decl contexts... - clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); - clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); - if (lhs_decl_ctx && rhs_decl_ctx) { - while (true) { - if (lhs_decl_ctx && rhs_decl_ctx) { - const clang::Decl::Kind lhs_decl_ctx_kind = - lhs_decl_ctx->getDeclKind(); - const clang::Decl::Kind rhs_decl_ctx_kind = - rhs_decl_ctx->getDeclKind(); - if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) { - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - - if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr) - break; - } else - return false; - } else - return false; - } - - // Now make sure the name of the decls match - clang::NamedDecl *lhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(lhs_decl); - clang::NamedDecl *rhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(rhs_decl); - if (lhs_named_decl && rhs_named_decl) { - clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } else - return false; - } else - return false; - - // We know that the decl context kinds all match, so now we need to - // make sure the names match as well - lhs_decl_ctx = lhs_decl->getDeclContext(); - rhs_decl_ctx = rhs_decl->getDeclContext(); - while (true) { - switch (lhs_decl_ctx->getDeclKind()) { - case clang::Decl::TranslationUnit: - // We don't care about the translation unit names - return true; - default: { - clang::NamedDecl *lhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx); - clang::NamedDecl *rhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx); - if (lhs_named_decl && rhs_named_decl) { - clang::DeclarationName lhs_decl_name = - lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = - rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } else - return false; - } else - return false; - } break; - } - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - } - } - } - } - return false; -} bool TypeSystemClang::GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl) { if (!decl) @@ -2636,6 +2556,13 @@ TypeSystemClang::GetDeclContextForType(const CompilerType &type) { return GetDeclContextForType(ClangUtil::GetQualType(type)); } +CompilerDeclContext +TypeSystemClang::GetCompilerDeclContextForType(const CompilerType &type) { + if (auto *decl_context = GetDeclContextForType(type)) + return CreateDeclContext(decl_context); + return CompilerDeclContext(); +} + /// Aggressively desugar the provided type, skipping past various kinds of /// syntactic sugar and other constructs one typically wants to ignore. /// The \p mask argument allows one to skip certain kinds of simplifications, @@ -3549,8 +3476,15 @@ bool TypeSystemClang::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { if (record_decl) { const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - return cxx_record_decl->isPolymorphic(); + if (cxx_record_decl) { + // We can't just call is isPolymorphic() here because that just + // means the current class has virtual functions, it doesn't check + // if any inherited classes have virtual functions. The doc string + // in SBType::IsPolymorphicClass() says it is looking for both + // if the class has virtual methods or if any bases do, so this + // should be more correct. + return cxx_record_decl->isDynamicClass(); + } } } break; @@ -4293,10 +4227,10 @@ CompilerType TypeSystemClang::GetArrayType(lldb::opaque_compiler_type_t type, if (size != 0) return GetType(ast_ctx.getConstantArrayType( qual_type, llvm::APInt(64, size), nullptr, - clang::ArrayType::ArraySizeModifier::Normal, 0)); + clang::ArraySizeModifier::Normal, 0)); else return GetType(ast_ctx.getIncompleteArrayType( - qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0)); + qual_type, clang::ArraySizeModifier::Normal, 0)); } return CompilerType(); @@ -4700,6 +4634,21 @@ TypeSystemClang::GetTypedefedType(lldb::opaque_compiler_type_t type) { CompilerType TypeSystemClang::GetBasicTypeFromAST(lldb::BasicType basic_type) { return TypeSystemClang::GetBasicType(basic_type); } + +CompilerType TypeSystemClang::CreateGenericFunctionPrototype() { + clang::ASTContext &ast = getASTContext(); + const FunctionType::ExtInfo generic_ext_info( + /*noReturn=*/false, + /*hasRegParm=*/false, + /*regParm=*/0, + CallingConv::CC_C, + /*producesResult=*/false, + /*noCallerSavedRegs=*/false, + /*NoCfCheck=*/false, + /*cmseNSCall=*/false); + QualType func_type = ast.getFunctionNoProtoType(ast.VoidTy, generic_ext_info); + return GetType(func_type); +} // Exploring the type const llvm::fltSemantics & @@ -4816,7 +4765,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::Type::FunctionNoProto: case clang::Type::FunctionProto: - break; + return lldb::eEncodingUint; case clang::Type::IncompleteArray: case clang::Type::VariableArray: @@ -5361,11 +5310,8 @@ uint32_t TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, num_children += cxx_record_decl->getNumBases(); } } - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), - field_end = record_decl->field_end(); - field != field_end; ++field) - ++num_children; + num_children += std::distance(record_decl->field_begin(), + record_decl->field_end()); } break; @@ -5576,13 +5522,8 @@ uint32_t TypeSystemClang::GetNumFields(lldb::opaque_compiler_type_t type) { if (record_type) { clang::RecordDecl *record_decl = record_type->getDecl(); if (record_decl) { - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), - field_end = record_decl->field_end(); - field != field_end; ++field) - ++field_idx; - count = field_idx; + count = std::distance(record_decl->field_begin(), + record_decl->field_end()); } } } @@ -7183,7 +7124,8 @@ GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl, // (including the ones preceding the parameter pack). const auto &pack = args[last_idx]; const size_t pack_idx = idx - last_idx; - assert(pack_idx < pack.pack_size() && "parameter pack index out-of-bounds"); + if (pack_idx >= pack.pack_size()) + return nullptr; return &pack.pack_elements()[pack_idx]; } @@ -7651,7 +7593,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( nullptr /*expr*/, is_explicit ? clang::ExplicitSpecKind::ResolvedTrue : clang::ExplicitSpecKind::ResolvedFalse); - if (name.startswith("~")) { + if (name.starts_with("~")) { cxx_dtor_decl = clang::CXXDestructorDecl::CreateDeserialized(getASTContext(), 0); cxx_dtor_decl->setDeclContext(cxx_record_decl); @@ -7986,8 +7928,8 @@ bool TypeSystemClang::AddObjCClassProperty( const bool isSynthesizedAccessorStub = false; const bool isImplicitlyDeclared = true; const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = - clang::ObjCMethodDecl::None; + const clang::ObjCImplementationControl impControl = + clang::ObjCImplementationControl::None; const bool HasRelatedResultType = false; getter = clang::ObjCMethodDecl::CreateDeserialized(clang_ast, 0); @@ -8028,8 +7970,8 @@ bool TypeSystemClang::AddObjCClassProperty( const bool isSynthesizedAccessorStub = false; const bool isImplicitlyDeclared = true; const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = - clang::ObjCMethodDecl::None; + const clang::ObjCImplementationControl impControl = + clang::ObjCImplementationControl::None; const bool HasRelatedResultType = false; setter = clang::ObjCMethodDecl::CreateDeserialized(clang_ast, 0); @@ -8085,8 +8027,8 @@ clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType( const char *name, // the full symbol name as seen in the symbol table // (lldb::opaque_compiler_type_t type, "-[NString // stringWithCString:]") - const CompilerType &method_clang_type, lldb::AccessType access, - bool is_artificial, bool is_variadic, bool is_objc_direct_call) { + const CompilerType &method_clang_type, bool is_artificial, bool is_variadic, + bool is_objc_direct_call) { if (!type || !method_clang_type.IsValid()) return nullptr; @@ -8150,8 +8092,8 @@ clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType( /// Force this to true because we don't have source locations. const bool isImplicitlyDeclared = true; const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = - clang::ObjCMethodDecl::None; + const clang::ObjCImplementationControl impControl = + clang::ObjCImplementationControl::None; const bool HasRelatedResultType = false; const unsigned num_args = method_function_prototype->getNumParams(); @@ -8520,380 +8462,6 @@ void TypeSystemClang::DumpFromSymbolFile(Stream &s, } } -void TypeSystemClang::DumpValue( - lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream &s, - lldb::Format format, const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, size_t data_byte_size, - uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, - bool show_summary, bool verbose, uint32_t depth) { - if (!type) - return; - - clang::QualType qual_type(GetQualType(type)); - switch (qual_type->getTypeClass()) { - case clang::Type::Record: - if (GetCompleteType(type)) { - const clang::RecordType *record_type = - llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - uint32_t field_bit_offset = 0; - uint32_t field_byte_offset = 0; - const clang::ASTRecordLayout &record_layout = - getASTContext().getASTRecordLayout(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = - llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) { - // We might have base classes to print out first - clang::CXXRecordDecl::base_class_const_iterator base_class, - base_class_end; - for (base_class = cxx_record_decl->bases_begin(), - base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; ++base_class) { - const clang::CXXRecordDecl *base_class_decl = - llvm::cast<clang::CXXRecordDecl>( - base_class->getType()->getAs<clang::RecordType>()->getDecl()); - - // Skip empty base classes - if (!verbose && !TypeSystemClang::RecordHasFields(base_class_decl)) - continue; - - if (base_class->isVirtual()) - field_bit_offset = - record_layout.getVBaseClassOffset(base_class_decl) - .getQuantity() * - 8; - else - field_bit_offset = record_layout.getBaseClassOffset(base_class_decl) - .getQuantity() * - 8; - field_byte_offset = field_bit_offset / 8; - assert(field_bit_offset % 8 == 0); - if (child_idx == 0) - s.PutChar('{'); - else - s.PutChar(','); - - clang::QualType base_class_qual_type = base_class->getType(); - std::string base_class_type_name(base_class_qual_type.getAsString()); - - // Indent and print the base class type name - s.Format("\n{0}{1}", llvm::fmt_repeat(" ", depth + DEPTH_INCREMENT), - base_class_type_name); - - clang::TypeInfo base_class_type_info = - getASTContext().getTypeInfo(base_class_qual_type); - - // Dump the value of the member - CompilerType base_clang_type = GetType(base_class_qual_type); - base_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - base_clang_type - .GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field_byte_offset, // Offset into "data" where - // to grab value from - base_class_type_info.Width / 8, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable - // types - show_summary, // Boolean indicating if we should show a summary - // for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have - // children - - ++child_idx; - } - } - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), - field_end = record_decl->field_end(); - field != field_end; ++field, ++field_idx, ++child_idx) { - // Print the starting squiggly bracket (if this is the first member) or - // comma (for member 2 and beyond) for the struct/union/class member. - if (child_idx == 0) - s.PutChar('{'); - else - s.PutChar(','); - - // Indent - s.Printf("\n%*s", depth + DEPTH_INCREMENT, ""); - - clang::QualType field_type = field->getType(); - // Print the member type if requested - // Figure out the type byte size (field_type_info.first) and alignment - // (field_type_info.second) from the AST context. - clang::TypeInfo field_type_info = - getASTContext().getTypeInfo(field_type); - assert(field_idx < record_layout.getFieldCount()); - // Figure out the field offset within the current struct/union/class - // type - field_bit_offset = record_layout.getFieldOffset(field_idx); - field_byte_offset = field_bit_offset / 8; - uint32_t field_bitfield_bit_size = 0; - uint32_t field_bitfield_bit_offset = 0; - if (FieldIsBitfield(*field, field_bitfield_bit_size)) - field_bitfield_bit_offset = field_bit_offset % 8; - - if (show_types) { - std::string field_type_name(field_type.getAsString()); - if (field_bitfield_bit_size > 0) - s.Printf("(%s:%u) ", field_type_name.c_str(), - field_bitfield_bit_size); - else - s.Printf("(%s) ", field_type_name.c_str()); - } - // Print the member name and equal sign - s.Printf("%s = ", field->getNameAsString().c_str()); - - // Dump the value of the member - CompilerType field_clang_type = GetType(field_type); - field_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - field_clang_type - .GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field_byte_offset, // Offset into "data" where to - // grab value from - field_type_info.Width / 8, // Size of this type in bytes - field_bitfield_bit_size, // Bitfield bit size - field_bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable - // types - show_summary, // Boolean indicating if we should show a summary for - // the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have - // children - } - - // Indent the trailing squiggly bracket - if (child_idx > 0) - s.Printf("\n%*s}", depth, ""); - } - return; - - case clang::Type::Enum: - if (GetCompleteType(type)) { - const clang::EnumType *enutype = - llvm::cast<clang::EnumType>(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = enutype->getDecl(); - assert(enum_decl); - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - lldb::offset_t offset = data_byte_offset; - const int64_t enum_value = data.GetMaxU64Bitfield( - &offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), - enum_end_pos = enum_decl->enumerator_end(); - enum_pos != enum_end_pos; ++enum_pos) { - if (enum_pos->getInitVal() == enum_value) { - s.Printf("%s", enum_pos->getNameAsString().c_str()); - return; - } - } - // If we have gotten here we didn't get find the enumerator in the enum - // decl, so just print the integer. - s.Printf("%" PRIi64, enum_value); - } - return; - - case clang::Type::ConstantArray: { - const clang::ConstantArrayType *array = - llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr()); - bool is_array_of_characters = false; - clang::QualType element_qual_type = array->getElementType(); - - const clang::Type *canonical_type = - element_qual_type->getCanonicalTypeInternal().getTypePtr(); - if (canonical_type) - is_array_of_characters = canonical_type->isCharType(); - - const uint64_t element_count = array->getSize().getLimitedValue(); - - clang::TypeInfo field_type_info = - getASTContext().getTypeInfo(element_qual_type); - - uint32_t element_idx = 0; - uint32_t element_offset = 0; - uint64_t element_byte_size = field_type_info.Width / 8; - uint32_t element_stride = element_byte_size; - - if (is_array_of_characters) { - s.PutChar('"'); - DumpDataExtractor(data, &s, data_byte_offset, lldb::eFormatChar, - element_byte_size, element_count, UINT32_MAX, - LLDB_INVALID_ADDRESS, 0, 0); - s.PutChar('"'); - return; - } else { - CompilerType element_clang_type = GetType(element_qual_type); - lldb::Format element_format = element_clang_type.GetFormat(); - - for (element_idx = 0; element_idx < element_count; ++element_idx) { - // Print the starting squiggly bracket (if this is the first member) or - // comman (for member 2 and beyong) for the struct/union/class member. - if (element_idx == 0) - s.PutChar('{'); - else - s.PutChar(','); - - // Indent and print the index - s.Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx); - - // Figure out the field offset within the current struct/union/class - // type - element_offset = element_idx * element_stride; - - // Dump the value of the member - element_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - element_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset + - element_offset, // Offset into "data" where to grab value from - element_byte_size, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable - // types - show_summary, // Boolean indicating if we should show a summary for - // the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have - // children - } - - // Indent the trailing squiggly bracket - if (element_idx > 0) - s.Printf("\n%*s}", depth, ""); - } - } - return; - - case clang::Type::Typedef: { - clang::QualType typedef_qual_type = - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType(); - - CompilerType typedef_clang_type = GetType(typedef_qual_type); - lldb::Format typedef_format = typedef_clang_type.GetFormat(); - clang::TypeInfo typedef_type_info = - getASTContext().getTypeInfo(typedef_qual_type); - uint64_t typedef_byte_size = typedef_type_info.Width / 8; - - return typedef_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - typedef_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - typedef_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the - // current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } break; - - case clang::Type::Auto: { - clang::QualType elaborated_qual_type = - llvm::cast<clang::AutoType>(qual_type)->getDeducedType(); - CompilerType elaborated_clang_type = GetType(elaborated_qual_type); - lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); - clang::TypeInfo elaborated_type_info = - getASTContext().getTypeInfo(elaborated_qual_type); - uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; - - return elaborated_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - elaborated_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - elaborated_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the - // current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } break; - - case clang::Type::Elaborated: { - clang::QualType elaborated_qual_type = - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(); - CompilerType elaborated_clang_type = GetType(elaborated_qual_type); - lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); - clang::TypeInfo elaborated_type_info = - getASTContext().getTypeInfo(elaborated_qual_type); - uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; - - return elaborated_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - elaborated_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - elaborated_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the - // current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } break; - - case clang::Type::Paren: { - clang::QualType desugar_qual_type = - llvm::cast<clang::ParenType>(qual_type)->desugar(); - CompilerType desugar_clang_type = GetType(desugar_qual_type); - - lldb::Format desugar_format = desugar_clang_type.GetFormat(); - clang::TypeInfo desugar_type_info = - getASTContext().getTypeInfo(desugar_qual_type); - uint64_t desugar_byte_size = desugar_type_info.Width / 8; - - return desugar_clang_type.DumpValue( - exe_ctx, - &s, // Stream to dump to - desugar_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - desugar_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the - // current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } break; - - default: - // We are down to a scalar type that we just need to display. - DumpDataExtractor(data, &s, data_byte_offset, format, data_byte_size, 1, - UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, - bitfield_bit_offset); - - if (show_summary) - DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size); - break; - } -} - static bool DumpEnumValue(const clang::QualType &qual_type, Stream &s, const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size, uint32_t bitfield_bit_offset, @@ -9099,51 +8667,6 @@ bool TypeSystemClang::DumpTypeValue( return false; } -void TypeSystemClang::DumpSummary(lldb::opaque_compiler_type_t type, - ExecutionContext *exe_ctx, Stream &s, - const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size) { - uint32_t length = 0; - if (IsCStringType(type, length)) { - if (exe_ctx) { - Process *process = exe_ctx->GetProcessPtr(); - if (process) { - lldb::offset_t offset = data_byte_offset; - lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size); - std::vector<uint8_t> buf; - if (length > 0) - buf.resize(length); - else - buf.resize(256); - - DataExtractor cstr_data(&buf.front(), buf.size(), - process->GetByteOrder(), 4); - buf.back() = '\0'; - size_t bytes_read; - size_t total_cstr_len = 0; - Status error; - while ((bytes_read = process->ReadMemory(pointer_address, &buf.front(), - buf.size(), error)) > 0) { - const size_t len = strlen((const char *)&buf.front()); - if (len == 0) - break; - if (total_cstr_len == 0) - s.PutCString(" \""); - DumpDataExtractor(cstr_data, &s, 0, lldb::eFormatChar, 1, len, - UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); - total_cstr_len += len; - if (len < buf.size()) - break; - pointer_address += total_cstr_len; - } - if (total_cstr_len > 0) - s.PutChar('"'); - } - } - } -} - void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, lldb::DescriptionLevel level) { StreamFile s(stdout, false); @@ -9468,6 +8991,66 @@ size_t TypeSystemClang::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } +static CompilerContextKind GetCompilerKind(clang::Decl::Kind clang_kind, + clang::DeclContext const *decl_ctx) { + switch (clang_kind) { + case Decl::TranslationUnit: + return CompilerContextKind::TranslationUnit; + case Decl::Namespace: + return CompilerContextKind::Namespace; + case Decl::Var: + return CompilerContextKind::Variable; + case Decl::Enum: + return CompilerContextKind::Enum; + case Decl::Typedef: + return CompilerContextKind::Typedef; + default: + // Many other kinds have multiple values + if (decl_ctx) { + if (decl_ctx->isFunctionOrMethod()) + return CompilerContextKind::Function; + else if (decl_ctx->isRecord()) + return (CompilerContextKind)((uint16_t)CompilerContextKind::Class | + (uint16_t)CompilerContextKind::Struct | + (uint16_t)CompilerContextKind::Union); + } + break; + } + return CompilerContextKind::Any; +} + +static void +InsertCompilerContext(TypeSystemClang *ts, clang::DeclContext *decl_ctx, + std::vector<lldb_private::CompilerContext> &context) { + if (decl_ctx == nullptr) + return; + InsertCompilerContext(ts, decl_ctx->getParent(), context); + clang::Decl::Kind clang_kind = decl_ctx->getDeclKind(); + if (clang_kind == Decl::TranslationUnit) + return; // Stop at the translation unit. + const CompilerContextKind compiler_kind = + GetCompilerKind(clang_kind, decl_ctx); + ConstString decl_ctx_name = ts->DeclContextGetName(decl_ctx); + context.push_back({compiler_kind, decl_ctx_name}); +} + +std::vector<lldb_private::CompilerContext> +TypeSystemClang::DeclGetCompilerContext(void *opaque_decl) { + std::vector<lldb_private::CompilerContext> context; + ConstString decl_name = DeclGetName(opaque_decl); + if (decl_name) { + clang::Decl *decl = (clang::Decl *)opaque_decl; + // Add the entire decl context first + clang::DeclContext *decl_ctx = decl->getDeclContext(); + InsertCompilerContext(this, decl_ctx, context); + // Now add the decl information + auto compiler_kind = + GetCompilerKind(decl->getKind(), dyn_cast<DeclContext>(decl)); + context.push_back({compiler_kind, decl_name}); + } + return context; +} + CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl, size_t idx) { if (clang::FunctionDecl *func_decl = @@ -9706,6 +9289,14 @@ bool TypeSystemClang::DeclContextIsClassMethod(void *opaque_decl_ctx) { return false; } +std::vector<lldb_private::CompilerContext> +TypeSystemClang::DeclContextGetCompilerContext(void *opaque_decl_ctx) { + auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx; + std::vector<lldb_private::CompilerContext> context; + InsertCompilerContext(this, decl_ctx, context); + return context; +} + bool TypeSystemClang::DeclContextIsContainedInLookup( void *opaque_decl_ctx, void *other_opaque_decl_ctx) { auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx; diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 3105e5b2e80f..878ab8f01e61 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -183,8 +183,6 @@ public: static void DumpDeclContextHiearchy(clang::DeclContext *decl_ctx); - static bool DeclsAreEquivalent(clang::Decl *lhs_decl, clang::Decl *rhs_decl); - static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl); void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id); @@ -219,6 +217,9 @@ public: static clang::DeclContext *GetDeclContextForType(const CompilerType &type); + CompilerDeclContext + GetCompilerDeclContextForType(const CompilerType &type) override; + uint32_t GetPointerByteSize() override; clang::TranslationUnitDecl *GetTranslationUnitDecl() { @@ -514,7 +515,7 @@ public: size_t bit_size); // TypeSystem methods - DWARFASTParser *GetDWARFParser() override; + plugin::dwarf::DWARFASTParser *GetDWARFParser() override; #ifdef LLDB_ENABLE_ALL PDBASTParser *GetPDBParser() override; npdb::PdbAstBuilder *GetNativePDBParser() override; @@ -557,6 +558,9 @@ public: CompilerType DeclGetFunctionArgumentType(void *opaque_decl, size_t arg_idx) override; + std::vector<lldb_private::CompilerContext> + DeclGetCompilerContext(void *opaque_decl) override; + CompilerType GetTypeForDecl(void *opaque_decl) override; // CompilerDeclContext override functions @@ -586,6 +590,9 @@ public: lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) override; + std::vector<lldb_private::CompilerContext> + DeclContextGetCompilerContext(void *opaque_decl_ctx) override; + // Clang specific clang::DeclContext functions static clang::DeclContext * @@ -634,8 +641,7 @@ public: bool IsConst(lldb::opaque_compiler_type_t type) override; - bool IsCStringType(lldb::opaque_compiler_type_t type, - uint32_t &length) override; + bool IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length); static bool IsCXXClassType(const CompilerType &type); @@ -802,6 +808,10 @@ public: // Create related types using the current type's AST CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override; + // Create a generic function prototype that can be used in ValuObject types + // to correctly display a function pointer with the right value and summary. + CompilerType CreateGenericFunctionPrototype() override; + // Exploring the type const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override; @@ -981,8 +991,8 @@ public: const char *name, // the full symbol name as seen in the symbol table // (lldb::opaque_compiler_type_t type, "-[NString // stringWithCString:]") - const CompilerType &method_compiler_type, lldb::AccessType access, - bool is_artificial, bool is_variadic, bool is_objc_direct_call); + const CompilerType &method_compiler_type, bool is_artificial, + bool is_variadic, bool is_objc_direct_call); static bool SetHasExternalStorage(lldb::opaque_compiler_type_t type, bool has_extern); @@ -1031,23 +1041,12 @@ public: /// The name of the symbol to dump, if it is empty dump all the symbols void DumpFromSymbolFile(Stream &s, llvm::StringRef symbol_name); - void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, - Stream &s, lldb::Format format, const DataExtractor &data, - lldb::offset_t data_offset, size_t data_byte_size, - uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, - bool show_types, bool show_summary, bool verbose, - uint32_t depth) override; - bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream &s, lldb::Format format, const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) override; - void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, - Stream &s, const DataExtractor &data, - lldb::offset_t data_offset, size_t data_byte_size) override; - void DumpTypeDescription( lldb::opaque_compiler_type_t type, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override; diff --git a/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp b/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp index 280425d5874b..c9796973940a 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp @@ -178,11 +178,7 @@ void CompileUnit::SetLineTable(LineTable *line_table) { m_line_table_up.reset(line_table); } -void CompileUnit::SetSupportFiles(const FileSpecList &support_files) { - m_support_files = support_files; -} - -void CompileUnit::SetSupportFiles(FileSpecList &&support_files) { +void CompileUnit::SetSupportFiles(FileSpecList support_files) { m_support_files = std::move(support_files); } diff --git a/contrib/llvm-project/lldb/source/Symbol/CompilerDecl.cpp b/contrib/llvm-project/lldb/source/Symbol/CompilerDecl.cpp index 3cafa9535a72..0eb630e5b9e1 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompilerDecl.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompilerDecl.cpp @@ -47,3 +47,8 @@ bool lldb_private::operator!=(const lldb_private::CompilerDecl &lhs, return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl(); } + +std::vector<lldb_private::CompilerContext> +CompilerDecl::GetCompilerContext() const { + return m_type_system->DeclGetCompilerContext(m_opaque_decl); +} diff --git a/contrib/llvm-project/lldb/source/Symbol/CompilerDeclContext.cpp b/contrib/llvm-project/lldb/source/Symbol/CompilerDeclContext.cpp index a188e60251f7..b40a08e9b195 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompilerDeclContext.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompilerDeclContext.cpp @@ -59,6 +59,13 @@ bool CompilerDeclContext::IsContainedInLookup(CompilerDeclContext other) const { other.m_opaque_decl_ctx); } +std::vector<lldb_private::CompilerContext> +CompilerDeclContext::GetCompilerContext() const { + if (IsValid()) + return m_type_system->DeclContextGetCompilerContext(m_opaque_decl_ctx); + return {}; +} + bool lldb_private::operator==(const lldb_private::CompilerDeclContext &lhs, const lldb_private::CompilerDeclContext &rhs) { return lhs.GetTypeSystem() == rhs.GetTypeSystem() && diff --git a/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp b/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp index 90d17b921a96..76b79daa6ac1 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp @@ -9,7 +9,6 @@ #include "lldb/Symbol/CompilerType.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -109,13 +108,6 @@ bool CompilerType::IsConst() const { return false; } -bool CompilerType::IsCStringType(uint32_t &length) const { - if (IsValid()) - if (auto type_system_sp = GetTypeSystem()) - return type_system_sp->IsCStringType(m_type, length); - return false; -} - bool CompilerType::IsFunctionType() const { if (IsValid()) if (auto type_system_sp = GetTypeSystem()) @@ -310,6 +302,192 @@ bool CompilerType::IsBeingDefined() const { return false; } +bool CompilerType::IsInteger() const { + bool is_signed = false; // May be reset by the call below. + return IsIntegerType(is_signed); +} + +bool CompilerType::IsFloat() const { + uint32_t count = 0; + bool is_complex = false; + return IsFloatingPointType(count, is_complex); +} + +bool CompilerType::IsEnumerationType() const { + bool is_signed = false; // May be reset by the call below. + return IsEnumerationType(is_signed); +} + +bool CompilerType::IsUnscopedEnumerationType() const { + return IsEnumerationType() && !IsScopedEnumerationType(); +} + +bool CompilerType::IsIntegerOrUnscopedEnumerationType() const { + return IsInteger() || IsUnscopedEnumerationType(); +} + +bool CompilerType::IsSigned() const { + return GetTypeInfo() & lldb::eTypeIsSigned; +} + +bool CompilerType::IsNullPtrType() const { + return GetCanonicalType().GetBasicTypeEnumeration() == + lldb::eBasicTypeNullPtr; +} + +bool CompilerType::IsBoolean() const { + return GetCanonicalType().GetBasicTypeEnumeration() == lldb::eBasicTypeBool; +} + +bool CompilerType::IsEnumerationIntegerTypeSigned() const { + if (IsValid()) + return GetEnumerationIntegerType().GetTypeInfo() & lldb::eTypeIsSigned; + + return false; +} + +bool CompilerType::IsScalarOrUnscopedEnumerationType() const { + return IsScalarType() || IsUnscopedEnumerationType(); +} + +bool CompilerType::IsPromotableIntegerType() const { + // Unscoped enums are always considered as promotable, even if their + // underlying type does not need to be promoted (e.g. "int"). + if (IsUnscopedEnumerationType()) + return true; + + switch (GetCanonicalType().GetBasicTypeEnumeration()) { + case lldb::eBasicTypeBool: + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + case lldb::eBasicTypeShort: + case lldb::eBasicTypeUnsignedShort: + case lldb::eBasicTypeWChar: + case lldb::eBasicTypeSignedWChar: + case lldb::eBasicTypeUnsignedWChar: + case lldb::eBasicTypeChar16: + case lldb::eBasicTypeChar32: + return true; + + default: + return false; + } + + llvm_unreachable("All cases handled above."); +} + +bool CompilerType::IsPointerToVoid() const { + if (!IsValid()) + return false; + + return IsPointerType() && + GetPointeeType().GetBasicTypeEnumeration() == lldb::eBasicTypeVoid; +} + +bool CompilerType::IsRecordType() const { + if (!IsValid()) + return false; + + return GetCanonicalType().GetTypeClass() & + (lldb::eTypeClassClass | lldb::eTypeClassStruct | + lldb::eTypeClassUnion); +} + +bool CompilerType::IsVirtualBase(CompilerType target_base, + CompilerType *virtual_base, + bool carry_virtual) const { + if (CompareTypes(target_base)) + return carry_virtual; + + if (!carry_virtual) { + uint32_t num_virtual_bases = GetNumVirtualBaseClasses(); + for (uint32_t i = 0; i < num_virtual_bases; ++i) { + uint32_t bit_offset; + auto base = GetVirtualBaseClassAtIndex(i, &bit_offset); + if (base.IsVirtualBase(target_base, virtual_base, + /*carry_virtual*/ true)) { + if (virtual_base) + *virtual_base = base; + + return true; + } + } + } + + uint32_t num_direct_bases = GetNumDirectBaseClasses(); + for (uint32_t i = 0; i < num_direct_bases; ++i) { + uint32_t bit_offset; + auto base = GetDirectBaseClassAtIndex(i, &bit_offset); + if (base.IsVirtualBase(target_base, virtual_base, carry_virtual)) + return true; + } + + return false; +} + +bool CompilerType::IsContextuallyConvertibleToBool() const { + return IsScalarType() || IsUnscopedEnumerationType() || IsPointerType() || + IsNullPtrType() || IsArrayType(); +} + +bool CompilerType::IsBasicType() const { + return GetCanonicalType().GetBasicTypeEnumeration() != + lldb::eBasicTypeInvalid; +} + +std::string CompilerType::TypeDescription() { + auto name = GetTypeName(); + auto canonical_name = GetCanonicalType().GetTypeName(); + if (name.IsEmpty() || canonical_name.IsEmpty()) + return "''"; // Should not happen, unless the input is broken somehow. + + if (name == canonical_name) + return llvm::formatv("'{0}'", name); + + return llvm::formatv("'{0}' (canonically referred to as '{1}')", name, + canonical_name); +} + +bool CompilerType::CompareTypes(CompilerType rhs) const { + if (*this == rhs) + return true; + + const ConstString name = GetFullyUnqualifiedType().GetTypeName(); + const ConstString rhs_name = rhs.GetFullyUnqualifiedType().GetTypeName(); + return name == rhs_name; +} + +const char *CompilerType::GetTypeTag() { + switch (GetTypeClass()) { + case lldb::eTypeClassClass: + return "class"; + case lldb::eTypeClassEnumeration: + return "enum"; + case lldb::eTypeClassStruct: + return "struct"; + case lldb::eTypeClassUnion: + return "union"; + default: + return "unknown"; + } + llvm_unreachable("All cases are covered by code above."); +} + +uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() { + uint32_t ret = 0; + uint32_t num_direct_bases = GetNumDirectBaseClasses(); + + for (uint32_t i = 0; i < num_direct_bases; ++i) { + uint32_t bit_offset; + CompilerType base_type = GetDirectBaseClassAtIndex(i, &bit_offset); + if (base_type.GetNumFields() > 0 || + base_type.GetNumberOfNonEmptyBaseClasses() > 0) + ret += 1; + } + return ret; +} + // Type Completion bool CompilerType::GetCompleteType() const { @@ -822,20 +1000,6 @@ CompilerType::GetIndexOfChildWithName(llvm::StringRef name, // Dumping types -void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s, - lldb::Format format, const DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size, uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, bool show_types, - bool show_summary, bool verbose, uint32_t depth) { - if (!IsValid()) - if (auto type_system_sp = GetTypeSystem()) - type_system_sp->DumpValue(m_type, exe_ctx, *s, format, data, - data_byte_offset, data_byte_size, - bitfield_bit_size, bitfield_bit_offset, - show_types, show_summary, verbose, depth); -} - bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format, const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size, @@ -850,16 +1014,6 @@ bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format, return false; } -void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s, - const DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size) { - if (IsValid()) - if (auto type_system_sp = GetTypeSystem()) - type_system_sp->DumpSummary(m_type, exe_ctx, *s, data, data_byte_offset, - data_byte_size); -} - void CompilerType::DumpTypeDescription(lldb::DescriptionLevel level) const { if (IsValid()) if (auto type_system_sp = GetTypeSystem()) @@ -983,6 +1137,18 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data, return false; } +CompilerType::CompilerType(CompilerType::TypeSystemSPWrapper type_system, + lldb::opaque_compiler_type_t type) + : m_type_system(type_system.GetSharedPointer()), m_type(type) { + assert(Verify() && "verification failed"); +} + +CompilerType::CompilerType(lldb::TypeSystemWP type_system, + lldb::opaque_compiler_type_t type) + : m_type_system(type_system), m_type(type) { + assert(Verify() && "verification failed"); +} + #ifndef NDEBUG bool CompilerType::Verify() const { if (!IsValid()) diff --git a/contrib/llvm-project/lldb/source/Symbol/Function.cpp b/contrib/llvm-project/lldb/source/Symbol/Function.cpp index 5ed0e66bdacb..fdc090355771 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Function.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Function.cpp @@ -122,6 +122,13 @@ size_t InlineFunctionInfo::MemorySize() const { /// @name Call site related structures /// @{ +CallEdge::~CallEdge() = default; + +CallEdge::CallEdge(AddrType caller_address_type, lldb::addr_t caller_address, + bool is_tail_call, CallSiteParameterArray &¶meters) + : caller_address(caller_address), caller_address_type(caller_address_type), + is_tail_call(is_tail_call), parameters(std::move(parameters)) {} + lldb::addr_t CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc, Function &caller, Target &target) { Log *log = GetLog(LLDBLog::Step); @@ -185,12 +192,30 @@ void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList &images) { resolved = true; } +DirectCallEdge::DirectCallEdge(const char *symbol_name, + AddrType caller_address_type, + lldb::addr_t caller_address, bool is_tail_call, + CallSiteParameterArray &¶meters) + : CallEdge(caller_address_type, caller_address, is_tail_call, + std::move(parameters)) { + lazy_callee.symbol_name = symbol_name; +} + Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &) { ParseSymbolFileAndResolve(images); assert(resolved && "Did not resolve lazy callee"); return lazy_callee.def; } +IndirectCallEdge::IndirectCallEdge(DWARFExpressionList call_target, + AddrType caller_address_type, + lldb::addr_t caller_address, + bool is_tail_call, + CallSiteParameterArray &¶meters) + : CallEdge(caller_address_type, caller_address, is_tail_call, + std::move(parameters)), + call_target(std::move(call_target)) {} + Function *IndirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &exe_ctx) { Log *log = GetLog(LLDBLog::Step); @@ -371,6 +396,15 @@ void Function::GetDescription(Stream *s, lldb::DescriptionLevel level, s->AsRawOstream() << ", name = \"" << name << '"'; if (mangled) s->AsRawOstream() << ", mangled = \"" << mangled << '"'; + if (level == eDescriptionLevelVerbose) { + *s << ", decl_context = {"; + auto decl_context = GetCompilerContext(); + // Drop the function itself from the context chain. + if (decl_context.size()) + decl_context.pop_back(); + llvm::interleaveComma(decl_context, *s, [&](auto &ctx) { ctx.Dump(*s); }); + *s << "}"; + } *s << ", range = "; Address::DumpStyle fallback_style; if (level == eDescriptionLevelVerbose) @@ -488,13 +522,17 @@ ConstString Function::GetDisplayName() const { } CompilerDeclContext Function::GetDeclContext() { - ModuleSP module_sp = CalculateSymbolContextModule(); - - if (module_sp) { + if (ModuleSP module_sp = CalculateSymbolContextModule()) if (SymbolFile *sym_file = module_sp->GetSymbolFile()) return sym_file->GetDeclContextForUID(GetID()); - } - return CompilerDeclContext(); + return {}; +} + +std::vector<CompilerContext> Function::GetCompilerContext() { + if (ModuleSP module_sp = CalculateSymbolContextModule()) + if (SymbolFile *sym_file = module_sp->GetSymbolFile()) + return sym_file->GetCompilerContextForUID(GetID()); + return {}; } Type *Function::GetType() { diff --git a/contrib/llvm-project/lldb/source/Symbol/LineTable.cpp b/contrib/llvm-project/lldb/source/Symbol/LineTable.cpp index 59b5d6125e04..abe4c98d5928 100644 --- a/contrib/llvm-project/lldb/source/Symbol/LineTable.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/LineTable.cpp @@ -89,7 +89,7 @@ void LineTable::AppendLineEntryToSequence( if (!entries.empty() && entries.back().file_addr == file_addr) { // GCC don't use the is_prologue_end flag to mark the first instruction // after the prologue. - // Instead of it it is issuing a line table entry for the first instruction + // Instead of it is issuing a line table entry for the first instruction // of the prologue and one for the first instruction after the prologue. If // the size of the prologue is 0 instruction then the 2 line entry will // have the same file address. Removing it will remove our ability to diff --git a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp b/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp deleted file mode 100644 index 66ee7589ac60..000000000000 --- a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp +++ /dev/null @@ -1,449 +0,0 @@ -//===-- LocateSymbolFile.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/Symbol/LocateSymbolFile.h" - -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/Progress.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/LLDBLog.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/Timer.h" -#include "lldb/Utility/UUID.h" - -#include "llvm/ADT/SmallSet.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/ThreadPool.h" - -// From MacOSX system header "mach/machine.h" -typedef int cpu_type_t; -typedef int cpu_subtype_t; - -using namespace lldb; -using namespace lldb_private; - -#if defined(__APPLE__) - -// Forward declaration of method defined in source/Host/macosx/Symbols.cpp -int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, - ModuleSpec &return_module_spec); - -#else - -int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, - ModuleSpec &return_module_spec) { - // Cannot find MacOSX files using debug symbols on non MacOSX. - return 0; -} - -#endif - -static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, - const ArchSpec *arch, - const lldb_private::UUID *uuid) { - ModuleSpecList module_specs; - if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) { - ModuleSpec spec; - for (size_t i = 0; i < module_specs.GetSize(); ++i) { - bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); - UNUSED_IF_ASSERT_DISABLED(got_spec); - assert(got_spec); - if ((uuid == nullptr || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && - (arch == nullptr || - (spec.GetArchitecturePtr() && - spec.GetArchitecture().IsCompatibleMatch(*arch)))) { - return true; - } - } - } - return false; -} - -// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid, -// return true if there is a matching dSYM bundle next to the exec_fspec, -// and return that value in dsym_fspec. -// If there is a .dSYM.yaa compressed archive next to the exec_fspec, -// call through Symbols::DownloadObjectAndSymbolFile to download the -// expanded/uncompressed dSYM and return that filepath in dsym_fspec. - -static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec, - const FileSpec &exec_fspec, - FileSpec &dsym_fspec) { - ConstString filename = exec_fspec.GetFilename(); - FileSpec dsym_directory = exec_fspec; - dsym_directory.RemoveLastPathComponent(); - - std::string dsym_filename = filename.AsCString(); - dsym_filename += ".dSYM"; - dsym_directory.AppendPathComponent(dsym_filename); - dsym_directory.AppendPathComponent("Contents"); - dsym_directory.AppendPathComponent("Resources"); - dsym_directory.AppendPathComponent("DWARF"); - - if (FileSystem::Instance().Exists(dsym_directory)) { - - // See if the binary name exists in the dSYM DWARF - // subdir. - dsym_fspec = dsym_directory; - dsym_fspec.AppendPathComponent(filename.AsCString()); - if (FileSystem::Instance().Exists(dsym_fspec) && - FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(), - mod_spec.GetUUIDPtr())) { - return true; - } - - // See if we have "../CF.framework" - so we'll look for - // CF.framework.dSYM/Contents/Resources/DWARF/CF - // We need to drop the last suffix after '.' to match - // 'CF' in the DWARF subdir. - std::string binary_name(filename.AsCString()); - auto last_dot = binary_name.find_last_of('.'); - if (last_dot != std::string::npos) { - binary_name.erase(last_dot); - dsym_fspec = dsym_directory; - dsym_fspec.AppendPathComponent(binary_name); - if (FileSystem::Instance().Exists(dsym_fspec) && - FileAtPathContainsArchAndUUID(dsym_fspec, - mod_spec.GetArchitecturePtr(), - mod_spec.GetUUIDPtr())) { - return true; - } - } - } - - // See if we have a .dSYM.yaa next to this executable path. - FileSpec dsym_yaa_fspec = exec_fspec; - dsym_yaa_fspec.RemoveLastPathComponent(); - std::string dsym_yaa_filename = filename.AsCString(); - dsym_yaa_filename += ".dSYM.yaa"; - dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename); - - if (FileSystem::Instance().Exists(dsym_yaa_fspec)) { - ModuleSpec mutable_mod_spec = mod_spec; - Status error; - if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, error, true) && - FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) { - dsym_fspec = mutable_mod_spec.GetSymbolFileSpec(); - return true; - } - } - - return false; -} - -// Given a ModuleSpec with a FileSpec and optionally uuid/architecture -// filled in, look for a .dSYM bundle next to that binary. Returns true -// if a .dSYM bundle is found, and that path is returned in the dsym_fspec -// FileSpec. -// -// This routine looks a few directory layers above the given exec_path - -// exec_path might be /System/Library/Frameworks/CF.framework/CF and the -// dSYM might be /System/Library/Frameworks/CF.framework.dSYM. -// -// If there is a .dSYM.yaa compressed archive found next to the binary, -// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM - -static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, - FileSpec &dsym_fspec) { - Log *log = GetLog(LLDBLog::Host); - const FileSpec &exec_fspec = module_spec.GetFileSpec(); - if (exec_fspec) { - if (::LookForDsymNextToExecutablePath(module_spec, exec_fspec, - dsym_fspec)) { - if (log) { - LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); - } - return true; - } else { - FileSpec parent_dirs = exec_fspec; - - // Remove the binary name from the FileSpec - parent_dirs.RemoveLastPathComponent(); - - // Add a ".dSYM" name to each directory component of the path, - // stripping off components. e.g. we may have a binary like - // /S/L/F/Foundation.framework/Versions/A/Foundation and - // /S/L/F/Foundation.framework.dSYM - // - // so we'll need to start with - // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the - // "A", and if that doesn't exist, strip off the "A" and try it again - // with "Versions", etc., until we find a dSYM bundle or we've - // stripped off enough path components that there's no need to - // continue. - - for (int i = 0; i < 4; i++) { - // Does this part of the path have a "." character - could it be a - // bundle's top level directory? - const char *fn = parent_dirs.GetFilename().AsCString(); - if (fn == nullptr) - break; - if (::strchr(fn, '.') != nullptr) { - if (::LookForDsymNextToExecutablePath(module_spec, parent_dirs, - dsym_fspec)) { - if (log) { - LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s", - dsym_fspec.GetPath().c_str()); - } - return true; - } - } - parent_dirs.RemoveLastPathComponent(); - } - } - } - dsym_fspec.Clear(); - return false; -} - -static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { - const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - - LLDB_SCOPED_TIMERF( - "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>", - arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); - - FileSpec symbol_fspec; - ModuleSpec dsym_module_spec; - // First try and find the dSYM in the same directory as the executable or in - // an appropriate parent directory - if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) { - // We failed to easily find the dSYM above, so use DebugSymbols - LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec); - } else { - dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; - } - - return dsym_module_spec.GetSymbolFileSpec(); -} - -ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) { - ModuleSpec result; - const FileSpec &exec_fspec = module_spec.GetFileSpec(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - LLDB_SCOPED_TIMERF( - "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec.GetFilename().AsCString("<NULL>") : "<NULL>", - arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid); - - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - if (exec_fspec && - ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { - result.GetFileSpec() = exec_fspec; - } else { - LocateMacOSXFilesUsingDebugSymbols(module_spec, result); - } - - return result; -} - -// Keep "symbols.enable-external-lookup" description in sync with this function. - -FileSpec -Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec, - const FileSpecList &default_search_paths) { - FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); - if (symbol_file_spec.IsAbsolute() && - FileSystem::Instance().Exists(symbol_file_spec)) - return symbol_file_spec; - - Progress progress(llvm::formatv( - "Locating external symbol file for {0}", - module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"))); - - FileSpecList debug_file_search_paths = default_search_paths; - - // Add module directory. - FileSpec module_file_spec = module_spec.GetFileSpec(); - // We keep the unresolved pathname if it fails. - FileSystem::Instance().ResolveSymbolicLink(module_file_spec, - module_file_spec); - - ConstString file_dir = module_file_spec.GetDirectory(); - { - FileSpec file_spec(file_dir.AsCString(".")); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } - - if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { - - // Add current working directory. - { - FileSpec file_spec("."); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } - -#ifndef _WIN32 -#if defined(__NetBSD__) - // Add /usr/libdata/debug directory. - { - FileSpec file_spec("/usr/libdata/debug"); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } -#else - // Add /usr/lib/debug directory. - { - FileSpec file_spec("/usr/lib/debug"); - FileSystem::Instance().Resolve(file_spec); - debug_file_search_paths.AppendIfUnique(file_spec); - } -#endif -#endif // _WIN32 - } - - std::string uuid_str; - const UUID &module_uuid = module_spec.GetUUID(); - if (module_uuid.IsValid()) { - // Some debug files are stored in the .build-id directory like this: - // /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug - uuid_str = module_uuid.GetAsString(""); - std::transform(uuid_str.begin(), uuid_str.end(), uuid_str.begin(), - ::tolower); - uuid_str.insert(2, 1, '/'); - uuid_str = uuid_str + ".debug"; - } - - size_t num_directories = debug_file_search_paths.GetSize(); - for (size_t idx = 0; idx < num_directories; ++idx) { - FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx); - FileSystem::Instance().Resolve(dirspec); - if (!FileSystem::Instance().IsDirectory(dirspec)) - continue; - - std::vector<std::string> files; - std::string dirname = dirspec.GetPath(); - - if (!uuid_str.empty()) - files.push_back(dirname + "/.build-id/" + uuid_str); - if (symbol_file_spec.GetFilename()) { - files.push_back(dirname + "/" + - symbol_file_spec.GetFilename().GetCString()); - files.push_back(dirname + "/.debug/" + - symbol_file_spec.GetFilename().GetCString()); - - // Some debug files may stored in the module directory like this: - // /usr/lib/debug/usr/lib/library.so.debug - if (!file_dir.IsEmpty()) - files.push_back(dirname + file_dir.AsCString() + "/" + - symbol_file_spec.GetFilename().GetCString()); - } - - const uint32_t num_files = files.size(); - for (size_t idx_file = 0; idx_file < num_files; ++idx_file) { - const std::string &filename = files[idx_file]; - FileSpec file_spec(filename); - FileSystem::Instance().Resolve(file_spec); - - if (llvm::sys::fs::equivalent(file_spec.GetPath(), - module_file_spec.GetPath())) - continue; - - if (FileSystem::Instance().Exists(file_spec)) { - lldb_private::ModuleSpecList specs; - const size_t num_specs = - ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs); - ModuleSpec mspec; - bool valid_mspec = false; - if (num_specs == 2) { - // Special case to handle both i386 and i686 from ObjectFilePECOFF - ModuleSpec mspec2; - if (specs.GetModuleSpecAtIndex(0, mspec) && - specs.GetModuleSpecAtIndex(1, mspec2) && - mspec.GetArchitecture().GetTriple().isCompatibleWith( - mspec2.GetArchitecture().GetTriple())) { - valid_mspec = true; - } - } - if (!valid_mspec) { - assert(num_specs <= 1 && - "Symbol Vendor supports only a single architecture"); - if (num_specs == 1) { - if (specs.GetModuleSpecAtIndex(0, mspec)) { - valid_mspec = true; - } - } - } - if (valid_mspec) { - // Skip the uuids check if module_uuid is invalid. For example, - // this happens for *.dwp files since at the moment llvm-dwp - // doesn't output build ids, nor does binutils dwp. - if (!module_uuid.IsValid() || module_uuid == mspec.GetUUID()) - return file_spec; - } - } - } - } - - return LocateExecutableSymbolFileDsym(module_spec); -} - -void Symbols::DownloadSymbolFileAsync(const UUID &uuid) { - if (!ModuleList::GetGlobalModuleListProperties().GetEnableBackgroundLookup()) - return; - - static llvm::SmallSet<UUID, 8> g_seen_uuids; - static std::mutex g_mutex; - Debugger::GetThreadPool().async([=]() { - { - std::lock_guard<std::mutex> guard(g_mutex); - if (g_seen_uuids.count(uuid)) - return; - g_seen_uuids.insert(uuid); - } - - Status error; - ModuleSpec module_spec; - module_spec.GetUUID() = uuid; - if (!Symbols::DownloadObjectAndSymbolFile(module_spec, error, - /*force_lookup=*/true, - /*copy_executable=*/false)) - return; - - if (error.Fail()) - return; - - Debugger::ReportSymbolChange(module_spec); - }); -} - -#if !defined(__APPLE__) - -FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle, - const lldb_private::UUID *uuid, - const ArchSpec *arch) { - // FIXME - return FileSpec(); -} - -bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, - Status &error, bool force_lookup, - bool copy_executable) { - // Fill in the module_spec.GetFileSpec() for the object file and/or the - // module_spec.GetSymbolFileSpec() for the debug symbols file. - return false; -} - -#endif diff --git a/contrib/llvm-project/lldb/source/Symbol/ObjectFile.cpp b/contrib/llvm-project/lldb/source/Symbol/ObjectFile.cpp index bebc9589418c..d890ad92e831 100644 --- a/contrib/llvm-project/lldb/source/Symbol/ObjectFile.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/ObjectFile.cpp @@ -357,6 +357,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { case eSectionTypeDWARFAppleObjC: case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: + case eSectionTypeSwiftModules: return AddressClass::eDebug; case eSectionTypeEHFrame: case eSectionTypeARMexidx: @@ -550,8 +551,8 @@ size_t ObjectFile::ReadSectionData(Section *section, // The object file now contains a full mmap'ed copy of the object file // data, so just use this - return GetData(section->GetFileOffset(), section->GetFileSize(), - section_data); + return GetData(section->GetFileOffset(), GetSectionDataSize(section), + section_data); } bool ObjectFile::SplitArchivePathWithObject(llvm::StringRef path_with_object, @@ -606,15 +607,15 @@ lldb::SymbolType ObjectFile::GetSymbolTypeFromName(llvm::StringRef name, lldb::SymbolType symbol_type_hint) { if (!name.empty()) { - if (name.startswith("_OBJC_")) { + if (name.starts_with("_OBJC_")) { // ObjC - if (name.startswith("_OBJC_CLASS_$_")) + if (name.starts_with("_OBJC_CLASS_$_")) return lldb::eSymbolTypeObjCClass; - if (name.startswith("_OBJC_METACLASS_$_")) + if (name.starts_with("_OBJC_METACLASS_$_")) return lldb::eSymbolTypeObjCMetaClass; - if (name.startswith("_OBJC_IVAR_$_")) + if (name.starts_with("_OBJC_IVAR_$_")) return lldb::eSymbolTypeObjCIVar; - } else if (name.startswith(".objc_class_name_")) { + } else if (name.starts_with(".objc_class_name_")) { // ObjC v1 return lldb::eSymbolTypeObjCClass; } diff --git a/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp b/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp index 26b4c4d62ad9..08900a3ef349 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp @@ -8,6 +8,8 @@ #include "lldb/Symbol/Symbol.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/Section.h" @@ -225,7 +227,7 @@ bool Symbol::IsTrampoline() const { return m_type == eSymbolTypeTrampoline; } bool Symbol::IsIndirect() const { return m_type == eSymbolTypeResolver; } void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level, - Target *target) const { + Target *target, llvm::StringRef pattern) const { s->Printf("id = {0x%8.8x}", m_uid); if (m_addr_range.GetBaseAddress().GetSection()) { @@ -252,11 +254,24 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level, s->Printf(", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset()); } - ConstString demangled = GetMangled().GetDemangledName(); - if (demangled) - s->Printf(", name=\"%s\"", demangled.AsCString()); - if (m_mangled.GetMangledName()) - s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString()); + llvm::StringRef ansi_prefix; + llvm::StringRef ansi_suffix; + if (target) { + ansi_prefix = target->GetDebugger().GetRegexMatchAnsiPrefix(); + ansi_suffix = target->GetDebugger().GetRegexMatchAnsiSuffix(); + } + if (ConstString demangled = m_mangled.GetDemangledName()) { + s->PutCString(", name=\""); + s->PutCStringColorHighlighted(demangled.GetStringRef(), pattern, + ansi_prefix, ansi_suffix); + s->PutCString("\""); + } + if (ConstString mangled_name = m_mangled.GetMangledName()) { + s->PutCString(", mangled=\""); + s->PutCStringColorHighlighted(mangled_name.GetStringRef(), pattern, + ansi_prefix, ansi_suffix); + s->PutCString("\""); + } } void Symbol::Dump(Stream *s, Target *target, uint32_t index, @@ -619,7 +634,7 @@ bool Symbol::IsSyntheticWithAutoGeneratedName() const { if (!m_mangled) return true; ConstString demangled = m_mangled.GetDemangledName(); - return demangled.GetStringRef().startswith(GetSyntheticSymbolPrefix()); + return demangled.GetStringRef().starts_with(GetSyntheticSymbolPrefix()); } void Symbol::SynthesizeNameIfNeeded() const { diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp index 63968ec2d150..9fd40b5ca567 100644 --- a/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp @@ -8,6 +8,7 @@ #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -71,7 +72,8 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, const Address &addr, bool show_fullpaths, bool show_module, bool show_inlined_frames, bool show_function_arguments, - bool show_function_name) const { + bool show_function_name, + llvm::StringRef pattern) const { bool dumped_something = false; if (show_module && module_sp) { if (show_fullpaths) @@ -81,7 +83,6 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, s->PutChar('`'); dumped_something = true; } - if (function != nullptr) { SymbolContext inline_parent_sc; Address inline_parent_addr; @@ -94,8 +95,16 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, name = function->GetNameNoArguments(); if (!name) name = function->GetName(); - if (name) - name.Dump(s); + if (name) { + llvm::StringRef ansi_prefix; + llvm::StringRef ansi_suffix; + if (target_sp) { + ansi_prefix = target_sp->GetDebugger().GetRegexMatchAnsiPrefix(); + ansi_suffix = target_sp->GetDebugger().GetRegexMatchAnsiSuffix(); + } + s->PutCStringColorHighlighted(name.GetStringRef(), pattern, ansi_prefix, + ansi_suffix); + } } if (addr.IsValid()) { @@ -163,7 +172,14 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, dumped_something = true; if (symbol->GetType() == eSymbolTypeTrampoline) s->PutCString("symbol stub for: "); - symbol->GetName().Dump(s); + llvm::StringRef ansi_prefix; + llvm::StringRef ansi_suffix; + if (target_sp) { + ansi_prefix = target_sp->GetDebugger().GetRegexMatchAnsiPrefix(); + ansi_suffix = target_sp->GetDebugger().GetRegexMatchAnsiSuffix(); + } + s->PutCStringColorHighlighted(symbol->GetName().GetStringRef(), pattern, + ansi_prefix, ansi_suffix); } if (addr.IsValid() && symbol->ValueIsAddress()) { @@ -186,7 +202,8 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, } void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, - Target *target) const { + Target *target, + llvm::StringRef pattern) const { if (module_sp) { s->Indent(" Module: file = \""); module_sp->GetFileSpec().Dump(s->AsRawOstream()); @@ -246,7 +263,7 @@ void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, if (symbol != nullptr) { s->Indent(" Symbol: "); - symbol->GetDescription(s, level, target); + symbol->GetDescription(s, level, target, pattern); s->EOL(); } diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp index b271efd07bfe..e318e2beb654 100644 --- a/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp @@ -18,6 +18,7 @@ #include "lldb/Symbol/VariableList.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private.h" #include <future> @@ -133,17 +134,6 @@ void SymbolFile::GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names) {} -void SymbolFile::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) {} - -void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern, - LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) {} - void SymbolFile::AssertModuleLock() { // The code below is too expensive to leave enabled in release builds. It's // enabled in debug builds or when the correct macro is set. @@ -215,7 +205,7 @@ void SymbolFileCommon::SetCompileUnitAtIndex(uint32_t idx, std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const size_t num_compile_units = GetNumCompileUnits(); assert(idx < num_compile_units); - (void)num_compile_units; + UNUSED_IF_ASSERT_DISABLED(num_compile_units); // Fire off an assertion if this compile unit already exists for now. The // partial parsing should take care of only setting the compile unit diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp index d3694580194f..33995252bfe2 100644 --- a/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp @@ -1,4 +1,4 @@ -//===-- SymbolFileDWARFDebugMap.cpp ---------------------------------------===// +//===-- SymbolFileOnDemand.cpp ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -431,31 +431,14 @@ void SymbolFileOnDemand::GetMangledNamesForFunction( mangled_names); } -void SymbolFileOnDemand::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - if (!m_debug_info_enabled) { - Log *log = GetLog(); - LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(), - __FUNCTION__, name); - return; - } - return m_sym_file_impl->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); -} - -void SymbolFileOnDemand::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { +void SymbolFileOnDemand::FindTypes(const TypeQuery &match, + TypeResults &results) { if (!m_debug_info_enabled) { LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__); return; } - return m_sym_file_impl->FindTypes(pattern, languages, searched_symbol_files, - types); + return m_sym_file_impl->FindTypes(match, results); } void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope, diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolLocator.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolLocator.cpp new file mode 100644 index 000000000000..918f13ed9c19 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolLocator.cpp @@ -0,0 +1,47 @@ +//===-- symbolLocator.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/Symbol/SymbolLocator.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" + +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/ThreadPool.h" + +using namespace lldb; +using namespace lldb_private; + +void SymbolLocator::DownloadSymbolFileAsync(const UUID &uuid) { + if (!ModuleList::GetGlobalModuleListProperties().GetEnableBackgroundLookup()) + return; + + static llvm::SmallSet<UUID, 8> g_seen_uuids; + static std::mutex g_mutex; + Debugger::GetThreadPool().async([=]() { + { + std::lock_guard<std::mutex> guard(g_mutex); + if (g_seen_uuids.count(uuid)) + return; + g_seen_uuids.insert(uuid); + } + + Status error; + ModuleSpec module_spec; + module_spec.GetUUID() = uuid; + if (!PluginManager::DownloadObjectAndSymbolFile(module_spec, error, + /*force_lookup=*/true, + /*copy_executable=*/false)) + return; + + if (error.Fail()) + return; + + Debugger::ReportSymbolChange(module_spec); + }); +} diff --git a/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp b/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp index cf8732530c1a..564a3a94cfa2 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp @@ -233,7 +233,7 @@ static bool lldb_skip_name(llvm::StringRef mangled, Mangled::ManglingScheme scheme) { switch (scheme) { case Mangled::eManglingSchemeItanium: { - if (mangled.size() < 3 || !mangled.startswith("_Z")) + if (mangled.size() < 3 || !mangled.starts_with("_Z")) return true; // Avoid the following types of symbols in the index. @@ -256,6 +256,7 @@ static bool lldb_skip_name(llvm::StringRef mangled, case Mangled::eManglingSchemeMSVC: case Mangled::eManglingSchemeRustV0: case Mangled::eManglingSchemeD: + case Mangled::eManglingSchemeSwift: return false; // Don't try and demangle things we can't categorize. @@ -1009,10 +1010,7 @@ void Symtab::Finalize() { // Calculate the size of symbols inside InitAddressIndexes. InitAddressIndexes(); // Shrink to fit the symbols so we don't waste memory - if (m_symbols.capacity() > m_symbols.size()) { - collection new_symbols(m_symbols.begin(), m_symbols.end()); - m_symbols.swap(new_symbols); - } + m_symbols.shrink_to_fit(); SaveToCache(); } @@ -1285,7 +1283,7 @@ bool Symtab::Encode(DataEncoder &encoder) const { // Now that all strings have been gathered, we will emit the string table. strtab.Encode(encoder); - // Followed the the symbol table data. + // Followed by the symbol table data. encoder.AppendData(symtab_encoder.GetData()); return true; } diff --git a/contrib/llvm-project/lldb/source/Symbol/Type.cpp b/contrib/llvm-project/lldb/source/Symbol/Type.cpp index 66284eb73cad..293fe1b78f4a 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Type.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Type.cpp @@ -64,49 +64,170 @@ bool lldb_private::contextMatches(llvm::ArrayRef<CompilerContext> context_chain, return true; } -void CompilerContext::Dump() const { +static CompilerContextKind ConvertTypeClass(lldb::TypeClass type_class) { + if (type_class == eTypeClassAny) + return CompilerContextKind::AnyType; + uint16_t result = 0; + if (type_class & lldb::eTypeClassClass) + result |= (uint16_t)CompilerContextKind::Class; + if (type_class & lldb::eTypeClassStruct) + result |= (uint16_t)CompilerContextKind::Struct; + if (type_class & lldb::eTypeClassUnion) + result |= (uint16_t)CompilerContextKind::Union; + if (type_class & lldb::eTypeClassEnumeration) + result |= (uint16_t)CompilerContextKind::Enum; + if (type_class & lldb::eTypeClassFunction) + result |= (uint16_t)CompilerContextKind::Function; + if (type_class & lldb::eTypeClassTypedef) + result |= (uint16_t)CompilerContextKind::Typedef; + return (CompilerContextKind)result; +} + +TypeQuery::TypeQuery(llvm::StringRef name, TypeQueryOptions options) + : m_options(options) { + llvm::StringRef scope, basename; + lldb::TypeClass type_class = lldb::eTypeClassAny; + if (Type::GetTypeScopeAndBasename(name, scope, basename, type_class)) { + if (scope.consume_front("::")) + m_options |= e_exact_match; + if (!scope.empty()) { + std::pair<llvm::StringRef, llvm::StringRef> scope_pair = + scope.split("::"); + while (!scope_pair.second.empty()) { + m_context.push_back({CompilerContextKind::AnyDeclContext, + ConstString(scope_pair.first.str())}); + scope_pair = scope_pair.second.split("::"); + } + m_context.push_back({CompilerContextKind::AnyDeclContext, + ConstString(scope_pair.first.str())}); + } + m_context.push_back( + {ConvertTypeClass(type_class), ConstString(basename.str())}); + } else { + m_context.push_back( + {CompilerContextKind::AnyType, ConstString(name.str())}); + } +} + +TypeQuery::TypeQuery(const CompilerDeclContext &decl_ctx, + ConstString type_basename, TypeQueryOptions options) + : m_options(options) { + // Always use an exact match if we are looking for a type in compiler context. + m_options |= e_exact_match; + m_context = decl_ctx.GetCompilerContext(); + m_context.push_back({CompilerContextKind::AnyType, type_basename}); +} + +TypeQuery::TypeQuery( + const llvm::ArrayRef<lldb_private::CompilerContext> &context, + TypeQueryOptions options) + : m_context(context), m_options(options) { + // Always use an exact match if we are looking for a type in compiler context. + m_options |= e_exact_match; +} + +TypeQuery::TypeQuery(const CompilerDecl &decl, TypeQueryOptions options) + : m_options(options) { + // Always for an exact match if we are looking for a type using a declaration. + m_options |= e_exact_match; + m_context = decl.GetCompilerContext(); +} + +ConstString TypeQuery::GetTypeBasename() const { + if (m_context.empty()) + return ConstString(); + return m_context.back().name; +} + +void TypeQuery::AddLanguage(LanguageType language) { + if (!m_languages) + m_languages = LanguageSet(); + m_languages->Insert(language); +} + +bool TypeQuery::ContextMatches( + llvm::ArrayRef<CompilerContext> context_chain) const { + if (GetExactMatch() || context_chain.size() == m_context.size()) + return ::contextMatches(context_chain, m_context); + + // We don't have an exact match, we need to bottom m_context.size() items to + // match for a successful lookup. + if (context_chain.size() < m_context.size()) + return false; // Not enough items in context_chain to allow for a match. + + size_t compare_count = context_chain.size() - m_context.size(); + return ::contextMatches( + llvm::ArrayRef<CompilerContext>(context_chain.data() + compare_count, + m_context.size()), + m_context); +} + +bool TypeQuery::LanguageMatches(lldb::LanguageType language) const { + // If we have no language filterm language always matches. + if (!m_languages.has_value()) + return true; + return (*m_languages)[language]; +} + +bool TypeResults::AlreadySearched(lldb_private::SymbolFile *sym_file) { + return !m_searched_symbol_files.insert(sym_file).second; +} + +bool TypeResults::InsertUnique(const lldb::TypeSP &type_sp) { + if (type_sp) + return m_type_map.InsertUnique(type_sp); + return false; +} + +bool TypeResults::Done(const TypeQuery &query) const { + if (query.GetFindOne()) + return !m_type_map.Empty(); + return false; +} + +void CompilerContext::Dump(Stream &s) const { switch (kind) { default: - printf("Invalid"); + s << "Invalid"; break; case CompilerContextKind::TranslationUnit: - printf("TranslationUnit"); + s << "TranslationUnit"; break; case CompilerContextKind::Module: - printf("Module"); + s << "Module"; break; case CompilerContextKind::Namespace: - printf("Namespace"); + s << "Namespace"; break; case CompilerContextKind::Class: - printf("Class"); + s << "Class"; break; case CompilerContextKind::Struct: - printf("Structure"); + s << "Structure"; break; case CompilerContextKind::Union: - printf("Union"); + s << "Union"; break; case CompilerContextKind::Function: - printf("Function"); + s << "Function"; break; case CompilerContextKind::Variable: - printf("Variable"); + s << "Variable"; break; case CompilerContextKind::Enum: - printf("Enumeration"); + s << "Enumeration"; break; case CompilerContextKind::Typedef: - printf("Typedef"); + s << "Typedef"; break; case CompilerContextKind::AnyModule: - printf("AnyModule"); + s << "AnyModule"; break; case CompilerContextKind::AnyType: - printf("AnyType"); + s << "AnyType"; break; } - printf("(\"%s\")\n", name.GetCString()); + s << "(" << name << ")"; } class TypeAppendVisitor { @@ -312,30 +433,6 @@ ConstString Type::GetBaseName() { void Type::DumpTypeName(Stream *s) { GetName().Dump(s, "<invalid-type-name>"); } -void Type::DumpValue(ExecutionContext *exe_ctx, Stream *s, - const DataExtractor &data, uint32_t data_byte_offset, - bool show_types, bool show_summary, bool verbose, - lldb::Format format) { - if (ResolveCompilerType(ResolveState::Forward)) { - if (show_types) { - s->PutChar('('); - if (verbose) - s->Printf("Type{0x%8.8" PRIx64 "} ", GetID()); - DumpTypeName(s); - s->PutCString(") "); - } - - GetForwardCompilerType().DumpValue( - exe_ctx, s, format == lldb::eFormatDefault ? GetFormat() : format, data, - data_byte_offset, - GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr) - .value_or(0), - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, show_summary, verbose, 0); - } -} - Type *Type::GetEncodingType() { if (m_encoding_type == nullptr && m_encoding_uid != LLDB_INVALID_UID) m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); @@ -416,24 +513,6 @@ lldb::Encoding Type::GetEncoding(uint64_t &count) { return GetForwardCompilerType().GetEncoding(count); } -bool Type::DumpValueInMemory(ExecutionContext *exe_ctx, Stream *s, - lldb::addr_t address, AddressType address_type, - bool show_types, bool show_summary, bool verbose) { - if (address != LLDB_INVALID_ADDRESS) { - DataExtractor data; - Target *target = nullptr; - if (exe_ctx) - target = exe_ctx->GetTargetPtr(); - if (target) - data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - if (ReadFromMemory(exe_ctx, address, address_type, data)) { - DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose); - return true; - } - } - return false; -} - bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) { if (address_type == eAddressTypeFile) { @@ -683,6 +762,8 @@ bool Type::GetTypeScopeAndBasename(llvm::StringRef name, if (name.empty()) return false; + // Clear the scope in case we have just a type class and a basename. + scope = llvm::StringRef(); basename = name; if (basename.consume_front("struct ")) type_class = eTypeClassStruct; @@ -696,8 +777,10 @@ bool Type::GetTypeScopeAndBasename(llvm::StringRef name, type_class = eTypeClassTypedef; size_t namespace_separator = basename.find("::"); - if (namespace_separator == llvm::StringRef::npos) - return false; + if (namespace_separator == llvm::StringRef::npos) { + // If "name" started a type class we need to return true with no scope. + return type_class != eTypeClassAny; + } size_t template_begin = basename.find('<'); while (namespace_separator != llvm::StringRef::npos) { @@ -790,6 +873,10 @@ void TypeAndOrName::SetName(const char *type_name_cstr) { m_type_name.SetCString(type_name_cstr); } +void TypeAndOrName::SetName(llvm::StringRef type_name) { + m_type_name.SetString(type_name); +} + void TypeAndOrName::SetTypeSP(lldb::TypeSP type_sp) { if (type_sp) { m_compiler_type = type_sp->GetForwardCompilerType(); @@ -1082,6 +1169,26 @@ bool TypeImpl::GetDescription(lldb_private::Stream &strm, return true; } +CompilerType TypeImpl::FindDirectNestedType(llvm::StringRef name) { + if (name.empty()) + return CompilerType(); + auto type_system = GetTypeSystem(/*prefer_dynamic*/ false); + auto *symbol_file = type_system->GetSymbolFile(); + if (!symbol_file) + return CompilerType(); + auto decl_context = type_system->GetCompilerDeclContextForType(m_static_type); + if (!decl_context.IsValid()) + return CompilerType(); + TypeQuery query(decl_context, ConstString(name), + TypeQueryOptions::e_find_one); + TypeResults results; + symbol_file->FindTypes(query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + return type_sp->GetFullCompilerType(); + return CompilerType(); +} + bool TypeMemberFunctionImpl::IsValid() { return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; } diff --git a/contrib/llvm-project/lldb/source/Symbol/TypeMap.cpp b/contrib/llvm-project/lldb/source/Symbol/TypeMap.cpp index 0d5f6d53e5a0..8933de53749c 100644 --- a/contrib/llvm-project/lldb/source/Symbol/TypeMap.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/TypeMap.cpp @@ -91,6 +91,12 @@ TypeSP TypeMap::GetTypeAtIndex(uint32_t idx) { return TypeSP(); } +lldb::TypeSP TypeMap::FirstType() const { + if (m_types.empty()) + return TypeSP(); + return m_types.begin()->second; +} + void TypeMap::ForEach( std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { @@ -121,10 +127,10 @@ bool TypeMap::Remove(const lldb::TypeSP &type_sp) { return false; } -void TypeMap::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) { - for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { - pos->second->Dump(s, show_context, level); - } +void TypeMap::Dump(Stream *s, bool show_context, + lldb::DescriptionLevel level) const { + for (const auto &pair : m_types) + pair.second->Dump(s, show_context, level); } void TypeMap::RemoveMismatchedTypes(llvm::StringRef type_scope, diff --git a/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp b/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp index 24f202930565..59b1b39e635a 100644 --- a/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp @@ -171,6 +171,16 @@ CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, return CompilerType(); } +std::vector<lldb_private::CompilerContext> +TypeSystem::DeclGetCompilerContext(void *opaque_decl) { + return {}; +} + +std::vector<lldb_private::CompilerContext> +TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx) { + return {}; +} + std::vector<CompilerDecl> TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, bool ignore_imported_decls) { @@ -186,6 +196,11 @@ std::optional<llvm::json::Value> TypeSystem::ReportStatistics() { return std::nullopt; } +CompilerDeclContext +TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) { + return CompilerDeclContext(); +} + #pragma mark TypeSystemMap TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {} diff --git a/contrib/llvm-project/lldb/source/Symbol/Variable.cpp b/contrib/llvm-project/lldb/source/Symbol/Variable.cpp index 85ceadd20c61..2bb2ff7db4b7 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Variable.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Variable.cpp @@ -227,7 +227,8 @@ bool Variable::LocationIsValidForFrame(StackFrame *frame) { // contains the current address when converted to a load address return m_location_list.ContainsAddress( loclist_base_load_addr, - frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get())); + frame->GetFrameCodeAddressForSymbolication().GetLoadAddress( + target_sp.get())); } } return false; @@ -509,7 +510,7 @@ static void PrivateAutoCompleteMembers( i, member_name, nullptr, nullptr, nullptr); if (partial_member_name.empty() || - llvm::StringRef(member_name).startswith(partial_member_name)) { + llvm::StringRef(member_name).starts_with(partial_member_name)) { if (member_name == partial_member_name) { PrivateAutoComplete( frame, partial_path, @@ -684,7 +685,7 @@ static void PrivateAutoComplete( continue; llvm::StringRef variable_name = var_sp->GetName().GetStringRef(); - if (variable_name.startswith(token)) { + if (variable_name.starts_with(token)) { if (variable_name == token) { Type *variable_type = var_sp->GetType(); if (variable_type) { diff --git a/contrib/llvm-project/lldb/source/Target/DynamicRegisterInfo.cpp b/contrib/llvm-project/lldb/source/Target/DynamicRegisterInfo.cpp index d577e20b3740..7469c1d4259a 100644 --- a/contrib/llvm-project/lldb/source/Target/DynamicRegisterInfo.cpp +++ b/contrib/llvm-project/lldb/source/Target/DynamicRegisterInfo.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/DynamicRegisterInfo.h" -#include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/LLDBLog.h" @@ -144,21 +144,21 @@ llvm::Expected<uint32_t> DynamicRegisterInfo::ByteOffsetFromComposite( uint32_t composite_offset = UINT32_MAX; for (uint32_t composite_idx = 0; composite_idx < num_composite_regs; ++composite_idx) { - ConstString composite_reg_name; - if (!composite_reg_list.GetItemAtIndexAsString(composite_idx, - composite_reg_name, nullptr)) + std::optional<llvm::StringRef> maybe_composite_reg_name = + composite_reg_list.GetItemAtIndexAsString(composite_idx); + if (!maybe_composite_reg_name) return llvm::createStringError( llvm::inconvertibleErrorCode(), "\"composite\" list value is not a Python string at index %d", composite_idx); const RegisterInfo *composite_reg_info = - GetRegisterInfo(composite_reg_name.GetStringRef()); + GetRegisterInfo(*maybe_composite_reg_name); if (!composite_reg_info) return llvm::createStringError( llvm::inconvertibleErrorCode(), "failed to find composite register by name: \"%s\"", - composite_reg_name.GetCString()); + maybe_composite_reg_name->str().c_str()); composite_offset = std::min(composite_offset, composite_reg_info->byte_offset); @@ -206,9 +206,11 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, if (dict.GetValueForKeyAsArray("sets", sets)) { const uint32_t num_sets = sets->GetSize(); for (uint32_t i = 0; i < num_sets; ++i) { - ConstString set_name; - if (sets->GetItemAtIndexAsString(i, set_name) && !set_name.IsEmpty()) { - m_sets.push_back({set_name.AsCString(), nullptr, 0, nullptr}); + std::optional<llvm::StringRef> maybe_set_name = + sets->GetItemAtIndexAsString(i); + if (maybe_set_name && !maybe_set_name->empty()) { + m_sets.push_back( + {ConstString(*maybe_set_name).AsCString(), nullptr, 0, nullptr}); } else { Clear(); printf("error: register sets must have valid names\n"); @@ -229,13 +231,15 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, // InvalidateNameMap; // InvalidateNameMap invalidate_map; for (uint32_t i = 0; i < num_regs; ++i) { - StructuredData::Dictionary *reg_info_dict = nullptr; - if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict)) { + std::optional<StructuredData::Dictionary *> maybe_reg_info_dict = + regs->GetItemAtIndexAsDictionary(i); + if (!maybe_reg_info_dict) { Clear(); printf("error: items in the 'registers' array must be dictionaries\n"); regs->DumpToStdout(); return 0; } + StructuredData::Dictionary *reg_info_dict = *maybe_reg_info_dict; // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, // 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2, @@ -345,12 +349,12 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, const size_t num_regs = invalidate_reg_list->GetSize(); if (num_regs > 0) { for (uint32_t idx = 0; idx < num_regs; ++idx) { - ConstString invalidate_reg_name; uint64_t invalidate_reg_num; - if (invalidate_reg_list->GetItemAtIndexAsString( - idx, invalidate_reg_name)) { + std::optional<llvm::StringRef> maybe_invalidate_reg_name = + invalidate_reg_list->GetItemAtIndexAsString(idx); + if (maybe_invalidate_reg_name) { const RegisterInfo *invalidate_reg_info = - GetRegisterInfo(invalidate_reg_name.GetStringRef()); + GetRegisterInfo(*maybe_invalidate_reg_name); if (invalidate_reg_info) { m_invalidate_regs_map[i].push_back( invalidate_reg_info->kinds[eRegisterKindLLDB]); @@ -359,7 +363,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, // format printf("error: failed to find a 'invalidate-regs' register for " "\"%s\" while parsing register \"%s\"\n", - invalidate_reg_name.GetCString(), reg_info.name); + maybe_invalidate_reg_name->str().c_str(), reg_info.name); } } else if (invalidate_reg_list->GetItemAtIndexAsInteger( idx, invalidate_reg_num)) { @@ -614,10 +618,11 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { ConfigureOffsets(); // Check if register info is reconfigurable - // AArch64 SVE register set has configurable register sizes + // AArch64 SVE register set has configurable register sizes, as does the ZA + // register that SME added (the streaming state of SME reuses the SVE state). if (arch.GetTriple().isAArch64()) { for (const auto ® : m_regs) { - if (strcmp(reg.name, "vg") == 0) { + if ((strcmp(reg.name, "vg") == 0) || (strcmp(reg.name, "svg") == 0)) { m_is_reconfigurable = true; break; } diff --git a/contrib/llvm-project/lldb/source/Target/Language.cpp b/contrib/llvm-project/lldb/source/Target/Language.cpp index 78785352676d..caf3e6636c1d 100644 --- a/contrib/llvm-project/lldb/source/Target/Language.cpp +++ b/contrib/llvm-project/lldb/source/Target/Language.cpp @@ -374,6 +374,7 @@ LanguageType Language::GetPrimaryLanguage(LanguageType language) { case eLanguageTypeJulia: case eLanguageTypeDylan: case eLanguageTypeMipsAssembler: + case eLanguageTypeMojo: case eLanguageTypeUnknown: default: return language; @@ -433,12 +434,10 @@ bool Language::ImageListTypeScavenger::Find_Impl( Target *target = exe_scope->CalculateTarget().get(); if (target) { const auto &images(target->GetImages()); - ConstString cs_key(key); - llvm::DenseSet<SymbolFile *> searched_sym_files; - TypeList matches; - images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files, - matches); - for (const auto &match : matches.Types()) { + TypeQuery query(key); + TypeResults type_results; + images.FindTypes(nullptr, query, type_results); + for (const auto &match : type_results.GetTypeMap().Types()) { if (match) { CompilerType compiler_type(match->GetFullCompilerType()); compiler_type = AdjustForInclusion(compiler_type); diff --git a/contrib/llvm-project/lldb/source/Target/Platform.cpp b/contrib/llvm-project/lldb/source/Target/Platform.cpp index 11a123fb6d58..4ce290dfbe03 100644 --- a/contrib/llvm-project/lldb/source/Target/Platform.cpp +++ b/contrib/llvm-project/lldb/source/Target/Platform.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Host/FileCache.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -73,8 +72,8 @@ enum { } // namespace -ConstString PlatformProperties::GetSettingName() { - static ConstString g_setting_name("platform"); +llvm::StringRef PlatformProperties::GetSettingName() { + static constexpr llvm::StringLiteral g_setting_name("platform"); return g_setting_name; } @@ -990,6 +989,14 @@ uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info, return match_count; } +ProcessInstanceInfoList Platform::GetAllProcesses() { + ProcessInstanceInfoList processes; + ProcessInstanceInfoMatch match; + assert(match.MatchAllProcesses()); + FindProcesses(match, processes); + return processes; +} + Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) { Status error; Log *log = GetLog(LLDBLog::Platform); @@ -1564,14 +1571,167 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec, resolved_module_spec.GetUUID() = module_spec.GetUUID(); } + // Call locate module callback if set. This allows users to implement their + // own module cache system. For example, to leverage build system artifacts, + // to bypass pulling files from remote platform, or to search symbol files + // from symbol servers. + FileSpec symbol_file_spec; + CallLocateModuleCallbackIfSet(resolved_module_spec, module_sp, + symbol_file_spec, did_create_ptr); + if (module_sp) { + // The module is loaded. + if (symbol_file_spec) { + // 1. module_sp:loaded, symbol_file_spec:set + // The callback found a module file and a symbol file for this + // resolved_module_spec. Set the symbol file to the module. + module_sp->SetSymbolFileFileSpec(symbol_file_spec); + } else { + // 2. module_sp:loaded, symbol_file_spec:empty + // The callback only found a module file for this + // resolved_module_spec. + } + return Status(); + } + + // The module is not loaded by CallLocateModuleCallbackIfSet. + // 3. module_sp:empty, symbol_file_spec:set + // The callback only found a symbol file for the module. We continue to + // find a module file for this resolved_module_spec. and we will call + // module_sp->SetSymbolFileFileSpec with the symbol_file_spec later. + // 4. module_sp:empty, symbol_file_spec:empty + // The callback is not set. Or the callback did not find any module + // files nor any symbol files. Or the callback failed, or something + // went wrong. We continue to find a module file for this + // resolved_module_spec. + // Trying to find a module by UUID on local file system. - const auto error = module_resolver(resolved_module_spec); + const Status error = module_resolver(resolved_module_spec); + if (error.Success()) { + if (module_sp && symbol_file_spec) { + // Set the symbol file to the module if the locate modudle callback was + // called and returned only a symbol file. + module_sp->SetSymbolFileFileSpec(symbol_file_spec); + } + return error; + } + + // Fallback to call GetCachedSharedModule on failure. + if (GetCachedSharedModule(resolved_module_spec, module_sp, did_create_ptr)) { + if (module_sp && symbol_file_spec) { + // Set the symbol file to the module if the locate modudle callback was + // called and returned only a symbol file. + module_sp->SetSymbolFileFileSpec(symbol_file_spec); + } + return Status(); + } + + return Status("Failed to call GetCachedSharedModule"); +} + +void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp, + FileSpec &symbol_file_spec, + bool *did_create_ptr) { + if (!m_locate_module_callback) { + // Locate module callback is not set. + return; + } + + FileSpec module_file_spec; + Status error = + m_locate_module_callback(module_spec, module_file_spec, symbol_file_spec); + + // Locate module callback is set and called. Check the error. + Log *log = GetLog(LLDBLog::Platform); if (error.Fail()) { - if (GetCachedSharedModule(resolved_module_spec, module_sp, did_create_ptr)) - return Status(); + LLDB_LOGF(log, "%s: locate module callback failed: %s", + LLVM_PRETTY_FUNCTION, error.AsCString()); + return; } - return error; + // The locate module callback was succeeded. + // Check the module_file_spec and symbol_file_spec values. + // 1. module:empty symbol:empty -> Failure + // - The callback did not return any files. + // 2. module:exists symbol:exists -> Success + // - The callback returned a module file and a symbol file. + // 3. module:exists symbol:empty -> Success + // - The callback returned only a module file. + // 4. module:empty symbol:exists -> Success + // - The callback returned only a symbol file. + // For example, a breakpad symbol text file. + if (!module_file_spec && !symbol_file_spec) { + // This is '1. module:empty symbol:empty -> Failure' + // The callback did not return any files. + LLDB_LOGF(log, + "%s: locate module callback did not set both " + "module_file_spec and symbol_file_spec", + LLVM_PRETTY_FUNCTION); + return; + } + + // If the callback returned a module file, it should exist. + if (module_file_spec && !FileSystem::Instance().Exists(module_file_spec)) { + LLDB_LOGF(log, + "%s: locate module callback set a non-existent file to " + "module_file_spec: %s", + LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str()); + // Clear symbol_file_spec for the error. + symbol_file_spec.Clear(); + return; + } + + // If the callback returned a symbol file, it should exist. + if (symbol_file_spec && !FileSystem::Instance().Exists(symbol_file_spec)) { + LLDB_LOGF(log, + "%s: locate module callback set a non-existent file to " + "symbol_file_spec: %s", + LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str()); + // Clear symbol_file_spec for the error. + symbol_file_spec.Clear(); + return; + } + + if (!module_file_spec && symbol_file_spec) { + // This is '4. module:empty symbol:exists -> Success' + // The locate module callback returned only a symbol file. For example, + // a breakpad symbol text file. GetRemoteSharedModule will use this returned + // symbol_file_spec. + LLDB_LOGF(log, "%s: locate module callback succeeded: symbol=%s", + LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str()); + return; + } + + // This is one of the following. + // - 2. module:exists symbol:exists -> Success + // - The callback returned a module file and a symbol file. + // - 3. module:exists symbol:empty -> Success + // - The callback returned Only a module file. + // Load the module file. + auto cached_module_spec(module_spec); + cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md5 + // content hash instead of real UUID. + cached_module_spec.GetFileSpec() = module_file_spec; + cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec(); + cached_module_spec.SetObjectOffset(0); + + error = ModuleList::GetSharedModule(cached_module_spec, module_sp, nullptr, + nullptr, did_create_ptr, false); + if (error.Success() && module_sp) { + // Succeeded to load the module file. + LLDB_LOGF(log, "%s: locate module callback succeeded: module=%s symbol=%s", + LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(), + symbol_file_spec.GetPath().c_str()); + } else { + LLDB_LOGF(log, + "%s: locate module callback succeeded but failed to load: " + "module=%s symbol=%s", + LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(), + symbol_file_spec.GetPath().c_str()); + // Clear module_sp and symbol_file_spec for the error. + module_sp.reset(); + symbol_file_spec.Clear(); + } } bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec, @@ -1854,7 +2014,7 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; - lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); + lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetConstituentAtIndex(0)); AddressClass addr_class = AddressClass::eUnknown; if (bp_loc_sp) { diff --git a/contrib/llvm-project/lldb/source/Target/Process.cpp b/contrib/llvm-project/lldb/source/Target/Process.cpp index 05ddbbd146a2..aa3b04c43cc5 100644 --- a/contrib/llvm-project/lldb/source/Target/Process.cpp +++ b/contrib/llvm-project/lldb/source/Target/Process.cpp @@ -21,7 +21,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/DynamicCheckerFunctions.h" #include "lldb/Expression/UserExpression.h" @@ -90,7 +89,7 @@ using namespace std::chrono; class ProcessOptionValueProperties : public Cloneable<ProcessOptionValueProperties, OptionValueProperties> { public: - ProcessOptionValueProperties(ConstString name) : Cloneable(name) {} + ProcessOptionValueProperties(llvm::StringRef name) : Cloneable(name) {} const Property * GetPropertyAtIndex(size_t idx, @@ -147,8 +146,7 @@ class ProcessExperimentalOptionValueProperties OptionValueProperties> { public: ProcessExperimentalOptionValueProperties() - : Cloneable( - ConstString(Properties::GetExperimentalSettingsName())) {} + : Cloneable(Properties::GetExperimentalSettingsName()) {} }; ProcessExperimentalProperties::ProcessExperimentalProperties() @@ -163,8 +161,7 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process) { if (process == nullptr) { // Global process properties, set them up one time - m_collection_sp = - std::make_shared<ProcessOptionValueProperties>(ConstString("process")); + m_collection_sp = std::make_shared<ProcessOptionValueProperties>("process"); m_collection_sp->Initialize(g_process_properties); m_collection_sp->AppendProperty( "thread", "Settings specific to threads.", true, @@ -439,7 +436,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, m_exit_status_mutex(), m_thread_mutex(), m_thread_list_real(this), m_thread_list(this), m_thread_plans(*this), m_extended_thread_list(this), m_extended_thread_stop_id(0), m_queue_list(this), m_queue_list_stop_id(0), - m_notifications(), m_image_tokens(), m_listener_sp(listener_sp), + m_watchpoint_resource_list(), m_notifications(), m_image_tokens(), m_breakpoint_site_list(), m_dynamic_checkers_up(), m_unix_signals_sp(unix_signals_sp), m_abi_sp(), m_process_input_reader(), m_stdio_communication("process.stdio"), m_stdio_communication_mutex(), @@ -448,7 +445,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, m_memory_cache(*this), m_allocated_memory_cache(*this), m_should_detach(false), m_next_event_action_up(), m_public_run_lock(), m_private_run_lock(), m_currently_handling_do_on_removals(false), - m_resume_requested(false), m_finalizing(false), + m_resume_requested(false), m_finalizing(false), m_destructing(false), m_clear_thread_plans_on_stop(false), m_force_next_event_delivery(false), m_last_broadcast_state(eStateInvalid), m_destroy_in_process(false), m_can_interpret_function_calls(false), m_run_thread_plan_lock(), @@ -475,10 +472,9 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, m_private_state_control_broadcaster.SetEventName( eBroadcastInternalStateControlResume, "control-resume"); - m_listener_sp->StartListeningForEvents( - this, eBroadcastBitStateChanged | eBroadcastBitInterrupt | - eBroadcastBitSTDOUT | eBroadcastBitSTDERR | - eBroadcastBitProfileData | eBroadcastBitStructuredData); + // The listener passed into process creation is the primary listener: + // It always listens for all the event bits for Process: + SetPrimaryListener(listener_sp); m_private_state_listener_sp->StartListeningForEvents( &m_private_state_broadcaster, @@ -522,9 +518,11 @@ ProcessProperties &Process::GetGlobalProperties() { return *g_settings_ptr; } -void Process::Finalize() { +void Process::Finalize(bool destructing) { if (m_finalizing.exchange(true)) return; + if (destructing) + m_destructing.exchange(true); // Destroy the process. This will call the virtual function DoDestroy under // the hood, giving our derived class a chance to do the ncessary tear down. @@ -551,6 +549,7 @@ void Process::Finalize() { m_extended_thread_list.Destroy(); m_queue_list.Clear(); m_queue_list_stop_id = 0; + m_watchpoint_resource_list.Clear(); std::vector<Notifications> empty_notifications; m_notifications.swap(empty_notifications); m_image_tokens.clear(); @@ -565,15 +564,6 @@ void Process::Finalize() { // Clear the last natural stop ID since it has a strong reference to this // process m_mod_id.SetStopEventForLastNaturalStopID(EventSP()); - //#ifdef LLDB_CONFIGURATION_DEBUG - // StreamFile s(stdout, false); - // EventSP event_sp; - // while (m_private_state_listener_sp->GetNextEvent(event_sp)) - // { - // event_sp->Dump (&s); - // s.EOL(); - // } - //#endif // We have to be very careful here as the m_private_state_listener might // contain events that have ProcessSP values in them which can keep this // process around forever. These events need to be cleared out. @@ -628,7 +618,7 @@ void Process::SynchronouslyNotifyStateChanged(StateType state) { StateType Process::GetNextEvent(EventSP &event_sp) { StateType state = eStateInvalid; - if (m_listener_sp->GetEventForBroadcaster(this, event_sp, + if (GetPrimaryListener()->GetEventForBroadcaster(this, event_sp, std::chrono::seconds(0)) && event_sp) state = Process::ProcessEventData::GetStateFromEvent(event_sp.get()); @@ -640,7 +630,7 @@ void Process::SyncIOHandler(uint32_t iohandler_id, const Timeout<std::micro> &timeout) { // don't sync (potentially context switch) in case where there is no process // IO - if (!m_process_input_reader) + if (!ProcessIOHandlerExists()) return; auto Result = m_iohandler_sync.WaitForValueNotEqualTo(iohandler_id, timeout); @@ -976,7 +966,7 @@ StateType Process::GetStateChangedEvents(EventSP &event_sp, ListenerSP listener_sp = hijack_listener_sp; if (!listener_sp) - listener_sp = m_listener_sp; + listener_sp = GetPrimaryListener(); StateType state = eStateInvalid; if (listener_sp->GetEventForBroadcasterWithType( @@ -998,7 +988,7 @@ Event *Process::PeekAtStateChangedEvents() { LLDB_LOGF(log, "Process::%s...", __FUNCTION__); Event *event_ptr; - event_ptr = m_listener_sp->PeekAtNextEventForBroadcasterWithType( + event_ptr = GetPrimaryListener()->PeekAtNextEventForBroadcasterWithType( this, eBroadcastBitStateChanged); if (log) { if (event_ptr) { @@ -1063,27 +1053,27 @@ const char *Process::GetExitDescription() { return nullptr; } -bool Process::SetExitStatus(int status, const char *cstr) { +bool Process::SetExitStatus(int status, llvm::StringRef exit_string) { // Use a mutex to protect setting the exit status. std::lock_guard<std::mutex> guard(m_exit_status_mutex); Log *log(GetLog(LLDBLog::State | LLDBLog::Process)); - LLDB_LOGF(log, "(plugin = %s status=%i (0x%8.8x), description=%s%s%s)", - GetPluginName().data(), status, status, cstr ? "\"" : "", - cstr ? cstr : "NULL", cstr ? "\"" : ""); + LLDB_LOG(log, "(plugin = {0} status = {1} ({1:x8}), description=\"{2}\")", + GetPluginName(), status, exit_string); // We were already in the exited state if (m_private_state.GetValue() == eStateExited) { - LLDB_LOGF(log, - "(plugin = %s) ignoring exit status because state was already set " - "to eStateExited", - GetPluginName().data()); + LLDB_LOG( + log, + "(plugin = {0}) ignoring exit status because state was already set " + "to eStateExited", + GetPluginName()); return false; } m_exit_status = status; - if (cstr) - m_exit_string = cstr; + if (!exit_string.empty()) + m_exit_string = exit_string.str(); else m_exit_string.clear(); @@ -1135,11 +1125,9 @@ bool Process::SetProcessExitStatus( if (target_sp) { ProcessSP process_sp(target_sp->GetProcessSP()); if (process_sp) { - const char *signal_cstr = nullptr; - if (signo) - signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo); - - process_sp->SetExitStatus(exit_status, signal_cstr); + llvm::StringRef signal_str = + process_sp->GetUnixSignals()->GetSignalAsStringRef(signo); + process_sp->SetExitStatus(exit_status, signal_str); } } return true; @@ -1429,7 +1417,13 @@ bool Process::StateChangedIsHijackedForSynchronousResume() { StateType Process::GetPrivateState() { return m_private_state.GetValue(); } void Process::SetPrivateState(StateType new_state) { - if (m_finalizing) + // Use m_destructing not m_finalizing here. If we are finalizing a process + // that we haven't started tearing down, we'd like to be able to nicely + // detach if asked, but that requires the event system be live. That will + // not be true for an in-the-middle-of-being-destructed Process, since the + // event system relies on Process::shared_from_this, which may have already + // been destroyed. + if (m_destructing) return; Log *log(GetLog(LLDBLog::State | LLDBLog::Process | LLDBLog::Unwind)); @@ -1578,11 +1572,12 @@ void Process::SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers) { m_dynamic_checkers_up.reset(dynamic_checkers); } -BreakpointSiteList &Process::GetBreakpointSiteList() { +StopPointSiteList<BreakpointSite> &Process::GetBreakpointSiteList() { return m_breakpoint_site_list; } -const BreakpointSiteList &Process::GetBreakpointSiteList() const { +const StopPointSiteList<BreakpointSite> & +Process::GetBreakpointSiteList() const { return m_breakpoint_site_list; } @@ -1630,7 +1625,7 @@ Status Process::EnableBreakpointSiteByID(lldb::user_id_t break_id) { } lldb::break_id_t -Process::CreateBreakpointSite(const BreakpointLocationSP &owner, +Process::CreateBreakpointSite(const BreakpointLocationSP &constituent, bool use_hardware) { addr_t load_addr = LLDB_INVALID_ADDRESS; @@ -1657,10 +1652,10 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner, // Reset the IsIndirect flag here, in case the location changes from pointing // to a indirect symbol to a regular symbol. - owner->SetIsIndirect(false); + constituent->SetIsIndirect(false); - if (owner->ShouldResolveIndirectFunctions()) { - Symbol *symbol = owner->GetAddress().CalculateSymbolContextSymbol(); + if (constituent->ShouldResolveIndirectFunctions()) { + Symbol *symbol = constituent->GetAddress().CalculateSymbolContextSymbol(); if (symbol && symbol->IsIndirect()) { Status error; Address symbol_address = symbol->GetAddress(); @@ -1670,37 +1665,37 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner, "warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", symbol->GetLoadAddress(&GetTarget()), - owner->GetBreakpoint().GetID(), owner->GetID(), + constituent->GetBreakpoint().GetID(), constituent->GetID(), error.AsCString() ? error.AsCString() : "unknown error"); return LLDB_INVALID_BREAK_ID; } Address resolved_address(load_addr); load_addr = resolved_address.GetOpcodeLoadAddress(&GetTarget()); - owner->SetIsIndirect(true); + constituent->SetIsIndirect(true); } else - load_addr = owner->GetAddress().GetOpcodeLoadAddress(&GetTarget()); + load_addr = constituent->GetAddress().GetOpcodeLoadAddress(&GetTarget()); } else - load_addr = owner->GetAddress().GetOpcodeLoadAddress(&GetTarget()); + load_addr = constituent->GetAddress().GetOpcodeLoadAddress(&GetTarget()); if (load_addr != LLDB_INVALID_ADDRESS) { BreakpointSiteSP bp_site_sp; - // Look up this breakpoint site. If it exists, then add this new owner, - // otherwise create a new breakpoint site and add it. + // Look up this breakpoint site. If it exists, then add this new + // constituent, otherwise create a new breakpoint site and add it. bp_site_sp = m_breakpoint_site_list.FindByAddress(load_addr); if (bp_site_sp) { - bp_site_sp->AddOwner(owner); - owner->SetBreakpointSite(bp_site_sp); + bp_site_sp->AddConstituent(constituent); + constituent->SetBreakpointSite(bp_site_sp); return bp_site_sp->GetID(); } else { - bp_site_sp.reset(new BreakpointSite(&m_breakpoint_site_list, owner, - load_addr, use_hardware)); + bp_site_sp.reset( + new BreakpointSite(constituent, load_addr, use_hardware)); if (bp_site_sp) { Status error = EnableBreakpointSite(bp_site_sp.get()); if (error.Success()) { - owner->SetBreakpointSite(bp_site_sp); + constituent->SetBreakpointSite(bp_site_sp); return m_breakpoint_site_list.Add(bp_site_sp); } else { if (show_error || use_hardware) { @@ -1708,7 +1703,8 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner, GetTarget().GetDebugger().GetErrorStream().Printf( "warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n", - load_addr, owner->GetBreakpoint().GetID(), owner->GetID(), + load_addr, constituent->GetBreakpoint().GetID(), + constituent->GetID(), error.AsCString() ? error.AsCString() : "unknown error"); } } @@ -1719,11 +1715,12 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner, return LLDB_INVALID_BREAK_ID; } -void Process::RemoveOwnerFromBreakpointSite(lldb::user_id_t owner_id, - lldb::user_id_t owner_loc_id, - BreakpointSiteSP &bp_site_sp) { - uint32_t num_owners = bp_site_sp->RemoveOwner(owner_id, owner_loc_id); - if (num_owners == 0) { +void Process::RemoveConstituentFromBreakpointSite( + lldb::user_id_t constituent_id, lldb::user_id_t constituent_loc_id, + BreakpointSiteSP &bp_site_sp) { + uint32_t num_constituents = + bp_site_sp->RemoveConstituent(constituent_id, constituent_loc_id); + if (num_constituents == 0) { // Don't try to disable the site if we don't have a live process anymore. if (IsAlive()) DisableBreakpointSite(bp_site_sp.get()); @@ -1734,7 +1731,7 @@ void Process::RemoveOwnerFromBreakpointSite(lldb::user_id_t owner_id, size_t Process::RemoveBreakpointOpcodesFromBuffer(addr_t bp_addr, size_t size, uint8_t *buf) const { size_t bytes_removed = 0; - BreakpointSiteList bp_sites_in_range; + StopPointSiteList<BreakpointSite> bp_sites_in_range; if (m_breakpoint_site_list.FindInRange(bp_addr, bp_addr + size, bp_sites_in_range)) { @@ -2155,7 +2152,7 @@ size_t Process::WriteMemory(addr_t addr, const void *buf, size_t size, // (enabled software breakpoints) any software traps (breakpoints) that we // may have placed in our tasks memory. - BreakpointSiteList bp_sites_in_range; + StopPointSiteList<BreakpointSite> bp_sites_in_range; if (!m_breakpoint_site_list.FindInRange(addr, addr + size, bp_sites_in_range)) return WriteMemoryPrivate(addr, buf, size, error); @@ -2419,26 +2416,17 @@ bool Process::GetLoadAddressPermissions(lldb::addr_t load_addr, range_info.GetExecutable() == MemoryRegionInfo::eDontKnow) { return false; } - - if (range_info.GetReadable() == MemoryRegionInfo::eYes) - permissions |= lldb::ePermissionsReadable; - - if (range_info.GetWritable() == MemoryRegionInfo::eYes) - permissions |= lldb::ePermissionsWritable; - - if (range_info.GetExecutable() == MemoryRegionInfo::eYes) - permissions |= lldb::ePermissionsExecutable; - + permissions = range_info.GetLLDBPermissions(); return true; } -Status Process::EnableWatchpoint(Watchpoint *watchpoint, bool notify) { +Status Process::EnableWatchpoint(WatchpointSP wp_sp, bool notify) { Status error; error.SetErrorString("watchpoints are not supported"); return error; } -Status Process::DisableWatchpoint(Watchpoint *watchpoint, bool notify) { +Status Process::DisableWatchpoint(WatchpointSP wp_sp, bool notify) { Status error; error.SetErrorString("watchpoints are not supported"); return error; @@ -2515,7 +2503,11 @@ Status Process::LaunchPrivate(ProcessLaunchInfo &launch_info, StateType &state, m_jit_loaders_up.reset(); m_system_runtime_up.reset(); m_os_up.reset(); - m_process_input_reader.reset(); + + { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); + m_process_input_reader.reset(); + } Module *exe_module = GetTarget().GetExecutableModulePointer(); @@ -2813,7 +2805,10 @@ Status Process::WillAttachToProcessWithName(const char *process_name, Status Process::Attach(ProcessAttachInfo &attach_info) { m_abi_sp.reset(); - m_process_input_reader.reset(); + { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); + m_process_input_reader.reset(); + } m_dyld_up.reset(); m_jit_loaders_up.reset(); m_system_runtime_up.reset(); @@ -3064,7 +3059,10 @@ void Process::CompleteAttach() { Status Process::ConnectRemote(llvm::StringRef remote_url) { m_abi_sp.reset(); - m_process_input_reader.reset(); + { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); + m_process_input_reader.reset(); + } // Find the process and its architecture. Make sure it matches the // architecture of the current Target, and if not adjust it. @@ -3170,8 +3168,8 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) { // Don't hijack and eat the eStateExited as the code that was doing the // attach will be waiting for this event... RestoreProcessEvents(); - SetExitStatus(SIGKILL, "Cancelled async attach."); Destroy(false); + SetExitStatus(SIGKILL, "Cancelled async attach."); return Status(); } @@ -3352,10 +3350,13 @@ Status Process::DestroyImpl(bool force_kill) { m_stdio_communication.Disconnect(); m_stdin_forward = false; - if (m_process_input_reader) { - m_process_input_reader->SetIsDone(true); - m_process_input_reader->Cancel(); - m_process_input_reader.reset(); + { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); + if (m_process_input_reader) { + m_process_input_reader->SetIsDone(true); + m_process_input_reader->Cancel(); + m_process_input_reader.reset(); + } } // If we exited when we were waiting for a process to stop, then forward @@ -3854,6 +3855,13 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { ") woke up with an interrupt while attaching - " "forwarding interrupt.", __FUNCTION__, static_cast<void *>(this), GetID()); + // The server may be spinning waiting for a process to appear, in which + // case we should tell it to stop doing that. Normally, we don't NEED + // to do that because we will next close the communication to the stub + // and that will get it to shut down. But there are remote debugging + // cases where relying on that side-effect causes the shutdown to be + // flakey, so we should send a positive signal to interrupt the wait. + Status error = HaltPrivate(); BroadcastEvent(eBroadcastBitInterrupt, nullptr); } else if (StateIsRunningState(m_last_broadcast_state)) { LLDB_LOGF(log, @@ -4114,8 +4122,8 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) { if (!still_should_stop && does_anybody_have_an_opinion) { // We've been asked to continue, so do that here. SetRestarted(true); - // Use the public resume method here, since this is just extending a - // public resume. + // Use the private resume method here, since we aren't changing the run + // lock state. process_sp->PrivateResume(); } else { bool hijacked = process_sp->IsHijackedForEvent(eBroadcastBitStateChanged) && @@ -4533,20 +4541,25 @@ void Process::SetSTDIOFileDescriptor(int fd) { m_stdio_communication.StartReadThread(); // Now read thread is set up, set up input reader. - - if (!m_process_input_reader) - m_process_input_reader = - std::make_shared<IOHandlerProcessSTDIO>(this, fd); + { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); + if (!m_process_input_reader) + m_process_input_reader = + std::make_shared<IOHandlerProcessSTDIO>(this, fd); + } } } bool Process::ProcessIOHandlerIsActive() { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); IOHandlerSP io_handler_sp(m_process_input_reader); if (io_handler_sp) return GetTarget().GetDebugger().IsTopIOHandler(io_handler_sp); return false; } + bool Process::PushProcessIOHandler() { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); IOHandlerSP io_handler_sp(m_process_input_reader); if (io_handler_sp) { Log *log = GetLog(LLDBLog::Process); @@ -4566,6 +4579,7 @@ bool Process::PushProcessIOHandler() { } bool Process::PopProcessIOHandler() { + std::lock_guard<std::mutex> guard(m_process_input_reader_mutex); IOHandlerSP io_handler_sp(m_process_input_reader); if (io_handler_sp) return GetTarget().GetDebugger().RemoveIOHandler(io_handler_sp); @@ -5907,12 +5921,12 @@ size_t Process::AddImageToken(lldb::addr_t image_ptr) { lldb::addr_t Process::GetImagePtrFromToken(size_t token) const { if (token < m_image_tokens.size()) return m_image_tokens[token]; - return LLDB_INVALID_ADDRESS; + return LLDB_INVALID_IMAGE_TOKEN; } void Process::ResetImageToken(size_t token) { if (token < m_image_tokens.size()) - m_image_tokens[token] = LLDB_INVALID_ADDRESS; + m_image_tokens[token] = LLDB_INVALID_IMAGE_TOKEN; } Address @@ -6248,3 +6262,185 @@ Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len, return DoWriteMemoryTags(addr, len, tag_manager->GetAllocationTagType(), *packed_tags); } + +// Create a CoreFileMemoryRange from a MemoryRegionInfo +static Process::CoreFileMemoryRange +CreateCoreFileMemoryRange(const MemoryRegionInfo ®ion) { + const addr_t addr = region.GetRange().GetRangeBase(); + llvm::AddressRange range(addr, addr + region.GetRange().GetByteSize()); + return {range, region.GetLLDBPermissions()}; +} + +// Add dirty pages to the core file ranges and return true if dirty pages +// were added. Return false if the dirty page information is not valid or in +// the region. +static bool AddDirtyPages(const MemoryRegionInfo ®ion, + Process::CoreFileMemoryRanges &ranges) { + const auto &dirty_page_list = region.GetDirtyPageList(); + if (!dirty_page_list) + return false; + const uint32_t lldb_permissions = region.GetLLDBPermissions(); + const addr_t page_size = region.GetPageSize(); + if (page_size == 0) + return false; + llvm::AddressRange range(0, 0); + for (addr_t page_addr : *dirty_page_list) { + if (range.empty()) { + // No range yet, initialize the range with the current dirty page. + range = llvm::AddressRange(page_addr, page_addr + page_size); + } else { + if (range.end() == page_addr) { + // Combine consective ranges. + range = llvm::AddressRange(range.start(), page_addr + page_size); + } else { + // Add previous contiguous range and init the new range with the + // current dirty page. + ranges.push_back({range, lldb_permissions}); + range = llvm::AddressRange(page_addr, page_addr + page_size); + } + } + } + // The last range + if (!range.empty()) + ranges.push_back({range, lldb_permissions}); + return true; +} + +// Given a region, add the region to \a ranges. +// +// Only add the region if it isn't empty and if it has some permissions. +// If \a try_dirty_pages is true, then try to add only the dirty pages for a +// given region. If the region has dirty page information, only dirty pages +// will be added to \a ranges, else the entire range will be added to \a +// ranges. +static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages, + Process::CoreFileMemoryRanges &ranges) { + // Don't add empty ranges or ranges with no permissions. + if (region.GetRange().GetByteSize() == 0 || region.GetLLDBPermissions() == 0) + return; + if (try_dirty_pages && AddDirtyPages(region, ranges)) + return; + ranges.push_back(CreateCoreFileMemoryRange(region)); +} + +// Save all memory regions that are not empty or have at least some permissions +// for a full core file style. +static void GetCoreFileSaveRangesFull(Process &process, + const MemoryRegionInfos ®ions, + Process::CoreFileMemoryRanges &ranges) { + + // Don't add only dirty pages, add full regions. +const bool try_dirty_pages = false; + for (const auto ®ion : regions) + AddRegion(region, try_dirty_pages, ranges); +} + +// Save only the dirty pages to the core file. Make sure the process has at +// least some dirty pages, as some OS versions don't support reporting what +// pages are dirty within an memory region. If no memory regions have dirty +// page information fall back to saving out all ranges with write permissions. +static void +GetCoreFileSaveRangesDirtyOnly(Process &process, + const MemoryRegionInfos ®ions, + Process::CoreFileMemoryRanges &ranges) { + // Iterate over the regions and find all dirty pages. + bool have_dirty_page_info = false; + for (const auto ®ion : regions) { + if (AddDirtyPages(region, ranges)) + have_dirty_page_info = true; + } + + if (!have_dirty_page_info) { + // We didn't find support for reporting dirty pages from the process + // plug-in so fall back to any region with write access permissions. + const bool try_dirty_pages = false; + for (const auto ®ion : regions) + if (region.GetWritable() == MemoryRegionInfo::eYes) + AddRegion(region, try_dirty_pages, ranges); + } +} + +// Save all thread stacks to the core file. Some OS versions support reporting +// when a memory region is stack related. We check on this information, but we +// also use the stack pointers of each thread and add those in case the OS +// doesn't support reporting stack memory. This function also attempts to only +// emit dirty pages from the stack if the memory regions support reporting +// dirty regions as this will make the core file smaller. If the process +// doesn't support dirty regions, then it will fall back to adding the full +// stack region. +static void +GetCoreFileSaveRangesStackOnly(Process &process, + const MemoryRegionInfos ®ions, + Process::CoreFileMemoryRanges &ranges) { + // Some platforms support annotating the region information that tell us that + // it comes from a thread stack. So look for those regions first. + + // Keep track of which stack regions we have added + std::set<addr_t> stack_bases; + + const bool try_dirty_pages = true; + for (const auto ®ion : regions) { + if (region.IsStackMemory() == MemoryRegionInfo::eYes) { + stack_bases.insert(region.GetRange().GetRangeBase()); + AddRegion(region, try_dirty_pages, ranges); + } + } + + // Also check with our threads and get the regions for their stack pointers + // and add those regions if not already added above. + for (lldb::ThreadSP thread_sp : process.GetThreadList().Threads()) { + if (!thread_sp) + continue; + StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0); + if (!frame_sp) + continue; + RegisterContextSP reg_ctx_sp = frame_sp->GetRegisterContext(); + if (!reg_ctx_sp) + continue; + const addr_t sp = reg_ctx_sp->GetSP(); + lldb_private::MemoryRegionInfo sp_region; + if (process.GetMemoryRegionInfo(sp, sp_region).Success()) { + // Only add this region if not already added above. If our stack pointer + // is pointing off in the weeds, we will want this range. + if (stack_bases.count(sp_region.GetRange().GetRangeBase()) == 0) + AddRegion(sp_region, try_dirty_pages, ranges); + } + } +} + +Status Process::CalculateCoreFileSaveRanges(lldb::SaveCoreStyle core_style, + CoreFileMemoryRanges &ranges) { + lldb_private::MemoryRegionInfos regions; + Status err = GetMemoryRegions(regions); + if (err.Fail()) + return err; + if (regions.empty()) + return Status("failed to get any valid memory regions from the process"); + + switch (core_style) { + case eSaveCoreUnspecified: + err = Status("callers must set the core_style to something other than " + "eSaveCoreUnspecified"); + break; + + case eSaveCoreFull: + GetCoreFileSaveRangesFull(*this, regions, ranges); + break; + + case eSaveCoreDirtyOnly: + GetCoreFileSaveRangesDirtyOnly(*this, regions, ranges); + break; + + case eSaveCoreStackOnly: + GetCoreFileSaveRangesStackOnly(*this, regions, ranges); + break; + } + + if (err.Fail()) + return err; + + if (ranges.empty()) + return Status("no valid address ranges found for core style"); + + return Status(); // Success! +} diff --git a/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp b/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp index 061af9e0e520..6e5ef6a379f9 100644 --- a/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp +++ b/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp @@ -50,7 +50,7 @@ ProcessTrace::~ProcessTrace() { // make sure all of the broadcaster cleanup goes as planned. If we destruct // this class, then Process::~Process() might have problems trying to fully // destroy the broadcaster. - Finalize(); + Finalize(true /* destructing */); } void ProcessTrace::DidAttach(ArchSpec &process_arch) { diff --git a/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp b/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp index 7236a45bff3b..47c50b8a0154 100644 --- a/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp +++ b/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp @@ -109,6 +109,12 @@ uint64_t RegisterContext::GetPC(uint64_t fail_value) { return pc; } +uint64_t RegisterContext::GetThreadPointer(uint64_t fail_value) { + uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_TP); + return ReadRegisterAsUnsigned(reg, fail_value); +} + bool RegisterContext::SetPC(uint64_t pc) { uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); diff --git a/contrib/llvm-project/lldb/source/Target/RegisterContextUnwind.cpp b/contrib/llvm-project/lldb/source/Target/RegisterContextUnwind.cpp index 242c7d3f6b94..13e101413a47 100644 --- a/contrib/llvm-project/lldb/source/Target/RegisterContextUnwind.cpp +++ b/contrib/llvm-project/lldb/source/Target/RegisterContextUnwind.cpp @@ -712,7 +712,7 @@ bool RegisterContextUnwind::CheckIfLoopingStack() { // frames with the same // CFA (in theory we // can have arbitrary number of frames with the same CFA, but more then 2 is - // very very unlikely) + // very unlikely) RegisterContextUnwind::SharedPtr next_frame = GetNextFrame(); if (next_frame) { diff --git a/contrib/llvm-project/lldb/source/Target/RegisterFlags.cpp b/contrib/llvm-project/lldb/source/Target/RegisterFlags.cpp index 06fb45d777ec..b1669b85fd2f 100644 --- a/contrib/llvm-project/lldb/source/Target/RegisterFlags.cpp +++ b/contrib/llvm-project/lldb/source/Target/RegisterFlags.cpp @@ -7,13 +7,21 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/RegisterFlags.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include "llvm/ADT/StringExtras.h" + #include <numeric> #include <optional> using namespace lldb_private; +RegisterFlags::Field::Field(std::string name, unsigned start, unsigned end) + : m_name(std::move(name)), m_start(start), m_end(end) { + assert(m_start <= m_end && "Start bit must be <= end bit."); +} + void RegisterFlags::Field::log(Log *log) const { LLDB_LOG(log, " Name: \"{0}\" Start: {1} End: {2}", m_name.c_str(), m_start, m_end); @@ -45,9 +53,7 @@ unsigned RegisterFlags::Field::PaddingDistance(const Field &other) const { return lhs_start - rhs_end - 1; } -RegisterFlags::RegisterFlags(std::string id, unsigned size, - const std::vector<Field> &fields) - : m_id(std::move(id)), m_size(size) { +void RegisterFlags::SetFields(const std::vector<Field> &fields) { // We expect that the XML processor will discard anything describing flags but // with no fields. assert(fields.size() && "Some fields must be provided."); @@ -55,6 +61,8 @@ RegisterFlags::RegisterFlags(std::string id, unsigned size, // We expect that these are unsorted but do not overlap. // They could fill the register but may have gaps. std::vector<Field> provided_fields = fields; + + m_fields.clear(); m_fields.reserve(provided_fields.size()); // ProcessGDBRemote should have sorted these in descending order already. @@ -63,7 +71,7 @@ RegisterFlags::RegisterFlags(std::string id, unsigned size, // Build a new list of fields that includes anonymous (empty name) fields // wherever there is a gap. This will simplify processing later. std::optional<Field> previous_field; - unsigned register_msb = (size * 8) - 1; + unsigned register_msb = (m_size * 8) - 1; for (auto field : provided_fields) { if (previous_field) { unsigned padding = previous_field->PaddingDistance(field); @@ -88,6 +96,12 @@ RegisterFlags::RegisterFlags(std::string id, unsigned size, m_fields.push_back(Field("", 0, previous_field->GetStart() - 1)); } +RegisterFlags::RegisterFlags(std::string id, unsigned size, + const std::vector<Field> &fields) + : m_id(std::move(id)), m_size(size) { + SetFields(fields); +} + void RegisterFlags::log(Log *log) const { LLDB_LOG(log, "ID: \"{0}\" Size: {1}", m_id.c_str(), m_size); for (const Field &field : m_fields) @@ -175,3 +189,41 @@ std::string RegisterFlags::AsTable(uint32_t max_width) const { return table; } + +void RegisterFlags::ToXML(StreamString &strm) const { + // Example XML: + // <flags id="cpsr_flags" size="4"> + // <field name="incorrect" start="0" end="0"/> + // </flags> + strm.Indent(); + strm << "<flags id=\"" << GetID() << "\" "; + strm.Printf("size=\"%d\"", GetSize()); + strm << ">"; + for (const Field &field : m_fields) { + // Skip padding fields. + if (field.GetName().empty()) + continue; + + strm << "\n"; + strm.IndentMore(); + field.ToXML(strm); + strm.IndentLess(); + } + strm.PutChar('\n'); + strm.Indent("</flags>\n"); +} + +void RegisterFlags::Field::ToXML(StreamString &strm) const { + // Example XML: + // <field name="correct" start="0" end="0"/> + strm.Indent(); + strm << "<field name=\""; + + std::string escaped_name; + llvm::raw_string_ostream escape_strm(escaped_name); + llvm::printHTMLEscaped(GetName(), escape_strm); + strm << escaped_name << "\" "; + + strm.Printf("start=\"%d\" end=\"%d\"", GetStart(), GetEnd()); + strm << "/>"; +} diff --git a/contrib/llvm-project/lldb/source/Target/StackFrame.cpp b/contrib/llvm-project/lldb/source/Target/StackFrame.cpp index 11ada92348ec..50cf01e63cd4 100644 --- a/contrib/llvm-project/lldb/source/Target/StackFrame.cpp +++ b/contrib/llvm-project/lldb/source/Target/StackFrame.cpp @@ -652,7 +652,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( Status deref_error; if (valobj_sp->GetCompilerType().IsReferenceType()) { valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error); - if (error.Fail()) { + if (!valobj_sp || deref_error.Fail()) { error.SetErrorStringWithFormatv( "Failed to dereference reference type: %s", deref_error); return ValueObjectSP(); @@ -660,7 +660,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( } valobj_sp = valobj_sp->Dereference(deref_error); - if (error.Fail()) { + if (!valobj_sp || deref_error.Fail()) { error.SetErrorStringWithFormatv( "Failed to dereference sythetic value: {0}", deref_error); return ValueObjectSP(); @@ -795,9 +795,9 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( // what we have is *ptr[low]. the most similar C++ syntax is to deref // ptr and extract bit low out of it. reading array item low would be // done by saying ptr[low], without a deref * sign - Status error; - ValueObjectSP temp(valobj_sp->Dereference(error)); - if (error.Fail()) { + Status deref_error; + ValueObjectSP temp(valobj_sp->Dereference(deref_error)); + if (!temp || deref_error.Fail()) { valobj_sp->GetExpressionPath(var_expr_path_strm); error.SetErrorStringWithFormat( "could not dereference \"(%s) %s\"", @@ -813,9 +813,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( // arr[0] (an operation that is equivalent to deref-ing arr) and // extract bit low out of it. reading array item low would be done by // saying arr[low], without a deref * sign - Status error; ValueObjectSP temp(valobj_sp->GetChildAtIndex(0)); - if (error.Fail()) { + if (!temp) { valobj_sp->GetExpressionPath(var_expr_path_strm); error.SetErrorStringWithFormat( "could not get item 0 for \"(%s) %s\"", @@ -994,9 +993,9 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( // deref ptr and extract bits low thru high out of it. reading array // items low thru high would be done by saying ptr[low-high], without a // deref * sign - Status error; - ValueObjectSP temp(valobj_sp->Dereference(error)); - if (error.Fail()) { + Status deref_error; + ValueObjectSP temp(valobj_sp->Dereference(deref_error)); + if (!temp || deref_error.Fail()) { valobj_sp->GetExpressionPath(var_expr_path_strm); error.SetErrorStringWithFormat( "could not dereference \"(%s) %s\"", @@ -1011,9 +1010,8 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( // get arr[0] (an operation that is equivalent to deref-ing arr) and // extract bits low thru high out of it. reading array items low thru // high would be done by saying arr[low-high], without a deref * sign - Status error; ValueObjectSP temp(valobj_sp->GetChildAtIndex(0)); - if (error.Fail()) { + if (!temp) { valobj_sp->GetExpressionPath(var_expr_path_strm); error.SetErrorStringWithFormat( "could not get item 0 for \"(%s) %s\"", @@ -1779,18 +1777,30 @@ void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) { exe_ctx.SetContext(shared_from_this()); } +bool StackFrame::DumpUsingFormat(Stream &strm, + const FormatEntity::Entry *format, + llvm::StringRef frame_marker) { + GetSymbolContext(eSymbolContextEverything); + ExecutionContext exe_ctx(shared_from_this()); + StreamString s; + s.PutCString(frame_marker); + + if (format && FormatEntity::Format(*format, s, &m_sc, &exe_ctx, nullptr, + nullptr, false, false)) { + strm.PutCString(s.GetString()); + return true; + } + return false; +} + void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, const char *frame_marker) { if (strm == nullptr) return; - GetSymbolContext(eSymbolContextEverything); ExecutionContext exe_ctx(shared_from_this()); StreamString s; - if (frame_marker) - s.PutCString(frame_marker); - const FormatEntity::Entry *frame_format = nullptr; Target *target = exe_ctx.GetTargetPtr(); if (target) { @@ -1800,10 +1810,7 @@ void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, frame_format = target->GetDebugger().GetFrameFormat(); } } - if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, - nullptr, nullptr, false, false)) { - strm->PutCString(s.GetString()); - } else { + if (!DumpUsingFormat(*strm, frame_format, frame_marker)) { Dump(strm, true, false); strm->EOL(); } diff --git a/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp b/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp index 2841f512439a..2273e52e2e04 100644 --- a/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp +++ b/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp @@ -11,7 +11,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/SourceManager.h" -#include "lldb/Core/StreamFile.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" @@ -156,9 +156,10 @@ void StackFrameList::ResetCurrentInlinedDepth() { m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id)); bool all_internal = true; if (bp_site_sp) { - uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); + uint32_t num_owners = bp_site_sp->GetNumberOfConstituents(); for (uint32_t i = 0; i < num_owners; i++) { - Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); + Breakpoint &bp_ref = + bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint(); if (!bp_ref.IsInternal()) { all_internal = false; } diff --git a/contrib/llvm-project/lldb/source/Target/StopInfo.cpp b/contrib/llvm-project/lldb/source/Target/StopInfo.cpp index efc8fd269ac2..3b65d661c1ab 100644 --- a/contrib/llvm-project/lldb/source/Target/StopInfo.cpp +++ b/contrib/llvm-project/lldb/source/Target/StopInfo.cpp @@ -12,6 +12,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/Watchpoint.h" +#include "lldb/Breakpoint/WatchpointResource.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" @@ -109,9 +110,9 @@ public: BreakpointSiteSP bp_site_sp( thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value)); if (bp_site_sp) { - uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); - if (num_owners == 1) { - BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0); + uint32_t num_constituents = bp_site_sp->GetNumberOfConstituents(); + if (num_constituents == 1) { + BreakpointLocationSP bp_loc_sp = bp_site_sp->GetConstituentAtIndex(0); if (bp_loc_sp) { Breakpoint & bkpt = bp_loc_sp->GetBreakpoint(); m_break_id = bkpt.GetID(); @@ -120,8 +121,10 @@ public: } } else { m_was_all_internal = true; - for (uint32_t i = 0; i < num_owners; i++) { - if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) { + for (uint32_t i = 0; i < num_constituents; i++) { + if (!bp_site_sp->GetConstituentAtIndex(i) + ->GetBreakpoint() + .IsInternal()) { m_was_all_internal = false; break; } @@ -189,9 +192,9 @@ public: // If we have just hit an internal breakpoint, and it has a kind // description, print that instead of the full breakpoint printing: if (bp_site_sp->IsInternal()) { - size_t num_owners = bp_site_sp->GetNumberOfOwners(); - for (size_t idx = 0; idx < num_owners; idx++) { - const char *kind = bp_site_sp->GetOwnerAtIndex(idx) + size_t num_constituents = bp_site_sp->GetNumberOfConstituents(); + for (size_t idx = 0; idx < num_constituents; idx++) { + const char *kind = bp_site_sp->GetConstituentAtIndex(idx) ->GetBreakpoint() .GetBreakpointKind(); if (kind != nullptr) { @@ -284,13 +287,14 @@ protected: // Use this variable to tell us if that is true. bool actually_hit_any_locations = false; if (bp_site_sp) { - // Let's copy the owners list out of the site and store them in a local - // list. That way if one of the breakpoint actions changes the site, - // then we won't be operating on a bad list. + // Let's copy the constituents list out of the site and store them in a + // local list. That way if one of the breakpoint actions changes the + // site, then we won't be operating on a bad list. BreakpointLocationCollection site_locations; - size_t num_owners = bp_site_sp->CopyOwnersList(site_locations); + size_t num_constituents = + bp_site_sp->CopyConstituentsList(site_locations); - if (num_owners == 0) { + if (num_constituents == 0) { m_should_stop = true; actually_hit_any_locations = true; // We're going to stop, don't // change the stop info. @@ -382,20 +386,21 @@ protected: StoppointCallbackContext context(event_ptr, exe_ctx, false); // For safety's sake let's also grab an extra reference to the - // breakpoint owners of the locations we're going to examine, since - // the locations are going to have to get back to their breakpoints, - // and the locations don't keep their owners alive. I'm just - // sticking the BreakpointSP's in a vector since I'm only using it to - // locally increment their retain counts. + // breakpoint constituents of the locations we're going to examine, + // since the locations are going to have to get back to their + // breakpoints, and the locations don't keep their constituents alive. + // I'm just sticking the BreakpointSP's in a vector since I'm only + // using it to locally increment their retain counts. - std::vector<lldb::BreakpointSP> location_owners; + std::vector<lldb::BreakpointSP> location_constituents; - for (size_t j = 0; j < num_owners; j++) { + for (size_t j = 0; j < num_constituents; j++) { BreakpointLocationSP loc(site_locations.GetByIndex(j)); - location_owners.push_back(loc->GetBreakpoint().shared_from_this()); + location_constituents.push_back( + loc->GetBreakpoint().shared_from_this()); } - for (size_t j = 0; j < num_owners; j++) { + for (size_t j = 0; j < num_constituents; j++) { lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j); StreamString loc_desc; if (log) { @@ -631,7 +636,7 @@ public: if (process_sp && watchpoint_sp) { const bool notify = false; watchpoint_sp->TurnOnEphemeralMode(); - process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); + process_sp->DisableWatchpoint(watchpoint_sp, notify); process_sp->AddPreResumeAction(SentryPreResumeAction, this); } } @@ -642,9 +647,9 @@ public: watchpoint_sp->TurnOffEphemeralMode(); const bool notify = false; if (was_disabled) { - process_sp->DisableWatchpoint(watchpoint_sp.get(), notify); + process_sp->DisableWatchpoint(watchpoint_sp, notify); } else { - process_sp->EnableWatchpoint(watchpoint_sp.get(), notify); + process_sp->EnableWatchpoint(watchpoint_sp, notify); } } } @@ -699,7 +704,6 @@ protected: eVoteNoOpinion), m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) { assert(watch_sp); - m_watch_index = watch_sp->GetHardwareIndex(); } bool DoWillResume(lldb::StateType resume_state, @@ -708,7 +712,7 @@ protected: return true; if (!m_did_disable_wp) { - GetThread().GetProcess()->DisableWatchpoint(m_watch_sp.get(), false); + GetThread().GetProcess()->DisableWatchpoint(m_watch_sp, false); m_did_disable_wp = true; } return true; @@ -752,14 +756,12 @@ protected: if (!m_did_disable_wp) return; m_did_disable_wp = true; - GetThread().GetProcess()->EnableWatchpoint(m_watch_sp.get(), true); - m_watch_sp->SetHardwareIndex(m_watch_index); + GetThread().GetProcess()->EnableWatchpoint(m_watch_sp, true); } private: StopInfoWatchpointSP m_stop_info_sp; WatchpointSP m_watch_sp; - uint32_t m_watch_index = LLDB_INVALID_INDEX32; bool m_did_disable_wp = false; }; @@ -982,15 +984,22 @@ protected: m_should_stop = false; } } + + // Don't stop if the watched region value is unmodified, and + // this is a Modify-type watchpoint. + if (m_should_stop && !wp_sp->WatchedValueReportable(exe_ctx)) + m_should_stop = false; + // Finally, if we are going to stop, print out the new & old values: if (m_should_stop) { wp_sp->CaptureWatchedValue(exe_ctx); Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); StreamSP output_sp = debugger.GetAsyncOutputStream(); - wp_sp->DumpSnapshots(output_sp.get()); - output_sp->EOL(); - output_sp->Flush(); + if (wp_sp->DumpSnapshots(output_sp.get())) { + output_sp->EOL(); + output_sp->Flush(); + } } } else { @@ -1067,9 +1076,9 @@ public: thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value); if (should_notify) { StreamString strm; - strm.Printf( - "thread %d received signal: %s", thread_sp->GetIndexID(), - thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString( + strm.Format( + "thread {0:d} received signal: {1}", thread_sp->GetIndexID(), + thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsStringRef( m_value)); Process::ProcessEventData::AddRestartedReason(event_ptr, strm.GetData()); @@ -1363,6 +1372,8 @@ StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread, return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop)); } +// LWP_TODO: We'll need a CreateStopReasonWithWatchpointResourceID akin +// to CreateStopReasonWithBreakpointSiteID StopInfoSP StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id, bool silently_continue) { diff --git a/contrib/llvm-project/lldb/source/Target/Target.cpp b/contrib/llvm-project/lldb/source/Target/Target.cpp index f0c57ef83c4a..302c2bad7021 100644 --- a/contrib/llvm-project/lldb/source/Target/Target.cpp +++ b/contrib/llvm-project/lldb/source/Target/Target.cpp @@ -23,7 +23,6 @@ #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Section.h" #include "lldb/Core/SourceManager.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -34,6 +33,7 @@ #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/Host.h" #include "lldb/Host/PosixApi.h" +#include "lldb/Host/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionGroupWatchpoint.h" @@ -197,7 +197,7 @@ void Target::DeleteCurrentProcess() { if (m_process_sp->IsAlive()) m_process_sp->Destroy(false); - m_process_sp->Finalize(); + m_process_sp->Finalize(false /* not destructing */); CleanupProcess(); @@ -335,6 +335,45 @@ BreakpointSP Target::GetBreakpointByID(break_id_t break_id) { return bp_sp; } +lldb::BreakpointSP +lldb_private::Target::CreateBreakpointAtUserEntry(Status &error) { + ModuleSP main_module_sp = GetExecutableModule(); + FileSpecList shared_lib_filter; + shared_lib_filter.Append(main_module_sp->GetFileSpec()); + llvm::SetVector<std::string, std::vector<std::string>, + std::unordered_set<std::string>> + entryPointNamesSet; + for (LanguageType lang_type : Language::GetSupportedLanguages()) { + Language *lang = Language::FindPlugin(lang_type); + if (!lang) { + error.SetErrorString("Language not found\n"); + return lldb::BreakpointSP(); + } + std::string entryPointName = lang->GetUserEntryPointName().str(); + if (!entryPointName.empty()) + entryPointNamesSet.insert(entryPointName); + } + if (entryPointNamesSet.empty()) { + error.SetErrorString("No entry point name found\n"); + return lldb::BreakpointSP(); + } + BreakpointSP bp_sp = CreateBreakpoint( + &shared_lib_filter, + /*containingSourceFiles=*/nullptr, entryPointNamesSet.takeVector(), + /*func_name_type_mask=*/eFunctionNameTypeFull, + /*language=*/eLanguageTypeUnknown, + /*offset=*/0, + /*skip_prologue=*/eLazyBoolNo, + /*internal=*/false, + /*hardware=*/false); + if (!bp_sp) { + error.SetErrorString("Breakpoint creation failed.\n"); + return lldb::BreakpointSP(); + } + bp_sp->SetOneShot(true); + return bp_sp; +} + BreakpointSP Target::CreateSourceRegexBreakpoint( const FileSpecList *containingModules, const FileSpecList *source_file_spec_list, @@ -441,12 +480,12 @@ BreakpointSP Target::CreateBreakpoint(const Address &addr, bool internal, lldb::BreakpointSP Target::CreateAddressInModuleBreakpoint(lldb::addr_t file_addr, bool internal, - const FileSpec *file_spec, + const FileSpec &file_spec, bool request_hardware) { SearchFilterSP filter_sp( new SearchFilterForUnconstrainedSearches(shared_from_this())); BreakpointResolverSP resolver_sp(new BreakpointResolverAddress( - nullptr, file_addr, file_spec ? *file_spec : FileSpec())); + nullptr, file_addr, file_spec)); return CreateBreakpoint(filter_sp, resolver_sp, internal, request_hardware, false); } @@ -688,7 +727,7 @@ void Target::AddBreakpoint(lldb::BreakpointSP bp_sp, bool internal) { } } -void Target::AddNameToBreakpoint(BreakpointID &id, const char *name, +void Target::AddNameToBreakpoint(BreakpointID &id, llvm::StringRef name, Status &error) { BreakpointSP bp_sp = m_breakpoint_list.FindBreakpointByID(id.GetBreakpointID()); @@ -701,7 +740,7 @@ void Target::AddNameToBreakpoint(BreakpointID &id, const char *name, AddNameToBreakpoint(bp_sp, name, error); } -void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, const char *name, +void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, llvm::StringRef name, Status &error) { if (!bp_sp) return; @@ -853,6 +892,18 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, if (ABISP abi = m_process_sp->GetABI()) addr = abi->FixDataAddress(addr); + // LWP_TODO this sequence is looking for an existing watchpoint + // at the exact same user-specified address, disables the new one + // if addr/size/type match. If type/size differ, disable old one. + // This isn't correct, we need both watchpoints to use a shared + // WatchpointResource in the target, and expand the WatchpointResource + // to handle the needs of both Watchpoints. + // Also, even if the addresses don't match, they may need to be + // supported by the same WatchpointResource, e.g. a watchpoint + // watching 1 byte at 0x102 and a watchpoint watching 1 byte at 0x103. + // They're in the same word and must be watched by a single hardware + // watchpoint register. + std::unique_lock<std::recursive_mutex> lock; this->GetWatchpointList().GetListMutex(lock); WatchpointSP matched_sp = m_watchpoint_list.FindByAddress(addr); @@ -860,14 +911,15 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, size_t old_size = matched_sp->GetByteSize(); uint32_t old_type = (matched_sp->WatchpointRead() ? LLDB_WATCH_TYPE_READ : 0) | - (matched_sp->WatchpointWrite() ? LLDB_WATCH_TYPE_WRITE : 0); + (matched_sp->WatchpointWrite() ? LLDB_WATCH_TYPE_WRITE : 0) | + (matched_sp->WatchpointModify() ? LLDB_WATCH_TYPE_MODIFY : 0); // Return the existing watchpoint if both size and type match. if (size == old_size && kind == old_type) { wp_sp = matched_sp; wp_sp->SetEnabled(false, notify); } else { // Nil the matched watchpoint; we will be creating a new one. - m_process_sp->DisableWatchpoint(matched_sp.get(), notify); + m_process_sp->DisableWatchpoint(matched_sp, notify); m_watchpoint_list.Remove(matched_sp->GetID(), true); } } @@ -878,7 +930,7 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, m_watchpoint_list.Add(wp_sp, true); } - error = m_process_sp->EnableWatchpoint(wp_sp.get(), notify); + error = m_process_sp->EnableWatchpoint(wp_sp, notify); LLDB_LOGF(log, "Target::%s (creation of watchpoint %s with id = %u)\n", __FUNCTION__, error.Success() ? "succeeded" : "failed", wp_sp->GetID()); @@ -887,11 +939,6 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size, // Enabling the watchpoint on the device side failed. Remove the said // watchpoint from the list maintained by the target instance. m_watchpoint_list.Remove(wp_sp->GetID(), true); - // See if we could provide more helpful error message. - if (!OptionGroupWatchpoint::IsWatchSizeSupported(size)) - error.SetErrorStringWithFormat( - "watch size of %" PRIu64 " is not supported", (uint64_t)size); - wp_sp.reset(); } else m_last_created_watchpoint = wp_sp; @@ -1191,7 +1238,7 @@ bool Target::RemoveAllWatchpoints(bool end_to_end) { if (!wp_sp) return false; - Status rc = m_process_sp->DisableWatchpoint(wp_sp.get()); + Status rc = m_process_sp->DisableWatchpoint(wp_sp); if (rc.Fail()) return false; } @@ -1220,7 +1267,7 @@ bool Target::DisableAllWatchpoints(bool end_to_end) { if (!wp_sp) return false; - Status rc = m_process_sp->DisableWatchpoint(wp_sp.get()); + Status rc = m_process_sp->DisableWatchpoint(wp_sp); if (rc.Fail()) return false; } @@ -1247,7 +1294,7 @@ bool Target::EnableAllWatchpoints(bool end_to_end) { if (!wp_sp) return false; - Status rc = m_process_sp->EnableWatchpoint(wp_sp.get()); + Status rc = m_process_sp->EnableWatchpoint(wp_sp); if (rc.Fail()) return false; } @@ -1310,7 +1357,7 @@ bool Target::DisableWatchpointByID(lldb::watch_id_t watch_id) { WatchpointSP wp_sp = m_watchpoint_list.FindByID(watch_id); if (wp_sp) { - Status rc = m_process_sp->DisableWatchpoint(wp_sp.get()); + Status rc = m_process_sp->DisableWatchpoint(wp_sp); if (rc.Success()) return true; @@ -1329,7 +1376,7 @@ bool Target::EnableWatchpointByID(lldb::watch_id_t watch_id) { WatchpointSP wp_sp = m_watchpoint_list.FindByID(watch_id); if (wp_sp) { - Status rc = m_process_sp->EnableWatchpoint(wp_sp.get()); + Status rc = m_process_sp->EnableWatchpoint(wp_sp); if (rc.Success()) return true; @@ -1813,7 +1860,7 @@ size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len, } else { // We have at least one section loaded. This can be because we have // manually loaded some sections with "target modules load ..." or - // because we have have a live process that has sections loaded through + // because we have a live process that has sections loaded through // the dynamic loader load_addr = fixed_addr.GetOffset(); // "fixed_addr" doesn't have a section, so @@ -2096,7 +2143,7 @@ bool Target::ReadPointerFromMemory(const Address &addr, Status &error, } else { // We have at least one section loaded. This can be because we have // manually loaded some sections with "target modules load ..." or - // because we have have a live process that has sections loaded through + // because we have a live process that has sections loaded through // the dynamic loader section_load_list.ResolveLoadAddress(pointer_vm_addr, pointer_addr); } @@ -2135,8 +2182,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, // own module cache system. For example, to leverage build system artifacts, // to bypass pulling files from remote platform, or to search symbol files // from symbol servers. - CallLocateModuleCallbackIfSet(module_spec, module_sp, symbol_file_spec, - did_create_module); + if (m_platform_sp) + m_platform_sp->CallLocateModuleCallbackIfSet( + module_spec, module_sp, symbol_file_spec, &did_create_module); // The result of this CallLocateModuleCallbackIfSet is one of the following. // 1. module_sp:loaded, symbol_file_spec:set @@ -2150,9 +2198,10 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, // to find a module file for this module_spec and we will call // module_sp->SetSymbolFileFileSpec with the symbol_file_spec later. // 4. module_sp:empty, symbol_file_spec:empty - // The callback is not set. Or the callback did not find any module - // files nor any symbol files. Or the callback failed, or something - // went wrong. We continue to find a module file for this module_spec. + // Platform does not exist, the callback is not set, the callback did + // not find any module files nor any symbol files, the callback failed, + // or something went wrong. We continue to find a module file for this + // module_spec. if (!module_sp) { // If there are image search path entries, try to use them to acquire a @@ -2338,113 +2387,6 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, return module_sp; } -void Target::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec, - lldb::ModuleSP &module_sp, - FileSpec &symbol_file_spec, - bool &did_create_module) { - if (!m_platform_sp) - return; - - Platform::LocateModuleCallback locate_module_callback = - m_platform_sp->GetLocateModuleCallback(); - if (!locate_module_callback) - return; - - FileSpec module_file_spec; - Status error = - locate_module_callback(module_spec, module_file_spec, symbol_file_spec); - - // Locate module callback is set and called. Check the error. - Log *log = GetLog(LLDBLog::Target); - if (error.Fail()) { - LLDB_LOGF(log, "%s: locate module callback failed: %s", - LLVM_PRETTY_FUNCTION, error.AsCString()); - return; - } - - // The locate module callback was succeeded. It should returned - // 1. a combination of a module file and a symbol file. - // 2. or only a module file. - // 3. or only a symbol file. For example, a breakpad symbol text file. - // - // Check the module_file_spec and symbol_file_spec values. - // 1. module:empty symbol:empty -> Invalid - // 2. module:exists symbol:exists -> Success - // 3. module:exists symbol:empty -> Success - // 4. module:empty symbol:exists -> Success - if (!module_file_spec && !symbol_file_spec) { - // This is '1. module:empty symbol:empty -> Invalid'. - LLDB_LOGF(log, - "%s: locate module callback did not set both " - "module_file_spec and symbol_file_spec", - LLVM_PRETTY_FUNCTION); - return; - } - - // The module file should exist. - if (module_file_spec && !FileSystem::Instance().Exists(module_file_spec)) { - LLDB_LOGF(log, - "%s: locate module callback set a non-existent file to " - "module_file_spec: %s", - LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str()); - // Clear symbol_file_spec for the error. - symbol_file_spec.Clear(); - return; - } - - // The symbol file should exist. - if (symbol_file_spec && !FileSystem::Instance().Exists(symbol_file_spec)) { - LLDB_LOGF(log, - "%s: locate module callback set a non-existent file to " - "symbol_file_spec: %s", - LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str()); - // Clear symbol_file_spec for the error. - symbol_file_spec.Clear(); - return; - } - - if (!module_file_spec && symbol_file_spec) { - // This is '4. module:empty symbol:exists -> Success'. - // The locate module callback returned only a symbol file. For example, - // a breakpad symbol text file. GetOrCreateModule will use this returned - // symbol_file_spec. - LLDB_LOGF(log, "%s: locate module callback succeeded: symbol=%s", - LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str()); - return; - } - - // The locate module callback returned - // - '2. module:exists symbol:exists -> Success' - // - a combination of a module file and a symbol file. - // - Or '3. module:exists symbol:empty -> Success' - // - only a module file. - // Load the module file. - auto cached_module_spec(module_spec); - cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md5 - // content hash instead of real UUID. - cached_module_spec.GetFileSpec() = module_file_spec; - cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec(); - cached_module_spec.SetObjectOffset(0); - - error = ModuleList::GetSharedModule(cached_module_spec, module_sp, nullptr, - nullptr, &did_create_module, false); - if (error.Success() && module_sp) { - // Succeeded to load the module file. - LLDB_LOGF(log, "%s: locate module callback succeeded: module=%s symbol=%s", - LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(), - symbol_file_spec.GetPath().c_str()); - } else { - LLDB_LOGF(log, - "%s: locate module callback succeeded but failed to load: " - "module=%s symbol=%s", - LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(), - symbol_file_spec.GetPath().c_str()); - // Clear module_sp and symbol_file_spec for the error. - module_sp.reset(); - symbol_file_spec.Clear(); - } -} - TargetSP Target::CalculateTarget() { return shared_from_this(); } ProcessSP Target::CalculateProcess() { return m_process_sp; } @@ -2969,12 +2911,12 @@ bool Target::RunStopHooks() { if (!any_active_hooks) return false; - // <rdar://problem/12027563> make sure we check that we are not stopped - // because of us running a user expression since in that case we do not want - // to run the stop-hooks. Note, you can't just check whether the last stop - // was for a User Expression, because breakpoint commands get run before - // stop hooks, and one of them might have run an expression. You have - // to ensure you run the stop hooks once per natural stop. + // Make sure we check that we are not stopped because of us running a user + // expression since in that case we do not want to run the stop-hooks. Note, + // you can't just check whether the last stop was for a User Expression, + // because breakpoint commands get run before stop hooks, and one of them + // might have run an expression. You have to ensure you run the stop hooks + // once per natural stop. uint32_t last_natural_stop = m_process_sp->GetModIDRef().GetLastNaturalStopID(); if (last_natural_stop != 0 && m_latest_stop_hook_id == last_natural_stop) return false; @@ -3964,11 +3906,10 @@ void Target::StopHookScripted::GetSubclassDescription( s.Indent("Args:\n"); s.SetIndentLevel(s.GetIndentLevel() + 4); - auto print_one_element = [&s](ConstString key, + auto print_one_element = [&s](llvm::StringRef key, StructuredData::Object *object) { s.Indent(); - s.Printf("%s : %s\n", key.GetCString(), - object->GetStringValue().str().c_str()); + s.Format("{0} : {1}\n", key, object->GetStringValue()); return true; }; @@ -4167,7 +4108,7 @@ enum { class TargetOptionValueProperties : public Cloneable<TargetOptionValueProperties, OptionValueProperties> { public: - TargetOptionValueProperties(ConstString name) : Cloneable(name) {} + TargetOptionValueProperties(llvm::StringRef name) : Cloneable(name) {} const Property * GetPropertyAtIndex(size_t idx, @@ -4203,7 +4144,7 @@ class TargetExperimentalOptionValueProperties OptionValueProperties> { public: TargetExperimentalOptionValueProperties() - : Cloneable(ConstString(Properties::GetExperimentalSettingsName())) {} + : Cloneable(Properties::GetExperimentalSettingsName()) {} }; TargetExperimentalProperties::TargetExperimentalProperties() @@ -4257,8 +4198,7 @@ TargetProperties::TargetProperties(Target *target) "errors if the setting is not present.", true, m_experimental_properties_up->GetValueProperties()); } else { - m_collection_sp = - std::make_shared<TargetOptionValueProperties>(ConstString("target")); + m_collection_sp = std::make_shared<TargetOptionValueProperties>("target"); m_collection_sp->Initialize(g_target_properties); m_experimental_properties_up = std::make_unique<TargetExperimentalProperties>(); @@ -4343,8 +4283,8 @@ bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) { } bool TargetProperties::GetPreloadSymbols() const { - if (INTERRUPT_REQUESTED(m_target->GetDebugger(), - "Interrupted checking preload symbols")) { + if (INTERRUPT_REQUESTED(m_target->GetDebugger(), + "Interrupted checking preload symbols")) { return false; } const uint32_t idx = ePropertyPreloadSymbols; @@ -4646,6 +4586,12 @@ bool TargetProperties::GetEnableSyntheticValue() const { idx, g_target_properties[idx].default_uint_value != 0); } +bool TargetProperties::ShowHexVariableValuesWithLeadingZeroes() const { + const uint32_t idx = ePropertyShowHexVariableValuesWithLeadingZeroes; + return GetPropertyAtIndexAs<bool>( + idx, g_target_properties[idx].default_uint_value != 0); +} + uint32_t TargetProperties::GetMaxZeroPaddingInFloatFormat() const { const uint32_t idx = ePropertyMaxZeroPaddingInFloatFormat; return GetPropertyAtIndexAs<uint64_t>( diff --git a/contrib/llvm-project/lldb/source/Target/TargetList.cpp b/contrib/llvm-project/lldb/source/Target/TargetList.cpp index cb198e388011..121b6253d2a5 100644 --- a/contrib/llvm-project/lldb/source/Target/TargetList.cpp +++ b/contrib/llvm-project/lldb/source/Target/TargetList.cpp @@ -271,7 +271,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger, arch = specified_arch; FileSpec file(user_exe_path); - if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) { + if (!FileSystem::Instance().Exists(file) && user_exe_path.starts_with("~")) { // we want to expand the tilde but we don't want to resolve any symbolic // links so we can't use the FileSpec constructor's resolve flag llvm::SmallString<64> unglobbed_path; @@ -370,7 +370,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger, bool TargetList::DeleteTarget(TargetSP &target_sp) { std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); - auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); + auto it = llvm::find(m_target_list, target_sp); if (it == m_target_list.end()) return false; @@ -506,7 +506,7 @@ lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const { uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const { std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); - auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); + auto it = llvm::find(m_target_list, target_sp); if (it != m_target_list.end()) return std::distance(m_target_list.begin(), it); return UINT32_MAX; @@ -533,7 +533,7 @@ void TargetList::SetSelectedTarget(uint32_t index) { void TargetList::SetSelectedTarget(const TargetSP &target_sp) { std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); - auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); + auto it = llvm::find(m_target_list, target_sp); SetSelectedTargetInternal(std::distance(m_target_list.begin(), it)); } diff --git a/contrib/llvm-project/lldb/source/Target/TargetProperties.td b/contrib/llvm-project/lldb/source/Target/TargetProperties.td index 19ea505af656..154a6e5919ab 100644 --- a/contrib/llvm-project/lldb/source/Target/TargetProperties.td +++ b/contrib/llvm-project/lldb/source/Target/TargetProperties.td @@ -82,6 +82,10 @@ let Definition = "target" in { def SaveObjectsDir: Property<"save-jit-objects-dir", "FileSpec">, DefaultStringValue<"">, Desc<"If specified, the directory to save intermediate object files generated by the LLVM JIT">; + def ShowHexVariableValuesWithLeadingZeroes: Property<"show-hex-variable-values-with-leading-zeroes", "Boolean">, + Global, + DefaultTrue, + Desc<"Whether to display leading zeroes when printing variable values in hex format.">; def MaxZeroPaddingInFloatFormat: Property<"max-zero-padding-in-float-format", "UInt64">, DefaultUnsignedValue<6>, Desc<"The maximum number of zeroes to insert when displaying a very small float before falling back to scientific notation.">; @@ -244,10 +248,18 @@ let Definition = "process" in { DefaultTrue, Desc<"If true, stop when the inferior exec's.">; def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">, +#ifdef LLDB_SANITIZED + DefaultUnsignedValue<60>, +#else DefaultUnsignedValue<15>, +#endif Desc<"The time in seconds to wait for LLDB-internal utility expressions.">; def InterruptTimeout: Property<"interrupt-timeout", "UInt64">, +#ifdef LLDB_SANITIZED + DefaultUnsignedValue<60>, +#else DefaultUnsignedValue<20>, +#endif Desc<"The time in seconds to wait for an interrupt succeed in stopping the target.">; def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">, DefaultFalse, diff --git a/contrib/llvm-project/lldb/source/Target/Thread.cpp b/contrib/llvm-project/lldb/source/Target/Thread.cpp index ec4ffcbd9205..865cee97e6d8 100644 --- a/contrib/llvm-project/lldb/source/Target/Thread.cpp +++ b/contrib/llvm-project/lldb/source/Target/Thread.cpp @@ -76,7 +76,7 @@ enum { class ThreadOptionValueProperties : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> { public: - ThreadOptionValueProperties(ConstString name) : Cloneable(name) {} + ThreadOptionValueProperties(llvm::StringRef name) : Cloneable(name) {} const Property * GetPropertyAtIndex(size_t idx, @@ -100,8 +100,7 @@ public: ThreadProperties::ThreadProperties(bool is_global) : Properties() { if (is_global) { - m_collection_sp = - std::make_shared<ThreadOptionValueProperties>(ConstString("thread")); + m_collection_sp = std::make_shared<ThreadOptionValueProperties>("thread"); m_collection_sp->Initialize(g_thread_properties); } else m_collection_sp = @@ -1590,12 +1589,12 @@ Status Thread::JumpToLine(const FileSpec &file, uint32_t line, return Status(); } -void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, - bool stop_format) { +bool Thread::DumpUsingFormat(Stream &strm, uint32_t frame_idx, + const FormatEntity::Entry *format) { ExecutionContext exe_ctx(shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); - if (process == nullptr) - return; + if (!process || !format) + return false; StackFrameSP frame_sp; SymbolContext frame_sc; @@ -1607,6 +1606,14 @@ void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, } } + return FormatEntity::Format(*format, strm, frame_sp ? &frame_sc : nullptr, + &exe_ctx, nullptr, nullptr, false, false); +} + +void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, + bool stop_format) { + ExecutionContext exe_ctx(shared_from_this()); + const FormatEntity::Entry *thread_format; if (stop_format) thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat(); @@ -1615,15 +1622,18 @@ void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, assert(thread_format); - FormatEntity::Format(*thread_format, strm, frame_sp ? &frame_sc : nullptr, - &exe_ctx, nullptr, nullptr, false, false); + DumpUsingFormat(strm, frame_idx, thread_format); } void Thread::SettingsInitialize() {} void Thread::SettingsTerminate() {} -lldb::addr_t Thread::GetThreadPointer() { return LLDB_INVALID_ADDRESS; } +lldb::addr_t Thread::GetThreadPointer() { + if (m_reg_context_sp) + return m_reg_context_sp->GetThreadPointer(); + return LLDB_INVALID_ADDRESS; +} addr_t Thread::GetThreadLocalData(const ModuleSP module, lldb::addr_t tls_file_addr) { diff --git a/contrib/llvm-project/lldb/source/Target/ThreadList.cpp b/contrib/llvm-project/lldb/source/Target/ThreadList.cpp index 006c8648be52..1ba0c435b993 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadList.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadList.cpp @@ -736,7 +736,7 @@ void ThreadList::Update(ThreadList &rhs) { if (this != &rhs) { // Lock both mutexes to make sure neither side changes anyone on us while // the assignment occurs - std::lock_guard<std::recursive_mutex> guard(GetMutex()); + std::scoped_lock<std::recursive_mutex, std::recursive_mutex> guard(GetMutex(), rhs.GetMutex()); m_process = rhs.m_process; m_stop_id = rhs.m_stop_id; diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp index 31027cd9e011..50dcb66b9719 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -291,10 +291,10 @@ bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { BreakpointSiteSP bp_site_sp; bp_site_sp = m_process.GetBreakpointSiteList().FindByID(break_site_id); if (bp_site_sp) { - uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); + uint32_t num_owners = bp_site_sp->GetNumberOfConstituents(); bool is_internal = true; for (uint32_t i = 0; i < num_owners; i++) { - Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); + Breakpoint &bp = bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint(); LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: hit " "breakpoint %d while calling function", diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp index 7bf1d2a8b579..0a1e2ae605ef 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepOut.cpp @@ -322,7 +322,7 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) { // important to report the user breakpoint than the step out // completion. - if (site_sp->GetNumberOfOwners() == 1) + if (site_sp->GetNumberOfConstituents() == 1) return true; } return false; diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp index 0d5144d7a46b..bb92adcae78b 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp @@ -400,14 +400,14 @@ bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop( return false; else { // If we've hit the next branch breakpoint, then clear it. - size_t num_owners = bp_site_sp->GetNumberOfOwners(); + size_t num_constituents = bp_site_sp->GetNumberOfConstituents(); bool explains_stop = true; - // If all the owners are internal, then we are probably just stepping over - // this range from multiple threads, or multiple frames, so we want to + // If all the constituents are internal, then we are probably just stepping + // over this range from multiple threads, or multiple frames, so we want to // continue. If one is not internal, then we should not explain the stop, // and let the user breakpoint handle the stop. - for (size_t i = 0; i < num_owners; i++) { - if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) { + for (size_t i = 0; i < num_constituents; i++) { + if (!bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint().IsInternal()) { explains_stop = false; break; } @@ -415,8 +415,8 @@ bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop( LLDB_LOGF(log, "ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit " "next range breakpoint which has %" PRIu64 - " owners - explains stop: %u.", - (uint64_t)num_owners, explains_stop); + " constituents - explains stop: %u.", + (uint64_t)num_constituents, explains_stop); ClearNextBranchBreakpoint(); return explains_stop; } diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepUntil.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepUntil.cpp index f63e97d3c402..ee0f803510e6 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStepUntil.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStepUntil.cpp @@ -182,7 +182,7 @@ void ThreadPlanStepUntil::AnalyzeStop() { } else m_should_stop = false; - if (this_site->GetNumberOfOwners() == 1) + if (this_site->GetNumberOfConstituents() == 1) m_explains_stop = true; else m_explains_stop = false; @@ -228,7 +228,7 @@ void ThreadPlanStepUntil::AnalyzeStop() { // only breakpoint here, then we do explain the stop, and we'll // continue. If not then we should let higher plans handle this // stop. - if (this_site->GetNumberOfOwners() == 1) + if (this_site->GetNumberOfConstituents() == 1) m_explains_stop = true; else { m_should_stop = true; diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp index f4d80ba89071..acadda8f582f 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp @@ -12,7 +12,6 @@ #include "lldb/Core/Disassembler.h" #include "lldb/Core/DumpRegisterValue.h" #include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeSystem.h" diff --git a/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp b/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp index d059d443805c..e92419e70b32 100644 --- a/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp +++ b/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp @@ -472,7 +472,7 @@ TraceDumper::TraceItem TraceDumper::CreatRawTraceItem() { static SymbolContext CalculateSymbolContext(const Address &address, const SymbolContext &prev_symbol_context) { - AddressRange range; + lldb_private::AddressRange range; if (prev_symbol_context.GetAddressRange(eSymbolContextEverything, 0, /*inline_block_range*/ true, range) && range.Contains(address)) @@ -508,7 +508,8 @@ CalculateDisass(const TraceDumper::SymbolInfo &symbol_info, // We fallback to a single instruction disassembler Target &target = exe_ctx.GetTargetRef(); const ArchSpec arch = target.GetArchitecture(); - AddressRange range(symbol_info.address, arch.GetMaximumOpcodeByteSize()); + lldb_private::AddressRange range(symbol_info.address, + arch.GetMaximumOpcodeByteSize()); DisassemblerSP disassembler = Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr, /*flavor*/ nullptr, target, range); @@ -778,7 +779,7 @@ static TraceDumper::FunctionCall &AppendInstructionToFunctionCallForest( return *roots.back(); } - AddressRange range; + lldb_private::AddressRange range; if (symbol_info.sc.GetAddressRange( eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol, 0, /*inline_block_range*/ true, range)) { diff --git a/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp b/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp index 0e738241b1c5..e3c7a83ece07 100644 --- a/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp +++ b/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp @@ -18,17 +18,13 @@ using namespace lldb_private; using namespace llvm; -UnixSignals::Signal::Signal(const char *name, bool default_suppress, +UnixSignals::Signal::Signal(llvm::StringRef name, bool default_suppress, bool default_stop, bool default_notify, - const char *description, const char *alias) - : m_name(name), m_alias(alias), m_description(), + llvm::StringRef description, llvm::StringRef alias) + : m_name(name), m_alias(alias), m_description(description), m_suppress(default_suppress), m_stop(default_stop), - m_notify(default_notify), - m_default_suppress(default_suppress), m_default_stop(default_stop), - m_default_notify(default_notify) { - if (description) - m_description.assign(description); -} + m_notify(default_notify), m_default_suppress(default_suppress), + m_default_stop(default_stop), m_default_notify(default_notify) {} lldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) { const auto &triple = arch.GetTriple(); @@ -104,9 +100,10 @@ void UnixSignals::Reset() { // clang-format on } -void UnixSignals::AddSignal(int signo, const char *name, bool default_suppress, - bool default_stop, bool default_notify, - const char *description, const char *alias) { +void UnixSignals::AddSignal(int signo, llvm::StringRef name, + bool default_suppress, bool default_stop, + bool default_notify, llvm::StringRef description, + llvm::StringRef alias) { Signal new_signal(name, default_suppress, default_stop, default_notify, description, alias); m_signals.insert(std::make_pair(signo, new_signal)); @@ -131,12 +128,11 @@ void UnixSignals::RemoveSignal(int signo) { ++m_version; } -const char *UnixSignals::GetSignalAsCString(int signo) const { - collection::const_iterator pos = m_signals.find(signo); +llvm::StringRef UnixSignals::GetSignalAsStringRef(int32_t signo) const { + const auto pos = m_signals.find(signo); if (pos == m_signals.end()) - return nullptr; - else - return pos->second.m_name.GetCString(); + return {}; + return pos->second.m_name; } std::string @@ -148,7 +144,7 @@ UnixSignals::GetSignalDescription(int32_t signo, std::optional<int32_t> code, collection::const_iterator pos = m_signals.find(signo); if (pos != m_signals.end()) { - str = pos->second.m_name.GetCString(); + str = pos->second.m_name.str(); if (code) { std::map<int32_t, SignalCode>::const_iterator cpos = @@ -200,14 +196,13 @@ llvm::StringRef UnixSignals::GetShortName(llvm::StringRef name) const { } int32_t UnixSignals::GetSignalNumberFromName(const char *name) const { - ConstString const_name(name); + llvm::StringRef name_ref(name); collection::const_iterator pos, end = m_signals.end(); for (pos = m_signals.begin(); pos != end; pos++) { - if ((const_name == pos->second.m_name) || - (const_name == pos->second.m_alias) || - (const_name == GetShortName(pos->second.m_name)) || - (const_name == GetShortName(pos->second.m_alias))) + if ((name_ref == pos->second.m_name) || (name_ref == pos->second.m_alias) || + (name_ref == GetShortName(pos->second.m_name)) || + (name_ref == GetShortName(pos->second.m_alias))) return pos->first; } @@ -238,19 +233,17 @@ int32_t UnixSignals::GetNextSignalNumber(int32_t current_signal) const { } } -const char *UnixSignals::GetSignalInfo(int32_t signo, bool &should_suppress, - bool &should_stop, - bool &should_notify) const { - collection::const_iterator pos = m_signals.find(signo); +bool UnixSignals::GetSignalInfo(int32_t signo, bool &should_suppress, + bool &should_stop, bool &should_notify) const { + const auto pos = m_signals.find(signo); if (pos == m_signals.end()) - return nullptr; - else { - const Signal &signal = pos->second; - should_suppress = signal.m_suppress; - should_stop = signal.m_stop; - should_notify = signal.m_notify; - return signal.m_name.AsCString(""); - } + return false; + + const Signal &signal = pos->second; + should_suppress = signal.m_suppress; + should_stop = signal.m_stop; + should_notify = signal.m_notify; + return true; } bool UnixSignals::GetShouldSuppress(int signo) const { @@ -376,11 +369,10 @@ void UnixSignals::IncrementSignalHitCount(int signo) { json::Value UnixSignals::GetHitCountStatistics() const { json::Array json_signals; - for (const auto &pair: m_signals) { + for (const auto &pair : m_signals) { if (pair.second.m_hit_count > 0) - json_signals.emplace_back(json::Object{ - { pair.second.m_name.GetCString(), pair.second.m_hit_count } - }); + json_signals.emplace_back( + json::Object{{pair.second.m_name, pair.second.m_hit_count}}); } return std::move(json_signals); } diff --git a/contrib/llvm-project/lldb/source/Utility/AddressableBits.cpp b/contrib/llvm-project/lldb/source/Utility/AddressableBits.cpp new file mode 100644 index 000000000000..c6e25f608da7 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/AddressableBits.cpp @@ -0,0 +1,51 @@ +//===-- AddressableBits.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/Utility/AddressableBits.h" +#include "lldb/Target/Process.h" +#include "lldb/lldb-types.h" + +using namespace lldb; +using namespace lldb_private; + +void AddressableBits::SetAddressableBits(uint32_t addressing_bits) { + m_low_memory_addr_bits = m_high_memory_addr_bits = addressing_bits; +} + +void AddressableBits::SetAddressableBits(uint32_t lowmem_addressing_bits, + uint32_t highmem_addressing_bits) { + m_low_memory_addr_bits = lowmem_addressing_bits; + m_high_memory_addr_bits = highmem_addressing_bits; +} + +void AddressableBits::SetLowmemAddressableBits( + uint32_t lowmem_addressing_bits) { + m_low_memory_addr_bits = lowmem_addressing_bits; +} + +void AddressableBits::SetHighmemAddressableBits( + uint32_t highmem_addressing_bits) { + m_high_memory_addr_bits = highmem_addressing_bits; +} + +void AddressableBits::SetProcessMasks(Process &process) { + if (m_low_memory_addr_bits == 0 && m_high_memory_addr_bits == 0) + return; + + if (m_low_memory_addr_bits != 0) { + addr_t low_addr_mask = ~((1ULL << m_low_memory_addr_bits) - 1); + process.SetCodeAddressMask(low_addr_mask); + process.SetDataAddressMask(low_addr_mask); + } + + if (m_high_memory_addr_bits != 0) { + addr_t hi_addr_mask = ~((1ULL << m_high_memory_addr_bits) - 1); + process.SetHighmemCodeAddressMask(hi_addr_mask); + process.SetHighmemDataAddressMask(hi_addr_mask); + } +} diff --git a/contrib/llvm-project/lldb/source/Utility/Args.cpp b/contrib/llvm-project/lldb/source/Utility/Args.cpp index d34433996021..13b993bc74c9 100644 --- a/contrib/llvm-project/lldb/source/Utility/Args.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Args.cpp @@ -25,7 +25,7 @@ static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted, // Inside double quotes, '\' and '"' are special. static const char *k_escapable_characters = "\"\\"; while (true) { - // Skip over over regular characters and append them. + // Skip over regular characters and append them. size_t regular = quoted.find_first_of(k_escapable_characters); result += quoted.substr(0, regular); quoted = quoted.substr(regular); @@ -93,7 +93,7 @@ ParseSingleArgument(llvm::StringRef command) { bool arg_complete = false; do { - // Skip over over regular characters and append them. + // Skip over regular characters and append them. size_t regular = command.find_first_of(" \t\r\"'`\\"); arg += command.substr(0, regular); command = command.substr(regular); @@ -445,6 +445,7 @@ uint32_t Args::StringToGenericRegister(llvm::StringRef s) { .Case("arg6", LLDB_REGNUM_GENERIC_ARG6) .Case("arg7", LLDB_REGNUM_GENERIC_ARG7) .Case("arg8", LLDB_REGNUM_GENERIC_ARG8) + .Case("tp", LLDB_REGNUM_GENERIC_TP) .Default(LLDB_INVALID_REGNUM); return result; } @@ -640,7 +641,7 @@ void OptionsWithRaw::SetFromString(llvm::StringRef arg_string) { // If the string doesn't start with a dash, we just have no options and just // a raw part. - if (!arg_string.startswith("-")) { + if (!arg_string.starts_with("-")) { m_suffix = std::string(original_args); return; } diff --git a/contrib/llvm-project/lldb/source/Utility/Broadcaster.cpp b/contrib/llvm-project/lldb/source/Utility/Broadcaster.cpp index c9ecd4a7d2a9..914812d78577 100644 --- a/contrib/llvm-project/lldb/source/Utility/Broadcaster.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Broadcaster.cpp @@ -50,22 +50,42 @@ void Broadcaster::CheckInWithManager() { } llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> -Broadcaster::BroadcasterImpl::GetListeners() { +Broadcaster::BroadcasterImpl::GetListeners(uint32_t event_mask, + bool include_primary) { llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> listeners; - listeners.reserve(m_listeners.size()); + size_t max_count = m_listeners.size(); + if (include_primary) + max_count++; + listeners.reserve(max_count); for (auto it = m_listeners.begin(); it != m_listeners.end();) { lldb::ListenerSP curr_listener_sp(it->first.lock()); - if (curr_listener_sp && it->second) { - listeners.emplace_back(std::move(curr_listener_sp), it->second); + if (curr_listener_sp) { + if (it->second & event_mask) + listeners.emplace_back(std::move(curr_listener_sp), it->second); ++it; } else + // If our listener_wp didn't resolve, then we should remove this entry. it = m_listeners.erase(it); } + if (include_primary && m_primary_listener_sp) + listeners.emplace_back(m_primary_listener_sp, m_primary_listener_mask); return listeners; } +bool Broadcaster::BroadcasterImpl::HasListeners(uint32_t event_mask) { + if (m_primary_listener_sp) + return true; + for (auto it = m_listeners.begin(); it != m_listeners.end(); it++) { + // Don't return a listener if the other end of the WP is gone: + lldb::ListenerSP curr_listener_sp(it->first.lock()); + if (curr_listener_sp && (it->second & event_mask)) + return true; + } + return false; +} + void Broadcaster::BroadcasterImpl::Clear() { std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); @@ -75,6 +95,7 @@ void Broadcaster::BroadcasterImpl::Clear() { pair.first->BroadcasterWillDestruct(&m_broadcaster); m_listeners.clear(); + m_primary_listener_sp.reset(); } Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() { @@ -122,7 +143,11 @@ Broadcaster::BroadcasterImpl::AddListener(const lldb::ListenerSP &listener_sp, bool handled = false; - for (auto &pair : GetListeners()) { + if (listener_sp == m_primary_listener_sp) + // This already handles all bits so just return the mask: + return event_mask; + + for (auto &pair : GetListeners(UINT32_MAX, false)) { if (pair.first == listener_sp) { handled = true; pair.second |= event_mask; @@ -151,11 +176,11 @@ bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) { if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back()) return true; - for (auto &pair : GetListeners()) { - if (pair.second & event_type) - return true; - } - return false; + // The primary listener listens for all event bits: + if (m_primary_listener_sp) + return true; + + return HasListeners(event_type); } bool Broadcaster::BroadcasterImpl::RemoveListener( @@ -163,12 +188,33 @@ bool Broadcaster::BroadcasterImpl::RemoveListener( if (!listener) return false; + if (listener == m_primary_listener_sp.get()) { + // Primary listeners listen for all the event bits for their broadcaster, + // so remove this altogether if asked: + m_primary_listener_sp.reset(); + return true; + } + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - for (auto &pair : GetListeners()) { - if (pair.first.get() == listener) { - pair.second &= ~event_mask; - return true; + for (auto it = m_listeners.begin(); it != m_listeners.end();) { + lldb::ListenerSP curr_listener_sp(it->first.lock()); + + if (!curr_listener_sp) { + // The weak pointer for this listener didn't resolve, lets' prune it + // as we go. + m_listeners.erase(it); + continue; } + + if (curr_listener_sp.get() == listener) { + it->second &= ~event_mask; + // If we removed all the event bits from a listener, remove it from + // the list as well. + if (!it->second) + m_listeners.erase(it); + return true; + } else + it++; } return false; } @@ -222,25 +268,34 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, event_description.GetData(), unique, static_cast<void *>(hijacking_listener_sp.get())); } + ListenerSP primary_listener_sp + = hijacking_listener_sp ? hijacking_listener_sp : m_primary_listener_sp; - if (hijacking_listener_sp) { - if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType( + if (primary_listener_sp) { + if (unique && primary_listener_sp->PeekAtNextEventForBroadcasterWithType( &m_broadcaster, event_type)) return; - hijacking_listener_sp->AddEvent(event_sp); - if (m_shadow_listener) - m_shadow_listener->AddEvent(event_sp); + // Add the pending listeners but not if the event is hijacked, since that + // is given sole access to the event stream it is hijacking. + // Make sure to do this before adding the event to the primary or it might + // start handling the event before we're done adding all the pending + // listeners. + // Also, don't redo the check for unique here, since otherwise that could + // be racy, and if we send the event to the primary listener then we SHOULD + // send it to the secondary listeners or they will get out of sync with the + // primary listener. + if (!hijacking_listener_sp) { + for (auto &pair : GetListeners(event_type, false)) + event_sp->AddPendingListener(pair.first); + } + primary_listener_sp->AddEvent(event_sp); } else { - for (auto &pair : GetListeners()) { - if (!(pair.second & event_type)) - continue; + for (auto &pair : GetListeners(event_type)) { if (unique && pair.first->PeekAtNextEventForBroadcasterWithType( &m_broadcaster, event_type)) continue; pair.first->AddEvent(event_sp); - if (m_shadow_listener) - m_shadow_listener->AddEvent(event_sp); } } } @@ -263,6 +318,15 @@ void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique( PrivateBroadcastEvent(event_sp, true); } +void Broadcaster::BroadcasterImpl::SetPrimaryListener(lldb::ListenerSP + listener_sp) { + // This might have already been added as a normal listener, make sure we + // don't hold two copies. + RemoveListener(listener_sp.get(), UINT32_MAX); + m_primary_listener_sp = listener_sp; + +} + bool Broadcaster::BroadcasterImpl::HijackBroadcaster( const lldb::ListenerSP &listener_sp, uint32_t event_mask) { std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); diff --git a/contrib/llvm-project/lldb/source/Utility/Checksum.cpp b/contrib/llvm-project/lldb/source/Utility/Checksum.cpp new file mode 100644 index 000000000000..8943b4e12852 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/Checksum.cpp @@ -0,0 +1,44 @@ +//===-- Checksum.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/Utility/Checksum.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" + +using namespace lldb_private; + +Checksum::Checksum(llvm::MD5::MD5Result md5) { SetMD5(md5); } + +Checksum::Checksum(const Checksum &checksum) { SetMD5(checksum.m_checksum); } + +Checksum &Checksum::operator=(const Checksum &checksum) { + SetMD5(checksum.m_checksum); + return *this; +} + +void Checksum::SetMD5(llvm::MD5::MD5Result md5) { + const constexpr size_t md5_length = 16; + std::uninitialized_copy_n(md5.begin(), md5_length, m_checksum.begin()); +} + +Checksum::operator bool() const { return !llvm::equal(m_checksum, g_sentinel); } + +bool Checksum::operator==(const Checksum &checksum) const { + return llvm::equal(m_checksum, checksum.m_checksum); +} + +bool Checksum::operator!=(const Checksum &checksum) const { + return !(*this == checksum); +} + +std::string Checksum::digest() const { + return std::string(m_checksum.digest()); +} + +llvm::MD5::MD5Result Checksum::g_sentinel = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; diff --git a/contrib/llvm-project/lldb/source/Utility/CompletionRequest.cpp b/contrib/llvm-project/lldb/source/Utility/CompletionRequest.cpp index 8f9dbb79d37b..e12609ca75e7 100644 --- a/contrib/llvm-project/lldb/source/Utility/CompletionRequest.cpp +++ b/contrib/llvm-project/lldb/source/Utility/CompletionRequest.cpp @@ -36,8 +36,8 @@ CompletionRequest::CompletionRequest(llvm::StringRef command_line, // The cursor is after a space but the space is not part of the argument. // Let's add an empty fake argument to the end to make sure the completion // code. Note: The space could be part of the last argument when it's quoted. - if (partial_command.endswith(" ") && - !GetCursorArgumentPrefix().endswith(" ")) + if (partial_command.ends_with(" ") && + !GetCursorArgumentPrefix().ends_with(" ")) AppendEmptyArgument(); } diff --git a/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp b/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp index 1632ae0f9dfd..b2a08165dd6c 100644 --- a/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp @@ -52,10 +52,8 @@ Diagnostics::CallbackID Diagnostics::AddCallback(Callback callback) { void Diagnostics::RemoveCallback(CallbackID id) { std::lock_guard<std::mutex> guard(m_callbacks_mutex); - m_callbacks.erase( - std::remove_if(m_callbacks.begin(), m_callbacks.end(), - [id](const CallbackEntry &e) { return e.id == id; }), - m_callbacks.end()); + llvm::erase_if(m_callbacks, + [id](const CallbackEntry &e) { return e.id == id; }); } bool Diagnostics::Dump(raw_ostream &stream) { diff --git a/contrib/llvm-project/lldb/source/Utility/Event.cpp b/contrib/llvm-project/lldb/source/Utility/Event.cpp index fcc367f43f93..cac118182c75 100644 --- a/contrib/llvm-project/lldb/source/Utility/Event.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Event.cpp @@ -11,6 +11,7 @@ #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "lldb/lldb-enumerations.h" @@ -80,8 +81,16 @@ void Event::Dump(Stream *s) const { } void Event::DoOnRemoval() { + std::lock_guard<std::mutex> guard(m_listeners_mutex); + if (m_data_sp) m_data_sp->DoOnRemoval(this); + // Now that the event has been handled by the primary event Listener, forward + // it to the other Listeners. + EventSP me_sp = shared_from_this(); + for (auto listener_sp : m_pending_listeners) + listener_sp->AddEvent(me_sp); + m_pending_listeners.clear(); } #pragma mark - diff --git a/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp b/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp index eb34ef97cea0..5387be9a681f 100644 --- a/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp +++ b/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp @@ -68,8 +68,9 @@ void Denormalize(llvm::SmallVectorImpl<char> &path, FileSpec::Style style) { FileSpec::FileSpec() : m_style(GetNativeStyle()) {} // Default constructor that can take an optional full path to a file on disk. -FileSpec::FileSpec(llvm::StringRef path, Style style) : m_style(style) { - SetFile(path, style); +FileSpec::FileSpec(llvm::StringRef path, Style style, const Checksum &checksum) + : m_checksum(checksum), m_style(style) { + SetFile(path, style, checksum); } FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &triple) @@ -171,9 +172,11 @@ void FileSpec::SetFile(llvm::StringRef pathname) { SetFile(pathname, m_style); } // Update the contents of this object with a new path. The path will be split // up into a directory and filename and stored as uniqued string values for // quick comparison and efficient memory usage. -void FileSpec::SetFile(llvm::StringRef pathname, Style style) { +void FileSpec::SetFile(llvm::StringRef pathname, Style style, + const Checksum &checksum) { Clear(); m_style = (style == Style::native) ? GetNativeStyle() : style; + m_checksum = checksum; if (pathname.empty()) return; @@ -308,9 +311,9 @@ bool FileSpec::Match(const FileSpec &pattern, const FileSpec &file) { std::optional<FileSpec::Style> FileSpec::GuessPathStyle(llvm::StringRef absolute_path) { - if (absolute_path.startswith("/")) + if (absolute_path.starts_with("/")) return Style::posix; - if (absolute_path.startswith(R"(\\)")) + if (absolute_path.starts_with(R"(\\)")) return Style::windows; if (absolute_path.size() >= 3 && llvm::isAlpha(absolute_path[0]) && (absolute_path.substr(1, 2) == R"(:\)" || diff --git a/contrib/llvm-project/lldb/source/Utility/FileSpecList.cpp b/contrib/llvm-project/lldb/source/Utility/FileSpecList.cpp index e5e0ac3e5981..e3d8ea650c75 100644 --- a/contrib/llvm-project/lldb/source/Utility/FileSpecList.cpp +++ b/contrib/llvm-project/lldb/source/Utility/FileSpecList.cpp @@ -117,7 +117,7 @@ size_t FileSpecList::FindCompatibleIndex(size_t start_idx, auto is_suffix = [](llvm::StringRef a, llvm::StringRef b, bool case_sensitive) -> bool { if (case_sensitive ? a.consume_back(b) : a.consume_back_insensitive(b)) - return a.empty() || a.endswith("/"); + return a.empty() || a.ends_with("/"); return false; }; const bool case_sensitive = @@ -140,12 +140,6 @@ const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const { return g_empty_file_spec; } -const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const { - if (idx < m_files.size()) - return &m_files[idx]; - return nullptr; -} - // Return the size in bytes that this object takes in memory. This returns the // size in bytes of this object's member variables and any FileSpec objects its // member variables contain, the result doesn't not include the string values @@ -162,9 +156,3 @@ size_t FileSpecList::MemorySize() const { // Return the number of files in the file spec list. size_t FileSpecList::GetSize() const { return m_files.size(); } - -size_t FileSpecList::GetFilesMatchingPartialPath(const char *path, - bool dir_okay, - FileSpecList &matches) { - return 0; -} diff --git a/contrib/llvm-project/lldb/source/Utility/Listener.cpp b/contrib/llvm-project/lldb/source/Utility/Listener.cpp index 48ea5fca899e..6a74c530ad25 100644 --- a/contrib/llvm-project/lldb/source/Utility/Listener.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Listener.cpp @@ -231,8 +231,7 @@ bool Listener::FindNextEventInternal( // to return it so it should be okay to get the next event off the queue // here - and it might be useful to do that in the "DoOnRemoval". lock.unlock(); - if (!m_is_shadow) - event_sp->DoOnRemoval(); + event_sp->DoOnRemoval(); } return true; } diff --git a/contrib/llvm-project/lldb/source/Utility/Log.cpp b/contrib/llvm-project/lldb/source/Utility/Log.cpp index 75912683e233..3a45a0285d3e 100644 --- a/contrib/llvm-project/lldb/source/Utility/Log.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Log.cpp @@ -210,7 +210,7 @@ void Log::Warning(const char *format, ...) { void Log::Register(llvm::StringRef name, Channel &channel) { auto iter = g_channel_map->try_emplace(name, channel); assert(iter.second == true); - (void)iter; + UNUSED_IF_ASSERT_DISABLED(iter); } void Log::Unregister(llvm::StringRef name) { diff --git a/contrib/llvm-project/lldb/source/Utility/NameMatches.cpp b/contrib/llvm-project/lldb/source/Utility/NameMatches.cpp index 1c8cd6a0ca31..f002b86f163b 100644 --- a/contrib/llvm-project/lldb/source/Utility/NameMatches.cpp +++ b/contrib/llvm-project/lldb/source/Utility/NameMatches.cpp @@ -22,9 +22,9 @@ bool lldb_private::NameMatches(llvm::StringRef name, NameMatch match_type, case NameMatch::Contains: return name.contains(match); case NameMatch::StartsWith: - return name.startswith(match); + return name.starts_with(match); case NameMatch::EndsWith: - return name.endswith(match); + return name.ends_with(match); case NameMatch::RegularExpression: { RegularExpression regex(match); return regex.Execute(name); diff --git a/contrib/llvm-project/lldb/source/Utility/Scalar.cpp b/contrib/llvm-project/lldb/source/Utility/Scalar.cpp index 791c0fb74352..5ad68065bce1 100644 --- a/contrib/llvm-project/lldb/source/Utility/Scalar.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Scalar.cpp @@ -153,20 +153,20 @@ bool Scalar::IsZero() const { return false; } -void Scalar::GetValue(Stream *s, bool show_type) const { +void Scalar::GetValue(Stream &s, bool show_type) const { if (show_type) - s->Printf("(%s) ", GetTypeAsCString()); + s.Printf("(%s) ", GetTypeAsCString()); switch (m_type) { case e_void: break; case e_int: - s->PutCString(llvm::toString(m_integer, 10)); + s.PutCString(llvm::toString(m_integer, 10)); break; case e_float: llvm::SmallString<24> string; m_float.toString(string); - s->PutCString(string); + s.PutCString(string); break; } } @@ -894,6 +894,6 @@ bool Scalar::SetBit(uint32_t bit) { llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, const Scalar &scalar) { StreamString s; - scalar.GetValue(&s, /*show_type*/ true); + scalar.GetValue(s, /*show_type*/ true); return os << s.GetString(); } diff --git a/contrib/llvm-project/lldb/source/Utility/Status.cpp b/contrib/llvm-project/lldb/source/Utility/Status.cpp index 4498961d83e7..3bd00bb20da2 100644 --- a/contrib/llvm-project/lldb/source/Utility/Status.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Status.cpp @@ -180,14 +180,6 @@ ErrorType Status::GetType() const { return m_type; } // otherwise non-success result. bool Status::Fail() const { return m_code != 0; } -// Set accessor for the error value to "err" and the type to -// "eErrorTypeMachKernel" -void Status::SetMachError(uint32_t err) { - m_code = err; - m_type = eErrorTypeMachKernel; - m_string.clear(); -} - void Status::SetExpressionError(lldb::ExpressionResults result, const char *mssg) { m_code = result; diff --git a/contrib/llvm-project/lldb/source/Utility/Stream.cpp b/contrib/llvm-project/lldb/source/Utility/Stream.cpp index af28a49a1f0c..62e061e9d09c 100644 --- a/contrib/llvm-project/lldb/source/Utility/Stream.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Stream.cpp @@ -8,11 +8,13 @@ #include "lldb/Utility/Stream.h" +#include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/VASPrintf.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Format.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/Regex.h" #include <string> @@ -70,6 +72,34 @@ size_t Stream::PutCString(llvm::StringRef str) { return bytes_written; } +void Stream::PutCStringColorHighlighted(llvm::StringRef text, + llvm::StringRef pattern, + llvm::StringRef prefix, + llvm::StringRef suffix) { + // Only apply color formatting when a pattern is present and both prefix and + // suffix are specified. In the absence of these conditions, output the text + // without color formatting. + if (pattern.empty() || (prefix.empty() && suffix.empty())) { + PutCString(text); + return; + } + + llvm::Regex reg_pattern(pattern); + llvm::SmallVector<llvm::StringRef, 1> matches; + llvm::StringRef remaining = text; + std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes( + prefix.str() + "%.*s" + suffix.str()); + while (reg_pattern.match(remaining, &matches)) { + llvm::StringRef match = matches[0]; + size_t match_start_pos = match.data() - remaining.data(); + PutCString(remaining.take_front(match_start_pos)); + Printf(format_str.c_str(), match.size(), match.data()); + remaining = remaining.drop_front(match_start_pos + match.size()); + } + if (remaining.size()) + PutCString(remaining); +} + // Print a double quoted NULL terminated C string to the stream using the // printf format in "format". void Stream::QuotedCString(const char *cstr, const char *format) { diff --git a/contrib/llvm-project/lldb/source/Utility/StringExtractor.cpp b/contrib/llvm-project/lldb/source/Utility/StringExtractor.cpp index c7e4ac794284..579faa3da42f 100644 --- a/contrib/llvm-project/lldb/source/Utility/StringExtractor.cpp +++ b/contrib/llvm-project/lldb/source/Utility/StringExtractor.cpp @@ -254,7 +254,7 @@ uint64_t StringExtractor::GetHexMaxU64(bool little_endian, bool StringExtractor::ConsumeFront(const llvm::StringRef &str) { llvm::StringRef S = GetStringRef(); - if (!S.startswith(str)) + if (!S.starts_with(str)) return false; else m_index += str.size(); diff --git a/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp b/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp index c0ed1e5a5c73..7686d052c599 100644 --- a/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp +++ b/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp @@ -162,8 +162,18 @@ void StructuredData::String::Serialize(json::OStream &s) const { void StructuredData::Dictionary::Serialize(json::OStream &s) const { s.objectBegin(); - for (const auto &pair : m_dict) { - s.attributeBegin(pair.first.GetStringRef()); + + // To ensure the output format is always stable, we sort the dictionary by key + // first. + using Entry = std::pair<llvm::StringRef, ObjectSP>; + std::vector<Entry> sorted_entries; + for (const auto &pair : m_dict) + sorted_entries.push_back({pair.first(), pair.second}); + + llvm::sort(sorted_entries); + + for (const auto &pair : sorted_entries) { + s.attributeBegin(pair.first); pair.second->Serialize(s); s.attributeEnd(); } @@ -228,9 +238,20 @@ void StructuredData::Array::GetDescription(lldb_private::Stream &s) const { void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const { size_t indentation_level = s.GetIndentLevel(); - for (const auto &pair : m_dict) { + + // To ensure the output format is always stable, we sort the dictionary by key + // first. + using Entry = std::pair<llvm::StringRef, ObjectSP>; + std::vector<Entry> sorted_entries; + for (const auto &pair : m_dict) + sorted_entries.push_back({pair.first(), pair.second}); + + llvm::sort(sorted_entries); + + for (auto iter = sorted_entries.begin(); iter != sorted_entries.end(); + iter++) { // Sanitize. - if (pair.first.IsNull() || pair.first.IsEmpty() || !pair.second) + if (iter->first.empty() || !iter->second) continue; // Reset original indentation level. @@ -238,11 +259,11 @@ void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const { s.Indent(); // Print key. - s.Printf("%s:", pair.first.AsCString()); + s.Format("{0}:", iter->first); // Return to new line and increase indentation if value is record type. // Otherwise add spacing. - bool should_indent = IsRecordType(pair.second); + bool should_indent = IsRecordType(iter->second); if (should_indent) { s.EOL(); s.IndentMore(); @@ -251,8 +272,8 @@ void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const { } // Print value and new line if now last pair. - pair.second->GetDescription(s); - if (pair != *(--m_dict.end())) + iter->second->GetDescription(s); + if (std::next(iter) != sorted_entries.end()) s.EOL(); // Reset indentation level if it was incremented previously. diff --git a/contrib/llvm-project/lldb/source/Utility/TildeExpressionResolver.cpp b/contrib/llvm-project/lldb/source/Utility/TildeExpressionResolver.cpp index 6311ae062f1f..2e334b2aae54 100644 --- a/contrib/llvm-project/lldb/source/Utility/TildeExpressionResolver.cpp +++ b/contrib/llvm-project/lldb/source/Utility/TildeExpressionResolver.cpp @@ -60,7 +60,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, while ((user_entry = getpwent()) != nullptr) { StringRef ThisName(user_entry->pw_name); - if (!ThisName.startswith(Expr)) + if (!ThisName.starts_with(Expr)) continue; Buffer.resize(1); @@ -75,7 +75,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, bool TildeExpressionResolver::ResolveFullPath( StringRef Expr, llvm::SmallVectorImpl<char> &Output) { - if (!Expr.startswith("~")) { + if (!Expr.starts_with("~")) { Output.assign(Expr.begin(), Expr.end()); return false; } diff --git a/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h b/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h deleted file mode 100644 index 40ebc1de24e4..000000000000 --- a/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h +++ /dev/null @@ -1,25 +0,0 @@ -//===-- UuidCompatibility.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 -// -//===----------------------------------------------------------------------===// - -// Include this header if your system does not have a definition of uuid_t - -#ifndef utility_UUID_COMPATIBILITY_H -#define utility_UUID_COMPATIBILITY_H - -// uuid_t is guaranteed to always be a 16-byte array -typedef unsigned char uuid_t[16]; - -// Return 1 if uuid is null, that is, all zeroes. -inline __attribute__((always_inline)) int uuid_is_null(uuid_t uuid) { - for (int i = 0; i < 16; i++) - if (uuid[i]) - return 0; - return 1; -} - -#endif // utility_UUID_COMPATIBILITY_H diff --git a/contrib/llvm-project/lldb/source/Utility/XcodeSDK.cpp b/contrib/llvm-project/lldb/source/Utility/XcodeSDK.cpp index 84f3ccbd01e2..d744336373b2 100644 --- a/contrib/llvm-project/lldb/source/Utility/XcodeSDK.cpp +++ b/contrib/llvm-project/lldb/source/Utility/XcodeSDK.cpp @@ -56,7 +56,7 @@ XcodeSDK::XcodeSDK(XcodeSDK::Info info) : m_name(GetName(info.type).str()) { XcodeSDK &XcodeSDK::operator=(const XcodeSDK &other) = default; -bool XcodeSDK::operator==(const XcodeSDK &other) { +bool XcodeSDK::operator==(const XcodeSDK &other) const { return m_name == other.m_name; } @@ -152,7 +152,7 @@ void XcodeSDK::Merge(const XcodeSDK &other) { *this = other; else { // The Internal flag always wins. - if (llvm::StringRef(m_name).endswith(".sdk")) + if (llvm::StringRef(m_name).ends_with(".sdk")) if (!l.internal && r.internal) m_name = m_name.substr(0, m_name.size() - 3) + std::string("Internal.sdk"); @@ -291,7 +291,7 @@ std::string XcodeSDK::FindXcodeContentsDirectoryInPath(llvm::StringRef path) { // .app. If the next component is Contents then we've found the Contents // directory. for (auto it = begin; it != end; ++it) { - if (it->endswith(".app")) { + if (it->ends_with(".app")) { auto next = it; if (++next != end && *next == "Contents") { llvm::SmallString<128> buffer; |