[Lldb-commits] [PATCH] fixes for Linux

dawn at burble.org dawn at burble.org
Mon Oct 17 10:36:09 PDT 2011


Seems I forgot the patch?  Doh!

On Fri, Oct 14, 2011 at 07:58:53PM -0700, dawn at burble.org wrote:
> This patch fixes debugging of single threaded apps on Linux. 
> It also adds some asserts and additional logging support.
> 
> Thanks in advance,
>     -Dawn
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
-------------- next part --------------
Index: source/Plugins/Process/Linux/ProcessLinux.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessLinux.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessLinux.cpp	(working copy)
@@ -119,7 +119,7 @@
 
     LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
     if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
-        log->Printf ("ProcessLinux::%s (pid = %i)", __FUNCTION__, GetID());
+        log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID());
 
     m_monitor = new ProcessMonitor(this, pid, error);
 
@@ -328,6 +328,10 @@
 void
 ProcessLinux::RefreshStateAfterStop()
 {
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
+    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+        log->Printf ("ProcessLinux::%s()", __FUNCTION__);
+
     Mutex::Locker lock(m_message_mutex);
     if (m_message_queue.empty())
         return;
@@ -335,10 +339,15 @@
     ProcessMessage &message = m_message_queue.front();
 
     // Resolve the thread this message corresponds to and pass it along.
+    // FIXME: we're really dealing with the pid here.  This should get
+    // fixed when this code is fixed to handle multiple threads.
     lldb::tid_t tid = message.GetTID();
+    if (log)
+        log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid);
     LinuxThread *thread = static_cast<LinuxThread*>(
         GetThreadList().FindThreadByID(tid, false).get());
 
+    assert(thread);
     thread->Notify(message);
 
     m_message_queue.pop();
@@ -355,6 +364,7 @@
 ProcessLinux::DoReadMemory(addr_t vm_addr,
                            void *buf, size_t size, Error &error)
 {
+    assert(m_monitor);
     return m_monitor->ReadMemory(vm_addr, buf, size, error);
 }
 
@@ -362,6 +372,7 @@
 ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
                             Error &error)
 {
+    assert(m_monitor);
     return m_monitor->WriteMemory(vm_addr, buf, size, error);
 }
 
@@ -453,12 +464,22 @@
 uint32_t
 ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
-    // FIXME: Should this be implemented?
     LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
     if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
-        log->Printf ("ProcessLinux::%s (pid = %i)", __FUNCTION__, GetID());
+        log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID());
 
-    return 0;
+    // Update the process thread list with this new thread.
+    // FIXME: We should be using tid, not pid.
+    assert(m_monitor);
+    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
+    if (!thread_sp)
+        thread_sp.reset(new LinuxThread(*this, GetID()));
+
+    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+        log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
+    new_thread_list.AddThread(thread_sp);
+
+    return new_thread_list.GetSize(false);
 }
 
 ByteOrder
Index: source/Plugins/Process/Linux/ProcessLinuxLog.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessLinuxLog.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessLinuxLog.cpp	(working copy)
@@ -69,6 +69,8 @@
                 else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT;
                 else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG;
                 else if (::strcasecmp (arg, "process")    == 0 ) flag_bits &= ~LINUX_LOG_PROCESS;
