Index: lldb/tools/debugserver/source/DNB.h =================================================================== --- lldb/tools/debugserver/source/DNB.h +++ lldb/tools/debugserver/source/DNB.h @@ -47,19 +47,20 @@ // working directory for inferior to this const char *stdin_path, const char *stdout_path, const char *stderr_path, bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, - const char *event_data, char *err_str, size_t err_len); + const char *event_data, bool unmask_signals, char *err_str, size_t err_len); nub_process_t DNBProcessGetPIDByName(const char *name); 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, - char *err_str, size_t err_len); -nub_process_t -DNBProcessAttachWait(const char *wait_name, nub_launch_flavor_t launch_flavor, - bool ignore_existing, struct timespec *timeout, - useconds_t interval, char *err_str, size_t err_len, - DNBShouldCancelCallback should_cancel = NULL, - void *callback_data = NULL); + bool unmask_signals, char *err_str, + size_t err_len); +nub_process_t DNBProcessAttachWait( + const char *wait_name, nub_launch_flavor_t launch_flavor, + bool ignore_existing, struct timespec *timeout, useconds_t interval, + bool unmask_signals, char *err_str, size_t err_len, + DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL); // Resume a process with exact instructions on what to do with each thread: // - If no thread actions are supplied (actions is NULL or num_actions is zero), // then all threads are continued. Index: lldb/tools/debugserver/source/DNB.cpp =================================================================== --- lldb/tools/debugserver/source/DNB.cpp +++ lldb/tools/debugserver/source/DNB.cpp @@ -324,7 +324,8 @@ // working directory for inferior to this const char *stdin_path, const char *stdout_path, const char *stderr_path, bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, - const char *event_data, char *err_str, size_t err_len) { + const char *event_data, bool unmask_signals, char *err_str, + size_t err_len) { DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, " "working_dir=%s, stdin=%s, stdout=%s, " "stderr=%s, no-stdio=%i, launch_flavor = %u, " @@ -349,10 +350,10 @@ MachProcessSP processSP(new MachProcess); if (processSP.get()) { DNBError launch_err; - pid_t pid = processSP->LaunchForDebug(path, argv, envp, working_directory, - stdin_path, stdout_path, stderr_path, - no_stdio, launch_flavor, disable_aslr, - event_data, launch_err); + pid_t pid = processSP->LaunchForDebug( + path, argv, envp, working_directory, stdin_path, stdout_path, + stderr_path, no_stdio, launch_flavor, disable_aslr, event_data, + unmask_signals, launch_err); if (err_str) { *err_str = '\0'; if (launch_err.Fail()) { @@ -412,7 +413,8 @@ } 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) err_str[0] = '\0'; std::vector matching_proc_infos; @@ -433,12 +435,12 @@ } 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, - struct timespec *timeout, char *err_str, - size_t err_len) { + struct timespec *timeout, bool unmask_signals, + char *err_str, size_t err_len) { if (err_str && err_len > 0) err_str[0] = '\0'; @@ -480,7 +482,8 @@ if (processSP.get()) { DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", 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) { bool res = AddProcessToMap(pid, processSP); @@ -670,8 +673,9 @@ nub_process_t DNBProcessAttachWait( const char *waitfor_process_name, nub_launch_flavor_t launch_flavor, bool ignore_existing, struct timespec *timeout_abstime, - useconds_t waitfor_interval, char *err_str, size_t err_len, - DNBShouldCancelCallback should_cancel_callback, void *callback_data) { + useconds_t waitfor_interval, bool unmask_signals, char *err_str, + size_t err_len, DNBShouldCancelCallback should_cancel_callback, + void *callback_data) { DNBError prepare_error; std::vector exclude_proc_infos; size_t num_exclude_proc_infos; @@ -771,8 +775,8 @@ if (waitfor_pid != INVALID_NUB_PROCESS) { DNBLogThreadedIf(LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid); - waitfor_pid = - DNBProcessAttach(waitfor_pid, timeout_abstime, err_str, err_len); + waitfor_pid = DNBProcessAttach(waitfor_pid, timeout_abstime, unmask_signals, + err_str, err_len); } bool success = waitfor_pid != INVALID_NUB_PROCESS; Index: lldb/tools/debugserver/source/MacOSX/MachProcess.h =================================================================== --- lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -78,12 +78,14 @@ }; // 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[], const char *working_directory, const char *stdin_path, const char *stdout_path, const char *stderr_path, 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 pid_t ForkChildForPTraceDebugging(const char *path, char const *argv[], @@ -107,7 +109,7 @@ pid_t BoardServiceLaunchForDebug(const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, - const char *event_data, + const char *event_data, bool unmask_signals, DNBError &launch_err); pid_t BoardServiceForkChildForPTraceDebugging( const char *path, char const *argv[], char const *envp[], bool no_stdio, @@ -128,7 +130,7 @@ #ifdef WITH_SPRINGBOARD pid_t SBLaunchForDebug(const char *app_bundle_path, char const *argv[], 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, char const *argv[], char const *envp[], bool no_stdio, Index: lldb/tools/debugserver/source/MacOSX/MachProcess.mm =================================================================== --- lldb/tools/debugserver/source/MacOSX/MachProcess.mm +++ lldb/tools/debugserver/source/MacOSX/MachProcess.mm @@ -2589,7 +2589,8 @@ 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(); if (pid != 0) { @@ -2606,7 +2607,7 @@ SetState(eStateAttaching); m_pid = pid; - if (!m_task.StartExceptionThread(err)) { + if (!m_task.StartExceptionThread(unmask_signals, err)) { const char *err_cstr = err.AsString(); ::snprintf(err_str, err_len, "%s", err_cstr ? err_cstr : "unable to start the exception thread"); @@ -3066,7 +3067,7 @@ // working directory for inferior to this const char *stdin_path, const char *stdout_path, const char *stderr_path, 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(); @@ -3171,7 +3172,7 @@ for (i = 0; (arg = argv[i]) != NULL; i++) m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); + m_task.StartExceptionThread(unmask_signals, launch_err); if (launch_err.Fail()) { if (launch_err.AsString() == NULL) launch_err.SetErrorString("unable to start the exception thread"); @@ -3514,7 +3515,8 @@ pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[], 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(); @@ -3530,7 +3532,7 @@ char const *arg; for (i = 0; (arg = argv[i]) != NULL; i++) m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); + m_task.StartExceptionThread(unmask_signals, launch_err); if (launch_err.Fail()) { if (launch_err.AsString() == NULL) @@ -3727,7 +3729,8 @@ #if defined(WITH_BKS) || defined(WITH_FBS) pid_t MachProcess::BoardServiceLaunchForDebug( 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); // Fork a child process for debugging @@ -3740,7 +3743,7 @@ char const *arg; for (i = 0; (arg = argv[i]) != NULL; i++) m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); + m_task.StartExceptionThread(unmask_signals, launch_err); if (launch_err.Fail()) { if (launch_err.AsString() == NULL) Index: lldb/tools/debugserver/source/MacOSX/MachTask.h =================================================================== --- lldb/tools/debugserver/source/MacOSX/MachTask.h +++ lldb/tools/debugserver/source/MacOSX/MachTask.h @@ -67,7 +67,7 @@ kern_return_t RestoreExceptionPortInfo(); kern_return_t ShutDownExcecptionThread(); - bool StartExceptionThread(DNBError &err); + bool StartExceptionThread(bool unmask_signals, DNBError &err); nub_addr_t GetDYLDAllImageInfosAddress(DNBError &err); kern_return_t BasicInfo(struct task_basic_info *info); static kern_return_t BasicInfo(task_t task, struct task_basic_info *info); Index: lldb/tools/debugserver/source/MacOSX/MachTask.mm =================================================================== --- lldb/tools/debugserver/source/MacOSX/MachTask.mm +++ lldb/tools/debugserver/source/MacOSX/MachTask.mm @@ -595,7 +595,7 @@ return false; } -bool MachTask::StartExceptionThread(DNBError &err) { +bool MachTask::StartExceptionThread(bool unmask_signals, DNBError &err) { DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); task_t task = TaskPortForProcessID(err); @@ -624,6 +624,12 @@ 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 err = ::task_set_exception_ports( task, m_exc_port_info.mask, m_exception_port, Index: lldb/tools/debugserver/source/RNBRemote.cpp =================================================================== --- lldb/tools/debugserver/source/RNBRemote.cpp +++ lldb/tools/debugserver/source/RNBRemote.cpp @@ -3928,7 +3928,7 @@ const bool ignore_existing = true; attach_pid = DNBProcessAttachWait( attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, - 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); + 1000, false, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); } else if (strstr(p, "vAttachOrWait;") == p) { p += strlen("vAttachOrWait;"); @@ -3940,7 +3940,7 @@ const bool ignore_existing = false; attach_pid = DNBProcessAttachWait( attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, - 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); + 1000, false, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); } else if (strstr(p, "vAttachName;") == p) { p += strlen("vAttachName;"); if (!GetProcessNameFrom_vAttach(p, attach_name)) { @@ -3948,8 +3948,8 @@ __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt"); } - attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str, - sizeof(err_str)); + attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, false, + err_str, sizeof(err_str)); } else if (strstr(p, "vAttach;") == p) { p += strlen("vAttach;"); @@ -3961,7 +3961,7 @@ struct timespec attach_timeout_abstime; DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, - err_str, sizeof(err_str)); + false, err_str, sizeof(err_str)); } } else { return HandlePacket_UNIMPLEMENTED(p); Index: lldb/tools/debugserver/source/debugserver.cpp =================================================================== --- lldb/tools/debugserver/source/debugserver.cpp +++ lldb/tools/debugserver/source/debugserver.cpp @@ -195,8 +195,8 @@ RNBRunLoopMode RNBRunLoopLaunchInferior(RNBRemote *remote, const char *stdin_path, const char *stdout_path, - const char *stderr_path, - bool no_stdio) { + const char *stderr_path, bool no_stdio, + bool unmask_signals) { RNBContext &ctx = remote->Context(); // The Process stuff takes a c array, the RNBContext has a vector... @@ -247,7 +247,7 @@ nub_process_t pid = DNBProcessLaunch( resolved_path, &inferior_argv[0], &inferior_envp[0], cwd, stdin_path, stdout_path, stderr_path, no_stdio, launch_flavor, g_disable_aslr, - process_event, launch_err_str, sizeof(launch_err_str)); + process_event, unmask_signals, launch_err_str, sizeof(launch_err_str)); g_pid = pid; @@ -362,13 +362,15 @@ // or crash process state. RNBRunLoopMode RNBRunLoopLaunchAttaching(RNBRemote *remote, nub_process_t attach_pid, - nub_process_t &pid) { + nub_process_t &pid, + bool unmask_signals) { RNBContext &ctx = remote->Context(); DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, attach_pid); char err_str[1024]; - pid = DNBProcessAttach(attach_pid, NULL, err_str, sizeof(err_str)); + pid = DNBProcessAttach(attach_pid, NULL, unmask_signals, err_str, + sizeof(err_str)); g_pid = pid; if (pid == INVALID_NUB_PROCESS) { @@ -889,6 +891,10 @@ 'F'}, // When debugserver launches the process, forward debugserver's // current environment variables to the child process ("./debugserver // -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}}; int communication_fd = -1; @@ -979,6 +985,7 @@ bool reverse_connect = false; // Set to true by an option to indicate we // should reverse connect to the host:port // supplied as the first debugserver argument + bool unmask_signals = false; #if !defined(DNBLOG_ENABLED) compile_options += "(no-logging) "; @@ -1260,6 +1267,10 @@ forward_env = true; break; + case 'U': + unmask_signals = true; + break; + case '2': // File descriptor passed to this process during fork/exec and is already // open and ready for communication. @@ -1513,9 +1524,10 @@ bool ignore_existing = false; RNBLogSTDOUT("Waiting to attach to process %s...\n", waitfor_pid_name.c_str()); - nub_process_t pid = DNBProcessAttachWait( - waitfor_pid_name.c_str(), launch_flavor, ignore_existing, - timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); + nub_process_t pid = + DNBProcessAttachWait(waitfor_pid_name.c_str(), launch_flavor, + ignore_existing, timeout_ptr, waitfor_interval, + unmask_signals, err_str, sizeof(err_str)); g_pid = pid; if (pid == INVALID_NUB_PROCESS) { @@ -1533,7 +1545,8 @@ RNBLogSTDOUT("Attaching to process %i...\n", attach_pid); nub_process_t attached_pid; - mode = RNBRunLoopLaunchAttaching(remote, attach_pid, attached_pid); + mode = RNBRunLoopLaunchAttaching(remote, attach_pid, attached_pid, + unmask_signals); if (mode != eRNBRunLoopModeInferiorExecuting) { const char *error_str = remote->Context().LaunchStatus().AsString(); RNBLogSTDERR("error: failed to attach process %i: %s\n", attach_pid, @@ -1549,8 +1562,9 @@ } RNBLogSTDOUT("Attaching to process %s...\n", attach_pid_name.c_str()); - nub_process_t pid = DNBProcessAttachByName( - attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); + nub_process_t pid = + DNBProcessAttachByName(attach_pid_name.c_str(), timeout_ptr, + unmask_signals, err_str, sizeof(err_str)); g_pid = pid; if (pid == INVALID_NUB_PROCESS) { ctx.LaunchStatus().SetError(-1, DNBError::Generic); @@ -1597,7 +1611,7 @@ case eRNBRunLoopModeInferiorLaunching: { mode = RNBRunLoopLaunchInferior(remote, ctx.GetSTDINPath(), ctx.GetSTDOUTPath(), ctx.GetSTDERRPath(), - no_stdio); + no_stdio, unmask_signals); if (mode == eRNBRunLoopModeInferiorExecuting) { if (port != INT32_MAX) {