static TypeAndOrName FixupTypeAndOrName (const TypeAndOrName& type_andor_name, ValueObject& parent) { TypeAndOrName ret(type_andor_name); if (type_andor_name.HasType()) { // The type will always be the type of the dynamic object. If our parent's type was a pointer, // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type // should be okay... ClangASTType orig_type = type_andor_name.GetClangASTType(); ClangASTType corrected_type = orig_type; if (parent.IsPointerType()) corrected_type = orig_type.GetPointerType (); else if (parent.IsPointerOrReferenceType()) corrected_type = orig_type.GetLValueReferenceType (); ret.SetClangASTType(corrected_type); } else /*if (m_dynamic_type_info.HasName())*/ { // If we are here we need to adjust our dynamic type name to include the correct & or * symbol std::string corrected_name (type_andor_name.GetName().GetCString()); if (parent.IsPointerType()) corrected_name.append(" *"); else if (parent.IsPointerOrReferenceType()) corrected_name.append(" &"); // the parent type should be a correctly pointer'ed or referenc'ed type ret.SetClangASTType(parent.GetClangType()); ret.SetName(corrected_name.c_str()); } return ret; }
bool AppleObjCRuntime::CouldHaveDynamicValue (ValueObject &in_value) { lldb::LanguageType known_type = in_value.GetObjectRuntimeLanguage(); if (known_type == lldb::eLanguageTypeObjC) return true; else return in_value.IsPointerType(); }
bool lldb_private::formatters::LibcxxContainerSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { if (valobj.IsPointerType()) { uint64_t value = valobj.GetValueAsUnsigned(0); if (!value) return false; stream.Printf("0x%016" PRIx64 " ", value); } return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr, nullptr, nullptr, &valobj, false, false); }
lldb::addr_t lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) { lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; if (valobj.IsPointerType()) data_addr = valobj.GetValueAsUnsigned(0); else if (valobj.IsArrayType()) data_addr = valobj.GetAddressOf(); return data_addr; }
bool lldb_private::formatters::GoStringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; if (valobj.IsPointerType()) { Error err; ValueObjectSP deref = valobj.Dereference(err); if (!err.Success()) return false; return GoStringSummaryProvider(*deref, stream, opts); } ConstString str_name("str"); ConstString len_name("len"); ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true); ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true); if (!data_sp || !len_sp) return false; bool success; lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success); if (!success) return false; uint64_t length = len_sp->GetValueAsUnsigned(0); if (length == 0) { stream.Printf("\"\""); return true; } StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetSourceSize(length); options.SetNeedsZeroTermination(false); options.SetLanguage(eLanguageTypeGo); if (!StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF8>(options)) { stream.Printf("Summary Unavailable"); return true; } return true; }
bool AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj) { // ObjC objects can only be pointers if (!valobj.IsPointerType()) return false; // Make the argument list: we pass one arg, the address of our pointer, to the print function. Value val; if (!valobj.ResolveValue(val.GetScalar())) return false; ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope()); }
bool lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t data_addr = 0; if (valobj.IsPointerType()) data_addr = valobj.GetValueAsUnsigned(0); else if (valobj.IsArrayType()) data_addr = valobj.GetAddressOf(); if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS) return false; clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); if (!ast) return false; ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(data_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); switch (wchar_size) { case 8: return ReadStringAndDumpToStream<StringElementType::UTF8>(options); case 16: return ReadStringAndDumpToStream<StringElementType::UTF16>(options); case 32: return ReadStringAndDumpToStream<StringElementType::UTF32>(options); default: stream.Printf("size for wchar_t is not valid"); return true; } return true; }
bool AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &object) { bool is_signed; // ObjC objects can only be pointers, but we extend this to integer types because an expression might just // result in an address, and we should try that to see if the address is an ObjC object. if (!(object.IsPointerType() || object.IsIntegerType(is_signed))) return NULL; // Make the argument list: we pass one arg, the address of our pointer, to the print function. Value val; if (!object.ResolveValue(val.GetScalar())) return NULL; return GetObjectDescription(str, val, object.GetExecutionContextScope()); }
bool lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); if (!descriptor.get() || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; uint32_t count = 0; bool is_type_ok = false; // check to see if this is a CFBag we know about if (descriptor->IsCFType()) { ConstString type_name(valobj.GetTypeName()); if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag")) { if (valobj.IsPointerType()) is_type_ok = true; } } if (is_type_ok == false) { StackFrameSP frame_sp(valobj.GetFrameSP()); if (!frame_sp) return false; ValueObjectSP count_sp; StreamString expr; expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExecutionCompleted) return false; if (!count_sp) return false; count = count_sp->GetValueAsUnsigned(0); } else { uint32_t offset = 2*ptr_size+4 + valobj_addr; Error error; count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); if (error.Fail()) return false; } stream.Printf("@\"%u value%s\"", count,(count == 1 ? "" : "s")); return true; }
bool lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); if (!descriptor.get() || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; uint32_t count = 0; bool is_type_ok = false; // check to see if this is a CFBag we know about if (descriptor->IsCFType()) { ConstString type_name(valobj.GetTypeName()); if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef")) { if (valobj.IsPointerType()) is_type_ok = true; } } if (is_type_ok == false) return false; Error error; count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); if (error.Fail()) return false; uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0); addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error); if (error.Fail()) return false; // make sure we do not try to read huge amounts of data if (num_bytes > 1024) num_bytes = 1024; DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0)); num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error); if (error.Fail() || num_bytes == 0) return false; uint8_t *bytes = buffer_sp->GetBytes(); for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++) { uint8_t byte = bytes[byte_idx]; bool bit0 = (byte & 1) == 1; bool bit1 = (byte & 2) == 2; bool bit2 = (byte & 4) == 4; bool bit3 = (byte & 8) == 8; bool bit4 = (byte & 16) == 16; bool bit5 = (byte & 32) == 32; bool bit6 = (byte & 64) == 64; bool bit7 = (byte & 128) == 128; stream.Printf("%c%c%c%c %c%c%c%c ", (bit7 ? '1' : '0'), (bit6 ? '1' : '0'), (bit5 ? '1' : '0'), (bit4 ? '1' : '0'), (bit3 ? '1' : '0'), (bit2 ? '1' : '0'), (bit1 ? '1' : '0'), (bit0 ? '1' : '0')); count -= 8; } { // print the last byte ensuring we do not print spurious bits uint8_t byte = bytes[num_bytes-1]; bool bit0 = (byte & 1) == 1; bool bit1 = (byte & 2) == 2; bool bit2 = (byte & 4) == 4; bool bit3 = (byte & 8) == 8; bool bit4 = (byte & 16) == 16; bool bit5 = (byte & 32) == 32; bool bit6 = (byte & 64) == 64; bool bit7 = (byte & 128) == 128; if (count) { stream.Printf("%c",bit7 ? '1' : '0'); count -= 1; } if (count) { stream.Printf("%c",bit6 ? '1' : '0'); count -= 1; } if (count) { stream.Printf("%c",bit5 ? '1' : '0'); count -= 1; } if (count) { stream.Printf("%c",bit4 ? '1' : '0'); count -= 1; } if (count) { stream.Printf("%c",bit3 ? '1' : '0'); count -= 1; } if (count) { stream.Printf("%c",bit2 ? '1' : '0'); count -= 1; } if (count) { stream.Printf("%c",bit1 ? '1' : '0'); count -= 1; } if (count) stream.Printf("%c",bit0 ? '1' : '0'); } return true; }
bool lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t data_addr = 0; if (valobj.IsPointerType()) data_addr = valobj.GetValueAsUnsigned(0); else if (valobj.IsArrayType()) data_addr = valobj.GetAddressOf(); if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS) return false; clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); if (!ast) return false; ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); const uint32_t wchar_size = wchar_clang_type.GetBitSize(); switch (wchar_size) { case 8: { // utf 8 ReadUTFBufferAndDumpToStreamOptions<UTF8> options; options.SetLocation(data_addr); options.SetConversionFunction(nullptr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); return ReadUTFBufferAndDumpToStream(options); } case 16: { // utf 16 ReadUTFBufferAndDumpToStreamOptions<UTF16> options; options.SetLocation(data_addr); options.SetConversionFunction(ConvertUTF16toUTF8); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); return ReadUTFBufferAndDumpToStream(options); } case 32: { // utf 32 ReadUTFBufferAndDumpToStreamOptions<UTF32> options; options.SetLocation(data_addr); options.SetConversionFunction(ConvertUTF32toUTF8); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); return ReadUTFBufferAndDumpToStream(options); } default: stream.Printf("size for wchar_t is not valid"); return true; } return true; }
bool lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { static ConstString g_TypeHint("CFBag"); ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); if (!descriptor.get() || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; uint32_t count = 0; bool is_type_ok = false; // check to see if this is a CFBag we know about if (descriptor->IsCFType()) { ConstString type_name(valobj.GetTypeName()); static ConstString g___CFBag("__CFBag"); static ConstString g_conststruct__CFBag("const struct __CFBag"); if (type_name == g___CFBag || type_name == g_conststruct__CFBag) { if (valobj.IsPointerType()) is_type_ok = true; } } if (is_type_ok) { lldb::addr_t offset = 2*ptr_size+4 + valobj_addr; Error error; count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); if (error.Fail()) return false; } else return false; std::string prefix,suffix; if (Language* language = Language::FindPlugin(options.GetLanguage())) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s\"%u value%s\"%s", prefix.c_str(), count,(count == 1 ? "" : "s"), suffix.c_str()); return true; }
bool lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { static ConstString g_TypeHint("CFBinaryHeap"); ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); if (!descriptor.get() || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; uint32_t count = 0; bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about if (descriptor->IsCFType()) { ConstString type_name(valobj.GetTypeName()); if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap")) { if (valobj.IsPointerType()) is_type_ok = true; } } if (is_type_ok == false) { StackFrameSP frame_sp(valobj.GetFrameSP()); if (!frame_sp) return false; ValueObjectSP count_sp; StreamString expr; expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); EvaluateExpressionOptions options; options.SetResultIsInternal(true); if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted) return false; if (!count_sp) return false; count = count_sp->GetValueAsUnsigned(0); } else { uint32_t offset = 2*ptr_size; Error error; count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); if (error.Fail()) return false; } std::string prefix,suffix; if (Language* language = Language::FindPlugin(options.GetLanguage())) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s\"%u item%s\"%s", prefix.c_str(), count,(count == 1 ? "" : "s"), suffix.c_str()); return true; }