+                else if (::strcasecmp (arg, "ptrace")     == 0 ) flag_bits &= ~LINUX_LOG_PTRACE;
+                else if (::strcasecmp (arg, "registers")  == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS;
                 else if (::strcasecmp (arg, "step")       == 0 ) flag_bits &= ~LINUX_LOG_STEP;
                 else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits &= ~LINUX_LOG_THREAD;
                 else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE;
@@ -126,6 +128,8 @@
             else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_SHORT;
             else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_LONG;
             else if (::strcasecmp (arg, "process")    == 0 ) flag_bits |= LINUX_LOG_PROCESS;
+            else if (::strcasecmp (arg, "ptrace")     == 0 ) flag_bits |= LINUX_LOG_PTRACE;
+            else if (::strcasecmp (arg, "registers")  == 0 ) flag_bits |= LINUX_LOG_REGISTERS;
             else if (::strcasecmp (arg, "step")       == 0 ) flag_bits |= LINUX_LOG_STEP;
             else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits |= LINUX_LOG_THREAD;
             else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits |= LINUX_LOG_VERBOSE;
@@ -162,6 +166,10 @@
                   "  data-short - log memory bytes for memory reads and writes for short transactions only\n"
                   "  data-long - log memory bytes for memory reads and writes for all transactions\n"
                   "  process - log process events and activities\n"
+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+                  "  ptrace - log all calls to ptrace\n"
+#endif
+                  "  registers - log register read/writes\n"
                   "  thread - log thread events and activities\n"
                   "  step - log step related activities\n"
                   "  verbose - enable verbose logging\n"
@@ -181,3 +189,5 @@
         va_end (args);
     }
 }
+
+int ProcessLinuxLog::m_nestinglevel;
Index: source/Plugins/Process/Linux/ProcessLinux.h
===================================================================
--- source/Plugins/Process/Linux/ProcessLinux.h	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessLinux.h	(working copy)
@@ -177,7 +177,8 @@
     /// Registers the given message with this process.
     void SendMessage(const ProcessMessage &message);
 
-    ProcessMonitor &GetMonitor() { return *m_monitor; }
+    ProcessMonitor &
+    GetMonitor() { assert(m_monitor); return *m_monitor; }
 
     lldb_private::UnixSignals &
     GetUnixSignals();
Index: source/Plugins/Process/Linux/ProcessLinuxLog.h
===================================================================
--- source/Plugins/Process/Linux/ProcessLinuxLog.h	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessLinuxLog.h	(working copy)
@@ -29,11 +29,18 @@
 #define LINUX_LOG_STEP                     (1u << 9)
 #define LINUX_LOG_COMM                     (1u << 10)
 #define LINUX_LOG_ASYNC                    (1u << 11)
+#define LINUX_LOG_PTRACE                   (1u << 12)
+#define LINUX_LOG_REGISTERS                (1u << 13)
 #define LINUX_LOG_ALL                      (UINT32_MAX)
 #define LINUX_LOG_DEFAULT                  LINUX_LOG_PACKETS
 
+// The size which determines "short memory reads/writes".
+#define LINUX_LOG_MEMORY_SHORT_BYTES       (4 * sizeof(ptrdiff_t))
+
 class ProcessLinuxLog
 {
+    static int m_nestinglevel;
+
 public:
     static lldb::LogSP
     GetLogIfAllCategoriesSet(uint32_t mask = 0);
@@ -42,13 +49,50 @@
     DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm);
 
     static lldb::LogSP
-    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, lldb_private::Args &args, lldb_private::Stream *feedback_strm);
+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,
+               lldb_private::Args &args, lldb_private::Stream *feedback_strm);
 
     static void
     ListLogCategories (lldb_private::Stream *strm);
 
     static void
     LogIf (uint32_t mask, const char *format, ...);
+
+    // The following functions can be used to enable the client to limit
+    // logging to only the top level function calls.  This is useful for
+    // recursive functions.  FIXME: not thread safe!
+    //     Example:
+    //     void NestingFunc() {
+    //         LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL));
+    //         if (log)
+    //         {
+    //             ProcessLinuxLog::IncNestLevel();
+    //             if (ProcessLinuxLog::AtTopNestLevel())
+    //                 log->Print(msg);
+    //         }
+    //         NestingFunc();
+    //         if (log)
+    //             ProcessLinuxLog::DecNestLevel();
+    //     }
+
+    static bool
+    AtTopNestLevel()
+    {
+        return m_nestinglevel == 1;
+    }
+
+    static void
+    IncNestLevel()
+    {
+        ++m_nestinglevel;
+    }
+
+    static void
+    DecNestLevel()
+    {
+        --m_nestinglevel;
+        assert(m_nestinglevel >= 0);
+    }
 };
 
 #endif  // liblldb_ProcessLinuxLog_h_
Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp	(working copy)
@@ -12,6 +12,7 @@
 #include "lldb/Host/Endian.h"
 
 #include "ProcessLinux.h"
