//===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "RegisterContextMacOSXFrameBackchain.h" // C Includes // C++ Includes // Other libraries and framework includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" #include "lldb/Target/Thread.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" using namespace lldb; using namespace lldb_private; //---------------------------------------------------------------------- // RegisterContextMacOSXFrameBackchain constructor //---------------------------------------------------------------------- RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain ( Thread &thread, uint32_t concrete_frame_idx, const UnwindMacOSXFrameBackchain::Cursor &cursor ) : RegisterContext (thread, concrete_frame_idx), m_cursor (cursor), m_cursor_is_valid (true) { } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain() { } void RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters () { m_cursor_is_valid = false; } size_t RegisterContextMacOSXFrameBackchain::GetRegisterCount () { return m_thread.GetRegisterContext()->GetRegisterCount(); } const RegisterInfo * RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg) { return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); } size_t RegisterContextMacOSXFrameBackchain::GetRegisterSetCount () { return m_thread.GetRegisterContext()->GetRegisterSetCount(); } const RegisterSet * RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set) { return m_thread.GetRegisterContext()->GetRegisterSet (reg_set); } bool RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) { if (!m_cursor_is_valid) return false; uint64_t reg_value = LLDB_INVALID_ADDRESS; switch (reg_info->kinds[eRegisterKindGeneric]) { case LLDB_REGNUM_GENERIC_PC: if (m_cursor.pc == LLDB_INVALID_ADDRESS) return false; reg_value = m_cursor.pc; break; case LLDB_REGNUM_GENERIC_FP: if (m_cursor.fp == LLDB_INVALID_ADDRESS) return false; reg_value = m_cursor.fp; break; default: return false; } switch (reg_info->encoding) { case eEncodingInvalid: case eEncodingVector: break; case eEncodingUint: case eEncodingSint: value.SetUInt(reg_value, reg_info->byte_size); return true; case eEncodingIEEE754: switch (reg_info->byte_size) { case sizeof (float): if (sizeof (float) == sizeof(uint32_t)) { value.SetUInt32(reg_value, RegisterValue::eTypeFloat); return true; } else if (sizeof (float) == sizeof(uint64_t)) { value.SetUInt64(reg_value, RegisterValue::eTypeFloat); return true; } break; case sizeof (double): if (sizeof (double) == sizeof(uint32_t)) { value.SetUInt32(reg_value, RegisterValue::eTypeDouble); return true; } else if (sizeof (double) == sizeof(uint64_t)) { value.SetUInt64(reg_value, RegisterValue::eTypeDouble); return true; } break; // TOOD: need a better way to detect when "long double" types are // the same bytes size as "double" #if !defined(__arm__) && !defined(_MSC_VER) && !defined(__mips__) case sizeof (long double): if (sizeof (long double) == sizeof(uint32_t)) { value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble); return true; } else if (sizeof (long double) == sizeof(uint64_t)) { value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble); return true; } break; #endif } break; } return false; } bool RegisterContextMacOSXFrameBackchain::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value) { // Not supported yet. We could easily add support for this by remembering // the address of each entry (it would need to be part of the cursor) return false; } bool RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) { // libunwind frames can't handle this it doesn't always have all register // values. This call should only be called on frame zero anyway so there // shouldn't be any problem return false; } bool RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) { // Since this class doesn't respond to "ReadAllRegisterValues()", it must // not have been the one that saved all the register values. So we just let // the thread's register context (the register context for frame zero) do // the writing. return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp); } uint32_t RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) { return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num); }