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