Commit bf9b4c17 authored by Andrew Kaylor's avatar Andrew Kaylor
Browse files

Adding support for process attach by pid on Linux.

llvm-svn: 181374
parent 8f1fb6f0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1189,7 +1189,7 @@ Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstance
}
#endif

#if !defined (__APPLE__) && !defined (__FreeBSD__)
#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined(__linux__)
bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
+97 −23
Original line number Diff line number Diff line
@@ -28,31 +28,11 @@
using namespace lldb;
using namespace lldb_private;

bool
Host::GetOSVersion(uint32_t &major, 
                   uint32_t &minor, 
                   uint32_t &update)
namespace
{
    struct utsname un;
    int status;

    if (uname(&un))
        return false;

    status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
     return status == 3;
}

Error
Host::LaunchProcess (ProcessLaunchInfo &launch_info)
{
    Error error;
    assert(!"Not implemented yet!!!");
    return error;
}

lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
ReadProcPseudoFile(lldb::pid_t pid, const char *name)
{
    static const size_t path_size = 128;
    static char path[path_size];
@@ -65,7 +45,7 @@ Host::GetAuxvData(lldb_private::Process *process)
    // dynamically generated by the kernel) which is incompatible with the
    // current ReadFileContents implementation.  Therefore we simply stream the
    // data into a DataBuffer ourselves.
    if (snprintf(path, path_size, "/proc/%" PRIu64 "/auxv", process->GetID()) < 0)
    if (snprintf(path, path_size, "/proc/%" PRIu64 "/%s", pid, name) < 0)
        return buf_sp;

    if ((fd = open(path, O_RDONLY, 0)) < 0)
@@ -96,3 +76,97 @@ Host::GetAuxvData(lldb_private::Process *process)

    return buf_sp;
}

} // anonymous namespace

bool
Host::GetOSVersion(uint32_t &major,
                   uint32_t &minor,
                   uint32_t &update)
{
    struct utsname un;
    int status;

    if (uname(&un))
        return false;

    status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
    return status == 3;
}

Error
Host::LaunchProcess (ProcessLaunchInfo &launch_info)
{
    Error error;
    assert(!"Not implemented yet!!!");
    return error;
}

lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
{
    return ReadProcPseudoFile(process->GetID(), "auxv");
}


bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
    process_info.Clear();
    process_info.SetProcessID(pid);

    // Architecture is intentionally omitted because that's better resolved
    // in other places (see ProcessPOSIX::DoAttachWithID().

    // Use special code here because proc/[pid]/exe is a symbolic link.
    char link_path[PATH_MAX];
    char exe_path[PATH_MAX] = "";
    if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) > 0)
    {
        ssize_t len = readlink(link_path, exe_path, sizeof(exe_path) - 1);
        if (len > 0)
            exe_path[len] = 0;

        static const ssize_t deleted_len = strlen(" (deleted)");
        if (len > deleted_len &&
            !strcmp(exe_path + len - deleted_len, " (deleted)"))
        {
            exe_path[len - deleted_len] = 0;
        }
    }
    process_info.GetExecutableFile().SetFile(exe_path, false);

    lldb::DataBufferSP buf_sp;

    // Get the process environment.
    buf_sp = ReadProcPseudoFile(pid, "environ");
    Args &info_env = process_info.GetEnvironmentEntries();
    char *next_var = (char *)buf_sp->GetBytes();
    char *end_buf = next_var + buf_sp->GetByteSize();
    while (next_var < end_buf && 0 != *next_var)
    {
        info_env.AppendArgument(next_var);
        next_var += strlen(next_var) + 1;
    }

    // Get the commond line used to start the process.
    buf_sp = ReadProcPseudoFile(pid, "cmdline");

    // Grab Arg0 first.
    char *cmd = (char *)buf_sp->GetBytes();
    process_info.SetArg0(cmd);

    // Now process any remaining arguments.
    Args &info_args = process_info.GetArguments();
    char *next_arg = cmd + strlen(cmd) + 1;
    end_buf = cmd + buf_sp->GetByteSize();
    while (next_arg < end_buf && 0 != *next_arg)
    {
        info_args.AppendArgument(next_arg);
        next_arg += strlen(next_arg) + 1;
    }

    // FIXME: Parse /proc/<pid>/status to get uid, gid, euid, egid and parent_pid

    return true;
}
 No newline at end of file
+6 −1
Original line number Diff line number Diff line
@@ -59,7 +59,12 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
      m_removed_soentries()
{
    // Cache a copy of the executable path
    m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
    if (m_process)
    {
        Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
        if (exe_mod)
            exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
    }
}

bool
+34 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Target.h"

#include "ProcessPOSIX.h"
@@ -99,7 +100,8 @@ ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)
    ModuleSP exe_module_sp(target.GetExecutableModule());
    if (exe_module_sp.get())
        return exe_module_sp->GetFileSpec().Exists();
    return false;
    // If there is no executable module, we return true since we might be preparing to attach.
    return true;
}

Error
@@ -117,7 +119,38 @@ ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)
    if (!error.Success())
        return error;

    PlatformSP platform_sp (m_target.GetPlatform ());
    assert (platform_sp.get());
    if (!platform_sp)
        return error;  // FIXME: Detatch?

    // Find out what we can about this process
    ProcessInstanceInfo process_info;
    platform_sp->GetProcessInfo (pid, process_info);

    // Resolve the executable module
    ModuleSP exe_module_sp;
    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
    error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
                                           m_target.GetArchitecture(),
                                           exe_module_sp,
                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);

    // Fix the target architecture if necessary
    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
    if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
        m_target.SetArchitecture(module_arch);

    // Initialize the target module list
    m_target.SetExecutableModule (exe_module_sp, true);

    if (!error.Success())
        return error;

    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());

    SetID(pid);

    return error;
}

+4 −1
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ class ConnectRemoteTestCase(TestBase):
        fakeserver.expect_exact('Listening on localhost:12345')

        # Connect to the fake server....
        if sys.platform.startswith("linux"):
            self.runCmd("process connect -p gdb-remote connect://localhost:12345")
        else:
            self.runCmd("process connect connect://localhost:12345")


Loading