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

source code of lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp