Hello everybody,

some days ago I noticed that lldb at the moment is missing the support
for i386 debugging on Linux and having some spare time I tried to
modify the plugin for the x86_64 architecture. In the attachment you
can find the patch. Any comments/suggestions or whatever are welcome,
you know I am a student and I have a lot to learn.

Before updating from svn the patch was able to compile and lldb was
able to run programs on my 32bit installation of Ubuntu. Now It seems
that something is broken due to a missing method. The exact error is:

LinuxThread.cpp:69:22: error: no member named 'GetGenericCPUType' in
'lldb_private::ArchSpec'
        switch (arch.GetGenericCPUType())

What has changed?

Best Regards
Marco

-- 
Marco Minutoli
Skype: mminutoli
GPG-Key: 0x36AD4977

"If A is success in life, then A equals x plus y plus z. Work is x;
y is play; and z is keeping your mouth shut." --A. Einstein
Index: include/lldb/Expression/ClangExpressionVariable.h
===================================================================
--- include/lldb/Expression/ClangExpressionVariable.h	(revision 126320)
+++ include/lldb/Expression/ClangExpressionVariable.h	(working copy)
@@ -117,7 +117,7 @@
     EnableParserVars()
     {
         if (!m_parser_vars.get())
-            m_parser_vars.reset(new struct ParserVars);
+            m_parser_vars.reset(new class ParserVars);
     }
     
     //----------------------------------------------------------------------
Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp	(revision 0)
+++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp	(revision 0)
@@ -0,0 +1,634 @@
+//===-- RegisterContextLinux_i386.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+
+#include "ProcessLinux.h"
+#include "ProcessMonitor.h"
+#include "RegisterContextLinux_i386.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+enum
+{
+    k_first_gpr,
+    gpr_eax = k_first_gpr,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs,
+    k_last_gpr = gpr_gs,
+
+    k_first_fpr,
+    fpu_fcw = k_first_fpr,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    k_last_fpr = fpu_xmm7,
+
+    k_num_registers,
+    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+    k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
+};
+
+// Number of register sets provided by this context.
+enum
+{
+    k_num_register_sets = 2
+};
+
+enum
+{
+    gcc_eax = 0,
+    gcc_ecx,
+    gcc_edx,
+    gcc_ebx,
+    gcc_ebp,
+    gcc_esp,
+    gcc_esi,
+    gcc_edi,
+    gcc_eip,
+    gcc_eflags
+};
+
+enum
+{
+    dwarf_eax = 0,
+    dwarf_ecx,
+    dwarf_edx,
+    dwarf_ebx,
+    dwarf_esp,
+    dwarf_ebp,
+    dwarf_esi,
+    dwarf_edi,
+    dwarf_eip,
+    dwarf_eflags,
+    dwarf_stmm0 = 11,
+    dwarf_stmm1,
+    dwarf_stmm2,
+    dwarf_stmm3,
+    dwarf_stmm4,
+    dwarf_stmm5,
+    dwarf_stmm6,
+    dwarf_stmm7,
+    dwarf_xmm0 = 21,
+    dwarf_xmm1,
+    dwarf_xmm2,
+    dwarf_xmm3,
+    dwarf_xmm4,
+    dwarf_xmm5,
+    dwarf_xmm6,
+    dwarf_xmm7
+};
+
+enum
+{
+    gdb_eax        =  0,
+    gdb_ecx        =  1,
+    gdb_edx        =  2,
+    gdb_ebx        =  3,
+    gdb_esp        =  4,
+    gdb_ebp        =  5,
+    gdb_esi        =  6,
+    gdb_edi        =  7,
+    gdb_eip        =  8,
+    gdb_eflags     =  9,
+    gdb_cs         = 10,
+    gdb_ss         = 11,
+    gdb_ds         = 12,
+    gdb_es         = 13,
+    gdb_fs         = 14,
+    gdb_gs         = 15,
+    gdb_stmm0      = 16,
+    gdb_stmm1      = 17,
+    gdb_stmm2      = 18,
+    gdb_stmm3      = 19,
+    gdb_stmm4      = 20,
+    gdb_stmm5      = 21,
+    gdb_stmm6      = 22,
+    gdb_stmm7      = 23,
+    gdb_fcw        = 24,
+    gdb_fsw        = 25,
+    gdb_ftw        = 26,
+    gdb_fpu_cs     = 27,
+    gdb_ip         = 28,
+    gdb_fpu_ds     = 29,
+    gdb_dp         = 30,
+    gdb_fop        = 31,
+    gdb_xmm0       = 32,
+    gdb_xmm1       = 33,
+    gdb_xmm2       = 34,
+    gdb_xmm3       = 35,
+    gdb_xmm4       = 36,
+    gdb_xmm5       = 37,
+    gdb_xmm6       = 38,
+    gdb_xmm7       = 39,
+    gdb_mxcsr      = 40,
+    gdb_mm0        = 41,
+    gdb_mm1        = 42,
+    gdb_mm2        = 43,
+    gdb_mm3        = 44,
+    gdb_mm4        = 45,
+    gdb_mm5        = 46,
+    gdb_mm6        = 47,
+    gdb_mm7        = 48
+};
+
+static const
+uint32_t g_gpr_regnums[k_num_gpr_registers] =
+{
+    gpr_eax,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_eip,
+    gpr_eflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs,
+    gpr_ss,
+    gpr_ds,
+    gpr_es
+};
+
+static const uint32_t
+g_fpu_regnums[k_num_fpu_registers] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7
+};
+
+static const RegisterSet
+g_reg_sets[k_num_register_sets] =
+{
+    { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
+    { "Floating Point Registers",  "fpu", k_num_fpu_registers, g_fpu_regnums }
+};
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+    (offsetof(RegisterContextLinux_i386::UserArea, regs) + \
+     offsetof(RegisterContextLinux_i386::GPR, regname))
+
+// Computes the offset of the given FPR in the user data area.
+#define FPR_OFFSET(regname) \
+    (offsetof(RegisterContextLinux_i386::UserArea, i387) + \
+     offsetof(RegisterContextLinux_i386::FPU, regname))
+
+// Number of bytes needed to represent a GPR.
+#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg)
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg)
+
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)        \
+    { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)              \
+    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+      eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }
+
+#define DEFINE_FP(reg, i)                                          \
+    { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector,  \
+      eFormatVectorOfUInt8,                                        \
+      { dwarf_##reg##i, dwarf_##reg##i,                            \
+        LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }
+
+#define DEFINE_XMM(reg, i)                                         \
+    { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
+      eFormatVectorOfUInt8,                                        \
+      { dwarf_##reg##i, dwarf_##reg##i,                            \
+        LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } }
+
+static RegisterInfo
+g_register_infos[k_num_registers] =
+{
+    // General purpose registers.
+    DEFINE_GPR(eax,    NULL,    gcc_eax,    dwarf_eax,    LLDB_INVALID_REGNUM,    gdb_eax),
+    DEFINE_GPR(ebx,    NULL,    gcc_ebx,    dwarf_ebx,    LLDB_INVALID_REGNUM,    gdb_ebx),
+    DEFINE_GPR(ecx,    NULL,    gcc_ecx,    dwarf_ecx,    LLDB_INVALID_REGNUM,    gdb_ecx),
+    DEFINE_GPR(edx,    NULL,    gcc_edx,    dwarf_edx,    LLDB_INVALID_REGNUM,    gdb_edx),
+    DEFINE_GPR(edi,    NULL,    gcc_edi,    dwarf_edi,    LLDB_INVALID_REGNUM,    gdb_edi),
+    DEFINE_GPR(esi,    NULL,    gcc_esi,    dwarf_esi,    LLDB_INVALID_REGNUM,    gdb_esi),
+    DEFINE_GPR(ebp,    "fp",    gcc_ebp,    dwarf_ebp,    LLDB_INVALID_REGNUM,    gdb_ebp),
+    DEFINE_GPR(esp,    "sp",    gcc_esp,    dwarf_esp,    LLDB_INVALID_REGNUM,    gdb_esp),
+    DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ss),
+    DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM,    gdb_eflags),
+    DEFINE_GPR(eip,    "pc",    gcc_eip,    dwarf_eip,    LLDB_INVALID_REGNUM,    gdb_eip),
+    DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_cs),
+    DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ds),
+    DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_es),
+    DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_fs),
+    DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_gs),
+    
+    // Floating point registers.
+    DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
+    DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
+    DEFINE_FPR(ftw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
+    DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs),
+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds),
+    DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
+    DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+    
+    DEFINE_FP(stmm, 0),
+    DEFINE_FP(stmm, 1),
+    DEFINE_FP(stmm, 2),
+    DEFINE_FP(stmm, 3),
+    DEFINE_FP(stmm, 4),
+    DEFINE_FP(stmm, 5),
+    DEFINE_FP(stmm, 6),
+    DEFINE_FP(stmm, 7),
+
+    // XMM registers
+    DEFINE_XMM(xmm, 0),
+    DEFINE_XMM(xmm, 1),
+    DEFINE_XMM(xmm, 2),
+    DEFINE_XMM(xmm, 3),
+    DEFINE_XMM(xmm, 4),
+    DEFINE_XMM(xmm, 5),
+    DEFINE_XMM(xmm, 6),
+    DEFINE_XMM(xmm, 7),
+    
+};
+
+static unsigned GetRegOffset(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return g_register_infos[reg].byte_offset;
+}
+
+static unsigned GetRegSize(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return g_register_infos[reg].byte_size;
+}
+
+static bool IsGPR(unsigned reg)
+{
+    return reg <= k_last_gpr;   // GPR's come first.
+}
+
+static bool IsFPR(unsigned reg)
+{
+    return (k_first_fpr <= reg && reg <= k_last_fpr);
+}
+
+
+RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread,
+                                                     uint32_t concrete_frame_idx)
+    : RegisterContextLinux(thread, concrete_frame_idx)
+{
+}
+
+RegisterContextLinux_i386::~RegisterContextLinux_i386()
+{
+}
+
+ProcessMonitor &
+RegisterContextLinux_i386::GetMonitor()
+{
+    ProcessLinux *process = static_cast<ProcessLinux*>(CalculateProcess());
+    return process->GetMonitor();
+}
+
+void
+RegisterContextLinux_i386::Invalidate()
+{
+}
+
+void
+RegisterContextLinux_i386::InvalidateAllRegisters()
+{
+}
+
+size_t
+RegisterContextLinux_i386::GetRegisterCount()
+{
+    return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg)
+{
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    else
+        return NULL;
+}
+
+size_t
+RegisterContextLinux_i386::GetRegisterSetCount()
+{
+    return k_num_register_sets;
+}
+
+const RegisterSet *
+RegisterContextLinux_i386::GetRegisterSet(uint32_t set)
+{
+    if (set < k_num_register_sets)
+        return &g_reg_sets[set];
+    else
+        return NULL;
+}
+
+bool
+RegisterContextLinux_i386::ReadRegisterValue(uint32_t reg,
+                                               Scalar &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadRegisterValue(GetRegOffset(reg), value);
+}
+
+bool
+RegisterContextLinux_i386::ReadRegisterBytes(uint32_t reg,
+                                             DataExtractor &data)
+{
+    uint8_t *buf = reinterpret_cast<uint8_t*>(&user);
+    bool status;
+
+    if (IsGPR(reg))
+        status = ReadGPR();
+    else if (IsFPR(reg))
+        status = ReadFPR();
+    else 
+    {
+        assert(false && "invalid register number");
+        status = false;
+    }
+
+    if (status)
+        data.SetData(buf + GetRegOffset(reg), GetRegSize(reg), lldb::endian::InlHostByteOrder());
+
+    return status;
+}
+
+bool
+RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextLinux_i386::WriteRegisterValue(uint32_t reg,
+                                              const Scalar &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteRegisterValue(GetRegOffset(reg), value);
+}
+
+bool
+RegisterContextLinux_i386::WriteRegisterBytes(uint32_t reg,
+                                              DataExtractor &data,
+                                              uint32_t data_offset)
+{
+    return false;
+}
+
+bool
+RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data)
+{
+    return false;
+}
+
+bool
+RegisterContextLinux_i386::UpdateAfterBreakpoint()
+{
+    // PC points one byte past the int3 responsible for the breakpoint.
+    lldb::addr_t pc;
+
+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+        return false;
+
+    SetPC(pc - 1);
+    return true;
+}
+
+uint32_t
+RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+                                                               uint32_t num)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (num)
+        {
+        case LLDB_REGNUM_GENERIC_PC:    return gpr_eip;
+        case LLDB_REGNUM_GENERIC_SP:    return gpr_esp;
+        case LLDB_REGNUM_GENERIC_FP:    return gpr_ebp;
+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
+        case LLDB_REGNUM_GENERIC_RA:
+        default:
+            return LLDB_INVALID_REGNUM;
+        }
+    }
+
+    if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    {
+        switch (num)
+        {
+        case dwarf_eax:  return gpr_eax;
+        case dwarf_edx:  return gpr_edx;
+        case dwarf_ecx:  return gpr_ecx;
+        case dwarf_ebx:  return gpr_ebx;
+        case dwarf_esi:  return gpr_esi;
+        case dwarf_edi:  return gpr_edi;
+        case dwarf_ebp:  return gpr_ebp;
+        case dwarf_esp:  return gpr_esp;
+        case dwarf_eip:  return gpr_eip;
+        case dwarf_xmm0: return fpu_xmm0;
+        case dwarf_xmm1: return fpu_xmm1;
+        case dwarf_xmm2: return fpu_xmm2;
+        case dwarf_xmm3: return fpu_xmm3;
+        case dwarf_xmm4: return fpu_xmm4;
+        case dwarf_xmm5: return fpu_xmm5;
+        case dwarf_xmm6: return fpu_xmm6;
+        case dwarf_xmm7: return fpu_xmm7;
+        case dwarf_stmm0: return fpu_stmm0;
+        case dwarf_stmm1: return fpu_stmm1;
+        case dwarf_stmm2: return fpu_stmm2;
+        case dwarf_stmm3: return fpu_stmm3;
+        case dwarf_stmm4: return fpu_stmm4;
+        case dwarf_stmm5: return fpu_stmm5;
+        case dwarf_stmm6: return fpu_stmm6;
+        case dwarf_stmm7: return fpu_stmm7;
+        default:
+            return LLDB_INVALID_REGNUM;
+        }
+    }
+
+    if (kind == eRegisterKindGDB)
+    {
+        switch (num)
+        {
+        case gdb_eax     : return gpr_eax;
+        case gdb_ebx     : return gpr_ebx;
+        case gdb_ecx     : return gpr_ecx;
+        case gdb_edx     : return gpr_edx;
+        case gdb_esi     : return gpr_esi;
+        case gdb_edi     : return gpr_edi;
+        case gdb_ebp     : return gpr_ebp;
+        case gdb_esp     : return gpr_esp;
+        case gdb_eip     : return gpr_eip;
+        case gdb_eflags  : return gpr_eflags;
+        case gdb_cs      : return gpr_cs;
+        case gdb_ss      : return gpr_ss;
+        case gdb_ds      : return gpr_ds;
+        case gdb_es      : return gpr_es;
+        case gdb_fs      : return gpr_fs;
+        case gdb_gs      : return gpr_gs;
+        case gdb_stmm0   : return fpu_stmm0;
+        case gdb_stmm1   : return fpu_stmm1;
+        case gdb_stmm2   : return fpu_stmm2;
+        case gdb_stmm3   : return fpu_stmm3;
+        case gdb_stmm4   : return fpu_stmm4;
+        case gdb_stmm5   : return fpu_stmm5;
+        case gdb_stmm6   : return fpu_stmm6;
+        case gdb_stmm7   : return fpu_stmm7;
+        case gdb_fcw     : return fpu_fcw;
+        case gdb_fsw     : return fpu_fsw;
+        case gdb_ftw     : return fpu_ftw;
+        case gdb_fpu_cs  : return fpu_cs;
+        case gdb_ip      : return fpu_ip;
+        case gdb_fpu_ds  : return fpu_ds;
+        case gdb_dp      : return fpu_dp;
+        case gdb_fop     : return fpu_fop;
+        case gdb_xmm0    : return fpu_xmm0;
+        case gdb_xmm1    : return fpu_xmm1;
+        case gdb_xmm2    : return fpu_xmm2;
+        case gdb_xmm3    : return fpu_xmm3;
+        case gdb_xmm4    : return fpu_xmm4;
+        case gdb_xmm5    : return fpu_xmm5;
+        case gdb_xmm6    : return fpu_xmm6;
+        case gdb_xmm7    : return fpu_xmm7;
+        case gdb_mxcsr   : return fpu_mxcsr;
+        default:
+            return LLDB_INVALID_REGNUM;
+        }
+    }
+    else if (kind == eRegisterKindLLDB)
+    {
+        return num;
+    }
+
+    return LLDB_INVALID_REGNUM;
+}
+
+bool
+RegisterContextLinux_i386::HardwareSingleStep(bool enable)
+{
+    enum { TRACE_BIT = 0x100 };
+    uint64_t eflags;
+
+    if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
+        return false;
+    
+    if (enable)
+    {
+        if (eflags & TRACE_BIT)
+            return true;
+
+        eflags |= TRACE_BIT;
+    }
+    else
+    {
+        if (!(eflags & TRACE_BIT))
+            return false;
+
+        eflags &= ~TRACE_BIT;
+    }
+
+    return WriteRegisterFromUnsigned(gpr_eflags, eflags);
+}
+
+bool
+RegisterContextLinux_i386::ReadGPR()
+{
+     ProcessMonitor &monitor = GetMonitor();
+     return monitor.ReadGPR(&user.regs);
+}
+
+bool
+RegisterContextLinux_i386::ReadFPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadFPR(&user.i387);
+}
Index: source/Plugins/Process/Linux/LinuxThread.cpp
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.cpp	(revision 126320)
+++ source/Plugins/Process/Linux/LinuxThread.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include "LinuxThread.h"
 #include "ProcessLinux.h"
 #include "ProcessMonitor.h"
