Home | History | Annotate | Download | only in DataFormatters
      1 //===-- CF.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/Error.h"
     16 #include "lldb/Core/Stream.h"
     17 #include "lldb/Core/ValueObject.h"
     18 #include "lldb/Core/ValueObjectConstResult.h"
     19 #include "lldb/Host/Endian.h"
     20 #include "lldb/Symbol/ClangASTContext.h"
     21 #include "lldb/Target/ObjCLanguageRuntime.h"
     22 #include "lldb/Target/Target.h"
     23 
     24 using namespace lldb;
     25 using namespace lldb_private;
     26 using namespace lldb_private::formatters;
     27 
     28 bool
     29 lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream)
     30 {
     31     time_t epoch = GetOSXEpoch();
     32     epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0);
     33     tm *tm_date = localtime(&epoch);
     34     if (!tm_date)
     35         return false;
     36     std::string buffer(1024,0);
     37     if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
     38         return false;
     39     stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
     40     return true;
     41 }
     42 
     43 bool
     44 lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream)
     45 {
     46     ProcessSP process_sp = valobj.GetProcessSP();
     47     if (!process_sp)
     48         return false;
     49 
     50     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
     51 
     52     if (!runtime)
     53         return false;
     54 
     55     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
     56 
     57     if (!descriptor.get() || !descriptor->IsValid())
     58         return false;
     59 
     60     uint32_t ptr_size = process_sp->GetAddressByteSize();
     61 
     62     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
     63 
     64     if (!valobj_addr)
     65         return false;
     66 
     67     uint32_t count = 0;
     68 
     69     bool is_type_ok = false; // check to see if this is a CFBag we know about
     70     if (descriptor->IsCFType())
     71     {
     72         ConstString type_name(valobj.GetTypeName());
     73         if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag"))
     74         {
     75             if (valobj.IsPointerType())
     76                 is_type_ok = true;
     77         }
     78     }
     79 
     80     if (is_type_ok == false)
     81     {
     82         StackFrameSP frame_sp(valobj.GetFrameSP());
     83         if (!frame_sp)
     84             return false;
     85         ValueObjectSP count_sp;
     86         StreamString expr;
     87         expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
     88         if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted)
     89             return false;
     90         if (!count_sp)
     91             return false;
     92         count = count_sp->GetValueAsUnsigned(0);
     93     }
     94     else
     95     {
     96         uint32_t offset = 2*ptr_size+4 + valobj_addr;
     97         Error error;
     98         count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
     99         if (error.Fail())
    100             return false;
    101     }
    102     stream.Printf("@\"%u value%s\"",
    103                   count,(count == 1 ? "" : "s"));
    104     return true;
    105 }
    106 
    107 bool
    108 lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream)
    109 {
    110     ProcessSP process_sp = valobj.GetProcessSP();
    111     if (!process_sp)
    112         return false;
    113 
    114     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    115 
    116     if (!runtime)
    117         return false;
    118 
    119     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    120 
    121     if (!descriptor.get() || !descriptor->IsValid())
    122         return false;
    123 
    124     uint32_t ptr_size = process_sp->GetAddressByteSize();
    125 
    126     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    127 
    128     if (!valobj_addr)
    129         return false;
    130 
    131     uint32_t count = 0;
    132 
    133     bool is_type_ok = false; // check to see if this is a CFBag we know about
    134     if (descriptor->IsCFType())
    135     {
    136         ConstString type_name(valobj.GetTypeName());
    137         if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef"))
    138         {
    139             if (valobj.IsPointerType())
    140                 is_type_ok = true;
    141         }
    142     }
    143 
    144     if (is_type_ok == false)
    145         return false;
    146 
    147     Error error;
    148     count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
    149     if (error.Fail())
    150         return false;
    151     uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);
    152     addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error);
    153     if (error.Fail())
    154         return false;
    155     // make sure we do not try to read huge amounts of data
    156     if (num_bytes > 1024)
    157         num_bytes = 1024;
    158     DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0));
    159     num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);
    160     if (error.Fail() || num_bytes == 0)
    161         return false;
    162     uint8_t *bytes = buffer_sp->GetBytes();
    163     for (int byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
    164     {
    165         uint8_t byte = bytes[byte_idx];
    166         bool bit0 = (byte & 1) == 1;
    167         bool bit1 = (byte & 2) == 2;
    168         bool bit2 = (byte & 4) == 4;
    169         bool bit3 = (byte & 8) == 8;
    170         bool bit4 = (byte & 16) == 16;
    171         bool bit5 = (byte & 32) == 32;
    172         bool bit6 = (byte & 64) == 64;
    173         bool bit7 = (byte & 128) == 128;
    174         stream.Printf("%c%c%c%c %c%c%c%c ",
    175                       (bit7 ? '1' : '0'),
    176                       (bit6 ? '1' : '0'),
    177                       (bit5 ? '1' : '0'),
    178                       (bit4 ? '1' : '0'),
    179                       (bit3 ? '1' : '0'),
    180                       (bit2 ? '1' : '0'),
    181                       (bit1 ? '1' : '0'),
    182                       (bit0 ? '1' : '0'));
    183         count -= 8;
    184     }
    185     {
    186         // print the last byte ensuring we do not print spurious bits
    187         uint8_t byte = bytes[num_bytes-1];
    188         bool bit0 = (byte & 1) == 1;
    189         bool bit1 = (byte & 2) == 2;
    190         bool bit2 = (byte & 4) == 4;
    191         bool bit3 = (byte & 8) == 8;
    192         bool bit4 = (byte & 16) == 16;
    193         bool bit5 = (byte & 32) == 32;
    194         bool bit6 = (byte & 64) == 64;
    195         bool bit7 = (byte & 128) == 128;
    196         if (count)
    197         {
    198             stream.Printf("%c",bit7 ? '1' : '0');
    199             count -= 1;
    200         }
    201         if (count)
    202         {
    203             stream.Printf("%c",bit6 ? '1' : '0');
    204             count -= 1;
    205         }
    206         if (count)
    207         {
    208             stream.Printf("%c",bit5 ? '1' : '0');
    209             count -= 1;
    210         }
    211         if (count)
    212         {
    213             stream.Printf("%c",bit4 ? '1' : '0');
    214             count -= 1;
    215         }
    216         if (count)
    217         {
    218             stream.Printf("%c",bit3 ? '1' : '0');
    219             count -= 1;
    220         }
    221         if (count)
    222         {
    223             stream.Printf("%c",bit2 ? '1' : '0');
    224             count -= 1;
    225         }
    226         if (count)
    227         {
    228             stream.Printf("%c",bit1 ? '1' : '0');
    229             count -= 1;
    230         }
    231         if (count)
    232             stream.Printf("%c",bit0 ? '1' : '0');
    233     }
    234     return true;
    235 }
    236 
    237 bool
    238 lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream)
    239 {
    240     ProcessSP process_sp = valobj.GetProcessSP();
    241     if (!process_sp)
    242         return false;
    243 
    244     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    245 
    246     if (!runtime)
    247         return false;
    248 
    249     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    250 
    251     if (!descriptor.get() || !descriptor->IsValid())
    252         return false;
    253 
    254     uint32_t ptr_size = process_sp->GetAddressByteSize();
    255 
    256     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    257 
    258     if (!valobj_addr)
    259         return false;
    260 
    261     uint32_t count = 0;
    262 
    263     bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about
    264     if (descriptor->IsCFType())
    265     {
    266         ConstString type_name(valobj.GetTypeName());
    267         if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap"))
    268         {
    269             if (valobj.IsPointerType())
    270                 is_type_ok = true;
    271         }
    272     }
    273 
    274     if (is_type_ok == false)
    275     {
    276         StackFrameSP frame_sp(valobj.GetFrameSP());
    277         if (!frame_sp)
    278             return false;
    279         ValueObjectSP count_sp;
    280         StreamString expr;
    281         expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
    282         if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted)
    283             return false;
    284         if (!count_sp)
    285             return false;
    286         count = count_sp->GetValueAsUnsigned(0);
    287     }
    288     else
    289     {
    290         uint32_t offset = 2*ptr_size;
    291         Error error;
    292         count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
    293         if (error.Fail())
    294             return false;
    295     }
    296     stream.Printf("@\"%u item%s\"",
    297                   count,(count == 1 ? "" : "s"));
    298     return true;
    299 }
    300