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
14#include "lldb/Target/Target.h"
16#include "lldb/Utility/Endian.h"
17#include "lldb/Utility/Status.h"
18#include "lldb/Utility/Stream.h"
21
22#include "llvm/Support/Error.h"
23
25
26using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::formatters;
29
31 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
32 time_t epoch = GetOSXEpoch();
33 epoch = epoch + (time_t)valobj.GetValueAsSigned(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,
41 tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,
42 tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
43 return true;
44}
45
47 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
48 static constexpr llvm::StringLiteral g_TypeHint("CFBag");
49
50 ProcessSP process_sp = valobj.GetProcessSP();
51 if (!process_sp)
52 return false;
53
54 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
55
56 if (!runtime)
57 return false;
58
60 runtime->GetClassDescriptor(valobj));
61
62 if (!descriptor.get() || !descriptor->IsValid())
63 return false;
64
65 uint32_t ptr_size = process_sp->GetAddressByteSize();
66
67 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
68
69 if (!valobj_addr)
70 return false;
71
72 uint32_t count = 0;
73
74 bool is_type_ok = false; // check to see if this is a CFBag we know about
75 if (descriptor->IsCFType()) {
76 llvm::StringRef type_name(valobj.GetTypeName().GetStringRef());
77
78 static constexpr llvm::StringLiteral g_CFBag("__CFBag");
79 static constexpr llvm::StringLiteral g_conststruct__CFBag(
80 "const struct __CFBag");
81
82 if (type_name == g_CFBag || type_name == g_conststruct__CFBag) {
83 if (valobj.IsPointerType())
84 is_type_ok = true;
85 }
86 }
87
88 if (is_type_ok) {
89 lldb::addr_t offset = 2 * ptr_size + 4 + valobj_addr;
91 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
92 if (error.Fail())
93 return false;
94 } else
95 return false;
96
97 llvm::StringRef prefix, suffix;
98 if (Language *language = Language::FindPlugin(options.GetLanguage()))
99 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
100
101 stream << prefix;
102 stream.Printf("\"%u value%s\"", count, (count == 1 ? "" : "s"));
103 stream << suffix;
104 return true;
105}
106
108 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
109 ProcessSP process_sp = valobj.GetProcessSP();
110 if (!process_sp)
111 return false;
112
113 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
114
115 if (!runtime)
116 return false;
117
119 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 llvm::StringRef type_name(valobj.GetTypeName().GetStringRef());
136
137 static constexpr llvm::StringLiteral g_CFMutableBitVector(
138 "__CFMutableBitVector");
139 static constexpr llvm::StringLiteral g_CFBitVector("__CFBitVector");
140 static constexpr llvm::StringLiteral g_CFMutableBitVectorRef(
141 "CFMutableBitVectorRef");
142 static constexpr llvm::StringLiteral g_CFBitVectorRef("CFBitVectorRef");
143
144 if (type_name == g_CFMutableBitVector || type_name == g_CFBitVector ||
145 type_name == g_CFMutableBitVectorRef || type_name == g_CFBitVectorRef) {
146 if (valobj.IsPointerType())
147 is_type_ok = true;
148 }
149 }
150
151 if (!is_type_ok)
152 return false;
153
155 count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size,
156 ptr_size, 0, error);
157 if (error.Fail())
158 return false;
159 uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);
160 llvm::Expected<addr_t> data_ptr = process_sp->ReadPointerFromMemory(
161 valobj_addr + 2 * ptr_size + 2 * ptr_size);
162 if (!data_ptr) {
163 llvm::consumeError(data_ptr.takeError());
164 return false;
165 }
166 // make sure we do not try to read huge amounts of data
167 if (num_bytes > 1024)
168 num_bytes = 1024;
169 WritableDataBufferSP buffer_sp(new DataBufferHeap(num_bytes, 0));
170 num_bytes = process_sp->ReadMemory(*data_ptr, buffer_sp->GetBytes(),
171 num_bytes, error);
172 if (error.Fail() || num_bytes == 0)
173 return false;
174 uint8_t *bytes = buffer_sp->GetBytes();
175 for (uint64_t byte_idx = 0; byte_idx < num_bytes - 1; byte_idx++) {
176 uint8_t byte = bytes[byte_idx];
177 bool bit0 = (byte & 1) == 1;
178 bool bit1 = (byte & 2) == 2;
179 bool bit2 = (byte & 4) == 4;
180 bool bit3 = (byte & 8) == 8;
181 bool bit4 = (byte & 16) == 16;
182 bool bit5 = (byte & 32) == 32;
183 bool bit6 = (byte & 64) == 64;
184 bool bit7 = (byte & 128) == 128;
185 stream.Printf("%c%c%c%c %c%c%c%c ", (bit7 ? '1' : '0'), (bit6 ? '1' : '0'),
186 (bit5 ? '1' : '0'), (bit4 ? '1' : '0'), (bit3 ? '1' : '0'),
187 (bit2 ? '1' : '0'), (bit1 ? '1' : '0'), (bit0 ? '1' : '0'));
188 count -= 8;
189 }
190 {
191 // print the last byte ensuring we do not print spurious bits
192 uint8_t byte = bytes[num_bytes - 1];
193 bool bit0 = (byte & 1) == 1;
194 bool bit1 = (byte & 2) == 2;
195 bool bit2 = (byte & 4) == 4;
196 bool bit3 = (byte & 8) == 8;
197 bool bit4 = (byte & 16) == 16;
198 bool bit5 = (byte & 32) == 32;
199 bool bit6 = (byte & 64) == 64;
200 bool bit7 = (byte & 128) == 128;
201 if (count) {
202 stream.Printf("%c", bit7 ? '1' : '0');
203 count -= 1;
204 }
205 if (count) {
206 stream.Printf("%c", bit6 ? '1' : '0');
207 count -= 1;
208 }
209 if (count) {
210 stream.Printf("%c", bit5 ? '1' : '0');
211 count -= 1;
212 }
213 if (count) {
214 stream.Printf("%c", bit4 ? '1' : '0');
215 count -= 1;
216 }
217 if (count) {
218 stream.Printf("%c", bit3 ? '1' : '0');
219 count -= 1;
220 }
221 if (count) {
222 stream.Printf("%c", bit2 ? '1' : '0');
223 count -= 1;
224 }
225 if (count) {
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
236 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
237 static constexpr llvm::StringLiteral g_TypeHint("CFBinaryHeap");
238
239 ProcessSP process_sp = valobj.GetProcessSP();
240 if (!process_sp)
241 return false;
242
243 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
244
245 if (!runtime)
246 return false;
247
249 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 =
264 false; // check to see if this is a CFBinaryHeap we know about
265 if (descriptor->IsCFType()) {
266 llvm::StringRef type_name(valobj.GetTypeName().GetStringRef());
267
268 static constexpr llvm::StringRef g_CFBinaryHeap("__CFBinaryHeap");
269 static constexpr llvm::StringRef g_conststruct__CFBinaryHeap(
270 "const struct __CFBinaryHeap");
271 static constexpr llvm::StringRef g_CFBinaryHeapRef("CFBinaryHeapRef");
272
273 if (type_name == g_CFBinaryHeap ||
274 type_name == g_conststruct__CFBinaryHeap ||
275 type_name == g_CFBinaryHeapRef) {
276 if (valobj.IsPointerType())
277 is_type_ok = true;
278 }
279 }
280
281 if (is_type_ok) {
282 lldb::addr_t offset = 2 * ptr_size + valobj_addr;
284 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
285 if (error.Fail())
286 return false;
287 } else
288 return false;
289
290 llvm::StringRef prefix, suffix;
291 if (Language *language = Language::FindPlugin(options.GetLanguage()))
292 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
293
294 stream << prefix;
295 stream.Printf("\"%u item%s\"", count, (count == 1 ? "" : "s"));
296 stream << suffix;
297 return true;
298}
static llvm::raw_ostream & error(Stream &strm)
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
A subclass of DataBuffer that stores a data buffer on the heap.
static Language * FindPlugin(lldb::LanguageType language)
Definition Language.cpp:84
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
An error handling class.
Definition Status.h:118
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:134
lldb::LanguageType GetLanguage() const
lldb::ProcessSP GetProcessSP() const
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
virtual ConstString GetTypeName()
virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success=nullptr)
bool CFBagSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:46
bool CFBinaryHeapSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:235
bool CFAbsoluteTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:30
bool CFBitVectorSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:107
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
uint64_t addr_t
Definition lldb-types.h:80