| //===-- 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/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 lldb::RegisterInfo * |
| RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (uint32_t reg) |
| { |
| return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg); |
| } |
| |
| size_t |
| RegisterContextMacOSXFrameBackchain::GetRegisterSetCount () |
| { |
| return m_thread.GetRegisterContext()->GetRegisterSetCount(); |
| } |
| |
| |
| |
| const lldb::RegisterSet * |
| RegisterContextMacOSXFrameBackchain::GetRegisterSet (uint32_t reg_set) |
| { |
| return m_thread.GetRegisterContext()->GetRegisterSet (reg_set); |
| } |
| |
| |
| |
| bool |
| RegisterContextMacOSXFrameBackchain::ReadRegisterValue (uint32_t reg, Scalar &value) |
| { |
| if (!m_cursor_is_valid) |
| return false; |
| |
| uint64_t reg_value = LLDB_INVALID_ADDRESS; |
| |
| const RegisterInfo *reg_info = m_thread.GetRegisterContext()->GetRegisterInfoAtIndex (reg); |
| if (reg_info == NULL) |
| return false; |
| |
| 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.pc; |
| break; |
| |
| default: |
| return false; |
| } |
| |
| switch (reg_info->encoding) |
| { |
| case eEncodingUint: |
| switch (reg_info->byte_size) |
| { |
| case 1: |
| case 2: |
| case 4: |
| value = (uint32_t)reg_value; |
| return true; |
| |
| case 8: |
| value = (uint64_t)reg_value; |
| return true; |
| } |
| break; |
| |
| case eEncodingSint: |
| switch (reg_info->byte_size) |
| { |
| case 1: |
| case 2: |
| case 4: |
| value = (int32_t)reg_value; |
| return true; |
| |
| case 8: |
| value = (int64_t)reg_value; |
| return true; |
| } |
| break; |
| |
| case eEncodingIEEE754: |
| switch (reg_info->byte_size) |
| { |
| case sizeof (float): |
| if (sizeof (float) == sizeof(uint32_t)) |
| { |
| value = (uint32_t)reg_value; |
| return true; |
| } |
| else if (sizeof (float) == sizeof(uint64_t)) |
| { |
| value = (uint64_t)reg_value; |
| return true; |
| } |
| break; |
| |
| case sizeof (double): |
| if (sizeof (double) == sizeof(uint32_t)) |
| { |
| value = (uint32_t)reg_value; |
| return true; |
| } |
| else if (sizeof (double) == sizeof(uint64_t)) |
| { |
| value = (uint64_t)reg_value; |
| return true; |
| } |
| break; |
| |
| case sizeof (long double): |
| if (sizeof (long double) == sizeof(uint32_t)) |
| { |
| value = (uint32_t)reg_value; |
| return true; |
| } |
| else if (sizeof (long double) == sizeof(uint64_t)) |
| { |
| value = (uint64_t)reg_value; |
| return true; |
| } |
| break; |
| } |
| break; |
| } |
| return false; |
| } |
| |
| |
| bool |
| RegisterContextMacOSXFrameBackchain::ReadRegisterBytes (uint32_t reg, DataExtractor &data) |
| { |
| Scalar reg_value; |
| |
| if (ReadRegisterValue (reg, reg_value)) |
| { |
| if (reg_value.GetData(data)) |
| { |
| // "reg_value" is local and now "data" points to the data within |
| // "reg_value", so we must make a copy that will live within "data" |
| DataBufferSP data_sp (new DataBufferHeap (data.GetDataStart(), data.GetByteSize())); |
| data.SetData (data_sp, 0, data.GetByteSize()); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| bool |
| RegisterContextMacOSXFrameBackchain::WriteRegisterValue (uint32_t reg, const Scalar &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::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset) |
| { |
| // 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); |
| } |
| |