[Lldb-commits] [PATCH] Primitive attach support for linux
Johnny Chen
johnny.chen at apple.com
Tue Jun 14 12:09:15 PDT 2011
Hi Marco,
I'll get to your patch shortly.
Thanks.
Johnny
On Jun 14, 2011, at 8:38 AM, Greg Clayton wrote:
> This patch is in linux files only, so feel free to commit as long as no one else has any objections!
>
> Greg Clayton
>
> On Jun 14, 2011, at 5:48 AM, Marco Minutoli wrote:
>
>> This patch is a starting point for the attach functionality.
>> ---
>> source/Plugins/Process/Linux/ProcessLinux.cpp | 11 ++-
>> source/Plugins/Process/Linux/ProcessMonitor.cpp | 178 +++++++++++++++++++++--
>> source/Plugins/Process/Linux/ProcessMonitor.h | 49 ++++++-
>> 3 files changed, 214 insertions(+), 24 deletions(-)
>>
>> diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
>> index c4ce8ee..e6940fe 100644
>> --- a/source/Plugins/Process/Linux/ProcessLinux.cpp
>> +++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
>> @@ -105,7 +105,16 @@ ProcessLinux::CanDebug(Target &target)
>> Error
>> ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
>> {
>> - return Error(1, eErrorTypeGeneric);
>> + Error error;
>> + assert(m_monitor == NULL);
>> +
>> + m_monitor = new ProcessMonitor(this, pid, error);
>> +
>> + if (!error.Success())
>> + return error;
>> +
>> + SetID(pid);
>> + return error;
>> }
>>
>> Error
>> diff --git a/source/Plugins/Process/Linux/ProcessMonitor.cpp b/source/Plugins/Process/Linux/ProcessMonitor.cpp
>> index ce16159..ebe5959 100644
>> --- a/source/Plugins/Process/Linux/ProcessMonitor.cpp
>> +++ b/source/Plugins/Process/Linux/ProcessMonitor.cpp
>> @@ -524,6 +524,17 @@ KillOperation::Execute(ProcessMonitor *monitor)
>> m_result = true;
>> }
>>
>> +ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
>> + : m_monitor(monitor)
>> +{
>> + sem_init(&m_semaphore, 0, 0);
>> +}
>> +
>> +ProcessMonitor::OperationArgs::~OperationArgs()
>> +{
>> + sem_destroy(&m_semaphore);
>> +}
>> +
>> ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
>> lldb_private::Module *module,
>> char const **argv,
>> @@ -531,21 +542,23 @@ ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
>> const char *stdin_path,
>> const char *stdout_path,
>> const char *stderr_path)
>> - : m_monitor(monitor),
>> + : OperationArgs(monitor),
>> m_module(module),
>> m_argv(argv),
>> m_envp(envp),
>> m_stdin_path(stdin_path),
>> m_stdout_path(stdout_path),
>> - m_stderr_path(stderr_path)
>> -{
>> - sem_init(&m_semaphore, 0, 0);
>> -}
>> + m_stderr_path(stderr_path) { }
>>
>> ProcessMonitor::LaunchArgs::~LaunchArgs()
>> -{
>> - sem_destroy(&m_semaphore);
>> -}
>> +{ }
>> +
>> +ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor,
>> + lldb::pid_t pid)
>> + : OperationArgs(monitor), m_pid(pid) { }
>> +
>> +ProcessMonitor::AttachArgs::~AttachArgs()
>> +{ }
>>
>> //------------------------------------------------------------------------------
>> /// The basic design of the ProcessMonitor is built around two threads.
>> @@ -587,7 +600,7 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
>> error.SetErrorString("Monitor failed to initialize.");
>> }
>>
>> - StartOperationThread(args.get(), error);
>> + StartLaunchOpThread(args.get(), error);
>> if (!error.Success())
>> return;
>>
>> @@ -607,7 +620,7 @@ WAIT_AGAIN:
>> // Check that the launch was a success.
>> if (!args->m_error.Success())
>> {
>> - StopOperationThread();
>> + StopLaunchOpThread();
>> error = args->m_error;
>> return;
>> }
>> @@ -623,6 +636,64 @@ WAIT_AGAIN:
>> }
>> }
>>
>> +ProcessMonitor::ProcessMonitor(ProcessLinux *process,
>> + lldb::pid_t pid,
>> + lldb_private::Error &error)
>> + : m_process(process),
>> + m_operation_thread(LLDB_INVALID_HOST_THREAD),
>> + m_pid(LLDB_INVALID_PROCESS_ID),
>> + m_terminal_fd(-1),
>> + m_monitor_thread(LLDB_INVALID_HOST_THREAD),
>> + m_client_fd(-1),
>> + m_server_fd(-1)
>> +{
>> + std::auto_ptr<AttachArgs> args;
>> +
>> + args.reset(new AttachArgs(this, pid));
>> +
>> + // Server/client descriptors.
>> + if (!EnableIPC())
>> + {
>> + error.SetErrorToGenericError();
>> + error.SetErrorString("Monitor failed to initialize.");
>> + }
>> +
>> + StartAttachOpThread(args.get(), error);
>> + if (!error.Success())
>> + return;
>> +
>> +WAIT_AGAIN:
>> + // Wait for the operation thread to initialize.
>> + if (sem_wait(&args->m_semaphore))
>> + {
>> + if (errno == EINTR)
>> + goto WAIT_AGAIN;
>> + else
>> + {
>> + error.SetErrorToErrno();
>> + return;
>> + }
>> + }
>> +
>> + // Check that the launch was a success.
>> + if (!args->m_error.Success())
>> + {
>> + StopAttachOpThread();
>> + error = args->m_error;
>> + return;
>> + }
>> +
>> + // Finally, start monitoring the child process for change in state.
>> + m_monitor_thread = Host::StartMonitoringChildProcess(
>> + ProcessMonitor::MonitorCallback, this, GetPID(), true);
>> + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
>> + {
>> + error.SetErrorToGenericError();
>> + error.SetErrorString("Process attach failed.");
>> + return;
>> + }
>> +}
>> +
>> ProcessMonitor::~ProcessMonitor()
>> {
>> StopMonitor();
>> @@ -631,7 +702,7 @@ ProcessMonitor::~ProcessMonitor()
>> //------------------------------------------------------------------------------
>> // Thread setup and tear down.
>> void
>> -ProcessMonitor::StartOperationThread(LaunchArgs *args, Error &error)
>> +ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error)
>> {
>> static const char *g_thread_name = "lldb.process.linux.operation";
>>
>> @@ -639,11 +710,11 @@ ProcessMonitor::StartOperationThread(LaunchArgs *args, Error &error)
>> return;
>>
>> m_operation_thread =
>> - Host::ThreadCreate(g_thread_name, OperationThread, args, &error);
>> + Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);
>> }
>>
>> void
>> -ProcessMonitor::StopOperationThread()
>> +ProcessMonitor::StopLaunchOpThread()
>> {
>> lldb::thread_result_t result;
>>
>> @@ -655,7 +726,7 @@ ProcessMonitor::StopOperationThread()
>> }
>>
>> void *
>> -ProcessMonitor::OperationThread(void *arg)
>> +ProcessMonitor::LaunchOpThread(void *arg)
>> {
>> LaunchArgs *args = static_cast<LaunchArgs*>(arg);
>>
>> @@ -833,6 +904,80 @@ ProcessMonitor::EnableIPC()
>> return true;
>> }
>>
>> +void
>> +ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)
>> +{
>> + static const char *g_thread_name = "lldb.process.linux.operation";
>> +
>> + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
>> + return;
>> +
>> + m_operation_thread =
>> + Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);
>> +}
>> +
>> +void
>> +ProcessMonitor::StopAttachOpThread()
>> +{
>> + assert(!"Not implemented yet!!!");
>> +}
>> +
>> +void *
>> +ProcessMonitor::AttachOpThread(void *arg)
>> +{
>> + AttachArgs *args = static_cast<AttachArgs*>(arg);
>> +
>> + if (!Attach(args))
>> + return NULL;
>> +
>> + ServeOperation(args);
>> + return NULL;
>> +}
>> +
>> +bool
>> +ProcessMonitor::Attach(AttachArgs *args)
>> +{
>> + lldb::pid_t pid = args->m_pid;
>> +
>> + ProcessMonitor *monitor = args->m_monitor;
>> + ProcessLinux &process = monitor->GetProcess();
>> +
>> + lldb::ThreadSP inferior;
>> +
>> + if (pid <= 1)
>> + {
>> + args->m_error.SetErrorToGenericError();
>> + args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
>> + goto FINISH;
>> + }
>> +
>> + // Attach to the requested process.
>> + if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0)
>> + {
>> + args->m_error.SetErrorToErrno();
>> + goto FINISH;
>> + }
>> +
>> + int status;
>> + if ((status = waitpid(pid, NULL, 0)) < 0)
>> + {
>> + args->m_error.SetErrorToErrno();
>> + goto FINISH;
>> + }
>> +
>> + // Update the process thread list with the attached thread and
>> + // mark it as current.
>> + inferior.reset(new LinuxThread(process, pid));
>> + process.GetThreadList().AddThread(inferior);
>> + process.GetThreadList().SetSelectedThreadByID(pid);
>> +
>> + // Let our process instance know the thread has stopped.
>> + process.SendMessage(ProcessMessage::Trace(pid));
>> +
>> + FINISH:
>> + return args->m_error.Success();
>> +}
>> +
>> bool
>> ProcessMonitor::MonitorCallback(void *callback_baton,
>> lldb::pid_t pid,
>> @@ -1094,10 +1239,11 @@ ProcessMonitor::GetCrashReasonForSIGBUS(const struct siginfo *info)
>> }
>>
>> void
>> -ProcessMonitor::ServeOperation(LaunchArgs *args)
>> +ProcessMonitor::ServeOperation(OperationArgs *args)
>> {
>> int status;
>> pollfd fdset;
>> +
>> ProcessMonitor *monitor = args->m_monitor;
>>
>> fdset.fd = monitor->m_server_fd;
>> @@ -1326,7 +1472,7 @@ void
>> ProcessMonitor::StopMonitor()
>> {
>> StopMonitoringChildProcess();
>> - StopOperationThread();
>> + StopLaunchOpThread();
>> CloseFD(m_terminal_fd);
>> CloseFD(m_client_fd);
>> CloseFD(m_server_fd);
>> diff --git a/source/Plugins/Process/Linux/ProcessMonitor.h b/source/Plugins/Process/Linux/ProcessMonitor.h
>> index 9b8051b..ef9a179 100644
>> --- a/source/Plugins/Process/Linux/ProcessMonitor.h
>> +++ b/source/Plugins/Process/Linux/ProcessMonitor.h
>> @@ -56,6 +56,10 @@ public:
>> const char *stderr_path,
>> lldb_private::Error &error);
>>
>> + ProcessMonitor(ProcessLinux *process,
>> + lldb::pid_t pid,
>> + lldb_private::Error &error);
>> +
>> ~ProcessMonitor();
>>
>> /// Provides the process number of debugee.
>> @@ -169,11 +173,22 @@ private:
>> int m_client_fd;
>> int m_server_fd;
>>
>> + struct OperationArgs
>> + {
>> + OperationArgs(ProcessMonitor *monitor);
>> +
>> + ~OperationArgs();
>> +
>> + ProcessMonitor *m_monitor; // The monitor performing the attach.
>> + sem_t m_semaphore; // Posted to once operation complete.
>> + lldb_private::Error m_error; // Set if process operation failed.
>> + };
>> +
>> /// @class LauchArgs
>> ///
>> /// @brief Simple structure to pass data to the thread responsible for
>> /// launching a child process.
>> - struct LaunchArgs
>> + struct LaunchArgs : OperationArgs
>> {
>> LaunchArgs(ProcessMonitor *monitor,
>> lldb_private::Module *module,
>> @@ -192,18 +207,16 @@ private:
>> const char *m_stdin_path; // Redirect stdin or NULL.
>> const char *m_stdout_path; // Redirect stdout or NULL.
>> const char *m_stderr_path; // Redirect stderr or NULL.
>> - sem_t m_semaphore; // Posted to once launch complete.
>> - lldb_private::Error m_error; // Set if process launch failed.
>> };
>>
>> void
>> - StartOperationThread(LaunchArgs *args, lldb_private::Error &error);
>> + StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
>>
>> void
>> - StopOperationThread();
>> + StopLaunchOpThread();
>>
>> static void *
>> - OperationThread(void *arg);
>> + LaunchOpThread(void *arg);
>>
>> static bool
>> Launch(LaunchArgs *args);
>> @@ -211,8 +224,30 @@ private:
>> bool
>> EnableIPC();
>>
>> + struct AttachArgs : OperationArgs
>> + {
>> + AttachArgs(ProcessMonitor *monitor,
>> + lldb::pid_t pid);
>> +
>> + ~AttachArgs();
>> +
>> + lldb::pid_t m_pid; // pid of the process to be attached.
>> + };
>> +
>> + void
>> + StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
>> +
>> + void
>> + StopAttachOpThread();
>> +
>> + static void *
>> + AttachOpThread(void *args);
>> +
>> + static bool
>> + Attach(AttachArgs *args);
>> +
>> static void
>> - ServeOperation(LaunchArgs *args);
>> + ServeOperation(OperationArgs *args);
>>
>> static bool
>> DupDescriptor(const char *path, int fd, int flags);
>> --
>> 1.7.3.4
>>
>> _______________________________________________
>> lldb-commits mailing list
>> lldb-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
More information about the lldb-commits
mailing list