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 //----------------------------------------------------------------------
29 RegisterContextMemory::RegisterContextMemory
30 (
31     Thread &thread,
32     uint32_t concrete_frame_idx,
33     DynamicRegisterInfo &reg_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 //----------------------------------------------------------------------
57 RegisterContextMemory::~RegisterContextMemory()
58 {
59 }
60 
61 void
62 RegisterContextMemory::InvalidateAllRegisters ()
63 {
64     SetAllRegisterValid (false);
65 }
66 
67 void
68 RegisterContextMemory::SetAllRegisterValid (bool b)
69 {
70     std::vector<bool>::iterator pos, end = m_reg_valid.end();
71     for (pos = m_reg_valid.begin(); pos != end; ++pos)
72         *pos = b;
73 }
74 
75 size_t
76 RegisterContextMemory::GetRegisterCount ()
77 {
78     return m_reg_infos.GetNumRegisters ();
79 }
80 
81 const RegisterInfo *
82 RegisterContextMemory::GetRegisterInfoAtIndex (uint32_t reg)
83 {
84     return m_reg_infos.GetRegisterInfoAtIndex (reg);
85 }
86 
87 size_t
88 RegisterContextMemory::GetRegisterSetCount ()
89 {
90     return m_reg_infos.GetNumRegisterSets ();
91 }
92 
93 const RegisterSet *
94 RegisterContextMemory::GetRegisterSet (uint32_t reg_set)
95 {
96     return m_reg_infos.GetRegisterSet (reg_set);
97 }
98 
99 uint32_t
100 RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
101 {
102     return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
103 }
104 
105 bool
106 RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
107 {
108     const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
109     if (!m_reg_valid[reg_num])
110     {
111         if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer ()))
112             return false;
113     }
114     const bool partial_data_ok = false;
115     return reg_value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok).Success();
116 }
117 
118 bool
119 RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
120 {
121     if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
122     {
123         const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
124         addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
125         Error error (WriteRegisterValueToMemory(reg_info, reg_addr, reg_info->byte_size, reg_value));
126         m_reg_valid[reg_num] = false;
127         return error.Success();
128     }
129     return false;
130 }
131 
132 bool
133 RegisterContextMemory::ReadAllRegisterValues (DataBufferSP &data_sp)
134 {
135     if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
136     {
137         Error error;
138         if (m_thread.GetProcess().ReadMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
139         {
140             SetAllRegisterValid (true);
141             return true;
142         }
143     }
144     return false;
145 }
146 
147 bool
148 RegisterContextMemory::WriteAllRegisterValues (const DataBufferSP &data_sp)
149 {
150     if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
151     {
152         Error error;
153         SetAllRegisterValid (false);
154         if (m_thread.GetProcess().WriteMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
155             return true;
156     }
157     return false;
158 }
159