mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-24 11:55:47 +01:00
Linux DWARF reader: Follow DW_AT_abstract_origin links to find function names.
Without this patch, debugging information like the following will produce FUNC records with no names, because the dumper (correctly) ignores the DW_TAG_subprogram DIEs that lack DW_AT_low_pc/DW_AT_high_pc attributes, but won't follow the DW_AT_abstract_origin link from the DIE that does have code addresses to find its name. <1><168>: Abbrev Number: 5 (DW_TAG_class_type) <169> DW_AT_name : Foo <2><183>: Abbrev Number: 7 (DW_TAG_subprogram) <185> DW_AT_name : Foo <18b> DW_AT_declaration : 1 <1><1b7>: Abbrev Number: 12 (DW_TAG_subprogram) <1b8> DW_AT_specification: <0x183> <1bc> DW_AT_inline : 2 (declared as inline but ignored) <1><1dc>: Abbrev Number: 16 (DW_TAG_subprogram) <1dd> DW_AT_abstract_origin: <0x1b7> <1e1> DW_AT_low_pc : 0x8048578 <1e5> DW_AT_high_pc : 0x8048588 a=dmuir, r=jimblandy git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@520 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
952f3c7b73
commit
dd5067f391
@ -522,5 +522,13 @@ enum DwarfLanguage
|
|||||||
DW_LANG_Upc =0x8765 // Unified Parallel C
|
DW_LANG_Upc =0x8765 // Unified Parallel C
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Inline codes. These are values for DW_AT_inline.
|
||||||
|
enum DwarfInline {
|
||||||
|
DW_INL_not_inlined =0x0,
|
||||||
|
DW_INL_inlined =0x1,
|
||||||
|
DW_INL_declared_not_inlined =0x2,
|
||||||
|
DW_INL_declared_inlined =0x3,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace dwarf2reader
|
} // namespace dwarf2reader
|
||||||
#endif // COMMON_DWARF_DWARF2ENUMS_H__
|
#endif // COMMON_DWARF_DWARF2ENUMS_H__
|
||||||
|
@ -68,6 +68,16 @@ struct DwarfCUToModule::Specification {
|
|||||||
string unqualified_name;
|
string unqualified_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An abstract origin -- base definition of an inline function.
|
||||||
|
struct AbstractOrigin {
|
||||||
|
AbstractOrigin() : name() {}
|
||||||
|
AbstractOrigin(const string& name) : name(name) {}
|
||||||
|
|
||||||
|
string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef map<uint64, AbstractOrigin> AbstractOriginByOffset;
|
||||||
|
|
||||||
// Data global to the DWARF-bearing file that is private to the
|
// Data global to the DWARF-bearing file that is private to the
|
||||||
// DWARF-to-Module process.
|
// DWARF-to-Module process.
|
||||||
struct DwarfCUToModule::FilePrivate {
|
struct DwarfCUToModule::FilePrivate {
|
||||||
@ -75,6 +85,8 @@ struct DwarfCUToModule::FilePrivate {
|
|||||||
// Specifications describing those DIEs. Specification references can
|
// Specifications describing those DIEs. Specification references can
|
||||||
// cross compilation unit boundaries.
|
// cross compilation unit boundaries.
|
||||||
SpecificationByOffset specifications;
|
SpecificationByOffset specifications;
|
||||||
|
|
||||||
|
AbstractOriginByOffset origins;
|
||||||
};
|
};
|
||||||
|
|
||||||
DwarfCUToModule::FileContext::FileContext(const string &filename_arg,
|
DwarfCUToModule::FileContext::FileContext(const string &filename_arg,
|
||||||
@ -230,7 +242,7 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
|
|||||||
// don't think any producers we care about ever emit such
|
// don't think any producers we care about ever emit such
|
||||||
// things.
|
// things.
|
||||||
cu_context_->reporter->UnknownSpecification(offset_, data);
|
cu_context_->reporter->UnknownSpecification(offset_, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
@ -287,10 +299,17 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
|||||||
FuncHandler(CUContext *cu_context, DIEContext *parent_context,
|
FuncHandler(CUContext *cu_context, DIEContext *parent_context,
|
||||||
uint64 offset)
|
uint64 offset)
|
||||||
: GenericDIEHandler(cu_context, parent_context, offset),
|
: GenericDIEHandler(cu_context, parent_context, offset),
|
||||||
low_pc_(0), high_pc_(0) { }
|
low_pc_(0), high_pc_(0), abstract_origin_(NULL), inline_(false) { }
|
||||||
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
uint64 data);
|
uint64 data);
|
||||||
|
void ProcessAttributeSigned(enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
int64 data);
|
||||||
|
void ProcessAttributeReference(enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 data);
|
||||||
|
|
||||||
bool EndAttributes();
|
bool EndAttributes();
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
@ -299,6 +318,8 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
|||||||
// specification_, parent_context_. Computed in EndAttributes.
|
// specification_, parent_context_. Computed in EndAttributes.
|
||||||
string name_;
|
string name_;
|
||||||
uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
|
uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
|
||||||
|
const AbstractOrigin* abstract_origin_;
|
||||||
|
bool inline_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
||||||
@ -306,6 +327,16 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
|||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
uint64 data) {
|
uint64 data) {
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
|
case dwarf2reader::DW_AT_inline:
|
||||||
|
switch(data) {
|
||||||
|
case dwarf2reader::DW_INL_inlined:
|
||||||
|
case dwarf2reader::DW_INL_declared_not_inlined:
|
||||||
|
case dwarf2reader::DW_INL_declared_inlined:
|
||||||
|
inline_ = true; break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case dwarf2reader::DW_AT_low_pc: low_pc_ = data; break;
|
case dwarf2reader::DW_AT_low_pc: low_pc_ = data; break;
|
||||||
case dwarf2reader::DW_AT_high_pc: high_pc_ = data; break;
|
case dwarf2reader::DW_AT_high_pc: high_pc_ = data; break;
|
||||||
default:
|
default:
|
||||||
@ -314,9 +345,54 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfCUToModule::FuncHandler::ProcessAttributeSigned(
|
||||||
|
enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
int64 data) {
|
||||||
|
switch (attr) {
|
||||||
|
case dwarf2reader::DW_AT_inline:
|
||||||
|
switch(data) {
|
||||||
|
case dwarf2reader::DW_INL_inlined:
|
||||||
|
case dwarf2reader::DW_INL_declared_not_inlined:
|
||||||
|
case dwarf2reader::DW_INL_declared_inlined:
|
||||||
|
inline_ = true; break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DwarfCUToModule::FuncHandler::ProcessAttributeReference(
|
||||||
|
enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 data) {
|
||||||
|
switch(attr) {
|
||||||
|
case dwarf2reader::DW_AT_abstract_origin: {
|
||||||
|
const AbstractOriginByOffset& origins =
|
||||||
|
cu_context_->file_context->file_private->origins;
|
||||||
|
AbstractOriginByOffset::const_iterator origin = origins.find(data);
|
||||||
|
if (origin != origins.end()) {
|
||||||
|
abstract_origin_ = &(origin->second);
|
||||||
|
} else {
|
||||||
|
cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
GenericDIEHandler::ProcessAttributeReference(attr, form, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool DwarfCUToModule::FuncHandler::EndAttributes() {
|
bool DwarfCUToModule::FuncHandler::EndAttributes() {
|
||||||
// Compute our name, and record a specification, if appropriate.
|
// Compute our name, and record a specification, if appropriate.
|
||||||
name_ = ComputeQualifiedName();
|
name_ = ComputeQualifiedName();
|
||||||
|
if (name_.empty() && abstract_origin_) {
|
||||||
|
name_ = abstract_origin_->name;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +410,9 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
|||||||
func->size = high_pc_ - low_pc_;
|
func->size = high_pc_ - low_pc_;
|
||||||
func->parameter_size = 0;
|
func->parameter_size = 0;
|
||||||
cu_context_->functions.push_back(func);
|
cu_context_->functions.push_back(func);
|
||||||
|
} else if (inline_) {
|
||||||
|
AbstractOrigin origin(name_);
|
||||||
|
cu_context_->file_context->file_private->origins[offset_] = origin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,6 +470,15 @@ void DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset,
|
|||||||
filename_.c_str(), offset, target);
|
filename_.c_str(), offset, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset,
|
||||||
|
uint64 target) {
|
||||||
|
CUHeading();
|
||||||
|
fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_abstract_origin"
|
||||||
|
" attribute referring to the die at offset 0x%llx, which either"
|
||||||
|
" was not marked as an inline, or comes later in the file",
|
||||||
|
filename_.c_str(), offset, target);
|
||||||
|
}
|
||||||
|
|
||||||
void DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
|
void DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
|
||||||
CUHeading();
|
CUHeading();
|
||||||
fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
|
fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
|
||||||
|
@ -130,7 +130,11 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
|
|||||||
// haven't processed yet, or that wasn't marked as a declaration,
|
// haven't processed yet, or that wasn't marked as a declaration,
|
||||||
// at TARGET.
|
// at TARGET.
|
||||||
virtual void UnknownSpecification(uint64 offset, uint64 target);
|
virtual void UnknownSpecification(uint64 offset, uint64 target);
|
||||||
|
|
||||||
|
// A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we
|
||||||
|
// haven't processed yet, or that wasn't marked as inline, at TARGET.
|
||||||
|
virtual void UnknownAbstractOrigin(uint64 offset, uint64 target);
|
||||||
|
|
||||||
// We were unable to find the DWARF section named SECTION_NAME.
|
// We were unable to find the DWARF section named SECTION_NAME.
|
||||||
virtual void MissingSection(const string §ion_name);
|
virtual void MissingSection(const string §ion_name);
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ using dwarf2reader::DIEHandler;
|
|||||||
using dwarf2reader::DwarfTag;
|
using dwarf2reader::DwarfTag;
|
||||||
using dwarf2reader::DwarfAttribute;
|
using dwarf2reader::DwarfAttribute;
|
||||||
using dwarf2reader::DwarfForm;
|
using dwarf2reader::DwarfForm;
|
||||||
|
using dwarf2reader::DwarfInline;
|
||||||
using dwarf2reader::RootDIEHandler;
|
using dwarf2reader::RootDIEHandler;
|
||||||
using google_breakpad::DwarfCUToModule;
|
using google_breakpad::DwarfCUToModule;
|
||||||
using google_breakpad::Module;
|
using google_breakpad::Module;
|
||||||
@ -74,6 +75,7 @@ class MockWarningReporter: public DwarfCUToModule::WarningReporter {
|
|||||||
: DwarfCUToModule::WarningReporter(filename, cu_offset) { }
|
: DwarfCUToModule::WarningReporter(filename, cu_offset) { }
|
||||||
MOCK_METHOD1(SetCUName, void(const string &name));
|
MOCK_METHOD1(SetCUName, void(const string &name));
|
||||||
MOCK_METHOD2(UnknownSpecification, void(uint64 offset, uint64 target));
|
MOCK_METHOD2(UnknownSpecification, void(uint64 offset, uint64 target));
|
||||||
|
MOCK_METHOD2(UnknownAbstractOrigin, void(uint64 offset, uint64 target));
|
||||||
MOCK_METHOD1(MissingSection, void(const string §ion_name));
|
MOCK_METHOD1(MissingSection, void(const string §ion_name));
|
||||||
MOCK_METHOD1(BadLineInfoOffset, void(uint64 offset));
|
MOCK_METHOD1(BadLineInfoOffset, void(uint64 offset));
|
||||||
MOCK_METHOD1(UncoveredFunction, void(const Module::Function &function));
|
MOCK_METHOD1(UncoveredFunction, void(const Module::Function &function));
|
||||||
@ -128,6 +130,7 @@ class CUFixtureBase {
|
|||||||
// these expectations.
|
// these expectations.
|
||||||
EXPECT_CALL(reporter_, SetCUName("compilation-unit-name")).Times(1);
|
EXPECT_CALL(reporter_, SetCUName("compilation-unit-name")).Times(1);
|
||||||
EXPECT_CALL(reporter_, UnknownSpecification(_, _)).Times(0);
|
EXPECT_CALL(reporter_, UnknownSpecification(_, _)).Times(0);
|
||||||
|
EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, _)).Times(0);
|
||||||
EXPECT_CALL(reporter_, MissingSection(_)).Times(0);
|
EXPECT_CALL(reporter_, MissingSection(_)).Times(0);
|
||||||
EXPECT_CALL(reporter_, BadLineInfoOffset(_)).Times(0);
|
EXPECT_CALL(reporter_, BadLineInfoOffset(_)).Times(0);
|
||||||
EXPECT_CALL(reporter_, UncoveredFunction(_)).Times(0);
|
EXPECT_CALL(reporter_, UncoveredFunction(_)).Times(0);
|
||||||
@ -210,6 +213,22 @@ class CUFixtureBase {
|
|||||||
uint64 specification, const string &name,
|
uint64 specification, const string &name,
|
||||||
Module::Address address = 0, Module::Address size = 0);
|
Module::Address address = 0, Module::Address size = 0);
|
||||||
|
|
||||||
|
// Create an inline DW_TAG_subprogram DIE as a child of PARENT. If
|
||||||
|
// SPECIFICATION is non-zero, then the DIE refers to the declaration DIE at
|
||||||
|
// offset SPECIFICATION as its specification. If Name is non-empty, pass it
|
||||||
|
// as the DW_AT_name attribute.
|
||||||
|
void AbstractInstanceDIE(DIEHandler *parent, uint64 offset,
|
||||||
|
DwarfInline type, uint64 specification,
|
||||||
|
const string &name,
|
||||||
|
DwarfForm form = dwarf2reader::DW_FORM_data1);
|
||||||
|
|
||||||
|
// Create a DW_TAG_subprogram DIE as a child of PARENT that refers to
|
||||||
|
// ORIGIN in its DW_AT_abstract_origin attribute. If NAME is the empty
|
||||||
|
// string, don't provide a DW_AT_name attribute.
|
||||||
|
void DefineInlineInstanceDIE(DIEHandler *parent, const string &name,
|
||||||
|
uint64 origin, Module::Address address,
|
||||||
|
Module::Address size);
|
||||||
|
|
||||||
// The following Test* functions should be called after calling
|
// The following Test* functions should be called after calling
|
||||||
// this.root_handler_.Finish. After that point, no further calls
|
// this.root_handler_.Finish. After that point, no further calls
|
||||||
// should be made on the handler.
|
// should be made on the handler.
|
||||||
@ -520,6 +539,83 @@ void CUFixtureBase::DefinitionDIE(DIEHandler *parent,
|
|||||||
delete die;
|
delete die;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CUFixtureBase::AbstractInstanceDIE(DIEHandler *parent,
|
||||||
|
uint64 offset,
|
||||||
|
DwarfInline type,
|
||||||
|
uint64 specification,
|
||||||
|
const string &name,
|
||||||
|
DwarfForm form) {
|
||||||
|
dwarf2reader::AttributeList attrs;
|
||||||
|
if (specification != 0ULL)
|
||||||
|
attrs.push_back(make_pair(dwarf2reader::DW_AT_specification,
|
||||||
|
dwarf2reader::DW_FORM_ref4));
|
||||||
|
attrs.push_back(make_pair(dwarf2reader::DW_AT_inline, form));
|
||||||
|
if (!name.empty())
|
||||||
|
attrs.push_back(make_pair(dwarf2reader::DW_AT_name,
|
||||||
|
dwarf2reader::DW_FORM_strp));
|
||||||
|
dwarf2reader::DIEHandler *die
|
||||||
|
= parent->FindChildHandler(offset, dwarf2reader::DW_TAG_subprogram, attrs);
|
||||||
|
ASSERT_TRUE(die != NULL);
|
||||||
|
if (specification != 0ULL)
|
||||||
|
die->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
|
||||||
|
dwarf2reader::DW_FORM_ref4,
|
||||||
|
specification);
|
||||||
|
if (form == dwarf2reader::DW_FORM_sdata) {
|
||||||
|
die->ProcessAttributeSigned(dwarf2reader::DW_AT_inline, form, type);
|
||||||
|
} else {
|
||||||
|
die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_inline, form, type);
|
||||||
|
}
|
||||||
|
if (!name.empty())
|
||||||
|
die->ProcessAttributeString(dwarf2reader::DW_AT_name,
|
||||||
|
dwarf2reader::DW_FORM_strp,
|
||||||
|
name);
|
||||||
|
|
||||||
|
EXPECT_TRUE(die->EndAttributes());
|
||||||
|
die->Finish();
|
||||||
|
delete die;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUFixtureBase::DefineInlineInstanceDIE(DIEHandler *parent,
|
||||||
|
const string &name,
|
||||||
|
uint64 origin,
|
||||||
|
Module::Address address,
|
||||||
|
Module::Address size) {
|
||||||
|
dwarf2reader::AttributeList func_attrs;
|
||||||
|
if (!name.empty())
|
||||||
|
func_attrs.push_back(make_pair(dwarf2reader::DW_AT_name,
|
||||||
|
dwarf2reader::DW_FORM_strp));
|
||||||
|
func_attrs.push_back(make_pair(dwarf2reader::DW_AT_low_pc,
|
||||||
|
dwarf2reader::DW_FORM_addr));
|
||||||
|
func_attrs.push_back(make_pair(dwarf2reader::DW_AT_high_pc,
|
||||||
|
dwarf2reader::DW_FORM_addr));
|
||||||
|
func_attrs.push_back(make_pair(dwarf2reader::DW_AT_abstract_origin,
|
||||||
|
dwarf2reader::DW_FORM_ref4));
|
||||||
|
PushBackStrangeAttributes(&func_attrs);
|
||||||
|
dwarf2reader::DIEHandler *func
|
||||||
|
= parent->FindChildHandler(0x11c70f94c6e87ccdLL,
|
||||||
|
dwarf2reader::DW_TAG_subprogram,
|
||||||
|
func_attrs);
|
||||||
|
ASSERT_TRUE(func != NULL);
|
||||||
|
if (!name.empty()) {
|
||||||
|
func->ProcessAttributeString(dwarf2reader::DW_AT_name,
|
||||||
|
dwarf2reader::DW_FORM_strp,
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
|
||||||
|
dwarf2reader::DW_FORM_addr,
|
||||||
|
address);
|
||||||
|
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
|
||||||
|
dwarf2reader::DW_FORM_addr,
|
||||||
|
address + size);
|
||||||
|
func->ProcessAttributeReference(dwarf2reader::DW_AT_abstract_origin,
|
||||||
|
dwarf2reader::DW_FORM_ref4,
|
||||||
|
origin);
|
||||||
|
ProcessStrangeAttributes(func);
|
||||||
|
EXPECT_TRUE(func->EndAttributes());
|
||||||
|
func->Finish();
|
||||||
|
delete func;
|
||||||
|
}
|
||||||
|
|
||||||
void CUFixtureBase::FillFunctions() {
|
void CUFixtureBase::FillFunctions() {
|
||||||
if (functions_filled_)
|
if (functions_filled_)
|
||||||
return;
|
return;
|
||||||
@ -629,6 +725,53 @@ TEST_F(Simple, UnusedFileContext) {
|
|||||||
reporter_.SetCUName("compilation-unit-name");
|
reporter_.SetCUName("compilation-unit-name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Simple, InlineFunction) {
|
||||||
|
PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
|
||||||
|
|
||||||
|
StartCU();
|
||||||
|
AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
|
||||||
|
dwarf2reader::DW_INL_inlined, 0, "inline-name");
|
||||||
|
DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
root_handler_.Finish();
|
||||||
|
|
||||||
|
TestFunctionCount(1);
|
||||||
|
TestFunction(0, "inline-name",
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Simple, InlineFunctionSignedAttribute) {
|
||||||
|
PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
|
||||||
|
|
||||||
|
StartCU();
|
||||||
|
AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
|
||||||
|
dwarf2reader::DW_INL_inlined, 0, "inline-name",
|
||||||
|
dwarf2reader::DW_FORM_sdata);
|
||||||
|
DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
root_handler_.Finish();
|
||||||
|
|
||||||
|
TestFunctionCount(1);
|
||||||
|
TestFunction(0, "inline-name",
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Simple, UnknownAbstractOrigin) {
|
||||||
|
EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, 1ULL)).WillOnce(Return());
|
||||||
|
PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
|
||||||
|
|
||||||
|
StartCU();
|
||||||
|
AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
|
||||||
|
dwarf2reader::DW_INL_inlined, 0, "inline-name");
|
||||||
|
DefineInlineInstanceDIE(&root_handler_, "", 1ULL,
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
root_handler_.Finish();
|
||||||
|
|
||||||
|
TestFunctionCount(1);
|
||||||
|
TestFunction(0, "",
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
}
|
||||||
|
|
||||||
// An address range.
|
// An address range.
|
||||||
struct Range {
|
struct Range {
|
||||||
Module::Address start, end;
|
Module::Address start, end;
|
||||||
@ -1114,6 +1257,24 @@ TEST_F(Specifications, NamedScopeDeclarationParent) {
|
|||||||
0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL);
|
0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test recreates bug 364.
|
||||||
|
TEST_F(Specifications, InlineFunction) {
|
||||||
|
PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
|
||||||
|
|
||||||
|
StartCU();
|
||||||
|
DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
|
||||||
|
dwarf2reader::DW_TAG_subprogram, "inline-name");
|
||||||
|
AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
|
||||||
|
dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, "");
|
||||||
|
DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
root_handler_.Finish();
|
||||||
|
|
||||||
|
TestFunctionCount(1);
|
||||||
|
TestFunction(0, "inline-name",
|
||||||
|
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
|
||||||
|
}
|
||||||
|
|
||||||
// Check name construction for a long chain containing each combination of:
|
// Check name construction for a long chain containing each combination of:
|
||||||
// - struct, union, class, namespace
|
// - struct, union, class, namespace
|
||||||
// - direct and definition
|
// - direct and definition
|
||||||
|
@ -50,6 +50,9 @@ COVERAGE=
|
|||||||
# SOME_ENV_VAR=value valgrind ./some-test-executable test-args
|
# SOME_ENV_VAR=value valgrind ./some-test-executable test-args
|
||||||
TEST_WRAPPER=
|
TEST_WRAPPER=
|
||||||
|
|
||||||
|
# Arguments to pass to the test programs.
|
||||||
|
TEST_ARGS=
|
||||||
|
|
||||||
### Variables used internally by this Makefile.
|
### Variables used internally by this Makefile.
|
||||||
|
|
||||||
# The top of the breakpad source tree.
|
# The top of the breakpad source tree.
|
||||||
|
Loading…
Reference in New Issue
Block a user