[Lldb-commits] [PATCH] fixes for Linux

dawn at burble.org dawn at burble.org
Mon Oct 17 19:46:00 PDT 2011


Just in case you missed it, this patch (attached in previous email) is
still awaiting review.  Please review and commit if acceptable.

Thanks again!
    -Dawn

On Mon, Oct 17, 2011 at 10:36:09AM -0700, dawn at burble.org wrote:
> 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

> 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);

> _______________________________________________
> 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