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 //---------------------------------------------------------------------- 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 //---------------------------------------------------------------------- 35 RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() {} 36 37 void RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters() { 38 m_cursor_is_valid = false; 39 } 40 41 size_t RegisterContextMacOSXFrameBackchain::GetRegisterCount() { 42 return m_thread.GetRegisterContext()->GetRegisterCount(); 43 } 44 45 const RegisterInfo * 46 RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex(size_t reg) { 47 return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); 48 } 49 50 size_t RegisterContextMacOSXFrameBackchain::GetRegisterSetCount() { 51 return m_thread.GetRegisterContext()->GetRegisterSetCount(); 52 } 53 54 const RegisterSet * 55 RegisterContextMacOSXFrameBackchain::GetRegisterSet(size_t reg_set) { 56 return m_thread.GetRegisterContext()->GetRegisterSet(reg_set); 57 } 58 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 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 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 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 161 RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber( 162 lldb::RegisterKind kind, uint32_t num) { 163 return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 164 kind, num); 165 } 166