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