diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:09:23 +0000 |
commit | f73363f1dd94996356cefbf24388f561891acf0b (patch) | |
tree | e3c31248bdb36eaec5fd833490d4278162dba2a0 /source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | |
parent | 160ee69dd7ae18978f4068116777639ea98dc951 (diff) |
Notes
Diffstat (limited to 'source/Plugins/Process/FreeBSD/ProcessMonitor.cpp')
-rw-r--r-- | source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | 138 |
1 files changed, 68 insertions, 70 deletions
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index bd06fa25f0a0..51fdf2e5ef33 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -38,15 +38,11 @@ #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" -extern "C" { -extern char **environ; -} - using namespace lldb; using namespace lldb_private; -// We disable the tracing of ptrace calls for integration builds to -// avoid the additional indirection and checks. +// We disable the tracing of ptrace calls for integration builds to avoid the +// additional indirection and checks. #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION // Wrapper for ptrace to catch errors and log calls. @@ -65,9 +61,8 @@ const char *Get_PT_IO_OP(int op) { } } -// Wrapper for ptrace to catch errors and log calls. -// Note that ptrace sets errno on error because -1 is reserved as a valid -// result. +// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets +// errno on error because -1 is reserved as a valid result. extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, const char *reqName, const char *file, int line) { long int result; @@ -134,8 +129,8 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, return result; } -// Wrapper for ptrace when logging is not required. -// Sets errno to 0 prior to calling ptrace. +// Wrapper for ptrace when logging is not required. Sets errno to 0 prior to +// calling ptrace. extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) { long result = 0; errno = 0; @@ -163,8 +158,10 @@ static size_t DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, pi_desc.piod_addr = buf; pi_desc.piod_len = size; - if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) { error.SetErrorToErrno(); + return 0; + } return pi_desc.piod_len; } @@ -177,8 +174,10 @@ static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, pi_desc.piod_addr = (void *)buf; pi_desc.piod_len = size; - if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) { error.SetErrorToErrno(); + return 0; + } return pi_desc.piod_len; } @@ -202,15 +201,16 @@ static bool EnsureFDFlags(int fd, int flags, Status &error) { //------------------------------------------------------------------------------ /// @class Operation -/// @brief Represents a ProcessMonitor operation. +/// Represents a ProcessMonitor operation. /// -/// Under FreeBSD, it is not possible to ptrace() from any other thread but the -/// one that spawned or attached to the process from the start. Therefore, when -/// a ProcessMonitor is asked to deliver or change the state of an inferior -/// process the operation must be "funneled" to a specific thread to perform the -/// task. The Operation class provides an abstract base for all services the -/// ProcessMonitor must perform via the single virtual function Execute, thus -/// encapsulating the code that needs to run in the privileged context. +/// Under FreeBSD, it is not possible to ptrace() from any other thread but +/// the one that spawned or attached to the process from the start. +/// Therefore, when a ProcessMonitor is asked to deliver or change the state +/// of an inferior process the operation must be "funneled" to a specific +/// thread to perform the task. The Operation class provides an abstract base +/// for all services the ProcessMonitor must perform via the single virtual +/// function Execute, thus encapsulating the code that needs to run in the +/// privileged context. class Operation { public: virtual ~Operation() {} @@ -219,7 +219,7 @@ public: //------------------------------------------------------------------------------ /// @class ReadOperation -/// @brief Implements ProcessMonitor::ReadMemory. +/// Implements ProcessMonitor::ReadMemory. class ReadOperation : public Operation { public: ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &error, @@ -245,7 +245,7 @@ void ReadOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class WriteOperation -/// @brief Implements ProcessMonitor::WriteMemory. +/// Implements ProcessMonitor::WriteMemory. class WriteOperation : public Operation { public: WriteOperation(lldb::addr_t addr, const void *buff, size_t size, @@ -271,7 +271,7 @@ void WriteOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class ReadRegOperation -/// @brief Implements ProcessMonitor::ReadRegisterValue. +/// Implements ProcessMonitor::ReadRegisterValue. class ReadRegOperation : public Operation { public: ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, @@ -311,7 +311,7 @@ void ReadRegOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class WriteRegOperation -/// @brief Implements ProcessMonitor::WriteRegisterValue. +/// Implements ProcessMonitor::WriteRegisterValue. class WriteRegOperation : public Operation { public: WriteRegOperation(lldb::tid_t tid, unsigned offset, @@ -344,7 +344,7 @@ void WriteRegOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class ReadDebugRegOperation -/// @brief Implements ProcessMonitor::ReadDebugRegisterValue. +/// Implements ProcessMonitor::ReadDebugRegisterValue. class ReadDebugRegOperation : public Operation { public: ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, @@ -379,7 +379,7 @@ void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class WriteDebugRegOperation -/// @brief Implements ProcessMonitor::WriteDebugRegisterValue. +/// Implements ProcessMonitor::WriteDebugRegisterValue. class WriteDebugRegOperation : public Operation { public: WriteDebugRegOperation(lldb::tid_t tid, unsigned offset, @@ -412,7 +412,7 @@ void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class ReadGPROperation -/// @brief Implements ProcessMonitor::ReadGPR. +/// Implements ProcessMonitor::ReadGPR. class ReadGPROperation : public Operation { public: ReadGPROperation(lldb::tid_t tid, void *buf, bool &result) @@ -439,7 +439,7 @@ void ReadGPROperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class ReadFPROperation -/// @brief Implements ProcessMonitor::ReadFPR. +/// Implements ProcessMonitor::ReadFPR. class ReadFPROperation : public Operation { public: ReadFPROperation(lldb::tid_t tid, void *buf, bool &result) @@ -462,7 +462,7 @@ void ReadFPROperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class WriteGPROperation -/// @brief Implements ProcessMonitor::WriteGPR. +/// Implements ProcessMonitor::WriteGPR. class WriteGPROperation : public Operation { public: WriteGPROperation(lldb::tid_t tid, void *buf, bool &result) @@ -485,7 +485,7 @@ void WriteGPROperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class WriteFPROperation -/// @brief Implements ProcessMonitor::WriteFPR. +/// Implements ProcessMonitor::WriteFPR. class WriteFPROperation : public Operation { public: WriteFPROperation(lldb::tid_t tid, void *buf, bool &result) @@ -508,7 +508,7 @@ void WriteFPROperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class ResumeOperation -/// @brief Implements ProcessMonitor::Resume. +/// Implements ProcessMonitor::Resume. class ResumeOperation : public Operation { public: ResumeOperation(uint32_t signo, bool &result) @@ -539,7 +539,7 @@ void ResumeOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class SingleStepOperation -/// @brief Implements ProcessMonitor::SingleStep. +/// Implements ProcessMonitor::SingleStep. class SingleStepOperation : public Operation { public: SingleStepOperation(uint32_t signo, bool &result) @@ -567,7 +567,7 @@ void SingleStepOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class LwpInfoOperation -/// @brief Implements ProcessMonitor::GetLwpInfo. +/// Implements ProcessMonitor::GetLwpInfo. class LwpInfoOperation : public Operation { public: LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err) @@ -596,7 +596,7 @@ void LwpInfoOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class ThreadSuspendOperation -/// @brief Implements ProcessMonitor::ThreadSuspend. +/// Implements ProcessMonitor::ThreadSuspend. class ThreadSuspendOperation : public Operation { public: ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result) @@ -616,7 +616,7 @@ void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class EventMessageOperation -/// @brief Implements ProcessMonitor::GetEventMessage. +/// Implements ProcessMonitor::GetEventMessage. class EventMessageOperation : public Operation { public: EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) @@ -646,7 +646,7 @@ void EventMessageOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class KillOperation -/// @brief Implements ProcessMonitor::Kill. +/// Implements ProcessMonitor::Kill. class KillOperation : public Operation { public: KillOperation(bool &result) : m_result(result) {} @@ -668,7 +668,7 @@ void KillOperation::Execute(ProcessMonitor *monitor) { //------------------------------------------------------------------------------ /// @class DetachOperation -/// @brief Implements ProcessMonitor::Detach. +/// Implements ProcessMonitor::Detach. class DetachOperation : public Operation { public: DetachOperation(Status &result) : m_error(result) {} @@ -695,13 +695,14 @@ ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); } ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module, - char const **argv, char const **envp, + char const **argv, Environment env, const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, const FileSpec &working_dir) - : OperationArgs(monitor), m_module(module), m_argv(argv), m_envp(envp), - m_stdin_file_spec(stdin_file_spec), m_stdout_file_spec(stdout_file_spec), + : OperationArgs(monitor), m_module(module), m_argv(argv), + m_env(std::move(env)), m_stdin_file_spec(stdin_file_spec), + m_stdout_file_spec(stdout_file_spec), m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {} ProcessMonitor::LaunchArgs::~LaunchArgs() {} @@ -714,11 +715,10 @@ ProcessMonitor::AttachArgs::~AttachArgs() {} //------------------------------------------------------------------------------ /// The basic design of the ProcessMonitor is built around two threads. /// -/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking -/// for changes in the debugee state. When a change is detected a +/// One thread (@see SignalThread) simply blocks on a call to waitpid() +/// looking for changes in the debugee state. When a change is detected a /// ProcessMessage is sent to the associated ProcessFreeBSD instance. This -/// thread -/// "drives" state changes in the debugger. +/// thread "drives" state changes in the debugger. /// /// The second thread (@see OperationThread) is responsible for two things 1) /// launching or attaching to the inferior process, and then 2) servicing @@ -726,7 +726,7 @@ ProcessMonitor::AttachArgs::~AttachArgs() {} /// on the Operation class for more info as to why this is needed. ProcessMonitor::ProcessMonitor( ProcessFreeBSD *process, Module *module, const char *argv[], - const char *envp[], const FileSpec &stdin_file_spec, + Environment env, const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, const FileSpec &working_dir, const lldb_private::ProcessLaunchInfo & /* launch_info */, @@ -736,7 +736,7 @@ ProcessMonitor::ProcessMonitor( using namespace std::placeholders; std::unique_ptr<LaunchArgs> args( - new LaunchArgs(this, module, argv, envp, stdin_file_spec, + new LaunchArgs(this, module, argv, std::move(env), stdin_file_spec, stdout_file_spec, stderr_file_spec, working_dir)); sem_init(&m_operation_pending, 0, 0); @@ -837,7 +837,6 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { ProcessMonitor *monitor = args->m_monitor; ProcessFreeBSD &process = monitor->GetProcess(); const char **argv = args->m_argv; - const char **envp = args->m_envp; const FileSpec &stdin_file_spec = args->m_stdin_file_spec; const FileSpec &stdout_file_spec = args->m_stdout_file_spec; const FileSpec &stderr_file_spec = args->m_stderr_file_spec; @@ -849,8 +848,8 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { ::pid_t pid; // Propagate the environment if one is not supplied. - if (envp == NULL || envp[0] == NULL) - envp = const_cast<const char **>(environ); + Environment::Envp envp = + (args->m_env.empty() ? Host::GetEnvironment() : args->m_env).getEnvp(); if ((pid = terminal.Fork(err_str, err_len)) == -1) { args->m_error.SetErrorToGenericError(); @@ -875,9 +874,9 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) exit(ePtraceFailed); - // terminal has already dupped the tty descriptors to stdin/out/err. - // This closes original fd from which they were copied (and avoids - // leaking descriptors to the debugged process. + // terminal has already dupped the tty descriptors to stdin/out/err. This + // closes original fd from which they were copied (and avoids leaking + // descriptors to the debugged process. terminal.CloseSlaveFileDescriptor(); // Do not inherit setgid powers. @@ -908,8 +907,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { exit(eChdirFailed); // Execute. We should never return. - execve(argv[0], const_cast<char *const *>(argv), - const_cast<char *const *>(envp)); + execve(argv[0], const_cast<char *const *>(argv), envp); exit(eExecFailed); } @@ -1103,9 +1101,9 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, break; case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): { - // The inferior process is about to exit. Maintain the process in a - // state of "limbo" until we are explicitly commanded to detach, - // destroy, resume, etc. + // The inferior process is about to exit. Maintain the process in a state + // of "limbo" until we are explicitly commanded to detach, destroy, resume, + // etc. unsigned long data = 0; if (!monitor->GetEventMessage(tid, &data)) data = -1; @@ -1160,8 +1158,8 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // POSIX says that process behaviour is undefined after it ignores a SIGFPE, - // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a - // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2) + // or raise(3). Similarly for tgkill(2) on FreeBSD. // // IOW, user generated signals never generate what we consider to be a // "crash". @@ -1197,8 +1195,8 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, } // else; Use atleast si_signo info for other si_code } - // Everything else is "normal" and does not require any special action on - // our part. + // Everything else is "normal" and does not require any special action on our + // part. return ProcessMessage::Signal(tid, signo); } @@ -1424,14 +1422,14 @@ void ProcessMonitor::StopMonitor() { } // FIXME: On Linux, when a new thread is created, we receive to notifications, -// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the -// child thread id as additional information, and (2) a SIGSTOP|SI_USER from -// the new child thread indicating that it has is stopped because we attached. -// We have no guarantee of the order in which these arrive, but we need both -// before we are ready to proceed. We currently keep a list of threads which -// have sent the initial SIGSTOP|SI_USER event. Then when we receive the -// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred -// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it. +// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the child +// thread id as additional information, and (2) a SIGSTOP|SI_USER from the new +// child thread indicating that it has is stopped because we attached. We have +// no guarantee of the order in which these arrive, but we need both before we +// are ready to proceed. We currently keep a list of threads which have sent +// the initial SIGSTOP|SI_USER event. Then when we receive the +// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not +// occurred we call ProcessMonitor::WaitForInitialTIDStop() to wait for it. // // Right now, the above logic is in ProcessPOSIX, so we need a definition of // this function in the FreeBSD ProcessMonitor implementation even if it isn't |