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