1 //===-- RegisterContextWindows_x86.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/lldb-private-types.h"
11 #include "lldb/Core/Error.h"
12 #include "lldb/Core/RegisterValue.h"
13 #include "lldb/Host/windows/HostThreadWindows.h"
14 #include "lldb/Host/windows/windows.h"
15 
16 #include "lldb-x86-register-enums.h"
17 #include "ProcessWindowsLog.h"
18 #include "RegisterContext_x86.h"
19 #include "RegisterContextWindows_x86.h"
20 
21 #include "llvm/ADT/STLExtras.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 #define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase
27 #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary
28 
29 namespace
30 {
31 
32 // This enum defines the layout of the global RegisterInfo array.  This is necessary because
33 // lldb register sets are defined in terms of indices into the register array.  As such, the
34 // order of RegisterInfos defined in global registers array must match the order defined here.
35 // When defining the register set layouts, these values can appear in an arbitrary order, and that
36 // determines the order that register values are displayed in a dump.
37 enum RegisterIndex
38 {
39     eRegisterIndexEax,
40     eRegisterIndexEbx,
41     eRegisterIndexEcx,
42     eRegisterIndexEdx,
43     eRegisterIndexEdi,
44     eRegisterIndexEsi,
45     eRegisterIndexEbp,
46     eRegisterIndexEsp,
47     eRegisterIndexEip,
48     eRegisterIndexEflags
49 };
50 
51 // Array of all register information supported by Windows x86
52 RegisterInfo g_register_infos[] =
53 {
54 //  Macro auto defines most stuff   eh_frame                DWARF                GENERIC                    GDB                   LLDB               VALUE REGS    INVALIDATE REGS
55 //  ==============================  ======================= ===================  =========================  ===================   =================  ==========    ===============
56     { DEFINE_GPR(eax,    nullptr),  { ehframe_eax_i386,     dwarf_eax_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM,  lldb_eax_i386   },  nullptr,      nullptr},
57     { DEFINE_GPR(ebx,    nullptr),  { ehframe_ebx_i386,     dwarf_ebx_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM,  lldb_ebx_i386   },  nullptr,      nullptr},
58     { DEFINE_GPR(ecx,    nullptr),  { ehframe_ecx_i386,     dwarf_ecx_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM,  lldb_ecx_i386   },  nullptr,      nullptr},
59     { DEFINE_GPR(edx,    nullptr),  { ehframe_edx_i386,     dwarf_edx_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM,  lldb_edx_i386   },  nullptr,      nullptr},
60     { DEFINE_GPR(edi,    nullptr),  { ehframe_edi_i386,     dwarf_edi_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM,  lldb_edi_i386   },  nullptr,      nullptr},
61     { DEFINE_GPR(esi,    nullptr),  { ehframe_esi_i386,     dwarf_esi_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM,  lldb_esi_i386   },  nullptr,      nullptr},
62     { DEFINE_GPR(ebp,    "fp"),     { ehframe_ebp_i386,     dwarf_ebp_i386,      LLDB_REGNUM_GENERIC_FP,    LLDB_INVALID_REGNUM,  lldb_ebp_i386   },  nullptr,      nullptr},
63     { DEFINE_GPR(esp,    "sp"),     { ehframe_esp_i386,     dwarf_esp_i386,      LLDB_REGNUM_GENERIC_SP,    LLDB_INVALID_REGNUM,  lldb_esp_i386   },  nullptr,      nullptr},
64     { DEFINE_GPR(eip,    "pc"),     { ehframe_eip_i386,     dwarf_eip_i386,      LLDB_REGNUM_GENERIC_PC,    LLDB_INVALID_REGNUM,  lldb_eip_i386   },  nullptr,      nullptr},
65     { DEFINE_GPR_BIN(eflags, "flags"), { ehframe_eflags_i386, dwarf_eflags_i386,   LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,  lldb_eflags_i386},  nullptr,      nullptr},
66 };
67 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
68 
69 // Array of lldb register numbers used to define the set of all General Purpose Registers
70 uint32_t g_gpr_reg_indices[] =
71 {
72     eRegisterIndexEax,
73     eRegisterIndexEbx,
74     eRegisterIndexEcx,
75     eRegisterIndexEdx,
76     eRegisterIndexEdi,
77     eRegisterIndexEsi,
78     eRegisterIndexEbp,
79     eRegisterIndexEsp,
80     eRegisterIndexEip,
81     eRegisterIndexEflags
82 };
83 
84 RegisterSet g_register_sets[] = {
85     {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
86 };
87 }
88 
89 //------------------------------------------------------------------
90 // Constructors and Destructors
91 //------------------------------------------------------------------
92 RegisterContextWindows_x86::RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx)
93     : RegisterContextWindows(thread, concrete_frame_idx)
94 {
95 }
96 
97 RegisterContextWindows_x86::~RegisterContextWindows_x86()
98 {
99 }
100 
101 size_t
102 RegisterContextWindows_x86::GetRegisterCount()
103 {
104     return llvm::array_lengthof(g_register_infos);
105 }
106 
107 const RegisterInfo *
108 RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg)
109 {
110     if (reg < k_num_register_infos)
111         return &g_register_infos[reg];
112     return NULL;
113 }
114 
115 size_t
116 RegisterContextWindows_x86::GetRegisterSetCount()
117 {
118     return llvm::array_lengthof(g_register_sets);
119 }
120 
121 const RegisterSet *
122 RegisterContextWindows_x86::GetRegisterSet(size_t reg_set)
123 {
124     return &g_register_sets[reg_set];
125 }
126 
127 bool
128 RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
129 {
130     if (!CacheAllRegisterValues())
131         return false;
132 
133     uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
134     switch (reg)
135     {
136         case lldb_eax_i386:
137             return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value);
138         case lldb_ebx_i386:
139             return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value);
140         case lldb_ecx_i386:
141             return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value);
142         case lldb_edx_i386:
143             return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value);
144         case lldb_edi_i386:
145             return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value);
146         case lldb_esi_i386:
147             return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value);
148         case lldb_ebp_i386:
149             return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value);
150         case lldb_esp_i386:
151             return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value);
152         case lldb_eip_i386:
153             return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value);
154         case lldb_eflags_i386:
155             return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, reg_value);
156         default:
157             WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg);
158             break;
159     }
160     return false;
161 }
162 
163 bool
164 RegisterContextWindows_x86::ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value,
165                                                RegisterValue &reg_value) const
166 {
167     if ((m_context.ContextFlags & flags_required) != flags_required)
168     {
169         WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", reg_name);
170         return false;
171     }
172     WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value, reg_name);
173     reg_value.SetUInt32(value);
174     return true;
175 }
176