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