From 983903ee0aef76f7a277ce09de6b12164eba8a32 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek@gmail.com" Date: Wed, 6 Mar 2013 15:32:53 +0000 Subject: 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 --- src/common/linux/dump_symbols.cc | 197 +++++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 93 deletions(-) (limited to 'src/common/linux/dump_symbols.cc') 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* 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(".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(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(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(".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(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(".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(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(".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(".got", SHT_PROGBITS, + if (dwarf_section) { + found_debug_info_section = true; + found_usable_info = true; + info->LoadedSection(".debug_info"); + if (!LoadDwarf(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(".debug_frame", SHT_PROGBITS, sections, names, names_end, elf_header->e_shnum); - const Shdr* text_section = - FindElfSectionByName(".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(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(".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(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(".got", SHT_PROGBITS, + sections, names, names_end, + elf_header->e_shnum); + const Shdr* text_section = + FindElfSectionByName(".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(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(".dynsym", SHT_DYNSYM, sections, names, names_end, elf_header->e_shnum); - const Shdr* dynstr_section = + const Shdr* dynstr_section = FindElfSectionByName(".dynstr", SHT_STRTAB, sections, names, names_end, elf_header->e_shnum); - if (dynsym_section && dynstr_section) { - info->LoadedSection(".dynsym"); - - const uint8_t* dynsyms = - GetOffset(elf_header, dynsym_section->sh_offset); - const uint8_t* dynstrs = - GetOffset(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(elf_header, + dynsym_section->sh_offset); + const uint8_t* dynstrs = + GetOffset(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 bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, const string& obj_filename, const std::vector& 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 info(debug_dirs); scoped_ptr module(new Module(name, os, architecture, id)); if (!LoadSymbols(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(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& 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( reinterpret_cast(obj_file), obj_filename, debug_dirs, - cfi, module); + symbol_data, module); } if (elfclass == ELFCLASS64) { return ReadSymbolDataElfClass( reinterpret_cast(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& 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& 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(elf_header), - obj_file, debug_dirs, cfi, module); + obj_file, debug_dirs, symbol_data, module); } } // namespace google_breakpad -- cgit v1.2.1