From 3ca4a120de8ec3f35e972e4b23f527bb8f65c479 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek" Date: Wed, 6 Jul 2011 17:05:59 +0000 Subject: Add some unit tests for Linux WriteSymbolFile This patch adds synth_elf::{StringTable,SymbolTable,ELF} classes to produce in-memory ELF files to properly test the Linux symbol dumping code. It also uses those classes to add some basic tests for the WriteSymbolFile function. R=jimb at http://breakpad.appspot.com/277001/show git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@794 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/common/linux/dump_symbols.cc | 48 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 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 77455a57..fc312983 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -721,25 +722,32 @@ std::string BaseFileName(const std::string &filename) { namespace google_breakpad { -bool WriteSymbolFile(const std::string &obj_file, - const std::string &debug_dir, FILE *sym_file) { - MmapWrapper map_wrapper; - ElfW(Ehdr) *elf_header = NULL; - if (!LoadELF(obj_file, &map_wrapper, &elf_header)) +// Not explicitly exported, but not static so it can be used in unit tests. +// Ideally obj_file would be const, but internally this code does write +// to some ELF header fields to make its work simpler. +bool WriteSymbolFileInternal(uint8_t* obj_file, + const std::string &obj_filename, + const std::string &debug_dir, + std::ostream &sym_stream) { + ElfW(Ehdr) *elf_header = reinterpret_cast(obj_file); + + if (!IsValidElf(elf_header)) { + fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str()); return false; + } unsigned char identifier[16]; - google_breakpad::FileID file_id(obj_file.c_str()); - if (!file_id.ElfFileIdentifierFromMappedFile(elf_header, identifier)) { + if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header, + identifier)) { fprintf(stderr, "%s: unable to generate file identifier\n", - obj_file.c_str()); + obj_filename.c_str()); return false; } const char *architecture = ElfArchitecture(elf_header); if (!architecture) { fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", - obj_file.c_str(), elf_header->e_machine); + obj_filename.c_str(), elf_header->e_machine); return false; } @@ -748,13 +756,13 @@ bool WriteSymbolFile(const std::string &obj_file, if (!ElfEndianness(elf_header, &big_endian)) return false; - std::string name = BaseFileName(obj_file); + std::string name = BaseFileName(obj_filename); std::string os = "Linux"; std::string id = FormatIdentifier(identifier); LoadSymbolsInfo info(debug_dir); Module module(name, os, architecture, id); - if (!LoadSymbols(obj_file, big_endian, elf_header, !debug_dir.empty(), + if (!LoadSymbols(obj_filename, big_endian, elf_header, !debug_dir.empty(), &info, &module)) { const std::string debuglink_file = info.debuglink_file(); if (debuglink_file.empty()) @@ -777,7 +785,7 @@ bool WriteSymbolFile(const std::string &obj_file, fprintf(stderr, "%s with ELF machine architecture %s does not match " "%s with ELF architecture %s\n", debuglink_file.c_str(), debug_architecture, - obj_file.c_str(), architecture); + obj_filename.c_str(), architecture); return false; } @@ -786,7 +794,7 @@ bool WriteSymbolFile(const std::string &obj_file, return false; if (debug_big_endian != big_endian) { fprintf(stderr, "%s and %s does not match in endianness\n", - obj_file.c_str(), debuglink_file.c_str()); + obj_filename.c_str(), debuglink_file.c_str()); return false; } @@ -795,10 +803,22 @@ bool WriteSymbolFile(const std::string &obj_file, return false; } } - if (!module.Write(sym_file)) + if (!module.Write(sym_stream)) return false; return true; } +bool WriteSymbolFile(const std::string &obj_file, + const std::string &debug_dir, + std::ostream &sym_stream) { + MmapWrapper map_wrapper; + ElfW(Ehdr) *elf_header = NULL; + if (!LoadELF(obj_file, &map_wrapper, &elf_header)) + return false; + + return WriteSymbolFileInternal(reinterpret_cast(elf_header), + obj_file, debug_dir, sym_stream); +} + } // namespace google_breakpad -- cgit v1.2.1