This patch fixes debugging of single threaded apps on Linux. 
It also adds some asserts and additional logging support.

from dawn@burble.org

llvm-svn: 142384
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
index d708ae1..ff1e024 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -19,6 +19,7 @@
 
 // C++ Includes
 // Other libraries and framework includes
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/Error.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Scalar.h"
@@ -29,11 +30,60 @@
 
 #include "LinuxThread.h"
 #include "ProcessLinux.h"
+#include "ProcessLinuxLog.h"
 #include "ProcessMonitor.h"
 
 
 using namespace lldb_private;
 
+// FIXME: this code is host-dependent with respect to types and
+// endianness and needs to be fixed.  For example, lldb::addr_t is
+// hard-coded to uint64_t, but on a 32-bit Linux host, ptrace requires
+// 32-bit pointer arguments.  This code uses casts to work around the
+// problem.
+
+// 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.
+extern long
+PtraceWrapper(__ptrace_request req, pid_t pid, void *addr, void *data,
+              const char* reqName, const char* file, int line)
+{
+    int result;
+
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE));
+    if (log)
+        log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d",
+                    reqName, pid, addr, data, file, line);
+
+    errno = 0;
+    result = ptrace(req, pid, addr, data);
+
+    if (log && (result == -1 || errno != 0))
+    {
+        const char* str;
+        switch (errno)
+        {
+        case ESRCH:  str = "ESRCH"; break;
+        case EINVAL: str = "EINVAL"; break;
+        case EBUSY:  str = "EBUSY"; break;
+        case EPERM:  str = "EPERM"; break;
+        default:     str = "<unknown>";
+        }
+        log->Printf("ptrace() failed; errno=%d (%s)", errno, str);
+    }
+
+    return result;
+}
+
+#define PTRACE(req, pid, addr, data) \
+    PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
+#else
+#define PTRACE ptrace
+#endif
+
 //------------------------------------------------------------------------------
 // Static implementations of ProcessMonitor::ReadMemory and
 // ProcessMonitor::WriteMemory.  This enables mutual recursion between these
@@ -48,25 +98,49 @@
     size_t remainder;
     long data;
 
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL));
+    if (log)
+        ProcessLinuxLog::IncNestLevel();
+    if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY))
+        log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
+                     pid, word_size, (void*)vm_addr, buf, size);
+
+    assert(sizeof(data) >= word_size);
+    assert(sizeof(void*) == word_size);
     for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
     {
         errno = 0;
-        data = ptrace(PTRACE_PEEKDATA, pid, vm_addr, NULL);
-
+        data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL);
         if (data == -1L && errno)
         {
             error.SetErrorToErrno();
+            if (log)
+                ProcessLinuxLog::DecNestLevel();
             return bytes_read;
         }
 
         remainder = size - bytes_read;
         remainder = remainder > word_size ? word_size : remainder;
+
+        // Copy the data into our buffer
+        if (log)
+            memset(dst, 0, sizeof(dst));
         for (unsigned i = 0; i < remainder; ++i)
             dst[i] = ((data >> i*8) & 0xFF);
+
+        if (log && ProcessLinuxLog::AtTopNestLevel() &&
+            (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) ||
+             (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) &&
+              size <= LINUX_LOG_MEMORY_SHORT_BYTES)))
+            log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                         (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data);
+
         vm_addr += word_size;
         dst += word_size;
     }
 
+    if (log)
+        ProcessLinuxLog::DecNestLevel();
     return bytes_read;
 }
 
