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/ObjCLanguageRuntime.h" 21 #include "lldb/Target/Target.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 using namespace lldb_private::formatters; 26 27 bool 28 lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 29 { 30 time_t epoch = GetOSXEpoch(); 31 epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0); 32 tm *tm_date = localtime(&epoch); 33 if (!tm_date) 34 return false; 35 std::string buffer(1024,0); 36 if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0) 37 return false; 38 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()); 39 return true; 40 } 41 42 bool 43 lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 44 { 45 ProcessSP process_sp = valobj.GetProcessSP(); 46 if (!process_sp) 47 return false; 48 49 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 50 51 if (!runtime) 52 return false; 53 54 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 55 56 if (!descriptor.get() || !descriptor->IsValid()) 57 return false; 58 59 uint32_t ptr_size = process_sp->GetAddressByteSize(); 60 61 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 62 63 if (!valobj_addr) 64 return false; 65 66 uint32_t count = 0; 67 68 bool is_type_ok = false; // check to see if this is a CFBag we know about 69 if (descriptor->IsCFType()) 70 { 71 ConstString type_name(valobj.GetTypeName()); 72 if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag")) 73 { 74 if (valobj.IsPointerType()) 75 is_type_ok = true; 76 } 77 } 78 79 if (is_type_ok == false) 80 { 81 StackFrameSP frame_sp(valobj.GetFrameSP()); 82 if (!frame_sp) 83 return false; 84 ValueObjectSP count_sp; 85 StreamString expr; 86 expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); 87 if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted) 88 return false; 89 if (!count_sp) 90 return false; 91 count = count_sp->GetValueAsUnsigned(0); 92 } 93 else 94 { 95 uint32_t offset = 2*ptr_size+4 + valobj_addr; 96 Error error; 97 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); 98 if (error.Fail()) 99 return false; 100 } 101 stream.Printf("@\"%u value%s\"", 102 count,(count == 1 ? "" : "s")); 103 return true; 104 } 105 106 bool 107 lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 108 { 109 ProcessSP process_sp = valobj.GetProcessSP(); 110 if (!process_sp) 111 return false; 112 113 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 114 115 if (!runtime) 116 return false; 117 118 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 119 120 if (!descriptor.get() || !descriptor->IsValid()) 121 return false; 122 123 uint32_t ptr_size = process_sp->GetAddressByteSize(); 124 125 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 126 127 if (!valobj_addr) 128 return false; 129 130 uint32_t count = 0; 131 132 bool is_type_ok = false; // check to see if this is a CFBag we know about 133 if (descriptor->IsCFType()) 134 { 135 ConstString type_name(valobj.GetTypeName()); 136 if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef")) 137 { 138 if (valobj.IsPointerType()) 139 is_type_ok = true; 140 } 141 } 142 143 if (is_type_ok == false) 144 return false; 145 146 Error error; 147 count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); 148 if (error.Fail()) 149 return false; 150 uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0); 151 addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error); 152 if (error.Fail()) 153 return false; 154 // make sure we do not try to read huge amounts of data 155 if (num_bytes > 1024) 156 num_bytes = 1024; 157 DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0)); 158 num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error); 159 if (error.Fail() || num_bytes == 0) 160 return false; 161 uint8_t *bytes = buffer_sp->GetBytes(); 162 for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++) 163 { 164 uint8_t byte = bytes[byte_idx]; 165 bool bit0 = (byte & 1) == 1; 166 bool bit1 = (byte & 2) == 2; 167 bool bit2 = (byte & 4) == 4; 168 bool bit3 = (byte & 8) == 8; 169 bool bit4 = (byte & 16) == 16; 170 bool bit5 = (byte & 32) == 32; 171 bool bit6 = (byte & 64) == 64; 172 bool bit7 = (byte & 128) == 128; 173 stream.Printf("%c%c%c%c %c%c%c%c ", 174 (bit7 ? '1' : '0'), 175 (bit6 ? '1' : '0'), 176 (bit5 ? '1' : '0'), 177 (bit4 ? '1' : '0'), 178 (bit3 ? '1' : '0'), 179 (bit2 ? '1' : '0'), 180 (bit1 ? '1' : '0'), 181 (bit0 ? '1' : '0')); 182 count -= 8; 183 } 184 { 185 // print the last byte ensuring we do not print spurious bits 186 uint8_t byte = bytes[num_bytes-1]; 187 bool bit0 = (byte & 1) == 1; 188 bool bit1 = (byte & 2) == 2; 189 bool bit2 = (byte & 4) == 4; 190 bool bit3 = (byte & 8) == 8; 191 bool bit4 = (byte & 16) == 16; 192 bool bit5 = (byte & 32) == 32; 193 bool bit6 = (byte & 64) == 64; 194 bool bit7 = (byte & 128) == 128; 195 if (count) 196 { 197 stream.Printf("%c",bit7 ? '1' : '0'); 198 count -= 1; 199 } 200 if (count) 201 { 202 stream.Printf("%c",bit6 ? '1' : '0'); 203 count -= 1; 204 } 205 if (count) 206 { 207 stream.Printf("%c",bit5 ? '1' : '0'); 208 count -= 1; 209 } 210 if (count) 211 { 212 stream.Printf("%c",bit4 ? '1' : '0'); 213 count -= 1; 214 } 215 if (count) 216 { 217 stream.Printf("%c",bit3 ? '1' : '0'); 218 count -= 1; 219 } 220 if (count) 221 { 222 stream.Printf("%c",bit2 ? '1' : '0'); 223 count -= 1; 224 } 225 if (count) 226 { 227 stream.Printf("%c",bit1 ? '1' : '0'); 228 count -= 1; 229 } 230 if (count) 231 stream.Printf("%c",bit0 ? '1' : '0'); 232 } 233 return true; 234 } 235 236 bool 237 lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 238 { 239 ProcessSP process_sp = valobj.GetProcessSP(); 240 if (!process_sp) 241 return false; 242 243 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 244 245 if (!runtime) 246 return false; 247 248 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 249 250 if (!descriptor.get() || !descriptor->IsValid()) 251 return false; 252 253 uint32_t ptr_size = process_sp->GetAddressByteSize(); 254 255 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 256 257 if (!valobj_addr) 258 return false; 259 260 uint32_t count = 0; 261 262 bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about 263 if (descriptor->IsCFType()) 264 { 265 ConstString type_name(valobj.GetTypeName()); 266 if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap")) 267 { 268 if (valobj.IsPointerType()) 269 is_type_ok = true; 270 } 271 } 272 273 if (is_type_ok == false) 274 { 275 StackFrameSP frame_sp(valobj.GetFrameSP()); 276 if (!frame_sp) 277 return false; 278 ValueObjectSP count_sp; 279 StreamString expr; 280 expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); 281 if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted) 282 return false; 283 if (!count_sp) 284 return false; 285 count = count_sp->GetValueAsUnsigned(0); 286 } 287 else 288 { 289 uint32_t offset = 2*ptr_size; 290 Error error; 291 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); 292 if (error.Fail()) 293 return false; 294 } 295 stream.Printf("@\"%u item%s\"", 296 count,(count == 1 ? "" : "s")); 297 return true; 298 } 299