brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 25b67be Raw
188 lines · cpp
1//===-- RegisterContextWindows.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#include "lldb/Host/windows/HostThreadWindows.h"10#include "lldb/Host/windows/windows.h"11#include "lldb/Utility/DataBufferHeap.h"12#include "lldb/Utility/Status.h"13#include "lldb/lldb-private-types.h"14 15#include "ProcessWindowsLog.h"16#include "RegisterContextWindows.h"17#include "TargetThreadWindows.h"18 19#include "llvm/ADT/STLExtras.h"20#include "lldb/Target/Target.h"21 22using namespace lldb;23using namespace lldb_private;24 25const DWORD kWinContextFlags = CONTEXT_ALL;26 27// Constructors and Destructors28RegisterContextWindows::RegisterContextWindows(Thread &thread,29                                               uint32_t concrete_frame_idx)30    : RegisterContext(thread, concrete_frame_idx), m_context(),31      m_context_stale(true) {}32 33RegisterContextWindows::~RegisterContextWindows() {}34 35void RegisterContextWindows::InvalidateAllRegisters() {36  m_context_stale = true;37}38 39bool RegisterContextWindows::ReadAllRegisterValues(40    lldb::WritableDataBufferSP &data_sp) {41 42  if (!CacheAllRegisterValues())43    return false;44 45  data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));46  memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));47 48  return true;49}50 51bool RegisterContextWindows::WriteAllRegisterValues(52    const lldb::DataBufferSP &data_sp) {53  assert(data_sp->GetByteSize() >= sizeof(m_context));54  memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));55 56  return ApplyAllRegisterValues();57}58 59uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber(60    lldb::RegisterKind kind, uint32_t num) {61  const uint32_t num_regs = GetRegisterCount();62 63  assert(kind < kNumRegisterKinds);64  for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {65    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);66 67    if (reg_info->kinds[kind] == num)68      return reg_idx;69  }70 71  return LLDB_INVALID_REGNUM;72}73 74bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }75 76bool RegisterContextWindows::AddHardwareBreakpoint(uint32_t slot,77                                                   lldb::addr_t address,78                                                   uint32_t size, bool read,79                                                   bool write) {80  if (slot >= NUM_HARDWARE_BREAKPOINT_SLOTS)81    return false;82 83  switch (size) {84  case 1:85  case 2:86  case 4:87#if defined(_WIN64)88  case 8:89#endif90    break;91  default:92    return false;93  }94 95  if (!CacheAllRegisterValues())96    return false;97 98#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)99  unsigned shift = 2 * slot;100  m_context.Dr7 |= 1ULL << shift;101 102  (&m_context.Dr0)[slot] = address;103 104  shift = 18 + 4 * slot;105  m_context.Dr7 &= ~(3ULL << shift);106  m_context.Dr7 |= (size == 8 ? 2ULL : size - 1) << shift;107 108  shift = 16 + 4 * slot;109  m_context.Dr7 &= ~(3ULL << shift);110  m_context.Dr7 |= (read ? 3ULL : (write ? 1ULL : 0)) << shift;111 112  return ApplyAllRegisterValues();113 114#else115  Log *log = GetLog(WindowsLog::Registers);116  LLDB_LOG(log, "hardware breakpoints not currently supported on this arch");117  return false;118#endif119}120 121bool RegisterContextWindows::RemoveHardwareBreakpoint(uint32_t slot) {122  if (slot >= NUM_HARDWARE_BREAKPOINT_SLOTS)123    return false;124 125  if (!CacheAllRegisterValues())126    return false;127 128#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)129  unsigned shift = 2 * slot;130  m_context.Dr7 &= ~(1ULL << shift);131 132  return ApplyAllRegisterValues();133#else134  return false;135#endif136}137 138uint32_t RegisterContextWindows::GetTriggeredHardwareBreakpointSlotId() {139  if (!CacheAllRegisterValues())140    return LLDB_INVALID_INDEX32;141 142#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)143  for (unsigned i = 0UL; i < NUM_HARDWARE_BREAKPOINT_SLOTS; i++)144    if (m_context.Dr6 & (1ULL << i))145      return i;146#endif147 148  return LLDB_INVALID_INDEX32;149}150 151bool RegisterContextWindows::CacheAllRegisterValues() {152  Log *log = GetLog(WindowsLog::Registers);153  if (!m_context_stale)154    return true;155 156  TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);157  memset(&m_context, 0, sizeof(m_context));158  m_context.ContextFlags = kWinContextFlags;159  if (::SuspendThread(160          wthread.GetHostThread().GetNativeThread().GetSystemHandle()) ==161      (DWORD)-1) {162    return false;163  }164  if (!::GetThreadContext(165          wthread.GetHostThread().GetNativeThread().GetSystemHandle(),166          &m_context)) {167    LLDB_LOG(168        log,169        "GetThreadContext failed with error {0} while caching register values.",170        ::GetLastError());171    return false;172  }173  if (::ResumeThread(174          wthread.GetHostThread().GetNativeThread().GetSystemHandle()) ==175      (DWORD)-1) {176    return false;177  }178  LLDB_LOG(log, "successfully updated the register values.");179  m_context_stale = false;180  return true;181}182 183bool RegisterContextWindows::ApplyAllRegisterValues() {184  TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);185  return ::SetThreadContext(186      wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);187}188