@@ -78,6 +152,14 @@
     size_t bytes_written = 0;
     size_t remainder;
 
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL));
+    if (log)
+        ProcessLinuxLog::IncNestLevel();
+    if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY))
+        log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
+                     pid, word_size, (void*)vm_addr, buf, size);
+
+    assert(sizeof(void*) == word_size);
     for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
     {
         remainder = size - bytes_written;
@@ -86,12 +168,22 @@
         if (remainder == word_size)
         {
             unsigned long data = 0;
+            assert(sizeof(data) >= word_size);
             for (unsigned i = 0; i < word_size; ++i)
                 data |= (unsigned long)src[i] << i*8;
 
-            if (ptrace(PTRACE_POKEDATA, pid, vm_addr, data))
+            if (log && ProcessLinuxLog::AtTopNestLevel() &&
+                (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) ||
+                 (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) &&
+                  size <= LINUX_LOG_MEMORY_SHORT_BYTES)))
+                 log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                              (void*)vm_addr, *(unsigned long*)src, data);
+
+            if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data))
             {
                 error.SetErrorToErrno();
+                if (log)
+                    ProcessLinuxLog::DecNestLevel();
                 return bytes_written;
             }
         }
@@ -100,18 +192,35 @@
             unsigned char buff[8];
             if (DoReadMemory(pid, word_size, vm_addr,
                              buff, word_size, error) != word_size)
+            {
+                if (log)
+                    ProcessLinuxLog::DecNestLevel();
                 return bytes_written;
+            }
 
             memcpy(buff, src, remainder);
 
             if (DoWriteMemory(pid, word_size, vm_addr,
                               buff, word_size, error) != word_size)
+            {
+                if (log)
+                    ProcessLinuxLog::DecNestLevel();
                 return bytes_written;
+            }
+
+            if (log && ProcessLinuxLog::AtTopNestLevel() &&
+                (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) ||
+                 (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) &&
+                  size <= LINUX_LOG_MEMORY_SHORT_BYTES)))
+                 log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                              (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff);
         }
 
         vm_addr += word_size;
         src += word_size;
     }
+    if (log)
+        ProcessLinuxLog::DecNestLevel();
     return bytes_written;
 }
 
@@ -216,6 +325,7 @@
     m_result = DoWriteMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
 }
 
+
 //------------------------------------------------------------------------------
 /// @class ReadRegOperation
 /// @brief Implements ProcessMonitor::ReadRegisterValue.
@@ -238,11 +348,11 @@
 ReadRegOperation::Execute(ProcessMonitor *monitor)
 {
     lldb::pid_t pid = monitor->GetPID();
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS));
 
     // Set errno to zero so that we can detect a failed peek.
     errno = 0;
-    uint32_t data = ptrace(PTRACE_PEEKUSER, pid, m_offset, NULL);
-
+    uint32_t data = PTRACE(PTRACE_PEEKUSER, pid, (void*)m_offset, NULL);
     if (data == -1UL && errno)
         m_result = false;
     else
@@ -250,6 +360,9 @@
         m_value = data;
         m_result = true;
     }
+    if (log)
+        log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__,
+                     LinuxThread::GetRegisterNameFromOffset(m_offset), data);
 }
 
 //------------------------------------------------------------------------------
@@ -273,9 +386,22 @@
 void
 WriteRegOperation::Execute(ProcessMonitor *monitor)
 {
+    void* buf;
     lldb::pid_t pid = monitor->GetPID();
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS));
 
-    if (ptrace(PTRACE_POKEUSER, pid, m_offset, m_value.GetAsUInt64()))
+    if (sizeof(void*) == sizeof(uint64_t))
+        buf = (void*) m_value.GetAsUInt64();
+    else
+    {
+        assert(sizeof(void*) == sizeof(uint32_t));
+        buf = (void*) m_value.GetAsUInt32();
+    }
+
+    if (log)
+        log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__,
+                     LinuxThread::GetRegisterNameFromOffset(m_offset), buf);
+    if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf))
         m_result = false;
     else
         m_result = true;
@@ -301,7 +427,7 @@
 void
 ReadGPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_GETREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_GETREGS, monitor->GetPID(), NULL, m_buf) < 0)
         m_result = false;
     else
         m_result = true;
@@ -327,7 +453,7 @@
 void
 ReadFPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_GETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_GETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
         m_result = false;
     else
         m_result = true;
@@ -353,7 +479,7 @@
 void
 WriteGPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_SETREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_SETREGS, monitor->GetPID(), NULL, m_buf) < 0)
         m_result = false;
     else
         m_result = true;
