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 &section,
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