blob: 03610a2fe7cd1d5a7d576bf599e6cac74b7b02c1 [file] [log] [blame]
//===-- RegisterContextMemory.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "RegisterContextMemory.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "DynamicRegisterInfo.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// RegisterContextMemory constructor
//----------------------------------------------------------------------
RegisterContextMemory::RegisterContextMemory
(
Thread &thread,
uint32_t concrete_frame_idx,
DynamicRegisterInfo &reg_infos,
addr_t reg_data_addr
) :
RegisterContext (thread, concrete_frame_idx),
m_reg_infos (reg_infos),
m_reg_valid (),
m_reg_data (),
m_reg_data_addr (reg_data_addr)
{
// Resize our vector of bools to contain one bool for every register.
// We will use these boolean values to know when a register value
// is valid in m_reg_data.
const size_t num_regs = reg_infos.GetNumRegisters();
assert (num_regs > 0);
m_reg_valid.resize (num_regs);
// Make a heap based buffer that is big enough to store all registers
DataBufferSP reg_data_sp(new DataBufferHeap (reg_infos.GetRegisterDataByteSize(), 0));
m_reg_data.SetData (reg_data_sp);
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
RegisterContextMemory::~RegisterContextMemory()
{
}
void
RegisterContextMemory::InvalidateAllRegisters ()
{
SetAllRegisterValid (false);
}
void
RegisterContextMemory::SetAllRegisterValid (bool b)
{
std::vector<bool>::iterator pos, end = m_reg_valid.end();
for (pos = m_reg_valid.begin(); pos != end; ++pos)
*pos = b;
}
size_t
RegisterContextMemory::GetRegisterCount ()
{
return m_reg_infos.GetNumRegisters ();
}
const RegisterInfo *
RegisterContextMemory::GetRegisterInfoAtIndex (uint32_t reg)
{
return m_reg_infos.GetRegisterInfoAtIndex (reg);
}
size_t
RegisterContextMemory::GetRegisterSetCount ()
{
return m_reg_infos.GetNumRegisterSets ();
}
const RegisterSet *
RegisterContextMemory::GetRegisterSet (uint32_t reg_set)
{
return m_reg_infos.GetRegisterSet (reg_set);
}
uint32_t
RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
{
return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
}
bool
RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
{
const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
if (!m_reg_valid[reg_num])
{
if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer ()))
return false;
}
const bool partial_data_ok = false;
return reg_value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok).Success();
}
bool
RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
{
if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
{
const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
Error error (WriteRegisterValueToMemory(reg_info, reg_addr, reg_info->byte_size, reg_value));
m_reg_valid[reg_num] = false;
return error.Success();
}
return false;
}
bool
RegisterContextMemory::ReadAllRegisterValues (DataBufferSP &data_sp)
{
if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
{
ProcessSP process_sp (CalculateProcess());
if (process_sp)
{
Error error;
if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
{
SetAllRegisterValid (true);
return true;
}
}
}
return false;
}
bool
RegisterContextMemory::WriteAllRegisterValues (const DataBufferSP &data_sp)
{
if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
{
ProcessSP process_sp (CalculateProcess());
if (process_sp)
{
Error error;
SetAllRegisterValid (false);
if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
return true;
}
}
return false;
}