@@ -379,7 +505,7 @@
 void
 WriteFPROperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_SETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
+    if (PTRACE(PTRACE_SETFPREGS, monitor->GetPID(), NULL, m_buf) < 0)
         m_result = false;
     else
         m_result = true;
@@ -410,7 +536,7 @@
     if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
         data = m_signo;
 
-    if (ptrace(PTRACE_CONT, m_tid, NULL, data))
+    if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data))
         m_result = false;
     else
         m_result = true;
@@ -441,7 +567,7 @@
     if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
         data = m_signo;
 
-    if (ptrace(PTRACE_SINGLESTEP, m_tid, NULL, data))
+    if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data))
         m_result = false;
     else
         m_result = true;
@@ -467,7 +593,7 @@
 void
 SiginfoOperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_GETSIGINFO, m_tid, NULL, m_info))
+    if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info))
         m_result = false;
     else
         m_result = true;
@@ -493,7 +619,7 @@
 void
 EventMessageOperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_GETEVENTMSG, m_tid, NULL, m_message))
+    if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message))
         m_result = false;
     else
         m_result = true;
@@ -518,7 +644,7 @@
 {
     lldb::pid_t pid = monitor->GetPID();
 
-    if (ptrace(PTRACE_KILL, pid, NULL, NULL))
+    if (PTRACE(PTRACE_KILL, pid, NULL, NULL))
         m_result = false;
     else
         m_result = true;
@@ -756,6 +882,7 @@
     lldb::pid_t pid;
 
     lldb::ThreadSP inferior;
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
 
     // Propagate the environment if one is not supplied.
     if (envp == NULL || envp[0] == NULL)
@@ -789,7 +916,7 @@
     if (pid == 0)
     {
         // Trace this process.
-        if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0)
+        if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL) < 0)
             exit(ePtraceFailed);
 
         // Do not inherit setgid powers.
@@ -861,7 +988,7 @@
 
     // Have the child raise an event on exit.  This is used to keep the child in
     // limbo until it is destroyed.
-    if (ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0)
+    if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)PTRACE_O_TRACEEXIT) < 0)
     {
         args->m_error.SetErrorToErrno();
         goto FINISH;
@@ -880,9 +1007,12 @@
 
     // Update the process thread list with this new thread and mark it as
     // current.
+    // FIXME: should we be letting UpdateThreadList handle this?
+    // FIXME: by using pids instead of tids, we can only support one thread.
     inferior.reset(new LinuxThread(process, pid));
+    if (log)
+        log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid);
     process.GetThreadList().AddThread(inferior);
-    process.GetThreadList().SetSelectedThreadByID(pid);
 
     // Let our process instance know the thread has stopped.
     process.SendMessage(ProcessMessage::Trace(pid));
@@ -943,6 +1073,7 @@
     ProcessLinux &process = monitor->GetProcess();
 
     lldb::ThreadSP inferior;
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
 
     if (pid <= 1)
     {
@@ -952,7 +1083,7 @@
     }
 
     // Attach to the requested process.
-    if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0)
+    if (PTRACE(PTRACE_ATTACH, pid, NULL, NULL) < 0)
     {
         args->m_error.SetErrorToErrno();
         goto FINISH;
@@ -968,6 +1099,8 @@
     // Update the process thread list with the attached thread and
     // mark it as current.
     inferior.reset(new LinuxThread(process, pid));
+    if (log)
+        log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid);
     process.GetThreadList().AddThread(inferior);
     process.GetThreadList().SetSelectedThreadByID(pid);
 
@@ -987,6 +1120,7 @@
     ProcessMessage message;
     ProcessMonitor *monitor = static_cast<ProcessMonitor*>(callback_baton);
     ProcessLinux *process = monitor->m_process;
+    assert(process);
     bool stop_monitoring;
     siginfo_t info;
 
@@ -1017,7 +1151,8 @@
 {
     ProcessMessage message;
 
-    assert(info->si_signo == SIGTRAP && "Unexpected child signal!");
+    assert(monitor);
+    assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
 
     switch (info->si_code)
     {