diff options
author | jimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2010-03-16 16:37:50 +0000 |
---|---|---|
committer | jimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2010-03-16 16:37:50 +0000 |
commit | a76aaa1442d765410da36d743ef92748ea1b815e (patch) | |
tree | 885e4efe8329d3362869680e0e6156fbb9ff0d65 /src/common/linux | |
parent | Breakpad DWARF parser: Add support for parsing .eh_frame encoded pointers. (diff) | |
download | breakpad-a76aaa1442d765410da36d743ef92748ea1b815e.tar.xz |
Breakpad Linux dumper: Parse the .eh_frame section.
Extend google_breakpad::CFISection with the ability to produce
.eh_frame data. Entry headers have a different format, and pointers
can be encoded in new and fascinating ways.
Extend dwarf2reader::CallFrameInfo to be able to parse either DWARF
CFI or .eh_frame data, as determined by an argument to the
constructor. Cope with variations in header formats, encoded pointers,
and additional data in 'z' augmentation data blocks. Extend the unit
tests appropriately.
Extend dump_syms to look for a .eh_frame section, and if it is
present, find the necessary base addresess and parse its contents.
There's no need for DwarfCFIToModule to check the version numbers; if
CallFrameInfo can parse it, DwarfCFIToModule should be able to handle
it. Adjust tests accordingly.
a=jimblandy, r=nealsid
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@552 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/linux')
-rw-r--r-- | src/common/linux/dump_symbols.cc | 36 | ||||
-rw-r--r-- | src/common/linux/dwarf_cfi_to_module.cc | 10 | ||||
-rw-r--r-- | src/common/linux/dwarf_cfi_to_module_unittest.cc | 14 |
3 files changed, 37 insertions, 23 deletions
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 79d7ad36..3df31372 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -46,6 +46,7 @@ #include <cstring> #include <string> +#include "common/dwarf/bytereader-inl.h" #include "common/dwarf/dwarf2diehandler.h" #include "common/linux/dump_stabs.h" #include "common/linux/dump_symbols.h" @@ -278,6 +279,9 @@ static bool LoadDwarfCFI(const string &dwarf_filename, const ElfW(Ehdr) *elf_header, const char *section_name, const ElfW(Shdr) *section, + bool eh_frame, + const ElfW(Shdr) *got_section, + const ElfW(Shdr) *text_section, Module *module) { // Find the appropriate set of register names for this file's // architecture. @@ -321,11 +325,19 @@ static bool LoadDwarfCFI(const string &dwarf_filename, dwarf_filename.c_str(), elf_header->e_ident[EI_CLASS]); return false; } + // Provide the base addresses for .eh_frame encoded pointers, if + // possible. + byte_reader.SetCFIDataBase(section->sh_addr, cfi); + if (got_section) + byte_reader.SetDataBase(got_section->sh_addr); + if (text_section) + byte_reader.SetTextBase(got_section->sh_addr); dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename, section_name); - dwarf2reader::CallFrameInfo parser(cfi, cfi_size, &byte_reader, - &handler, &dwarf_reporter); + dwarf2reader::CallFrameInfo parser(cfi, cfi_size, + &byte_reader, &handler, &dwarf_reporter, + eh_frame); parser.Start(); return true; } @@ -379,7 +391,25 @@ static bool LoadSymbols(const std::string &obj_file, ElfW(Ehdr) *elf_header, // information, the other debugging information could be perfectly // useful. LoadDwarfCFI(obj_file, elf_header, ".debug_frame", - dwarf_cfi_section, module); + dwarf_cfi_section, false, 0, 0, module); + } + + // Linux C++ exception handling information can also provide + // unwinding data. + const ElfW(Shdr) *eh_frame_section = + FindSectionByName(".eh_frame", sections, section_names, + elf_header->e_shnum); + if (eh_frame_section) { + // Pointers in .eh_frame data may be relative to the base addresses of + // certain sections. Provide those sections if present. + const ElfW(Shdr) *got_section = + FindSectionByName(".got", sections, section_names, elf_header->e_shnum); + const ElfW(Shdr) *text_section = + FindSectionByName(".text", sections, section_names, + elf_header->e_shnum); + // As above, ignore the return value of this function. + LoadDwarfCFI(obj_file, elf_header, ".eh_frame", + eh_frame_section, true, got_section, text_section, module); } if (!found_debug_info_section) { diff --git a/src/common/linux/dwarf_cfi_to_module.cc b/src/common/linux/dwarf_cfi_to_module.cc index d7946a0e..603acc0e 100644 --- a/src/common/linux/dwarf_cfi_to_module.cc +++ b/src/common/linux/dwarf_cfi_to_module.cc @@ -46,12 +46,10 @@ bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length, uint8 version, const string &augmentation, unsigned return_address) { assert(!entry_); - // The latest CFI format version we understand is version 3. - if (version > 3) - return false; - // We only handle non-augmented DWARF unwinding data at the moment. - if (!augmentation.empty()) - return false; + + // If dwarf2reader::CallFrameInfo can handle this version and + // augmentation, then we should be okay with that, so there's no + // need to check them here. // Get ready to collect entries. entry_ = new Module::StackFrameEntry; diff --git a/src/common/linux/dwarf_cfi_to_module_unittest.cc b/src/common/linux/dwarf_cfi_to_module_unittest.cc index de769393..d7b08aef 100644 --- a/src/common/linux/dwarf_cfi_to_module_unittest.cc +++ b/src/common/linux/dwarf_cfi_to_module_unittest.cc @@ -78,20 +78,6 @@ struct DwarfCFIToModuleFixture { class Entry: public DwarfCFIToModuleFixture, public Test { }; -TEST_F(Entry, IgnoreVersion) { - ASSERT_FALSE(handler.Entry(0xf120e638, 0x2851bc1f7a181d6dULL, - 0x40589a48d66e5a88ULL, 4, "", 0x1ad80491)); - module.GetStackFrameEntries(&entries); - EXPECT_EQ(0U, entries.size()); -} - -TEST_F(Entry, IgnoreAugmentation) { - ASSERT_FALSE(handler.Entry(0x3f9d228a, 0xcf9a94bb805cf5a4ULL, - 0xe6c41bf958d4c171ULL, 3, "snazzy", 0x444a14f3)); - module.GetStackFrameEntries(&entries); - EXPECT_EQ(0U, entries.size()); -} - TEST_F(Entry, Accept) { ASSERT_TRUE(handler.Entry(0x3b8961b8, 0xa21069698096fc98ULL, 0xb440ce248169c8d6ULL, 3, "", 0xea93c106)); |