//===-- RegisterContext.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Target/RegisterContext.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Scalar.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; //---------------------------------------------------------------------- // RegisterContext constructors //---------------------------------------------------------------------- RegisterContext::RegisterContext (Thread &thread, StackFrame *frame) : m_thread (thread), m_frame (frame) { } RegisterContext::RegisterContext (Thread &thread) : m_thread (thread), m_frame (NULL) { } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- RegisterContext::~RegisterContext() { } const RegisterInfo * RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx) { if (reg_name && reg_name[0]) { const uint32_t num_registers = GetRegisterCount(); for (uint32_t reg = start_idx; reg < num_registers; ++reg) { const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); if ((reg_info->name != NULL && ::strcasecmp (reg_info->name, reg_name) == 0) || (reg_info->alt_name != NULL && ::strcasecmp (reg_info->alt_name, reg_name) == 0)) { return reg_info; } } } return NULL; } const char * RegisterContext::GetRegisterName (uint32_t reg) { const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg); if (reg_info) return reg_info->name; return NULL; } uint64_t RegisterContext::GetPC(uint64_t fail_value) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); return ReadRegisterAsUnsigned (reg, fail_value); } bool RegisterContext::SetPC(uint64_t pc) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); bool success = WriteRegisterFromUnsigned (reg, pc); if (success) { if (m_frame) m_frame->ChangePC(pc); else m_thread.ClearStackFrames (); } return success; } uint64_t RegisterContext::GetSP(uint64_t fail_value) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); return ReadRegisterAsUnsigned (reg, fail_value); } bool RegisterContext::SetSP(uint64_t sp) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); return WriteRegisterFromUnsigned (reg, sp); } uint64_t RegisterContext::GetFP(uint64_t fail_value) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); return ReadRegisterAsUnsigned (reg, fail_value); } bool RegisterContext::SetFP(uint64_t fp) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); return WriteRegisterFromUnsigned (reg, fp); } uint64_t RegisterContext::GetReturnAddress (uint64_t fail_value) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); return ReadRegisterAsUnsigned (reg, fail_value); } uint64_t RegisterContext::GetFlags (uint64_t fail_value) { uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); return ReadRegisterAsUnsigned (reg, fail_value); } uint64_t RegisterContext::ReadRegisterAsUnsigned (uint32_t reg, uint64_t fail_value) { if (reg != LLDB_INVALID_REGNUM) { Scalar value; if (ReadRegisterValue (reg, value)) return value.GetRawBits64(fail_value); } return fail_value; } bool RegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval) { if (reg == LLDB_INVALID_REGNUM) return false; Scalar value(uval); return WriteRegisterValue (reg, value); } lldb::tid_t RegisterContext::GetThreadID() const { return m_thread.GetID(); } uint32_t RegisterContext::NumSupportedHardwareBreakpoints () { return 0; } uint32_t RegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) { return LLDB_INVALID_INDEX32; } bool RegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx) { return false; } uint32_t RegisterContext::NumSupportedHardwareWatchpoints () { return 0; } uint32_t RegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write) { return LLDB_INVALID_INDEX32; } bool RegisterContext::ClearHardwareWatchpoint (uint32_t hw_index) { return false; } bool RegisterContext::HardwareSingleStep (bool enable) { return false; } void RegisterContext::SetStackFrame (StackFrame *frame) { m_frame = frame; } Target * RegisterContext::CalculateTarget () { return m_thread.CalculateTarget(); } Process * RegisterContext::CalculateProcess () { return m_thread.CalculateProcess (); } Thread * RegisterContext::CalculateThread () { return &m_thread; } StackFrame * RegisterContext::CalculateStackFrame () { return m_frame; } void RegisterContext::CalculateExecutionContext (ExecutionContext &exe_ctx) { if (m_frame) m_frame->CalculateExecutionContext (exe_ctx); else m_thread.CalculateExecutionContext (exe_ctx); } bool RegisterContext::ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t& target_regnum) { const uint32_t num_registers = GetRegisterCount(); for (uint32_t reg = 0; reg < num_registers; ++reg) { const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg); if (reg_info->kinds[source_rk] == source_regnum) { target_regnum = reg_info->kinds[target_rk]; if (target_regnum == LLDB_INVALID_REGNUM) { return false; } else { return true; } } } return false; } bool RegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value) { DataExtractor data; if (!ReadRegisterBytes (reg, data)) return false; const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); uint32_t offset = 0; switch (reg_info->encoding) { case eEncodingUint: switch (reg_info->byte_size) { case 1: { value = data.GetU8 (&offset); return true; } case 2: { value = data.GetU16 (&offset); return true; } case 4: { value = data.GetU32 (&offset); return true; } case 8: { value = data.GetU64 (&offset); return true; } } break; case eEncodingSint: switch (reg_info->byte_size) { case 1: { int8_t v; if (data.ExtractBytes (0, sizeof (int8_t), eByteOrderHost, &v) != sizeof (int8_t)) return false; value = v; return true; } case 2: { int16_t v; if (data.ExtractBytes (0, sizeof (int16_t), eByteOrderHost, &v) != sizeof (int16_t)) return false; value = v; return true; } case 4: { int32_t v; if (data.ExtractBytes (0, sizeof (int32_t), eByteOrderHost, &v) != sizeof (int32_t)) return false; value = v; return true; } case 8: { int64_t v; if (data.ExtractBytes (0, sizeof (int64_t), eByteOrderHost, &v) != sizeof (int64_t)) return false; value = v; return true; } } break; case eEncodingIEEE754: switch (reg_info->byte_size) { case sizeof (float): { float v; if (data.ExtractBytes (0, sizeof (float), eByteOrderHost, &v) != sizeof (float)) return false; value = v; return true; } case sizeof (double): { double v; if (data.ExtractBytes (0, sizeof (double), eByteOrderHost, &v) != sizeof (double)) return false; value = v; return true; } case sizeof (long double): { double v; if (data.ExtractBytes (0, sizeof (long double), eByteOrderHost, &v) != sizeof (long double)) return false; value = v; return true; } } break; } return false; } bool RegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value) { DataExtractor data; if (!value.IsValid()) return false; if (!value.GetData (data)) return false; return WriteRegisterBytes (reg, data); }