Home | History | Annotate | Download | only in Utility
      1 //===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "RegisterContextMacOSXFrameBackchain.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 #include "lldb/Core/DataBufferHeap.h"
     16 #include "lldb/Core/DataExtractor.h"
     17 #include "lldb/Core/RegisterValue.h"
     18 #include "lldb/Core/Scalar.h"
     19 #include "lldb/Core/StreamString.h"
     20 #include "lldb/Target/Thread.h"
     21 // Project includes
     22 #include "Utility/StringExtractorGDBRemote.h"
     23 
     24 using namespace lldb;
     25 using namespace lldb_private;
     26 
     27 //----------------------------------------------------------------------
     28 // RegisterContextMacOSXFrameBackchain constructor
     29 //----------------------------------------------------------------------
     30 RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain
     31 (
     32     Thread &thread,
     33     uint32_t concrete_frame_idx,
     34     const UnwindMacOSXFrameBackchain::Cursor &cursor
     35 ) :
     36     RegisterContext (thread, concrete_frame_idx),
     37     m_cursor (cursor),
     38     m_cursor_is_valid (true)
     39 {
     40 }
     41 
     42 //----------------------------------------------------------------------
     43 // Destructor
     44 //----------------------------------------------------------------------
     45 RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain()
     46 {
     47 }
     48 
     49 void
     50 RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters ()
     51 {
     52     m_cursor_is_valid = false;
     53 }
     54 
     55 size_t
     56 RegisterContextMacOSXFrameBackchain::GetRegisterCount ()
     57 {
     58     return m_thread.GetRegisterContext()->GetRegisterCount();
     59 }
     60 
     61 const RegisterInfo *
     62 RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg)
     63 {
     64     return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
     65 }
     66 
     67 size_t
     68 RegisterContextMacOSXFrameBackchain::GetRegisterSetCount ()
     69 {
     70     return m_thread.GetRegisterContext()->GetRegisterSetCount();
     71 }
     72 
     73 
     74 
     75 const RegisterSet *
     76 RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set)
     77 {
     78     return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
     79 }
     80 
     81 
     82 
     83 bool
     84 RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
     85                                                    RegisterValue &value)
     86 {
     87     if (!m_cursor_is_valid)
     88         return false;
     89 
     90     uint64_t reg_value = LLDB_INVALID_ADDRESS;
     91 
     92     switch (reg_info->kinds[eRegisterKindGeneric])
     93     {
     94     case LLDB_REGNUM_GENERIC_PC:
     95         if (m_cursor.pc == LLDB_INVALID_ADDRESS)
     96             return false;
     97         reg_value = m_cursor.pc;
     98         break;
     99 
    100     case LLDB_REGNUM_GENERIC_FP:
    101         if (m_cursor.fp == LLDB_INVALID_ADDRESS)
    102             return false;
    103         reg_value = m_cursor.fp;
    104         break;
    105 
    106     default:
    107         return false;
    108     }
    109 
    110     switch (reg_info->encoding)
    111     {
    112     case eEncodingInvalid:
    113     case eEncodingVector:
    114         break;
    115 
    116     case eEncodingUint:
    117     case eEncodingSint:
    118         value.SetUInt(reg_value, reg_info->byte_size);
    119         return true;
    120 
    121     case eEncodingIEEE754:
    122         switch (reg_info->byte_size)
    123         {
    124         case sizeof (float):
    125             if (sizeof (float) == sizeof(uint32_t))
    126             {
    127                 value.SetUInt32(reg_value, RegisterValue::eTypeFloat);
    128                 return true;
    129             }
    130             else if (sizeof (float) == sizeof(uint64_t))
    131             {
    132                 value.SetUInt64(reg_value, RegisterValue::eTypeFloat);
    133                 return true;
    134             }
    135             break;
    136 
    137         case sizeof (double):
    138             if (sizeof (double) == sizeof(uint32_t))
    139             {
    140                 value.SetUInt32(reg_value, RegisterValue::eTypeDouble);
    141                 return true;
    142             }
    143             else if (sizeof (double) == sizeof(uint64_t))
    144             {
    145                 value.SetUInt64(reg_value, RegisterValue::eTypeDouble);
    146                 return true;
    147             }
    148             break;
    149 
    150             // TOOD: need a better way to detect when "long double" types are
    151             // the same bytes size as "double"
    152 #if !defined(__arm__)
    153         case sizeof (long double):
    154             if (sizeof (long double) == sizeof(uint32_t))
    155             {
    156                 value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble);
    157                 return true;
    158             }
    159             else if (sizeof (long double) == sizeof(uint64_t))
    160             {
    161                 value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble);
    162                 return true;
    163             }
    164             break;
    165 #endif
    166         }
    167         break;
    168     }
    169     return false;
    170 }
    171 
    172 bool
    173 RegisterContextMacOSXFrameBackchain::WriteRegister (const RegisterInfo *reg_info,
    174                                                     const RegisterValue &value)
    175 {
    176     // Not supported yet. We could easily add support for this by remembering
    177     // the address of each entry (it would need to be part of the cursor)
    178     return false;
    179 }
    180 
    181 bool
    182 RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
    183 {
    184     // libunwind frames can't handle this it doesn't always have all register
    185     // values. This call should only be called on frame zero anyway so there
    186     // shouldn't be any problem
    187     return false;
    188 }
    189 
    190 bool
    191 RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
    192 {
    193     // Since this class doesn't respond to "ReadAllRegisterValues()", it must
    194     // not have been the one that saved all the register values. So we just let
    195     // the thread's register context (the register context for frame zero) do
    196     // the writing.
    197     return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
    198 }
    199 
    200 
    201 uint32_t
    202 RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
    203 {
    204     return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
    205 }
    206 
    207