+#include "ProcessLinuxLog.h"
 #include "ProcessMonitor.h"
 #include "RegisterContextLinux_i386.h"
 
@@ -31,7 +32,6 @@
     gpr_esp,
     gpr_ss,
     gpr_eflags,
-    gpr_orig_ax,
     gpr_eip,
     gpr_cs,
     gpr_ds,
@@ -189,7 +189,6 @@
     gpr_esp,
     gpr_ss,
     gpr_eflags,
-    gpr_orig_ax,
     gpr_eip,
     gpr_cs,
     gpr_ds,
@@ -330,12 +329,17 @@
 
 };
 
+#ifndef NDEBUG
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+#endif
+
 static unsigned GetRegOffset(unsigned reg)
 {
     assert(reg < k_num_registers && "Invalid register number.");
     return g_register_infos[reg].byte_offset;
 }
 
+#if 0 // These functions are currently not in use.
 static unsigned GetRegSize(unsigned reg)
 {
     assert(reg < k_num_registers && "Invalid register number.");
@@ -351,6 +355,7 @@
 {
     return (k_first_fpr <= reg && reg <= k_last_fpr);
 }
+#endif
 
 
 RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread,
@@ -383,12 +388,14 @@
 size_t
 RegisterContextLinux_i386::GetRegisterCount()
 {
+    assert(k_num_register_infos == k_num_registers);
     return k_num_registers;
 }
 
 const RegisterInfo *
 RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg)
 {
+    assert(k_num_register_infos == k_num_registers);
     if (reg < k_num_registers)
         return &g_register_infos[reg];
     else
@@ -410,6 +417,26 @@
         return NULL;
 }
 
+unsigned
+RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    for (reg = 0; reg < k_num_registers; reg++)
+    {
+        if (g_register_infos[reg].byte_offset == offset)
+            break;
+    }
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return reg;
+}
+
+const char *
+RegisterContextLinux_i386::GetRegisterName(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return g_register_infos[reg].name;
+}
+
 bool
 RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info,
                                         RegisterValue &value)
@@ -588,11 +615,31 @@
     return WriteRegisterFromUnsigned(gpr_eflags, eflags);
 }
 
+void
+RegisterContextLinux_i386::LogGPR(const char *title)
+{
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS));
+    if (log)
+    {
+        if (title)
+            log->Printf ("%s", title);
+        for (uint32_t i=0; i<k_num_gpr_registers; i++)
+        {
+            uint32_t reg = gpr_eax + i;
+            log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]);
+        }
+    }
+}
+
 bool
 RegisterContextLinux_i386::ReadGPR()
 {
-     ProcessMonitor &monitor = GetMonitor();
-     return monitor.ReadGPR(&user.regs);
+    bool result;
+
+    ProcessMonitor &monitor = GetMonitor();
+    result = monitor.ReadGPR(&user.regs);
+    LogGPR("RegisterContextLinux_i386::ReadGPR()");
+    return result;
 }
 
 bool
Index: source/Plugins/Process/Linux/ProcessMessage.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessMessage.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessMessage.cpp	(working copy)
@@ -89,3 +89,157 @@
 
     return str;
 }
