brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.3 KiB · 3f4c649 Raw
281 lines · cpp
1//===-- RegisterContextWindows_x86.cpp ------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#if defined(__i386__) || defined(_M_IX86)10 11#include "lldb/Host/windows/HostThreadWindows.h"12#include "lldb/Host/windows/windows.h"13#include "lldb/Utility/RegisterValue.h"14#include "lldb/Utility/Status.h"15#include "lldb/lldb-private-types.h"16 17#include "ProcessWindowsLog.h"18#include "RegisterContextWindows_x86.h"19#include "Plugins/Process/Utility/RegisterContext_x86.h"20#include "TargetThreadWindows.h"21#include "Plugins/Process/Utility/lldb-x86-register-enums.h"22 23#include "llvm/ADT/STLExtras.h"24 25using namespace lldb;26using namespace lldb_private;27 28#define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase29#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary30 31namespace {32 33// This enum defines the layout of the global RegisterInfo array.  This is34// necessary because lldb register sets are defined in terms of indices into35// the register array. As such, the order of RegisterInfos defined in global36// registers array must match the order defined here. When defining the37// register set layouts, these values can appear in an arbitrary order, and38// that determines the order that register values are displayed in a dump.39enum RegisterIndex {40  eRegisterIndexEax,41  eRegisterIndexEbx,42  eRegisterIndexEcx,43  eRegisterIndexEdx,44  eRegisterIndexEdi,45  eRegisterIndexEsi,46  eRegisterIndexEbp,47  eRegisterIndexEsp,48  eRegisterIndexEip,49  eRegisterIndexEflags50};51 52// Array of all register information supported by Windows x8653RegisterInfo g_register_infos[] = {54    {DEFINE_GPR(eax, nullptr),55     {ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM,56      LLDB_INVALID_REGNUM, lldb_eax_i386},57     nullptr,58     nullptr,59     nullptr,60    },61    {DEFINE_GPR(ebx, nullptr),62     {ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM,63      LLDB_INVALID_REGNUM, lldb_ebx_i386},64     nullptr,65     nullptr,66     nullptr,67    },68    {DEFINE_GPR(ecx, nullptr),69     {ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM,70      LLDB_INVALID_REGNUM, lldb_ecx_i386},71     nullptr,72     nullptr,73     nullptr,74    },75    {DEFINE_GPR(edx, nullptr),76     {ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM,77      LLDB_INVALID_REGNUM, lldb_edx_i386},78     nullptr,79     nullptr,80     nullptr,81    },82    {DEFINE_GPR(edi, nullptr),83     {ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM,84      LLDB_INVALID_REGNUM, lldb_edi_i386},85     nullptr,86     nullptr,87     nullptr,88    },89    {DEFINE_GPR(esi, nullptr),90     {ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM,91      LLDB_INVALID_REGNUM, lldb_esi_i386},92     nullptr,93     nullptr,94     nullptr,95    },96    {DEFINE_GPR(ebp, "fp"),97     {ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP,98      LLDB_INVALID_REGNUM, lldb_ebp_i386},99     nullptr,100     nullptr,101     nullptr,102    },103    {DEFINE_GPR(esp, "sp"),104     {ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP,105      LLDB_INVALID_REGNUM, lldb_esp_i386},106     nullptr,107     nullptr,108     nullptr,109    },110    {DEFINE_GPR(eip, "pc"),111     {ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC,112      LLDB_INVALID_REGNUM, lldb_eip_i386},113     nullptr,114     nullptr,115     nullptr,116    },117    {DEFINE_GPR_BIN(eflags, "flags"),118     {ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS,119      LLDB_INVALID_REGNUM, lldb_eflags_i386},120     nullptr,121     nullptr,122     nullptr,123    },124};125static size_t k_num_register_infos = std::size(g_register_infos);126 127// Array of lldb register numbers used to define the set of all General Purpose128// Registers129uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx,130                                eRegisterIndexEcx, eRegisterIndexEdx,131                                eRegisterIndexEdi, eRegisterIndexEsi,132                                eRegisterIndexEbp, eRegisterIndexEsp,133                                eRegisterIndexEip, eRegisterIndexEflags};134 135RegisterSet g_register_sets[] = {136    {"General Purpose Registers", "gpr", std::size(g_gpr_reg_indices),137     g_gpr_reg_indices},138};139}140 141// Constructors and Destructors142RegisterContextWindows_x86::RegisterContextWindows_x86(143    Thread &thread, uint32_t concrete_frame_idx)144    : RegisterContextWindows(thread, concrete_frame_idx) {}145 146RegisterContextWindows_x86::~RegisterContextWindows_x86() {}147 148size_t RegisterContextWindows_x86::GetRegisterCount() {149  return std::size(g_register_infos);150}151 152const RegisterInfo *153RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) {154  if (reg < k_num_register_infos)155    return &g_register_infos[reg];156  return NULL;157}158 159size_t RegisterContextWindows_x86::GetRegisterSetCount() {160  return std::size(g_register_sets);161}162 163const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) {164  return &g_register_sets[reg_set];165}166 167bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,168                                              RegisterValue &reg_value) {169  if (!CacheAllRegisterValues())170    return false;171 172  if (reg_info == nullptr)173    return false;174 175  uint32_t reg = reg_info->kinds[eRegisterKindLLDB];176  switch (reg) {177  case lldb_eax_i386:178    return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value);179  case lldb_ebx_i386:180    return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value);181  case lldb_ecx_i386:182    return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value);183  case lldb_edx_i386:184    return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value);185  case lldb_edi_i386:186    return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value);187  case lldb_esi_i386:188    return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value);189  case lldb_ebp_i386:190    return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value);191  case lldb_esp_i386:192    return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value);193  case lldb_eip_i386:194    return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value);195  case lldb_eflags_i386:196    return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags,197                              reg_value);198  default:199    Log *log = GetLog(WindowsLog::Registers);200    LLDB_LOG(log, "Requested unknown register {0}", reg);201    break;202  }203  return false;204}205 206bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info,207                                               const RegisterValue &reg_value) {208  // Since we cannot only write a single register value to the inferior, we209  // need to make sure our cached copy of the register values are fresh.210  // Otherwise when writing EAX, for example, we may also overwrite some other211  // register with a stale value.212  if (!CacheAllRegisterValues())213    return false;214 215  Log *log = GetLog(WindowsLog::Registers);216  uint32_t reg = reg_info->kinds[eRegisterKindLLDB];217  switch (reg) {218  case lldb_eax_i386:219    LLDB_LOG(log, "Write value {0:x} to EAX", reg_value.GetAsUInt32());220    m_context.Eax = reg_value.GetAsUInt32();221    break;222  case lldb_ebx_i386:223    LLDB_LOG(log, "Write value {0:x} to EBX", reg_value.GetAsUInt32());224    m_context.Ebx = reg_value.GetAsUInt32();225    break;226  case lldb_ecx_i386:227    LLDB_LOG(log, "Write value {0:x} to ECX", reg_value.GetAsUInt32());228    m_context.Ecx = reg_value.GetAsUInt32();229    break;230  case lldb_edx_i386:231    LLDB_LOG(log, "Write value {0:x} to EDX", reg_value.GetAsUInt32());232    m_context.Edx = reg_value.GetAsUInt32();233    break;234  case lldb_edi_i386:235    LLDB_LOG(log, "Write value {0:x} to EDI", reg_value.GetAsUInt32());236    m_context.Edi = reg_value.GetAsUInt32();237    break;238  case lldb_esi_i386:239    LLDB_LOG(log, "Write value {0:x} to ESI", reg_value.GetAsUInt32());240    m_context.Esi = reg_value.GetAsUInt32();241    break;242  case lldb_ebp_i386:243    LLDB_LOG(log, "Write value {0:x} to EBP", reg_value.GetAsUInt32());244    m_context.Ebp = reg_value.GetAsUInt32();245    break;246  case lldb_esp_i386:247    LLDB_LOG(log, "Write value {0:x} to ESP", reg_value.GetAsUInt32());248    m_context.Esp = reg_value.GetAsUInt32();249    break;250  case lldb_eip_i386:251    LLDB_LOG(log, "Write value {0:x} to EIP", reg_value.GetAsUInt32());252    m_context.Eip = reg_value.GetAsUInt32();253    break;254  case lldb_eflags_i386:255    LLDB_LOG(log, "Write value {0:x} to EFLAGS", reg_value.GetAsUInt32());256    m_context.EFlags = reg_value.GetAsUInt32();257    break;258  default:259    LLDB_LOG(log, "Write value {0:x} to unknown register {1}",260             reg_value.GetAsUInt32(), reg);261  }262 263  // Physically update the registers in the target process.264  return ApplyAllRegisterValues();265}266 267bool RegisterContextWindows_x86::ReadRegisterHelper(268    DWORD flags_required, const char *reg_name, DWORD value,269    RegisterValue &reg_value) const {270  Log *log = GetLog(WindowsLog::Registers);271  if ((m_context.ContextFlags & flags_required) != flags_required) {272    LLDB_LOG(log, "Thread context doesn't have {0}", reg_name);273    return false;274  }275  LLDB_LOG(log, "Read value {0:x} from {1}", value, reg_name);276  reg_value.SetUInt32(value);277  return true;278}279 280#endif // defined(__i386__) || defined(_M_IX86)281