1cfca06d7SDimitry Andric //===-- RegisterContextMemory.cpp -----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "RegisterContextMemory.h"
10f034231aSEd Maste
11f034231aSEd Maste #include "lldb/Target/Process.h"
12f034231aSEd Maste #include "lldb/Target/Thread.h"
1374a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
1494994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
15b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
16f034231aSEd Maste
17f034231aSEd Maste using namespace lldb;
18f034231aSEd Maste using namespace lldb_private;
19f034231aSEd Maste
20f034231aSEd Maste // RegisterContextMemory constructor
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)2114f1b3e8SDimitry Andric RegisterContextMemory::RegisterContextMemory(Thread &thread,
22f034231aSEd Maste uint32_t concrete_frame_idx,
23f034231aSEd Maste DynamicRegisterInfo ®_infos,
2414f1b3e8SDimitry Andric addr_t reg_data_addr)
2514f1b3e8SDimitry Andric : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
2614f1b3e8SDimitry Andric m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
27f73363f1SDimitry Andric // Resize our vector of bools to contain one bool for every register. We will
28f73363f1SDimitry Andric // use these boolean values to know when a register value is valid in
29f73363f1SDimitry Andric // m_reg_data.
30f034231aSEd Maste const size_t num_regs = reg_infos.GetNumRegisters();
31f034231aSEd Maste assert(num_regs > 0);
32f034231aSEd Maste m_reg_valid.resize(num_regs);
33f034231aSEd Maste
34f034231aSEd Maste // Make a heap based buffer that is big enough to store all registers
35145449b1SDimitry Andric m_data =
36145449b1SDimitry Andric std::make_shared<DataBufferHeap>(reg_infos.GetRegisterDataByteSize(), 0);
37145449b1SDimitry Andric m_reg_data.SetData(m_data);
38f034231aSEd Maste }
39f034231aSEd Maste
40f034231aSEd Maste // Destructor
41344a3780SDimitry Andric RegisterContextMemory::~RegisterContextMemory() = default;
42f034231aSEd Maste
InvalidateAllRegisters()4314f1b3e8SDimitry Andric void RegisterContextMemory::InvalidateAllRegisters() {
44f034231aSEd Maste if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
45f034231aSEd Maste SetAllRegisterValid(false);
46f034231aSEd Maste }
47f034231aSEd Maste
SetAllRegisterValid(bool b)4814f1b3e8SDimitry Andric void RegisterContextMemory::SetAllRegisterValid(bool b) {
49f034231aSEd Maste std::vector<bool>::iterator pos, end = m_reg_valid.end();
50f034231aSEd Maste for (pos = m_reg_valid.begin(); pos != end; ++pos)
51f034231aSEd Maste *pos = b;
52f034231aSEd Maste }
53f034231aSEd Maste
GetRegisterCount()5414f1b3e8SDimitry Andric size_t RegisterContextMemory::GetRegisterCount() {
55f034231aSEd Maste return m_reg_infos.GetNumRegisters();
56f034231aSEd Maste }
57f034231aSEd Maste
GetRegisterInfoAtIndex(size_t reg)5814f1b3e8SDimitry Andric const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
59f034231aSEd Maste return m_reg_infos.GetRegisterInfoAtIndex(reg);
60f034231aSEd Maste }
61f034231aSEd Maste
GetRegisterSetCount()6214f1b3e8SDimitry Andric size_t RegisterContextMemory::GetRegisterSetCount() {
63f034231aSEd Maste return m_reg_infos.GetNumRegisterSets();
64f034231aSEd Maste }
65f034231aSEd Maste
GetRegisterSet(size_t reg_set)6614f1b3e8SDimitry Andric const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
67f034231aSEd Maste return m_reg_infos.GetRegisterSet(reg_set);
68f034231aSEd Maste }
69f034231aSEd Maste
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)7014f1b3e8SDimitry Andric uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
7114f1b3e8SDimitry Andric lldb::RegisterKind kind, uint32_t num) {
72f034231aSEd Maste return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
73f034231aSEd Maste }
74f034231aSEd Maste
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)7514f1b3e8SDimitry Andric bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
7614f1b3e8SDimitry Andric RegisterValue ®_value) {
77f034231aSEd Maste const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
7814f1b3e8SDimitry Andric if (!m_reg_valid[reg_num]) {
79145449b1SDimitry Andric if (!ReadAllRegisterValues(m_data))
80f034231aSEd Maste return false;
81f034231aSEd Maste }
82f034231aSEd Maste const bool partial_data_ok = false;
8314f1b3e8SDimitry Andric return reg_value
84e3b55780SDimitry Andric .SetValueFromData(*reg_info, m_reg_data, reg_info->byte_offset,
8514f1b3e8SDimitry Andric partial_data_ok)
8614f1b3e8SDimitry Andric .Success();
87f034231aSEd Maste }
88f034231aSEd Maste
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)8914f1b3e8SDimitry Andric bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
9014f1b3e8SDimitry Andric const RegisterValue ®_value) {
9114f1b3e8SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
92f034231aSEd Maste const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
93f034231aSEd Maste addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
94b76161e4SDimitry Andric Status error(WriteRegisterValueToMemory(reg_info, reg_addr,
9514f1b3e8SDimitry Andric reg_info->byte_size, reg_value));
96f034231aSEd Maste m_reg_valid[reg_num] = false;
97f034231aSEd Maste return error.Success();
98f034231aSEd Maste }
99f034231aSEd Maste return false;
100f034231aSEd Maste }
101f034231aSEd Maste
ReadAllRegisterValues(WritableDataBufferSP & data_sp)102145449b1SDimitry Andric bool RegisterContextMemory::ReadAllRegisterValues(
103145449b1SDimitry Andric WritableDataBufferSP &data_sp) {
10414f1b3e8SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
105f034231aSEd Maste ProcessSP process_sp(CalculateProcess());
10614f1b3e8SDimitry Andric if (process_sp) {
107b76161e4SDimitry Andric Status error;
10814f1b3e8SDimitry Andric if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(),
10914f1b3e8SDimitry Andric data_sp->GetByteSize(),
11014f1b3e8SDimitry Andric error) == data_sp->GetByteSize()) {
111f034231aSEd Maste SetAllRegisterValid(true);
112f034231aSEd Maste return true;
113f034231aSEd Maste }
114f034231aSEd Maste }
115f034231aSEd Maste }
116f034231aSEd Maste return false;
117f034231aSEd Maste }
118f034231aSEd Maste
WriteAllRegisterValues(const DataBufferSP & data_sp)11914f1b3e8SDimitry Andric bool RegisterContextMemory::WriteAllRegisterValues(
12014f1b3e8SDimitry Andric const DataBufferSP &data_sp) {
12114f1b3e8SDimitry Andric if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
122f034231aSEd Maste ProcessSP process_sp(CalculateProcess());
12314f1b3e8SDimitry Andric if (process_sp) {
124b76161e4SDimitry Andric Status error;
125f034231aSEd Maste SetAllRegisterValid(false);
12614f1b3e8SDimitry Andric if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(),
12714f1b3e8SDimitry Andric data_sp->GetByteSize(),
12814f1b3e8SDimitry Andric error) == data_sp->GetByteSize())
129f034231aSEd Maste return true;
130f034231aSEd Maste }
131f034231aSEd Maste }
132f034231aSEd Maste return false;
133f034231aSEd Maste }
134f034231aSEd Maste
SetAllRegisterData(const lldb::DataBufferSP & data_sp)13514f1b3e8SDimitry Andric void RegisterContextMemory::SetAllRegisterData(
13614f1b3e8SDimitry Andric const lldb::DataBufferSP &data_sp) {
137f034231aSEd Maste m_reg_data.SetData(data_sp);
138f034231aSEd Maste SetAllRegisterValid(true);
139f034231aSEd Maste }
140