+#include "RegisterContextLinux_i386.h"
 #include "RegisterContextLinux_x86_64.h"
 #include "UnwindLLDB.h"
 
@@ -71,6 +72,10 @@
             assert(false && "CPU type not supported!");
             break;
 
+        case ArchSpec::eCPU_i386:
+            m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0));
+            break;
+
         case ArchSpec::eCPU_x86_64:
             m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
             break;
Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h
===================================================================
--- source/Plugins/Process/Linux/RegisterContextLinux_i386.h	(revision 0)
+++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h	(revision 0)
@@ -0,0 +1,157 @@
+//===-- RegisterContextLinux_i386.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextLinux_i386_h_
+#define liblldb_RegisterContextLinux_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextLinux.h"
+
+class RegisterContextLinux_i386 : public RegisterContextLinux
+{
+public:
+    RegisterContextLinux_i386(lldb_private::Thread &thread,
+                              uint32_t concreate_frame_idx);
+
+    ~RegisterContextLinux_i386();
+
+    void
+    Invalidate();
+
+    void
+    InvalidateAllRegisters();
+
+    size_t
+    GetRegisterCount();
+
+    const lldb::RegisterInfo *
+    GetRegisterInfoAtIndex(uint32_t reg);
+
+    size_t
+    GetRegisterSetCount();
+
+    const lldb::RegisterSet *
+    GetRegisterSet(uint32_t set);
+
+    bool
+    ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
+
+    bool
+    ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    bool
+    WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);
+
+    bool
+    WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,
+                       uint32_t data_offset = 0);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+    bool
+    UpdateAfterBreakpoint();
+
+    struct GPR
+    {
+        uint32_t eax;
+        uint32_t ebx;
+        uint32_t ecx;
+        uint32_t edx;
+        uint32_t edi;
+        uint32_t esi;
+        uint32_t ebp;
+        uint32_t esp;
+        uint32_t ss;
+        uint32_t eflags;
+        uint32_t eip;
+        uint32_t cs;
+        uint32_t ds;
+        uint32_t es;
+        uint32_t fs;
+        uint32_t gs;
+    };
+
+    struct MMSReg
+    {
+        uint8_t bytes[10];
+        uint8_t pad[6];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        uint32_t    pad[2];
+        uint16_t    fcw;
+        uint16_t    fsw;
+        uint8_t     ftw;
+        uint8_t     pad1;
+        uint16_t    fop;
+        uint32_t    ip;
+        uint16_t    cs;
+        uint16_t    pad2;
+        uint32_t    dp;
+        uint16_t    ds;
+        uint16_t    pad3;
+        uint32_t    mxcsr;
+        uint32_t    mxcsrmask;
+        MMSReg      stmm[8];
+        XMMReg      xmm[8];
+        uint8_t     pad4[14*16];
+        int         pad5;
+    };
+
+    struct UserArea
+    {
+        GPR      regs;          // General purpose registers.
+        int32_t  fpvalid;       // True if FPU is being used.
+        int32_t  pad0;
+        FPU      i387;          // FPU registers.
+        uint32_t tsize;         // Text segment size.
+        uint32_t dsize;         // Data segment size.
+        uint32_t ssize;         // Stack segment size.
+        uint32_t start_code;    // VM address of text.
+        uint32_t start_stack;   // VM address of stack bottom (top in rsp).
+        int32_t  signal;        // Signal causing core dump.
+        int32_t  reserved;      // Unused.
+        int32_t  pad1;
+        uint32_t ar0;           // Location of GPR's.
+        FPU*     fpstate;       // Location of FPR's.
+        uint32_t magic;         // Identifier for core dumps.
+        char     u_comm[32];    // Command causing core dump.
+        uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+        uint32_t error_code;    // CPU error code.
+        uint32_t fault_address; // Control register CR3.
+    };
+private:
+    UserArea user;
+
+    ProcessMonitor &GetMonitor();
+
+    bool ReadGPR();
+    bool ReadFPR();
+};
+
+#endif // #ifndef liblldb_RegisterContextLinux_i386_h_
_______________________________________________
lldb-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to