Bug 942290 - Merge ARM exidx info with DWARF if both are present. r=ted

This commit is contained in:
Jed Davis 2014-05-19 15:46:00 +02:00
parent a73a63035b
commit 8e0a916215
5 changed files with 124 additions and 11 deletions

View File

@ -0,0 +1,93 @@
commit 8885dea3716170ec7f3b213421c330f31cd5ac4b
Author: Jed Davis <jld@mozilla.com>
Date: Mon May 19 15:41:28 2014 -0700
Bug 942290: Merge ARM exidx info with DWARF if both are present.
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
index 5d87ab4..97f99e4 100644
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
@@ -487,14 +487,16 @@ void ExceptionTableInfo::Start()
// create CFI entries that Breakpad can use. This can also fail.
// First, add a new stack frame entry, into which ExtabEntryDecode
// will write the CFI entries.
- handler_->AddStackFrame(addr, next_addr - addr);
- int ret = ExtabEntryDecode(buf, buf_used);
- if (ret < 0) {
- handler_->DeleteStackFrame();
- BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
- continue;
+ if (!handler_->HasStackFrame(addr, next_addr - addr)) {
+ handler_->AddStackFrame(addr, next_addr - addr);
+ int ret = ExtabEntryDecode(buf, buf_used);
+ if (ret < 0) {
+ handler_->DeleteStackFrame();
+ BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
+ continue;
+ }
+ handler_->SubmitStackFrame();
}
- handler_->SubmitStackFrame();
} /* iterating over .exidx */
}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
index f8535b7..b5e3b06 100644
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
@@ -162,6 +162,21 @@ int ARMExToModule::TranslateCmd(const struct extab_data* edata,
return ret;
}
+bool ARMExToModule::HasStackFrame(uintptr_t addr, size_t size) {
+ // Invariant: the range [addr,covered) is covered by existing stack
+ // frame entries.
+ uintptr_t covered = addr;
+ while (covered < addr + size) {
+ const Module::StackFrameEntry *old_entry =
+ module_->FindStackFrameEntryByAddress(covered);
+ if (!old_entry) {
+ return false;
+ }
+ covered = old_entry->address + old_entry->size;
+ }
+ return true;
+}
+
void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
stack_frame_entry_ = new Module::StackFrameEntry;
stack_frame_entry_->address = addr;
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
index 73c936c..9d6a879 100644
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
@@ -108,6 +108,7 @@ class ARMExToModule {
ARMExToModule(Module* module)
: module_(module) { }
~ARMExToModule() { }
+ bool HasStackFrame(uintptr_t addr, size_t size);
void AddStackFrame(uintptr_t addr, size_t size);
int ImproveStackFrame(const struct extab_data* edata);
void DeleteStackFrame();
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
index d59832c..9a54bab 100644
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
@@ -695,10 +695,12 @@ bool LoadSymbols(const string& obj_file,
FindElfSectionByName<ElfClass>(".ARM.extab", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
- // Only load information from this section if there isn't a .debug_info
- // section.
- if (!found_debug_info_section
- && arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
+ // Load information from these sections even if there is
+ // .debug_info, because some functions (e.g., hand-written or
+ // script-generated assembly) could have exidx entries but no DWARF.
+ // (For functions with both, the DWARF info that has already been
+ // parsed will take precedence.)
+ if (arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
info->LoadedSection(".ARM.exidx");
info->LoadedSection(".ARM.extab");
bool result = LoadARMexidx<ElfClass>(elf_header,

View File

@ -487,14 +487,16 @@ void ExceptionTableInfo::Start()
// create CFI entries that Breakpad can use. This can also fail.
// First, add a new stack frame entry, into which ExtabEntryDecode
// will write the CFI entries.
handler_->AddStackFrame(addr, next_addr - addr);
int ret = ExtabEntryDecode(buf, buf_used);
if (ret < 0) {
handler_->DeleteStackFrame();
BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
continue;
if (!handler_->HasStackFrame(addr, next_addr - addr)) {
handler_->AddStackFrame(addr, next_addr - addr);
int ret = ExtabEntryDecode(buf, buf_used);
if (ret < 0) {
handler_->DeleteStackFrame();
BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
continue;
}
handler_->SubmitStackFrame();
}
handler_->SubmitStackFrame();
} /* iterating over .exidx */
}

View File

@ -162,6 +162,21 @@ int ARMExToModule::TranslateCmd(const struct extab_data* edata,
return ret;
}
bool ARMExToModule::HasStackFrame(uintptr_t addr, size_t size) {
// Invariant: the range [addr,covered) is covered by existing stack
// frame entries.
uintptr_t covered = addr;
while (covered < addr + size) {
const Module::StackFrameEntry *old_entry =
module_->FindStackFrameEntryByAddress(covered);
if (!old_entry) {
return false;
}
covered = old_entry->address + old_entry->size;
}
return true;
}
void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
stack_frame_entry_ = new Module::StackFrameEntry;
stack_frame_entry_->address = addr;

View File

@ -108,6 +108,7 @@ class ARMExToModule {
ARMExToModule(Module* module)
: module_(module) { }
~ARMExToModule() { }
bool HasStackFrame(uintptr_t addr, size_t size);
void AddStackFrame(uintptr_t addr, size_t size);
int ImproveStackFrame(const struct extab_data* edata);
void DeleteStackFrame();

View File

@ -695,10 +695,12 @@ bool LoadSymbols(const string& obj_file,
FindElfSectionByName<ElfClass>(".ARM.extab", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
// Only load information from this section if there isn't a .debug_info
// section.
if (!found_debug_info_section
&& arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
// Load information from these sections even if there is
// .debug_info, because some functions (e.g., hand-written or
// script-generated assembly) could have exidx entries but no DWARF.
// (For functions with both, the DWARF info that has already been
// parsed will take precedence.)
if (arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
info->LoadedSection(".ARM.exidx");
info->LoadedSection(".ARM.extab");
bool result = LoadARMexidx<ElfClass>(elf_header,