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