+
+const char *
+ProcessMessage::PrintCrashReason(CrashReason reason)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+    // Just return the code in asci for integration builds.
+    chcar str[8];
+    sprintf(str, "%d", reason);
+#else
+    const char *str = NULL;
+
+    switch (reason)
+    {
+    default:
+        assert(false && "invalid CrashReason");
+        break;
+
+        case eInvalidCrashReason:
+            str = "eInvalidCrashReason";
+            break;
+
+        // SIGSEGV crash rcase easons.
+        case eInvalidAddress:
+            str = "eInvalidAddress";
+            break;
+        case ePrivilegedAddress:
+            str = "ePrivilegedAddress";
+            break;
+
+        // SIGILL crash rcase easons.
+        case eIllegalOpcode:
+            str = "eIllegalOpcode";
+            break;
+        case eIllegalOperand:
+            str = "eIllegalOperand";
+            break;
+        case eIllegalAddressingMode:
+            str = "eIllegalAddressingMode";
+            break;
+        case eIllegalTrap:
+            str = "eIllegalTrap";
+            break;
+        case ePrivilegedOpcode:
+            str = "ePrivilegedOpcode";
+            break;
+        case ePrivilegedRegister:
+            str = "ePrivilegedRegister";
+            break;
+        case eCoprocessorError:
+            str = "eCoprocessorError";
+            break;
+        case eInternalStackError:
+            str = "eInternalStackError";
+            break;
+
+        // SIGBUS crash rcase easons:
+        case eIllegalAlignment:
+            str = "eIllegalAlignment";
+            break;
+        case eIllegalAddress:
+            str = "eIllegalAddress";
+            break;
+        case eHardwareError:
+            str = "eHardwareError";
+            break;
+
+        // SIGFPE crash rcase easons:
+        case eIntegerDivideByZero:
+            str = "eIntegerDivideByZero";
+            break;
+        case eIntegerOverflow:
+            str = "eIntegerOverflow";
+            break;
+        case eFloatDivideByZero:
+            str = "eFloatDivideByZero";
+            break;
+        case eFloatOverflow:
+            str = "eFloatOverflow";
+            break;
+        case eFloatUnderflow:
+            str = "eFloatUnderflow";
+            break;
+        case eFloatInexactResult:
+            str = "eFloatInexactResult";
+            break;
+        case eFloatInvalidOperation:
+            str = "eFloatInvalidOperation";
+            break;
+        case eFloatSubscriptRange:
+            str = "eFloatSubscriptRange";
+            break;
+    }
+#endif
+
+    return str;
+}
+
+const char *
+ProcessMessage::PrintCrashReason() const
+{
+    return PrintCrashReason(m_crash_reason);
+}
+
+const char *
+ProcessMessage::PrintKind(Kind kind)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+    // Just return the code in asci for integration builds.
+    chcar str[8];
+    sprintf(str, "%d", reason);
+#else
+    const char *str = NULL;
+
+    switch (kind)
+    {
+    default:
+        assert(false && "invalid Kind");
+        break;
+
+    case eInvalidMessage:
+        str = "eInvalidMessage";
+        break;
+    case eExitMessage:
+        str = "eExitMessage";
+        break;
+    case eLimboMessage:
+        str = "eLimboMessage";
+        break;
+    case eSignalMessage:
+        str = "eSignalMessage";
+        break;
+    case eSignalDeliveredMessage:
+        str = "eSignalDeliveredMessage";
+        break;
+    case eTraceMessage:
+        str = "eTraceMessage";
+        break;
+    case eBreakpointMessage:
+        str = "eBreakpointMessage";
+        break;
+    case eCrashMessage:
+        str = "eCrashMessage";
+        break;
+    }
+#endif
+
+    return str;
+}
+
+const char *
+ProcessMessage::PrintKind() const
+{
+    return PrintKind(m_kind);
+}
Index: source/Plugins/Process/Linux/ProcessMonitor.cpp
===================================================================
--- source/Plugins/Process/Linux/ProcessMonitor.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessMonitor.cpp	(working copy)
@@ -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)
     {
Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp	(working copy)
@@ -405,6 +405,7 @@
     return g_register_infos[reg].byte_offset;
 }
 
