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