예제 #1
0
TypeSP DWARFASTParserOCaml::ParseBaseTypeFromDIE(const DWARFDIE &die) {
  SymbolFileDWARF *dwarf = die.GetDWARF();
  dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

  ConstString type_name;
  uint64_t byte_size = 0;

  DWARFAttributes attributes;
  const size_t num_attributes = die.GetAttributes(attributes);
  for (uint32_t i = 0; i < num_attributes; ++i) {
    DWARFFormValue form_value;
    dw_attr_t attr = attributes.AttributeAtIndex(i);
    if (attributes.ExtractFormValueAtIndex(i, form_value)) {
      switch (attr) {
      case DW_AT_name:
        type_name.SetCString(form_value.AsCString());
        break;
      case DW_AT_byte_size:
        byte_size = form_value.Unsigned();
        break;
      case DW_AT_encoding:
        break;
      default:
        assert(false && "Unsupported attribute for DW_TAG_base_type");
      }
    }
  }

  Declaration decl;
  CompilerType compiler_type = m_ast.CreateBaseType(type_name, byte_size);
  return std::make_shared<Type>(die.GetID(), dwarf, type_name, byte_size,
                                nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
                                decl, compiler_type, Type::eResolveStateFull);
}
예제 #2
0
void
DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
                                      std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
                                      uint32_t &bit_stride)
{
    if (!parent_die)
        return;

    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {
        const dw_tag_t tag = die.Tag();
        switch (tag)
        {
            case DW_TAG_subrange_type:
            {
                DWARFAttributes attributes;
                const size_t num_child_attributes = die.GetAttributes(attributes);
                if (num_child_attributes > 0)
                {
                    uint64_t num_elements = 0;
                    uint32_t i;
                    for (i = 0; i < num_child_attributes; ++i)
                    {
                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
                        DWARFFormValue form_value;
                        if (attributes.ExtractFormValueAtIndex(i, form_value))
                        {
                            switch (attr)
                            {
                                case DW_AT_count:
                                    num_elements = form_value.Unsigned();
                                    break;

                                default:
                                case DW_AT_type:
                                    break;
                            }
                        }
                    }

                    element_orders.push_back(num_elements);
                }
            }
            break;
        }
    }
}
TypeSP
DWARFASTParserJava::ParseReferenceTypeFromDIE(const DWARFDIE &die)
{
    SymbolFileDWARF *dwarf = die.GetDWARF();
    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

    Declaration decl;
    DWARFFormValue type_attr_value;

    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    for (uint32_t i = 0; i < num_attributes; ++i)
    {
        DWARFFormValue form_value;
        dw_attr_t attr = attributes.AttributeAtIndex(i);
        if (attributes.ExtractFormValueAtIndex(i, form_value))
        {
            switch (attr)
            {
                case DW_AT_type:
                    type_attr_value = form_value;
                    break;
                default:
                    assert(false && "Unsupported attribute for DW_TAG_array_type");
            }
        }
    }

    DIERef type_die_ref(type_attr_value);
    Type *pointee_type = dwarf->ResolveTypeUID(type_die_ref);
    if (!pointee_type)
        return nullptr;

    CompilerType pointee_compiler_type = pointee_type->GetForwardCompilerType();
    CompilerType reference_compiler_type = m_ast.CreateReferenceType(pointee_compiler_type);
    TypeSP type_sp(new Type(die.GetID(), dwarf, reference_compiler_type.GetTypeName(), -1, nullptr,
                            type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl,
                            reference_compiler_type, Type::eResolveStateFull));
    type_sp->SetEncodingType(pointee_type);
    return type_sp;
}
예제 #4
0
파일: DWARFDIE.cpp 프로젝트: k06a/lldb
size_t
DWARFDIE::GetAttributes (DWARFAttributes &attributes, uint32_t depth) const
{
    if (IsValid())
    {
        return m_die->GetAttributes (m_cu,
                                     m_cu->GetFixedFormSizes(),
                                     attributes,
                                     depth);
    }
    if (depth == 0)
        attributes.Clear();
    return 0;
}
예제 #5
0
void
DWARFCompileUnit::Index (const uint32_t cu_idx,
                         NameToDIE& func_basenames,
                         NameToDIE& func_fullnames,
                         NameToDIE& func_methods,
                         NameToDIE& func_selectors,
                         NameToDIE& objc_class_selectors,
                         NameToDIE& globals,
                         NameToDIE& types,
                         NameToDIE& namespaces)
{
    DWARFFormValue::FixedFormSizes fixed_form_sizes =
        DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);

    Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));

    if (log)
    {
        m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log,
                "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]",
                GetOffset());
    }

    const LanguageType cu_language = GetLanguageType();
    DWARFDebugInfoEntry::const_iterator pos;
    DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
    for (pos = begin; pos != end; ++pos)
    {
        const DWARFDebugInfoEntry &die = *pos;

        const dw_tag_t tag = die.Tag();

        switch (tag)
        {
        case DW_TAG_subprogram:
        case DW_TAG_inlined_subroutine:
        case DW_TAG_base_type:
        case DW_TAG_class_type:
        case DW_TAG_constant:
        case DW_TAG_enumeration_type:
        case DW_TAG_string_type:
        case DW_TAG_subroutine_type:
        case DW_TAG_structure_type:
        case DW_TAG_union_type:
        case DW_TAG_typedef:
        case DW_TAG_namespace:
        case DW_TAG_variable:
        case DW_TAG_unspecified_type:
            break;

        default:
            continue;
        }

        DWARFAttributes attributes;
        const char *name = NULL;
        const char *mangled_cstr = NULL;
        bool is_declaration = false;
        //bool is_artificial = false;
        bool has_address = false;
        bool has_location = false;
        bool is_global_or_static_variable = false;

        dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
        const size_t num_attributes = die.GetAttributes(this, fixed_form_sizes, attributes);
        if (num_attributes > 0)
        {
            for (uint32_t i=0; i<num_attributes; ++i)
            {
                dw_attr_t attr = attributes.AttributeAtIndex(i);
                DWARFFormValue form_value;
                switch (attr)
                {
                case DW_AT_name:
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                        name = form_value.AsCString();
                    break;

                case DW_AT_declaration:
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                        is_declaration = form_value.Unsigned() != 0;
                    break;

//                case DW_AT_artificial:
//                    if (attributes.ExtractFormValueAtIndex(i, form_value))
//                        is_artificial = form_value.Unsigned() != 0;
//                    break;

                case DW_AT_MIPS_linkage_name:
                case DW_AT_linkage_name:
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                        mangled_cstr = form_value.AsCString();
                    break;

                case DW_AT_low_pc:
                case DW_AT_high_pc:
                case DW_AT_ranges:
                    has_address = true;
                    break;

                case DW_AT_entry_pc:
                    has_address = true;
                    break;

                case DW_AT_location:
                    has_location = true;
                    if (tag == DW_TAG_variable)
                    {
                        const DWARFDebugInfoEntry* parent_die = die.GetParent();
                        while ( parent_die != NULL )
                        {
                            switch (parent_die->Tag())
                            {
                            case DW_TAG_subprogram:
                            case DW_TAG_lexical_block:
                            case DW_TAG_inlined_subroutine:
                                // Even if this is a function level static, we don't add it. We could theoretically
                                // add these if we wanted to by introspecting into the DW_AT_location and seeing
                                // if the location describes a hard coded address, but we dont want the performance
                                // penalty of that right now.
                                is_global_or_static_variable = false;
//                              if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
//                              {
//                                  // If we have valid block data, then we have location expression bytes
//                                  // that are fixed (not a location list).
//                                  const uint8_t *block_data = form_value.BlockData();
//                                  if (block_data)
//                                  {
//                                      uint32_t block_length = form_value.Unsigned();
//                                      if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
//                                      {
//                                          if (block_data[0] == DW_OP_addr)
//                                              add_die = true;
//                                      }
//                                  }
//                              }
                                parent_die = NULL;  // Terminate the while loop.
                                break;

                            case DW_TAG_compile_unit:
                                is_global_or_static_variable = true;
                                parent_die = NULL;  // Terminate the while loop.
                                break;

                            default:
                                parent_die = parent_die->GetParent();   // Keep going in the while loop.
                                break;
                            }
                        }
                    }
                    break;

                case DW_AT_specification:
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                        specification_die_offset = form_value.Reference();
                    break;
                }
            }
        }

        switch (tag)
        {
        case DW_TAG_subprogram:
            if (has_address)
            {
                if (name)
                {
                    ObjCLanguage::MethodName objc_method(name, true);
                    if (objc_method.IsValid(true))
                    {
                        ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory());
                        ConstString objc_selector_name (objc_method.GetSelector());
                        ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true));
                        ConstString objc_class_name_no_category (objc_method.GetClassName());
                        func_fullnames.Insert (ConstString(name), die.GetOffset());
                        if (objc_class_name_with_category)
                            objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset());
                        if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category)
                            objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset());
                        if (objc_selector_name)
                            func_selectors.Insert (objc_selector_name, die.GetOffset());
                        if (objc_fullname_no_category_name)
                            func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset());
                    }
                    // If we have a mangled name, then the DW_AT_name attribute
                    // is usually the method name without the class or any parameters
                    const DWARFDebugInfoEntry *parent = die.GetParent();
                    bool is_method = false;
                    if (parent)
                    {
                        dw_tag_t parent_tag = parent->Tag();
                        if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
                        {
                            is_method = true;
                        }
                        else
                        {
                            if (specification_die_offset != DW_INVALID_OFFSET)
                            {
                                DWARFDIE specification_die = m_dwarf2Data->DebugInfo()->GetDIE (specification_die_offset);
                                if (specification_die.GetParent().IsStructOrClass())
                                    is_method = true;
                            }
                        }
                    }


                    if (is_method)
                        func_methods.Insert (ConstString(name), die.GetOffset());
                    else
                        func_basenames.Insert (ConstString(name), die.GetOffset());

                    if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
                        func_fullnames.Insert (ConstString(name), die.GetOffset());
                }
                if (mangled_cstr)
                {
                    // Make sure our mangled name isn't the same string table entry
                    // as our name. If it starts with '_', then it is ok, else compare
                    // the string to make sure it isn't the same and we don't end up
                    // with duplicate entries
                    if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0)))
                    {
                        Mangled mangled (ConstString(mangled_cstr), true);
                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
                        ConstString demangled = mangled.GetDemangledName(cu_language);
                        if (demangled)
                            func_fullnames.Insert (demangled, die.GetOffset());
                    }
                }
            }
            break;

        case DW_TAG_inlined_subroutine:
            if (has_address)
            {
                if (name)
                    func_basenames.Insert (ConstString(name), die.GetOffset());
                if (mangled_cstr)
                {
                    // Make sure our mangled name isn't the same string table entry
                    // as our name. If it starts with '_', then it is ok, else compare
                    // the string to make sure it isn't the same and we don't end up
                    // with duplicate entries
                    if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
                    {
                        Mangled mangled (ConstString(mangled_cstr), true);
                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
                        ConstString demangled = mangled.GetDemangledName(cu_language);
                        if (demangled)
                            func_fullnames.Insert (demangled, die.GetOffset());
                    }
                }
                else
                    func_fullnames.Insert (ConstString(name), die.GetOffset());
            }
            break;

        case DW_TAG_base_type:
        case DW_TAG_class_type:
        case DW_TAG_constant:
        case DW_TAG_enumeration_type:
        case DW_TAG_string_type:
        case DW_TAG_subroutine_type:
        case DW_TAG_structure_type:
        case DW_TAG_union_type:
        case DW_TAG_typedef:
        case DW_TAG_unspecified_type:
            if (name && is_declaration == false)
            {
                types.Insert (ConstString(name), die.GetOffset());
            }
            break;

        case DW_TAG_namespace:
            if (name)
                namespaces.Insert (ConstString(name), die.GetOffset());
            break;

        case DW_TAG_variable:
            if (name && has_location && is_global_or_static_variable)
            {
                globals.Insert (ConstString(name), die.GetOffset());
                // Be sure to include variables by their mangled and demangled
                // names if they have any since a variable can have a basename
                // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
                // mangled name "(anonymous namespace)::i"...

                // Make sure our mangled name isn't the same string table entry
                // as our name. If it starts with '_', then it is ok, else compare
                // the string to make sure it isn't the same and we don't end up
                // with duplicate entries
                if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
                {
                    Mangled mangled (ConstString(mangled_cstr), true);
                    globals.Insert (mangled.GetMangledName(), die.GetOffset());
                    ConstString demangled = mangled.GetDemangledName(cu_language);
                    if (demangled)
                        globals.Insert (demangled, die.GetOffset());
                }
            }
            break;

        default:
            continue;
        }
    }
}
예제 #6
0
size_t
DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type)
{
    size_t count = 0;
    uint32_t member_idx = 0;

    ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
    GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem());
    if (ast == nullptr)
        return 0;

    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {
        dw_tag_t tag = die.Tag();

        switch (tag)
        {
            case DW_TAG_member:
            {
                DWARFAttributes attributes;
                const size_t num_attributes = die.GetAttributes(attributes);
                if (num_attributes > 0)
                {
                    Declaration decl;
                    const char *name = NULL;

                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
                    uint32_t member_byte_offset = UINT32_MAX;
                    uint32_t i;
                    for (i = 0; i < num_attributes; ++i)
                    {
                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
                        DWARFFormValue form_value;
                        if (attributes.ExtractFormValueAtIndex(i, form_value))
                        {
                            switch (attr)
                            {
                                case DW_AT_name:
                                    name = form_value.AsCString();
                                    break;
                                case DW_AT_type:
                                    encoding_uid = form_value.Reference();
                                    break;
                                case DW_AT_data_member_location:
                                    if (form_value.BlockData())
                                    {
                                        Value initialValue(0);
                                        Value memberOffset(0);
                                        const DWARFDataExtractor &debug_info_data =
                                            die.GetDWARF()->get_debug_info_data();
                                        uint32_t block_length = form_value.Unsigned();
                                        uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
                                        if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
                                                                      NULL, // ClangExpressionVariableList *
                                                                      NULL, // ClangExpressionDeclMap *
                                                                      NULL, // RegisterContext *
                                                                      module_sp, debug_info_data, die.GetCU(),
                                                                      block_offset, block_length, eRegisterKindDWARF,
                                                                      &initialValue, NULL, memberOffset, NULL))
                                        {
                                            member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
                                        }
                                    }
                                    else
                                    {
                                        // With DWARF 3 and later, if the value is an integer constant,
                                        // this form value is the offset in bytes from the beginning
                                        // of the containing entity.
                                        member_byte_offset = form_value.Unsigned();
                                    }
                                    break;

                                default:
                                    break;
                            }
                        }
                    }

                    Type *member_type = die.ResolveTypeUID(encoding_uid);
                    if (member_type)
                    {
                        CompilerType member_go_type = member_type->GetFullCompilerType();
                        ConstString name_const_str(name);
                        m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset);
                    }
                }
                ++member_idx;
            }
            break;

            default:
                break;
        }
    }

    return count;
}
예제 #7
0
TypeSP
DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
                                     bool *type_is_new_ptr)
{
    TypeSP type_sp;

    if (type_is_new_ptr)
        *type_is_new_ptr = false;

    if (die)
    {
        SymbolFileDWARF *dwarf = die.GetDWARF();
        if (log)
        {
            dwarf->GetObjectFile()->GetModule()->LogMessage(
                log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(),
                DW_TAG_value_to_name(die.Tag()), die.GetName());
        }

        Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
        TypeList *type_list = dwarf->GetTypeList();
        if (type_ptr == NULL)
        {
            if (type_is_new_ptr)
                *type_is_new_ptr = true;

            const dw_tag_t tag = die.Tag();

            bool is_forward_declaration = false;
            DWARFAttributes attributes;
            const char *type_name_cstr = NULL;
            ConstString type_name_const_str;
            Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
            uint64_t byte_size = 0;
            uint64_t go_kind = 0;
            Declaration decl;

            Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
            CompilerType compiler_type;
            DWARFFormValue form_value;

            dw_attr_t attr;

            switch (tag)
            {
                case DW_TAG_base_type:
                case DW_TAG_pointer_type:
                case DW_TAG_typedef:
                case DW_TAG_unspecified_type:
                {
                    // Set a bit that lets us know that we are currently parsing this
                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

                    const size_t num_attributes = die.GetAttributes(attributes);
                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;

                    if (num_attributes > 0)
                    {
                        uint32_t i;
                        for (i = 0; i < num_attributes; ++i)
                        {
                            attr = attributes.AttributeAtIndex(i);
                            if (attributes.ExtractFormValueAtIndex(i, form_value))
                            {
                                switch (attr)
                                {
                                    case DW_AT_name:
                                        type_name_cstr = form_value.AsCString();
                                        if (type_name_cstr)
                                            type_name_const_str.SetCString(type_name_cstr);
                                        break;
                                    case DW_AT_byte_size:
                                        byte_size = form_value.Unsigned();
                                        break;
                                    case DW_AT_encoding:
                                        // = form_value.Unsigned();
                                        break;
                                    case DW_AT_type:
                                        encoding_uid = form_value.Reference();
                                        break;
                                    case DW_AT_go_kind:
                                        go_kind = form_value.Unsigned();
                                        break;
                                    default:
                                        // Do we care about DW_AT_go_key or DW_AT_go_elem?
                                        break;
                                }
                            }
                        }
                    }

                    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()),
                                 DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);

                    switch (tag)
                    {
                        default:
                            break;

                        case DW_TAG_unspecified_type:
                            resolve_state = Type::eResolveStateFull;
                            compiler_type = m_ast.CreateVoidType(type_name_const_str);
                            break;

                        case DW_TAG_base_type:
                            resolve_state = Type::eResolveStateFull;
                            compiler_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
                            break;

                        case DW_TAG_pointer_type:
                            encoding_data_type = Type::eEncodingIsPointerUID;
                            break;
                        case DW_TAG_typedef:
                            encoding_data_type = Type::eEncodingIsTypedefUID;
                            CompilerType impl;
                            Type *type = dwarf->ResolveTypeUID(encoding_uid);
                            if (type)
                            {
                                if (go_kind == 0 && type->GetName() == type_name_const_str)
                                {
                                    // Go emits extra typedefs as a forward declaration. Ignore these.
                                    dwarf->m_die_to_type[die.GetDIE()] = type;
                                    return type->shared_from_this();
                                }
                                impl = type->GetForwardCompilerType();
                                compiler_type = m_ast.CreateTypedefType (go_kind, type_name_const_str, impl);
                            }
                            break;
                    }

                    type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
                                           NULL, encoding_uid, encoding_data_type, &decl, compiler_type, resolve_state));

                    dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
                }
                break;

                case DW_TAG_structure_type:
                {
                    // Set a bit that lets us know that we are currently parsing this
                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
                    bool byte_size_valid = false;

                    const size_t num_attributes = die.GetAttributes(attributes);
                    if (num_attributes > 0)
                    {
                        uint32_t i;
                        for (i = 0; i < num_attributes; ++i)
                        {
                            attr = attributes.AttributeAtIndex(i);
                            if (attributes.ExtractFormValueAtIndex(i, form_value))
                            {
                                switch (attr)
                                {
                                    case DW_AT_name:
                                        type_name_cstr = form_value.AsCString();
                                        type_name_const_str.SetCString(type_name_cstr);
                                        break;

                                    case DW_AT_byte_size:
                                        byte_size = form_value.Unsigned();
                                        byte_size_valid = true;
                                        break;

                                    case DW_AT_go_kind:
                                        go_kind = form_value.Unsigned();
                                        break;

                                    // TODO: Should we use SLICETYPE's DW_AT_go_elem?
                                    default:
                                        break;
                                }
                            }
                        }
                    }

                    // TODO(ribrdb): Do we need this?

                    // UniqueDWARFASTType is large, so don't create a local variables on the
                    // stack, put it on the heap. This function is often called recursively
                    // and clang isn't good and sharing the stack space for variables in different blocks.
                    std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());

                    // Only try and unique the type if it has a name.
                    if (type_name_const_str &&
                        dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
                                                               byte_size_valid ? byte_size : -1, *unique_ast_entry_ap))
                    {
                        // We have already parsed this type or from another
                        // compile unit. GCC loves to use the "one definition
                        // rule" which can result in multiple definitions
                        // of the same class over and over in each compile
                        // unit.
                        type_sp = unique_ast_entry_ap->m_type_sp;
                        if (type_sp)
                        {
                            dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
                            return type_sp;
                        }
                    }

                    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
                                 DW_TAG_value_to_name(tag), type_name_cstr);

                    bool compiler_type_was_created = false;
                    compiler_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
                    if (!compiler_type)
                    {
                        compiler_type_was_created = true;
                        compiler_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
                    }

                    type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
                                           NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
                                           Type::eResolveStateForward));

                    // Add our type to the unique type map so we don't
                    // end up creating many copies of the same type over
                    // and over in the ASTContext for our module
                    unique_ast_entry_ap->m_type_sp = type_sp;
                    unique_ast_entry_ap->m_die = die;
                    unique_ast_entry_ap->m_declaration = decl;
                    unique_ast_entry_ap->m_byte_size = byte_size;
                    dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap);

                    if (!is_forward_declaration)
                    {
                        // Always start the definition for a class type so that
                        // if the class has child classes or types that require
                        // the class to be created for use as their decl contexts
                        // the class will be ready to accept these child definitions.
                        if (die.HasChildren() == false)
                        {
                            // No children for this struct/union/class, lets finish it
                            m_ast.CompleteStructType(compiler_type);
                        }
                        else if (compiler_type_was_created)
                        {
                            // Leave this as a forward declaration until we need
                            // to know the details of the type. lldb_private::Type
                            // will automatically call the SymbolFile virtual function
                            // "SymbolFileDWARF::CompleteType(Type *)"
                            // When the definition needs to be defined.
                            dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = compiler_type.GetOpaqueQualType();
                            dwarf->m_forward_decl_clang_type_to_die[compiler_type.GetOpaqueQualType()] = die.GetDIERef();
                            // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true);
                        }
                    }
                }
                break;

                case DW_TAG_subprogram:
                case DW_TAG_subroutine_type:
                {
                    // Set a bit that lets us know that we are currently parsing this
                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

                    bool is_variadic = false;
                    clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern

                    const size_t num_attributes = die.GetAttributes(attributes);
                    if (num_attributes > 0)
                    {
                        uint32_t i;
                        for (i = 0; i < num_attributes; ++i)
                        {
                            attr = attributes.AttributeAtIndex(i);
                            if (attributes.ExtractFormValueAtIndex(i, form_value))
                            {
                                switch (attr)
                                {
                                    case DW_AT_name:
                                        type_name_cstr = form_value.AsCString();
                                        type_name_const_str.SetCString(type_name_cstr);
                                        break;

                                    case DW_AT_external:
                                        if (form_value.Unsigned())
                                        {
                                            if (storage == clang::SC_None)
                                                storage = clang::SC_Extern;
                                            else
                                                storage = clang::SC_PrivateExtern;
                                        }
                                        break;

                                    case DW_AT_high_pc:
                                    case DW_AT_low_pc:
                                        break;
                                }
                            }
                        }
                    }

                    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
                                 DW_TAG_value_to_name(tag), type_name_cstr);

                    std::vector<CompilerType> function_param_types;

                    // Parse the function children for the parameters

                    if (die.HasChildren())
                    {
                        ParseChildParameters(sc, die, is_variadic, function_param_types);
                    }

                    // compiler_type will get the function prototype clang type after this call
                    compiler_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(),
                                                          function_param_types.size(), is_variadic);

                    type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL,
                                           LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
                                           Type::eResolveStateFull));
                    assert(type_sp.get());
                }
                break;

                case DW_TAG_array_type:
                {
                    // Set a bit that lets us know that we are currently parsing this
                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

                    lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
                    int64_t first_index = 0;
                    uint32_t byte_stride = 0;
                    uint32_t bit_stride = 0;
                    const size_t num_attributes = die.GetAttributes(attributes);

                    if (num_attributes > 0)
                    {
                        uint32_t i;
                        for (i = 0; i < num_attributes; ++i)
                        {
                            attr = attributes.AttributeAtIndex(i);
                            if (attributes.ExtractFormValueAtIndex(i, form_value))
                            {
                                switch (attr)
                                {
                                    case DW_AT_name:
                                        type_name_cstr = form_value.AsCString();
                                        type_name_const_str.SetCString(type_name_cstr);
                                        break;

                                    case DW_AT_type:
                                        type_die_offset = form_value.Reference();
                                        break;
                                    case DW_AT_byte_size:
                                        break; // byte_size = form_value.Unsigned(); break;
                                    case DW_AT_go_kind:
                                        go_kind = form_value.Unsigned();
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }

                        DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
                                     DW_TAG_value_to_name(tag), type_name_cstr);

                        Type *element_type = dwarf->ResolveTypeUID(type_die_offset);

                        if (element_type)
                        {
                            std::vector<uint64_t> element_orders;
                            ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
                            if (byte_stride == 0)
                                byte_stride = element_type->GetByteSize();
                            CompilerType array_element_type = element_type->GetForwardCompilerType();
                            if (element_orders.size() > 0)
                            {
                                if (element_orders.size() > 1)
                                    printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr);
                                compiler_type =
                                    m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]);
                            }
                            else
                            {
                                compiler_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0);
                            }
                            type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str,
                                                   byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl,
                                                   compiler_type, Type::eResolveStateFull));
                            type_sp->SetEncodingType(element_type);
                        }
                    }
                }
                break;

                default:
                    dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), "
                                                                     "please file a bug and attach the file at the "
                                                                     "start of this error message",
                                                                     die.GetOffset(), tag, DW_TAG_value_to_name(tag));
                    break;
            }

            if (type_sp.get())
            {
                DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
                dw_tag_t sc_parent_tag = sc_parent_die.Tag();

                SymbolContextScope *symbol_context_scope = NULL;
                if (sc_parent_tag == DW_TAG_compile_unit)
                {
                    symbol_context_scope = sc.comp_unit;
                }
                else if (sc.function != NULL && sc_parent_die)
                {
                    symbol_context_scope =
                        sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset()));
                    if (symbol_context_scope == NULL)
                        symbol_context_scope = sc.function;
                }

                if (symbol_context_scope != NULL)
                {
                    type_sp->SetSymbolContextScope(symbol_context_scope);
                }

                // We are ready to put this type into the uniqued list up at the module level
                type_list->Insert(type_sp);

                dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
            }
        }
        else if (type_ptr != DIE_IS_BEING_PARSED)
        {
            type_sp = type_ptr->shared_from_this();
        }
    }
    return type_sp;
}
예제 #8
0
size_t
DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc,

                                       const DWARFDIE &parent_die, bool &is_variadic,
                                       std::vector<CompilerType> &function_param_types)
{
    if (!parent_die)
        return 0;

    size_t arg_idx = 0;
    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {

        dw_tag_t tag = die.Tag();
        switch (tag)
        {
            case DW_TAG_formal_parameter:
            {
                DWARFAttributes attributes;
                const size_t num_attributes = die.GetAttributes(attributes);
                if (num_attributes > 0)
                {
                    Declaration decl;
                    dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;

                    uint32_t i;
                    for (i = 0; i < num_attributes; ++i)
                    {
                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
                        DWARFFormValue form_value;
                        if (attributes.ExtractFormValueAtIndex(i, form_value))
                        {
                            switch (attr)
                            {
                                case DW_AT_name:
                                    // = form_value.AsCString();
                                    break;
                                case DW_AT_type:
                                    param_type_die_offset = form_value.Reference();
                                    break;
                                case DW_AT_location:
                                //                          if (form_value.BlockData())
                                //                          {
                                //                              const DWARFDataExtractor& debug_info_data =
                                //                              debug_info();
                                //                              uint32_t block_length = form_value.Unsigned();
                                //                              DWARFDataExtractor location(debug_info_data,
                                //                              form_value.BlockData() - debug_info_data.GetDataStart(),
                                //                              block_length);
                                //                          }
                                //                          else
                                //                          {
                                //                          }
                                //                          break;
                                default:
                                    break;
                            }
                        }
                    }

                    Type *type = parent_die.ResolveTypeUID(param_type_die_offset);
                    if (type)
                    {
                        function_param_types.push_back(type->GetForwardCompilerType());
                    }
                }
                arg_idx++;
            }
            break;

            case DW_TAG_unspecified_parameters:
                is_variadic = true;
                break;

            default:
                break;
        }
    }
    return arg_idx;
}
TypeSP
DWARFASTParserJava::ParseArrayTypeFromDIE(const DWARFDIE &die)
{
    SymbolFileDWARF *dwarf = die.GetDWARF();
    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

    ConstString linkage_name;
    DWARFFormValue type_attr_value;
    lldb::addr_t data_offset = LLDB_INVALID_ADDRESS;
    DWARFExpression length_expression(die.GetCU());

    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    for (uint32_t i = 0; i < num_attributes; ++i)
    {
        DWARFFormValue form_value;
        dw_attr_t attr = attributes.AttributeAtIndex(i);
        if (attributes.ExtractFormValueAtIndex(i, form_value))
        {
            switch (attr)
            {
                case DW_AT_linkage_name:
                    linkage_name.SetCString(form_value.AsCString());
                    break;
                case DW_AT_type:
                    type_attr_value = form_value;
                    break;
                case DW_AT_data_member_location:
                    data_offset = form_value.Unsigned();
                    break;
                case DW_AT_declaration:
                    break;
                default:
                    assert(false && "Unsupported attribute for DW_TAG_array_type");
            }
        }
    }

    for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); child_die = child_die.GetSibling())
    {
        if (child_die.Tag() == DW_TAG_subrange_type)
        {
            DWARFAttributes attributes;
            const size_t num_attributes = child_die.GetAttributes(attributes);
            for (uint32_t i = 0; i < num_attributes; ++i)
            {
                DWARFFormValue form_value;
                dw_attr_t attr = attributes.AttributeAtIndex(i);
                if (attributes.ExtractFormValueAtIndex(i, form_value))
                {
                    switch (attr)
                    {
                        case DW_AT_count:
                            if (form_value.BlockData())
                                length_expression.CopyOpcodeData(form_value.BlockData(), form_value.Unsigned(),
                                                                 child_die.GetCU()->GetByteOrder(),
                                                                 child_die.GetCU()->GetAddressByteSize());
                            break;
                        default:
                            assert(false && "Unsupported attribute for DW_TAG_subrange_type");
                    }
                }
            }
        }
        else
        {
            assert(false && "Unsupported child for DW_TAG_array_type");
        }
    }

    DIERef type_die_ref(type_attr_value);
    Type *element_type = dwarf->ResolveTypeUID(type_die_ref);
    if (!element_type)
        return nullptr;

    CompilerType element_compiler_type = element_type->GetForwardCompilerType();
    CompilerType array_compiler_type =
        m_ast.CreateArrayType(element_compiler_type, length_expression, data_offset);

    Declaration decl;
    TypeSP type_sp(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(), -1, nullptr,
                            type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl,
                            array_compiler_type, Type::eResolveStateFull));
    type_sp->SetEncodingType(element_type);
    return type_sp;
}
예제 #10
0
void
DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die, CompilerType &compiler_type)
{
    DWARFCompileUnit *dwarf_cu = parent_die.GetCU();
    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {
        switch (die.Tag())
        {
            case DW_TAG_member:
            {
                const char *name = nullptr;
                DWARFFormValue encoding_uid;
                uint32_t member_byte_offset = UINT32_MAX;
                DWARFExpression member_location_expression(dwarf_cu);
                bool artificial = true;

                DWARFAttributes attributes;
                size_t num_attributes = die.GetAttributes(attributes);
                for (size_t i = 0; i < num_attributes; ++i)
                {
                    DWARFFormValue form_value;
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                    {
                        switch (attributes.AttributeAtIndex(i))
                        {
                            case DW_AT_name:
                                name = form_value.AsCString();
                                break;
                            case DW_AT_type:
                                encoding_uid = form_value;
                                break;
                            case DW_AT_data_member_location:
                                if (form_value.BlockData())
                                    member_location_expression.CopyOpcodeData(
                                        form_value.BlockData(), form_value.Unsigned(), dwarf_cu->GetByteOrder(),
                                        dwarf_cu->GetAddressByteSize());
                                else
                                    member_byte_offset = form_value.Unsigned();
                                break;
                            case DW_AT_artificial:
                                artificial = form_value.Boolean();
                                break;
                            case DW_AT_accessibility:
                                // TODO: Handle when needed
                                break;
                            default:
                                assert(false && "Unhandled attribute for DW_TAG_member");
                                break;
                        }
                    }
                }

                if (strcmp(name, ".dynamic_type") == 0)
                    m_ast.SetDynamicTypeId(compiler_type, member_location_expression);
                else
                {
                    if (Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid)))
                        m_ast.AddMemberToObject(compiler_type, ConstString(name), member_type->GetFullCompilerType(),
                                                member_byte_offset);
                }
                break;
            }
            case DW_TAG_inheritance:
            {
                DWARFFormValue encoding_uid;
                uint32_t member_byte_offset = UINT32_MAX;

                DWARFAttributes attributes;
                size_t num_attributes = die.GetAttributes(attributes);
                for (size_t i = 0; i < num_attributes; ++i)
                {
                    DWARFFormValue form_value;
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                    {
                        switch (attributes.AttributeAtIndex(i))
                        {
                            case DW_AT_type:
                                encoding_uid = form_value;
                                break;
                            case DW_AT_data_member_location:
                                member_byte_offset = form_value.Unsigned();
                                break;
                            case DW_AT_accessibility:
                                // In java all base class is public so we can ignore this attribute
                                break;
                            default:
                                assert(false && "Unhandled attribute for DW_TAG_member");
                                break;
                        }
                    }
                }
                if (Type *base_type = die.ResolveTypeUID(DIERef(encoding_uid)))
                    m_ast.AddBaseClassToObject(compiler_type, base_type->GetFullCompilerType(), member_byte_offset);
                break;
            }
            default:
                break;
        }
    }
}
예제 #11
0
lldb::TypeSP
DWARFASTParserJava::ParseClassTypeFromDIE(const DWARFDIE &die, bool &is_new_type)
{
    SymbolFileDWARF *dwarf = die.GetDWARF();
    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

    Declaration decl;
    ConstString name;
    ConstString linkage_name;
    bool is_forward_declaration = false;
    uint32_t byte_size = 0;

    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    for (uint32_t i = 0; i < num_attributes; ++i)
    {
        DWARFFormValue form_value;
        dw_attr_t attr = attributes.AttributeAtIndex(i);
        if (attributes.ExtractFormValueAtIndex(i, form_value))
        {
            switch (attr)
            {
                case DW_AT_name:
                    name.SetCString(form_value.AsCString());
                    break;
                case DW_AT_declaration:
                    is_forward_declaration = form_value.Boolean();
                    break;
                case DW_AT_byte_size:
                    byte_size = form_value.Unsigned();
                    break;
                case DW_AT_linkage_name:
                    linkage_name.SetCString(form_value.AsCString());
                    break;
                default:
                    assert(false && "Unsupported attribute for DW_TAG_class_type");
            }
        }
    }

    UniqueDWARFASTType unique_ast_entry;
    if (name)
    {
        std::string qualified_name;
        if (die.GetQualifiedName(qualified_name))
        {
            name.SetCString(qualified_name.c_str());
            if (dwarf->GetUniqueDWARFASTTypeMap().Find(name, die, Declaration(), -1, unique_ast_entry))
            {
                if (unique_ast_entry.m_type_sp)
                {
                    dwarf->GetDIEToType()[die.GetDIE()] = unique_ast_entry.m_type_sp.get();
                    is_new_type = false;
                    return unique_ast_entry.m_type_sp;
                }
            }
        }
    }

    if (is_forward_declaration)
    {
        DWARFDeclContext die_decl_ctx;
        die.GetDWARFDeclContext(die_decl_ctx);

        TypeSP type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
        if (type_sp)
        {
            // We found a real definition for this type elsewhere so lets use it
            dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
            is_new_type = false;
            return type_sp;
        }
    }

    CompilerType compiler_type(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
    if (!compiler_type)
        compiler_type = m_ast.CreateObjectType(name, linkage_name, byte_size);

    is_new_type = true;
    TypeSP type_sp(new Type(die.GetID(), dwarf, name,
                            -1, // byte size isn't specified
                            nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
                            Type::eResolveStateForward));

    // Add our type to the unique type map
    unique_ast_entry.m_type_sp = type_sp;
    unique_ast_entry.m_die = die;
    unique_ast_entry.m_declaration = decl;
    unique_ast_entry.m_byte_size = -1;
    dwarf->GetUniqueDWARFASTTypeMap().Insert(name, unique_ast_entry);

    if (!is_forward_declaration)
    {
        // Leave this as a forward declaration until we need to know the details of the type
        dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = compiler_type.GetOpaqueQualType();
        dwarf->GetForwardDeclClangTypeToDie()[compiler_type.GetOpaqueQualType()] = die.GetDIERef();
    }
    return type_sp;
}
예제 #12
0
void ManualDWARFIndex::IndexUnitImpl(
    DWARFUnit &unit, const LanguageType cu_language,
    const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
    const dw_offset_t cu_offset, IndexSet &set) {
  for (const DWARFDebugInfoEntry &die : unit.dies()) {
    const dw_tag_t tag = die.Tag();

    switch (tag) {
    case DW_TAG_array_type:
    case DW_TAG_base_type:
    case DW_TAG_class_type:
    case DW_TAG_constant:
    case DW_TAG_enumeration_type:
    case DW_TAG_inlined_subroutine:
    case DW_TAG_namespace:
    case DW_TAG_string_type:
    case DW_TAG_structure_type:
    case DW_TAG_subprogram:
    case DW_TAG_subroutine_type:
    case DW_TAG_typedef:
    case DW_TAG_union_type:
    case DW_TAG_unspecified_type:
    case DW_TAG_variable:
      break;

    default:
      continue;
    }

    DWARFAttributes attributes;
    const char *name = NULL;
    const char *mangled_cstr = NULL;
    bool is_declaration = false;
    // bool is_artificial = false;
    bool has_address = false;
    bool has_location_or_const_value = false;
    bool is_global_or_static_variable = false;

    DWARFFormValue specification_die_form;
    const size_t num_attributes =
        die.GetAttributes(&unit, fixed_form_sizes, attributes);
    if (num_attributes > 0) {
      for (uint32_t i = 0; i < num_attributes; ++i) {
        dw_attr_t attr = attributes.AttributeAtIndex(i);
        DWARFFormValue form_value;
        switch (attr) {
        case DW_AT_name:
          if (attributes.ExtractFormValueAtIndex(i, form_value))
            name = form_value.AsCString();
          break;

        case DW_AT_declaration:
          if (attributes.ExtractFormValueAtIndex(i, form_value))
            is_declaration = form_value.Unsigned() != 0;
          break;

        //                case DW_AT_artificial:
        //                    if (attributes.ExtractFormValueAtIndex(i,
        //                    form_value))
        //                        is_artificial = form_value.Unsigned() != 0;
        //                    break;

        case DW_AT_MIPS_linkage_name:
        case DW_AT_linkage_name:
          if (attributes.ExtractFormValueAtIndex(i, form_value))
            mangled_cstr = form_value.AsCString();
          break;

        case DW_AT_low_pc:
        case DW_AT_high_pc:
        case DW_AT_ranges:
          has_address = true;
          break;

        case DW_AT_entry_pc:
          has_address = true;
          break;

        case DW_AT_location:
        case DW_AT_const_value:
          has_location_or_const_value = true;
          if (tag == DW_TAG_variable) {
            const DWARFDebugInfoEntry *parent_die = die.GetParent();
            while (parent_die != NULL) {
              switch (parent_die->Tag()) {
              case DW_TAG_subprogram:
              case DW_TAG_lexical_block:
              case DW_TAG_inlined_subroutine:
                // Even if this is a function level static, we don't add it. We
                // could theoretically add these if we wanted to by
                // introspecting into the DW_AT_location and seeing if the
                // location describes a hard coded address, but we don't want
                // the performance penalty of that right now.
                is_global_or_static_variable = false;
                // if (attributes.ExtractFormValueAtIndex(dwarf, i,
                //                                        form_value)) {
                //   // If we have valid block data, then we have location
                //   // expression bytesthat are fixed (not a location list).
                //   const uint8_t *block_data = form_value.BlockData();
                //   if (block_data) {
                //     uint32_t block_length = form_value.Unsigned();
                //     if (block_length == 1 +
                //     attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) {
                //       if (block_data[0] == DW_OP_addr)
                //         add_die = true;
                //     }
                //   }
                // }
                parent_die = NULL; // Terminate the while loop.
                break;

              case DW_TAG_compile_unit:
              case DW_TAG_partial_unit:
                is_global_or_static_variable = true;
                parent_die = NULL; // Terminate the while loop.
                break;

              default:
                parent_die =
                    parent_die->GetParent(); // Keep going in the while loop.
                break;
              }
            }
          }
          break;

        case DW_AT_specification:
          if (attributes.ExtractFormValueAtIndex(i, form_value))
            specification_die_form = form_value;
          break;
        }
      }
    }

    switch (tag) {
    case DW_TAG_inlined_subroutine:
    case DW_TAG_subprogram:
      if (has_address) {
        if (name) {
          ObjCLanguage::MethodName objc_method(name, true);
          if (objc_method.IsValid(true)) {
            ConstString objc_class_name_with_category(
                objc_method.GetClassNameWithCategory());
            ConstString objc_selector_name(objc_method.GetSelector());
            ConstString objc_fullname_no_category_name(
                objc_method.GetFullNameWithoutCategory(true));
            ConstString objc_class_name_no_category(objc_method.GetClassName());
            set.function_fullnames.Insert(ConstString(name),
                                          DIERef(cu_offset, die.GetOffset()));
            if (objc_class_name_with_category)
              set.objc_class_selectors.Insert(
                  objc_class_name_with_category,
                  DIERef(cu_offset, die.GetOffset()));
            if (objc_class_name_no_category &&
                objc_class_name_no_category != objc_class_name_with_category)
              set.objc_class_selectors.Insert(
                  objc_class_name_no_category,
                  DIERef(cu_offset, die.GetOffset()));
            if (objc_selector_name)
              set.function_selectors.Insert(objc_selector_name,
                                            DIERef(cu_offset, die.GetOffset()));
            if (objc_fullname_no_category_name)
              set.function_fullnames.Insert(objc_fullname_no_category_name,
                                            DIERef(cu_offset, die.GetOffset()));
          }
          // If we have a mangled name, then the DW_AT_name attribute is
          // usually the method name without the class or any parameters
          bool is_method = DWARFDIE(&unit, &die).IsMethod();

          if (is_method)
            set.function_methods.Insert(ConstString(name),
                                        DIERef(cu_offset, die.GetOffset()));
          else
            set.function_basenames.Insert(ConstString(name),
                                          DIERef(cu_offset, die.GetOffset()));

          if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
            set.function_fullnames.Insert(ConstString(name),
                                          DIERef(cu_offset, die.GetOffset()));
        }
        if (mangled_cstr) {
          // Make sure our mangled name isn't the same string table entry as
          // our name. If it starts with '_', then it is ok, else compare the
          // string to make sure it isn't the same and we don't end up with
          // duplicate entries
          if (name && name != mangled_cstr &&
              ((mangled_cstr[0] == '_') ||
               (::strcmp(name, mangled_cstr) != 0))) {
            set.function_fullnames.Insert(ConstString(mangled_cstr),
                                          DIERef(cu_offset, die.GetOffset()));
          }
        }
      }
      break;

    case DW_TAG_array_type:
    case DW_TAG_base_type:
    case DW_TAG_class_type:
    case DW_TAG_constant:
    case DW_TAG_enumeration_type:
    case DW_TAG_string_type:
    case DW_TAG_structure_type:
    case DW_TAG_subroutine_type:
    case DW_TAG_typedef:
    case DW_TAG_union_type:
    case DW_TAG_unspecified_type:
      if (name && !is_declaration)
        set.types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
      if (mangled_cstr && !is_declaration)
        set.types.Insert(ConstString(mangled_cstr),
                         DIERef(cu_offset, die.GetOffset()));
      break;

    case DW_TAG_namespace:
      if (name)
        set.namespaces.Insert(ConstString(name),
                              DIERef(cu_offset, die.GetOffset()));
      break;

    case DW_TAG_variable:
      if (name && has_location_or_const_value && is_global_or_static_variable) {
        set.globals.Insert(ConstString(name),
                           DIERef(cu_offset, die.GetOffset()));
        // Be sure to include variables by their mangled and demangled names if
        // they have any since a variable can have a basename "i", a mangled
        // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
        // "(anonymous namespace)::i"...

        // Make sure our mangled name isn't the same string table entry as our
        // name. If it starts with '_', then it is ok, else compare the string
        // to make sure it isn't the same and we don't end up with duplicate
        // entries
        if (mangled_cstr && name != mangled_cstr &&
            ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
          set.globals.Insert(ConstString(mangled_cstr),
                             DIERef(cu_offset, die.GetOffset()));
        }
      }
      break;

    default:
      continue;
    }
  }
}