From 7e72c6677ab358b34752d08041172d817f81bbec Mon Sep 17 00:00:00 2001 From: "ted.mielczarek@gmail.com" Date: Fri, 18 Jan 2013 20:24:16 +0000 Subject: [PATCH] Provide a ReadSymbolData function to get symbol data in a Module instead of just serializing it R=thestig at https://breakpad.appspot.com/510002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1099 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/common/linux/dump_symbols.cc | 52 +++++++++++++++-------- src/common/linux/dump_symbols.h | 10 +++++ src/common/linux/dump_symbols_unittest.cc | 48 ++++++++++++--------- 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index f3c6d9b1..bcb39ca7 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -62,6 +62,7 @@ #include "common/linux/elf_symbols_to_module.h" #include "common/linux/file_id.h" #include "common/module.h" +#include "common/scoped_ptr.h" #include "common/stabs_reader.h" #include "common/stabs_to_module.h" #include "common/using_std_string.h" @@ -80,6 +81,7 @@ using google_breakpad::GetOffset; using google_breakpad::IsValidElf; using google_breakpad::Module; using google_breakpad::StabsToModule; +using google_breakpad::scoped_ptr; // // FDWrapper @@ -708,14 +710,16 @@ string BaseFileName(const string &filename) { } template -bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header, +bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, const string& obj_filename, const string& debug_dir, bool cfi, - std::ostream& sym_stream) { + Module** out_module) { typedef typename ElfClass::Ehdr Ehdr; typedef typename ElfClass::Shdr Shdr; + *out_module = NULL; + unsigned char identifier[16]; if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) { @@ -741,9 +745,9 @@ bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header, string id = FormatIdentifier(identifier); LoadSymbolsInfo info(debug_dir); - Module module(name, os, architecture, id); + scoped_ptr module(new Module(name, os, architecture, id)); if (!LoadSymbols(obj_filename, big_endian, elf_header, - !debug_dir.empty(), &info, &module)) { + !debug_dir.empty(), &info, module.get())) { const string debuglink_file = info.debuglink_file(); if (debuglink_file.empty()) return false; @@ -781,13 +785,12 @@ bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header, } if (!LoadSymbols(debuglink_file, debug_big_endian, - debug_elf_header, false, &info, &module)) { + debug_elf_header, false, &info, module.get())) { return false; } } - if (!module.Write(sym_stream, cfi)) - return false; + *out_module = module.release(); return true; } @@ -796,11 +799,11 @@ bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header, namespace google_breakpad { // Not explicitly exported, but not static so it can be used in unit tests. -bool WriteSymbolFileInternal(const uint8_t* obj_file, - const string& obj_filename, - const string& debug_dir, - bool cfi, - std::ostream& sym_stream) { +bool ReadSymbolDataInternal(const uint8_t* obj_file, + const string& obj_filename, + const string& debug_dir, + bool cfi, + Module** module) { if (!IsValidElf(obj_file)) { fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str()); @@ -809,14 +812,14 @@ bool WriteSymbolFileInternal(const uint8_t* obj_file, int elfclass = ElfClass(obj_file); if (elfclass == ELFCLASS32) { - return WriteSymbolFileElfClass( + return ReadSymbolDataElfClass( reinterpret_cast(obj_file), obj_filename, debug_dir, - cfi, sym_stream); + cfi, module); } if (elfclass == ELFCLASS64) { - return WriteSymbolFileElfClass( + return ReadSymbolDataElfClass( reinterpret_cast(obj_file), obj_filename, debug_dir, - cfi, sym_stream); + cfi, module); } return false; @@ -826,13 +829,26 @@ bool WriteSymbolFile(const string &obj_file, const string &debug_dir, bool cfi, std::ostream &sym_stream) { + Module* module; + if (!ReadSymbolData(obj_file, debug_dir, cfi, &module)) + return false; + + bool result = module->Write(sym_stream, cfi); + delete module; + return result; +} + +bool ReadSymbolData(const string& obj_file, + const string& debug_dir, + bool cfi, + Module** module) { MmapWrapper map_wrapper; void* elf_header = NULL; if (!LoadELF(obj_file, &map_wrapper, &elf_header)) return false; - return WriteSymbolFileInternal(reinterpret_cast(elf_header), - obj_file, debug_dir, cfi, sym_stream); + return ReadSymbolDataInternal(reinterpret_cast(elf_header), + obj_file, debug_dir, cfi, module); } } // namespace google_breakpad diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h index 7b192817..9084733e 100644 --- a/src/common/linux/dump_symbols.h +++ b/src/common/linux/dump_symbols.h @@ -42,6 +42,8 @@ namespace google_breakpad { +class Module; + // Find all the debugging information in OBJ_FILE, an ELF executable // or shared library, and write it to SYM_STREAM in the Breakpad symbol // file format. @@ -53,6 +55,14 @@ bool WriteSymbolFile(const string &obj_file, bool cfi, std::ostream &sym_stream); +// As above, but simply return the debugging information in MODULE +// instead of writing it to a stream. The caller owns the resulting +// Module object and must delete it when finished. +bool ReadSymbolData(const string& obj_file, + const string& debug_dir, + bool cfi, + Module** module); + } // namespace google_breakpad #endif // COMMON_LINUX_DUMP_SYMBOLS_H__ diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc index 2281fc7c..3d9b4a9e 100644 --- a/src/common/linux/dump_symbols_unittest.cc +++ b/src/common/linux/dump_symbols_unittest.cc @@ -37,19 +37,19 @@ #include #include -#include #include #include "breakpad_googletest_includes.h" #include "common/linux/synth_elf.h" +#include "common/module.h" #include "common/using_std_string.h" namespace google_breakpad { -bool WriteSymbolFileInternal(const uint8_t* obj_file, - const string &obj_filename, - const string &debug_dir, - bool cfi, - std::ostream &sym_stream); +bool ReadSymbolDataInternal(const uint8_t* obj_file, + const string &obj_filename, + const string &debug_dir, + bool cfi, + Module** module); } using google_breakpad::synth_elf::ELF; @@ -57,7 +57,8 @@ using google_breakpad::synth_elf::StringTable; using google_breakpad::synth_elf::SymbolTable; using google_breakpad::test_assembler::kLittleEndian; using google_breakpad::test_assembler::Section; -using google_breakpad::WriteSymbolFileInternal; +using google_breakpad::Module; +using google_breakpad::ReadSymbolDataInternal; using std::stringstream; using std::vector; using ::testing::Test; @@ -81,12 +82,12 @@ class DumpSymbols : public Test { TEST_F(DumpSymbols, Invalid) { Elf32_Ehdr header; memset(&header, 0, sizeof(header)); - stringstream s; - EXPECT_FALSE(WriteSymbolFileInternal(reinterpret_cast(&header), + Module* module; + EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast(&header), "foo", "", true, - s)); + &module)); } TEST_F(DumpSymbols, SimplePublic32) { @@ -113,15 +114,19 @@ TEST_F(DumpSymbols, SimplePublic32) { elf.Finish(); GetElfContents(elf); + Module* module; + EXPECT_TRUE(ReadSymbolDataInternal(elfdata, + "foo", + "", + true, + &module)); + stringstream s; - ASSERT_TRUE(WriteSymbolFileInternal(elfdata, - "foo", - "", - true, - s)); + module->Write(s, true); EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n" "PUBLIC 1000 0 superfunc\n", s.str()); + delete module; } TEST_F(DumpSymbols, SimplePublic64) { @@ -148,12 +153,15 @@ TEST_F(DumpSymbols, SimplePublic64) { elf.Finish(); GetElfContents(elf); + Module* module; + EXPECT_TRUE(ReadSymbolDataInternal(elfdata, + "foo", + "", + true, + &module)); + stringstream s; - ASSERT_TRUE(WriteSymbolFileInternal(elfdata, - "foo", - "", - true, - s)); + module->Write(s, true); EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n" "PUBLIC 1000 0 superfunc\n", s.str());