Home | History | Annotate | Download | only in POSIX
      1 //===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Core/DataExtractor.h"
     11 #include "lldb/Target/Thread.h"
     12 #include "lldb/Host/Endian.h"
     13 #include "llvm/Support/Compiler.h"
     14 
     15 #include "ProcessPOSIX.h"
     16 #include "ProcessPOSIXLog.h"
     17 #include "ProcessMonitor.h"
     18 #include "RegisterContext_i386.h"
     19 #include "RegisterContext_x86.h"
     20 
     21 using namespace lldb_private;
     22 using namespace lldb;
     23 
     24 enum
     25 {
     26     k_first_gpr,
     27     gpr_eax = k_first_gpr,
     28     gpr_ebx,
     29     gpr_ecx,
     30     gpr_edx,
     31     gpr_edi,
     32     gpr_esi,
     33     gpr_ebp,
     34     gpr_esp,
     35     gpr_ss,
     36     gpr_eflags,
     37 #ifdef __FreeBSD__
     38     gpr_orig_ax,
     39 #endif
     40     gpr_eip,
     41     gpr_cs,
     42     gpr_ds,
     43     gpr_es,
     44     gpr_fs,
     45     gpr_gs,
     46     k_last_gpr = gpr_gs,
     47 
     48     k_first_fpr,
     49     fpu_fcw = k_first_fpr,
     50     fpu_fsw,
     51     fpu_ftw,
     52     fpu_fop,
     53     fpu_ip,
     54     fpu_cs,
     55     fpu_foo,
     56     fpu_fos,
     57     fpu_mxcsr,
     58     fpu_stmm0,
     59     fpu_stmm1,
     60     fpu_stmm2,
     61     fpu_stmm3,
     62     fpu_stmm4,
     63     fpu_stmm5,
     64     fpu_stmm6,
     65     fpu_stmm7,
     66     fpu_xmm0,
     67     fpu_xmm1,
     68     fpu_xmm2,
     69     fpu_xmm3,
     70     fpu_xmm4,
     71     fpu_xmm5,
     72     fpu_xmm6,
     73     fpu_xmm7,
     74     k_last_fpr = fpu_xmm7,
     75 
     76     k_num_registers,
     77     k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
     78     k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
     79 };
     80 
     81 // Number of register sets provided by this context.
     82 enum
     83 {
     84     k_num_register_sets = 2
     85 };
     86 
     87 static const
     88 uint32_t g_gpr_regnums[k_num_gpr_registers] =
     89 {
     90     gpr_eax,
     91     gpr_ebx,
     92     gpr_ecx,
     93     gpr_edx,
     94     gpr_edi,
     95     gpr_esi,
     96     gpr_ebp,
     97     gpr_esp,
     98     gpr_ss,
     99     gpr_eflags,
    100 #ifdef __FreeBSD__
    101     gpr_orig_ax,
    102 #endif
    103     gpr_eip,
    104     gpr_cs,
    105     gpr_ds,
    106     gpr_es,
    107     gpr_fs,
    108     gpr_gs,
    109 };
    110 
    111 static const uint32_t
    112 g_fpu_regnums[k_num_fpu_registers] =
    113 {
    114     fpu_fcw,
    115     fpu_fsw,
    116     fpu_ftw,
    117     fpu_fop,
    118     fpu_ip,
    119     fpu_cs,
    120     fpu_foo,
    121     fpu_fos,
    122     fpu_mxcsr,
    123     fpu_stmm0,
    124     fpu_stmm1,
    125     fpu_stmm2,
    126     fpu_stmm3,
    127     fpu_stmm4,
    128     fpu_stmm5,
    129     fpu_stmm6,
    130     fpu_stmm7,
    131     fpu_xmm0,
    132     fpu_xmm1,
    133     fpu_xmm2,
    134     fpu_xmm3,
    135     fpu_xmm4,
    136     fpu_xmm5,
    137     fpu_xmm6,
    138     fpu_xmm7,
    139 };
    140 
    141 static const RegisterSet
    142 g_reg_sets[k_num_register_sets] =
    143 {
    144     { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
    145     { "Floating Point Registers",  "fpu", k_num_fpu_registers, g_fpu_regnums }
    146 };
    147 
    148 // Computes the offset of the given GPR in the user data area.
    149 #define GPR_OFFSET(regname) \
    150     (offsetof(RegisterContext_i386::UserArea, regs) + \
    151      offsetof(RegisterContext_i386::GPR, regname))
    152 
    153 // Computes the offset of the given FPR in the user data area.
    154 #define FPR_OFFSET(regname) \
    155     (offsetof(RegisterContext_i386::UserArea, i387) + \
    156      offsetof(RegisterContext_i386::FPU, regname))
    157 
    158 // Number of bytes needed to represent a GPR.
    159 #define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
    160 
    161 // Number of bytes needed to represent a FPR.
    162 #define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg)
    163 
    164 // Number of bytes needed to represent the i'th FP register.
    165 #define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes)
    166 
    167 // Number of bytes needed to represent an XMM register.
    168 #define XMM_SIZE sizeof(RegisterContext_i386::XMMReg)
    169 
    170 #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)        \
    171     { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
    172       eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
    173 
    174 #define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)              \
    175     { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
    176       eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
    177 
    178 #define DEFINE_FP(reg, i)                                          \
    179     { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),    \
    180       eEncodingVector, eFormatVectorOfUInt8,                       \
    181       { dwarf_##reg##i, dwarf_##reg##i,                            \
    182         LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
    183 
    184 #define DEFINE_XMM(reg, i)                                         \
    185     { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),   \
    186        eEncodingVector, eFormatVectorOfUInt8,                      \
    187       { dwarf_##reg##i, dwarf_##reg##i,                            \
    188         LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
    189 
    190 static RegisterInfo
    191 g_register_infos[k_num_registers] =
    192 {
    193     // General purpose registers.
    194     DEFINE_GPR(eax,    NULL,    gcc_eax,    dwarf_eax,    LLDB_INVALID_REGNUM,    gdb_eax),
    195     DEFINE_GPR(ebx,    NULL,    gcc_ebx,    dwarf_ebx,    LLDB_INVALID_REGNUM,    gdb_ebx),
    196     DEFINE_GPR(ecx,    NULL,    gcc_ecx,    dwarf_ecx,    LLDB_INVALID_REGNUM,    gdb_ecx),
    197     DEFINE_GPR(edx,    NULL,    gcc_edx,    dwarf_edx,    LLDB_INVALID_REGNUM,    gdb_edx),
    198     DEFINE_GPR(edi,    NULL,    gcc_edi,    dwarf_edi,    LLDB_INVALID_REGNUM,    gdb_edi),
    199     DEFINE_GPR(esi,    NULL,    gcc_esi,    dwarf_esi,    LLDB_INVALID_REGNUM,    gdb_esi),
    200     DEFINE_GPR(ebp,    "fp",    gcc_ebp,    dwarf_ebp,    LLDB_INVALID_REGNUM,    gdb_ebp),
    201     DEFINE_GPR(esp,    "sp",    gcc_esp,    dwarf_esp,    LLDB_INVALID_REGNUM,    gdb_esp),
    202     DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ss),
    203     DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM,    gdb_eflags),
    204     DEFINE_GPR(eip,    "pc",    gcc_eip,    dwarf_eip,    LLDB_INVALID_REGNUM,    gdb_eip),
    205     DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_cs),
    206     DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ds),
    207     DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_es),
    208     DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_fs),
    209     DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_gs),
    210 
    211     // Floating point registers.
    212     DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
    213     DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
    214     DEFINE_FPR(ftw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
    215     DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
    216     DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
    217     DEFINE_FPR(cs,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
    218     DEFINE_FPR(foo,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
    219     DEFINE_FPR(fos,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
    220     DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
    221 
    222     DEFINE_FP(stmm, 0),
    223     DEFINE_FP(stmm, 1),
    224     DEFINE_FP(stmm, 2),
    225     DEFINE_FP(stmm, 3),
    226     DEFINE_FP(stmm, 4),
    227     DEFINE_FP(stmm, 5),
    228     DEFINE_FP(stmm, 6),
    229     DEFINE_FP(stmm, 7),
    230 
    231     // XMM registers
    232     DEFINE_XMM(xmm, 0),
    233     DEFINE_XMM(xmm, 1),
    234     DEFINE_XMM(xmm, 2),
    235     DEFINE_XMM(xmm, 3),
    236     DEFINE_XMM(xmm, 4),
    237     DEFINE_XMM(xmm, 5),
    238     DEFINE_XMM(xmm, 6),
    239     DEFINE_XMM(xmm, 7),
    240 
    241 };
    242 
    243 #ifndef NDEBUG
    244 static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
    245 #endif
    246 
    247 static unsigned GetRegOffset(unsigned reg)
    248 {
    249     assert(reg < k_num_registers && "Invalid register number.");
    250     return g_register_infos[reg].byte_offset;
    251 }
    252 
    253 static unsigned GetRegSize(unsigned reg)
    254 {
    255     assert(reg < k_num_registers && "Invalid register number.");
    256     return g_register_infos[reg].byte_size;
    257 }
    258 
    259 RegisterContext_i386::RegisterContext_i386(Thread &thread,
    260                                                      uint32_t concrete_frame_idx)
    261     : RegisterContextPOSIX(thread, concrete_frame_idx)
    262 {
    263 }
    264 
    265 RegisterContext_i386::~RegisterContext_i386()
    266 {
    267 }
    268 
    269 ProcessMonitor &
    270 RegisterContext_i386::GetMonitor()
    271 {
    272     ProcessSP base = CalculateProcess();
    273     ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
    274     return process->GetMonitor();
    275 }
    276 
    277 void
    278 RegisterContext_i386::Invalidate()
    279 {
    280 }
    281 
    282 void
    283 RegisterContext_i386::InvalidateAllRegisters()
    284 {
    285 }
    286 
    287 size_t
    288 RegisterContext_i386::GetRegisterCount()
    289 {
    290     assert(k_num_register_infos == k_num_registers);
    291     return k_num_registers;
    292 }
    293 
    294 const RegisterInfo *
    295 RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg)
    296 {
    297     assert(k_num_register_infos == k_num_registers);
    298     if (reg < k_num_registers)
    299         return &g_register_infos[reg];
    300     else
    301         return NULL;
    302 }
    303 
    304 size_t
    305 RegisterContext_i386::GetRegisterSetCount()
    306 {
    307     return k_num_register_sets;
    308 }
    309 
    310 const RegisterSet *
    311 RegisterContext_i386::GetRegisterSet(size_t set)
    312 {
    313     if (set < k_num_register_sets)
    314         return &g_reg_sets[set];
    315     else
    316         return NULL;
    317 }
    318 
    319 unsigned
    320 RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset)
    321 {
    322     unsigned reg;
    323     for (reg = 0; reg < k_num_registers; reg++)
    324     {
    325         if (g_register_infos[reg].byte_offset == offset)
    326             break;
    327     }
    328     assert(reg < k_num_registers && "Invalid register offset.");
    329     return reg;
    330 }
    331 
    332 const char *
    333 RegisterContext_i386::GetRegisterName(unsigned reg)
    334 {
    335     assert(reg < k_num_registers && "Invalid register offset.");
    336     return g_register_infos[reg].name;
    337 }
    338 
    339 bool
    340 RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info,
    341                                         RegisterValue &value)
    342 {
    343     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
    344     ProcessMonitor &monitor = GetMonitor();
    345     return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg),
    346                                      GetRegisterName(reg), GetRegSize(reg), value);
    347 }
    348 
    349 bool
    350 RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
    351 {
    352     return false;
    353 }
    354 
    355 bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
    356                                          const RegisterValue &value)
    357 {
    358     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
    359     ProcessMonitor &monitor = GetMonitor();
    360     return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg),
    361                                       GetRegisterName(reg), value);
    362 }
    363 
    364 bool
    365 RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data)
    366 {
    367     return false;
    368 }
    369 
    370 bool
    371 RegisterContext_i386::UpdateAfterBreakpoint()
    372 {
    373     // PC points one byte past the int3 responsible for the breakpoint.
    374     lldb::addr_t pc;
    375 
    376     if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
    377         return false;
    378 
    379     SetPC(pc - 1);
    380     return true;
    381 }
    382 
    383 uint32_t
    384 RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
    385                                                                uint32_t num)
    386 {
    387     if (kind == eRegisterKindGeneric)
    388     {
    389         switch (num)
    390         {
    391         case LLDB_REGNUM_GENERIC_PC:    return gpr_eip;
    392         case LLDB_REGNUM_GENERIC_SP:    return gpr_esp;
    393         case LLDB_REGNUM_GENERIC_FP:    return gpr_ebp;
    394         case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
    395         case LLDB_REGNUM_GENERIC_RA:
    396         default:
    397             return LLDB_INVALID_REGNUM;
    398         }
    399     }
    400 
    401     if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
    402     {
    403         switch (num)
    404         {
    405         case dwarf_eax:  return gpr_eax;
    406         case dwarf_edx:  return gpr_edx;
    407         case dwarf_ecx:  return gpr_ecx;
    408         case dwarf_ebx:  return gpr_ebx;
    409         case dwarf_esi:  return gpr_esi;
    410         case dwarf_edi:  return gpr_edi;
    411         case dwarf_ebp:  return gpr_ebp;
    412         case dwarf_esp:  return gpr_esp;
    413         case dwarf_eip:  return gpr_eip;
    414         case dwarf_xmm0: return fpu_xmm0;
    415         case dwarf_xmm1: return fpu_xmm1;
    416         case dwarf_xmm2: return fpu_xmm2;
    417         case dwarf_xmm3: return fpu_xmm3;
    418         case dwarf_xmm4: return fpu_xmm4;
    419         case dwarf_xmm5: return fpu_xmm5;
    420         case dwarf_xmm6: return fpu_xmm6;
    421         case dwarf_xmm7: return fpu_xmm7;
    422         case dwarf_stmm0: return fpu_stmm0;
    423         case dwarf_stmm1: return fpu_stmm1;
    424         case dwarf_stmm2: return fpu_stmm2;
    425         case dwarf_stmm3: return fpu_stmm3;
    426         case dwarf_stmm4: return fpu_stmm4;
    427         case dwarf_stmm5: return fpu_stmm5;
    428         case dwarf_stmm6: return fpu_stmm6;
    429         case dwarf_stmm7: return fpu_stmm7;
    430         default:
    431             return LLDB_INVALID_REGNUM;
    432         }
    433     }
    434 
    435     if (kind == eRegisterKindGDB)
    436     {
    437         switch (num)
    438         {
    439         case gdb_eax     : return gpr_eax;
    440         case gdb_ebx     : return gpr_ebx;
    441         case gdb_ecx     : return gpr_ecx;
    442         case gdb_edx     : return gpr_edx;
    443         case gdb_esi     : return gpr_esi;
    444         case gdb_edi     : return gpr_edi;
    445         case gdb_ebp     : return gpr_ebp;
    446         case gdb_esp     : return gpr_esp;
    447         case gdb_eip     : return gpr_eip;
    448         case gdb_eflags  : return gpr_eflags;
    449         case gdb_cs      : return gpr_cs;
    450         case gdb_ss      : return gpr_ss;
    451         case gdb_ds      : return gpr_ds;
    452         case gdb_es      : return gpr_es;
    453         case gdb_fs      : return gpr_fs;
    454         case gdb_gs      : return gpr_gs;
    455         case gdb_stmm0   : return fpu_stmm0;
    456         case gdb_stmm1   : return fpu_stmm1;
    457         case gdb_stmm2   : return fpu_stmm2;
    458         case gdb_stmm3   : return fpu_stmm3;
    459         case gdb_stmm4   : return fpu_stmm4;
    460         case gdb_stmm5   : return fpu_stmm5;
    461         case gdb_stmm6   : return fpu_stmm6;
    462         case gdb_stmm7   : return fpu_stmm7;
    463         case gdb_fcw     : return fpu_fcw;
    464         case gdb_fsw     : return fpu_fsw;
    465         case gdb_ftw     : return fpu_ftw;
    466         case gdb_fpu_cs  : return fpu_cs;
    467         case gdb_ip      : return fpu_ip;
    468         case gdb_fpu_ds  : return fpu_fos;
    469         case gdb_dp      : return fpu_foo;
    470         case gdb_fop     : return fpu_fop;
    471         case gdb_xmm0    : return fpu_xmm0;
    472         case gdb_xmm1    : return fpu_xmm1;
    473         case gdb_xmm2    : return fpu_xmm2;
    474         case gdb_xmm3    : return fpu_xmm3;
    475         case gdb_xmm4    : return fpu_xmm4;
    476         case gdb_xmm5    : return fpu_xmm5;
    477         case gdb_xmm6    : return fpu_xmm6;
    478         case gdb_xmm7    : return fpu_xmm7;
    479         case gdb_mxcsr   : return fpu_mxcsr;
    480         default:
    481             return LLDB_INVALID_REGNUM;
    482         }
    483     }
    484     else if (kind == eRegisterKindLLDB)
    485     {
    486         return num;
    487     }
    488 
    489     return LLDB_INVALID_REGNUM;
    490 }
    491 
    492 bool
    493 RegisterContext_i386::HardwareSingleStep(bool enable)
    494 {
    495     enum { TRACE_BIT = 0x100 };
    496     uint64_t eflags;
    497 
    498     if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
    499         return false;
    500 
    501     if (enable)
    502     {
    503         if (eflags & TRACE_BIT)
    504             return true;
    505 
    506         eflags |= TRACE_BIT;
    507     }
    508     else
    509     {
    510         if (!(eflags & TRACE_BIT))
    511             return false;
    512 
    513         eflags &= ~TRACE_BIT;
    514     }
    515 
    516     return WriteRegisterFromUnsigned(gpr_eflags, eflags);
    517 }
    518 
    519 void
    520 RegisterContext_i386::LogGPR(const char *title)
    521 {
    522     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
    523     if (log)
    524     {
    525         if (title)
    526             log->Printf ("%s", title);
    527         for (uint32_t i=0; i<k_num_gpr_registers; i++)
    528         {
    529             uint32_t reg = gpr_eax + i;
    530             log->Printf("%12s = 0x%8.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]);
    531         }
    532     }
    533 }
    534 
    535 bool
    536 RegisterContext_i386::ReadGPR()
    537 {
    538     bool result;
    539 
    540     ProcessMonitor &monitor = GetMonitor();
    541     result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs));
    542     LogGPR("RegisterContext_i386::ReadGPR()");
    543     return result;
    544 }
    545 
    546 bool
    547 RegisterContext_i386::ReadFPR()
    548 {
    549     ProcessMonitor &monitor = GetMonitor();
    550     return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387));
    551 }
    552