1ac7ddfbfSEd Maste //===-- RegisterContextMemory.cpp -------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "RegisterContextMemory.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste #include "DynamicRegisterInfo.h"
13ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
14ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
15f678e45dSDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
16*b5893f02SDimitry Andric #include "lldb/Utility/RegisterValue.h"
175517e702SDimitry Andric #include "lldb/Utility/Status.h"
18ac7ddfbfSEd Maste 
19ac7ddfbfSEd Maste using namespace lldb;
20ac7ddfbfSEd Maste using namespace lldb_private;
21ac7ddfbfSEd Maste 
22ac7ddfbfSEd Maste //----------------------------------------------------------------------
23ac7ddfbfSEd Maste // RegisterContextMemory constructor
24ac7ddfbfSEd Maste //----------------------------------------------------------------------
RegisterContextMemory(Thread & thread,uint32_t concrete_frame_idx,DynamicRegisterInfo & reg_infos,addr_t reg_data_addr)25435933ddSDimitry Andric RegisterContextMemory::RegisterContextMemory(Thread &thread,
26ac7ddfbfSEd Maste                                              uint32_t concrete_frame_idx,
27ac7ddfbfSEd Maste                                              DynamicRegisterInfo &reg_infos,
28435933ddSDimitry Andric                                              addr_t reg_data_addr)
29435933ddSDimitry Andric     : RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
30435933ddSDimitry Andric       m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
314ba319b5SDimitry Andric   // Resize our vector of bools to contain one bool for every register. We will
324ba319b5SDimitry Andric   // use these boolean values to know when a register value is valid in
334ba319b5SDimitry Andric   // m_reg_data.
34ac7ddfbfSEd Maste   const size_t num_regs = reg_infos.GetNumRegisters();
35ac7ddfbfSEd Maste   assert(num_regs > 0);
36ac7ddfbfSEd Maste   m_reg_valid.resize(num_regs);
37ac7ddfbfSEd Maste 
38ac7ddfbfSEd Maste   // Make a heap based buffer that is big enough to store all registers
39435933ddSDimitry Andric   DataBufferSP reg_data_sp(
40435933ddSDimitry Andric       new DataBufferHeap(reg_infos.GetRegisterDataByteSize(), 0));
41ac7ddfbfSEd Maste   m_reg_data.SetData(reg_data_sp);
42ac7ddfbfSEd Maste }
43ac7ddfbfSEd Maste 
44ac7ddfbfSEd Maste //----------------------------------------------------------------------
45ac7ddfbfSEd Maste // Destructor
46ac7ddfbfSEd Maste //----------------------------------------------------------------------
~RegisterContextMemory()47435933ddSDimitry Andric RegisterContextMemory::~RegisterContextMemory() {}
48ac7ddfbfSEd Maste 
InvalidateAllRegisters()49435933ddSDimitry Andric void RegisterContextMemory::InvalidateAllRegisters() {
50ac7ddfbfSEd Maste   if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
51ac7ddfbfSEd Maste     SetAllRegisterValid(false);
52ac7ddfbfSEd Maste }
53ac7ddfbfSEd Maste 
SetAllRegisterValid(bool b)54435933ddSDimitry Andric void RegisterContextMemory::SetAllRegisterValid(bool b) {
55ac7ddfbfSEd Maste   std::vector<bool>::iterator pos, end = m_reg_valid.end();
56ac7ddfbfSEd Maste   for (pos = m_reg_valid.begin(); pos != end; ++pos)
57ac7ddfbfSEd Maste     *pos = b;
58ac7ddfbfSEd Maste }
59ac7ddfbfSEd Maste 
GetRegisterCount()60435933ddSDimitry Andric size_t RegisterContextMemory::GetRegisterCount() {
61ac7ddfbfSEd Maste   return m_reg_infos.GetNumRegisters();
62ac7ddfbfSEd Maste }
63ac7ddfbfSEd Maste 
GetRegisterInfoAtIndex(size_t reg)64435933ddSDimitry Andric const RegisterInfo *RegisterContextMemory::GetRegisterInfoAtIndex(size_t reg) {
65ac7ddfbfSEd Maste   return m_reg_infos.GetRegisterInfoAtIndex(reg);
66ac7ddfbfSEd Maste }
67ac7ddfbfSEd Maste 
GetRegisterSetCount()68435933ddSDimitry Andric size_t RegisterContextMemory::GetRegisterSetCount() {
69ac7ddfbfSEd Maste   return m_reg_infos.GetNumRegisterSets();
70ac7ddfbfSEd Maste }
71ac7ddfbfSEd Maste 
GetRegisterSet(size_t reg_set)72435933ddSDimitry Andric const RegisterSet *RegisterContextMemory::GetRegisterSet(size_t reg_set) {
73ac7ddfbfSEd Maste   return m_reg_infos.GetRegisterSet(reg_set);
74ac7ddfbfSEd Maste }
75ac7ddfbfSEd Maste 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)76435933ddSDimitry Andric uint32_t RegisterContextMemory::ConvertRegisterKindToRegisterNumber(
77435933ddSDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
78ac7ddfbfSEd Maste   return m_reg_infos.ConvertRegisterKindToRegisterNumber(kind, num);
79ac7ddfbfSEd Maste }
80ac7ddfbfSEd Maste 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)81435933ddSDimitry Andric bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
82435933ddSDimitry Andric                                          RegisterValue &reg_value) {
83ac7ddfbfSEd Maste   const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
84435933ddSDimitry Andric   if (!m_reg_valid[reg_num]) {
85ac7ddfbfSEd Maste     if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer()))
86ac7ddfbfSEd Maste       return false;
87ac7ddfbfSEd Maste   }
88ac7ddfbfSEd Maste   const bool partial_data_ok = false;
89435933ddSDimitry Andric   return reg_value
90435933ddSDimitry Andric       .SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset,
91435933ddSDimitry Andric                         partial_data_ok)
92435933ddSDimitry Andric       .Success();
93ac7ddfbfSEd Maste }
94ac7ddfbfSEd Maste 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)95435933ddSDimitry Andric bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
96435933ddSDimitry Andric                                           const RegisterValue &reg_value) {
97435933ddSDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
98ac7ddfbfSEd Maste     const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
99ac7ddfbfSEd Maste     addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
1005517e702SDimitry Andric     Status error(WriteRegisterValueToMemory(reg_info, reg_addr,
101435933ddSDimitry Andric                                             reg_info->byte_size, reg_value));
102ac7ddfbfSEd Maste     m_reg_valid[reg_num] = false;
103ac7ddfbfSEd Maste     return error.Success();
104ac7ddfbfSEd Maste   }
105ac7ddfbfSEd Maste   return false;
106ac7ddfbfSEd Maste }
107ac7ddfbfSEd Maste 
ReadAllRegisterValues(DataBufferSP & data_sp)108435933ddSDimitry Andric bool RegisterContextMemory::ReadAllRegisterValues(DataBufferSP &data_sp) {
109435933ddSDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
110ac7ddfbfSEd Maste     ProcessSP process_sp(CalculateProcess());
111435933ddSDimitry Andric     if (process_sp) {
1125517e702SDimitry Andric       Status error;
113435933ddSDimitry Andric       if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(),
114435933ddSDimitry Andric                                  data_sp->GetByteSize(),
115435933ddSDimitry Andric                                  error) == data_sp->GetByteSize()) {
116ac7ddfbfSEd Maste         SetAllRegisterValid(true);
117ac7ddfbfSEd Maste         return true;
118ac7ddfbfSEd Maste       }
119ac7ddfbfSEd Maste     }
120ac7ddfbfSEd Maste   }
121ac7ddfbfSEd Maste   return false;
122ac7ddfbfSEd Maste }
123ac7ddfbfSEd Maste 
WriteAllRegisterValues(const DataBufferSP & data_sp)124435933ddSDimitry Andric bool RegisterContextMemory::WriteAllRegisterValues(
125435933ddSDimitry Andric     const DataBufferSP &data_sp) {
126435933ddSDimitry Andric   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
127ac7ddfbfSEd Maste     ProcessSP process_sp(CalculateProcess());
128435933ddSDimitry Andric     if (process_sp) {
1295517e702SDimitry Andric       Status error;
130ac7ddfbfSEd Maste       SetAllRegisterValid(false);
131435933ddSDimitry Andric       if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(),
132435933ddSDimitry Andric                                   data_sp->GetByteSize(),
133435933ddSDimitry Andric                                   error) == data_sp->GetByteSize())
134ac7ddfbfSEd Maste         return true;
135ac7ddfbfSEd Maste     }
136ac7ddfbfSEd Maste   }
137ac7ddfbfSEd Maste   return false;
138ac7ddfbfSEd Maste }
139ac7ddfbfSEd Maste 
SetAllRegisterData(const lldb::DataBufferSP & data_sp)140435933ddSDimitry Andric void RegisterContextMemory::SetAllRegisterData(
141435933ddSDimitry Andric     const lldb::DataBufferSP &data_sp) {
142ac7ddfbfSEd Maste   m_reg_data.SetData(data_sp);
143ac7ddfbfSEd Maste   SetAllRegisterValid(true);
144ac7ddfbfSEd Maste }
145