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,
|
||||
uint64 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,
|
||||
enum DwarfForm form,
|
||||
uint64 data);
|
||||
|
@ -404,6 +405,7 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
|||
// specification_, parent_context_. Computed in EndAttributes.
|
||||
string name_;
|
||||
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_;
|
||||
bool inline_;
|
||||
};
|
||||
|
@ -419,7 +421,11 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
|||
case dwarf2reader::DW_AT_inline: inline_ = true; 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:
|
||||
GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
|
||||
break;
|
||||
|
@ -473,6 +479,11 @@ bool DwarfCUToModule::FuncHandler::EndAttributes() {
|
|||
}
|
||||
|
||||
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
|
||||
// entries have low and high addresses (for example, inlined
|
||||
// functions that were never used), but all the ones we're
|
||||
|
|
|
@ -193,12 +193,15 @@ class CUFixtureBase {
|
|||
DIEHandler *StartSpecifiedDIE(DIEHandler *parent, DwarfTag tag,
|
||||
uint64 specification, const char *name = NULL);
|
||||
|
||||
// Define a function as a child of PARENT with the given name,
|
||||
// address, and size. Call EndAttributes and Finish; one cannot
|
||||
// define children of the defined function's DIE.
|
||||
// Define a function as a child of PARENT with the given name, address, and
|
||||
// size. If high_pc_form is DW_FORM_addr then the DW_AT_high_pc attribute
|
||||
// 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,
|
||||
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
|
||||
// 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,
|
||||
const string &name, Module::Address address,
|
||||
Module::Address size,
|
||||
const char* mangled_name) {
|
||||
const char* mangled_name,
|
||||
DwarfForm high_pc_form) {
|
||||
dwarf2reader::DIEHandler *func
|
||||
= parent->FindChildHandler(0xe34797c7e68590a8LL,
|
||||
dwarf2reader::DW_TAG_subprogram);
|
||||
|
@ -425,9 +429,15 @@ void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
|||
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
|
||||
dwarf2reader::DW_FORM_addr,
|
||||
address);
|
||||
|
||||
Module::Address high_pc = size;
|
||||
if (high_pc_form == dwarf2reader::DW_FORM_addr) {
|
||||
high_pc += address;
|
||||
}
|
||||
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
|
||||
dwarf2reader::DW_FORM_addr,
|
||||
address + size);
|
||||
high_pc_form,
|
||||
high_pc);
|
||||
|
||||
if (mangled_name)
|
||||
func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
|
||||
dwarf2reader::DW_FORM_strp,
|
||||
|
@ -598,16 +608,20 @@ void CUFixtureBase::TestLine(int i, int j,
|
|||
|
||||
// Include caller locations for our test subroutines.
|
||||
#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 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,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)))
|
||||
#define TestLineCount(a,b) TRACE(TestLineCount((a),(b)))
|
||||
#define TestLine(a,b,c,d,e,f) TRACE(TestLine((a),(b),(c),(d),(e),(f)))
|
||||
#define PushLine(a,b,c,d) TRACE(PushLine((a),(b),(c),(d)))
|
||||
#define SetLanguage(a) TRACE(SetLanguage(a))
|
||||
#define StartCU() TRACE(StartCU())
|
||||
#define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e)))
|
||||
// (DefineFunction) instead of DefineFunction to avoid macro expansion.
|
||||
#define DefineFunction6(a,b,c,d,e,f) \
|
||||
TRACE((DefineFunction)((a),(b),(c),(d),(e),(f)))
|
||||
#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)))
|
||||
#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 {
|
||||
};
|
||||
|
@ -627,6 +641,23 @@ TEST_F(SimpleCU, OneFunc) {
|
|||
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) {
|
||||
PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
|
||||
|
||||
|
|
Loading…
Reference in a new issue