コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
bool
lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
    options.SetLocation(valobj_addr);
    options.SetConversionFunction(ConvertUTF32toUTF8);
    options.SetProcessSP(process_sp);
    options.SetStream(&stream);
    options.SetPrefixToken('U');
    
    if (!ReadUTFBufferAndDumpToStream(options))
    {
        stream.Printf("Summary Unavailable");
        return true;
    }
    
    return true;
}
コード例 #4
0
bool
lldb_private::formatters::swift::ObjC_Selector_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    static ConstString g_ptr("ptr");
    static ConstString g__rawValue("_rawValue");
    
    ValueObjectSP ptr_sp(valobj.GetChildAtNamePath({ g_ptr, g__rawValue }));
    if (!ptr_sp)
        return false;
    
    auto ptr_value = ptr_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    
    if (0 == ptr_value || LLDB_INVALID_ADDRESS == ptr_value)
        return false;
    
    StringPrinter::ReadStringAndDumpToStreamOptions read_options;
    read_options.SetLocation(ptr_value)
    .SetProcessSP(valobj.GetProcessSP())
    .SetStream(&stream)
    .SetQuote('"')
    .SetNeedsZeroTermination(true)
    .SetLanguage(lldb::eLanguageTypeSwift);

    return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(read_options);
}
コード例 #5
0
bool
lldb_private::formatters::swift::Metadata_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return false;
    SwiftLanguageRuntime *runtime(process_sp->GetSwiftLanguageRuntime());
    if (!runtime)
        return false;
    SwiftLanguageRuntime::MetadataSP metadata_sp(runtime->GetMetadataForLocation(valobj.GetValueAsUnsigned(0)));
    if (!metadata_sp)
        return false;
    if (SwiftLanguageRuntime::NominalTypeMetadata *nominal_type_metadata = llvm::dyn_cast<SwiftLanguageRuntime::NominalTypeMetadata>(metadata_sp.get()))
    {
        stream.Printf("typename=%s",nominal_type_metadata->GetMangledName().c_str());
        Mangled mangled( ConstString(nominal_type_metadata->GetMangledName().c_str()) );
        ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeSwift);
        if (demangled)
            stream.Printf(" --> %s", demangled.GetCString());
        return true;
    }
    if (SwiftLanguageRuntime::TupleMetadata *tuple_metadata = llvm::dyn_cast<SwiftLanguageRuntime::TupleMetadata>(metadata_sp.get()))
    {
        stream.Printf("tuple with %zu items",tuple_metadata->GetNumElements());
        return true;
    }
    // what about other types? not sure
    return false;
}
コード例 #6
0
ファイル: Cocoa.cpp プロジェクト: kleopatra999/lldb
bool
lldb_private::formatters::ObjCClassSummaryProvider (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->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    stream.Printf("%s",class_name);
    return true;
}
コード例 #7
0
ファイル: Cocoa.cpp プロジェクト: atrick/swift-lldb
bool
lldb_private::formatters::ObjCClassSummaryProvider (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->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
    
    if (!descriptor || !descriptor->IsValid())
        return false;
    
    ConstString class_name = descriptor->GetClassName();
    
    if (class_name.IsEmpty())
        return false;
    
    if (ConstString cs = Mangled(class_name).GetDemangledName(lldb::eLanguageTypeUnknown))
        class_name = cs;
    
    stream.Printf("%s",class_name.AsCString("<unknown class>"));
    return true;
}
コード例 #8
0
ファイル: CXXFormatterFunctions.cpp プロジェクト: gnuhub/lldb
bool
lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    ReadStringAndDumpToStreamOptions options(valobj);
    options.SetLocation(valobj_addr);
    options.SetProcessSP(process_sp);
    options.SetStream(&stream);
    options.SetPrefixToken('U');
    
    if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
    {
        stream.Printf("Summary Unavailable");
        return true;
    }
    
    return true;
}
コード例 #9
0
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());
                   
}
コード例 #10
0
ファイル: CxxStringTypes.cpp プロジェクト: 2asoft/freebsd
bool
lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
    if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
        return false;
    
    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
    options.SetLocation(valobj_addr);
    options.SetProcessSP(process_sp);
    options.SetStream(&stream);
    options.SetPrefixToken("U");
    
    if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options))
    {
        stream.Printf("Summary Unavailable");
        return true;
    }
    
    return true;
}
コード例 #11
0
ファイル: CXXFormatterFunctions.cpp プロジェクト: filcab/lldb
bool
lldb_private::formatters::NSNumberSummaryProvider (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;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber"))
    {
        if (descriptor->IsTagged())
        {
            // we have a call to get info and value bits in the tagged descriptor. but we prefer not to cast and replicate them
            int64_t value = (valobj_addr & ~0x0000000000000000FFL) >> 8;
            uint64_t i_bits = (valobj_addr & 0xF0) >> 4;
            
            switch (i_bits)
            {
                case 0:
                    stream.Printf("(char)%hhd",(char)value);
                    break;
                case 4:
                    stream.Printf("(short)%hd",(short)value);
                    break;
                case 8:
                    stream.Printf("(int)%d",(int)value);
                    break;
                case 12:
                    stream.Printf("(long)%" PRId64,value);
                    break;
                default:
                    stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64,i_bits,value);
                    break;
            }
            return true;
        }
        else
        {
コード例 #12
0
ファイル: NSError.cpp プロジェクト: 2asoft/freebsd
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;
    }
}
コード例 #13
0
ファイル: AppleObjCRuntimeV1.cpp プロジェクト: carlokok/lldb
AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
{
    ObjCISA ptr_value = isa_pointer.GetValueAsUnsigned(0);

    lldb::ProcessSP process_sp = isa_pointer.GetProcessSP();

    Initialize (ptr_value,process_sp);
}
コード例 #14
0
ファイル: CXXFormatterFunctions.cpp プロジェクト: filcab/lldb
bool
lldb_private::formatters::NSDataSummaryProvider (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;
    
    bool is_64bit = (process_sp->GetAddressByteSize() == 8);
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    uint64_t value = 0;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (!strcmp(class_name,"NSConcreteData") ||
        !strcmp(class_name,"NSConcreteMutableData") ||
        !strcmp(class_name,"__NSCFData"))
    {
        uint32_t offset = (is_64bit ? 16 : 8);
        Error error;
        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
        if (error.Fail())
            return false;
    }
    else
    {
        if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
            return false;
    }
    
    stream.Printf("%s%" PRIu64 " byte%s%s",
                  (needs_at ? "@\"" : ""),
                  value,
                  (value > 1 ? "s" : ""),
                  (needs_at ? "\"" : ""));
    
    return true;
}
コード例 #15
0
std::unique_ptr<SwiftHashedContainerBufferHandler>
SwiftHashedContainerBufferHandler::CreateBufferHandlerForNativeStorageOwner (ValueObject &valobj,
                                                                             lldb::addr_t storage_ptr,
                                                                             bool fail_on_no_children,
                                                                             NativeCreatorFunction Native)
{
#if 0
    static ConstString g_Native("native");
    static ConstString g_nativeStorage("nativeStorage");
    static ConstString g_buffer("buffer");
    
    Error error;
    
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return nullptr;
    
    ValueObjectSP native_sp(valobj.GetChildAtNamePath( {g_Native, g_nativeStorage, g_buffer} ));
    if (!native_sp)
    {
        if (fail_on_no_children)
            return nullptr;
        else
        {
            lldb::addr_t native_storage_ptr = storage_ptr + (3 * process_sp->GetAddressByteSize());
            native_storage_ptr = process_sp->ReadPointerFromMemory(native_storage_ptr, error);
            // (AnyObject,AnyObject)?
            SwiftASTContext *swift_ast_ctx = process_sp->GetTarget().GetScratchSwiftASTContext(error);
            if (swift_ast_ctx)
            {
                CompilerType element_type(swift_ast_ctx->GetTypeFromMangledTypename("_TtGSqTPs9AnyObject_PS____", error));
                auto handler = std::unique_ptr<SwiftHashedContainerBufferHandler>(Native(valobj, native_storage_ptr, element_type));
                if (handler && handler->IsValid())
                    return handler;
            }
            return nullptr;
        }
    }
    CompilerType child_type(native_sp->GetCompilerType());
    lldb::TemplateArgumentKind kind;
    CompilerType element_type(child_type.GetTemplateArgument(1, kind));
    if (element_type.IsValid() == false || kind != lldb::eTemplateArgumentKindType)
        return nullptr;
    lldb::addr_t native_storage_ptr = process_sp->ReadPointerFromMemory(storage_ptr + 2*process_sp->GetAddressByteSize(), error);
    if (error.Fail() || native_storage_ptr == LLDB_INVALID_ADDRESS)
        return nullptr;
    auto handler = std::unique_ptr<SwiftHashedContainerBufferHandler>(Native(valobj, native_storage_ptr, element_type));
    if (handler && handler->IsValid())
        return handler;
#endif
    return nullptr;
}
コード例 #16
0
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;
}
コード例 #17
0
bool
lldb_private::formatters::swift::StaticString_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options, StringPrinter::ReadStringAndDumpToStreamOptions read_options)
{
    static ConstString g__startPtrOrData("_startPtrOrData");
    static ConstString g__byteSize("_utf8CodeUnitCount");
    static ConstString g__flags("_flags");

    ValueObjectSP flags_sp(valobj.GetChildMemberWithName(g__flags, true));
    if (!flags_sp)
        return false;
    
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return false;
    
    // 0 == pointer representation
    InferiorSizedWord flags(flags_sp->GetValueAsUnsigned(0), *process_sp);
    if (0 != (flags & 0x1).GetValue())
        return false;
    
    ValueObjectSP startptr_sp(valobj.GetChildMemberWithName(g__startPtrOrData, true));
    ValueObjectSP bytesize_sp(valobj.GetChildMemberWithName(g__byteSize, true));
    if (!startptr_sp || !bytesize_sp)
        return false;
    
    lldb::addr_t start_ptr = startptr_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    uint64_t size = bytesize_sp->GetValueAsUnsigned(0);
    
    if (start_ptr == LLDB_INVALID_ADDRESS || start_ptr == 0)
        return false;
    
    if (size == 0)
    {
        stream.Printf("\"\"");
        return true;
    }
    
    read_options.SetProcessSP(process_sp);
    read_options.SetLocation(start_ptr);
    read_options.SetSourceSize(size);
    read_options.SetBinaryZeroIsTerminator(false);
    read_options.SetNeedsZeroTermination(false);
    read_options.SetStream(&stream);
    read_options.SetIgnoreMaxLength(summary_options.GetCapping() == lldb::eTypeSummaryUncapped);
    read_options.SetLanguage(lldb::eLanguageTypeSwift);
    
    return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(read_options);
}
コード例 #18
0
ファイル: Cocoa.cpp プロジェクト: kleopatra999/lldb
bool
lldb_private::formatters::NSMachPortSummaryProvider (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;
    
    uint64_t port_number = 0;
    
    do
    {
        if (!strcmp(class_name,"NSMachPort"))
        {
            uint64_t offset = (ptr_size == 4 ? 12 : 20);
            Error error;
            port_number = process_sp->ReadUnsignedIntegerFromMemory(offset+valobj_addr, 4, 0, error);
            if (error.Success())
                break;
        }
        if (!ExtractValueFromObjCExpression(valobj, "int", "machPort", port_number))
            return false;
    } while (false);
    
    stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF));
    return true;
}
コード例 #19
0
bool lldb_private::formatters::JavaStringSummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
  if (valobj.IsPointerOrReferenceType()) {
    Error error;
    ValueObjectSP deref = valobj.Dereference(error);
    if (error.Fail())
      return false;
    return JavaStringSummaryProvider(*deref, stream, opts);
  }

  ProcessSP process_sp = valobj.GetProcessSP();
  if (!process_sp)
    return false;

  ConstString data_name("value");
  ConstString length_name("count");

  ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true);
  ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true);
  if (!data_sp || !length_sp)
    return false;

  bool success = false;
  uint64_t length = length_sp->GetValueAsUnsigned(0, &success);
  if (!success)
    return false;

  if (length == 0) {
    stream.Printf("\"\"");
    return true;
  }
  lldb::addr_t valobj_addr = data_sp->GetAddressOf();

  StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
  options.SetLocation(valobj_addr);
  options.SetProcessSP(process_sp);
  options.SetStream(&stream);
  options.SetSourceSize(length);
  options.SetNeedsZeroTermination(false);
  options.SetLanguage(eLanguageTypeJava);

  if (StringPrinter::ReadStringAndDumpToStream<
          StringPrinter::StringElementType::UTF16>(options))
    return true;

  stream.Printf("Summary Unavailable");
  return true;
}
コード例 #20
0
ファイル: LibStdcpp.cpp プロジェクト: kraj/lldb
bool lldb_private::formatters::LibStdcppStringSummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
  const bool scalar_is_load_addr = true;
  AddressType addr_type;
  lldb::addr_t addr_of_string =
      valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
  if (addr_of_string != LLDB_INVALID_ADDRESS) {
    switch (addr_type) {
    case eAddressTypeLoad: {
      ProcessSP process_sp(valobj.GetProcessSP());
      if (!process_sp)
        return false;

      StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
      Error error;
      lldb::addr_t addr_of_data =
          process_sp->ReadPointerFromMemory(addr_of_string, error);
      if (error.Fail() || addr_of_data == 0 ||
          addr_of_data == LLDB_INVALID_ADDRESS)
        return false;
      options.SetLocation(addr_of_data);
      options.SetProcessSP(process_sp);
      options.SetStream(&stream);
      options.SetNeedsZeroTermination(false);
      options.SetBinaryZeroIsTerminator(true);
      lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
          addr_of_string + process_sp->GetAddressByteSize(), error);
      if (error.Fail())
        return false;
      options.SetSourceSize(size_of_data);

      if (!StringPrinter::ReadStringAndDumpToStream<
              StringPrinter::StringElementType::UTF8>(options)) {
        stream.Printf("Summary Unavailable");
        return true;
      } else
        return true;
    } break;
    case eAddressTypeHost:
      break;
    case eAddressTypeInvalid:
    case eAddressTypeFile:
      break;
    }
  }
  return false;
}
コード例 #21
0
ファイル: Cocoa.cpp プロジェクト: kleopatra999/lldb
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);
}
コード例 #22
0
ファイル: Cocoa.cpp プロジェクト: atrick/swift-lldb
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;
}
コード例 #23
0
ファイル: CXXFormatterFunctions.cpp プロジェクト: gnuhub/lldb
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;
}
コード例 #24
0
ファイル: CxxStringTypes.cpp プロジェクト: kraj/lldb
bool lldb_private::formatters::WCharStringSummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
  ProcessSP process_sp = valobj.GetProcessSP();
  if (!process_sp)
    return false;

  lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
  if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
    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::ReadStringAndDumpToStreamOptions options(valobj);
  options.SetLocation(valobj_addr);
  options.SetProcessSP(process_sp);
  options.SetStream(&stream);
  options.SetPrefixToken("L");

  switch (wchar_size) {
  case 8:
    return StringPrinter::ReadStringAndDumpToStream<
        StringPrinter::StringElementType::UTF8>(options);
  case 16:
    return StringPrinter::ReadStringAndDumpToStream<
        StringPrinter::StringElementType::UTF16>(options);
  case 32:
    return StringPrinter::ReadStringAndDumpToStream<
        StringPrinter::StringElementType::UTF32>(options);
  default:
    stream.Printf("size for wchar_t is not valid");
    return true;
  }
  return true;
}
コード例 #25
0
bool
lldb_private::formatters::swift::NSContiguousString_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    static ConstString g_StringCoreType("_TtVs11_StringCore");
    lldb::addr_t core_location = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    if (core_location == LLDB_INVALID_ADDRESS)
        return false;
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return false;
    size_t ptr_size = process_sp->GetAddressByteSize();
    core_location += 2*ptr_size;

    Error error;
    
    InferiorSizedWord isw_1(process_sp->ReadPointerFromMemory(core_location, error),*process_sp);
    InferiorSizedWord isw_2(process_sp->ReadPointerFromMemory(core_location+ptr_size, error),*process_sp);
    InferiorSizedWord isw_3(process_sp->ReadPointerFromMemory(core_location+ptr_size+ptr_size, error),*process_sp);
    
    DataBufferSP buffer_sp(new DataBufferHeap(3*ptr_size, 0));
    uint8_t* buffer = buffer_sp->GetBytes();
    
    buffer = isw_1.CopyToBuffer(buffer);
    buffer = isw_2.CopyToBuffer(buffer);
    buffer = isw_3.CopyToBuffer(buffer);

    DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);

    SwiftASTContext* lldb_swift_ast = process_sp->GetTarget().GetScratchSwiftASTContext(error);
    if (!lldb_swift_ast)
        return false;
    CompilerType string_core_type = lldb_swift_ast->GetTypeFromMangledTypename(g_StringCoreType.GetCString(), error);
    if (string_core_type.IsValid() == false)
        return false;
    
    ValueObjectSP string_core_sp = ValueObject::CreateValueObjectFromData("stringcore", data, valobj.GetExecutionContextRef(), string_core_type);
    if (string_core_sp)
        return StringCore_SummaryProvider(*string_core_sp, stream, options);
    return false;
}
コード例 #26
0
ファイル: NSError.cpp プロジェクト: llvm-project/lldb
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;
}
コード例 #27
0
ファイル: CF.cpp プロジェクト: VanirLLVM/toolchain_lldb
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;
}
コード例 #28
0
ファイル: CF.cpp プロジェクト: VanirLLVM/toolchain_lldb
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;
}
コード例 #29
0
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;
}
コード例 #30
0
ファイル: CF.cpp プロジェクト: Aj0Ay/lldb
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;
}