blob: bc78c1d6160c2f983eaecd52ab9eeb6bdf8d7ca0 [file] [log] [blame] [edit]
//===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "RegisterContextMacOSXFrameBackchain.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/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__) && !defined(__powerpc__) && \
!defined(__ANDROID__)
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);
}