124269Speter//===-- CF.cpp ----------------------------------------------------*- C++ -*-===// 224269Speter// 324269Speter// The LLVM Compiler Infrastructure 424269Speter// 524269Speter// This file is distributed under the University of Illinois Open Source 624269Speter// License. See LICENSE.TXT for details. 724269Speter// 824269Speter//===----------------------------------------------------------------------===// 924269Speter 1024269Speter#include "lldb/lldb-python.h" 1124269Speter 1224269Speter#include "lldb/DataFormatters/CXXFormatterFunctions.h" 1324269Speter 1424269Speter#include "lldb/Core/DataBufferHeap.h" 1524269Speter#include "lldb/Core/Error.h" 1624269Speter#include "lldb/Core/Stream.h" 1724269Speter#include "lldb/Core/ValueObject.h" 1824269Speter#include "lldb/Core/ValueObjectConstResult.h" 1924269Speter#include "lldb/Host/Endian.h" 2024269Speter#include "lldb/Symbol/ClangASTContext.h" 2124269Speter#include "lldb/Target/ObjCLanguageRuntime.h" 2224269Speter#include "lldb/Target/Target.h" 2324269Speter 2424269Speterusing namespace lldb; 2524269Speterusing namespace lldb_private; 2624269Speterusing namespace lldb_private::formatters; 2724269Speter 2824269Speterbool 2924269Speterlldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream) 3024269Speter{ 3124269Speter time_t epoch = GetOSXEpoch(); 3224269Speter epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0); 3324269Speter tm *tm_date = localtime(&epoch); 3424269Speter if (!tm_date) 3524269Speter return false; 3624269Speter std::string buffer(1024,0); 3724269Speter if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0) 3850477Speter return false; 3924269Speter 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()); 4024269Speter return true; 4124269Speter} 4224269Speter 4324269Speterbool 4428920Sfsmplldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream) 4528920Sfsmp{ 4628920Sfsmp ProcessSP process_sp = valobj.GetProcessSP(); 4724269Speter if (!process_sp) 4824269Speter return false; 4924269Speter 5024269Speter ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 5124269Speter 5224269Speter if (!runtime) 5327657Sfsmp return false; 5424269Speter 5524269Speter ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 5624269Speter 5724269Speter if (!descriptor.get() || !descriptor->IsValid()) 5824269Speter return false; 5924269Speter 6024269Speter uint32_t ptr_size = process_sp->GetAddressByteSize(); 6124269Speter 6242900Seivind lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 6342900Seivind 6442900Seivind if (!valobj_addr) 6542900Seivind return false; 6642900Seivind 6724269Speter uint32_t count = 0; 6824269Speter 6924269Speter bool is_type_ok = false; // check to see if this is a CFBag we know about 7024269Speter if (descriptor->IsCFType()) 7124269Speter { 7224269Speter ConstString type_name(valobj.GetTypeName()); 7324269Speter if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag")) 7424269Speter { 7524269Speter if (valobj.IsPointerType()) 7624269Speter is_type_ok = true; 7724269Speter } 7824269Speter } 7924269Speter 8024269Speter if (is_type_ok == false) 8124269Speter { 8224269Speter StackFrameSP frame_sp(valobj.GetFrameSP()); 8324269Speter if (!frame_sp) 8424269Speter return false; 8524269Speter ValueObjectSP count_sp; 8624269Speter StreamString expr; 8724269Speter expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); 8824269Speter if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted) 8924269Speter return false; 9024269Speter if (!count_sp) 9124269Speter return false; 9224269Speter count = count_sp->GetValueAsUnsigned(0); 9324269Speter } 9424269Speter else 9524269Speter { 9624269Speter uint32_t offset = 2*ptr_size+4 + valobj_addr; 9724269Speter Error error; 9824269Speter count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); 9924269Speter if (error.Fail()) 10024269Speter return false; 10124269Speter } 10224269Speter stream.Printf("@\"%u value%s\"", 10324269Speter count,(count == 1 ? "" : "s")); 10424269Speter return true; 10524269Speter} 10624269Speter 10724269Speterbool 10824269Speterlldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream) 10924269Speter{ 11024269Speter ProcessSP process_sp = valobj.GetProcessSP(); 11124269Speter if (!process_sp) 11224269Speter return false; 11324269Speter 11424269Speter ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 11524269Speter 11629653Sdyson if (!runtime) 11724269Speter return false; 11824269Speter 11924269Speter ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 12024269Speter 12129653Sdyson if (!descriptor.get() || !descriptor->IsValid()) 12224269Speter return false; 12324269Speter 12424269Speter uint32_t ptr_size = process_sp->GetAddressByteSize(); 12524269Speter 12624269Speter lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 12724269Speter 12824269Speter if (!valobj_addr) 12924269Speter return false; 13024269Speter 13124269Speter uint32_t count = 0; 13224269Speter 13324269Speter bool is_type_ok = false; // check to see if this is a CFBag we know about 13424269Speter if (descriptor->IsCFType()) 13524269Speter { 13624269Speter ConstString type_name(valobj.GetTypeName()); 13728345Sdyson if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef")) 13828345Sdyson { 13928345Sdyson if (valobj.IsPointerType()) 14032286Sdyson is_type_ok = true; 14124269Speter } 14224269Speter } 14328345Sdyson 14428345Sdyson if (is_type_ok == false) 14528345Sdyson return false; 14628345Sdyson 14728345Sdyson Error error; 14828345Sdyson count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); 14924269Speter if (error.Fail()) 15024269Speter return false; 15124269Speter uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0); 15224269Speter addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error); 15324269Speter if (error.Fail()) 15424269Speter return false; 15524269Speter // make sure we do not try to read huge amounts of data 15624269Speter if (num_bytes > 1024) 15724269Speter num_bytes = 1024; 15824269Speter DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0)); 15924269Speter num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error); 16024269Speter if (error.Fail() || num_bytes == 0) 16124269Speter return false; 16224269Speter uint8_t *bytes = buffer_sp->GetBytes(); 16324269Speter for (int byte_idx = 0; byte_idx < num_bytes-1; byte_idx++) 16424269Speter { 16524269Speter uint8_t byte = bytes[byte_idx]; 16624269Speter bool bit0 = (byte & 1) == 1; 16724269Speter bool bit1 = (byte & 2) == 2; 16824269Speter bool bit2 = (byte & 4) == 4; 16924269Speter bool bit3 = (byte & 8) == 8; 17024269Speter bool bit4 = (byte & 16) == 16; 17128345Sdyson bool bit5 = (byte & 32) == 32; 17224269Speter bool bit6 = (byte & 64) == 64; 17324269Speter bool bit7 = (byte & 128) == 128; 17424269Speter stream.Printf("%c%c%c%c %c%c%c%c ", 17524269Speter (bit7 ? '1' : '0'), 17642900Seivind (bit6 ? '1' : '0'), 17742900Seivind (bit5 ? '1' : '0'), 17842900Seivind (bit4 ? '1' : '0'), 17942900Seivind (bit3 ? '1' : '0'), 18042900Seivind (bit2 ? '1' : '0'), 18142900Seivind (bit1 ? '1' : '0'), 18242900Seivind (bit0 ? '1' : '0')); 18342900Seivind count -= 8; 18442900Seivind } 18542900Seivind { 18627894Sfsmp // print the last byte ensuring we do not print spurious bits 18724269Speter uint8_t byte = bytes[num_bytes-1]; 18842900Seivind bool bit0 = (byte & 1) == 1; 18924272Speter bool bit1 = (byte & 2) == 2; 19024269Speter bool bit2 = (byte & 4) == 4; 19148225Smckusick bool bit3 = (byte & 8) == 8; 19224269Speter bool bit4 = (byte & 16) == 16; 19324271Speter bool bit5 = (byte & 32) == 32; 19427894Sfsmp bool bit6 = (byte & 64) == 64; 19524269Speter bool bit7 = (byte & 128) == 128; 19627894Sfsmp if (count) 19724269Speter { 19827894Sfsmp stream.Printf("%c",bit7 ? '1' : '0'); 19924269Speter count -= 1; 20024269Speter } 20124271Speter if (count) 20224269Speter { 20342248Sbde stream.Printf("%c",bit6 ? '1' : '0'); 20424269Speter count -= 1; 20524269Speter } 20624269Speter if (count) 20724269Speter { 20824269Speter stream.Printf("%c",bit5 ? '1' : '0'); 20924271Speter count -= 1; 21024269Speter } 21124269Speter if (count) 212 { 213 stream.Printf("%c",bit4 ? '1' : '0'); 214 count -= 1; 215 } 216 if (count) 217 { 218 stream.Printf("%c",bit3 ? '1' : '0'); 219 count -= 1; 220 } 221 if (count) 222 { 223 stream.Printf("%c",bit2 ? '1' : '0'); 224 count -= 1; 225 } 226 if (count) 227 { 228 stream.Printf("%c",bit1 ? '1' : '0'); 229 count -= 1; 230 } 231 if (count) 232 stream.Printf("%c",bit0 ? '1' : '0'); 233 } 234 return true; 235} 236 237bool 238lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream) 239{ 240 ProcessSP process_sp = valobj.GetProcessSP(); 241 if (!process_sp) 242 return false; 243 244 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 245 246 if (!runtime) 247 return false; 248 249 ObjCLanguageRuntime::ClassDescriptorSP descriptor(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 = false; // check to see if this is a CFBinaryHeap we know about 264 if (descriptor->IsCFType()) 265 { 266 ConstString type_name(valobj.GetTypeName()); 267 if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap")) 268 { 269 if (valobj.IsPointerType()) 270 is_type_ok = true; 271 } 272 } 273 274 if (is_type_ok == false) 275 { 276 StackFrameSP frame_sp(valobj.GetFrameSP()); 277 if (!frame_sp) 278 return false; 279 ValueObjectSP count_sp; 280 StreamString expr; 281 expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); 282 if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted) 283 return false; 284 if (!count_sp) 285 return false; 286 count = count_sp->GetValueAsUnsigned(0); 287 } 288 else 289 { 290 uint32_t offset = 2*ptr_size; 291 Error error; 292 count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); 293 if (error.Fail()) 294 return false; 295 } 296 stream.Printf("@\"%u item%s\"", 297 count,(count == 1 ? "" : "s")); 298 return true; 299} 300