LLDB mainline
CF.cpp
Go to the documentation of this file.
1//===-- CF.cpp ------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CF.h"
10
17#include "lldb/Target/Target.h"
19#include "lldb/Utility/Endian.h"
20#include "lldb/Utility/Status.h"
21#include "lldb/Utility/Stream.h"
22
24
25using namespace lldb;
26using namespace lldb_private;
27using namespace lldb_private::formatters;
28
30 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
31 time_t epoch = GetOSXEpoch();
32 epoch = epoch + (time_t)valobj.GetValueAsSigned(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,
40 tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,
41 tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
42 return true;
43}
44
46 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
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::Get(*process_sp);
54
55 if (!runtime)
56 return false;
57
59 runtime->GetClassDescriptor(valobj));
60
61 if (!descriptor.get() || !descriptor->IsValid())
62 return false;
63
64 uint32_t ptr_size = process_sp->GetAddressByteSize();
65
66 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
67
68 if (!valobj_addr)
69 return false;
70
71 uint32_t count = 0;
72
73 bool is_type_ok = false; // check to see if this is a CFBag we know about
74 if (descriptor->IsCFType()) {
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 || type_name == g_conststruct__CFBag) {
81 if (valobj.IsPointerType())
82 is_type_ok = true;
83 }
84 }
85
86 if (is_type_ok) {
87 lldb::addr_t offset = 2 * ptr_size + 4 + valobj_addr;
89 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
90 if (error.Fail())
91 return false;
92 } else
93 return false;
94
95 std::string prefix, suffix;
96 if (Language *language = Language::FindPlugin(options.GetLanguage())) {
97 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
98 suffix)) {
99 prefix.clear();
100 suffix.clear();
101 }
102 }
103
104 stream.Printf("%s\"%u value%s\"%s", prefix.c_str(), count,
105 (count == 1 ? "" : "s"), suffix.c_str());
106 return true;
107}
108
110 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
111 ProcessSP process_sp = valobj.GetProcessSP();
112 if (!process_sp)
113 return false;
114
115 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
116
117 if (!runtime)
118 return false;
119
121 runtime->GetClassDescriptor(valobj));
122
123 if (!descriptor.get() || !descriptor->IsValid())
124 return false;
125
126 uint32_t ptr_size = process_sp->GetAddressByteSize();
127
128 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
129
130 if (!valobj_addr)
131 return false;
132
133 uint32_t count = 0;
134
135 bool is_type_ok = false; // check to see if this is a CFBag we know about
136 if (descriptor->IsCFType()) {
137 ConstString type_name(valobj.GetTypeName());
138 if (type_name == "__CFMutableBitVector" || type_name == "__CFBitVector" ||
139 type_name == "CFMutableBitVectorRef" || type_name == "CFBitVectorRef") {
140 if (valobj.IsPointerType())
141 is_type_ok = true;
142 }
143 }
144
145 if (!is_type_ok)
146 return false;
147
149 count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size,
150 ptr_size, 0, error);
151 if (error.Fail())
152 return false;
153 uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);
154 addr_t data_ptr = process_sp->ReadPointerFromMemory(
155 valobj_addr + 2 * ptr_size + 2 * ptr_size, error);
156 if (error.Fail())
157 return false;
158 // make sure we do not try to read huge amounts of data
159 if (num_bytes > 1024)
160 num_bytes = 1024;
161 WritableDataBufferSP buffer_sp(new DataBufferHeap(num_bytes, 0));
162 num_bytes =
163 process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);
164 if (error.Fail() || num_bytes == 0)
165 return false;
166 uint8_t *bytes = buffer_sp->GetBytes();
167 for (uint64_t byte_idx = 0; byte_idx < num_bytes - 1; byte_idx++) {
168 uint8_t byte = bytes[byte_idx];
169 bool bit0 = (byte & 1) == 1;
170 bool bit1 = (byte & 2) == 2;
171 bool bit2 = (byte & 4) == 4;
172 bool bit3 = (byte & 8) == 8;
173 bool bit4 = (byte & 16) == 16;
174 bool bit5 = (byte & 32) == 32;
175 bool bit6 = (byte & 64) == 64;
176 bool bit7 = (byte & 128) == 128;
177 stream.Printf("%c%c%c%c %c%c%c%c ", (bit7 ? '1' : '0'), (bit6 ? '1' : '0'),
178 (bit5 ? '1' : '0'), (bit4 ? '1' : '0'), (bit3 ? '1' : '0'),
179 (bit2 ? '1' : '0'), (bit1 ? '1' : '0'), (bit0 ? '1' : '0'));
180 count -= 8;
181 }
182 {
183 // print the last byte ensuring we do not print spurious bits
184 uint8_t byte = bytes[num_bytes - 1];
185 bool bit0 = (byte & 1) == 1;
186 bool bit1 = (byte & 2) == 2;
187 bool bit2 = (byte & 4) == 4;
188 bool bit3 = (byte & 8) == 8;
189 bool bit4 = (byte & 16) == 16;
190 bool bit5 = (byte & 32) == 32;
191 bool bit6 = (byte & 64) == 64;
192 bool bit7 = (byte & 128) == 128;
193 if (count) {
194 stream.Printf("%c", bit7 ? '1' : '0');
195 count -= 1;
196 }
197 if (count) {
198 stream.Printf("%c", bit6 ? '1' : '0');
199 count -= 1;
200 }
201 if (count) {
202 stream.Printf("%c", bit5 ? '1' : '0');
203 count -= 1;
204 }
205 if (count) {
206 stream.Printf("%c", bit4 ? '1' : '0');
207 count -= 1;
208 }
209 if (count) {
210 stream.Printf("%c", bit3 ? '1' : '0');
211 count -= 1;
212 }
213 if (count) {
214 stream.Printf("%c", bit2 ? '1' : '0');
215 count -= 1;
216 }
217 if (count) {
218 stream.Printf("%c", bit1 ? '1' : '0');
219 count -= 1;
220 }
221 if (count)
222 stream.Printf("%c", bit0 ? '1' : '0');
223 }
224 return true;
225}
226
228 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
229 static ConstString g_TypeHint("CFBinaryHeap");
230
231 ProcessSP process_sp = valobj.GetProcessSP();
232 if (!process_sp)
233 return false;
234
235 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
236
237 if (!runtime)
238 return false;
239
241 runtime->GetClassDescriptor(valobj));
242
243 if (!descriptor.get() || !descriptor->IsValid())
244 return false;
245
246 uint32_t ptr_size = process_sp->GetAddressByteSize();
247
248 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
249
250 if (!valobj_addr)
251 return false;
252
253 uint32_t count = 0;
254
255 bool is_type_ok =
256 false; // check to see if this is a CFBinaryHeap we know about
257 if (descriptor->IsCFType()) {
258 ConstString type_name(valobj.GetTypeName());
259
260 static ConstString g_CFBinaryHeap("__CFBinaryHeap");
261 static ConstString g_conststruct__CFBinaryHeap(
262 "const struct __CFBinaryHeap");
263 static ConstString g_CFBinaryHeapRef("CFBinaryHeapRef");
264
265 if (type_name == g_CFBinaryHeap ||
266 type_name == g_conststruct__CFBinaryHeap ||
267 type_name == g_CFBinaryHeapRef) {
268 if (valobj.IsPointerType())
269 is_type_ok = true;
270 }
271 }
272
273 if (is_type_ok) {
274 lldb::addr_t offset = 2 * ptr_size + valobj_addr;
276 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
277 if (error.Fail())
278 return false;
279 } else
280 return false;
281
282 std::string prefix, suffix;
283 if (Language *language = Language::FindPlugin(options.GetLanguage())) {
284 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
285 suffix)) {
286 prefix.clear();
287 suffix.clear();
288 }
289 }
290
291 stream.Printf("%s\"%u item%s\"%s", prefix.c_str(), count,
292 (count == 1 ? "" : "s"), suffix.c_str());
293 return true;
294}
static llvm::raw_ostream & error(Stream &strm)
A uniqued constant string class.
Definition: ConstString.h:39
A subclass of DataBuffer that stores a data buffer on the heap.
static Language * FindPlugin(lldb::LanguageType language)
Definition: Language.cpp:53
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
An error handling class.
Definition: Status.h:44
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb::LanguageType GetLanguage() const
Definition: TypeSummary.cpp:31
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:338
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
virtual ConstString GetTypeName()
Definition: ValueObject.h:365
virtual bool IsPointerType()
Definition: ValueObject.h:382
virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success=nullptr)
bool CFBagSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:45
bool CFBinaryHeapSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:227
bool CFAbsoluteTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:29
bool CFBitVectorSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:109
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
uint64_t addr_t
Definition: lldb-types.h:83