DWARF can store DW_AT_high_pc as either an address or a constant. In the latter
case it's the length of the function. breakpad always treats it as an address. a=mattdr, r=jimb git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1094 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
3d451f31d8
commit
a8426a5c66
2 changed files with 61 additions and 19 deletions
|
@ -385,7 +385,8 @@ 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), abstract_origin_(NULL), inline_(false) { }
|
low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr),
|
||||||
|
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);
|
||||||
|
@ -404,6 +405,7 @@ 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
|
||||||
|
DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address.
|
||||||
const AbstractOrigin* abstract_origin_;
|
const AbstractOrigin* abstract_origin_;
|
||||||
bool inline_;
|
bool inline_;
|
||||||
};
|
};
|
||||||
|
@ -419,7 +421,11 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
||||||
case dwarf2reader::DW_AT_inline: inline_ = true; break;
|
case dwarf2reader::DW_AT_inline: inline_ = true; 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_form_ = form;
|
||||||
|
high_pc_ = data;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
|
GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
|
||||||
break;
|
break;
|
||||||
|
@ -473,6 +479,11 @@ bool DwarfCUToModule::FuncHandler::EndAttributes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DwarfCUToModule::FuncHandler::Finish() {
|
void DwarfCUToModule::FuncHandler::Finish() {
|
||||||
|
// Make high_pc_ an address, if it isn't already.
|
||||||
|
if (high_pc_form_ != dwarf2reader::DW_FORM_addr) {
|
||||||
|
high_pc_ += low_pc_;
|
||||||
|
}
|
||||||
|
|
||||||
// Did we collect the information we need? Not all DWARF function
|
// Did we collect the information we need? Not all DWARF function
|
||||||
// entries have low and high addresses (for example, inlined
|
// entries have low and high addresses (for example, inlined
|
||||||
// functions that were never used), but all the ones we're
|
// functions that were never used), but all the ones we're
|
||||||
|
|
|
@ -193,12 +193,15 @@ class CUFixtureBase {
|
||||||
DIEHandler *StartSpecifiedDIE(DIEHandler *parent, DwarfTag tag,
|
DIEHandler *StartSpecifiedDIE(DIEHandler *parent, DwarfTag tag,
|
||||||
uint64 specification, const char *name = NULL);
|
uint64 specification, const char *name = NULL);
|
||||||
|
|
||||||
// Define a function as a child of PARENT with the given name,
|
// Define a function as a child of PARENT with the given name, address, and
|
||||||
// address, and size. Call EndAttributes and Finish; one cannot
|
// size. If high_pc_form is DW_FORM_addr then the DW_AT_high_pc attribute
|
||||||
// define children of the defined function's DIE.
|
// will be written as an address; otherwise it will be written as the
|
||||||
|
// function's size. Call EndAttributes and Finish; one cannot define
|
||||||
|
// children of the defined function's DIE.
|
||||||
void DefineFunction(DIEHandler *parent, const string &name,
|
void DefineFunction(DIEHandler *parent, const string &name,
|
||||||
Module::Address address, Module::Address size,
|
Module::Address address, Module::Address size,
|
||||||
const char* mangled_name);
|
const char* mangled_name,
|
||||||
|
DwarfForm high_pc_form = dwarf2reader::DW_FORM_addr);
|
||||||
|
|
||||||
// Create a declaration DIE as a child of PARENT with the given
|
// Create a declaration DIE as a child of PARENT with the given
|
||||||
// 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
|
||||||
|
@ -414,7 +417,8 @@ DIEHandler *CUFixtureBase::StartSpecifiedDIE(DIEHandler *parent,
|
||||||
void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
||||||
const string &name, Module::Address address,
|
const string &name, Module::Address address,
|
||||||
Module::Address size,
|
Module::Address size,
|
||||||
const char* mangled_name) {
|
const char* mangled_name,
|
||||||
|
DwarfForm high_pc_form) {
|
||||||
dwarf2reader::DIEHandler *func
|
dwarf2reader::DIEHandler *func
|
||||||
= parent->FindChildHandler(0xe34797c7e68590a8LL,
|
= parent->FindChildHandler(0xe34797c7e68590a8LL,
|
||||||
dwarf2reader::DW_TAG_subprogram);
|
dwarf2reader::DW_TAG_subprogram);
|
||||||
|
@ -425,9 +429,15 @@ void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
||||||
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
|
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
|
||||||
dwarf2reader::DW_FORM_addr,
|
dwarf2reader::DW_FORM_addr,
|
||||||
address);
|
address);
|
||||||
|
|
||||||
|
Module::Address high_pc = size;
|
||||||
|
if (high_pc_form == dwarf2reader::DW_FORM_addr) {
|
||||||
|
high_pc += address;
|
||||||
|
}
|
||||||
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
|
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
|
||||||
dwarf2reader::DW_FORM_addr,
|
high_pc_form,
|
||||||
address + size);
|
high_pc);
|
||||||
|
|
||||||
if (mangled_name)
|
if (mangled_name)
|
||||||
func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
|
func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
|
||||||
dwarf2reader::DW_FORM_strp,
|
dwarf2reader::DW_FORM_strp,
|
||||||
|
@ -598,16 +608,20 @@ void CUFixtureBase::TestLine(int i, int j,
|
||||||
|
|
||||||
// Include caller locations for our test subroutines.
|
// Include caller locations for our test subroutines.
|
||||||
#define TRACE(call) do { SCOPED_TRACE("called from here"); call; } while (0)
|
#define TRACE(call) do { SCOPED_TRACE("called from here"); call; } while (0)
|
||||||
#define PushLine(a,b,c,d) TRACE(PushLine((a),(b),(c),(d)))
|
#define PushLine(a,b,c,d) TRACE(PushLine((a),(b),(c),(d)))
|
||||||
#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,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e)))
|
// (DefineFunction) instead of DefineFunction to avoid macro expansion.
|
||||||
#define DefinitionDIE(a,b,c,d,e,f) TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f)))
|
#define DefineFunction6(a,b,c,d,e,f) \
|
||||||
#define TestFunctionCount(a) TRACE(TestFunctionCount(a))
|
TRACE((DefineFunction)((a),(b),(c),(d),(e),(f)))
|
||||||
#define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d)))
|
#define DeclarationDIE(a,b,c,d,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e)))
|
||||||
#define TestLineCount(a,b) TRACE(TestLineCount((a),(b)))
|
#define DefinitionDIE(a,b,c,d,e,f) \
|
||||||
#define TestLine(a,b,c,d,e,f) TRACE(TestLine((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)))
|
||||||
|
#define TestLineCount(a,b) TRACE(TestLineCount((a),(b)))
|
||||||
|
#define TestLine(a,b,c,d,e,f) TRACE(TestLine((a),(b),(c),(d),(e),(f)))
|
||||||
|
|
||||||
class SimpleCU: public CUFixtureBase, public Test {
|
class SimpleCU: public CUFixtureBase, public Test {
|
||||||
};
|
};
|
||||||
|
@ -627,6 +641,23 @@ TEST_F(SimpleCU, OneFunc) {
|
||||||
246571772);
|
246571772);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As above, only DW_AT_high_pc is a length rather than an address.
|
||||||
|
TEST_F(SimpleCU, OneFuncHighPcIsLength) {
|
||||||
|
PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
|
||||||
|
|
||||||
|
StartCU();
|
||||||
|
DefineFunction6(&root_handler_, "function1",
|
||||||
|
0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL,
|
||||||
|
dwarf2reader::DW_FORM_udata);
|
||||||
|
root_handler_.Finish();
|
||||||
|
|
||||||
|
TestFunctionCount(1);
|
||||||
|
TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
|
||||||
|
TestLineCount(0, 1);
|
||||||
|
TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file",
|
||||||
|
246571772);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(SimpleCU, MangledName) {
|
TEST_F(SimpleCU, MangledName) {
|
||||||
PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
|
PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue