1//===-- RegisterContextMacOSXFrameBackchain.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 "RegisterContextMacOSXFrameBackchain.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15#include "lldb/Core/DataBufferHeap.h"
16#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/RegisterValue.h"
18#include "lldb/Core/Scalar.h"
19#include "lldb/Core/StreamString.h"
20#include "lldb/Target/Thread.h"
21// Project includes
22#include "Utility/StringExtractorGDBRemote.h"
23
24using namespace lldb;
25using namespace lldb_private;
26
27//----------------------------------------------------------------------
28// RegisterContextMacOSXFrameBackchain constructor
29//----------------------------------------------------------------------
30RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain
31(
32    Thread &thread,
33    uint32_t concrete_frame_idx,
34    const UnwindMacOSXFrameBackchain::Cursor &cursor
35) :
36    RegisterContext (thread, concrete_frame_idx),
37    m_cursor (cursor),
38    m_cursor_is_valid (true)
39{
40}
41
42//----------------------------------------------------------------------
43// Destructor
44//----------------------------------------------------------------------
45RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain()
46{
47}
48
49void
50RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters ()
51{
52    m_cursor_is_valid = false;
53}
54
55size_t
56RegisterContextMacOSXFrameBackchain::GetRegisterCount ()
57{
58    return m_thread.GetRegisterContext()->GetRegisterCount();
59}
60
61const RegisterInfo *
62RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg)
63{
64    return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
65}
66
67size_t
68RegisterContextMacOSXFrameBackchain::GetRegisterSetCount ()
69{
70    return m_thread.GetRegisterContext()->GetRegisterSetCount();
71}
72
73
74
75const RegisterSet *
76RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set)
77{
78    return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
79}
80
81
82
83bool
84RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
85                                                   RegisterValue &value)
86{
87    if (!m_cursor_is_valid)
88        return false;
89
90    uint64_t reg_value = LLDB_INVALID_ADDRESS;
91
92    switch (reg_info->kinds[eRegisterKindGeneric])
93    {
94    case LLDB_REGNUM_GENERIC_PC:
95        if (m_cursor.pc == LLDB_INVALID_ADDRESS)
96            return false;
97        reg_value = m_cursor.pc;
98        break;
99
100    case LLDB_REGNUM_GENERIC_FP:
101        if (m_cursor.fp == LLDB_INVALID_ADDRESS)
102            return false;
103        reg_value = m_cursor.fp;
104        break;
105
106    default:
107        return false;
108    }
109
110    switch (reg_info->encoding)
111    {
112    case eEncodingInvalid:
113    case eEncodingVector:
114        break;
115
116    case eEncodingUint:
117    case eEncodingSint:
118        value.SetUInt(reg_value, reg_info->byte_size);
119        return true;
120
121    case eEncodingIEEE754:
122        switch (reg_info->byte_size)
123        {
124        case sizeof (float):
125            if (sizeof (float) == sizeof(uint32_t))
126            {
127                value.SetUInt32(reg_value, RegisterValue::eTypeFloat);
128                return true;
129            }
130            else if (sizeof (float) == sizeof(uint64_t))
131            {
132                value.SetUInt64(reg_value, RegisterValue::eTypeFloat);
133                return true;
134            }
135            break;
136
137        case sizeof (double):
138            if (sizeof (double) == sizeof(uint32_t))
139            {
140                value.SetUInt32(reg_value, RegisterValue::eTypeDouble);
141                return true;
142            }
143            else if (sizeof (double) == sizeof(uint64_t))
144            {
145                value.SetUInt64(reg_value, RegisterValue::eTypeDouble);
146                return true;
147            }
148            break;
149
150            // TOOD: need a better way to detect when "long double" types are
151            // the same bytes size as "double"
152#if !defined(__arm__)
153        case sizeof (long double):
154            if (sizeof (long double) == sizeof(uint32_t))
155            {
156                value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble);
157                return true;
158            }
159            else if (sizeof (long double) == sizeof(uint64_t))
160            {
161                value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble);
162                return true;
163            }
164            break;
165#endif
166        }
167        break;
168    }
169    return false;
170}
171
172bool
173RegisterContextMacOSXFrameBackchain::WriteRegister (const RegisterInfo *reg_info,
174                                                    const RegisterValue &value)
175{
176    // Not supported yet. We could easily add support for this by remembering
177    // the address of each entry (it would need to be part of the cursor)
178    return false;
179}
180
181bool
182RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
183{
184    // libunwind frames can't handle this it doesn't always have all register
185    // values. This call should only be called on frame zero anyway so there
186    // shouldn't be any problem
187    return false;
188}
189
190bool
191RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
192{
193    // Since this class doesn't respond to "ReadAllRegisterValues()", it must
194    // not have been the one that saved all the register values. So we just let
195    // the thread's register context (the register context for frame zero) do
196    // the writing.
197    return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
198}
199
200
201uint32_t
202RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
203{
204    return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
205}
206
207