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