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 ®_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 ®_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