124269Speter//===-- CF.cpp ----------------------------------------------------*- C++ -*-===//
224269Speter//
324269Speter//                     The LLVM Compiler Infrastructure
424269Speter//
524269Speter// This file is distributed under the University of Illinois Open Source
624269Speter// License. See LICENSE.TXT for details.
724269Speter//
824269Speter//===----------------------------------------------------------------------===//
924269Speter
1024269Speter#include "lldb/lldb-python.h"
1124269Speter
1224269Speter#include "lldb/DataFormatters/CXXFormatterFunctions.h"
1324269Speter
1424269Speter#include "lldb/Core/DataBufferHeap.h"
1524269Speter#include "lldb/Core/Error.h"
1624269Speter#include "lldb/Core/Stream.h"
1724269Speter#include "lldb/Core/ValueObject.h"
1824269Speter#include "lldb/Core/ValueObjectConstResult.h"
1924269Speter#include "lldb/Host/Endian.h"
2024269Speter#include "lldb/Symbol/ClangASTContext.h"
2124269Speter#include "lldb/Target/ObjCLanguageRuntime.h"
2224269Speter#include "lldb/Target/Target.h"
2324269Speter
2424269Speterusing namespace lldb;
2524269Speterusing namespace lldb_private;
2624269Speterusing namespace lldb_private::formatters;
2724269Speter
2824269Speterbool
2924269Speterlldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream)
3024269Speter{
3124269Speter    time_t epoch = GetOSXEpoch();
3224269Speter    epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0);
3324269Speter    tm *tm_date = localtime(&epoch);
3424269Speter    if (!tm_date)
3524269Speter        return false;
3624269Speter    std::string buffer(1024,0);
3724269Speter    if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
3850477Speter        return false;
3924269Speter    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());
4024269Speter    return true;
4124269Speter}
4224269Speter
4324269Speterbool
4428920Sfsmplldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream)
4528920Sfsmp{
4628920Sfsmp    ProcessSP process_sp = valobj.GetProcessSP();
4724269Speter    if (!process_sp)
4824269Speter        return false;
4924269Speter
5024269Speter    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
5124269Speter
5224269Speter    if (!runtime)
5327657Sfsmp        return false;
5424269Speter
5524269Speter    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
5624269Speter
5724269Speter    if (!descriptor.get() || !descriptor->IsValid())
5824269Speter        return false;
5924269Speter
6024269Speter    uint32_t ptr_size = process_sp->GetAddressByteSize();
6124269Speter
6242900Seivind    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
6342900Seivind
6442900Seivind    if (!valobj_addr)
6542900Seivind        return false;
6642900Seivind
6724269Speter    uint32_t count = 0;
6824269Speter
6924269Speter    bool is_type_ok = false; // check to see if this is a CFBag we know about
7024269Speter    if (descriptor->IsCFType())
7124269Speter    {
7224269Speter        ConstString type_name(valobj.GetTypeName());
7324269Speter        if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag"))
7424269Speter        {
7524269Speter            if (valobj.IsPointerType())
7624269Speter                is_type_ok = true;
7724269Speter        }
7824269Speter    }
7924269Speter
8024269Speter    if (is_type_ok == false)
8124269Speter    {
8224269Speter        StackFrameSP frame_sp(valobj.GetFrameSP());
8324269Speter        if (!frame_sp)
8424269Speter            return false;
8524269Speter        ValueObjectSP count_sp;
8624269Speter        StreamString expr;
8724269Speter        expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
8824269Speter        if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted)
8924269Speter            return false;
9024269Speter        if (!count_sp)
9124269Speter            return false;
9224269Speter        count = count_sp->GetValueAsUnsigned(0);
9324269Speter    }
9424269Speter    else
9524269Speter    {
9624269Speter        uint32_t offset = 2*ptr_size+4 + valobj_addr;
9724269Speter        Error error;
9824269Speter        count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
9924269Speter        if (error.Fail())
10024269Speter            return false;
10124269Speter    }
10224269Speter    stream.Printf("@\"%u value%s\"",
10324269Speter                  count,(count == 1 ? "" : "s"));
10424269Speter    return true;
10524269Speter}
10624269Speter
10724269Speterbool
10824269Speterlldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream)
10924269Speter{
11024269Speter    ProcessSP process_sp = valobj.GetProcessSP();
11124269Speter    if (!process_sp)
11224269Speter        return false;
11324269Speter
11424269Speter    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
11524269Speter
11629653Sdyson    if (!runtime)
11724269Speter        return false;
11824269Speter
11924269Speter    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
12024269Speter
12129653Sdyson    if (!descriptor.get() || !descriptor->IsValid())
12224269Speter        return false;
12324269Speter
12424269Speter    uint32_t ptr_size = process_sp->GetAddressByteSize();
12524269Speter
12624269Speter    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
12724269Speter
12824269Speter    if (!valobj_addr)
12924269Speter        return false;
13024269Speter
13124269Speter    uint32_t count = 0;
13224269Speter
13324269Speter    bool is_type_ok = false; // check to see if this is a CFBag we know about
13424269Speter    if (descriptor->IsCFType())
13524269Speter    {
13624269Speter        ConstString type_name(valobj.GetTypeName());
13728345Sdyson        if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef"))
13828345Sdyson        {
13928345Sdyson            if (valobj.IsPointerType())
14032286Sdyson                is_type_ok = true;
14124269Speter        }
14224269Speter    }
14328345Sdyson
14428345Sdyson    if (is_type_ok == false)
14528345Sdyson        return false;
14628345Sdyson
14728345Sdyson    Error error;
14828345Sdyson    count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
14924269Speter    if (error.Fail())
15024269Speter        return false;
15124269Speter    uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);
15224269Speter    addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error);
15324269Speter    if (error.Fail())
15424269Speter        return false;
15524269Speter    // make sure we do not try to read huge amounts of data
15624269Speter    if (num_bytes > 1024)
15724269Speter        num_bytes = 1024;
15824269Speter    DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0));
15924269Speter    num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);
16024269Speter    if (error.Fail() || num_bytes == 0)
16124269Speter        return false;
16224269Speter    uint8_t *bytes = buffer_sp->GetBytes();
16324269Speter    for (int byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
16424269Speter    {
16524269Speter        uint8_t byte = bytes[byte_idx];
16624269Speter        bool bit0 = (byte & 1) == 1;
16724269Speter        bool bit1 = (byte & 2) == 2;
16824269Speter        bool bit2 = (byte & 4) == 4;
16924269Speter        bool bit3 = (byte & 8) == 8;
17024269Speter        bool bit4 = (byte & 16) == 16;
17128345Sdyson        bool bit5 = (byte & 32) == 32;
17224269Speter        bool bit6 = (byte & 64) == 64;
17324269Speter        bool bit7 = (byte & 128) == 128;
17424269Speter        stream.Printf("%c%c%c%c %c%c%c%c ",
17524269Speter                      (bit7 ? '1' : '0'),
17642900Seivind                      (bit6 ? '1' : '0'),
17742900Seivind                      (bit5 ? '1' : '0'),
17842900Seivind                      (bit4 ? '1' : '0'),
17942900Seivind                      (bit3 ? '1' : '0'),
18042900Seivind                      (bit2 ? '1' : '0'),
18142900Seivind                      (bit1 ? '1' : '0'),
18242900Seivind                      (bit0 ? '1' : '0'));
18342900Seivind        count -= 8;
18442900Seivind    }
18542900Seivind    {
18627894Sfsmp        // print the last byte ensuring we do not print spurious bits
18724269Speter        uint8_t byte = bytes[num_bytes-1];
18842900Seivind        bool bit0 = (byte & 1) == 1;
18924272Speter        bool bit1 = (byte & 2) == 2;
19024269Speter        bool bit2 = (byte & 4) == 4;
19148225Smckusick        bool bit3 = (byte & 8) == 8;
19224269Speter        bool bit4 = (byte & 16) == 16;
19324271Speter        bool bit5 = (byte & 32) == 32;
19427894Sfsmp        bool bit6 = (byte & 64) == 64;
19524269Speter        bool bit7 = (byte & 128) == 128;
19627894Sfsmp        if (count)
19724269Speter        {
19827894Sfsmp            stream.Printf("%c",bit7 ? '1' : '0');
19924269Speter            count -= 1;
20024269Speter        }
20124271Speter        if (count)
20224269Speter        {
20342248Sbde            stream.Printf("%c",bit6 ? '1' : '0');
20424269Speter            count -= 1;
20524269Speter        }
20624269Speter        if (count)
20724269Speter        {
20824269Speter            stream.Printf("%c",bit5 ? '1' : '0');
20924271Speter            count -= 1;
21024269Speter        }
21124269Speter        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
237bool
238lldb_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