+#if 0 // These functions are currently not being used.
 static unsigned GetRegSize(unsigned reg)
 {
     assert(reg < k_num_registers && "Invalid register number.");
@@ -420,6 +421,7 @@
 {
     return (k_first_fpr <= reg && reg <= k_last_fpr);
 }
+#endif
 
 RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread,
                                                          uint32_t concrete_frame_idx)
@@ -478,6 +480,26 @@
         return NULL;
 }
 
+unsigned
+RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    for (reg = 0; reg < k_num_registers; reg++)
+    {
+        if (g_register_infos[reg].byte_offset == offset)
+            break;
+    }
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return reg;
+}
+
+const char *
+RegisterContextLinux_x86_64::GetRegisterName(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return g_register_infos[reg].name;
+}
+
 bool
 RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
                                           RegisterValue &value)
Index: source/Plugins/Process/Linux/LinuxThread.cpp
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.cpp	(revision 142029)
+++ source/Plugins/Process/Linux/LinuxThread.cpp	(working copy)
@@ -13,14 +13,15 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Core/Debugger.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Target.h"
-
 #include "LinuxStopInfo.h"
 #include "LinuxThread.h"
 #include "ProcessLinux.h"
+#include "ProcessLinuxLog.h"
 #include "ProcessMonitor.h"
 #include "RegisterContextLinux_i386.h"
 #include "RegisterContextLinux_x86_64.h"
@@ -33,6 +34,9 @@
     : Thread(process, tid),
       m_frame_ap(0)
 {
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
+    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+        log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid);
 }
 
 LinuxThread::~LinuxThread()
@@ -50,6 +54,14 @@
 void
 LinuxThread::RefreshStateAfterStop()
 {
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
+    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+        log->Printf ("LinuxThread::%s ()", __FUNCTION__);
+
+    // Let all threads recover from stopping and do any clean up based
+    // on the previous thread state (if any).
+    ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess());
+    process.GetThreadList().RefreshStateAfterStop();
 }
 
 const char *
@@ -91,13 +103,20 @@
     lldb::RegisterContextSP reg_ctx_sp;
     uint32_t concrete_frame_idx = 0;
 
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
+    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+        log->Printf ("LinuxThread::%s ()", __FUNCTION__);
+
     if (frame)
         concrete_frame_idx = frame->GetConcreteFrameIndex();
 
     if (concrete_frame_idx == 0)
         reg_ctx_sp = GetRegisterContext();
     else
+    {
+        assert(GetUnwinder());
         reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
+    }
 
     return reg_ctx_sp;
 }
@@ -136,6 +155,10 @@
     ProcessMonitor &monitor = GetMonitor();
     bool status;
 
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
+    if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+        log->Printf ("LinuxThread::%s ()", __FUNCTION__);
+
     switch (resume_state)
     {
     default:
@@ -160,6 +183,10 @@
 void
 LinuxThread::Notify(const ProcessMessage &message)
 {
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
+    if (log)
+        log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind());
+
     switch (message.GetKind())
     {
     default:
@@ -196,14 +223,20 @@
 LinuxThread::BreakNotify(const ProcessMessage &message)
 {
     bool status;
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
 
+    assert(GetRegisterContextLinux());
     status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
     assert(status && "Breakpoint update failed!");
 
     // With our register state restored, resolve the breakpoint object
     // corresponding to our current PC.
+    assert(GetRegisterContext());
     lldb::addr_t pc = GetRegisterContext()->GetPC();
+    if (log)
+        log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
     lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
+    assert(bp_site);
     lldb::break_id_t bp_id = bp_site->GetID();
     assert(bp_site && bp_site->ValidForThisThread(this));
 
@@ -250,7 +283,68 @@
 
     assert(message.GetKind() == ProcessMessage::eCrashMessage);
 
+    LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
+    if (log)
+        log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason());
+
     m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
                                        *this, signo, message.GetCrashReason()));
     SetResumeSignal(signo);
 }
