[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