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
CFAbsoluteTimeSummaryProvider(ValueObject & valobj,Stream & stream)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
CFBagSummaryProvider(ValueObject & valobj,Stream & stream)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
CFBitVectorSummaryProvider(ValueObject & valobj,Stream & stream)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
CFBinaryHeapSummaryProvider(ValueObject & valobj,Stream & stream)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