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 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "DynamicRegisterInfo.h"
17 #include "lldb/Core/DataBufferHeap.h"
18 #include "lldb/Core/Error.h"
19 #include "lldb/Core/RegisterValue.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Thread.h"
22
23 using namespace lldb;
24 using namespace lldb_private;
25
26 //----------------------------------------------------------------------
27 // RegisterContextMemory constructor
28 //----------------------------------------------------------------------
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)29 RegisterContextMemory::RegisterContextMemory
30 (
31 Thread &thread,
32 uint32_t concrete_frame_idx,
33 DynamicRegisterInfo ®_infos,
34 addr_t reg_data_addr
35 ) :
36 RegisterContext (thread, concrete_frame_idx),
37 m_reg_infos (reg_infos),
38 m_reg_valid (),
39 m_reg_data (),
40 m_reg_data_addr (reg_data_addr)
41 {
42 // Resize our vector of bools to contain one bool for every register.
43 // We will use these boolean values to know when a register value
44 // is valid in m_reg_data.
45 const size_t num_regs = reg_infos.GetNumRegisters();
46 assert (num_regs > 0);
47 m_reg_valid.resize (num_regs);
48
49 // Make a heap based buffer that is big enough to store all registers
50 DataBufferSP reg_data_sp(new DataBufferHeap (reg_infos.GetRegisterDataByteSize(), 0));
51 m_reg_data.SetData (reg_data_sp);
52 }
53
54 //----------------------------------------------------------------------
55 // Destructor
56 //----------------------------------------------------------------------
~RegisterContextMemory()57 RegisterContextMemory::~RegisterContextMemory()
58 {
59 }
60
61 void
InvalidateAllRegisters()62 RegisterContextMemory::InvalidateAllRegisters ()
63 {
64 if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
65 SetAllRegisterValid (false);
66 }
67
68 void
SetAllRegisterValid(bool b)69 RegisterContextMemory::SetAllRegisterValid (bool b)
70 {
71 std::vector<bool>::iterator pos, end = m_reg_valid.end();
72 for (pos = m_reg_valid.begin(); pos != end; ++pos)
73 *pos = b;
74 }
75
76 size_t
GetRegisterCount()77 RegisterContextMemory::GetRegisterCount ()
78 {
79 return m_reg_infos.GetNumRegisters ();
80 }
81
82 const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)83 RegisterContextMemory::GetRegisterInfoAtIndex (size_t reg)
84 {
85 return m_reg_infos.GetRegisterInfoAtIndex (reg);
86 }
87
88 size_t
GetRegisterSetCount()89 RegisterContextMemory::GetRegisterSetCount ()
90 {
91 return m_reg_infos.GetNumRegisterSets ();
92 }
93
94 const RegisterSet *
GetRegisterSet(size_t reg_set)95 RegisterContextMemory::GetRegisterSet (size_t reg_set)
96 {
97 return m_reg_infos.GetRegisterSet (reg_set);
98 }
99
100 uint32_t
ConvertRegisterKindToRegisterNumber(uint32_t kind,uint32_t num)101 RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
102 {
103 return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
104 }
105
106 bool
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)107 RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value)
108 {
109 const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
110 if (!m_reg_valid[reg_num])
111 {
112 if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer ()))
113 return false;
114 }
115 const bool partial_data_ok = false;
116 return reg_value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok).Success();
117 }
118
119 bool
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)120 RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value)
121 {
122 if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
123 {
124 const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
125 addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
126 Error error (WriteRegisterValueToMemory(reg_info, reg_addr, reg_info->byte_size, reg_value));
127 m_reg_valid[reg_num] = false;
128 return error.Success();
129 }
130 return false;
131 }
132
133 bool
ReadAllRegisterValues(DataBufferSP & data_sp)134 RegisterContextMemory::ReadAllRegisterValues (DataBufferSP &data_sp)
135 {
136 if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
137 {
138 ProcessSP process_sp (CalculateProcess());
139 if (process_sp)
140 {
141 Error error;
142 if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
143 {
144 SetAllRegisterValid (true);
145 return true;
146 }
147 }
148 }
149 return false;
150 }
151
152 bool
WriteAllRegisterValues(const DataBufferSP & data_sp)153 RegisterContextMemory::WriteAllRegisterValues (const DataBufferSP &data_sp)
154 {
155 if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
156 {
157 ProcessSP process_sp (CalculateProcess());
158 if (process_sp)
159 {
160 Error error;
161 SetAllRegisterValid (false);
162 if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
163 return true;
164 }
165 }
166 return false;
167 }
168
169 void
SetAllRegisterData(const lldb::DataBufferSP & data_sp)170 RegisterContextMemory::SetAllRegisterData (const lldb::DataBufferSP &data_sp)
171 {
172 m_reg_data.SetData(data_sp);
173 SetAllRegisterValid (true);
174 }
175