1 //===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "RegisterContextMacOSXFrameBackchain.h"
11 #include "lldb/Target/Thread.h"
12 #include "lldb/Utility/DataBufferHeap.h"
13 #include "lldb/Utility/DataExtractor.h"
14 #include "lldb/Utility/RegisterValue.h"
15 #include "lldb/Utility/Scalar.h"
16 #include "lldb/Utility/StreamString.h"
17 #include "lldb/Utility/StringExtractorGDBRemote.h"
20 using namespace lldb_private;
22 // RegisterContextMacOSXFrameBackchain constructor
23 RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain(
24 Thread &thread, uint32_t concrete_frame_idx,
25 const UnwindMacOSXFrameBackchain::Cursor &cursor)
26 : RegisterContext(thread, concrete_frame_idx), m_cursor(cursor),
27 m_cursor_is_valid(true) {}
30 RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() {}
32 void RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters() {
33 m_cursor_is_valid = false;
36 size_t RegisterContextMacOSXFrameBackchain::GetRegisterCount() {
37 return m_thread.GetRegisterContext()->GetRegisterCount();
41 RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex(size_t reg) {
42 return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
45 size_t RegisterContextMacOSXFrameBackchain::GetRegisterSetCount() {
46 return m_thread.GetRegisterContext()->GetRegisterSetCount();
50 RegisterContextMacOSXFrameBackchain::GetRegisterSet(size_t reg_set) {
51 return m_thread.GetRegisterContext()->GetRegisterSet(reg_set);
54 bool RegisterContextMacOSXFrameBackchain::ReadRegister(
55 const RegisterInfo *reg_info, RegisterValue &value) {
56 if (!m_cursor_is_valid)
59 uint64_t reg_value = LLDB_INVALID_ADDRESS;
61 switch (reg_info->kinds[eRegisterKindGeneric]) {
62 case LLDB_REGNUM_GENERIC_PC:
63 if (m_cursor.pc == LLDB_INVALID_ADDRESS)
65 reg_value = m_cursor.pc;
68 case LLDB_REGNUM_GENERIC_FP:
69 if (m_cursor.fp == LLDB_INVALID_ADDRESS)
71 reg_value = m_cursor.fp;
78 switch (reg_info->encoding) {
79 case eEncodingInvalid:
85 value.SetUInt(reg_value, reg_info->byte_size);
88 case eEncodingIEEE754:
89 switch (reg_info->byte_size) {
91 if (sizeof(float) == sizeof(uint32_t)) {
92 value.SetUInt32(reg_value, RegisterValue::eTypeFloat);
94 } else if (sizeof(float) == sizeof(uint64_t)) {
95 value.SetUInt64(reg_value, RegisterValue::eTypeFloat);
101 if (sizeof(double) == sizeof(uint32_t)) {
102 value.SetUInt32(reg_value, RegisterValue::eTypeDouble);
104 } else if (sizeof(double) == sizeof(uint64_t)) {
105 value.SetUInt64(reg_value, RegisterValue::eTypeDouble);
110 // TOOD: need a better way to detect when "long double" types are
111 // the same bytes size as "double"
112 #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && \
113 !defined(_MSC_VER) && !defined(__mips__) && !defined(__powerpc__) && \
114 !defined(__ANDROID__)
115 case sizeof(long double):
116 if (sizeof(long double) == sizeof(uint32_t)) {
117 value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble);
119 } else if (sizeof(long double) == sizeof(uint64_t)) {
120 value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble);
131 bool RegisterContextMacOSXFrameBackchain::WriteRegister(
132 const RegisterInfo *reg_info, const RegisterValue &value) {
133 // Not supported yet. We could easily add support for this by remembering the
134 // address of each entry (it would need to be part of the cursor)
138 bool RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues(
139 lldb::DataBufferSP &data_sp) {
140 // libunwind frames can't handle this it doesn't always have all register
141 // values. This call should only be called on frame zero anyway so there
142 // shouldn't be any problem
146 bool RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues(
147 const lldb::DataBufferSP &data_sp) {
148 // Since this class doesn't respond to "ReadAllRegisterValues()", it must not
149 // have been the one that saved all the register values. So we just let the
150 // thread's register context (the register context for frame zero) do the
152 return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
156 RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber(
157 lldb::RegisterKind kind, uint32_t num) {
158 return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber(