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.

A=Rafael Ávila de Espíndola <respindola@mozilla.com> R=jimb at https://breakpad.appspot.
com/478004/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1062 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
jimblandy 2012-10-05 21:47:55 +00:00
parent 872d464500
commit 4fcccf68cb
2 changed files with 87 additions and 40 deletions

View file

@ -74,6 +74,9 @@ using std::vector;
// A Specification holds information gathered from a declaration DIE that // A Specification holds information gathered from a declaration DIE that
// we may need if we find a DW_AT_specification link pointing to it. // we may need if we find a DW_AT_specification link pointing to it.
struct DwarfCUToModule::Specification { 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. // The name of the enclosing scope, or the empty string if there is none.
string enclosing_name; string enclosing_name;
@ -314,38 +317,54 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
} }
string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() { string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
// Use DW_AT_MIPS_linkage_name if it is available. It is already qualified, // Use the demangled name, if one is available. Demangled names are
// so there is no need to add enclosing_name. // preferable to those inferred from the DWARF structure because they
if (!demangled_name_.empty()) // include argument types.
return demangled_name_; 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; 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; const string *enclosing_name;
if (specification_) if (!qualified_name) {
enclosing_name = &specification_->enclosing_name; // Find our unqualified name. If the DIE has its own DW_AT_name
else // attribute, then use that; otherwise, check our specification.
enclosing_name = &parent_context_->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.
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 // If this DIE was marked as a declaration, record its names in the
// specification table. // specification table.
if (declaration_) { if (declaration_) {
FileContext *file_context = cu_context_->file_context; FileContext *file_context = cu_context_->file_context;
Specification spec; Specification spec;
spec.enclosing_name = *enclosing_name; if (qualified_name)
spec.unqualified_name = *unqualified_name; spec.qualified_name = *qualified_name;
else {
spec.enclosing_name = *enclosing_name;
spec.unqualified_name = *unqualified_name;
}
file_context->file_private->specifications[offset_] = spec; file_context->file_private->specifications[offset_] = spec;
} }
if (qualified_name)
return *qualified_name;
// Combine the enclosing name and unqualified name to produce our // Combine the enclosing name and unqualified name to produce our
// own fully-qualified name. // own fully-qualified name.
return cu_context_->language->MakeQualifiedName(*enclosing_name, return cu_context_->language->MakeQualifiedName(*enclosing_name,

View file

@ -209,7 +209,8 @@ class CUFixtureBase {
// offset, tag and name. If NAME is the empty string, don't provide // offset, tag and name. If NAME is the empty string, don't provide
// a DW_AT_name attribute. Call EndAttributes and Finish. // a DW_AT_name attribute. Call EndAttributes and Finish.
void DeclarationDIE(DIEHandler *parent, uint64 offset, 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 // Create a definition DIE as a child of PARENT with the given tag
// that refers to the declaration DIE at offset SPECIFICATION as its // 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, void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset,
DwarfTag tag, DwarfTag tag,
const string &name) { const string &name,
const string &mangled_name) {
dwarf2reader::AttributeList attrs; dwarf2reader::AttributeList attrs;
if (!name.empty()) if (!name.empty())
attrs.push_back(make_pair(dwarf2reader::DW_AT_name, attrs.push_back(make_pair(dwarf2reader::DW_AT_name,
dwarf2reader::DW_FORM_strp)); dwarf2reader::DW_FORM_strp));
attrs.push_back(make_pair(dwarf2reader::DW_AT_declaration, attrs.push_back(make_pair(dwarf2reader::DW_AT_declaration,
dwarf2reader::DW_FORM_flag)); dwarf2reader::DW_FORM_flag));
dwarf2reader::DIEHandler *die = parent->FindChildHandler(offset, tag, attrs); 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, die->ProcessAttributeString(dwarf2reader::DW_AT_name,
dwarf2reader::DW_FORM_strp, dwarf2reader::DW_FORM_strp,
name); 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, die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_declaration,
dwarf2reader::DW_FORM_flag, dwarf2reader::DW_FORM_flag,
1); 1);
@ -683,7 +692,7 @@ void CUFixtureBase::TestLine(int i, int j,
#define SetLanguage(a) TRACE(SetLanguage(a)) #define SetLanguage(a) TRACE(SetLanguage(a))
#define StartCU() TRACE(StartCU()) #define StartCU() TRACE(StartCU())
#define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e))) #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 DefinitionDIE(a,b,c,d,e,f) TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f)))
#define TestFunctionCount(a) TRACE(TestFunctionCount(a)) #define TestFunctionCount(a) TRACE(TestFunctionCount(a))
#define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d))) #define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d)))
@ -1224,7 +1233,7 @@ TEST_F(Specifications, Function) {
StartCU(); StartCU();
DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
dwarf2reader::DW_TAG_subprogram, "declaration-name"); dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
0xcd3c51b946fb1eeeLL, "", 0xcd3c51b946fb1eeeLL, "",
0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
@ -1235,6 +1244,23 @@ TEST_F(Specifications, Function) {
0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); 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) { TEST_F(Specifications, MemberFunction) {
PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691); PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691);
@ -1242,7 +1268,7 @@ TEST_F(Specifications, MemberFunction) {
DIEHandler *class_handler DIEHandler *class_handler
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A"); = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A");
DeclarationDIE(class_handler, 0x7d83028c431406e8ULL, DeclarationDIE(class_handler, 0x7d83028c431406e8ULL,
dwarf2reader::DW_TAG_subprogram, "declaration-name"); dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
class_handler->Finish(); class_handler->Finish();
delete class_handler; delete class_handler;
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
@ -1267,7 +1293,7 @@ TEST_F(Specifications, FunctionDeclarationParent) {
"class_A"); "class_A");
ASSERT_TRUE(class_handler != NULL); ASSERT_TRUE(class_handler != NULL);
DeclarationDIE(class_handler, 0x0e0e877c8404544aULL, DeclarationDIE(class_handler, 0x0e0e877c8404544aULL,
dwarf2reader::DW_TAG_subprogram, "declaration-name"); dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
class_handler->Finish(); class_handler->Finish();
delete class_handler; delete class_handler;
} }
@ -1295,7 +1321,8 @@ TEST_F(Specifications, NamedScopeDeclarationParent) {
"space_A"); "space_A");
ASSERT_TRUE(space_handler != NULL); ASSERT_TRUE(space_handler != NULL);
DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL, DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL,
dwarf2reader::DW_TAG_class_type, "class-declaration-name"); dwarf2reader::DW_TAG_class_type, "class-declaration-name",
"");
space_handler->Finish(); space_handler->Finish();
delete space_handler; delete space_handler;
} }
@ -1324,7 +1351,7 @@ TEST_F(Specifications, InlineFunction) {
StartCU(); StartCU();
DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
dwarf2reader::DW_TAG_subprogram, "inline-name"); dwarf2reader::DW_TAG_subprogram, "inline-name", "");
AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL, AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, ""); dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, "");
DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL, DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
@ -1374,7 +1401,7 @@ TEST_F(Specifications, LongChain) {
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace, = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
"space_A"); "space_A");
DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL, DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL,
dwarf2reader::DW_TAG_namespace, "space_B"); dwarf2reader::DW_TAG_namespace, "space_B", "");
space_A_handler->Finish(); space_A_handler->Finish();
delete space_A_handler; delete space_A_handler;
} }
@ -1387,7 +1414,7 @@ TEST_F(Specifications, LongChain) {
= StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type, = StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type,
"struct_C"); "struct_C");
DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL, DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL,
dwarf2reader::DW_TAG_structure_type, "struct_D"); dwarf2reader::DW_TAG_structure_type, "struct_D", "");
struct_C_handler->Finish(); struct_C_handler->Finish();
delete struct_C_handler; delete struct_C_handler;
space_B_handler->Finish(); space_B_handler->Finish();
@ -1402,7 +1429,7 @@ TEST_F(Specifications, LongChain) {
= StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type, = StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type,
"union_E"); "union_E");
DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL, DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL,
dwarf2reader::DW_TAG_union_type, "union_F"); dwarf2reader::DW_TAG_union_type, "union_F", "");
union_E_handler->Finish(); union_E_handler->Finish();
delete union_E_handler; delete union_E_handler;
struct_D_handler->Finish(); struct_D_handler->Finish();
@ -1417,7 +1444,7 @@ TEST_F(Specifications, LongChain) {
= StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type, = StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type,
"class_G"); "class_G");
DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL, DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL,
dwarf2reader::DW_TAG_class_type, "class_H"); dwarf2reader::DW_TAG_class_type, "class_H", "");
class_G_handler->Finish(); class_G_handler->Finish();
delete class_G_handler; delete class_G_handler;
union_F_handler->Finish(); union_F_handler->Finish();
@ -1429,7 +1456,7 @@ TEST_F(Specifications, LongChain) {
= StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
0xb70d960dcc173b6eULL); 0xb70d960dcc173b6eULL);
DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL, DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL,
dwarf2reader::DW_TAG_subprogram, "func_I"); dwarf2reader::DW_TAG_subprogram, "func_I", "");
class_H_handler->Finish(); class_H_handler->Finish();
delete class_H_handler; delete class_H_handler;
} }
@ -1467,7 +1494,7 @@ TEST_F(Specifications, InterCU) {
ProcessStrangeAttributes(&root1_handler); ProcessStrangeAttributes(&root1_handler);
ASSERT_TRUE(root1_handler.EndAttributes()); ASSERT_TRUE(root1_handler.EndAttributes());
DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL, DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL,
dwarf2reader::DW_TAG_class_type, "class_A"); dwarf2reader::DW_TAG_class_type, "class_A", "");
root1_handler.Finish(); root1_handler.Finish();
} }
@ -1482,7 +1509,7 @@ TEST_F(Specifications, InterCU) {
= StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type, = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type,
0xb8fbfdd5f0b26fceULL); 0xb8fbfdd5f0b26fceULL);
DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL, DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL,
dwarf2reader::DW_TAG_subprogram, "member_func_B"); dwarf2reader::DW_TAG_subprogram, "member_func_B", "");
class_A_handler->Finish(); class_A_handler->Finish();
delete class_A_handler; delete class_A_handler;
root2_handler.Finish(); root2_handler.Finish();
@ -1514,7 +1541,7 @@ TEST_F(Specifications, BadOffset) {
StartCU(); StartCU();
DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL, DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL,
dwarf2reader::DW_TAG_subprogram, ""); dwarf2reader::DW_TAG_subprogram, "", "");
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
0x2be953efa6f9a996ULL, "function", 0x2be953efa6f9a996ULL, "function",
0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL); 0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL);
@ -1526,7 +1553,7 @@ TEST_F(Specifications, FunctionDefinitionHasOwnName) {
StartCU(); StartCU();
DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL, DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL,
dwarf2reader::DW_TAG_subprogram, "declaration-name"); dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
0xc34ff4786cae78bdULL, "definition-name", 0xc34ff4786cae78bdULL, "definition-name",
0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL); 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL);
@ -1542,7 +1569,7 @@ TEST_F(Specifications, ClassDefinitionHasOwnName) {
StartCU(); StartCU();
DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL, DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL,
dwarf2reader::DW_TAG_class_type, "class-declaration-name"); dwarf2reader::DW_TAG_class_type, "class-declaration-name", "");
dwarf2reader::DIEHandler *class_definition dwarf2reader::DIEHandler *class_definition
= StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
@ -1550,7 +1577,7 @@ TEST_F(Specifications, ClassDefinitionHasOwnName) {
ASSERT_TRUE(class_definition); ASSERT_TRUE(class_definition);
DeclarationDIE(class_definition, 0x6d028229c15623dbULL, DeclarationDIE(class_definition, 0x6d028229c15623dbULL,
dwarf2reader::DW_TAG_subprogram, dwarf2reader::DW_TAG_subprogram,
"function-declaration-name"); "function-declaration-name", "");
class_definition->Finish(); class_definition->Finish();
delete class_definition; delete class_definition;
@ -1578,7 +1605,8 @@ TEST_F(Specifications, PreferSpecificationParents) {
dwarf2reader::DIEHandler *declaration_class_handler dwarf2reader::DIEHandler *declaration_class_handler
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "declaration-class"); = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "declaration-class");
DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL, DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL,
dwarf2reader::DW_TAG_subprogram, "function-declaration"); dwarf2reader::DW_TAG_subprogram, "function-declaration",
"");
declaration_class_handler->Finish(); declaration_class_handler->Finish();
delete declaration_class_handler; delete declaration_class_handler;
} }