aboutsummaryrefslogtreecommitdiff
path: root/lldb/source
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2022-05-11 15:10:16 -0700
committerJim Ingham <jingham@apple.com>2022-05-18 10:16:11 -0700
commitbff4673b41781ec5bff6b96b52cf321d2271726c (patch)
tree4a259e5663ec63d18d551c8eaad64b2848702c33 /lldb/source
parentececce1b5ec1a83434568591e4c18ac79e4f3631 (diff)
downloadllvm-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')
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp129
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h14
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformMacOSXProperties.td9
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp21
-rw-r--r--lldb/source/Target/Platform.cpp4
-rw-r--r--lldb/source/Utility/StringExtractorGDBRemote.cpp2
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:"))