[debugserver] Add option to propagate SIGSEGV to target process

Adds a command line option that makes debugserver propagate the SIGSEGV
signal to the target process.

Motivation: I'm one of the maintainers of Delve [1] a debugger for Go.
We use debugserver as our backend on macOS and one of the most often
reported bugs is that, on macOS, we don't propagate SIGSEGV back to the
target process [2]. Sometimes some programs will actually cause a
SIGSEGV, by design, and then handle it. Those programs can not be
debugged at all.

Since catching signals isn't very important for a Go debugger I'd much
rather have a command line option in debugserver that causes it to let
SIGSEGV go directly to the target process.

[1] https://github.com/go-delve/delve/
[2] https://github.com/go-delve/delve/issues/852

Differential revision: https://reviews.llvm.org/D89315
This commit is contained in:
Alessandro Arzilli 2020-11-17 09:26:20 -08:00 committed by Jonas Devlieghere
parent 8a4fe75d70
commit 27012c0f75
9 changed files with 102 additions and 64 deletions

View File

@ -319,20 +319,21 @@ static bool spawn_waitpid_thread(pid_t pid) {
} }
nub_process_t DNBProcessLaunch( nub_process_t DNBProcessLaunch(
const char *path, char const *argv[], const char *envp[], RNBContext *ctx, const char *path, char const *argv[], const char *envp[],
const char *working_directory, // NULL => don't change, non-NULL => set const char *working_directory, // NULL => don't change, non-NULL => set
// working directory for inferior to this // working directory for inferior to this
const char *stdin_path, const char *stdout_path, const char *stderr_path, const char *stdin_path, const char *stdout_path, const char *stderr_path,
bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, bool no_stdio, int disable_aslr, const char *event_data, char *err_str,
const char *event_data, char *err_str, size_t err_len) { size_t err_len) {
DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, " DNBLogThreadedIf(LOG_PROCESS,
"%s ( path='%s', argv = %p, envp = %p, "
"working_dir=%s, stdin=%s, stdout=%s, " "working_dir=%s, stdin=%s, stdout=%s, "
"stderr=%s, no-stdio=%i, launch_flavor = %u, " "stderr=%s, no-stdio=%i, launch_flavor = %u, "
"disable_aslr = %d, err = %p, err_len = " "disable_aslr = %d, err = %p, err_len = "
"%llu) called...", "%llu) called...",
__FUNCTION__, path, static_cast<void *>(argv), __FUNCTION__, path, static_cast<void *>(argv),
static_cast<void *>(envp), working_directory, stdin_path, static_cast<void *>(envp), working_directory, stdin_path,
stdout_path, stderr_path, no_stdio, launch_flavor, stdout_path, stderr_path, no_stdio, ctx->LaunchFlavor(),
disable_aslr, static_cast<void *>(err_str), disable_aslr, static_cast<void *>(err_str),
static_cast<uint64_t>(err_len)); static_cast<uint64_t>(err_len));
@ -349,10 +350,10 @@ nub_process_t DNBProcessLaunch(
MachProcessSP processSP(new MachProcess); MachProcessSP processSP(new MachProcess);
if (processSP.get()) { if (processSP.get()) {
DNBError launch_err; DNBError launch_err;
pid_t pid = processSP->LaunchForDebug(path, argv, envp, working_directory, pid_t pid = processSP->LaunchForDebug(
stdin_path, stdout_path, stderr_path, path, argv, envp, working_directory, stdin_path, stdout_path,
no_stdio, launch_flavor, disable_aslr, stderr_path, no_stdio, ctx->LaunchFlavor(), disable_aslr, event_data,
event_data, launch_err); ctx->GetUnmaskSignals(), launch_err);
if (err_str) { if (err_str) {
*err_str = '\0'; *err_str = '\0';
if (launch_err.Fail()) { if (launch_err.Fail()) {
@ -412,7 +413,8 @@ nub_process_t DNBProcessGetPIDByName(const char *name) {
} }
nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout, nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout,
char *err_str, size_t err_len) { bool unmask_signals, char *err_str,
size_t err_len) {
if (err_str && err_len > 0) if (err_str && err_len > 0)
err_str[0] = '\0'; err_str[0] = '\0';
std::vector<struct kinfo_proc> matching_proc_infos; std::vector<struct kinfo_proc> matching_proc_infos;
@ -433,12 +435,12 @@ nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout,
} }
return DNBProcessAttach(matching_proc_infos[0].kp_proc.p_pid, timeout, return DNBProcessAttach(matching_proc_infos[0].kp_proc.p_pid, timeout,
err_str, err_len); unmask_signals, err_str, err_len);
} }
nub_process_t DNBProcessAttach(nub_process_t attach_pid, nub_process_t DNBProcessAttach(nub_process_t attach_pid,
struct timespec *timeout, char *err_str, struct timespec *timeout, bool unmask_signals,
size_t err_len) { char *err_str, size_t err_len) {
if (err_str && err_len > 0) if (err_str && err_len > 0)
err_str[0] = '\0'; err_str[0] = '\0';
@ -480,7 +482,8 @@ nub_process_t DNBProcessAttach(nub_process_t attach_pid,
if (processSP.get()) { if (processSP.get()) {
DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...",
attach_pid); attach_pid);
pid = processSP->AttachForDebug(attach_pid, err_str, err_len); pid =
processSP->AttachForDebug(attach_pid, unmask_signals, err_str, err_len);
if (pid != INVALID_NUB_PROCESS) { if (pid != INVALID_NUB_PROCESS) {
bool res = AddProcessToMap(pid, processSP); bool res = AddProcessToMap(pid, processSP);
@ -667,15 +670,18 @@ GetAllInfosMatchingName(const char *full_process_name,
return matching_proc_infos.size(); return matching_proc_infos.size();
} }
nub_process_t DNBProcessAttachWait( nub_process_t
const char *waitfor_process_name, nub_launch_flavor_t launch_flavor, DNBProcessAttachWait(RNBContext *ctx, const char *waitfor_process_name,
bool ignore_existing, struct timespec *timeout_abstime, bool ignore_existing, struct timespec *timeout_abstime,
useconds_t waitfor_interval, char *err_str, size_t err_len, useconds_t waitfor_interval, char *err_str, size_t err_len,
DNBShouldCancelCallback should_cancel_callback, void *callback_data) { DNBShouldCancelCallback should_cancel_callback,
void *callback_data) {
DNBError prepare_error; DNBError prepare_error;
std::vector<struct kinfo_proc> exclude_proc_infos; std::vector<struct kinfo_proc> exclude_proc_infos;
size_t num_exclude_proc_infos; size_t num_exclude_proc_infos;
nub_launch_flavor_t launch_flavor = ctx->LaunchFlavor();
// If the PrepareForAttach returns a valid token, use MachProcess to check // If the PrepareForAttach returns a valid token, use MachProcess to check
// for the process, otherwise scan the process table. // for the process, otherwise scan the process table.
@ -771,8 +777,8 @@ nub_process_t DNBProcessAttachWait(
if (waitfor_pid != INVALID_NUB_PROCESS) { if (waitfor_pid != INVALID_NUB_PROCESS) {
DNBLogThreadedIf(LOG_PROCESS, "Attaching to %s with pid %i...\n", DNBLogThreadedIf(LOG_PROCESS, "Attaching to %s with pid %i...\n",
waitfor_process_name, waitfor_pid); waitfor_process_name, waitfor_pid);
waitfor_pid = waitfor_pid = DNBProcessAttach(waitfor_pid, timeout_abstime,
DNBProcessAttach(waitfor_pid, timeout_abstime, err_str, err_len); ctx->GetUnmaskSignals(), err_str, err_len);
} }
bool success = waitfor_pid != INVALID_NUB_PROCESS; bool success = waitfor_pid != INVALID_NUB_PROCESS;

View File

@ -18,10 +18,11 @@
#include "MacOSX/DarwinLog/DarwinLogEvent.h" #include "MacOSX/DarwinLog/DarwinLogEvent.h"
#include "MacOSX/Genealogy.h" #include "MacOSX/Genealogy.h"
#include "MacOSX/ThreadInfo.h" #include "MacOSX/ThreadInfo.h"
#include <mach/thread_info.h> #include "RNBContext.h"
#include <string>
#include <Availability.h> #include <Availability.h>
#include <mach/machine.h> #include <mach/machine.h>
#include <mach/thread_info.h>
#include <string>
#define DNB_EXPORT __attribute__((visibility("default"))) #define DNB_EXPORT __attribute__((visibility("default")))
@ -42,22 +43,25 @@ nub_bool_t DNBSetArchitecture(const char *arch);
// Process control // Process control
nub_process_t DNBProcessLaunch( nub_process_t DNBProcessLaunch(
const char *path, char const *argv[], const char *envp[], RNBContext *ctx, const char *path, char const *argv[], const char *envp[],
const char *working_directory, // NULL => don't change, non-NULL => set const char *working_directory, // NULL => don't change, non-NULL => set
// working directory for inferior to this // working directory for inferior to this
const char *stdin_path, const char *stdout_path, const char *stderr_path, const char *stdin_path, const char *stdout_path, const char *stderr_path,
bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, bool no_stdio, int disable_aslr, const char *event_data, char *err_str,
const char *event_data, char *err_str, size_t err_len); size_t err_len);
nub_process_t DNBProcessGetPIDByName(const char *name); nub_process_t DNBProcessGetPIDByName(const char *name);
nub_process_t DNBProcessAttach(nub_process_t pid, struct timespec *timeout, nub_process_t DNBProcessAttach(nub_process_t pid, struct timespec *timeout,
char *err_str, size_t err_len); bool unmask_signals, char *err_str,
size_t err_len);
nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout, nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout,
char *err_str, size_t err_len); bool unmask_signals, char *err_str,
nub_process_t size_t err_len);
DNBProcessAttachWait(const char *wait_name, nub_launch_flavor_t launch_flavor, nub_process_t DNBProcessAttachWait(RNBContext *ctx, const char *wait_name,
bool ignore_existing, struct timespec *timeout, bool ignore_existing,
useconds_t interval, char *err_str, size_t err_len, struct timespec *timeout,
useconds_t interval, char *err_str,
size_t err_len,
DNBShouldCancelCallback should_cancel = NULL, DNBShouldCancelCallback should_cancel = NULL,
void *callback_data = NULL); void *callback_data = NULL);
// Resume a process with exact instructions on what to do with each thread: // Resume a process with exact instructions on what to do with each thread:

View File

@ -78,12 +78,14 @@ public:
}; };
// Child process control // Child process control
pid_t AttachForDebug(pid_t pid, char *err_str, size_t err_len); pid_t AttachForDebug(pid_t pid, bool unmask_signals, char *err_str,
size_t err_len);
pid_t LaunchForDebug(const char *path, char const *argv[], char const *envp[], pid_t LaunchForDebug(const char *path, char const *argv[], char const *envp[],
const char *working_directory, const char *stdin_path, const char *working_directory, const char *stdin_path,
const char *stdout_path, const char *stderr_path, const char *stdout_path, const char *stderr_path,
bool no_stdio, nub_launch_flavor_t launch_flavor, bool no_stdio, nub_launch_flavor_t launch_flavor,
int disable_aslr, const char *event_data, DNBError &err); int disable_aslr, const char *event_data,
bool unmask_signals, DNBError &err);
static uint32_t GetCPUTypeForLocalProcess(pid_t pid); static uint32_t GetCPUTypeForLocalProcess(pid_t pid);
static pid_t ForkChildForPTraceDebugging(const char *path, char const *argv[], static pid_t ForkChildForPTraceDebugging(const char *path, char const *argv[],
@ -107,7 +109,7 @@ public:
pid_t BoardServiceLaunchForDebug(const char *app_bundle_path, pid_t BoardServiceLaunchForDebug(const char *app_bundle_path,
char const *argv[], char const *envp[], char const *argv[], char const *envp[],
bool no_stdio, bool disable_aslr, bool no_stdio, bool disable_aslr,
const char *event_data, const char *event_data, bool unmask_signals,
DNBError &launch_err); DNBError &launch_err);
pid_t BoardServiceForkChildForPTraceDebugging( pid_t BoardServiceForkChildForPTraceDebugging(
const char *path, char const *argv[], char const *envp[], bool no_stdio, const char *path, char const *argv[], char const *envp[], bool no_stdio,
@ -128,7 +130,7 @@ public:
#ifdef WITH_SPRINGBOARD #ifdef WITH_SPRINGBOARD
pid_t SBLaunchForDebug(const char *app_bundle_path, char const *argv[], pid_t SBLaunchForDebug(const char *app_bundle_path, char const *argv[],
char const *envp[], bool no_stdio, bool disable_aslr, char const *envp[], bool no_stdio, bool disable_aslr,
DNBError &launch_err); bool unmask_signals, DNBError &launch_err);
static pid_t SBForkChildForPTraceDebugging(const char *path, static pid_t SBForkChildForPTraceDebugging(const char *path,
char const *argv[], char const *argv[],
char const *envp[], bool no_stdio, char const *envp[], bool no_stdio,

View File

@ -2600,7 +2600,8 @@ void *MachProcess::ProfileThread(void *arg) {
return NULL; return NULL;
} }
pid_t MachProcess::AttachForDebug(pid_t pid, char *err_str, size_t err_len) { pid_t MachProcess::AttachForDebug(pid_t pid, bool unmask_signals, char *err_str,
size_t err_len) {
// Clear out and clean up from any current state // Clear out and clean up from any current state
Clear(); Clear();
if (pid != 0) { if (pid != 0) {
@ -2617,7 +2618,7 @@ pid_t MachProcess::AttachForDebug(pid_t pid, char *err_str, size_t err_len) {
SetState(eStateAttaching); SetState(eStateAttaching);
m_pid = pid; m_pid = pid;
if (!m_task.StartExceptionThread(err)) { if (!m_task.StartExceptionThread(unmask_signals, err)) {
const char *err_cstr = err.AsString(); const char *err_cstr = err.AsString();
::snprintf(err_str, err_len, "%s", ::snprintf(err_str, err_len, "%s",
err_cstr ? err_cstr : "unable to start the exception thread"); err_cstr ? err_cstr : "unable to start the exception thread");
@ -3077,7 +3078,7 @@ pid_t MachProcess::LaunchForDebug(
// working directory for inferior to this // working directory for inferior to this
const char *stdin_path, const char *stdout_path, const char *stderr_path, const char *stdin_path, const char *stdout_path, const char *stderr_path,
bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr,
const char *event_data, DNBError &launch_err) { const char *event_data, bool unmask_signals, DNBError &launch_err) {
// Clear out and clean up from any current state // Clear out and clean up from any current state
Clear(); Clear();
@ -3182,7 +3183,7 @@ pid_t MachProcess::LaunchForDebug(
for (i = 0; (arg = argv[i]) != NULL; i++) for (i = 0; (arg = argv[i]) != NULL; i++)
m_args.push_back(arg); m_args.push_back(arg);
m_task.StartExceptionThread(launch_err); m_task.StartExceptionThread(unmask_signals, launch_err);
if (launch_err.Fail()) { if (launch_err.Fail()) {
if (launch_err.AsString() == NULL) if (launch_err.AsString() == NULL)
launch_err.SetErrorString("unable to start the exception thread"); launch_err.SetErrorString("unable to start the exception thread");
@ -3525,7 +3526,8 @@ static CFStringRef CopyBundleIDForPath(const char *app_bundle_path,
pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[], pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[],
char const *envp[], bool no_stdio, char const *envp[], bool no_stdio,
bool disable_aslr, DNBError &launch_err) { bool disable_aslr, bool unmask_signals,
DNBError &launch_err) {
// Clear out and clean up from any current state // Clear out and clean up from any current state
Clear(); Clear();
@ -3541,7 +3543,7 @@ pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[],
char const *arg; char const *arg;
for (i = 0; (arg = argv[i]) != NULL; i++) for (i = 0; (arg = argv[i]) != NULL; i++)
m_args.push_back(arg); m_args.push_back(arg);
m_task.StartExceptionThread(launch_err); m_task.StartExceptionThread(unmask_signals, launch_err);
if (launch_err.Fail()) { if (launch_err.Fail()) {
if (launch_err.AsString() == NULL) if (launch_err.AsString() == NULL)
@ -3738,7 +3740,8 @@ pid_t MachProcess::SBForkChildForPTraceDebugging(
#if defined(WITH_BKS) || defined(WITH_FBS) #if defined(WITH_BKS) || defined(WITH_FBS)
pid_t MachProcess::BoardServiceLaunchForDebug( pid_t MachProcess::BoardServiceLaunchForDebug(
const char *path, char const *argv[], char const *envp[], bool no_stdio, const char *path, char const *argv[], char const *envp[], bool no_stdio,
bool disable_aslr, const char *event_data, DNBError &launch_err) { bool disable_aslr, const char *event_data, bool unmask_signals,
DNBError &launch_err) {
DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path);
// Fork a child process for debugging // Fork a child process for debugging
@ -3751,7 +3754,7 @@ pid_t MachProcess::BoardServiceLaunchForDebug(
char const *arg; char const *arg;
for (i = 0; (arg = argv[i]) != NULL; i++) for (i = 0; (arg = argv[i]) != NULL; i++)
m_args.push_back(arg); m_args.push_back(arg);
m_task.StartExceptionThread(launch_err); m_task.StartExceptionThread(unmask_signals, launch_err);
if (launch_err.Fail()) { if (launch_err.Fail()) {
if (launch_err.AsString() == NULL) if (launch_err.AsString() == NULL)

View File

@ -67,7 +67,7 @@ public:
kern_return_t RestoreExceptionPortInfo(); kern_return_t RestoreExceptionPortInfo();
kern_return_t ShutDownExcecptionThread(); kern_return_t ShutDownExcecptionThread();
bool StartExceptionThread(DNBError &err); bool StartExceptionThread(bool unmask_signals, DNBError &err);
nub_addr_t GetDYLDAllImageInfosAddress(DNBError &err); nub_addr_t GetDYLDAllImageInfosAddress(DNBError &err);
kern_return_t BasicInfo(struct task_basic_info *info); kern_return_t BasicInfo(struct task_basic_info *info);
static kern_return_t BasicInfo(task_t task, struct task_basic_info *info); static kern_return_t BasicInfo(task_t task, struct task_basic_info *info);

View File

@ -595,7 +595,7 @@ bool MachTask::IsValid(task_t task) {
return false; return false;
} }
bool MachTask::StartExceptionThread(DNBError &err) { bool MachTask::StartExceptionThread(bool unmask_signals, DNBError &err) {
DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__);
task_t task = TaskPortForProcessID(err); task_t task = TaskPortForProcessID(err);
@ -624,6 +624,12 @@ bool MachTask::StartExceptionThread(DNBError &err) {
return false; return false;
} }
if (unmask_signals) {
m_exc_port_info.mask = m_exc_port_info.mask &
~(EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION |
EXC_MASK_ARITHMETIC);
}
// Set the ability to get all exceptions on this port // Set the ability to get all exceptions on this port
err = ::task_set_exception_ports( err = ::task_set_exception_ports(
task, m_exc_port_info.mask, m_exception_port, task, m_exc_port_info.mask, m_exception_port,

View File

@ -124,6 +124,11 @@ public:
void SetDetachOnError(bool detach) { m_detach_on_error = detach; } void SetDetachOnError(bool detach) { m_detach_on_error = detach; }
bool GetDetachOnError() { return m_detach_on_error; } bool GetDetachOnError() { return m_detach_on_error; }
void SetUnmaskSignals(bool unmask_signals) {
m_unmask_signals = unmask_signals;
}
bool GetUnmaskSignals() { return m_unmask_signals; }
protected: protected:
// Classes that inherit from RNBContext can see and modify these // Classes that inherit from RNBContext can see and modify these
nub_process_t m_pid; nub_process_t m_pid;
@ -147,6 +152,7 @@ protected:
void StartProcessStatusThread(); void StartProcessStatusThread();
void StopProcessStatusThread(); void StopProcessStatusThread();
static void *ThreadFunctionProcessStatus(void *arg); static void *ThreadFunctionProcessStatus(void *arg);
bool m_unmask_signals;
private: private:
RNBContext(const RNBContext &rhs) = delete; RNBContext(const RNBContext &rhs) = delete;

View File

@ -3927,8 +3927,8 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
} }
const bool ignore_existing = true; const bool ignore_existing = true;
attach_pid = DNBProcessAttachWait( attach_pid = DNBProcessAttachWait(
attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, &m_ctx, attach_name.c_str(), ignore_existing, NULL, 1000, err_str,
1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); sizeof(err_str), RNBRemoteShouldCancelCallback);
} else if (strstr(p, "vAttachOrWait;") == p) { } else if (strstr(p, "vAttachOrWait;") == p) {
p += strlen("vAttachOrWait;"); p += strlen("vAttachOrWait;");
@ -3939,8 +3939,8 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
} }
const bool ignore_existing = false; const bool ignore_existing = false;
attach_pid = DNBProcessAttachWait( attach_pid = DNBProcessAttachWait(
attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, &m_ctx, attach_name.c_str(), ignore_existing, NULL, 1000, err_str,
1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); sizeof(err_str), RNBRemoteShouldCancelCallback);
} else if (strstr(p, "vAttachName;") == p) { } else if (strstr(p, "vAttachName;") == p) {
p += strlen("vAttachName;"); p += strlen("vAttachName;");
if (!GetProcessNameFrom_vAttach(p, attach_name)) { if (!GetProcessNameFrom_vAttach(p, attach_name)) {
@ -3948,7 +3948,8 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt"); __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
} }
attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str, attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL,
Context().GetUnmaskSignals(), err_str,
sizeof(err_str)); sizeof(err_str));
} else if (strstr(p, "vAttach;") == p) { } else if (strstr(p, "vAttach;") == p) {
@ -3961,7 +3962,7 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
struct timespec attach_timeout_abstime; struct timespec attach_timeout_abstime;
DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
err_str, sizeof(err_str)); false, err_str, sizeof(err_str));
} }
} else { } else {
return HandlePacket_UNIMPLEMENTED(p); return HandlePacket_UNIMPLEMENTED(p);

View File

@ -245,8 +245,8 @@ RNBRunLoopMode RNBRunLoopLaunchInferior(RNBRemote *remote,
: ctx.GetWorkingDirectory()); : ctx.GetWorkingDirectory());
const char *process_event = ctx.GetProcessEvent(); const char *process_event = ctx.GetProcessEvent();
nub_process_t pid = DNBProcessLaunch( nub_process_t pid = DNBProcessLaunch(
resolved_path, &inferior_argv[0], &inferior_envp[0], cwd, stdin_path, &ctx, resolved_path, &inferior_argv[0], &inferior_envp[0], cwd,
stdout_path, stderr_path, no_stdio, launch_flavor, g_disable_aslr, stdin_path, stdout_path, stderr_path, no_stdio, g_disable_aslr,
process_event, launch_err_str, sizeof(launch_err_str)); process_event, launch_err_str, sizeof(launch_err_str));
g_pid = pid; g_pid = pid;
@ -368,7 +368,8 @@ RNBRunLoopMode RNBRunLoopLaunchAttaching(RNBRemote *remote,
DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__,
attach_pid); attach_pid);
char err_str[1024]; char err_str[1024];
pid = DNBProcessAttach(attach_pid, NULL, err_str, sizeof(err_str)); pid = DNBProcessAttach(attach_pid, NULL, ctx.GetUnmaskSignals(), err_str,
sizeof(err_str));
g_pid = pid; g_pid = pid;
if (pid == INVALID_NUB_PROCESS) { if (pid == INVALID_NUB_PROCESS) {
@ -889,6 +890,10 @@ static struct option g_long_options[] = {
'F'}, // When debugserver launches the process, forward debugserver's 'F'}, // When debugserver launches the process, forward debugserver's
// current environment variables to the child process ("./debugserver // current environment variables to the child process ("./debugserver
// -F localhost:1234 -- /bin/ls" // -F localhost:1234 -- /bin/ls"
{"unmask-signals", no_argument, NULL,
'U'}, // debugserver will ignore EXC_MASK_BAD_ACCESS,
// EXC_MASK_BAD_INSTRUCTION and EXC_MASK_ARITHMETIC, which results in
// SIGSEGV, SIGILL and SIGFPE being propagated to the target process.
{NULL, 0, NULL, 0}}; {NULL, 0, NULL, 0}};
int communication_fd = -1; int communication_fd = -1;
@ -1260,6 +1265,10 @@ int main(int argc, char *argv[]) {
forward_env = true; forward_env = true;
break; break;
case 'U':
ctx.SetUnmaskSignals(true);
break;
case '2': case '2':
// File descriptor passed to this process during fork/exec and is already // File descriptor passed to this process during fork/exec and is already
// open and ready for communication. // open and ready for communication.
@ -1514,8 +1523,8 @@ int main(int argc, char *argv[]) {
RNBLogSTDOUT("Waiting to attach to process %s...\n", RNBLogSTDOUT("Waiting to attach to process %s...\n",
waitfor_pid_name.c_str()); waitfor_pid_name.c_str());
nub_process_t pid = DNBProcessAttachWait( nub_process_t pid = DNBProcessAttachWait(
waitfor_pid_name.c_str(), launch_flavor, ignore_existing, &ctx, waitfor_pid_name.c_str(), ignore_existing, timeout_ptr,
timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); waitfor_interval, err_str, sizeof(err_str));
g_pid = pid; g_pid = pid;
if (pid == INVALID_NUB_PROCESS) { if (pid == INVALID_NUB_PROCESS) {
@ -1550,7 +1559,8 @@ int main(int argc, char *argv[]) {
RNBLogSTDOUT("Attaching to process %s...\n", attach_pid_name.c_str()); RNBLogSTDOUT("Attaching to process %s...\n", attach_pid_name.c_str());
nub_process_t pid = DNBProcessAttachByName( nub_process_t pid = DNBProcessAttachByName(
attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); attach_pid_name.c_str(), timeout_ptr, ctx.GetUnmaskSignals(),
err_str, sizeof(err_str));
g_pid = pid; g_pid = pid;
if (pid == INVALID_NUB_PROCESS) { if (pid == INVALID_NUB_PROCESS) {
ctx.LaunchStatus().SetError(-1, DNBError::Generic); ctx.LaunchStatus().SetError(-1, DNBError::Generic);