1 // -*- mode: c++ -*- 2 3 // Copyright (c) 2011, Google Inc. 4 // All rights reserved. 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // * Neither the name of Google Inc. nor the names of its 17 // contributors may be used to endorse or promote products derived from 18 // this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 // Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 33 34 // dump_syms.h: Declaration of google_breakpad::DumpSymbols, a class for 35 // reading debugging information from Mach-O files and writing it out as a 36 // Breakpad symbol file. 37 38 #include <mach-o/loader.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 42 #include <ostream> 43 #include <string> 44 #include <vector> 45 46 #include "common/byte_cursor.h" 47 #include "common/mac/macho_reader.h" 48 #include "common/mac/super_fat_arch.h" 49 #include "common/module.h" 50 #include "common/scoped_ptr.h" 51 #include "common/symbol_data.h" 52 53 namespace google_breakpad { 54 55 class DumpSymbols { 56 public: DumpSymbols(SymbolData symbol_data,bool handle_inter_cu_refs)57 DumpSymbols(SymbolData symbol_data, bool handle_inter_cu_refs) 58 : symbol_data_(symbol_data), 59 handle_inter_cu_refs_(handle_inter_cu_refs), 60 input_pathname_(), 61 object_filename_(), 62 contents_(), 63 object_files_(), 64 selected_object_file_(), 65 selected_object_name_() { } ~DumpSymbols()66 ~DumpSymbols() { 67 } 68 69 // Prepare to read debugging information from |filename|. |filename| may be 70 // the name of a universal binary, a Mach-O file, or a dSYM bundle 71 // containing either of the above. On success, return true; if there is a 72 // problem reading |filename|, report it and return false. 73 bool Read(const std::string &filename); 74 75 // If this dumper's file includes an object file for |cpu_type| and 76 // |cpu_subtype|, then select that object file for dumping, and return 77 // true. Otherwise, return false, and leave this dumper's selected 78 // architecture unchanged. 79 // 80 // By default, if this dumper's file contains only one object file, then 81 // the dumper will dump those symbols; and if it contains more than one 82 // object file, then the dumper will dump the object file whose 83 // architecture matches that of this dumper program. 84 bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); 85 86 // If this dumper's file includes an object file for |arch_name|, then select 87 // that object file for dumping, and return true. Otherwise, return false, 88 // and leave this dumper's selected architecture unchanged. 89 // 90 // By default, if this dumper's file contains only one object file, then 91 // the dumper will dump those symbols; and if it contains more than one 92 // object file, then the dumper will dump the object file whose 93 // architecture matches that of this dumper program. 94 bool SetArchitecture(const std::string &arch_name); 95 96 // Return a pointer to an array of SuperFatArch structures describing the 97 // object files contained in this dumper's file. Set *|count| to the number 98 // of elements in the array. The returned array is owned by this DumpSymbols 99 // instance. 100 // 101 // If there are no available architectures, this function 102 // may return NULL. AvailableArchitectures(size_t * count)103 const SuperFatArch* AvailableArchitectures(size_t *count) { 104 *count = object_files_.size(); 105 if (object_files_.size() > 0) 106 return &object_files_[0]; 107 return NULL; 108 } 109 110 // Read the selected object file's debugging information, and write it out to 111 // |stream|. Return true on success; if an error occurs, report it and 112 // return false. 113 bool WriteSymbolFile(std::ostream &stream); 114 115 // Read the selected object file's debugging information, and write out the 116 // header only to |stream|. Return true on success; if an error occurs, report 117 // it and return false. 118 bool WriteSymbolFileHeader(std::ostream &stream); 119 120 // As above, but simply return the debugging information in module 121 // instead of writing it to a stream. The caller owns the resulting 122 // module object and must delete it when finished. 123 bool ReadSymbolData(Module** module); 124 125 private: 126 // Used internally. 127 class DumperLineToModule; 128 class DumperRangesHandler; 129 class LoadCommandDumper; 130 131 // This method behaves similarly to NXFindBestFatArch, but it supports 132 // SuperFatArch. 133 SuperFatArch* FindBestMatchForArchitecture( 134 cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); 135 136 // Return an identifier string for the file this DumpSymbols is dumping. 137 std::string Identifier(); 138 139 140 // Creates an empty module object. 141 bool CreateEmptyModule(scoped_ptr<Module>& module); 142 143 // Read debugging information from |dwarf_sections|, which was taken from 144 // |macho_reader|, and add it to |module|. 145 void ReadDwarf(google_breakpad::Module *module, 146 const mach_o::Reader &macho_reader, 147 const mach_o::SectionMap &dwarf_sections, 148 bool handle_inter_cu_refs) const; 149 150 // Read DWARF CFI or .eh_frame data from |section|, belonging to 151 // |macho_reader|, and record it in |module|. If |eh_frame| is true, 152 // then the data is .eh_frame-format data; otherwise, it is standard DWARF 153 // .debug_frame data. On success, return true; on failure, report 154 // the problem and return false. 155 bool ReadCFI(google_breakpad::Module *module, 156 const mach_o::Reader &macho_reader, 157 const mach_o::Section §ion, 158 bool eh_frame) const; 159 160 // The selection of what type of symbol data to read/write. 161 const SymbolData symbol_data_; 162 163 // Whether to handle references between compilation units. 164 const bool handle_inter_cu_refs_; 165 166 // The name of the file or bundle whose symbols this will dump. 167 // This is the path given to Read, for use in error messages. 168 std::string input_pathname_; 169 170 // The name of the file this DumpSymbols will actually read debugging 171 // information from. Normally, this is the same as input_pathname_, but if 172 // filename refers to a dSYM bundle, then this is the resource file 173 // within that bundle. 174 std::string object_filename_; 175 176 // The complete contents of object_filename_, mapped into memory. 177 scoped_array<uint8_t> contents_; 178 179 // A vector of SuperFatArch structures describing the object files 180 // object_filename_ contains. If object_filename_ refers to a fat binary, 181 // this may have more than one element; if it refers to a Mach-O file, this 182 // has exactly one element. 183 vector<SuperFatArch> object_files_; 184 185 // The object file in object_files_ selected to dump, or NULL if 186 // SetArchitecture hasn't been called yet. 187 const SuperFatArch *selected_object_file_; 188 189 // A string that identifies the selected object file, for use in error 190 // messages. This is usually object_filename_, but if that refers to a 191 // fat binary, it includes an indication of the particular architecture 192 // within that binary. 193 string selected_object_name_; 194 }; 195 196 } // namespace google_breakpad 197