[Lldb-commits] [PATCH] Primitive attach support for linux

Greg Clayton gclayton at apple.com
Tue Jun 14 08:38:33 PDT 2011


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




More information about the lldb-commits mailing list