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