ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
                                           lldb::SyntheticChildrenSP filter)
    : ValueObject(parent), m_synth_sp(filter), m_children_byindex(),
      m_name_toindex(), m_synthetic_children_count(UINT32_MAX),
      m_synthetic_children_cache(), m_parent_type_name(parent.GetTypeName()),
      m_might_have_children(eLazyBoolCalculate),
      m_provides_value(eLazyBoolCalculate) {
  SetName(parent.GetName());
  CopyValueData(m_parent);
  CreateSynthFilter();
}
ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
    ValueObject(parent),
    m_synth_sp(filter),
    m_children_byindex(),
    m_name_toindex(),
    m_synthetic_children_count(UINT32_MAX),
    m_parent_type_name(parent.GetTypeName()),
    m_might_have_children(eLazyBoolCalculate),
    m_provides_value(eLazyBoolCalculate)
{
#ifdef FOOBAR
    std::string new_name(parent.GetName().AsCString());
    new_name += "$$__synth__";
    SetName (ConstString(new_name.c_str()));
#else
    SetName(parent.GetName());
#endif
    CopyValueData(m_parent);
    CreateSynthFilter();
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
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;
}
TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
    ValueObject &in_value, lldb::addr_t original_ptr,
    lldb::addr_t vtable_load_addr) {
  if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) {
    // Find the symbol that contains the "vtable_load_addr" address
    Address vtable_addr;
    Target &target = m_process->GetTarget();
    if (!target.GetSectionLoadList().IsEmpty()) {
      if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr,
                                                         vtable_addr)) {
        // See if we have cached info for this type already
        TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr);
        if (type_info)
          return type_info;

        SymbolContext sc;
        target.GetImages().ResolveSymbolContextForAddress(
            vtable_addr, 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);
            type_info.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.
            llvm::DenseSet<SymbolFile *> searched_symbol_files;
            if (sc.module_sp) {
              num_matches = sc.module_sp->FindTypes(
                  sc, ConstString(class_name), exact_match, 1,
                  searched_symbol_files, 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,
                  searched_symbol_files, 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 TypeAndOrName();
            }
            if (num_matches == 1) {
              type_sp = class_types.GetTypeAtIndex(0);
              if (type_sp) {
                if (ClangASTContext::IsCXXClassType(
                        type_sp->GetForwardCompilerType())) {
                  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());
                  type_info.SetTypeSP(type_sp);
                }
              }
            } 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->GetForwardCompilerType())) {
                    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());
                    type_info.SetTypeSP(type_sp);
                  }
                }
              }

              if (log && i == num_matches) {
                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());
              }
            }
            if (type_info)
              SetDynamicTypeInfo(vtable_addr, type_info);
            return type_info;
          }
        }
      }
    }
  }
  return TypeAndOrName();
}
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;
}
示例#9
0
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;
}