diff options
author | Jim Ingham <jingham@apple.com> | 2022-05-11 15:10:16 -0700 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2022-05-18 10:16:11 -0700 |
commit | bff4673b41781ec5bff6b96b52cf321d2271726c (patch) | |
tree | 4a259e5663ec63d18d551c8eaad64b2848702c33 /lldb/source | |
parent | ececce1b5ec1a83434568591e4c18ac79e4f3631 (diff) | |
download | llvm-bff4673b41781ec5bff6b96b52cf321d2271726c.zip llvm-bff4673b41781ec5bff6b96b52cf321d2271726c.tar.gz llvm-bff4673b41781ec5bff6b96b52cf321d2271726c.tar.bz2 |
Add a darwin platform setting to specify which exceptions debugserver
should not receive as exceptions (some will get converted to BSD
signals instead). This is really the only stable way to ensure that
a Mach exception gets converted to it's equivalent BSD signal. For
programs that rely on BSD signal handlers, this has to happen or you
can't even get the program to invoke the signal handler when under
the debugger.
This builds on a previous solution to this problem which required you
start debugserver with the -U flag. This was not very discoverable
and required lldb be the one to launch debugserver, which is not always
the case.
Differential Revision: https://reviews.llvm.org/D125434
Diffstat (limited to 'lldb/source')
6 files changed, 174 insertions, 5 deletions
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index cac9c67..455b760 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -19,11 +19,15 @@ #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/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/XML.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" @@ -48,12 +52,137 @@ using namespace lldb; using namespace lldb_private; +static Status ExceptionMaskValidator(const char *string, void *unused) { + Status error; + llvm::StringRef str_ref(string); + llvm::SmallVector<llvm::StringRef> candidates; + str_ref.split(candidates, '|'); + for (auto candidate : candidates) { + if (!(candidate == "EXC_BAD_ACCESS" + || candidate == "EXC_BAD_INSTRUCTION" + || candidate == "EXC_ARITHMETIC" + || candidate == "EXC_RESOURCE" + || candidate == "EXC_GUARD")) { + error.SetErrorStringWithFormat("invalid exception type: '%s'", + candidate.str().c_str()); + return error; + } + } + return {}; +} + /// Destructor. /// /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. PlatformDarwin::~PlatformDarwin() = default; +// Static Variables +static uint32_t g_initialize_count = 0; + +void PlatformDarwin::Initialize() { + Platform::Initialize(); + + if (g_initialize_count++ == 0) { + PluginManager::RegisterPlugin(PlatformDarwin::GetPluginNameStatic(), + PlatformDarwin::GetDescriptionStatic(), + PlatformDarwin::CreateInstance, + PlatformDarwin::DebuggerInitialize); + } +} + +void PlatformDarwin::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformDarwin::CreateInstance); + } + } + + Platform::Terminate(); +} + +llvm::StringRef PlatformDarwin::GetDescriptionStatic() { + return "Darwin platform plug-in."; +} + +PlatformSP PlatformDarwin::CreateInstance(bool force, const ArchSpec *arch) { + // We only create subclasses of the PlatformDarwin plugin. + return PlatformSP(); +} + +#define LLDB_PROPERTIES_platformdarwin +#include "PlatformMacOSXProperties.inc" + +#define LLDB_PROPERTIES_platformdarwin +enum { +#include "PlatformMacOSXPropertiesEnum.inc" +}; + +class PlatformDarwinProperties : public Properties { +public: + static ConstString &GetSettingName() { + static ConstString g_setting_name("darwin"); + return g_setting_name; + } + + PlatformDarwinProperties() : Properties() { + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); + m_collection_sp->Initialize(g_platformdarwin_properties); + } + + ~PlatformDarwinProperties() override = default; + + const char *GetIgnoredExceptions() const { + const uint32_t idx = ePropertyIgnoredExceptions; + const OptionValueString *option_value = + m_collection_sp->GetPropertyAtIndexAsOptionValueString( + NULL, false, idx); + assert(option_value); + return option_value->GetCurrentValue(); + } + + OptionValueString *GetIgnoredExceptionValue() { + const uint32_t idx = ePropertyIgnoredExceptions; + OptionValueString *option_value = + m_collection_sp->GetPropertyAtIndexAsOptionValueString( + NULL, false, idx); + assert(option_value); + return option_value; + } +}; + +static PlatformDarwinProperties &GetGlobalProperties() { + static PlatformDarwinProperties g_settings; + return g_settings; +} + +void PlatformDarwin::DebuggerInitialize( + lldb_private::Debugger &debugger) { + if (!PluginManager::GetSettingForPlatformPlugin( + debugger, PlatformDarwinProperties::GetSettingName())) { + const bool is_global_setting = false; + PluginManager::CreateSettingForPlatformPlugin( + debugger, GetGlobalProperties().GetValueProperties(), + ConstString("Properties for the Darwin platform plug-in."), + is_global_setting); + OptionValueString *value = GetGlobalProperties().GetIgnoredExceptionValue(); + value->SetValidator(ExceptionMaskValidator); + } +} + +Args +PlatformDarwin::GetExtraStartupCommands() { + std::string ignored_exceptions + = GetGlobalProperties().GetIgnoredExceptions(); + if (ignored_exceptions.empty()) + return {}; + Args ret_args; + std::string packet = "QSetIgnoredExceptions:"; + packet.append(ignored_exceptions); + ret_args.AppendArgument(packet); + return ret_args; +} + lldb_private::Status PlatformDarwin::PutFile(const lldb_private::FileSpec &source, const lldb_private::FileSpec &destination, uint32_t uid, diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h index b4c791e..334410e 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -48,6 +48,18 @@ public: ~PlatformDarwin() override; + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + + static void DebuggerInitialize(lldb_private::Debugger &debugger); + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "darwin"; } + + static llvm::StringRef GetDescriptionStatic(); + Status PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; @@ -96,6 +108,8 @@ public: FileSpec LocateExecutable(const char *basename) override; Status LaunchProcess(ProcessLaunchInfo &launch_info) override; + + Args GetExtraStartupCommands() override; static std::tuple<llvm::VersionTuple, llvm::StringRef> ParseVersionBuildDir(llvm::StringRef str); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSXProperties.td b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSXProperties.td index 39e9641..f0d305a 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSXProperties.td +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSXProperties.td @@ -5,3 +5,12 @@ let Definition = "platformdarwinkernel" in { DefaultStringValue<"">, Desc<"Directories/KDKs to search for kexts in when starting a kernel debug session.">; } + +let Definition = "platformdarwin" in { + def IgnoredExceptions: Property<"ignored-exceptions", "String">, + DefaultStringValue<"">, + Desc<"List the mach exceptions to ignore, separated by '|' " + "(e.g. 'EXC_BAD_ACCESS|EXC_BAD_INSTRUCTION'). " + "lldb will instead stop on the BSD signal the exception was converted " + "into, if there is one.">; +} diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index f7e2188..a00961d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -954,12 +954,23 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { m_gdb_comm.GetVAttachOrWaitSupported(); m_gdb_comm.EnableErrorStringInPacket(); - size_t num_cmds = GetExtraStartupCommands().GetArgumentCount(); - for (size_t idx = 0; idx < num_cmds; idx++) { - StringExtractorGDBRemote response; - m_gdb_comm.SendPacketAndWaitForResponse( - GetExtraStartupCommands().GetArgumentAtIndex(idx), response); + // First dispatch any commands from the platform: + auto handle_cmds = [&] (const Args &args) -> void { + for (const Args::ArgEntry &entry : args) { + StringExtractorGDBRemote response; + m_gdb_comm.SendPacketAndWaitForResponse( + entry.c_str(), response); + } + }; + + PlatformSP platform_sp = GetTarget().GetPlatform(); + if (platform_sp) { + handle_cmds(platform_sp->GetExtraStartupCommands()); } + + // Then dispatch any process commands: + handle_cmds(GetExtraStartupCommands()); + return error; } diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 1976aa6..559f766 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1945,6 +1945,10 @@ CompilerType Platform::GetSiginfoType(const llvm::Triple& triple) { return CompilerType(); } +Args Platform::GetExtraStartupCommands() { + return {}; +} + PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) { std::lock_guard<std::recursive_mutex> guard(m_mutex); for (const PlatformSP &platform_sp : m_platforms) { diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index d6bbf71..f1e54b3 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -126,6 +126,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_QSetWorkingDir; if (PACKET_STARTS_WITH("QSetLogging:")) return eServerPacketType_QSetLogging; + if (PACKET_STARTS_WITH("QSetIgnoredExceptions")) + return eServerPacketType_QSetIgnoredExceptions; if (PACKET_STARTS_WITH("QSetMaxPacketSize:")) return eServerPacketType_QSetMaxPacketSize; if (PACKET_STARTS_WITH("QSetMaxPayloadSize:")) |