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