diff options
| author | Stephen Wilson <wilsons@start.ca> | 2011-02-28 22:52:38 +0000 |
|---|---|---|
| committer | Stephen Wilson <wilsons@start.ca> | 2011-02-28 22:52:38 +0000 |
| commit | bbb7e06ad3cef702a2afc1bff72be816f90136ab (patch) | |
| tree | 9335514b6ef9956590045b46620c56395fa72835 /lldb/source/Plugins | |
| parent | 1ac5e0c5c6d5cd5a622eafb633a80507fc7c9cd3 (diff) | |
| download | bcm5719-llvm-bbb7e06ad3cef702a2afc1bff72be816f90136ab.tar.gz bcm5719-llvm-bbb7e06ad3cef702a2afc1bff72be816f90136ab.zip | |
Add register context for i386 on Linux.
Patch by Marco Minutoli!
llvm-svn: 126696
Diffstat (limited to 'lldb/source/Plugins')
3 files changed, 791 insertions, 4 deletions
diff --git a/lldb/source/Plugins/Process/Linux/LinuxThread.cpp b/lldb/source/Plugins/Process/Linux/LinuxThread.cpp index 397d31bf497..ebda0d8965c 100644 --- a/lldb/source/Plugins/Process/Linux/LinuxThread.cpp +++ b/lldb/source/Plugins/Process/Linux/LinuxThread.cpp @@ -12,6 +12,7 @@ // C++ Includes // Other libraries and framework includes +#include "lldb/Host/Host.h" #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" @@ -19,6 +20,7 @@ #include "LinuxThread.h" #include "ProcessLinux.h" #include "ProcessMonitor.h" +#include "RegisterContextLinux_i386.h" #include "RegisterContextLinux_x86_64.h" #include "UnwindLLDB.h" @@ -59,11 +61,9 @@ LinuxThread::GetInfo() lldb::RegisterContextSP LinuxThread::GetRegisterContext() { - ProcessLinux &process = static_cast<ProcessLinux&>(GetProcess()); - if (!m_reg_context_sp) { - ArchSpec arch = process.GetTarget().GetArchitecture(); + ArchSpec arch = Host::GetArchitecture(); switch (arch.GetCore()) { @@ -71,6 +71,12 @@ LinuxThread::GetRegisterContext() 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: + m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); + break; + case ArchSpec::eCore_x86_64_x86_64: m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); break; @@ -99,7 +105,7 @@ LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) if (frame) concrete_frame_idx = frame->GetConcreteFrameIndex(); - + if (concrete_frame_idx == 0) reg_ctx_sp = GetRegisterContext(); else diff --git a/lldb/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp b/lldb/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp new file mode 100644 index 00000000000..6bee0c90906 --- /dev/null +++ b/lldb/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp @@ -0,0 +1,633 @@ +//===-- 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_orig_ax, + 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_foo, + fpu_fos, + fpu_mxcsr, + 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_ss, + gpr_eflags, + gpr_orig_ax, + gpr_eip, + gpr_cs, + gpr_ds, + gpr_es, + gpr_fs, + gpr_gs, +}; + +static const uint32_t +g_fpu_regnums[k_num_fpu_registers] = +{ + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_foo, + fpu_fos, + fpu_mxcsr, + 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(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), + DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), + DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), + + 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_fos; + case gdb_dp : return fpu_foo; + 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); +} diff --git a/lldb/source/Plugins/Process/Linux/RegisterContextLinux_i386.h b/lldb/source/Plugins/Process/Linux/RegisterContextLinux_i386.h new file mode 100644 index 00000000000..30b3d7073c1 --- /dev/null +++ b/lldb/source/Plugins/Process/Linux/RegisterContextLinux_i386.h @@ -0,0 +1,148 @@ +//===-- 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 ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + uint32_t orig_ax; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; + }; + + struct MMSReg + { + uint8_t bytes[8]; + }; + + struct XMMReg + { + uint8_t bytes[16]; + }; + + struct FPU + { + uint16_t fcw; + uint16_t fsw; + uint16_t ftw; + uint16_t fop; + uint32_t ip; + uint32_t cs; + uint32_t foo; + uint32_t fos; + uint32_t mxcsr; + uint32_t reserved; + MMSReg stmm[8]; + XMMReg xmm[8]; + uint32_t pad[56]; + }; + + struct UserArea + { + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + 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. + 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). + }; +private: + UserArea user; + + ProcessMonitor &GetMonitor(); + + bool ReadGPR(); + bool ReadFPR(); +}; + +#endif // #ifndef liblldb_RegisterContextLinux_i386_h_ |

