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