aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux/dump_symbols.cc
diff options
context:
space:
mode:
authorted.mielczarek@gmail.com <ted.mielczarek@gmail.com@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-03-06 15:32:53 +0000
committerted.mielczarek@gmail.com <ted.mielczarek@gmail.com@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-03-06 15:32:53 +0000
commit983903ee0aef76f7a277ce09de6b12164eba8a32 (patch)
tree2156b673c7b77dc1cd056ce730d0995fb0f90f41 /src/common/linux/dump_symbols.cc
parentMinor Android fixup for symbol dumping code (diff)
downloadbreakpad-983903ee0aef76f7a277ce09de6b12164eba8a32.tar.xz
Allow reading just CFI data when reading symbols
R=thestig at https://breakpad.appspot.com/517002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1124 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/linux/dump_symbols.cc')
-rw-r--r--src/common/linux/dump_symbols.cc197
1 files changed, 104 insertions, 93 deletions
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index fed27b7a..f2d42660 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -515,6 +515,7 @@ bool LoadSymbols(const string& obj_file,
const typename ElfClass::Ehdr* elf_header,
const bool read_gnu_debug_link,
LoadSymbolsInfo<ElfClass>* info,
+ SymbolData symbol_data,
Module* module) {
typedef typename ElfClass::Addr Addr;
typedef typename ElfClass::Phdr Phdr;
@@ -535,81 +536,85 @@ bool LoadSymbols(const string& obj_file,
bool found_debug_info_section = false;
bool found_usable_info = false;
- // Look for STABS debugging information, and load it if present.
- const Shdr* stab_section =
+ if (symbol_data != ONLY_CFI) {
+ // Look for STABS debugging information, and load it if present.
+ const Shdr* stab_section =
FindElfSectionByName<ElfClass>(".stab", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
- if (stab_section) {
- const Shdr* stabstr_section = stab_section->sh_link + sections;
- if (stabstr_section) {
- found_debug_info_section = true;
- found_usable_info = true;
- info->LoadedSection(".stab");
- if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section,
- big_endian, module)) {
- fprintf(stderr, "%s: \".stab\" section found, but failed to load STABS"
- " debugging information\n", obj_file.c_str());
+ if (stab_section) {
+ const Shdr* stabstr_section = stab_section->sh_link + sections;
+ if (stabstr_section) {
+ found_debug_info_section = true;
+ found_usable_info = true;
+ info->LoadedSection(".stab");
+ if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section,
+ big_endian, module)) {
+ fprintf(stderr, "%s: \".stab\" section found, but failed to load"
+ " STABS debugging information\n", obj_file.c_str());
+ }
}
}
- }
- // Look for DWARF debugging information, and load it if present.
- const Shdr* dwarf_section =
+ // Look for DWARF debugging information, and load it if present.
+ const Shdr* dwarf_section =
FindElfSectionByName<ElfClass>(".debug_info", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
- if (dwarf_section) {
- found_debug_info_section = true;
- found_usable_info = true;
- info->LoadedSection(".debug_info");
- if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian, module))
- fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
- "DWARF debugging information\n", obj_file.c_str());
- }
-
- // Dwarf Call Frame Information (CFI) is actually independent from
- // the other DWARF debugging information, and can be used alone.
- const Shdr* dwarf_cfi_section =
- FindElfSectionByName<ElfClass>(".debug_frame", SHT_PROGBITS,
- sections, names, names_end,
- elf_header->e_shnum);
- if (dwarf_cfi_section) {
- // Ignore the return value of this function; even without call frame
- // information, the other debugging information could be perfectly
- // useful.
- info->LoadedSection(".debug_frame");
- bool result =
- LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".debug_frame",
- dwarf_cfi_section, false, 0, 0, big_endian,
- module);
- found_usable_info = found_usable_info || result;
- }
-
- // Linux C++ exception handling information can also provide
- // unwinding data.
- const Shdr* eh_frame_section =
- FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS,
- sections, names, names_end,
- 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 Shdr* got_section =
- FindElfSectionByName<ElfClass>(".got", SHT_PROGBITS,
+ if (dwarf_section) {
+ found_debug_info_section = true;
+ found_usable_info = true;
+ info->LoadedSection(".debug_info");
+ if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian, module))
+ fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
+ "DWARF debugging information\n", obj_file.c_str());
+ }
+ }
+
+ if (symbol_data != NO_CFI) {
+ // Dwarf Call Frame Information (CFI) is actually independent from
+ // the other DWARF debugging information, and can be used alone.
+ const Shdr* dwarf_cfi_section =
+ FindElfSectionByName<ElfClass>(".debug_frame", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
- const Shdr* text_section =
- FindElfSectionByName<ElfClass>(".text", SHT_PROGBITS,
+ if (dwarf_cfi_section) {
+ // Ignore the return value of this function; even without call frame
+ // information, the other debugging information could be perfectly
+ // useful.
+ info->LoadedSection(".debug_frame");
+ bool result =
+ LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".debug_frame",
+ dwarf_cfi_section, false, 0, 0, big_endian,
+ module);
+ found_usable_info = found_usable_info || result;
+ }
+
+ // Linux C++ exception handling information can also provide
+ // unwinding data.
+ const Shdr* eh_frame_section =
+ FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
- info->LoadedSection(".eh_frame");
- // As above, ignore the return value of this function.
- bool result =
- LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame",
- eh_frame_section, true,
- got_section, text_section, big_endian, module);
- found_usable_info = found_usable_info || result;
+ 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 Shdr* got_section =
+ FindElfSectionByName<ElfClass>(".got", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ const Shdr* text_section =
+ FindElfSectionByName<ElfClass>(".text", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ info->LoadedSection(".eh_frame");
+ // As above, ignore the return value of this function.
+ bool result =
+ LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame",
+ eh_frame_section, true,
+ got_section, text_section, big_endian, module);
+ found_usable_info = found_usable_info || result;
+ }
}
if (!found_debug_info_section) {
@@ -642,32 +647,36 @@ bool LoadSymbols(const string& obj_file,
obj_file.c_str());
}
} else {
- // The caller doesn't want to consult .gnu_debuglink.
- // See if there are export symbols available.
- const Shdr* dynsym_section =
+ if (symbol_data != ONLY_CFI) {
+ // The caller doesn't want to consult .gnu_debuglink.
+ // See if there are export symbols available.
+ const Shdr* dynsym_section =
FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
sections, names, names_end,
elf_header->e_shnum);
- const Shdr* dynstr_section =
+ const Shdr* dynstr_section =
FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
sections, names, names_end,
elf_header->e_shnum);
- if (dynsym_section && dynstr_section) {
- info->LoadedSection(".dynsym");
-
- const uint8_t* dynsyms =
- GetOffset<ElfClass, uint8_t>(elf_header, dynsym_section->sh_offset);
- const uint8_t* dynstrs =
- GetOffset<ElfClass, uint8_t>(elf_header, dynstr_section->sh_offset);
- bool result =
- ELFSymbolsToModule(dynsyms,
- dynsym_section->sh_size,
- dynstrs,
- dynstr_section->sh_size,
- big_endian,
- ElfClass::kAddrSize,
- module);
- found_usable_info = found_usable_info || result;
+ if (dynsym_section && dynstr_section) {
+ info->LoadedSection(".dynsym");
+
+ const uint8_t* dynsyms =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ dynsym_section->sh_offset);
+ const uint8_t* dynstrs =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ dynstr_section->sh_offset);
+ bool result =
+ ELFSymbolsToModule(dynsyms,
+ dynsym_section->sh_size,
+ dynstrs,
+ dynstr_section->sh_size,
+ big_endian,
+ ElfClass::kAddrSize,
+ module);
+ found_usable_info = found_usable_info || result;
+ }
}
// Return true if some usable information was found, since
@@ -736,7 +745,7 @@ template<typename ElfClass>
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
const std::vector<string>& debug_dirs,
- bool cfi,
+ SymbolData symbol_data,
Module** out_module) {
typedef typename ElfClass::Ehdr Ehdr;
typedef typename ElfClass::Shdr Shdr;
@@ -770,7 +779,8 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
LoadSymbolsInfo<ElfClass> info(debug_dirs);
scoped_ptr<Module> module(new Module(name, os, architecture, id));
if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
- !debug_dirs.empty(), &info, module.get())) {
+ !debug_dirs.empty(), &info,
+ symbol_data, module.get())) {
const string debuglink_file = info.debuglink_file();
if (debuglink_file.empty())
return false;
@@ -808,7 +818,8 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
}
if (!LoadSymbols<ElfClass>(debuglink_file, debug_big_endian,
- debug_elf_header, false, &info, module.get())) {
+ debug_elf_header, false, &info,
+ symbol_data, module.get())) {
return false;
}
}
@@ -825,7 +836,7 @@ namespace google_breakpad {
bool ReadSymbolDataInternal(const uint8_t* obj_file,
const string& obj_filename,
const std::vector<string>& debug_dirs,
- bool cfi,
+ SymbolData symbol_data,
Module** module) {
if (!IsValidElf(obj_file)) {
@@ -837,12 +848,12 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file,
if (elfclass == ELFCLASS32) {
return ReadSymbolDataElfClass<ElfClass32>(
reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dirs,
- cfi, module);
+ symbol_data, module);
}
if (elfclass == ELFCLASS64) {
return ReadSymbolDataElfClass<ElfClass64>(
reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dirs,
- cfi, module);
+ symbol_data, module);
}
return false;
@@ -850,20 +861,20 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file,
bool WriteSymbolFile(const string &obj_file,
const std::vector<string>& debug_dirs,
- bool cfi,
+ SymbolData symbol_data,
std::ostream &sym_stream) {
Module* module;
- if (!ReadSymbolData(obj_file, debug_dirs, cfi, &module))
+ if (!ReadSymbolData(obj_file, debug_dirs, symbol_data, &module))
return false;
- bool result = module->Write(sym_stream, cfi);
+ bool result = module->Write(sym_stream, symbol_data);
delete module;
return result;
}
bool ReadSymbolData(const string& obj_file,
const std::vector<string>& debug_dirs,
- bool cfi,
+ SymbolData symbol_data,
Module** module) {
MmapWrapper map_wrapper;
void* elf_header = NULL;
@@ -871,7 +882,7 @@ bool ReadSymbolData(const string& obj_file,
return false;
return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
- obj_file, debug_dirs, cfi, module);
+ obj_file, debug_dirs, symbol_data, module);
}
} // namespace google_breakpad