CF.cpp revision 884288bcb6824452a3c64eb772c0976501acc47a
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
24using namespace lldb;
25using namespace lldb_private;
26using namespace lldb_private::formatters;
27
28bool
29lldb_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
43bool
44lldb_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
107bool
108lldb_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())
161        return false;
162    for (int byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
163    {
164        uint8_t byte = buffer_sp->GetBytes()[byte_idx];
165        bool bit0 = (byte & 1) == 1;
166        bool bit1 = (byte & 2) == 2;
167        bool bit2 = (byte & 4) == 4;
168        bool bit3 = (byte & 8) == 8;
169        bool bit4 = (byte & 16) == 16;
170        bool bit5 = (byte & 32) == 32;
171        bool bit6 = (byte & 64) == 64;
172        bool bit7 = (byte & 128) == 128;
173        stream.Printf("%c%c%c%c %c%c%c%c ",
174                      (bit7 ? '1' : '0'),
175                      (bit6 ? '1' : '0'),
176                      (bit5 ? '1' : '0'),
177                      (bit4 ? '1' : '0'),
178                      (bit3 ? '1' : '0'),
179                      (bit2 ? '1' : '0'),
180                      (bit1 ? '1' : '0'),
181                      (bit0 ? '1' : '0'));
182        count -= 8;
183    }
184    {
185        // print the last byte ensuring we do not print spurious bits
186        uint8_t byte = buffer_sp->GetBytes()[num_bytes-1];
187        bool bit0 = (byte & 1) == 1;
188        bool bit1 = (byte & 2) == 2;
189        bool bit2 = (byte & 4) == 4;
190        bool bit3 = (byte & 8) == 8;
191        bool bit4 = (byte & 16) == 16;
192        bool bit5 = (byte & 32) == 32;
193        bool bit6 = (byte & 64) == 64;
194        bool bit7 = (byte & 128) == 128;
195        if (count)
196        {
197            stream.Printf("%c",bit7 ? '1' : '0');
198            count -= 1;
199        }
200        if (count)
201        {
202            stream.Printf("%c",bit6 ? '1' : '0');
203            count -= 1;
204        }
205        if (count)
206        {
207            stream.Printf("%c",bit5 ? '1' : '0');
208            count -= 1;
209        }
210        if (count)
211        {
212            stream.Printf("%c",bit4 ? '1' : '0');
213            count -= 1;
214        }
215        if (count)
216        {
217            stream.Printf("%c",bit3 ? '1' : '0');
218            count -= 1;
219        }
220        if (count)
221        {
222            stream.Printf("%c",bit2 ? '1' : '0');
223            count -= 1;
224        }
225        if (count)
226        {
227            stream.Printf("%c",bit1 ? '1' : '0');
228            count -= 1;
229        }
230        if (count)
231        {
232            stream.Printf("%c",bit0 ? '1' : '0');
233            count -= 1;
234        }
235    }
236    return true;
237}
238
239bool
240lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream)
241{
242    ProcessSP process_sp = valobj.GetProcessSP();
243    if (!process_sp)
244        return false;
245
246    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
247
248    if (!runtime)
249        return false;
250
251    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
252
253    if (!descriptor.get() || !descriptor->IsValid())
254        return false;
255
256    uint32_t ptr_size = process_sp->GetAddressByteSize();
257
258    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
259
260    if (!valobj_addr)
261        return false;
262
263    uint32_t count = 0;
264
265    bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about
266    if (descriptor->IsCFType())
267    {
268        ConstString type_name(valobj.GetTypeName());
269        if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap"))
270        {
271            if (valobj.IsPointerType())
272                is_type_ok = true;
273        }
274    }
275
276    if (is_type_ok == false)
277    {
278        StackFrameSP frame_sp(valobj.GetFrameSP());
279        if (!frame_sp)
280            return false;
281        ValueObjectSP count_sp;
282        StreamString expr;
283        expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
284        if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted)
285            return false;
286        if (!count_sp)
287            return false;
288        count = count_sp->GetValueAsUnsigned(0);
289    }
290    else
291    {
292        uint32_t offset = 2*ptr_size;
293        Error error;
294        count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
295        if (error.Fail())
296            return false;
297    }
298    stream.Printf("@\"%u item%s\"",
299                  count,(count == 1 ? "" : "s"));
300    return true;
301}
302