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 ++++++++++++++++-------------- src/common/linux/dump_symbols.h | 7 +- src/common/linux/dump_symbols_unittest.cc | 12 +- src/common/mac/dump_syms.h | 15 ++- src/common/mac/dump_syms.mm | 36 ++++-- src/common/module.cc | 84 ++++++------- src/common/module.h | 7 +- src/common/module_unittest.cc | 22 ++-- src/common/symbol_data.h | 42 +++++++ src/tools/linux/dump_syms/dump_syms.cc | 3 +- src/tools/mac/dump_syms/dump_syms_tool.mm | 4 +- 11 files changed, 251 insertions(+), 178 deletions(-) create mode 100644 src/common/symbol_data.h 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 diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h index 8765ffdb..f3c92cd5 100644 --- a/src/common/linux/dump_symbols.h +++ b/src/common/linux/dump_symbols.h @@ -39,6 +39,7 @@ #include #include +#include "common/symbol_data.h" #include "common/using_std_string.h" namespace google_breakpad { @@ -50,10 +51,10 @@ class Module; // file format. // If OBJ_FILE has been stripped but contains a .gnu_debuglink section, // then look for the debug file in DEBUG_DIRS. -// If CFI is set to false, then omit the CFI section. +// SYMBOL_DATA allows limiting the type of symbol data written. bool WriteSymbolFile(const string &obj_file, const std::vector& debug_dirs, - bool cfi, + SymbolData symbol_data, std::ostream &sym_stream); // As above, but simply return the debugging information in MODULE @@ -61,7 +62,7 @@ bool WriteSymbolFile(const string &obj_file, // Module object and must delete it when finished. bool ReadSymbolData(const string& obj_file, const std::vector& debug_dirs, - bool cfi, + SymbolData symbol_data, Module** module); } // namespace google_breakpad diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc index d48512f7..6f5aef2e 100644 --- a/src/common/linux/dump_symbols_unittest.cc +++ b/src/common/linux/dump_symbols_unittest.cc @@ -48,7 +48,7 @@ namespace google_breakpad { bool ReadSymbolDataInternal(const uint8_t* obj_file, const string& obj_filename, const std::vector& debug_dir, - bool cfi, + SymbolData symbol_data, Module** module); } @@ -86,7 +86,7 @@ TEST_F(DumpSymbols, Invalid) { EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast(&header), "foo", vector(), - true, + ALL_SYMBOL_DATA, &module)); } @@ -118,11 +118,11 @@ TEST_F(DumpSymbols, SimplePublic32) { EXPECT_TRUE(ReadSymbolDataInternal(elfdata, "foo", vector(), - true, + ALL_SYMBOL_DATA, &module)); stringstream s; - module->Write(s, true); + module->Write(s, ALL_SYMBOL_DATA); EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n" "PUBLIC 1000 0 superfunc\n", s.str()); @@ -157,11 +157,11 @@ TEST_F(DumpSymbols, SimplePublic64) { EXPECT_TRUE(ReadSymbolDataInternal(elfdata, "foo", vector(), - true, + ALL_SYMBOL_DATA, &module)); stringstream s; - module->Write(s, true); + module->Write(s, ALL_SYMBOL_DATA); EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n" "PUBLIC 1000 0 superfunc\n", s.str()); diff --git a/src/common/mac/dump_syms.h b/src/common/mac/dump_syms.h index 0e2f464d..af12b778 100644 --- a/src/common/mac/dump_syms.h +++ b/src/common/mac/dump_syms.h @@ -47,13 +47,15 @@ #include "common/byte_cursor.h" #include "common/mac/macho_reader.h" #include "common/module.h" +#include "common/symbol_data.h" namespace google_breakpad { class DumpSymbols { public: - DumpSymbols() - : input_pathname_(), + explicit DumpSymbols(SymbolData symbol_data) + : symbol_data_(symbol_data), + input_pathname_(), object_filename_(), contents_(), selected_object_file_(), @@ -110,9 +112,9 @@ class DumpSymbols { } // Read the selected object file's debugging information, and write it out to - // |stream|. Write the CFI section if |cfi| is true. Return true on success; - // if an error occurs, report it and return false. - bool WriteSymbolFile(std::ostream &stream, bool cfi); + // |stream|. Return true on success; if an error occurs, report it and + // return false. + bool WriteSymbolFile(std::ostream &stream); private: // Used internally. @@ -139,6 +141,9 @@ class DumpSymbols { const mach_o::Section §ion, bool eh_frame) const; + // The selection of what type of symbol data to read/write. + const SymbolData symbol_data_; + // The name of the file or bundle whose symbols this will dump. // This is the path given to Read, for use in error messages. NSString *input_pathname_; diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.mm index e26b05ea..f1aab426 100644 --- a/src/common/mac/dump_syms.mm +++ b/src/common/mac/dump_syms.mm @@ -55,6 +55,7 @@ #include "common/module.h" #include "common/stabs_reader.h" #include "common/stabs_to_module.h" +#include "common/symbol_data.h" #ifndef CPU_TYPE_ARM #define CPU_TYPE_ARM (static_cast(12)) @@ -370,8 +371,12 @@ class DumpSymbols::LoadCommandDumper: // file, and adding data to MODULE. LoadCommandDumper(const DumpSymbols &dumper, google_breakpad::Module *module, - const mach_o::Reader &reader) - : dumper_(dumper), module_(module), reader_(reader) { } + const mach_o::Reader &reader, + SymbolData symbol_data) + : dumper_(dumper), + module_(module), + reader_(reader), + symbol_data_(symbol_data) { } bool SegmentCommand(const mach_o::Segment &segment); bool SymtabCommand(const ByteBuffer &entries, const ByteBuffer &strings); @@ -380,6 +385,7 @@ class DumpSymbols::LoadCommandDumper: const DumpSymbols &dumper_; google_breakpad::Module *module_; // WEAK const mach_o::Reader &reader_; + const SymbolData symbol_data_; }; bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment &segment) { @@ -387,7 +393,7 @@ bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment &segment) { if (!reader_.MapSegmentSections(segment, §ion_map)) return false; - if (segment.name == "__TEXT") { + if (segment.name == "__TEXT" && symbol_data_ != NO_CFI) { module_->SetLoadAddress(segment.vmaddr); mach_o::SectionMap::const_iterator eh_frame = section_map.find("__eh_frame"); @@ -399,13 +405,17 @@ bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment &segment) { } if (segment.name == "__DWARF") { - if (!dumper_.ReadDwarf(module_, reader_, section_map)) - return false; - mach_o::SectionMap::const_iterator debug_frame - = section_map.find("__debug_frame"); - if (debug_frame != section_map.end()) { - // If there is a problem reading this, don't treat it as a fatal error. - dumper_.ReadCFI(module_, reader_, debug_frame->second, false); + if (symbol_data_ != ONLY_CFI) { + if (!dumper_.ReadDwarf(module_, reader_, section_map)) + return false; + } + if (symbol_data_ != NO_CFI) { + mach_o::SectionMap::const_iterator debug_frame + = section_map.find("__debug_frame"); + if (debug_frame != section_map.end()) { + // If there is a problem reading this, don't treat it as a fatal error. + dumper_.ReadCFI(module_, reader_, debug_frame->second, false); + } } } @@ -429,7 +439,7 @@ bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer &entries, return true; } -bool DumpSymbols::WriteSymbolFile(std::ostream &stream, bool cfi) { +bool DumpSymbols::WriteSymbolFile(std::ostream &stream) { // Select an object file, if SetArchitecture hasn't been called to set one // explicitly. if (!selected_object_file_) { @@ -494,11 +504,11 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream, bool cfi) { return false; // Walk its load commands, and deal with whatever is there. - LoadCommandDumper load_command_dumper(*this, &module, reader); + LoadCommandDumper load_command_dumper(*this, &module, reader, symbol_data_); if (!reader.WalkLoadCommands(&load_command_dumper)) return false; - return module.Write(stream, cfi); + return module.Write(stream, symbol_data_); } } // namespace google_breakpad diff --git a/src/common/module.cc b/src/common/module.cc index 4e257d1d..2d2e4efc 100644 --- a/src/common/module.cc +++ b/src/common/module.cc @@ -204,62 +204,62 @@ bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) { return stream.good(); } -bool Module::Write(std::ostream &stream, bool cfi) { +bool Module::Write(std::ostream &stream, SymbolData symbol_data) { stream << "MODULE " << os_ << " " << architecture_ << " " << id_ << " " << name_ << endl; if (!stream.good()) return ReportError(); - AssignSourceIds(); + if (symbol_data != ONLY_CFI) { + AssignSourceIds(); - // Write out files. - for (FileByNameMap::iterator file_it = files_.begin(); - file_it != files_.end(); ++file_it) { - File *file = file_it->second; - if (file->source_id >= 0) { - stream << "FILE " << file->source_id << " " << file->name << endl; - if (!stream.good()) - return ReportError(); + // Write out files. + for (FileByNameMap::iterator file_it = files_.begin(); + file_it != files_.end(); ++file_it) { + File *file = file_it->second; + if (file->source_id >= 0) { + stream << "FILE " << file->source_id << " " << file->name << endl; + if (!stream.good()) + return ReportError(); + } } - } - // Write out functions and their lines. - for (FunctionSet::const_iterator func_it = functions_.begin(); - func_it != functions_.end(); ++func_it) { - Function *func = *func_it; - stream << "FUNC " << hex - << (func->address - load_address_) << " " - << func->size << " " - << func->parameter_size << " " - << func->name << dec << endl; - - if (!stream.good()) - return ReportError(); - for (vector::iterator line_it = func->lines.begin(); - line_it != func->lines.end(); ++line_it) { - stream << hex - << (line_it->address - load_address_) << " " - << line_it->size << " " - << dec - << line_it->number << " " - << line_it->file->source_id << endl; + // Write out functions and their lines. + for (FunctionSet::const_iterator func_it = functions_.begin(); + func_it != functions_.end(); ++func_it) { + Function *func = *func_it; + stream << "FUNC " << hex + << (func->address - load_address_) << " " + << func->size << " " + << func->parameter_size << " " + << func->name << dec << endl; if (!stream.good()) return ReportError(); + + for (vector::iterator line_it = func->lines.begin(); + line_it != func->lines.end(); ++line_it) { + stream << hex + << (line_it->address - load_address_) << " " + << line_it->size << " " + << dec + << line_it->number << " " + << line_it->file->source_id << endl; + if (!stream.good()) + return ReportError(); + } } - } - // Write out 'PUBLIC' records. - for (ExternSet::const_iterator extern_it = externs_.begin(); - extern_it != externs_.end(); ++extern_it) { - Extern *ext = *extern_it; - stream << "PUBLIC " << hex - << (ext->address - load_address_) << " 0 " - << ext->name << dec << endl; - if (!stream.good()) - return ReportError(); + // Write out 'PUBLIC' records. + for (ExternSet::const_iterator extern_it = externs_.begin(); + extern_it != externs_.end(); ++extern_it) { + Extern *ext = *extern_it; + stream << "PUBLIC " << hex + << (ext->address - load_address_) << " 0 " + << ext->name << dec << endl; + } } - if (cfi) { + if (symbol_data != NO_CFI) { // Write out 'STACK CFI INIT' and 'STACK CFI' records. vector::const_iterator frame_it; for (frame_it = stack_frame_entries_.begin(); diff --git a/src/common/module.h b/src/common/module.h index cecab32f..398bc315 100644 --- a/src/common/module.h +++ b/src/common/module.h @@ -44,6 +44,7 @@ #include #include +#include "common/symbol_data.h" #include "common/using_std_string.h" #include "google_breakpad/common/breakpad_types.h" @@ -259,13 +260,15 @@ class Module { // breakpad symbol format. Return true if all goes well, or false if // an error occurs. This method writes out: // - a header based on the values given to the constructor, + // If symbol_data is not ONLY_CFI then: // - the source files added via FindFile, // - the functions added via AddFunctions, each with its lines, // - all public records, - // - and if CFI is true, all CFI records. + // If symbol_data is not NO_CFI then: + // - all CFI records. // Addresses in the output are all relative to the load address // established by SetLoadAddress. - bool Write(std::ostream &stream, bool cfi); + bool Write(std::ostream &stream, SymbolData symbol_data); private: // Report an error that has occurred writing the symbol file, using diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc index 04dc4041..5c0c6975 100644 --- a/src/common/module_unittest.cc +++ b/src/common/module_unittest.cc @@ -70,7 +70,7 @@ static Module::Function *generate_duplicate_function(const string &name) { TEST(Write, Header) { stringstream s; Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n", contents.c_str()); @@ -91,7 +91,7 @@ TEST(Write, OneLineFunc) { function->lines.push_back(line); m.AddFunction(function); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FILE 0 file_name.cc\n" @@ -141,7 +141,7 @@ TEST(Write, RelativeLoadAddress) { // the module must work fine. m.SetLoadAddress(0x2ab698b0b6407073LL); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FILE 0 filename-a.cc\n" @@ -197,7 +197,7 @@ TEST(Write, OmitUnusedFiles) { EXPECT_NE(-1, vec[2]->source_id); stringstream s; - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FILE 0 filename1\n" @@ -245,7 +245,7 @@ TEST(Write, NoCFI) { // the module must work fine. m.SetLoadAddress(0x2ab698b0b6407073LL); - m.Write(s, false); + m.Write(s, NO_CFI); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FILE 0 filename.cc\n" @@ -279,7 +279,7 @@ TEST(Construct, AddFunctions) { m.AddFunctions(vec.begin(), vec.end()); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988" @@ -331,7 +331,7 @@ TEST(Construct, AddFrames) { m.AddStackFrameEntry(entry3); // Check that Write writes STACK CFI records properly. - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n" @@ -407,7 +407,7 @@ TEST(Construct, DuplicateFunctions) { m.AddFunction(function1); m.AddFunction(function2); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" @@ -426,7 +426,7 @@ TEST(Construct, FunctionsWithSameAddress) { m.AddFunction(function1); m.AddFunction(function2); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" @@ -453,7 +453,7 @@ TEST(Construct, Externs) { m.AddExtern(extern1); m.AddExtern(extern2); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " @@ -480,7 +480,7 @@ TEST(Construct, DuplicateExterns) { m.AddExtern(extern1); m.AddExtern(extern2); - m.Write(s, true); + m.Write(s, ALL_SYMBOL_DATA); string contents = s.str(); EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " diff --git a/src/common/symbol_data.h b/src/common/symbol_data.h new file mode 100644 index 00000000..2cf15a85 --- /dev/null +++ b/src/common/symbol_data.h @@ -0,0 +1,42 @@ +// -*- mode: c++ -*- + +// Copyright (c) 2013 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef COMMON_SYMBOL_DATA_H_ +#define COMMON_SYMBOL_DATA_H_ + +// Control what data is used from the symbol file. +enum SymbolData { + ALL_SYMBOL_DATA, + NO_CFI, + ONLY_CFI +}; + +#endif // COMMON_SYMBOL_DATA_H_ diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc index aa504589..f58952ed 100644 --- a/src/tools/linux/dump_syms/dump_syms.cc +++ b/src/tools/linux/dump_syms/dump_syms.cc @@ -68,7 +68,8 @@ int main(int argc, char **argv) { debug_dirs.push_back(argv[debug_dir_index]); } - if (!WriteSymbolFile(binary, debug_dirs, cfi, std::cout)) { + SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI; + if (!WriteSymbolFile(binary, debug_dirs, symbol_data, std::cout)) { fprintf(stderr, "Failed to write symbol file.\n"); return 1; } diff --git a/src/tools/mac/dump_syms/dump_syms_tool.mm b/src/tools/mac/dump_syms/dump_syms_tool.mm index 14bbcbbd..68321db3 100644 --- a/src/tools/mac/dump_syms/dump_syms_tool.mm +++ b/src/tools/mac/dump_syms/dump_syms_tool.mm @@ -54,7 +54,7 @@ struct Options { //============================================================================= static bool Start(const Options &options) { - DumpSymbols dump_symbols; + DumpSymbols dump_symbols(options.cfi ? ALL_SYMBOL_DATA : NO_CFI); if (!dump_symbols.Read(options.srcPath)) return false; @@ -86,7 +86,7 @@ static bool Start(const Options &options) { } } - return dump_symbols.WriteSymbolFile(std::cout, options.cfi); + return dump_symbols.WriteSymbolFile(std::cout); } //============================================================================= -- cgit v1.2.1