From 4fcccf68cbb32bec2c041168fe8fbd5b11550ac1 Mon Sep 17 00:00:00 2001 From: jimblandy Date: Fri, 5 Oct 2012 21:47:55 +0000 Subject: If a specification DIE has a DW_AT_MIPS_linkage_name attribute, don't fail to add it to the specifications table. Record the fully-qualified name provided by the demangler in the table. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A=Rafael Ávila de Espíndola R=jimb at https://breakpad.appspot. com/478004/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1062 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/common/dwarf_cu_to_module.cc | 59 ++++++++++++++++++--------- src/common/dwarf_cu_to_module_unittest.cc | 68 ++++++++++++++++++++++--------- 2 files changed, 87 insertions(+), 40 deletions(-) (limited to 'src/common') diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc index ef2489c8..081260c6 100644 --- a/src/common/dwarf_cu_to_module.cc +++ b/src/common/dwarf_cu_to_module.cc @@ -74,6 +74,9 @@ using std::vector; // A Specification holds information gathered from a declaration DIE that // we may need if we find a DW_AT_specification link pointing to it. struct DwarfCUToModule::Specification { + // The qualified name that can be found by demangling DW_AT_MIPS_linkage_name. + string qualified_name; + // The name of the enclosing scope, or the empty string if there is none. string enclosing_name; @@ -314,38 +317,54 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString( } string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() { - // Use DW_AT_MIPS_linkage_name if it is available. It is already qualified, - // so there is no need to add enclosing_name. - if (!demangled_name_.empty()) - return demangled_name_; + // Use the demangled name, if one is available. Demangled names are + // preferable to those inferred from the DWARF structure because they + // include argument types. + const string *qualified_name = NULL; + if (!demangled_name_.empty()) { + // Found it is this DIE. + qualified_name = &demangled_name_; + } else if (specification_ && !specification_->qualified_name.empty()) { + // Found it on the specification. + qualified_name = &specification_->qualified_name; + } - // Find our unqualified name. If the DIE has its own DW_AT_name - // attribute, then use that; otherwise, check our specification. const string *unqualified_name; - if (name_attribute_.empty() && specification_) - unqualified_name = &specification_->unqualified_name; - else - unqualified_name = &name_attribute_; - - // Find the name of our enclosing context. If we have a - // specification, it's the specification's enclosing context that - // counts; otherwise, use this DIE's context. const string *enclosing_name; - if (specification_) - enclosing_name = &specification_->enclosing_name; - else - enclosing_name = &parent_context_->name; + if (!qualified_name) { + // Find our unqualified name. If the DIE has its own DW_AT_name + // attribute, then use that; otherwise, check our specification. + if (name_attribute_.empty() && specification_) + unqualified_name = &specification_->unqualified_name; + else + unqualified_name = &name_attribute_; + + // Find the name of our enclosing context. If we have a + // specification, it's the specification's enclosing context that + // counts; otherwise, use this DIE's context. + if (specification_) + enclosing_name = &specification_->enclosing_name; + else + enclosing_name = &parent_context_->name; + } // If this DIE was marked as a declaration, record its names in the // specification table. if (declaration_) { FileContext *file_context = cu_context_->file_context; Specification spec; - spec.enclosing_name = *enclosing_name; - spec.unqualified_name = *unqualified_name; + if (qualified_name) + spec.qualified_name = *qualified_name; + else { + spec.enclosing_name = *enclosing_name; + spec.unqualified_name = *unqualified_name; + } file_context->file_private->specifications[offset_] = spec; } + if (qualified_name) + return *qualified_name; + // Combine the enclosing name and unqualified name to produce our // own fully-qualified name. return cu_context_->language->MakeQualifiedName(*enclosing_name, diff --git a/src/common/dwarf_cu_to_module_unittest.cc b/src/common/dwarf_cu_to_module_unittest.cc index 93d27d98..377630e3 100644 --- a/src/common/dwarf_cu_to_module_unittest.cc +++ b/src/common/dwarf_cu_to_module_unittest.cc @@ -209,7 +209,8 @@ class CUFixtureBase { // offset, tag and name. If NAME is the empty string, don't provide // a DW_AT_name attribute. Call EndAttributes and Finish. void DeclarationDIE(DIEHandler *parent, uint64 offset, - DwarfTag tag, const string &name); + DwarfTag tag, const string &name, + const string &mangled_name); // Create a definition DIE as a child of PARENT with the given tag // that refers to the declaration DIE at offset SPECIFICATION as its @@ -490,11 +491,14 @@ void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent, void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset, DwarfTag tag, - const string &name) { + const string &name, + const string &mangled_name) { dwarf2reader::AttributeList attrs; if (!name.empty()) attrs.push_back(make_pair(dwarf2reader::DW_AT_name, dwarf2reader::DW_FORM_strp)); + + attrs.push_back(make_pair(dwarf2reader::DW_AT_declaration, dwarf2reader::DW_FORM_flag)); dwarf2reader::DIEHandler *die = parent->FindChildHandler(offset, tag, attrs); @@ -503,6 +507,11 @@ void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset, die->ProcessAttributeString(dwarf2reader::DW_AT_name, dwarf2reader::DW_FORM_strp, name); + if (!mangled_name.empty()) + die->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name, + dwarf2reader::DW_FORM_strp, + mangled_name); + die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_declaration, dwarf2reader::DW_FORM_flag, 1); @@ -683,7 +692,7 @@ void CUFixtureBase::TestLine(int i, int j, #define SetLanguage(a) TRACE(SetLanguage(a)) #define StartCU() TRACE(StartCU()) #define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e))) -#define DeclarationDIE(a,b,c,d) TRACE(DeclarationDIE((a),(b),(c),(d))) +#define DeclarationDIE(a,b,c,d,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e))) #define DefinitionDIE(a,b,c,d,e,f) TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f))) #define TestFunctionCount(a) TRACE(TestFunctionCount(a)) #define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d))) @@ -1224,7 +1233,7 @@ TEST_F(Specifications, Function) { StartCU(); DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, - dwarf2reader::DW_TAG_subprogram, "declaration-name"); + dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, 0xcd3c51b946fb1eeeLL, "", 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); @@ -1235,6 +1244,23 @@ TEST_F(Specifications, Function) { 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); } +TEST_F(Specifications, MangledName) { + PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661); + + StartCU(); + DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, + dwarf2reader::DW_TAG_subprogram, "declaration-name", + "_ZN1C1fEi"); + DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, + 0xcd3c51b946fb1eeeLL, "", + 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); + root_handler_.Finish(); + + TestFunctionCount(1); + TestFunction(0, "C::f(int)", + 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); +} + TEST_F(Specifications, MemberFunction) { PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691); @@ -1242,7 +1268,7 @@ TEST_F(Specifications, MemberFunction) { DIEHandler *class_handler = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A"); DeclarationDIE(class_handler, 0x7d83028c431406e8ULL, - dwarf2reader::DW_TAG_subprogram, "declaration-name"); + dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); class_handler->Finish(); delete class_handler; DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, @@ -1267,7 +1293,7 @@ TEST_F(Specifications, FunctionDeclarationParent) { "class_A"); ASSERT_TRUE(class_handler != NULL); DeclarationDIE(class_handler, 0x0e0e877c8404544aULL, - dwarf2reader::DW_TAG_subprogram, "declaration-name"); + dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); class_handler->Finish(); delete class_handler; } @@ -1295,7 +1321,8 @@ TEST_F(Specifications, NamedScopeDeclarationParent) { "space_A"); ASSERT_TRUE(space_handler != NULL); DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL, - dwarf2reader::DW_TAG_class_type, "class-declaration-name"); + dwarf2reader::DW_TAG_class_type, "class-declaration-name", + ""); space_handler->Finish(); delete space_handler; } @@ -1324,7 +1351,7 @@ TEST_F(Specifications, InlineFunction) { StartCU(); DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, - dwarf2reader::DW_TAG_subprogram, "inline-name"); + dwarf2reader::DW_TAG_subprogram, "inline-name", ""); AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL, dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, ""); DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL, @@ -1374,7 +1401,7 @@ TEST_F(Specifications, LongChain) { = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, "space_A"); DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL, - dwarf2reader::DW_TAG_namespace, "space_B"); + dwarf2reader::DW_TAG_namespace, "space_B", ""); space_A_handler->Finish(); delete space_A_handler; } @@ -1387,7 +1414,7 @@ TEST_F(Specifications, LongChain) { = StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type, "struct_C"); DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL, - dwarf2reader::DW_TAG_structure_type, "struct_D"); + dwarf2reader::DW_TAG_structure_type, "struct_D", ""); struct_C_handler->Finish(); delete struct_C_handler; space_B_handler->Finish(); @@ -1402,7 +1429,7 @@ TEST_F(Specifications, LongChain) { = StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type, "union_E"); DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL, - dwarf2reader::DW_TAG_union_type, "union_F"); + dwarf2reader::DW_TAG_union_type, "union_F", ""); union_E_handler->Finish(); delete union_E_handler; struct_D_handler->Finish(); @@ -1417,7 +1444,7 @@ TEST_F(Specifications, LongChain) { = StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type, "class_G"); DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL, - dwarf2reader::DW_TAG_class_type, "class_H"); + dwarf2reader::DW_TAG_class_type, "class_H", ""); class_G_handler->Finish(); delete class_G_handler; union_F_handler->Finish(); @@ -1429,7 +1456,7 @@ TEST_F(Specifications, LongChain) { = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, 0xb70d960dcc173b6eULL); DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL, - dwarf2reader::DW_TAG_subprogram, "func_I"); + dwarf2reader::DW_TAG_subprogram, "func_I", ""); class_H_handler->Finish(); delete class_H_handler; } @@ -1467,7 +1494,7 @@ TEST_F(Specifications, InterCU) { ProcessStrangeAttributes(&root1_handler); ASSERT_TRUE(root1_handler.EndAttributes()); DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL, - dwarf2reader::DW_TAG_class_type, "class_A"); + dwarf2reader::DW_TAG_class_type, "class_A", ""); root1_handler.Finish(); } @@ -1482,7 +1509,7 @@ TEST_F(Specifications, InterCU) { = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type, 0xb8fbfdd5f0b26fceULL); DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL, - dwarf2reader::DW_TAG_subprogram, "member_func_B"); + dwarf2reader::DW_TAG_subprogram, "member_func_B", ""); class_A_handler->Finish(); delete class_A_handler; root2_handler.Finish(); @@ -1514,7 +1541,7 @@ TEST_F(Specifications, BadOffset) { StartCU(); DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL, - dwarf2reader::DW_TAG_subprogram, ""); + dwarf2reader::DW_TAG_subprogram, "", ""); DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, 0x2be953efa6f9a996ULL, "function", 0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL); @@ -1526,7 +1553,7 @@ TEST_F(Specifications, FunctionDefinitionHasOwnName) { StartCU(); DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL, - dwarf2reader::DW_TAG_subprogram, "declaration-name"); + dwarf2reader::DW_TAG_subprogram, "declaration-name", ""); DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, 0xc34ff4786cae78bdULL, "definition-name", 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL); @@ -1542,7 +1569,7 @@ TEST_F(Specifications, ClassDefinitionHasOwnName) { StartCU(); DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL, - dwarf2reader::DW_TAG_class_type, "class-declaration-name"); + dwarf2reader::DW_TAG_class_type, "class-declaration-name", ""); dwarf2reader::DIEHandler *class_definition = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, @@ -1550,7 +1577,7 @@ TEST_F(Specifications, ClassDefinitionHasOwnName) { ASSERT_TRUE(class_definition); DeclarationDIE(class_definition, 0x6d028229c15623dbULL, dwarf2reader::DW_TAG_subprogram, - "function-declaration-name"); + "function-declaration-name", ""); class_definition->Finish(); delete class_definition; @@ -1578,7 +1605,8 @@ TEST_F(Specifications, PreferSpecificationParents) { dwarf2reader::DIEHandler *declaration_class_handler = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "declaration-class"); DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL, - dwarf2reader::DW_TAG_subprogram, "function-declaration"); + dwarf2reader::DW_TAG_subprogram, "function-declaration", + ""); declaration_class_handler->Finish(); delete declaration_class_handler; } -- cgit v1.2.1