summaryrefslogtreecommitdiffstats
blob: 9463f7dc0ce529f7a8e7013061850d5c3fca4360 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// -*- mode: c++ -*-

// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>

// dump_syms.h: Declaration of google_breakpad::DumpSymbols, a class for
// reading debugging information from Mach-O files and writing it out as a
// Breakpad symbol file.

#include <mach-o/loader.h>
#include <stdio.h>
#include <stdlib.h>

#include <ostream>
#include <string>
#include <vector>

#include "common/byte_cursor.h"
#include "common/mac/macho_reader.h"
#include "common/mac/super_fat_arch.h"
#include "common/module.h"
#include "common/scoped_ptr.h"
#include "common/symbol_data.h"

namespace google_breakpad {

class DumpSymbols {
 public:
  DumpSymbols(SymbolData symbol_data, bool handle_inter_cu_refs)
      : symbol_data_(symbol_data),
        handle_inter_cu_refs_(handle_inter_cu_refs),
        input_pathname_(),
        object_filename_(),
        contents_(),
        object_files_(),
        selected_object_file_(),
        selected_object_name_() { }
  ~DumpSymbols() {
  }

  // Prepare to read debugging information from |filename|. |filename| may be
  // the name of a universal binary, a Mach-O file, or a dSYM bundle
  // containing either of the above. On success, return true; if there is a
  // problem reading |filename|, report it and return false.
  bool Read(const std::string &filename);

  // If this dumper's file includes an object file for |cpu_type| and
  // |cpu_subtype|, then select that object file for dumping, and return
  // true. Otherwise, return false, and leave this dumper's selected
  // architecture unchanged.
  //
  // By default, if this dumper's file contains only one object file, then
  // the dumper will dump those symbols; and if it contains more than one
  // object file, then the dumper will dump the object file whose
  // architecture matches that of this dumper program.
  bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);

  // If this dumper's file includes an object file for |arch_name|, then select
  // that object file for dumping, and return true. Otherwise, return false,
  // and leave this dumper's selected architecture unchanged.
  //
  // By default, if this dumper's file contains only one object file, then
  // the dumper will dump those symbols; and if it contains more than one
  // object file, then the dumper will dump the object file whose
  // architecture matches that of this dumper program.
  bool SetArchitecture(const std::string &arch_name);

  // Return a pointer to an array of SuperFatArch structures describing the
  // object files contained in this dumper's file. Set *|count| to the number
  // of elements in the array. The returned array is owned by this DumpSymbols
  // instance.
  //
  // If there are no available architectures, this function
  // may return NULL.
  const SuperFatArch* AvailableArchitectures(size_t *count) {
    *count = object_files_.size();
    if (object_files_.size() > 0)
      return &object_files_[0];
    return NULL;
  }

  // Read the selected object file's debugging information, and write it out to
  // |stream|. Return true on success; if an error occurs, report it and
  // return false.
  bool WriteSymbolFile(std::ostream &stream);

  // Read the selected object file's debugging information, and write out the
  // header only to |stream|. Return true on success; if an error occurs, report
  // it and return false.
  bool WriteSymbolFileHeader(std::ostream &stream);

  // As above, but simply return the debugging information in module
  // instead of writing it to a stream. The caller owns the resulting
  // module object and must delete it when finished.
  bool ReadSymbolData(Module** module);

 private:
  // Used internally.
  class DumperLineToModule;
  class LoadCommandDumper;

  // This method behaves similarly to NXFindBestFatArch, but it supports
  // SuperFatArch.
  SuperFatArch* FindBestMatchForArchitecture(
      cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);

  // Return an identifier string for the file this DumpSymbols is dumping.
  std::string Identifier();


  // Creates an empty module object.
  bool CreateEmptyModule(scoped_ptr<Module>& module);

  // Read debugging information from |dwarf_sections|, which was taken from
  // |macho_reader|, and add it to |module|. On success, return true;
  // on failure, report the problem and return false.
  bool ReadDwarf(google_breakpad::Module *module,
                 const mach_o::Reader &macho_reader,
                 const mach_o::SectionMap &dwarf_sections,
                 bool handle_inter_cu_refs) const;

  // Read DWARF CFI or .eh_frame data from |section|, belonging to
  // |macho_reader|, and record it in |module|.  If |eh_frame| is true,
  // then the data is .eh_frame-format data; otherwise, it is standard DWARF
  // .debug_frame data. On success, return true; on failure, report
  // the problem and return false.
  bool ReadCFI(google_breakpad::Module *module,
               const mach_o::Reader &macho_reader,
               const mach_o::Section &section,
               bool eh_frame) const;

  // The selection of what type of symbol data to read/write.
  const SymbolData symbol_data_;

  // Whether to handle references between compilation units.
  const bool handle_inter_cu_refs_;

  // The name of the file or bundle whose symbols this will dump.
  // This is the path given to Read, for use in error messages.
  std::string input_pathname_;

  // The name of the file this DumpSymbols will actually read debugging
  // information from. Normally, this is the same as input_pathname_, but if
  // filename refers to a dSYM bundle, then this is the resource file
  // within that bundle.
  std::string object_filename_;

  // The complete contents of object_filename_, mapped into memory.
  scoped_array<uint8_t> contents_;

  // A vector of SuperFatArch structures describing the object files
  // object_filename_ contains. If object_filename_ refers to a fat binary,
  // this may have more than one element; if it refers to a Mach-O file, this
  // has exactly one element.
  vector<SuperFatArch> object_files_;

  // The object file in object_files_ selected to dump, or NULL if
  // SetArchitecture hasn't been called yet.
  const SuperFatArch *selected_object_file_;

  // A string that identifies the selected object file, for use in error
  // messages.  This is usually object_filename_, but if that refers to a
  // fat binary, it includes an indication of the particular architecture
  // within that binary.
  string selected_object_name_;
};

}  // namespace google_breakpad