aboutsummaryrefslogblamecommitdiff
path: root/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
blob: b3f507128f824982dd8a4279af16bed0d43ec427 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                                

                                                
                                        
                                
                                    














                                                                    



                                                                           
 
                                                    
 

                                                       

 








                                                             

 



                                                             
 




                                                                              
 
              

 


                                                                     
 


                                                                   
 


                                     
 
                             




                                                                    


                                                                    

 


                                                                         

 

                                                                       

 


                                                                    

 



                                                                              

 

                                                                         

 
                                                                              
 
                                                       
                                                                   
                       
                






                                                                              


                                                                                


                          
                                                             

                          
 
//===-- RegisterContextWindows.cpp ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"

#include "ProcessWindowsLog.h"
#include "RegisterContextWindows.h"
#include "TargetThreadWindows.h"

#include "llvm/ADT/STLExtras.h"

using namespace lldb;
using namespace lldb_private;

const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;

//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows::RegisterContextWindows(Thread &thread,
                                               uint32_t concrete_frame_idx)
    : RegisterContext(thread, concrete_frame_idx), m_context(),
      m_context_stale(true) {}

RegisterContextWindows::~RegisterContextWindows() {}

void RegisterContextWindows::InvalidateAllRegisters() {
  m_context_stale = true;
}

bool RegisterContextWindows::ReadAllRegisterValues(
    lldb::DataBufferSP &data_sp) {
  if (!CacheAllRegisterValues())
    return false;
  if (data_sp->GetByteSize() < sizeof(m_context)) {
    data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
  }
  memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
  return true;
}

bool RegisterContextWindows::WriteAllRegisterValues(
    const lldb::DataBufferSP &data_sp) {
  assert(data_sp->GetByteSize() >= sizeof(m_context));
  memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));

  TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
  if (!::SetThreadContext(
          wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
          &m_context))
    return false;

  return true;
}

uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber(
    lldb::RegisterKind kind, uint32_t num) {
  const uint32_t num_regs = GetRegisterCount();

  assert(kind < kNumRegisterKinds);
  for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);

    if (reg_info->kinds[kind] == num)
      return reg_idx;
  }

  return LLDB_INVALID_REGNUM;
}

//------------------------------------------------------------------
// Subclasses can these functions if desired
//------------------------------------------------------------------
uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() {
  // Support for hardware breakpoints not yet implemented.
  return 0;
}

uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr,
                                                       size_t size) {
  return 0;
}

bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) {
  return false;
}

uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() {
  // Support for hardware watchpoints not yet implemented.
  return 0;
}

uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr,
                                                       size_t size, bool read,
                                                       bool write) {
  return 0;
}

bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) {
  return false;
}

bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }

bool RegisterContextWindows::CacheAllRegisterValues() {
  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
  if (!m_context_stale)
    return true;

  TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
  memset(&m_context, 0, sizeof(m_context));
  m_context.ContextFlags = kWinContextFlags;
  if (!::GetThreadContext(
          wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
          &m_context)) {
    LLDB_LOG(
        log,
        "GetThreadContext failed with error {0} while caching register values.",
        ::GetLastError());
    return false;
  }
  LLDB_LOG(log, "successfully updated the register values.");
  m_context_stale = false;
  return true;
}