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