1*0b57cec5SDimitry Andric //===-- RegisterContextMemory.cpp -----------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric
9*0b57cec5SDimitry Andric #include "RegisterContextMemory.h"
10*0b57cec5SDimitry Andric
11*0b57cec5SDimitry Andric #include "lldb/Target/Process.h"
12*0b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
13*0b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
14*0b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
15*0b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
16*0b57cec5SDimitry Andric
17*0b57cec5SDimitry Andric using namespace lldb;
18*0b57cec5SDimitry Andric using namespace lldb_private;
19*0b57cec5SDimitry Andric
20*0b57cec5SDimitry Andric // RegisterContextMemory constructor
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)21*0b57cec5SDimitry Andric RegisterContextMemory::RegisterContextMemory(Thread &thread,
22*0b57cec5SDimitry Andric uint32_t concrete_frame_idx,
23*0b57cec5SDimitry Andric DynamicRegisterInfo ®_infos,
24*0b57cec5SDimitry Andric addr_t reg_data_addr)
25*0b57cec5SDimitry Andric : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
26*0b57cec5SDimitry Andric m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
27*0b57cec5SDimitry Andric // Resize our vector of bools to contain one bool for every register. We will
28*0b57cec5SDimitry Andric // use these boolean values to know when a register value is valid in
29*0b57cec5SDimitry Andric // m_reg_data.
30*0b57cec5SDimitry Andric const size_t num_regs = reg_infos.GetNumRegisters();
31*0b57cec5SDimitry Andric assert(num_regs > 0);
32*0b57cec5SDimitry Andric m_reg_valid.resize(num_regs);
33*0b57cec5SDimitry Andric
34*0b57cec5SDimitry Andric // Make a heap based buffer that is big enough to store all registers
35*0b57cec5SDimitry Andric m_data =
36*0b57cec5SDimitry Andric std::make_shared<DataBufferHeap>(reg_infos.GetRegisterDataByteSize(), 0);
37*0b57cec5SDimitry Andric m_reg_data.SetData(m_data);
38*0b57cec5SDimitry Andric }
39*0b57cec5SDimitry Andric
40*0b57cec5SDimitry Andric // Destructor
41*0b57cec5SDimitry Andric RegisterContextMemory::~RegisterContextMemory() = default;
42*0b57cec5SDimitry Andric
InvalidateAllRegisters()43*0b57cec5SDimitry Andric void RegisterContextMemory::InvalidateAllRegisters() {
44*0b57cec5SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
45*0b57cec5SDimitry Andric SetAllRegisterValid(false);
46*0b57cec5SDimitry Andric }
47*0b57cec5SDimitry Andric
SetAllRegisterValid(bool b)48*0b57cec5SDimitry Andric void RegisterContextMemory::SetAllRegisterValid(bool b) {
49*0b57cec5SDimitry Andric std::vector<bool>::iterator pos, end = m_reg_valid.end();
50*0b57cec5SDimitry Andric for (pos = m_reg_valid.begin(); pos != end; ++pos)
51*0b57cec5SDimitry Andric *pos = b;
52*0b57cec5SDimitry Andric }
53*0b57cec5SDimitry Andric
GetRegisterCount()54*0b57cec5SDimitry Andric size_t RegisterContextMemory::GetRegisterCount() {
55*0b57cec5SDimitry Andric return m_reg_infos.GetNumRegisters();
56*0b57cec5SDimitry Andric }
57*0b57cec5SDimitry Andric
GetRegisterInfoAtIndex(size_t reg)58*0b57cec5SDimitry Andric const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
59*0b57cec5SDimitry Andric return m_reg_infos.GetRegisterInfoAtIndex(reg);
60*0b57cec5SDimitry Andric }
61*0b57cec5SDimitry Andric
GetRegisterSetCount()62*0b57cec5SDimitry Andric size_t RegisterContextMemory::GetRegisterSetCount() {
63*0b57cec5SDimitry Andric return m_reg_infos.GetNumRegisterSets();
64*0b57cec5SDimitry Andric }
65*0b57cec5SDimitry Andric
GetRegisterSet(size_t reg_set)66*0b57cec5SDimitry Andric const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
67*0b57cec5SDimitry Andric return m_reg_infos.GetRegisterSet(reg_set);
68*0b57cec5SDimitry Andric }
69*0b57cec5SDimitry Andric
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)70*0b57cec5SDimitry Andric uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
71*0b57cec5SDimitry Andric lldb::RegisterKind kind, uint32_t num) {
72*0b57cec5SDimitry Andric return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
73*0b57cec5SDimitry Andric }
74*0b57cec5SDimitry Andric
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)75*0b57cec5SDimitry Andric bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
76*0b57cec5SDimitry Andric RegisterValue ®_value) {
77*0b57cec5SDimitry Andric const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
78*0b57cec5SDimitry Andric if (!m_reg_valid[reg_num]) {
79*0b57cec5SDimitry Andric if (!ReadAllRegisterValues(m_data))
80*0b57cec5SDimitry Andric return false;
81*0b57cec5SDimitry Andric }
82*0b57cec5SDimitry Andric const bool partial_data_ok = false;
83*0b57cec5SDimitry Andric return reg_value
84*0b57cec5SDimitry Andric .SetValueFromData(*reg_info, m_reg_data, reg_info->byte_offset,
85*0b57cec5SDimitry Andric partial_data_ok)
86*0b57cec5SDimitry Andric .Success();
87*0b57cec5SDimitry Andric }
88*0b57cec5SDimitry Andric
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)89*0b57cec5SDimitry Andric bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
90*0b57cec5SDimitry Andric const RegisterValue ®_value) {
91*0b57cec5SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
92*0b57cec5SDimitry Andric const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
93*0b57cec5SDimitry Andric addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
94*0b57cec5SDimitry Andric Status error(WriteRegisterValueToMemory(reg_info, reg_addr,
95*0b57cec5SDimitry Andric reg_info->byte_size, reg_value));
96*0b57cec5SDimitry Andric m_reg_valid[reg_num] = false;
97*0b57cec5SDimitry Andric return error.Success();
98*0b57cec5SDimitry Andric }
99*0b57cec5SDimitry Andric return false;
100*0b57cec5SDimitry Andric }
101*0b57cec5SDimitry Andric
ReadAllRegisterValues(WritableDataBufferSP & data_sp)102*0b57cec5SDimitry Andric bool RegisterContextMemory::ReadAllRegisterValues(
103*0b57cec5SDimitry Andric WritableDataBufferSP &data_sp) {
104*0b57cec5SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
105*0b57cec5SDimitry Andric ProcessSP process_sp(CalculateProcess());
106*0b57cec5SDimitry Andric if (process_sp) {
107*0b57cec5SDimitry Andric Status error;
108*0b57cec5SDimitry Andric if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(),
109*0b57cec5SDimitry Andric data_sp->GetByteSize(),
110*0b57cec5SDimitry Andric error) == data_sp->GetByteSize()) {
111*0b57cec5SDimitry Andric SetAllRegisterValid(true);
112*0b57cec5SDimitry Andric return true;
113*0b57cec5SDimitry Andric }
114*0b57cec5SDimitry Andric }
115*0b57cec5SDimitry Andric }
116*0b57cec5SDimitry Andric return false;
117*0b57cec5SDimitry Andric }
118*0b57cec5SDimitry Andric
WriteAllRegisterValues(const DataBufferSP & data_sp)119*0b57cec5SDimitry Andric bool RegisterContextMemory::WriteAllRegisterValues(
120*0b57cec5SDimitry Andric const DataBufferSP &data_sp) {
121*0b57cec5SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
122*0b57cec5SDimitry Andric ProcessSP process_sp(CalculateProcess());
123*0b57cec5SDimitry Andric if (process_sp) {
124*0b57cec5SDimitry Andric Status error;
125*0b57cec5SDimitry Andric SetAllRegisterValid(false);
126*0b57cec5SDimitry Andric if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(),
127*0b57cec5SDimitry Andric data_sp->GetByteSize(),
128*0b57cec5SDimitry Andric error) == data_sp->GetByteSize())
129*0b57cec5SDimitry Andric return true;
130*0b57cec5SDimitry Andric }
131*0b57cec5SDimitry Andric }
132*0b57cec5SDimitry Andric return false;
133*0b57cec5SDimitry Andric }
134*0b57cec5SDimitry Andric
SetAllRegisterData(const lldb::DataBufferSP & data_sp)135*0b57cec5SDimitry Andric void RegisterContextMemory::SetAllRegisterData(
136*0b57cec5SDimitry Andric const lldb::DataBufferSP &data_sp) {
137*0b57cec5SDimitry Andric m_reg_data.SetData(data_sp);
138*0b57cec5SDimitry Andric SetAllRegisterValid(true);
139*0b57cec5SDimitry Andric }
140