bool lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { TargetSP target_sp(valobj.GetTargetSP()); if (!target_sp) return false; uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize(); uint64_t pointer_value = valobj.GetValueAsUnsigned(0); if (!pointer_value) return false; pointer_value += addr_size; CompilerType type(valobj.GetCompilerType()); ExecutionContext exe_ctx(target_sp,false); ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type)); if (!child_ptr_sp) return false; DataExtractor data; Error error; child_ptr_sp->GetData(data, error); if (error.Fail()) return false; ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type)); child_sp->GetValueAsUnsigned(0); if (child_sp) return NSStringSummaryProvider(*child_sp, stream, options); return false; }
bool OCamlLanguage::IsNilReference(ValueObject &valobj) { if (!valobj.GetCompilerType().IsReferenceType()) return false; // If we failed to read the value then it is not a nil reference. return valobj.GetValueAsUnsigned(UINT64_MAX) == 0; }
bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) { const bool check_cxx = true; const bool check_objc = false; const bool check_swift = false; return in_value.GetCompilerType().IsPossibleDynamicType( NULL, check_cxx, check_objc, check_swift); }
bool lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo(); ValueObjectSP real_guy_sp = valobj.GetSP(); if (type_info & eTypeIsPointer) { Error err; real_guy_sp = valobj.Dereference(err); if (err.Fail() || !real_guy_sp) return false; } else if (type_info & eTypeIsReference) { real_guy_sp = valobj.GetChildAtIndex(0, true); if (!real_guy_sp) return false; } uint64_t value = real_guy_sp->GetValueAsUnsigned(0); if (value == 0) { stream.Printf("NO"); return true; } stream.Printf("YES"); return true; }
bool lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { lldb::ValueObjectSP valobj_sp; CompilerType charstar (valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType()); if (!charstar) return false; ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); if (is_sel_ptr) { lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (data_address == LLDB_INVALID_ADDRESS) return false; valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar); } else { DataExtractor data; Error error; valobj.GetData(data, error); if (error.Fail()) return false; valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar); } if (!valobj_sp) return false; stream.Printf("%s",valobj_sp->GetSummaryAsCString()); return true; }
bool AppleObjCRuntime::CouldHaveDynamicValue (ValueObject &in_value) { return in_value.GetCompilerType().IsPossibleDynamicType (NULL, false, // do not check C++ true); // check ObjC }
TypeAndOrName AppleObjCRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name, ValueObject& static_value) { CompilerType static_type(static_value.GetCompilerType()); Flags static_type_flags(static_type.GetTypeInfo()); TypeAndOrName ret(type_and_or_name); if (type_and_or_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... CompilerType orig_type = type_and_or_name.GetCompilerType(); CompilerType corrected_type = orig_type; if (static_type_flags.AllSet(eTypeIsPointer)) corrected_type = orig_type.GetPointerType (); ret.SetCompilerType(corrected_type); } else { // If we are here we need to adjust our dynamic type name to include the correct & or * symbol std::string corrected_name (type_and_or_name.GetName().GetCString()); if (static_type_flags.AllSet(eTypeIsPointer)) corrected_name.append(" *"); // the parent type should be a correctly pointer'ed or referenc'ed type ret.SetCompilerType(static_type); ret.SetName(corrected_name.c_str()); } return ret; }
bool AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj) { CompilerType compiler_type(valobj.GetCompilerType()); bool is_signed; // ObjC objects can only be pointers (or numbers that actually represents pointers // but haven't been typecast, because reasons..) if (!compiler_type.IsIntegerType (is_signed) && !compiler_type.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; // Value Objects may not have a process in their ExecutionContextRef. But we need to have one // in the ref we pass down to eventually call description. Get it from the target if it isn't // present. ExecutionContext exe_ctx; if (valobj.GetProcessSP()) { exe_ctx = ExecutionContext(valobj.GetExecutionContextRef()); } else { exe_ctx.SetContext(valobj.GetTargetSP(), true); if (!exe_ctx.HasProcessScope()) return false; } return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope()); }
bool lldb_private::formatters::swift::SwiftMetatype_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { lldb::addr_t metadata_ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (metadata_ptr == LLDB_INVALID_ADDRESS || metadata_ptr == 0) { CompilerType compiler_metatype_type(valobj.GetCompilerType()); CompilerType instancetype(compiler_metatype_type.GetInstanceType()); const char* ptr = instancetype.GetDisplayTypeName().AsCString(nullptr); if (ptr && *ptr) { stream.Printf("%s", ptr); return true; } } else { auto swift_runtime = valobj.GetProcessSP()->GetSwiftLanguageRuntime(); if (!swift_runtime) return false; SwiftLanguageRuntime::MetadataPromiseSP metadata_promise_sp = swift_runtime->GetMetadataPromise(metadata_ptr); if (CompilerType resolved_type = metadata_promise_sp->FulfillTypePromise()) { stream.Printf("%s", resolved_type.GetDisplayTypeName().AsCString()); return true; } } return false; }
bool lldb_private::formatters::swift::SwiftOptionalSummaryProvider::DoesPrintChildren (ValueObject* target_valobj) const { if (!target_valobj) return false; ValueObject *some = ExtractSomeIfAny(target_valobj,target_valobj->GetDynamicValueType(),true); if (!some) return true; lldb_private::Flags some_flags(some->GetCompilerType().GetTypeInfo()); if (some_flags.AllSet(eTypeIsSwift | eTypeInstanceIsPointer)) return true; lldb::TypeSummaryImplSP summary_sp = some->GetSummaryFormat(); if (!summary_sp) { if (lldb_private::DataVisualization::ShouldPrintAsOneLiner(*some)) return false; else return (some->GetNumChildren() > 0); } else return (some->GetNumChildren() > 0) && (summary_sp->DoesPrintChildren(some)); }
std::vector<ConstString> ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) { std::vector<ConstString> result; if (use_dynamic == lldb::eNoDynamicValues) return result; CompilerType compiler_type(valobj.GetCompilerType()); const bool check_cpp = false; const bool check_objc = true; bool canBeObjCDynamic = compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc); if (canBeObjCDynamic) { do { lldb::ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) break; ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime(); if (runtime == nullptr) break; ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj)); if (!objc_class_sp) break; if (ConstString name = objc_class_sp->GetClassName()) result.push_back(name); } while (false); } return result; }
bool lldb_private::formatters::NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) return false; lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS; CompilerType valobj_type(valobj.GetCompilerType()); Flags type_flags(valobj_type.GetTypeInfo()); if (type_flags.AllClear(eTypeHasValue)) { if (valobj.IsBaseClass() && valobj.GetParent()) ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); } else ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (ptr_value == LLDB_INVALID_ADDRESS) return false; size_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t code_location = ptr_value + 2 * ptr_size; lldb::addr_t domain_location = ptr_value + 3 * ptr_size; Error error; uint64_t code = process_sp->ReadUnsignedIntegerFromMemory(code_location, ptr_size, 0, error); if (error.Fail()) return false; lldb::addr_t domain_str_value = process_sp->ReadPointerFromMemory(domain_location, error); if (error.Fail() || domain_str_value == LLDB_INVALID_ADDRESS) return false; if (!domain_str_value) { stream.Printf("domain: nil - code: %" PRIu64, code); return true; } InferiorSizedWord isw(domain_str_value, *process_sp); ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData("domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()); if (!domain_str_sp) return false; StreamString domain_str_summary; if (NSStringSummaryProvider(*domain_str_sp, domain_str_summary, options) && !domain_str_summary.Empty()) { stream.Printf("domain: %s - code: %" PRIu64, domain_str_summary.GetData(), code); return true; } else { stream.Printf("domain: nil - code: %" PRIu64, code); return true; } }
BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool); if (auto target_sp = m_backend.GetTargetSP()) { m_byte_order = target_sp->GetArchitecture().GetByteOrder(); m_byte_size = target_sp->GetArchitecture().GetAddressByteSize(); Update(); } }
bool JavaLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &dynamic_address, Value::ValueType &value_type) { class_type_or_name.Clear(); // null references don't have a dynamic type if (in_value.IsNilReference()) return false; ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); if (!target) return false; ConstString linkage_name; CompilerType in_type = in_value.GetCompilerType(); if (in_type.IsPossibleDynamicType(nullptr, false, false)) linkage_name = GetDynamicTypeId(&exe_ctx, target, in_value); else linkage_name = JavaASTContext::GetLinkageName(in_type); if (!linkage_name) return false; class_type_or_name.SetName(in_type.GetNonReferenceType().GetTypeName()); SymbolContext sc; TypeList class_types; llvm::DenseSet<SymbolFile *> searched_symbol_files; size_t num_matches = target->GetImages().FindTypes(sc, linkage_name, true, // name_is_fully_qualified UINT32_MAX, searched_symbol_files, class_types); for (size_t i = 0; i < num_matches; ++i) { TypeSP type_sp = class_types.GetTypeAtIndex(i); CompilerType compiler_type = type_sp->GetFullCompilerType(); if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava) continue; if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) { class_type_or_name.SetTypeSP(type_sp); Value &value = in_value.GetValue(); value_type = value.GetValueType(); dynamic_address.SetRawAddress(value.GetScalar().ULongLong(0)); return true; } } return false; }
bool ObjCLanguage::IsNilReference (ValueObject& valobj) { const uint32_t mask = eTypeIsObjC | eTypeIsPointer; bool isObjCpointer = (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask); if (!isObjCpointer) return false; bool canReadValue = true; bool isZero = valobj.GetValueAsUnsigned(0,&canReadValue) == 0; return canReadValue && isZero; }
TypeAndOrName JavaLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) { CompilerType static_type(static_value.GetCompilerType()); TypeAndOrName ret(type_and_or_name); if (type_and_or_name.HasType()) { CompilerType orig_type = type_and_or_name.GetCompilerType(); if (static_type.IsReferenceType()) ret.SetCompilerType(orig_type.GetLValueReferenceType()); } return ret; }
bool lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { 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; const char* class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name,"NSBundle")) { uint64_t offset = 5 * ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); StreamString summary_stream; bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s",summary_stream.GetData()); return true; } } // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle] // which is encoded differently and needs to be handled by running code return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream); }
bool lldb_private::formatters::JavaArraySummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { if (valobj.IsPointerOrReferenceType()) { Error error; ValueObjectSP deref = valobj.Dereference(error); if (error.Fail()) return false; return JavaArraySummaryProvider(*deref, stream, options); } CompilerType type = valobj.GetCompilerType(); uint32_t size = JavaASTContext::CalculateArraySize(type, valobj); if (size == UINT32_MAX) return false; stream.Printf("[%u]{...}", size); return true; }
bool lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { 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 || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char* class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name,"NSBundle")) { uint64_t offset = 5 * ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); StreamString summary_stream; bool was_nsstring_ok = NSStringSummaryProvider(*text, summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s",summary_stream.GetData()); return true; } } return false; }
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; // Get a wchar_t basic type from the current type system CompilerType wchar_clang_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); if (!wchar_clang_type) return false; 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 lldb_private::formatters::WCharSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; Error error; valobj.GetData(data, error); if (error.Fail()) return false; // Get a wchar_t basic type from the current type system CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); if (!wchar_compiler_type) return false; const uint32_t wchar_size = wchar_compiler_type.GetBitSize( nullptr); // Safe to pass NULL for exe_scope here StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); options.SetData(data); options.SetStream(&stream); options.SetPrefixToken("L"); options.SetQuote('\''); options.SetSourceSize(1); options.SetBinaryZeroIsTerminator(false); switch (wchar_size) { case 8: return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF8>(options); case 16: return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); case 32: return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF32>(options); default: stream.Printf("size for wchar_t is not valid"); return true; } return true; }
bool AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj) { CompilerType compiler_type(valobj.GetCompilerType()); bool is_signed; // ObjC objects can only be pointers (or numbers that actually represents pointers // but haven't been typecast, because reasons..) if (!compiler_type.IsIntegerType (is_signed) && !compiler_type.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()); }
ObjCLanguageRuntime::ClassDescriptorSP ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) { ClassDescriptorSP objc_class_sp; // if we get an invalid VO (which might still happen when playing around // with pointers returned by the expression parser, don't consider this // a valid ObjC object) if (valobj.GetCompilerType().IsValid()) { addr_t isa_pointer = valobj.GetPointerValue(); if (isa_pointer != LLDB_INVALID_ADDRESS) { ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); Process *process = exe_ctx.GetProcessPtr(); if (process) { Error error; ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); if (isa != LLDB_INVALID_ADDRESS) objc_class_sp = GetClassDescriptorFromISA(isa); } } } return objc_class_sp; }
static lldb::addr_t DerefToNSErrorPointer(ValueObject &valobj) { CompilerType valobj_type(valobj.GetCompilerType()); Flags type_flags(valobj_type.GetTypeInfo()); if (type_flags.AllClear(eTypeHasValue)) { if (valobj.IsBaseClass() && valobj.GetParent()) return valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); } else { lldb::addr_t ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (type_flags.AllSet(eTypeIsPointer)) { CompilerType pointee_type(valobj_type.GetPointeeType()); Flags pointee_flags(pointee_type.GetTypeInfo()); if (pointee_flags.AllSet(eTypeIsPointer)) { if (ProcessSP process_sp = valobj.GetProcessSP()) { Status error; ptr_value = process_sp->ReadPointerFromMemory(ptr_value, error); } } } return ptr_value; } return LLDB_INVALID_ADDRESS; }
static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp, ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp, ValueObjectSP *reserved_sp) { ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) return false; lldb::addr_t ptr = LLDB_INVALID_ADDRESS; CompilerType valobj_type(valobj.GetCompilerType()); Flags type_flags(valobj_type.GetTypeInfo()); if (type_flags.AllClear(eTypeHasValue)) { if (valobj.IsBaseClass() && valobj.GetParent()) ptr = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); } else { ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); } if (ptr == LLDB_INVALID_ADDRESS) return false; size_t ptr_size = process_sp->GetAddressByteSize(); Status error; auto name = process_sp->ReadPointerFromMemory(ptr + 1 * ptr_size, error); if (error.Fail() || name == LLDB_INVALID_ADDRESS) return false; auto reason = process_sp->ReadPointerFromMemory(ptr + 2 * ptr_size, error); if (error.Fail() || reason == LLDB_INVALID_ADDRESS) return false; auto userinfo = process_sp->ReadPointerFromMemory(ptr + 3 * ptr_size, error); if (error.Fail() || userinfo == LLDB_INVALID_ADDRESS) return false; auto reserved = process_sp->ReadPointerFromMemory(ptr + 4 * ptr_size, error); if (error.Fail() || reserved == LLDB_INVALID_ADDRESS) return false; InferiorSizedWord name_isw(name, *process_sp); InferiorSizedWord reason_isw(reason, *process_sp); InferiorSizedWord userinfo_isw(userinfo, *process_sp); InferiorSizedWord reserved_isw(reserved, *process_sp); CompilerType voidstar = process_sp->GetTarget() .GetScratchClangASTContext() ->GetBasicType(lldb::eBasicTypeVoid) .GetPointerType(); if (name_sp) *name_sp = ValueObject::CreateValueObjectFromData( "name", name_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); if (reason_sp) *reason_sp = ValueObject::CreateValueObjectFromData( "reason", reason_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); if (userinfo_sp) *userinfo_sp = ValueObject::CreateValueObjectFromData( "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); if (reserved_sp) *reserved_sp = ValueObject::CreateValueObjectFromData( "reserved", reserved_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); return true; }
bool lldb_private::formatters::NSException_SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) return false; lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS; CompilerType valobj_type(valobj.GetCompilerType()); Flags type_flags(valobj_type.GetTypeInfo()); if (type_flags.AllClear(eTypeHasValue)) { if (valobj.IsBaseClass() && valobj.GetParent()) ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); } else ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (ptr_value == LLDB_INVALID_ADDRESS) return false; size_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t name_location = ptr_value + 1 * ptr_size; lldb::addr_t reason_location = ptr_value + 2 * ptr_size; Error error; lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error); if (error.Fail() || name == LLDB_INVALID_ADDRESS) return false; lldb::addr_t reason = process_sp->ReadPointerFromMemory(reason_location, error); if (error.Fail() || reason == LLDB_INVALID_ADDRESS) return false; InferiorSizedWord name_isw(name, *process_sp); InferiorSizedWord reason_isw(reason, *process_sp); CompilerType voidstar = process_sp->GetTarget() .GetScratchClangASTContext() ->GetBasicType(lldb::eBasicTypeVoid) .GetPointerType(); ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData( "name_str", name_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData( "reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); if (!name_sp || !reason_sp) return false; StreamString name_str_summary; StreamString reason_str_summary; if (NSStringSummaryProvider(*name_sp, name_str_summary, options) && NSStringSummaryProvider(*reason_sp, reason_str_summary, options) && !name_str_summary.Empty() && !reason_str_summary.Empty()) { stream.Printf("name: %s - reason: %s", name_str_summary.GetData(), reason_str_summary.GetData()); return true; } else return false; }
bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &dynamic_address, Value::ValueType &value_type) { // For Itanium, if the type has a vtable pointer in the object, it will be at // offset 0 // in the object. That will point to the "address point" within the vtable // (not the beginning of the // vtable.) We can then look up the symbol containing this "address point" // and that symbol's name // demangled will contain the full class name. // The second pointer above the "address point" is the "offset_to_top". We'll // use that to get the // start of the value object which holds the dynamic type. // class_type_or_name.Clear(); value_type = Value::ValueType::eValueTypeScalar; // Only a pointer or reference type can have a different dynamic and static // type: if (CouldHaveDynamicValue(in_value)) { // First job, pull out the address at 0 offset from the object. AddressType address_type; lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); if (original_ptr == LLDB_INVALID_ADDRESS) return false; ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); Process *process = exe_ctx.GetProcessPtr(); if (process == nullptr) return false; Error error; const lldb::addr_t vtable_address_point = process->ReadPointerFromMemory(original_ptr, error); if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) { return false; } class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, vtable_address_point); if (class_type_or_name) { TypeSP type_sp = class_type_or_name.GetTypeSP(); // There can only be one type with a given name, // so we've just found duplicate definitions, and this // one will do as well as any other. // We don't consider something to have a dynamic type if // it is the same as the static type. So compare against // the value we were handed. if (type_sp) { if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type_sp->GetForwardCompilerType())) { // The dynamic type we found was the same type, // so we don't have a dynamic type here... return false; } // The offset_to_top is two pointers above the vtable pointer. const uint32_t addr_byte_size = process->GetAddressByteSize(); const lldb::addr_t offset_to_top_location = vtable_address_point - 2 * addr_byte_size; // Watch for underflow, offset_to_top_location should be less than // vtable_address_point if (offset_to_top_location >= vtable_address_point) return false; const int64_t offset_to_top = process->ReadSignedIntegerFromMemory( offset_to_top_location, addr_byte_size, INT64_MIN, error); if (offset_to_top == INT64_MIN) return false; // So the dynamic type is a value that starts at offset_to_top // above the original address. lldb::addr_t dynamic_addr = original_ptr + offset_to_top; if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress( dynamic_addr, dynamic_address)) { dynamic_address.SetRawAddress(dynamic_addr); } return true; } } } return class_type_or_name.IsEmpty() == false; }
bool lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { 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; const char* class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (strcmp(class_name, "NSURL") == 0) { uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit) uint64_t offset_base = offset_text + ptr_size; CompilerType type(valobj.GetCompilerType()); ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true)); ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true)); if (!text) return false; if (text->GetValueAsUnsigned(0) == 0) return false; StreamString summary; if (!NSStringSummaryProvider(*text, summary, options)) return false; if (base && base->GetValueAsUnsigned(0)) { if (summary.GetSize() > 0) summary.GetString().resize(summary.GetSize()-1); summary.Printf(" -- "); StreamString base_summary; if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0) summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData()); } if (summary.GetSize()) { stream.Printf("%s",summary.GetData()); return true; } } else { return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream); } return false; }
std::unique_ptr<SwiftHashedContainerBufferHandler> SwiftHashedContainerBufferHandler::CreateBufferHandler (ValueObject& valobj, NativeCreatorFunction Native, SyntheticCreatorFunction Synthetic, ConstString mangled, ConstString demangled) { static ConstString g__variantStorage("_variantStorage"); static ConstString g_Native("native"); static ConstString g_Cocoa("cocoa"); static ConstString g_nativeStorage("nativeStorage"); static ConstString g_buffer("buffer"); static ConstString g_storage("storage"); static ConstString g__storage("_storage"); static ConstString g_Some("some"); Error error; ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) return nullptr; ConstString type_name_cs(valobj.GetTypeName()); if (type_name_cs) { llvm::StringRef type_name_strref(type_name_cs.GetStringRef()); if (type_name_strref.startswith(mangled.GetCString()) || type_name_strref.startswith(demangled.GetCString())) { return CreateBufferHandlerForNativeStorageOwner(valobj, valobj.GetPointerValue(), false, Native); } } ValueObjectSP valobj_sp = valobj.GetSP()->GetQualifiedRepresentationIfAvailable(lldb::eDynamicCanRunTarget, false); ValueObjectSP _variantStorageSP(valobj_sp->GetChildMemberWithName(g__variantStorage, true)); if (!_variantStorageSP) return nullptr; ConstString storage_kind(_variantStorageSP->GetValueAsCString()); if (!storage_kind) return nullptr; if (g_Cocoa == storage_kind) { ValueObjectSP child_sp(_variantStorageSP->GetChildMemberWithName(g_Native, true)); if (!child_sp) return nullptr; // it's an NSDictionary in disguise uint64_t cocoa_storage_ptr = child_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (cocoa_storage_ptr == LLDB_INVALID_ADDRESS || error.Fail()) return nullptr; cocoa_storage_ptr &= 0x00FFFFFFFFFFFFFF; // for some reason I need to zero out the MSB; figure out why later CompilerType id = process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID); InferiorSizedWord isw(cocoa_storage_ptr, *process_sp); ValueObjectSP cocoarr_sp = ValueObject::CreateValueObjectFromData("cocoarr", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), id); if (!cocoarr_sp) return nullptr; auto objc_runtime = process_sp->GetObjCLanguageRuntime(); auto descriptor_sp = objc_runtime->GetClassDescriptor(*cocoarr_sp); if (!descriptor_sp) return nullptr; ConstString classname(descriptor_sp->GetClassName()); if (classname && classname.GetStringRef().startswith(mangled.GetCString())) { return CreateBufferHandlerForNativeStorageOwner(*_variantStorageSP, cocoa_storage_ptr, true, Native); } else { auto handler = std::unique_ptr<SwiftHashedContainerBufferHandler>(Synthetic(cocoarr_sp)); if (handler && handler->IsValid()) return handler; return nullptr; } } if (g_Native == storage_kind) { ValueObjectSP native_sp(_variantStorageSP->GetChildAtNamePath({ g_Native })); ValueObjectSP nativeStorage_sp(_variantStorageSP->GetChildAtNamePath( { g_Native, g_nativeStorage } )); if (!native_sp || !nativeStorage_sp) return nullptr; CompilerType child_type(valobj.GetCompilerType()); lldb::TemplateArgumentKind kind; CompilerType key_type(child_type.GetTemplateArgument(0, kind)); CompilerType value_type(child_type.GetTemplateArgument(1, kind)); auto handler = std::unique_ptr<SwiftHashedContainerBufferHandler>(Native(nativeStorage_sp, key_type, value_type)); if (handler && handler->IsValid()) return handler; return nullptr; } return nullptr; }
bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &dynamic_address, Value::ValueType &value_type) { // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0 // in the object. That will point to the "address point" within the vtable (not the beginning of the // vtable.) We can then look up the symbol containing this "address point" and that symbol's name // demangled will contain the full class name. // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the // start of the value object which holds the dynamic type. // class_type_or_name.Clear(); value_type = Value::ValueType::eValueTypeScalar; // Only a pointer or reference type can have a different dynamic and static type: if (CouldHaveDynamicValue (in_value)) { // First job, pull out the address at 0 offset from the object. AddressType address_type; lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); if (original_ptr == LLDB_INVALID_ADDRESS) return false; ExecutionContext exe_ctx (in_value.GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); char memory_buffer[16]; DataExtractor data(memory_buffer, sizeof(memory_buffer), process->GetByteOrder(), process->GetAddressByteSize()); size_t address_byte_size = process->GetAddressByteSize(); Error error; size_t bytes_read = process->ReadMemory (original_ptr, memory_buffer, address_byte_size, error); if (!error.Success() || (bytes_read != address_byte_size)) { return false; } lldb::offset_t offset = 0; lldb::addr_t vtable_address_point = data.GetAddress (&offset); if (offset == 0) return false; // Now find the symbol that contains this address: SymbolContext sc; Address address_point_address; if (target && !target->GetSectionLoadList().IsEmpty()) { if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address)) { target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc); Symbol *symbol = sc.symbol; if (symbol != NULL) { const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString(); if (name && strstr(name, vtable_demangled_prefix) == name) { Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n", original_ptr, in_value.GetTypeName().GetCString(), name); // We are a C++ class, that's good. Get the class name and look it up: const char *class_name = name + strlen(vtable_demangled_prefix); class_type_or_name.SetName (class_name); const bool exact_match = true; TypeList class_types; uint32_t num_matches = 0; // First look in the module that the vtable symbol came from // and look for a single exact match. if (sc.module_sp) { num_matches = sc.module_sp->FindTypes (sc, ConstString(class_name), exact_match, 1, class_types); } // If we didn't find a symbol, then move on to the entire // module list in the target and get as many unique matches // as possible if (num_matches == 0) { num_matches = target->GetImages().FindTypes (sc, ConstString(class_name), exact_match, UINT32_MAX, class_types); } lldb::TypeSP type_sp; if (num_matches == 0) { if (log) log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr); return false; } if (num_matches == 1) { type_sp = class_types.GetTypeAtIndex(0); if (log) log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n", original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(), type_sp->GetName().GetCString()); class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0)); } else if (num_matches > 1) { size_t i; if (log) { for (i = 0; i < num_matches; i++) { type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { if (log) log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n", original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(), type_sp->GetName().GetCString()); } } } for (i = 0; i < num_matches; i++) { type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { if (ClangASTContext::IsCXXClassType(type_sp->GetFullCompilerType ())) { if (log) log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n", original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(), type_sp->GetName().GetCString()); class_type_or_name.SetTypeSP(type_sp); break; } } } if (i == num_matches) { if (log) log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n", original_ptr, in_value.GetTypeName().AsCString()); return false; } } // There can only be one type with a given name, // so we've just found duplicate definitions, and this // one will do as well as any other. // We don't consider something to have a dynamic type if // it is the same as the static type. So compare against // the value we were handed. if (type_sp) { if (ClangASTContext::AreTypesSame (in_value.GetCompilerType(), type_sp->GetFullCompilerType ())) { // The dynamic type we found was the same type, // so we don't have a dynamic type here... return false; } // The offset_to_top is two pointers above the address. Address offset_to_top_address = address_point_address; int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize()); offset_to_top_address.Slide (slide); Error error; lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target); size_t bytes_read = process->ReadMemory (offset_to_top_location, memory_buffer, address_byte_size, error); if (!error.Success() || (bytes_read != address_byte_size)) { return false; } offset = 0; int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize()); // So the dynamic type is a value that starts at offset_to_top // above the original address. lldb::addr_t dynamic_addr = original_ptr + offset_to_top; if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address)) { dynamic_address.SetRawAddress(dynamic_addr); } return true; } } } } } } return class_type_or_name.IsEmpty() == false; }