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 //----------------------------------------------------------------------
25 RegisterContextMemory::RegisterContextMemory(Thread &thread,
26                                              uint32_t concrete_frame_idx,
27                                              DynamicRegisterInfo &reg_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 //----------------------------------------------------------------------
47 RegisterContextMemory::~RegisterContextMemory() {}
48 
49 void RegisterContextMemory::InvalidateAllRegisters() {
50   if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
51     SetAllRegisterValid(false);
52 }
53 
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 
60 size_t RegisterContextMemory::GetRegisterCount() {
61   return m_reg_infos.GetNumRegisters();
62 }
63 
64 const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
65   return m_reg_infos.GetRegisterInfoAtIndex(reg);
66 }
67 
68 size_t RegisterContextMemory::GetRegisterSetCount() {
69   return m_reg_infos.GetNumRegisterSets();
70 }
71 
72 const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
73   return m_reg_infos.GetRegisterSet(reg_set);
74 }
75 
76 uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
77     lldb::RegisterKind kind, uint32_t num) {
78   return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
79 }
80 
81 bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
82                                          RegisterValue &reg_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 
95 bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
96                                           const RegisterValue &reg_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 
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 
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 
140 void RegisterContextMemory::SetAllRegisterData(
141     const lldb::DataBufferSP &data_sp) {
142   m_reg_data.SetData(data_sp);
143   SetAllRegisterValid(true);
144 }
145