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
23using namespace lldb;
24using namespace lldb_private;
25
26//----------------------------------------------------------------------
27// RegisterContextMemory constructor
28//----------------------------------------------------------------------
29RegisterContextMemory::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//----------------------------------------------------------------------
57RegisterContextMemory::~RegisterContextMemory()
58{
59}
60
61void
62RegisterContextMemory::InvalidateAllRegisters ()
63{
64    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
65        SetAllRegisterValid (false);
66}
67
68void
69RegisterContextMemory::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
76size_t
77RegisterContextMemory::GetRegisterCount ()
78{
79    return m_reg_infos.GetNumRegisters ();
80}
81
82const RegisterInfo *
83RegisterContextMemory::GetRegisterInfoAtIndex (size_t reg)
84{
85    return m_reg_infos.GetRegisterInfoAtIndex (reg);
86}
87
88size_t
89RegisterContextMemory::GetRegisterSetCount ()
90{
91    return m_reg_infos.GetNumRegisterSets ();
92}
93
94const RegisterSet *
95RegisterContextMemory::GetRegisterSet (size_t reg_set)
96{
97    return m_reg_infos.GetRegisterSet (reg_set);
98}
99
100uint32_t
101RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
102{
103    return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
104}
105
106bool
107RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_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
119bool
120RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_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
133bool
134RegisterContextMemory::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
152bool
153RegisterContextMemory::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
169void
170RegisterContextMemory::SetAllRegisterData  (const lldb::DataBufferSP &data_sp)
171{
172    m_reg_data.SetData(data_sp);
173    SetAllRegisterValid (true);
174}
175