+
+unsigned
+LinuxThread::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    ArchSpec arch = Host::GetArchitecture();
+
+    switch (arch.GetCore())
+    {
+    default:
+        assert(false && "CPU type not supported!");
+        break;
+
+    case ArchSpec::eCore_x86_32_i386:
+    case ArchSpec::eCore_x86_32_i486:
+    case ArchSpec::eCore_x86_32_i486sx:
+        reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset);
+        break;
+
+    case ArchSpec::eCore_x86_64_x86_64:
+        reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset);
+        break;
+    }
+    return reg;
+}
+
+const char *
+LinuxThread::GetRegisterName(unsigned reg)
+{
+    const char * name;
+    ArchSpec arch = Host::GetArchitecture();
+
+    switch (arch.GetCore())
+    {
+    default:
+        assert(false && "CPU type not supported!");
+        break;
+
+    case ArchSpec::eCore_x86_32_i386:
+    case ArchSpec::eCore_x86_32_i486:
+    case ArchSpec::eCore_x86_32_i486sx:
+        name = RegisterContextLinux_i386::GetRegisterName(reg);
+        break;
+
+    case ArchSpec::eCore_x86_64_x86_64:
+        name = RegisterContextLinux_x86_64::GetRegisterName(reg);
+        break;
+    }
+    return name;
+}
+
+const char *
+LinuxThread::GetRegisterNameFromOffset(unsigned offset)
+{
+    return GetRegisterName(GetRegisterIndexFromOffset(offset));
+}
+
Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_i386.h	(revision 142029)
+++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h	(working copy)
@@ -14,6 +14,7 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/Core/Log.h"
 #include "RegisterContextLinux.h"
 
 class RegisterContextLinux_i386 : public RegisterContextLinux
@@ -42,6 +43,12 @@
     const lldb_private::RegisterSet *
     GetRegisterSet(uint32_t set);
 
+    static unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    static const char *
+    GetRegisterName(unsigned reg);
+
 #if 0
     bool
     ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
@@ -153,6 +160,8 @@
 
     ProcessMonitor &GetMonitor();
 
+    void LogGPR(const char *title);
+
     bool ReadGPR();
     bool ReadFPR();
 };
Index: source/Plugins/Process/Linux/ProcessMessage.h
===================================================================
--- source/Plugins/Process/Linux/ProcessMessage.h	(revision 142029)
+++ source/Plugins/Process/Linux/ProcessMessage.h	(working copy)
@@ -140,6 +140,18 @@
     static const char *
     GetCrashReasonString(CrashReason reason);
 
+    const char *
+    PrintCrashReason() const;
+
+    static const char *
+    PrintCrashReason(CrashReason reason);
+
+    const char *
+    PrintKind() const;
+
+    static const char *
+    PrintKind(Kind);
+
 private:
     ProcessMessage(lldb::tid_t tid, Kind kind, 
                    int status = 0, lldb::addr_t addr = 0)
Index: source/Plugins/Process/Linux/LinuxThread.h
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.h	(revision 142029)
+++ source/Plugins/Process/Linux/LinuxThread.h	(working copy)
@@ -48,6 +48,20 @@
     CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
 
     //--------------------------------------------------------------------------
+    // These static functions provide a mapping from the register offset
+    // back to the register index or name for use in debugging or log
+    // output.
+
+    static unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    static const char *
+    GetRegisterName(unsigned reg);
+
+    static const char *
+    GetRegisterNameFromOffset(unsigned offset);
+
+    //--------------------------------------------------------------------------
     // These methods form a specialized interface to linux threads.
     //
     bool Resume();
Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h	(revision 142029)
+++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h	(working copy)
@@ -41,6 +41,12 @@
     const lldb_private::RegisterSet *
     GetRegisterSet(uint32_t set);
 
+    static unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    static const char *
+    GetRegisterName(unsigned reg);
+
     virtual bool
     ReadRegister(const lldb_private::RegisterInfo *reg_info,
                  lldb_private::RegisterValue &value);


More information about the lldb-commits mailing list