11adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek// -*- mode: c++ -*- 21adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 38d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org// Copyright (c) 2011, Google Inc. 49ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// All rights reserved. 59ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// 69ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// Redistribution and use in source and binary forms, with or without 79ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// modification, are permitted provided that the following conditions are 89ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// met: 99ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// 109ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// * Redistributions of source code must retain the above copyright 119ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// notice, this list of conditions and the following disclaimer. 129ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// * Redistributions in binary form must reproduce the above 139ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// copyright notice, this list of conditions and the following disclaimer 149ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// in the documentation and/or other materials provided with the 159ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// distribution. 169ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// * Neither the name of Google Inc. nor the names of its 179ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// contributors may be used to endorse or promote products derived from 189ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// this software without specific prior written permission. 199ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// 209ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 219ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 229ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 239ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 249ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 259ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 269ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 279ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 289ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 299ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 309ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 319ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis 321adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 331adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 341adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek// dump_syms.h: Declaration of google_breakpad::DumpSymbols, a class for 351adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek// reading debugging information from Mach-O files and writing it out as a 361adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek// Breakpad symbol file. 379ddb3ae9499634c2ec61b09d6358d4dc7ddf9f32waylonis 381adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include <Foundation/Foundation.h> 39cb4aa6b804d9c4a5d43aa50bfbc46257bc55c001nealsid#include <mach-o/loader.h> 401adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include <stdio.h> 411adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include <stdlib.h> 421adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 4348550041f9663bd13cb805cf770b7d1ddcb1514ated.mielczarek#include <ostream> 441adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include <string> 451adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include <vector> 461adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 471adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include "common/byte_cursor.h" 481adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include "common/mac/macho_reader.h" 491adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek#include "common/module.h" 5006e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com#include "common/symbol_data.h" 511adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 521adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczareknamespace google_breakpad { 531adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 541adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarekclass DumpSymbols { 551adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek public: 5665cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org DumpSymbols(SymbolData symbol_data, bool handle_inter_cu_refs) 5706e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com : symbol_data_(symbol_data), 5865cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org handle_inter_cu_refs_(handle_inter_cu_refs), 5906e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com input_pathname_(), 608d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org object_filename_(), 611adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek contents_(), 621adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek selected_object_file_(), 631adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek selected_object_name_() { } 641adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek ~DumpSymbols() { 651adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek [input_pathname_ release]; 661adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek [object_filename_ release]; 671adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek [contents_ release]; 681adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek } 691adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 701adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // Prepare to read debugging information from |filename|. |filename| may be 711adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // the name of a universal binary, a Mach-O file, or a dSYM bundle 721adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // containing either of the above. On success, return true; if there is a 731adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // problem reading |filename|, report it and return false. 741adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // 751adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // (This class uses NSString for filenames and related values, 761adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // because the Mac Foundation framework seems to support 771adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // filename-related operations more fully on NSString values.) 781adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek bool Read(NSString *filename); 791adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 801adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // If this dumper's file includes an object file for |cpu_type| and 811adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // |cpu_subtype|, then select that object file for dumping, and return 821adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // true. Otherwise, return false, and leave this dumper's selected 831adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // architecture unchanged. 841adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // 851adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // By default, if this dumper's file contains only one object file, then 861adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // the dumper will dump those symbols; and if it contains more than one 871adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // object file, then the dumper will dump the object file whose 881adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // architecture matches that of this dumper program. 891adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); 908d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org 918d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org // If this dumper's file includes an object file for |arch_name|, then select 928d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org // that object file for dumping, and return true. Otherwise, return false, 934ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach // and leave this dumper's selected architecture unchanged. 944ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach // 954ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach // By default, if this dumper's file contains only one object file, then 964ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach // the dumper will dump those symbols; and if it contains more than one 974ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach // object file, then the dumper will dump the object file whose 984ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach // architecture matches that of this dumper program. 994ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach bool SetArchitecture(const std::string &arch_name); 1008d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org 1011adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // Return a pointer to an array of 'struct fat_arch' structures, 1021adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // describing the object files contained in this dumper's file. Set 1031adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // *|count| to the number of elements in the array. The returned array is 1041adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // owned by this DumpSymbols instance. 1051adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // 1061adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // If there are no available architectures, this function 1071adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // may return NULL. 1081adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek const struct fat_arch *AvailableArchitectures(size_t *count) { 1091adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek *count = object_files_.size(); 1101adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek if (object_files_.size() > 0) 1111adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek return &object_files_[0]; 1121adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek return NULL; 1131adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek } 1141adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1158d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org // Read the selected object file's debugging information, and write it out to 11606e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com // |stream|. Return true on success; if an error occurs, report it and 11706e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com // return false. 11806e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com bool WriteSymbolFile(std::ostream &stream); 1191adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 12068e2449df39b027ed0b3fd395d821d243de1bafeted.mielczarek@gmail.com // As above, but simply return the debugging information in module 12168e2449df39b027ed0b3fd395d821d243de1bafeted.mielczarek@gmail.com // instead of writing it to a stream. The caller owns the resulting 12268e2449df39b027ed0b3fd395d821d243de1bafeted.mielczarek@gmail.com // module object and must delete it when finished. 12368e2449df39b027ed0b3fd395d821d243de1bafeted.mielczarek@gmail.com bool ReadSymbolData(Module** module); 12468e2449df39b027ed0b3fd395d821d243de1bafeted.mielczarek@gmail.com 1251adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek private: 1261adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // Used internally. 1271adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek class DumperLineToModule; 1281adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek class LoadCommandDumper; 1291adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1301adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // Return an identifier string for the file this DumpSymbols is dumping. 1311adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek std::string Identifier(); 1321adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1331adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // Read debugging information from |dwarf_sections|, which was taken from 1341adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // |macho_reader|, and add it to |module|. On success, return true; 1351adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // on failure, report the problem and return false. 1361adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek bool ReadDwarf(google_breakpad::Module *module, 1371adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek const mach_o::Reader &macho_reader, 13865cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org const mach_o::SectionMap &dwarf_sections, 13965cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org bool handle_inter_cu_refs) const; 1401adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1411adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // Read DWARF CFI or .eh_frame data from |section|, belonging to 1421adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // |macho_reader|, and record it in |module|. If |eh_frame| is true, 1431adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // then the data is .eh_frame-format data; otherwise, it is standard DWARF 1441adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // .debug_frame data. On success, return true; on failure, report 1451adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // the problem and return false. 1461adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek bool ReadCFI(google_breakpad::Module *module, 1471adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek const mach_o::Reader &macho_reader, 1481adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek const mach_o::Section §ion, 1491adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek bool eh_frame) const; 1501adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 15106e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com // The selection of what type of symbol data to read/write. 15206e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com const SymbolData symbol_data_; 15306e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com 15465cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org // Whether to handle references between compilation units. 15565cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org const bool handle_inter_cu_refs_; 15665cecb6f4ff63fd7819ea9fb32bc6920589d670ethestig@chromium.org 1571adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // The name of the file or bundle whose symbols this will dump. 1581adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // This is the path given to Read, for use in error messages. 1591adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek NSString *input_pathname_; 1601adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1611adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // The name of the file this DumpSymbols will actually read debugging 1621adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // information from. Normally, this is the same as input_pathname_, but if 1631adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // filename refers to a dSYM bundle, then this is the resource file 1641adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // within that bundle. 1651adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek NSString *object_filename_; 1661adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1671adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // The complete contents of object_filename_, mapped into memory. 1681adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek NSData *contents_; 1691adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1701adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // A vector of fat_arch structures describing the object files 1711adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // object_filename_ contains. If object_filename_ refers to a fat binary, 1721adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // this may have more than one element; if it refers to a Mach-O file, this 1731adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // has exactly one element. 1741adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek vector<struct fat_arch> object_files_; 1751adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1768d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org // The object file in object_files_ selected to dump, or NULL if 1771adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // SetArchitecture hasn't been called yet. 1781adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek const struct fat_arch *selected_object_file_; 1791adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1801adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // A string that identifies the selected object file, for use in error 1811adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // messages. This is usually object_filename_, but if that refers to a 1821adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // fat binary, it includes an indication of the particular architecture 1831adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek // within that binary. 1841adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek string selected_object_name_; 1851adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek}; 1861adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek 1871adc07f0ffd92068215567f5e1546a9c98e58e42ted.mielczarek} // namespace google_breakpad 188