bool lldb_private::formatters::CXXFunctionPointerSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { std::string destination; StreamString sstr; AddressType func_ptr_address_type = eAddressTypeInvalid; addr_t func_ptr_address = valobj.GetPointerValue(&func_ptr_address_type); if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) { switch (func_ptr_address_type) { case eAddressTypeInvalid: case eAddressTypeFile: case eAddressTypeHost: break; case eAddressTypeLoad: { ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); Address so_addr; Target *target = exe_ctx.GetTargetPtr(); if (target && target->GetSectionLoadList().IsEmpty() == false) { if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) { so_addr.Dump(&sstr, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset); } } } break; } } if (sstr.GetSize() > 0) { stream.Printf("(%s)", sstr.GetData()); return true; } else return false; }
bool lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj, const char* target_type, const char* selector, Stream &stream) { if (!target_type || !*target_type) return false; if (!selector || !*selector) return false; StreamString expr; expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); lldb::ValueObjectSP result_sp; Target* target = exe_ctx.GetTargetPtr(); StackFrame* stack_frame = GetViableFrame(exe_ctx); if (!target || !stack_frame) return false; EvaluateExpressionOptions options; options.SetCoerceToId(false); options.SetUnwindOnError(true); options.SetKeepInMemory(true); options.SetUseDynamic(lldb::eDynamicCanRunTarget); target->EvaluateExpression(expr.GetData(), stack_frame, result_sp, options); if (!result_sp) return false; stream.Printf("%s",result_sp->GetSummaryAsCString()); return true; }
bool lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj, const char* target_type, const char* selector, uint64_t &value) { if (!target_type || !*target_type) return false; if (!selector || !*selector) return false; StreamString expr; expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); lldb::ValueObjectSP result_sp; Target* target = exe_ctx.GetTargetPtr(); StackFrame* stack_frame = exe_ctx.GetFramePtr(); if (!target || !stack_frame) return false; EvaluateExpressionOptions options; options.SetCoerceToId(false) .SetUnwindOnError(true) .SetKeepInMemory(true); target->EvaluateExpression(expr.GetData(), stack_frame, result_sp, options); if (!result_sp) return false; value = result_sp->GetValueAsUnsigned(0); return true; }
// this code relies on the assumption that an Objective-C object always starts // with an ISA at offset 0. ObjCLanguageRuntime::ObjCISA AppleObjCRuntimeV1::GetISA(ValueObject& valobj) { if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC) return 0; // 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.GetValue().GetContextType() == Value::eContextTypeInvalid) return 0; addr_t isa_pointer = valobj.GetPointerValue(); ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); Process *process = exe_ctx.GetProcessPtr(); if (process) { uint8_t pointer_size = process->GetAddressByteSize(); Error error; return process->ReadUnsignedIntegerFromMemory (isa_pointer, pointer_size, 0, error); } return 0; }
// for V1 runtime we just try to return a class name as that is the minimum level of support // required for the data formatters to work bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address) { class_type_or_name.Clear(); if (CouldHaveDynamicValue(in_value)) { auto class_descriptor(GetClassDescriptor(in_value)); if (class_descriptor && class_descriptor->IsValid() && class_descriptor->GetClassName()) { const addr_t object_ptr = in_value.GetPointerValue(); address.SetRawAddress(object_ptr); class_type_or_name.SetName(class_descriptor->GetClassName()); } } return class_type_or_name.IsEmpty() == false; }
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; }
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 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 ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &dynamic_address) { // 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(); // 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().AsCString(); if (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 (type_sp->GetClangFullType().IsCXXClassType()) { 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.GetClangType(), type_sp->GetClangFullType())) { // 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; }
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) { // 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. // // Only a pointer or reference type can have a different dynamic and static type: if (CouldHaveDynamicValue (in_value)) { // FIXME: Can we get the Clang Type and ask it if the thing is really virtual? That would avoid false positives, // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong. // 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; Target *target = in_value.GetUpdatePoint().GetTargetSP().get(); Process *process = in_value.GetUpdatePoint().GetProcessSP().get(); 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; } uint32_t offset_ptr = 0; lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr); if (offset_ptr == 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().AsCString(); if (strstr(name, vtable_demangled_prefix) == 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); TypeList class_types; uint32_t num_matches = target->GetImages().FindTypes (sc, ConstString(class_name), true, UINT32_MAX, class_types); if (num_matches == 1) { class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0)); } else if (num_matches > 1) { for (size_t i = 0; i < num_matches; i++) { lldb::TypeSP this_type(class_types.GetTypeAtIndex(i)); if (this_type) { if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType())) { // 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: clang::ASTContext *in_ast_ctx = in_value.GetClangAST (); clang::ASTContext *this_ast_ctx = this_type->GetClangAST (); if (in_ast_ctx != this_ast_ctx || !ClangASTContext::AreTypesSame (in_ast_ctx, in_value.GetClangType(), this_type->GetClangFullType())) { class_type_or_name.SetTypeSP (this_type); return true; } return false; } } } } else 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_ptr = 0; int64_t offset_to_top = data.GetMaxS64(&offset_ptr, 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.SetOffset(dynamic_addr); dynamic_address.SetSection(NULL); } return true; } } } } } return false; }
bool ValueObjectChild::UpdateValue () { m_error.Clear(); SetValueIsValid (false); ValueObject* parent = m_parent; if (parent) { if (parent->UpdateValueIfNeeded(false)) { m_value.SetClangType(GetClangType()); // Copy the parent scalar value and the scalar value type m_value.GetScalar() = parent->GetValue().GetScalar(); Value::ValueType value_type = parent->GetValue().GetValueType(); m_value.SetValueType (value_type); if (parent->GetClangType().IsPointerOrReferenceType ()) { lldb::addr_t addr = parent->GetPointerValue (); m_value.GetScalar() = addr; if (addr == LLDB_INVALID_ADDRESS) { m_error.SetErrorString ("parent address is invalid."); } else if (addr == 0) { m_error.SetErrorString ("parent is NULL"); } else { m_value.GetScalar() += m_byte_offset; AddressType addr_type = parent->GetAddressTypeOfChildren(); switch (addr_type) { case eAddressTypeFile: { lldb::ProcessSP process_sp (GetProcessSP()); if (process_sp && process_sp->IsAlive() == true) m_value.SetValueType (Value::eValueTypeLoadAddress); else m_value.SetValueType(Value::eValueTypeFileAddress); } break; case eAddressTypeLoad: m_value.SetValueType (Value::eValueTypeLoadAddress); break; case eAddressTypeHost: m_value.SetValueType(Value::eValueTypeHostAddress); break; case eAddressTypeInvalid: // TODO: does this make sense? m_value.SetValueType(Value::eValueTypeScalar); break; } } } else { switch (value_type) { case Value::eValueTypeLoadAddress: case Value::eValueTypeFileAddress: case Value::eValueTypeHostAddress: { lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); if (addr == LLDB_INVALID_ADDRESS) { m_error.SetErrorString ("parent address is invalid."); } else if (addr == 0) { m_error.SetErrorString ("parent is NULL"); } else { // Set this object's scalar value to the address of its // value by adding its byte offset to the parent address m_value.GetScalar() += GetByteOffset(); } } break; case Value::eValueTypeScalar: // TODO: What if this is a register value? Do we try and // extract the child value from within the parent data? // Probably... default: m_error.SetErrorString ("parent has invalid value."); break; } } if (m_error.Success()) { ExecutionContext exe_ctx (GetExecutionContextRef().Lock()); m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); } } else { m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", parent->GetError().AsCString()); } } else { m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject."); } return m_error.Success(); }
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; }