Home | History | Annotate | Download | only in Utility
      1 //===-- DynamicRegisterInfo.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 "lldb/lldb-python.h"
     11 
     12 #include "DynamicRegisterInfo.h"
     13 
     14 // C Includes
     15 // C++ Includes
     16 // Other libraries and framework includes
     17 // Project includes
     18 #include "lldb/Interpreter/Args.h"
     19 
     20 #ifndef LLDB_DISABLE_PYTHON
     21 #include "lldb/Interpreter/PythonDataObjects.h"
     22 #endif
     23 
     24 using namespace lldb;
     25 using namespace lldb_private;
     26 
     27 DynamicRegisterInfo::DynamicRegisterInfo () :
     28     m_regs (),
     29     m_sets (),
     30     m_set_reg_nums (),
     31     m_set_names (),
     32     m_reg_data_byte_size (0)
     33 {
     34 }
     35 
     36 DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
     37     m_regs (),
     38     m_sets (),
     39     m_set_reg_nums (),
     40     m_set_names (),
     41     m_reg_data_byte_size (0)
     42 {
     43     SetRegisterInfo (dict);
     44 }
     45 
     46 DynamicRegisterInfo::~DynamicRegisterInfo ()
     47 {
     48 }
     49 
     50 
     51 size_t
     52 DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
     53 {
     54 #ifndef LLDB_DISABLE_PYTHON
     55     PythonList sets (dict.GetItemForKey("sets"));
     56     if (sets)
     57     {
     58         const uint32_t num_sets = sets.GetSize();
     59         for (uint32_t i=0; i<num_sets; ++i)
     60         {
     61             PythonString py_set_name(sets.GetItemAtIndex(i));
     62             ConstString set_name;
     63             if (py_set_name)
     64                 set_name.SetCString(py_set_name.GetString());
     65             if (set_name)
     66             {
     67                 RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
     68                 m_sets.push_back (new_set);
     69             }
     70             else
     71             {
     72                 Clear();
     73                 return 0;
     74             }
     75         }
     76         m_set_reg_nums.resize(m_sets.size());
     77     }
     78     PythonList regs (dict.GetItemForKey("registers"));
     79     if (regs)
     80     {
     81         const uint32_t num_regs = regs.GetSize();
     82         PythonString name_pystr("name");
     83         PythonString altname_pystr("alt-name");
     84         PythonString bitsize_pystr("bitsize");
     85         PythonString offset_pystr("offset");
     86         PythonString encoding_pystr("encoding");
     87         PythonString format_pystr("format");
     88         PythonString set_pystr("set");
     89         PythonString gcc_pystr("gcc");
     90         PythonString dwarf_pystr("dwarf");
     91         PythonString generic_pystr("generic");
     92         for (uint32_t i=0; i<num_regs; ++i)
     93         {
     94             PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
     95             if (reg_info_dict)
     96             {
     97                 // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
     98                 RegisterInfo reg_info;
     99                 bzero (&reg_info, sizeof(reg_info));
    100 
    101                 reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
    102                 if (reg_info.name == NULL)
    103                 {
    104                     Clear();
    105                     return 0;
    106                 }
    107 
    108                 reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
    109 
    110                 reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);
    111 
    112                 if (reg_info.byte_offset == UINT32_MAX)
    113                 {
    114                     Clear();
    115                     return 0;
    116                 }
    117                 reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
    118 
    119                 if (reg_info.byte_size == 0)
    120                 {
    121                     Clear();
    122                     return 0;
    123                 }
    124 
    125                 const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
    126                 if (format_cstr)
    127                 {
    128                     if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
    129                     {
    130                         Clear();
    131                         return 0;
    132                     }
    133                 }
    134                 else
    135                     reg_info.format = eFormatHex;
    136 
    137                 const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
    138                 if (encoding_cstr)
    139                     reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
    140                 else
    141                     reg_info.encoding = eEncodingUint;
    142 
    143                 const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
    144                 if (set >= m_sets.size())
    145                 {
    146                     Clear();
    147                     return 0;
    148                 }
    149 
    150                 reg_info.kinds[lldb::eRegisterKindLLDB]    = i;
    151                 reg_info.kinds[lldb::eRegisterKindGDB]     = i;
    152                 reg_info.kinds[lldb::eRegisterKindGCC]     = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
    153                 reg_info.kinds[lldb::eRegisterKindDWARF]   = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
    154                 reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
    155                 const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
    156                 if (m_reg_data_byte_size < end_reg_offset)
    157                     m_reg_data_byte_size = end_reg_offset;
    158 
    159                 m_regs.push_back (reg_info);
    160                 m_set_reg_nums[set].push_back(i);
    161 
    162             }
    163             else
    164             {
    165                 Clear();
    166                 return 0;
    167             }
    168         }
    169         Finalize ();
    170     }
    171 #endif
    172     return 0;
    173 }
    174 
    175 
    176 void
    177 DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
    178                                   ConstString &reg_name,
    179                                   ConstString &reg_alt_name,
    180                                   ConstString &set_name)
    181 {
    182     const uint32_t reg_num = m_regs.size();
    183     reg_info.name = reg_name.AsCString();
    184     assert (reg_info.name);
    185     reg_info.alt_name = reg_alt_name.AsCString(NULL);
    186     m_regs.push_back (reg_info);
    187     uint32_t set = GetRegisterSetIndexByName (set_name, true);
    188     assert (set < m_sets.size());
    189     assert (set < m_set_reg_nums.size());
    190     assert (set < m_set_names.size());
    191     m_set_reg_nums[set].push_back(reg_num);
    192     size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
    193     if (m_reg_data_byte_size < end_reg_offset)
    194         m_reg_data_byte_size = end_reg_offset;
    195 }
    196 
    197 void
    198 DynamicRegisterInfo::Finalize ()
    199 {
    200     for (uint32_t set = 0; set < m_sets.size(); ++set)
    201     {
    202         assert (m_sets.size() == m_set_reg_nums.size());
    203         m_sets[set].num_registers = m_set_reg_nums[set].size();
    204         m_sets[set].registers = &m_set_reg_nums[set][0];
    205     }
    206 }
    207 
    208 size_t
    209 DynamicRegisterInfo::GetNumRegisters() const
    210 {
    211     return m_regs.size();
    212 }
    213 
    214 size_t
    215 DynamicRegisterInfo::GetNumRegisterSets() const
    216 {
    217     return m_sets.size();
    218 }
    219 
    220 size_t
    221 DynamicRegisterInfo::GetRegisterDataByteSize() const
    222 {
    223     return m_reg_data_byte_size;
    224 }
    225 
    226 const RegisterInfo *
    227 DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) const
    228 {
    229     if (i < m_regs.size())
    230         return &m_regs[i];
    231     return NULL;
    232 }
    233 
    234 const RegisterSet *
    235 DynamicRegisterInfo::GetRegisterSet (uint32_t i) const
    236 {
    237     if (i < m_sets.size())
    238         return &m_sets[i];
    239     return NULL;
    240 }
    241 
    242 uint32_t
    243 DynamicRegisterInfo::GetRegisterSetIndexByName (ConstString &set_name, bool can_create)
    244 {
    245     name_collection::iterator pos, end = m_set_names.end();
    246     for (pos = m_set_names.begin(); pos != end; ++pos)
    247     {
    248         if (*pos == set_name)
    249             return std::distance (m_set_names.begin(), pos);
    250     }
    251 
    252     m_set_names.push_back(set_name);
    253     m_set_reg_nums.resize(m_set_reg_nums.size()+1);
    254     RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
    255     m_sets.push_back (new_set);
    256     return m_sets.size() - 1;
    257 }
    258 
    259 uint32_t
    260 DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
    261 {
    262     reg_collection::const_iterator pos, end = m_regs.end();
    263     for (pos = m_regs.begin(); pos != end; ++pos)
    264     {
    265         if (pos->kinds[kind] == num)
    266             return std::distance (m_regs.begin(), pos);
    267     }
    268 
    269     return LLDB_INVALID_REGNUM;
    270 }
    271 
    272 void
    273 DynamicRegisterInfo::Clear()
    274 {
    275     m_regs.clear();
    276     m_sets.clear();
    277     m_set_reg_nums.clear();
    278     m_set_names.clear();
    279 }
    280