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     {DEFINE_GPR(ebx, nullptr),
67      {ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM,
68       LLDB_INVALID_REGNUM, lldb_ebx_i386},
69      nullptr,
70      nullptr},
71     {DEFINE_GPR(ecx, nullptr),
72      {ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM,
73       LLDB_INVALID_REGNUM, lldb_ecx_i386},
74      nullptr,
75      nullptr},
76     {DEFINE_GPR(edx, nullptr),
77      {ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM,
78       LLDB_INVALID_REGNUM, lldb_edx_i386},
79      nullptr,
80      nullptr},
81     {DEFINE_GPR(edi, nullptr),
82      {ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM,
83       LLDB_INVALID_REGNUM, lldb_edi_i386},
84      nullptr,
85      nullptr},
86     {DEFINE_GPR(esi, nullptr),
87      {ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM,
88       LLDB_INVALID_REGNUM, lldb_esi_i386},
89      nullptr,
90      nullptr},
91     {DEFINE_GPR(ebp, "fp"),
92      {ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP,
93       LLDB_INVALID_REGNUM, lldb_ebp_i386},
94      nullptr,
95      nullptr},
96     {DEFINE_GPR(esp, "sp"),
97      {ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP,
98       LLDB_INVALID_REGNUM, lldb_esp_i386},
99      nullptr,
100      nullptr},
101     {DEFINE_GPR(eip, "pc"),
102      {ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC,
103       LLDB_INVALID_REGNUM, lldb_eip_i386},
104      nullptr,
105      nullptr},
106     {DEFINE_GPR_BIN(eflags, "flags"),
107      {ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS,
108       LLDB_INVALID_REGNUM, lldb_eflags_i386},
109      nullptr,
110      nullptr},
111 };
112 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
113 
114 // Array of lldb register numbers used to define the set of all General Purpose
115 // Registers
116 uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx,
117                                 eRegisterIndexEcx, eRegisterIndexEdx,
118                                 eRegisterIndexEdi, eRegisterIndexEsi,
119                                 eRegisterIndexEbp, eRegisterIndexEsp,
120                                 eRegisterIndexEip, eRegisterIndexEflags};
121 
122 RegisterSet g_register_sets[] = {
123     {"General Purpose Registers", "gpr",
124      llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
125 };
126 }
127 
128 //------------------------------------------------------------------
129 // Constructors and Destructors
130 //------------------------------------------------------------------
131 RegisterContextWindows_x86::RegisterContextWindows_x86(
132     Thread &thread, uint32_t concrete_frame_idx)
133     : RegisterContextWindows(thread, concrete_frame_idx) {}
134 
135 RegisterContextWindows_x86::~RegisterContextWindows_x86() {}
136 
137 size_t RegisterContextWindows_x86::GetRegisterCount() {
138   return llvm::array_lengthof(g_register_infos);
139 }
140 
141 const RegisterInfo *
142 RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) {
143   if (reg < k_num_register_infos)
144     return &g_register_infos[reg];
145   return NULL;
146 }
147 
148 size_t RegisterContextWindows_x86::GetRegisterSetCount() {
149   return llvm::array_lengthof(g_register_sets);
150 }
151 
152 const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) {
153   return &g_register_sets[reg_set];
154 }
155 
156 bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
157                                               RegisterValue &reg_value) {
158   if (!CacheAllRegisterValues())
159     return false;
160 
161   uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
162   switch (reg) {
163   case lldb_eax_i386:
164     return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value);
165   case lldb_ebx_i386:
166     return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value);
167   case lldb_ecx_i386:
168     return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value);
169   case lldb_edx_i386:
170     return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value);
171   case lldb_edi_i386:
172     return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value);
173   case lldb_esi_i386:
174     return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value);
175   case lldb_ebp_i386:
176     return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value);
177   case lldb_esp_i386:
178     return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value);
179   case lldb_eip_i386:
180     return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value);
181   case lldb_eflags_i386:
182     return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags,
183                               reg_value);
184   default:
185     WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg);
186     break;
187   }
188   return false;
189 }
190 
191 bool RegisterContextWindows_x86::ReadRegisterHelper(
192     DWORD flags_required, const char *reg_name, DWORD value,
193     RegisterValue &reg_value) const {
194   if ((m_context.ContextFlags & flags_required) != flags_required) {
195     WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s",
196                  reg_name);
197     return false;
198   }
199   WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value,
200                reg_name);
201   reg_value.SetUInt32(value);
202   return true;
203 }
204