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 ( 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 //---------------------------------------------------------------------- 45 RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() 46 { 47 } 48 49 void 50 RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters () 51 { 52 m_cursor_is_valid = false; 53 } 54 55 size_t 56 RegisterContextMacOSXFrameBackchain::GetRegisterCount () 57 { 58 return m_thread.GetRegisterContext()->GetRegisterCount(); 59 } 60 61 const RegisterInfo * 62 RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg) 63 { 64 return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); 65 } 66 67 size_t 68 RegisterContextMacOSXFrameBackchain::GetRegisterSetCount () 69 { 70 return m_thread.GetRegisterContext()->GetRegisterSetCount(); 71 } 72 73 74 75 const RegisterSet * 76 RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set) 77 { 78 return m_thread.GetRegisterContext()->GetRegisterSet (reg_set); 79 } 80 81 82 83 bool 84 RegisterContextMacOSXFrameBackchain::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 172 bool 173 RegisterContextMacOSXFrameBackchain::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 181 bool 182 RegisterContextMacOSXFrameBackchain::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 190 bool 191 RegisterContextMacOSXFrameBackchain::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 201 uint32_t 202 RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) 203 { 204 return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num); 205 } 206 207