Home | History | Annotate | Download | only in DataFormatters
      1 //===-- LibCxx.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 "lldb/DataFormatters/CXXFormatterFunctions.h"
     13 
     14 #include "lldb/Core/DataBufferHeap.h"
     15 #include "lldb/Core/Debugger.h"
     16 #include "lldb/Core/Error.h"
     17 #include "lldb/Core/Stream.h"
     18 #include "lldb/Core/ValueObject.h"
     19 #include "lldb/Core/ValueObjectConstResult.h"
     20 #include "lldb/Host/Endian.h"
     21 #include "lldb/Symbol/ClangASTContext.h"
     22 #include "lldb/Target/ObjCLanguageRuntime.h"
     23 #include "lldb/Target/Target.h"
     24 
     25 using namespace lldb;
     26 using namespace lldb_private;
     27 using namespace lldb_private::formatters;
     28 
     29 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
     30 SyntheticChildrenFrontEnd(*valobj_sp.get()),
     31 m_exe_ctx_ref(),
     32 m_count(0),
     33 m_base_data_address(0),
     34 m_options()
     35 {
     36     if (valobj_sp)
     37         Update();
     38     m_options.SetCoerceToId(false)
     39     .SetUnwindOnError(true)
     40     .SetKeepInMemory(true)
     41     .SetUseDynamic(lldb::eDynamicCanRunTarget);
     42 }
     43 
     44 size_t
     45 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
     46 {
     47     return m_count;
     48 }
     49 
     50 lldb::ValueObjectSP
     51 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
     52 {
     53     if (idx >= m_count)
     54         return ValueObjectSP();
     55     if (m_base_data_address == 0 || m_count == 0)
     56         return ValueObjectSP();
     57     size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
     58     size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
     59     lldb::addr_t byte_location = m_base_data_address + byte_idx;
     60     ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
     61     if (!process_sp)
     62         return ValueObjectSP();
     63     uint8_t byte = 0;
     64     uint8_t mask = 0;
     65     Error err;
     66     size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
     67     if (err.Fail() || bytes_read == 0)
     68         return ValueObjectSP();
     69     switch (bit_index)
     70     {
     71         case 0:
     72             mask = 1; break;
     73         case 1:
     74             mask = 2; break;
     75         case 2:
     76             mask = 4; break;
     77         case 3:
     78             mask = 8; break;
     79         case 4:
     80             mask = 16; break;
     81         case 5:
     82             mask = 32; break;
     83         case 6:
     84             mask = 64; break;
     85         case 7:
     86             mask = 128; break;
     87         default:
     88             return ValueObjectSP();
     89     }
     90     bool bit_set = ((byte & mask) != 0);
     91     Target& target(process_sp->GetTarget());
     92     ValueObjectSP retval_sp;
     93     if (bit_set)
     94         target.EvaluateExpression("(bool)true", NULL, retval_sp);
     95     else
     96         target.EvaluateExpression("(bool)false", NULL, retval_sp);
     97     StreamString name; name.Printf("[%zu]",idx);
     98     if (retval_sp)
     99         retval_sp->SetName(ConstString(name.GetData()));
    100     return retval_sp;
    101 }
    102 
    103 /*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
    104  __begin_ = 0x00000001001000e0
    105  __size_ = 56
    106  __cap_alloc_ = {
    107  std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
    108  __first_ = 1
    109  }
    110  }
    111  }*/
    112 
    113 bool
    114 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
    115 {
    116     ValueObjectSP valobj_sp = m_backend.GetSP();
    117     if (!valobj_sp)
    118         return false;
    119     if (!valobj_sp)
    120         return false;
    121     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
    122     ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
    123     if (!size_sp)
    124         return false;
    125     m_count = size_sp->GetValueAsUnsigned(0);
    126     if (!m_count)
    127         return true;
    128     ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
    129     if (!begin_sp)
    130     {
    131         m_count = 0;
    132         return false;
    133     }
    134     m_base_data_address = begin_sp->GetValueAsUnsigned(0);
    135     if (!m_base_data_address)
    136     {
    137         m_count = 0;
    138         return false;
    139     }
    140     return false;
    141 }
    142 
    143 bool
    144 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
    145 {
    146     return true;
    147 }
    148 
    149 size_t
    150 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
    151 {
    152     if (!m_count || !m_base_data_address)
    153         return UINT32_MAX;
    154     const char* item_name = name.GetCString();
    155     uint32_t idx = ExtractIndexFromString(item_name);
    156     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
    157         return UINT32_MAX;
    158     return idx;
    159 }
    160 
    161 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
    162 {}
    163 
    164 SyntheticChildrenFrontEnd*
    165 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
    166 {
    167     if (!valobj_sp)
    168         return NULL;
    169     return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
    170 }
    171 
    172 /*
    173  (lldb) fr var ibeg --raw --ptr-depth 1
    174  (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
    175  __i_ = {
    176  __ptr_ = 0x0000000100103870 {
    177  std::__1::__tree_node_base<void *> = {
    178  std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
    179  __left_ = 0x0000000000000000
    180  }
    181  __right_ = 0x0000000000000000
    182  __parent_ = 0x00000001001038b0
    183  __is_black_ = true
    184  }
    185  __value_ = {
    186  first = 0
    187  second = { std::string }
    188  */
    189 
    190 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
    191 SyntheticChildrenFrontEnd(*valobj_sp.get()),
    192 m_pair_ptr()
    193 {
    194     if (valobj_sp)
    195         Update();
    196 }
    197 
    198 bool
    199 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update()
    200 {
    201     ValueObjectSP valobj_sp = m_backend.GetSP();
    202     if (!valobj_sp)
    203         return false;
    204 
    205     TargetSP target_sp(valobj_sp->GetTargetSP());
    206 
    207     if (!target_sp)
    208         return false;
    209 
    210     if (!valobj_sp)
    211         return false;
    212 
    213     // this must be a ValueObject* because it is a child of the ValueObject we are producing children for
    214     // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator)
    215     // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory
    216     m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_",
    217                                                      NULL,
    218                                                      NULL,
    219                                                      NULL,
    220                                                      ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().DontAllowSyntheticChildren(),
    221                                                      NULL).get();
    222 
    223     return false;
    224 }
    225 
    226 size_t
    227 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
    228 {
    229     return 2;
    230 }
    231 
    232 lldb::ValueObjectSP
    233 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
    234 {
    235     if (!m_pair_ptr)
    236         return lldb::ValueObjectSP();
    237     return m_pair_ptr->GetChildAtIndex(idx, true);
    238 }
    239 
    240 bool
    241 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren ()
    242 {
    243     return true;
    244 }
    245 
    246 size_t
    247 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
    248 {
    249     if (name == ConstString("first"))
    250         return 0;
    251     if (name == ConstString("second"))
    252         return 1;
    253     return UINT32_MAX;
    254 }
    255 
    256 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd ()
    257 {
    258     // this will be deleted when its parent dies (since it's a child object)
    259     //delete m_pair_ptr;
    260 }
    261 
    262 SyntheticChildrenFrontEnd*
    263 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
    264 {
    265     if (!valobj_sp)
    266         return NULL;
    267     return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp));
    268 }
    269 
    270 /*
    271  (lldb) fr var ibeg --raw --ptr-depth 1 -T
    272  (std::__1::__wrap_iter<int *>) ibeg = {
    273  (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
    274  (int) *__i = 1
    275  }
    276  }
    277 */
    278 
    279 SyntheticChildrenFrontEnd*
    280 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
    281 {
    282     static ConstString g_item_name;
    283     if (!g_item_name)
    284         g_item_name.SetCString("__i");
    285     if (!valobj_sp)
    286         return NULL;
    287     return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
    288 }
    289 
    290 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
    291 SyntheticChildrenFrontEnd(*valobj_sp.get()),
    292 m_cntrl(NULL),
    293 m_count_sp(),
    294 m_weak_count_sp(),
    295 m_ptr_size(0),
    296 m_byte_order(lldb::eByteOrderInvalid)
    297 {
    298     if (valobj_sp)
    299         Update();
    300 }
    301 
    302 size_t
    303 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren ()
    304 {
    305     return (m_cntrl ? 1 : 0);
    306 }
    307 
    308 lldb::ValueObjectSP
    309 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx)
    310 {
    311     if (!m_cntrl)
    312         return lldb::ValueObjectSP();
    313 
    314     ValueObjectSP valobj_sp = m_backend.GetSP();
    315     if (!valobj_sp)
    316         return lldb::ValueObjectSP();
    317 
    318     if (idx == 0)
    319         return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
    320 
    321     if (idx > 2)
    322         return lldb::ValueObjectSP();
    323 
    324     if (idx == 1)
    325     {
    326         if (!m_count_sp)
    327         {
    328             ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true));
    329             if (!shared_owners_sp)
    330                 return lldb::ValueObjectSP();
    331             uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
    332             DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
    333             m_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType());
    334         }
    335         return m_count_sp;
    336     }
    337     else /* if (idx == 2) */
    338     {
    339         if (!m_weak_count_sp)
    340         {
    341             ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true));
    342             if (!shared_weak_owners_sp)
    343                 return lldb::ValueObjectSP();
    344             uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
    345             DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
    346             m_weak_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType());
    347         }
    348         return m_weak_count_sp;
    349     }
    350 }
    351 
    352 bool
    353 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update()
    354 {
    355     m_count_sp.reset();
    356     m_weak_count_sp.reset();
    357     m_cntrl = NULL;
    358 
    359     ValueObjectSP valobj_sp = m_backend.GetSP();
    360     if (!valobj_sp)
    361         return false;
    362 
    363     TargetSP target_sp(valobj_sp->GetTargetSP());
    364     if (!target_sp)
    365         return false;
    366 
    367     m_byte_order = target_sp->GetArchitecture().GetByteOrder();
    368     m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
    369 
    370     lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true));
    371 
    372     m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency
    373     return false;
    374 }
    375 
    376 bool
    377 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren ()
    378 {
    379     return true;
    380 }
    381 
    382 size_t
    383 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
    384 {
    385     if (name == ConstString("__ptr_"))
    386         return 0;
    387     if (name == ConstString("count"))
    388         return 1;
    389     if (name == ConstString("weak_count"))
    390         return 2;
    391     return UINT32_MAX;
    392 }
    393 
    394 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd ()
    395 {}
    396 
    397 SyntheticChildrenFrontEnd*
    398 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
    399 {
    400     if (!valobj_sp)
    401         return NULL;
    402     return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
    403 }
    404 
    405 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
    406     SyntheticChildrenFrontEnd(*valobj_sp.get()),
    407     m_start(NULL),
    408     m_finish(NULL),
    409     m_element_type(),
    410     m_element_size(0),
    411     m_children()
    412 {
    413     if (valobj_sp)
    414         Update();
    415 }
    416 
    417 size_t
    418 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
    419 {
    420     if (!m_start || !m_finish)
    421         return 0;
    422     uint64_t start_val = m_start->GetValueAsUnsigned(0);
    423     uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
    424 
    425     if (start_val == 0 || finish_val == 0)
    426         return 0;
    427 
    428     if (start_val >= finish_val)
    429         return 0;
    430 
    431     size_t num_children = (finish_val - start_val);
    432     if (num_children % m_element_size)
    433         return 0;
    434     return num_children/m_element_size;
    435 }
    436 
    437 lldb::ValueObjectSP
    438 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
    439 {
    440     if (!m_start || !m_finish)
    441         return lldb::ValueObjectSP();
    442 
    443     auto cached = m_children.find(idx);
    444     if (cached != m_children.end())
    445         return cached->second;
    446 
    447     uint64_t offset = idx * m_element_size;
    448     offset = offset + m_start->GetValueAsUnsigned(0);
    449     StreamString name;
    450     name.Printf("[%zu]",idx);
    451     ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
    452     m_children[idx] = child_sp;
    453     return child_sp;
    454 }
    455 
    456 bool
    457 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
    458 {
    459     m_start = m_finish = NULL;
    460     m_children.clear();
    461     ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
    462     if (!data_type_finder_sp)
    463         return false;
    464     data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
    465     if (!data_type_finder_sp)
    466         return false;
    467     m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
    468     m_element_size = m_element_type.GetByteSize();
    469 
    470     if (m_element_size > 0)
    471     {
    472         // store raw pointers or end up with a circular dependency
    473         m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
    474         m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
    475     }
    476     return false;
    477 }
    478 
    479 bool
    480 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
    481 {
    482     return true;
    483 }
    484 
    485 size_t
    486 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
    487 {
    488     if (!m_start || !m_finish)
    489         return UINT32_MAX;
    490     return ExtractIndexFromString(name.GetCString());
    491 }
    492 
    493 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
    494 {
    495     // these need to stay around because they are child objects who will follow their parent's life cycle
    496     // delete m_start;
    497     // delete m_finish;
    498 }
    499 
    500 SyntheticChildrenFrontEnd*
    501 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
    502 {
    503     if (!valobj_sp)
    504         return NULL;
    505     return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
    506 }
    507 
    508 bool
    509 lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream)
    510 {
    511     if (valobj.IsPointerType())
    512     {
    513         uint64_t value = valobj.GetValueAsUnsigned(0);
    514         if (!value)
    515             return false;
    516         stream.Printf("0x%016" PRIx64 " ", value);
    517     }
    518     return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj);
    519 }
    520