1 : // -*- mode: c++ -*-
2 :
3 : // Copyright (c) 2010 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 : // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
33 :
34 : // Add DWARF debugging information to a Breakpad symbol file. This
35 : // file defines the DwarfCUToModule class, which accepts parsed DWARF
36 : // data and populates a google_breakpad::Module with the results; the
37 : // Module can then write its contents as a Breakpad symbol file.
38 :
39 : #ifndef COMMON_LINUX_DWARF_CU_TO_MODULE_H__
40 : #define COMMON_LINUX_DWARF_CU_TO_MODULE_H__
41 :
42 : #include <string>
43 :
44 : #include "common/language.h"
45 : #include "common/module.h"
46 : #include "common/dwarf/bytereader.h"
47 : #include "common/dwarf/dwarf2diehandler.h"
48 : #include "common/dwarf/dwarf2reader.h"
49 :
50 : namespace google_breakpad {
51 :
52 : using dwarf2reader::AttributeList;
53 : using dwarf2reader::DwarfAttribute;
54 : using dwarf2reader::DwarfForm;
55 : using dwarf2reader::DwarfLanguage;
56 : using dwarf2reader::DwarfTag;
57 :
58 : // Populate a google_breakpad::Module with DWARF debugging information.
59 : //
60 : // An instance of this class can be provided as a handler to a
61 : // dwarf2reader::CompilationUnit DWARF parser. The handler uses the
62 : // results of parsing to populate a google_breakpad::Module with
63 : // source file, function, and source line information.
64 : class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
65 : struct FilePrivate;
66 : public:
67 :
68 : // Information global to the DWARF-bearing file we are processing,
69 : // for use by DwarfCUToModule. Each DwarfCUToModule instance deals
70 : // with a single compilation unit within the file, but information
71 : // global to the whole file is held here. The client is responsible
72 : // for filling it in appropriately (except for the 'file_private'
73 : // field, which the constructor and destructor take care of), and
74 : // then providing it to the DwarfCUToModule instance for each
75 : // compilation unit we process in that file.
76 : struct FileContext {
77 : FileContext(const string &filename_arg, Module *module_arg);
78 : ~FileContext();
79 :
80 : // The name of this file, for use in error messages.
81 : string filename;
82 :
83 : // A map of this file's sections, used for finding other DWARF
84 : // sections that the .debug_info section may refer to.
85 : dwarf2reader::SectionMap section_map;
86 :
87 : // The Module to which we're contributing definitions.
88 : Module *module;
89 :
90 : // Inter-compilation unit data used internally by the handlers.
91 : FilePrivate *file_private;
92 : };
93 :
94 : // An abstract base class for functors that handle DWARF line data
95 : // for DwarfCUToModule. DwarfCUToModule could certainly just use
96 : // dwarf2reader::LineInfo itself directly, but decoupling things
97 : // this way makes unit testing a little easier.
98 : class LineToModuleFunctor {
99 : public:
100 124 : LineToModuleFunctor() { }
101 124 : virtual ~LineToModuleFunctor() { }
102 :
103 : // Populate MODULE and LINES with source file names and code/line
104 : // mappings, given a pointer to some DWARF line number data
105 : // PROGRAM, and an overestimate of its size. Add no zero-length
106 : // lines to LINES.
107 : virtual void operator()(const char *program, uint64 length,
108 : Module *module, vector<Module::Line> *lines) = 0;
109 : };
110 :
111 : // The interface DwarfCUToModule uses to report warnings. The member
112 : // function definitions for this class write messages to stderr, but
113 : // you can override them if you'd like to detect or report these
114 : // conditions yourself.
115 : class WarningReporter {
116 : public:
117 : // Warn about problems in the DWARF file FILENAME, in the
118 : // compilation unit at OFFSET.
119 4773 : WarningReporter(const string &filename, uint64 cu_offset)
120 : : filename_(filename), cu_offset_(cu_offset), printed_cu_header_(false),
121 : printed_unpaired_header_(false),
122 4773 : uncovered_warnings_enabled_(false) { }
123 4773 : virtual ~WarningReporter() { }
124 :
125 : // Set the name of the compilation unit we're processing to NAME.
126 4773 : virtual void SetCUName(const string &name) { cu_name_ = name; }
127 :
128 : // Accessor and setter for uncovered_warnings_enabled_.
129 : // UncoveredFunction and UncoveredLine only report a problem if that is
130 : // true. By default, these warnings are disabled, because those
131 : // conditions occur occasionally in healthy code.
132 0 : virtual bool uncovered_warnings_enabled() const {
133 0 : return uncovered_warnings_enabled_;
134 : }
135 0 : virtual void set_uncovered_warnings_enabled(bool value) {
136 0 : uncovered_warnings_enabled_ = value;
137 0 : }
138 :
139 : // A DW_AT_specification in the DIE at OFFSET refers to a DIE we
140 : // haven't processed yet, or that wasn't marked as a declaration,
141 : // at TARGET.
142 : virtual void UnknownSpecification(uint64 offset, uint64 target);
143 :
144 : // A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we
145 : // haven't processed yet, or that wasn't marked as inline, at TARGET.
146 : virtual void UnknownAbstractOrigin(uint64 offset, uint64 target);
147 :
148 : // We were unable to find the DWARF section named SECTION_NAME.
149 : virtual void MissingSection(const string §ion_name);
150 :
151 : // The CU's DW_AT_stmt_list offset OFFSET is bogus.
152 : virtual void BadLineInfoOffset(uint64 offset);
153 :
154 : // FUNCTION includes code covered by no line number data.
155 : virtual void UncoveredFunction(const Module::Function &function);
156 :
157 : // Line number NUMBER in LINE_FILE, of length LENGTH, includes code
158 : // covered by no function.
159 : virtual void UncoveredLine(const Module::Line &line);
160 :
161 : protected:
162 : string filename_;
163 : uint64 cu_offset_;
164 : string cu_name_;
165 : bool printed_cu_header_;
166 : bool printed_unpaired_header_;
167 : bool uncovered_warnings_enabled_;
168 :
169 : private:
170 : // Print a per-CU heading, once.
171 : void CUHeading();
172 : // Print an unpaired function/line heading, once.
173 : void UncoveredHeading();
174 : };
175 :
176 : // Create a DWARF debugging info handler for a compilation unit
177 : // within FILE_CONTEXT. This uses information received from the
178 : // dwarf2reader::CompilationUnit DWARF parser to populate
179 : // FILE_CONTEXT->module. Use LINE_READER to handle the compilation
180 : // unit's line number data. Use REPORTER to report problems with the
181 : // data we find.
182 : DwarfCUToModule(FileContext *file_context,
183 : LineToModuleFunctor *line_reader,
184 : WarningReporter *reporter);
185 : ~DwarfCUToModule();
186 :
187 : void ProcessAttributeSigned(enum DwarfAttribute attr,
188 : enum DwarfForm form,
189 : int64 data);
190 : void ProcessAttributeUnsigned(enum DwarfAttribute attr,
191 : enum DwarfForm form,
192 : uint64 data);
193 : void ProcessAttributeString(enum DwarfAttribute attr,
194 : enum DwarfForm form,
195 : const string &data);
196 : bool EndAttributes();
197 : DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
198 : const AttributeList &attrs);
199 :
200 : // Assign all our source Lines to the Functions that cover their
201 : // addresses, and then add them to module_.
202 : void Finish();
203 :
204 : bool StartCompilationUnit(uint64 offset, uint8 address_size,
205 : uint8 offset_size, uint64 cu_length,
206 : uint8 dwarf_version);
207 : bool StartRootDIE(uint64 offset, enum DwarfTag tag,
208 : const AttributeList& attrs);
209 :
210 : private:
211 :
212 : // Used internally by the handler. Full definitions are in
213 : // dwarf_cu_to_module.cc.
214 : struct FilePrivate;
215 : struct Specification;
216 : struct CUContext;
217 : struct DIEContext;
218 : class GenericDIEHandler;
219 : class FuncHandler;
220 : class NamedScopeHandler;
221 :
222 : // A map from section offsets to specifications.
223 : typedef map<uint64, Specification> SpecificationByOffset;
224 :
225 : // Set this compilation unit's source language to LANGUAGE.
226 : void SetLanguage(DwarfLanguage language);
227 :
228 : // Read source line information at OFFSET in the .debug_line
229 : // section. Record source files in module_, but record source lines
230 : // in lines_; we apportion them to functions in
231 : // AssignLinesToFunctions.
232 : void ReadSourceLines(uint64 offset);
233 :
234 : // Assign the lines in lines_ to the individual line lists of the
235 : // functions in functions_. (DWARF line information maps an entire
236 : // compilation unit at a time, and gives no indication of which
237 : // lines belong to which functions, beyond their addresses.)
238 : void AssignLinesToFunctions();
239 :
240 : // The only reason cu_context_ and child_context_ are pointers is
241 : // that we want to keep their definitions private to
242 : // dwarf_cu_to_module.cc, instead of listing them all here. They are
243 : // owned by this DwarfCUToModule: the constructor sets them, and the
244 : // destructor deletes them.
245 :
246 : // The functor to use to handle line number data.
247 : LineToModuleFunctor *line_reader_;
248 :
249 : // This compilation unit's context.
250 : CUContext *cu_context_;
251 :
252 : // A context for our children.
253 : DIEContext *child_context_;
254 :
255 : // True if this compilation unit has source line information.
256 : bool has_source_line_info_;
257 :
258 : // The offset of this compilation unit's line number information in
259 : // the .debug_line section.
260 : uint64 source_line_offset_;
261 :
262 : // The line numbers we have seen thus far. We accumulate these here
263 : // during parsing. Then, in Finish, we call AssignLinesToFunctions
264 : // to dole them out to the appropriate functions.
265 : vector<Module::Line> lines_;
266 : };
267 :
268 : } // namespace google_breakpad
269 :
270 : #endif // COMMON_LINUX_DWARF_CU_TO_MODULE_H__
|