aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-01-08 02:14:44 +0000
committerjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-01-08 02:14:44 +0000
commita8426a5c6607c5f3384e948c74e7cab29c3809ff (patch)
treea07c7a8865235f8b47c444e41bd5a85e76287512 /src
parent Fix typo. (diff)
downloadbreakpad-a8426a5c6607c5f3384e948c74e7cab29c3809ff.tar.xz
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
Diffstat (limited to 'src')
-rw-r--r--src/common/dwarf_cu_to_module.cc15
-rw-r--r--src/common/dwarf_cu_to_module_unittest.cc65
2 files changed, 61 insertions, 19 deletions
diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc
index 04b8843f..127beacb 100644
--- a/src/common/dwarf_cu_to_module.cc
+++ b/src/common/dwarf_cu_to_module.cc
@@ -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
diff --git a/src/common/dwarf_cu_to_module_unittest.cc b/src/common/dwarf_cu_to_module_unittest.cc
index e71d344b..37061d2a 100644
--- a/src/common/dwarf_cu_to_module_unittest.cc
+++ b/src/common/dwarf_cu_to_module_unittest.cc
@@ -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);