mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-01-01 12:14:56 +01:00
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
This commit is contained in:
parent
0de9f43b87
commit
a76aaa1442
11 changed files with 1335 additions and 142 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue