| //===-- 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(__arm64__) && !defined(__aarch64__) && !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 (lldb::RegisterKind kind, uint32_t num) |
| { |
| return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num); |
| } |
| |