Home | History | Annotate | Download | only in linux
      1 // Copyright (c) 2011 Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // Restructured in 2009 by: Jim Blandy <jimb (at) mozilla.com> <jimb (at) red-bean.com>
     31 
     32 // dump_symbols.cc: implement google_breakpad::WriteSymbolFile:
     33 // Find all the debugging info in a file and dump it as a Breakpad symbol file.
     34 
     35 #include "common/linux/dump_symbols.h"
     36 
     37 #include <assert.h>
     38 #include <elf.h>
     39 #include <errno.h>
     40 #include <fcntl.h>
     41 #include <link.h>
     42 #include <stdio.h>
     43 #include <stdlib.h>
     44 #include <string.h>
     45 #include <sys/mman.h>
     46 #include <sys/stat.h>
     47 #include <unistd.h>
     48 
     49 #include <iostream>
     50 #include <set>
     51 #include <string>
     52 #include <utility>
     53 #include <vector>
     54 
     55 #include "common/dwarf/bytereader-inl.h"
     56 #include "common/dwarf/dwarf2diehandler.h"
     57 #include "common/dwarf_cfi_to_module.h"
     58 #include "common/dwarf_cu_to_module.h"
     59 #include "common/dwarf_line_to_module.h"
     60 #include "common/linux/crc32.h"
     61 #include "common/linux/eintr_wrapper.h"
     62 #include "common/linux/elfutils.h"
     63 #include "common/linux/elfutils-inl.h"
     64 #include "common/linux/elf_symbols_to_module.h"
     65 #include "common/linux/file_id.h"
     66 #include "common/module.h"
     67 #include "common/scoped_ptr.h"
     68 #ifndef NO_STABS_SUPPORT
     69 #include "common/stabs_reader.h"
     70 #include "common/stabs_to_module.h"
     71 #endif
     72 #include "common/using_std_string.h"
     73 
     74 // This namespace contains helper functions.
     75 namespace {
     76 
     77 using google_breakpad::DumpOptions;
     78 using google_breakpad::DwarfCFIToModule;
     79 using google_breakpad::DwarfCUToModule;
     80 using google_breakpad::DwarfLineToModule;
     81 using google_breakpad::ElfClass;
     82 using google_breakpad::ElfClass32;
     83 using google_breakpad::ElfClass64;
     84 using google_breakpad::FindElfSectionByName;
     85 using google_breakpad::GetOffset;
     86 using google_breakpad::IsValidElf;
     87 using google_breakpad::Module;
     88 #ifndef NO_STABS_SUPPORT
     89 using google_breakpad::StabsToModule;
     90 #endif
     91 using google_breakpad::scoped_ptr;
     92 
     93 // Define AARCH64 ELF architecture if host machine does not include this define.
     94 #ifndef EM_AARCH64
     95 #define EM_AARCH64      183
     96 #endif
     97 
     98 //
     99 // FDWrapper
    100 //
    101 // Wrapper class to make sure opened file is closed.
    102 //
    103 class FDWrapper {
    104  public:
    105   explicit FDWrapper(int fd) :
    106     fd_(fd) {}
    107   ~FDWrapper() {
    108     if (fd_ != -1)
    109       close(fd_);
    110   }
    111   int get() {
    112     return fd_;
    113   }
    114   int release() {
    115     int fd = fd_;
    116     fd_ = -1;
    117     return fd;
    118   }
    119  private:
    120   int fd_;
    121 };
    122 
    123 //
    124 // MmapWrapper
    125 //
    126 // Wrapper class to make sure mapped regions are unmapped.
    127 //
    128 class MmapWrapper {
    129  public:
    130   MmapWrapper() : is_set_(false) {}
    131   ~MmapWrapper() {
    132     if (is_set_ && base_ != NULL) {
    133       assert(size_ > 0);
    134       munmap(base_, size_);
    135     }
    136   }
    137   void set(void *mapped_address, size_t mapped_size) {
    138     is_set_ = true;
    139     base_ = mapped_address;
    140     size_ = mapped_size;
    141   }
    142   void release() {
    143     assert(is_set_);
    144     is_set_ = false;
    145     base_ = NULL;
    146     size_ = 0;
    147   }
    148 
    149  private:
    150   bool is_set_;
    151   void* base_;
    152   size_t size_;
    153 };
    154 
    155 // Find the preferred loading address of the binary.
    156 template<typename ElfClass>
    157 typename ElfClass::Addr GetLoadingAddress(
    158     const typename ElfClass::Phdr* program_headers,
    159     int nheader) {
    160   typedef typename ElfClass::Phdr Phdr;
    161 
    162   // For non-PIC executables (e_type == ET_EXEC), the load address is
    163   // the start address of the first PT_LOAD segment.  (ELF requires
    164   // the segments to be sorted by load address.)  For PIC executables
    165   // and dynamic libraries (e_type == ET_DYN), this address will
    166   // normally be zero.
    167   for (int i = 0; i < nheader; ++i) {
    168     const Phdr& header = program_headers[i];
    169     if (header.p_type == PT_LOAD)
    170       return header.p_vaddr;
    171   }
    172   return 0;
    173 }
    174 
    175 #ifndef NO_STABS_SUPPORT
    176 template<typename ElfClass>
    177 bool LoadStabs(const typename ElfClass::Ehdr* elf_header,
    178                const typename ElfClass::Shdr* stab_section,
    179                const typename ElfClass::Shdr* stabstr_section,
    180                const bool big_endian,
    181                Module* module) {
    182   // A callback object to handle data from the STABS reader.
    183   StabsToModule handler(module);
    184   // Find the addresses of the STABS data, and create a STABS reader object.
    185   // On Linux, STABS entries always have 32-bit values, regardless of the
    186   // address size of the architecture whose code they're describing, and
    187   // the strings are always "unitized".
    188   const uint8_t* stabs =
    189       GetOffset<ElfClass, uint8_t>(elf_header, stab_section->sh_offset);
    190   const uint8_t* stabstr =
    191       GetOffset<ElfClass, uint8_t>(elf_header, stabstr_section->sh_offset);
    192   google_breakpad::StabsReader reader(stabs, stab_section->sh_size,
    193                                       stabstr, stabstr_section->sh_size,
    194                                       big_endian, 4, true, &handler);
    195   // Read the STABS data, and do post-processing.
    196   if (!reader.Process())
    197     return false;
    198   handler.Finalize();
    199   return true;
    200 }
    201 #endif  // NO_STABS_SUPPORT
    202 
    203 // A line-to-module loader that accepts line number info parsed by
    204 // dwarf2reader::LineInfo and populates a Module and a line vector
    205 // with the results.
    206 class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler {
    207  public:
    208   // Create a line-to-module converter using BYTE_READER.
    209   explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader)
    210       : byte_reader_(byte_reader) { }
    211   void StartCompilationUnit(const string& compilation_dir) {
    212     compilation_dir_ = compilation_dir;
    213   }
    214   void ReadProgram(const char* program, uint64 length,
    215                    Module* module, std::vector<Module::Line>* lines) {
    216     DwarfLineToModule handler(module, compilation_dir_, lines);
    217     dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler);
    218     parser.Start();
    219   }
    220  private:
    221   string compilation_dir_;
    222   dwarf2reader::ByteReader *byte_reader_;
    223 };
    224 
    225 template<typename ElfClass>
    226 bool LoadDwarf(const string& dwarf_filename,
    227                const typename ElfClass::Ehdr* elf_header,
    228                const bool big_endian,
    229                bool handle_inter_cu_refs,
    230                Module* module) {
    231   typedef typename ElfClass::Shdr Shdr;
    232 
    233   const dwarf2reader::Endianness endianness = big_endian ?
    234       dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE;
    235   dwarf2reader::ByteReader byte_reader(endianness);
    236 
    237   // Construct a context for this file.
    238   DwarfCUToModule::FileContext file_context(dwarf_filename,
    239                                             module,
    240                                             handle_inter_cu_refs);
    241 
    242   // Build a map of the ELF file's sections.
    243   const Shdr* sections =
    244       GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
    245   int num_sections = elf_header->e_shnum;
    246   const Shdr* section_names = sections + elf_header->e_shstrndx;
    247   for (int i = 0; i < num_sections; i++) {
    248     const Shdr* section = &sections[i];
    249     string name = GetOffset<ElfClass, char>(elf_header,
    250                                             section_names->sh_offset) +
    251                   section->sh_name;
    252     const char* contents = GetOffset<ElfClass, char>(elf_header,
    253                                                      section->sh_offset);
    254     file_context.AddSectionToSectionMap(name, contents, section->sh_size);
    255   }
    256 
    257   // Parse all the compilation units in the .debug_info section.
    258   DumperLineToModule line_to_module(&byte_reader);
    259   dwarf2reader::SectionMap::const_iterator debug_info_entry =
    260       file_context.section_map().find(".debug_info");
    261   assert(debug_info_entry != file_context.section_map().end());
    262   const std::pair<const char*, uint64>& debug_info_section =
    263       debug_info_entry->second;
    264   // This should never have been called if the file doesn't have a
    265   // .debug_info section.
    266   assert(debug_info_section.first);
    267   uint64 debug_info_length = debug_info_section.second;
    268   for (uint64 offset = 0; offset < debug_info_length;) {
    269     // Make a handler for the root DIE that populates MODULE with the
    270     // data that was found.
    271     DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset);
    272     DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter);
    273     // Make a Dwarf2Handler that drives the DIEHandler.
    274     dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
    275     // Make a DWARF parser for the compilation unit at OFFSET.
    276     dwarf2reader::CompilationUnit reader(file_context.section_map(),
    277                                          offset,
    278                                          &byte_reader,
    279                                          &die_dispatcher);
    280     // Process the entire compilation unit; get the offset of the next.
    281     offset += reader.Start();
    282   }
    283   return true;
    284 }
    285 
    286 // Fill REGISTER_NAMES with the register names appropriate to the
    287 // machine architecture given in HEADER, indexed by the register
    288 // numbers used in DWARF call frame information. Return true on
    289 // success, or false if HEADER's machine architecture is not
    290 // supported.
    291 template<typename ElfClass>
    292 bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
    293                            std::vector<string>* register_names) {
    294   switch (elf_header->e_machine) {
    295     case EM_386:
    296       *register_names = DwarfCFIToModule::RegisterNames::I386();
    297       return true;
    298     case EM_ARM:
    299       *register_names = DwarfCFIToModule::RegisterNames::ARM();
    300       return true;
    301     case EM_AARCH64:
    302       *register_names = DwarfCFIToModule::RegisterNames::ARM64();
    303       return true;
    304     case EM_MIPS:
    305       *register_names = DwarfCFIToModule::RegisterNames::MIPS();
    306       return true;
    307     case EM_X86_64:
    308       *register_names = DwarfCFIToModule::RegisterNames::X86_64();
    309       return true;
    310     default:
    311       return false;
    312   }
    313 }
    314 
    315 template<typename ElfClass>
    316 bool LoadDwarfCFI(const string& dwarf_filename,
    317                   const typename ElfClass::Ehdr* elf_header,
    318                   const char* section_name,
    319                   const typename ElfClass::Shdr* section,
    320                   const bool eh_frame,
    321                   const typename ElfClass::Shdr* got_section,
    322                   const typename ElfClass::Shdr* text_section,
    323                   const bool big_endian,
    324                   Module* module) {
    325   // Find the appropriate set of register names for this file's
    326   // architecture.
    327   std::vector<string> register_names;
    328   if (!DwarfCFIRegisterNames<ElfClass>(elf_header, &register_names)) {
    329     fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';"
    330             " cannot convert DWARF call frame information\n",
    331             dwarf_filename.c_str(), elf_header->e_machine);
    332     return false;
    333   }
    334 
    335   const dwarf2reader::Endianness endianness = big_endian ?
    336       dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE;
    337 
    338   // Find the call frame information and its size.
    339   const char* cfi =
    340       GetOffset<ElfClass, char>(elf_header, section->sh_offset);
    341   size_t cfi_size = section->sh_size;
    342 
    343   // Plug together the parser, handler, and their entourages.
    344   DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name);
    345   DwarfCFIToModule handler(module, register_names, &module_reporter);
    346   dwarf2reader::ByteReader byte_reader(endianness);
    347 
    348   byte_reader.SetAddressSize(ElfClass::kAddrSize);
    349 
    350   // Provide the base addresses for .eh_frame encoded pointers, if
    351   // possible.
    352   byte_reader.SetCFIDataBase(section->sh_addr, cfi);
    353   if (got_section)
    354     byte_reader.SetDataBase(got_section->sh_addr);
    355   if (text_section)
    356     byte_reader.SetTextBase(text_section->sh_addr);
    357 
    358   dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename,
    359                                                        section_name);
    360   dwarf2reader::CallFrameInfo parser(cfi, cfi_size,
    361                                      &byte_reader, &handler, &dwarf_reporter,
    362                                      eh_frame);
    363   parser.Start();
    364   return true;
    365 }
    366 
    367 bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper,
    368              void** elf_header) {
    369   int obj_fd = open(obj_file.c_str(), O_RDONLY);
    370   if (obj_fd < 0) {
    371     fprintf(stderr, "Failed to open ELF file '%s': %s\n",
    372             obj_file.c_str(), strerror(errno));
    373     return false;
    374   }
    375   FDWrapper obj_fd_wrapper(obj_fd);
    376   struct stat st;
    377   if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) {
    378     fprintf(stderr, "Unable to fstat ELF file '%s': %s\n",
    379             obj_file.c_str(), strerror(errno));
    380     return false;
    381   }
    382   void* obj_base = mmap(NULL, st.st_size,
    383                         PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0);
    384   if (obj_base == MAP_FAILED) {
    385     fprintf(stderr, "Failed to mmap ELF file '%s': %s\n",
    386             obj_file.c_str(), strerror(errno));
    387     return false;
    388   }
    389   map_wrapper->set(obj_base, st.st_size);
    390   *elf_header = obj_base;
    391   if (!IsValidElf(*elf_header)) {
    392     fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
    393     return false;
    394   }
    395   return true;
    396 }
    397 
    398 // Get the endianness of ELF_HEADER. If it's invalid, return false.
    399 template<typename ElfClass>
    400 bool ElfEndianness(const typename ElfClass::Ehdr* elf_header,
    401                    bool* big_endian) {
    402   if (elf_header->e_ident[EI_DATA] == ELFDATA2LSB) {
    403     *big_endian = false;
    404     return true;
    405   }
    406   if (elf_header->e_ident[EI_DATA] == ELFDATA2MSB) {
    407     *big_endian = true;
    408     return true;
    409   }
    410 
    411   fprintf(stderr, "bad data encoding in ELF header: %d\n",
    412           elf_header->e_ident[EI_DATA]);
    413   return false;
    414 }
    415 
    416 // Given |left_abspath|, find the absolute path for |right_path| and see if the
    417 // two absolute paths are the same.
    418 bool IsSameFile(const char* left_abspath, const string& right_path) {
    419   char right_abspath[PATH_MAX];
    420   if (!realpath(right_path.c_str(), right_abspath))
    421     return false;
    422   return strcmp(left_abspath, right_abspath) == 0;
    423 }
    424 
    425 // Read the .gnu_debuglink and get the debug file name. If anything goes
    426 // wrong, return an empty string.
    427 string ReadDebugLink(const char* debuglink,
    428                      const size_t debuglink_size,
    429                      const bool big_endian,
    430                      const string& obj_file,
    431                      const std::vector<string>& debug_dirs) {
    432   size_t debuglink_len = strlen(debuglink) + 5;  // Include '\0' + CRC32.
    433   debuglink_len = 4 * ((debuglink_len + 3) / 4);  // Round up to 4 bytes.
    434 
    435   // Sanity check.
    436   if (debuglink_len != debuglink_size) {
    437     fprintf(stderr, "Mismatched .gnu_debuglink string / section size: "
    438             "%zx %zx\n", debuglink_len, debuglink_size);
    439     return string();
    440   }
    441 
    442   char obj_file_abspath[PATH_MAX];
    443   if (!realpath(obj_file.c_str(), obj_file_abspath)) {
    444     fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str());
    445     return string();
    446   }
    447 
    448   std::vector<string> searched_paths;
    449   string debuglink_path;
    450   std::vector<string>::const_iterator it;
    451   for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) {
    452     const string& debug_dir = *it;
    453     debuglink_path = debug_dir + "/" + debuglink;
    454 
    455     // There is the annoying case of /path/to/foo.so having foo.so as the
    456     // debug link file name. Thus this may end up opening /path/to/foo.so again,
    457     // and there is a small chance of the two files having the same CRC.
    458     if (IsSameFile(obj_file_abspath, debuglink_path))
    459       continue;
    460 
    461     searched_paths.push_back(debug_dir);
    462     int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
    463     if (debuglink_fd < 0)
    464       continue;
    465 
    466     FDWrapper debuglink_fd_wrapper(debuglink_fd);
    467 
    468     // The CRC is the last 4 bytes in |debuglink|.
    469     const dwarf2reader::Endianness endianness = big_endian ?
    470         dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE;
    471     dwarf2reader::ByteReader byte_reader(endianness);
    472     uint32_t expected_crc =
    473         byte_reader.ReadFourBytes(&debuglink[debuglink_size - 4]);
    474 
    475     uint32_t actual_crc = 0;
    476     while (true) {
    477       const size_t kReadSize = 4096;
    478       char buf[kReadSize];
    479       ssize_t bytes_read = HANDLE_EINTR(read(debuglink_fd, &buf, kReadSize));
    480       if (bytes_read < 0) {
    481         fprintf(stderr, "Error reading debug ELF file %s.\n",
    482                 debuglink_path.c_str());
    483         return string();
    484       }
    485       if (bytes_read == 0)
    486         break;
    487       actual_crc = google_breakpad::UpdateCrc32(actual_crc, buf, bytes_read);
    488     }
    489     if (actual_crc != expected_crc) {
    490       fprintf(stderr, "Error reading debug ELF file - CRC32 mismatch: %s\n",
    491               debuglink_path.c_str());
    492       continue;
    493     }
    494 
    495     // Found debug file.
    496     return debuglink_path;
    497   }
    498 
    499   // Not found case.
    500   fprintf(stderr, "Failed to find debug ELF file for '%s' after trying:\n",
    501           obj_file.c_str());
    502   for (it = searched_paths.begin(); it < searched_paths.end(); ++it) {
    503     const string& debug_dir = *it;
    504     fprintf(stderr, "  %s/%s\n", debug_dir.c_str(), debuglink);
    505   }
    506   return string();
    507 }
    508 
    509 //
    510 // LoadSymbolsInfo
    511 //
    512 // Holds the state between the two calls to LoadSymbols() in case it's necessary
    513 // to follow the .gnu_debuglink section and load debug information from a
    514 // different file.
    515 //
    516 template<typename ElfClass>
    517 class LoadSymbolsInfo {
    518  public:
    519   typedef typename ElfClass::Addr Addr;
    520 
    521   explicit LoadSymbolsInfo(const std::vector<string>& dbg_dirs) :
    522     debug_dirs_(dbg_dirs),
    523     has_loading_addr_(false) {}
    524 
    525   // Keeps track of which sections have been loaded so sections don't
    526   // accidentally get loaded twice from two different files.
    527   void LoadedSection(const string &section) {
    528     if (loaded_sections_.count(section) == 0) {
    529       loaded_sections_.insert(section);
    530     } else {
    531       fprintf(stderr, "Section %s has already been loaded.\n",
    532               section.c_str());
    533     }
    534   }
    535 
    536   // The ELF file and linked debug file are expected to have the same preferred
    537   // loading address.
    538   void set_loading_addr(Addr addr, const string &filename) {
    539     if (!has_loading_addr_) {
    540       loading_addr_ = addr;
    541       loaded_file_ = filename;
    542       return;
    543     }
    544 
    545     if (addr != loading_addr_) {
    546       fprintf(stderr,
    547               "ELF file '%s' and debug ELF file '%s' "
    548               "have different load addresses.\n",
    549               loaded_file_.c_str(), filename.c_str());
    550       assert(false);
    551     }
    552   }
    553 
    554   // Setters and getters
    555   const std::vector<string>& debug_dirs() const {
    556     return debug_dirs_;
    557   }
    558 
    559   string debuglink_file() const {
    560     return debuglink_file_;
    561   }
    562   void set_debuglink_file(string file) {
    563     debuglink_file_ = file;
    564   }
    565 
    566  private:
    567   const std::vector<string>& debug_dirs_; // Directories in which to
    568                                           // search for the debug ELF file.
    569 
    570   string debuglink_file_;  // Full path to the debug ELF file.
    571 
    572   bool has_loading_addr_;  // Indicate if LOADING_ADDR_ is valid.
    573 
    574   Addr loading_addr_;  // Saves the preferred loading address from the
    575                        // first call to LoadSymbols().
    576 
    577   string loaded_file_;  // Name of the file loaded from the first call to
    578                         // LoadSymbols().
    579 
    580   std::set<string> loaded_sections_;  // Tracks the Loaded ELF sections
    581                                       // between calls to LoadSymbols().
    582 };
    583 
    584 template<typename ElfClass>
    585 bool LoadSymbols(const string& obj_file,
    586                  const bool big_endian,
    587                  const typename ElfClass::Ehdr* elf_header,
    588                  const bool read_gnu_debug_link,
    589                  LoadSymbolsInfo<ElfClass>* info,
    590                  const DumpOptions& options,
    591                  Module* module) {
    592   typedef typename ElfClass::Addr Addr;
    593   typedef typename ElfClass::Phdr Phdr;
    594   typedef typename ElfClass::Shdr Shdr;
    595   typedef typename ElfClass::Word Word;
    596 
    597   Addr loading_addr = GetLoadingAddress<ElfClass>(
    598       GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff),
    599       elf_header->e_phnum);
    600   module->SetLoadAddress(loading_addr);
    601   info->set_loading_addr(loading_addr, obj_file);
    602 
    603   Word debug_section_type =
    604       elf_header->e_machine == EM_MIPS ? SHT_MIPS_DWARF : SHT_PROGBITS;
    605   const Shdr* sections =
    606       GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
    607   const Shdr* section_names = sections + elf_header->e_shstrndx;
    608   const char* names =
    609       GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
    610   const char *names_end = names + section_names->sh_size;
    611   bool found_debug_info_section = false;
    612   bool found_usable_info = false;
    613 
    614   if (options.symbol_data != ONLY_CFI) {
    615 #ifndef NO_STABS_SUPPORT
    616     // Look for STABS debugging information, and load it if present.
    617     const Shdr* stab_section =
    618       FindElfSectionByName<ElfClass>(".stab", SHT_PROGBITS,
    619                                      sections, names, names_end,
    620                                      elf_header->e_shnum);
    621     if (stab_section) {
    622       const Shdr* stabstr_section = stab_section->sh_link + sections;
    623       if (stabstr_section) {
    624         found_debug_info_section = true;
    625         found_usable_info = true;
    626         info->LoadedSection(".stab");
    627         if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section,
    628                                  big_endian, module)) {
    629           fprintf(stderr, "%s: \".stab\" section found, but failed to load"
    630                   " STABS debugging information\n", obj_file.c_str());
    631         }
    632       }
    633     }
    634 #endif  // NO_STABS_SUPPORT
    635 
    636     // Look for DWARF debugging information, and load it if present.
    637     const Shdr* dwarf_section =
    638       FindElfSectionByName<ElfClass>(".debug_info", debug_section_type,
    639                                      sections, names, names_end,
    640                                      elf_header->e_shnum);
    641     if (dwarf_section) {
    642       found_debug_info_section = true;
    643       found_usable_info = true;
    644       info->LoadedSection(".debug_info");
    645       if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian,
    646                                options.handle_inter_cu_refs, module)) {
    647         fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
    648                 "DWARF debugging information\n", obj_file.c_str());
    649       }
    650     }
    651 
    652     // See if there are export symbols available.
    653     const Shdr* dynsym_section =
    654       FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
    655                                      sections, names, names_end,
    656                                      elf_header->e_shnum);
    657     const Shdr* dynstr_section =
    658       FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
    659                                      sections, names, names_end,
    660                                      elf_header->e_shnum);
    661     if (dynsym_section && dynstr_section) {
    662       info->LoadedSection(".dynsym");
    663 
    664       const uint8_t* dynsyms =
    665           GetOffset<ElfClass, uint8_t>(elf_header,
    666                                        dynsym_section->sh_offset);
    667       const uint8_t* dynstrs =
    668           GetOffset<ElfClass, uint8_t>(elf_header,
    669                                        dynstr_section->sh_offset);
    670       bool result =
    671           ELFSymbolsToModule(dynsyms,
    672                              dynsym_section->sh_size,
    673                              dynstrs,
    674                              dynstr_section->sh_size,
    675                              big_endian,
    676                              ElfClass::kAddrSize,
    677                              module);
    678       found_usable_info = found_usable_info || result;
    679     }
    680   }
    681 
    682   if (options.symbol_data != NO_CFI) {
    683     // Dwarf Call Frame Information (CFI) is actually independent from
    684     // the other DWARF debugging information, and can be used alone.
    685     const Shdr* dwarf_cfi_section =
    686         FindElfSectionByName<ElfClass>(".debug_frame", debug_section_type,
    687                                        sections, names, names_end,
    688                                        elf_header->e_shnum);
    689     if (dwarf_cfi_section) {
    690       // Ignore the return value of this function; even without call frame
    691       // information, the other debugging information could be perfectly
    692       // useful.
    693       info->LoadedSection(".debug_frame");
    694       bool result =
    695           LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".debug_frame",
    696                                  dwarf_cfi_section, false, 0, 0, big_endian,
    697                                  module);
    698       found_usable_info = found_usable_info || result;
    699     }
    700 
    701     // Linux C++ exception handling information can also provide
    702     // unwinding data.
    703     const Shdr* eh_frame_section =
    704         FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS,
    705                                        sections, names, names_end,
    706                                        elf_header->e_shnum);
    707     if (eh_frame_section) {
    708       // Pointers in .eh_frame data may be relative to the base addresses of
    709       // certain sections. Provide those sections if present.
    710       const Shdr* got_section =
    711           FindElfSectionByName<ElfClass>(".got", SHT_PROGBITS,
    712                                          sections, names, names_end,
    713                                          elf_header->e_shnum);
    714       const Shdr* text_section =
    715           FindElfSectionByName<ElfClass>(".text", SHT_PROGBITS,
    716                                          sections, names, names_end,
    717                                          elf_header->e_shnum);
    718       info->LoadedSection(".eh_frame");
    719       // As above, ignore the return value of this function.
    720       bool result =
    721           LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame",
    722                                  eh_frame_section, true,
    723                                  got_section, text_section, big_endian, module);
    724       found_usable_info = found_usable_info || result;
    725     }
    726   }
    727 
    728   if (!found_debug_info_section) {
    729     fprintf(stderr, "%s: file contains no debugging information"
    730             " (no \".stab\" or \".debug_info\" sections)\n",
    731             obj_file.c_str());
    732 
    733     // Failed, but maybe there's a .gnu_debuglink section?
    734     if (read_gnu_debug_link) {
    735       const Shdr* gnu_debuglink_section
    736           = FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS,
    737                                            sections, names,
    738                                            names_end, elf_header->e_shnum);
    739       if (gnu_debuglink_section) {
    740         if (!info->debug_dirs().empty()) {
    741           const char* debuglink_contents =
    742               GetOffset<ElfClass, char>(elf_header,
    743                                         gnu_debuglink_section->sh_offset);
    744           string debuglink_file =
    745               ReadDebugLink(debuglink_contents,
    746                             gnu_debuglink_section->sh_size,
    747                             big_endian,
    748                             obj_file,
    749                             info->debug_dirs());
    750           info->set_debuglink_file(debuglink_file);
    751         } else {
    752           fprintf(stderr, ".gnu_debuglink section found in '%s', "
    753                   "but no debug path specified.\n", obj_file.c_str());
    754         }
    755       } else {
    756         fprintf(stderr, "%s does not contain a .gnu_debuglink section.\n",
    757                 obj_file.c_str());
    758       }
    759     } else {
    760       // Return true if some usable information was found, since the caller
    761       // doesn't want to use .gnu_debuglink.
    762       return found_usable_info;
    763     }
    764 
    765     // No debug info was found, let the user try again with .gnu_debuglink
    766     // if present.
    767     return false;
    768   }
    769 
    770   return true;
    771 }
    772 
    773 // Return the breakpad symbol file identifier for the architecture of
    774 // ELF_HEADER.
    775 template<typename ElfClass>
    776 const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) {
    777   typedef typename ElfClass::Half Half;
    778   Half arch = elf_header->e_machine;
    779   switch (arch) {
    780     case EM_386:        return "x86";
    781     case EM_ARM:        return "arm";
    782     case EM_AARCH64:    return "arm64";
    783     case EM_MIPS:       return "mips";
    784     case EM_PPC64:      return "ppc64";
    785     case EM_PPC:        return "ppc";
    786     case EM_S390:       return "s390";
    787     case EM_SPARC:      return "sparc";
    788     case EM_SPARCV9:    return "sparcv9";
    789     case EM_X86_64:     return "x86_64";
    790     default: return NULL;
    791   }
    792 }
    793 
    794 // Format the Elf file identifier in IDENTIFIER as a UUID with the
    795 // dashes removed.
    796 string FormatIdentifier(unsigned char identifier[16]) {
    797   char identifier_str[40];
    798   google_breakpad::FileID::ConvertIdentifierToString(
    799       identifier,
    800       identifier_str,
    801       sizeof(identifier_str));
    802   string id_no_dash;
    803   for (int i = 0; identifier_str[i] != '\0'; ++i)
    804     if (identifier_str[i] != '-')
    805       id_no_dash += identifier_str[i];
    806   // Add an extra "0" by the end.  PDB files on Windows have an 'age'
    807   // number appended to the end of the file identifier; this isn't
    808   // really used or necessary on other platforms, but be consistent.
    809   id_no_dash += '0';
    810   return id_no_dash;
    811 }
    812 
    813 // Return the non-directory portion of FILENAME: the portion after the
    814 // last slash, or the whole filename if there are no slashes.
    815 string BaseFileName(const string &filename) {
    816   // Lots of copies!  basename's behavior is less than ideal.
    817   char* c_filename = strdup(filename.c_str());
    818   string base = basename(c_filename);
    819   free(c_filename);
    820   return base;
    821 }
    822 
    823 template<typename ElfClass>
    824 bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header,
    825                        const string& debuglink_file,
    826                        const string& obj_filename,
    827                        const char* obj_file_architecture,
    828                        const bool obj_file_is_big_endian) {
    829   const char* debug_architecture =
    830       ElfArchitecture<ElfClass>(debug_elf_header);
    831   if (!debug_architecture) {
    832     fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
    833             debuglink_file.c_str(), debug_elf_header->e_machine);
    834     return false;
    835   }
    836   if (strcmp(obj_file_architecture, debug_architecture)) {
    837     fprintf(stderr, "%s with ELF machine architecture %s does not match "
    838             "%s with ELF architecture %s\n",
    839             debuglink_file.c_str(), debug_architecture,
    840             obj_filename.c_str(), obj_file_architecture);
    841     return false;
    842   }
    843   bool debug_big_endian;
    844   if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian))
    845     return false;
    846   if (debug_big_endian != obj_file_is_big_endian) {
    847     fprintf(stderr, "%s and %s does not match in endianness\n",
    848             obj_filename.c_str(), debuglink_file.c_str());
    849     return false;
    850   }
    851   return true;
    852 }
    853 
    854 template<typename ElfClass>
    855 bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
    856                             const string& obj_filename,
    857                             const std::vector<string>& debug_dirs,
    858                             const DumpOptions& options,
    859                             Module** out_module) {
    860   typedef typename ElfClass::Ehdr Ehdr;
    861   typedef typename ElfClass::Shdr Shdr;
    862 
    863   *out_module = NULL;
    864 
    865   unsigned char identifier[16];
    866   if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header,
    867                                                                 identifier)) {
    868     fprintf(stderr, "%s: unable to generate file identifier\n",
    869             obj_filename.c_str());
    870     return false;
    871   }
    872 
    873   const char *architecture = ElfArchitecture<ElfClass>(elf_header);
    874   if (!architecture) {
    875     fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
    876             obj_filename.c_str(), elf_header->e_machine);
    877     return false;
    878   }
    879 
    880   // Figure out what endianness this file is.
    881   bool big_endian;
    882   if (!ElfEndianness<ElfClass>(elf_header, &big_endian))
    883     return false;
    884 
    885   string name = BaseFileName(obj_filename);
    886   string os = "Linux";
    887   string id = FormatIdentifier(identifier);
    888 
    889   LoadSymbolsInfo<ElfClass> info(debug_dirs);
    890   scoped_ptr<Module> module(new Module(name, os, architecture, id));
    891   if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
    892                              !debug_dirs.empty(), &info,
    893                              options, module.get())) {
    894     const string debuglink_file = info.debuglink_file();
    895     if (debuglink_file.empty())
    896       return false;
    897 
    898     // Load debuglink ELF file.
    899     fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str());
    900     MmapWrapper debug_map_wrapper;
    901     Ehdr* debug_elf_header = NULL;
    902     if (!LoadELF(debuglink_file, &debug_map_wrapper,
    903                  reinterpret_cast<void**>(&debug_elf_header)) ||
    904         !SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file,
    905                                      obj_filename, architecture, big_endian)) {
    906       return false;
    907     }
    908 
    909     if (!LoadSymbols<ElfClass>(debuglink_file, big_endian,
    910                                debug_elf_header, false, &info,
    911                                options, module.get())) {
    912       return false;
    913     }
    914   }
    915 
    916   *out_module = module.release();
    917   return true;
    918 }
    919 
    920 }  // namespace
    921 
    922 namespace google_breakpad {
    923 
    924 // Not explicitly exported, but not static so it can be used in unit tests.
    925 bool ReadSymbolDataInternal(const uint8_t* obj_file,
    926                             const string& obj_filename,
    927                             const std::vector<string>& debug_dirs,
    928                             const DumpOptions& options,
    929                             Module** module) {
    930   if (!IsValidElf(obj_file)) {
    931     fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str());
    932     return false;
    933   }
    934 
    935   int elfclass = ElfClass(obj_file);
    936   if (elfclass == ELFCLASS32) {
    937     return ReadSymbolDataElfClass<ElfClass32>(
    938         reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dirs,
    939         options, module);
    940   }
    941   if (elfclass == ELFCLASS64) {
    942     return ReadSymbolDataElfClass<ElfClass64>(
    943         reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dirs,
    944         options, module);
    945   }
    946 
    947   return false;
    948 }
    949 
    950 bool WriteSymbolFile(const string &obj_file,
    951                      const std::vector<string>& debug_dirs,
    952                      const DumpOptions& options,
    953                      std::ostream &sym_stream) {
    954   Module* module;
    955   if (!ReadSymbolData(obj_file, debug_dirs, options, &module))
    956     return false;
    957 
    958   bool result = module->Write(sym_stream, options.symbol_data);
    959   delete module;
    960   return result;
    961 }
    962 
    963 bool ReadSymbolData(const string& obj_file,
    964                     const std::vector<string>& debug_dirs,
    965                     const DumpOptions& options,
    966                     Module** module) {
    967   MmapWrapper map_wrapper;
    968   void* elf_header = NULL;
    969   if (!LoadELF(obj_file, &map_wrapper, &elf_header))
    970     return false;
    971 
    972   return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
    973                                 obj_file, debug_dirs, options, module);
    974 }
    975 
    976 }  // namespace google_breakpad
    977