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