1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,280 @@ 1.4 +// -*- mode: c++ -*- 1.5 + 1.6 +// Copyright (c) 2010 Google Inc. 1.7 +// All rights reserved. 1.8 +// 1.9 +// Redistribution and use in source and binary forms, with or without 1.10 +// modification, are permitted provided that the following conditions are 1.11 +// met: 1.12 +// 1.13 +// * Redistributions of source code must retain the above copyright 1.14 +// notice, this list of conditions and the following disclaimer. 1.15 +// * Redistributions in binary form must reproduce the above 1.16 +// copyright notice, this list of conditions and the following disclaimer 1.17 +// in the documentation and/or other materials provided with the 1.18 +// distribution. 1.19 +// * Neither the name of Google Inc. nor the names of its 1.20 +// contributors may be used to endorse or promote products derived from 1.21 +// this software without specific prior written permission. 1.22 +// 1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 + 1.35 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.36 + 1.37 +// Add DWARF debugging information to a Breakpad symbol file. This 1.38 +// file defines the DwarfCUToModule class, which accepts parsed DWARF 1.39 +// data and populates a google_breakpad::Module with the results; the 1.40 +// Module can then write its contents as a Breakpad symbol file. 1.41 + 1.42 +#ifndef COMMON_LINUX_DWARF_CU_TO_MODULE_H__ 1.43 +#define COMMON_LINUX_DWARF_CU_TO_MODULE_H__ 1.44 + 1.45 +#include <string> 1.46 + 1.47 +#include "common/language.h" 1.48 +#include "common/module.h" 1.49 +#include "common/dwarf/bytereader.h" 1.50 +#include "common/dwarf/dwarf2diehandler.h" 1.51 +#include "common/dwarf/dwarf2reader.h" 1.52 +#include "common/using_std_string.h" 1.53 + 1.54 +namespace google_breakpad { 1.55 + 1.56 +using dwarf2reader::DwarfAttribute; 1.57 +using dwarf2reader::DwarfForm; 1.58 +using dwarf2reader::DwarfLanguage; 1.59 +using dwarf2reader::DwarfTag; 1.60 + 1.61 +// Populate a google_breakpad::Module with DWARF debugging information. 1.62 +// 1.63 +// An instance of this class can be provided as a handler to a 1.64 +// dwarf2reader::DIEDispatcher, which can in turn be a handler for a 1.65 +// dwarf2reader::CompilationUnit DWARF parser. The handler uses the results 1.66 +// of parsing to populate a google_breakpad::Module with source file, 1.67 +// function, and source line information. 1.68 +class DwarfCUToModule: public dwarf2reader::RootDIEHandler { 1.69 + struct FilePrivate; 1.70 + public: 1.71 + 1.72 + // Information global to the DWARF-bearing file we are processing, 1.73 + // for use by DwarfCUToModule. Each DwarfCUToModule instance deals 1.74 + // with a single compilation unit within the file, but information 1.75 + // global to the whole file is held here. The client is responsible 1.76 + // for filling it in appropriately (except for the 'file_private' 1.77 + // field, which the constructor and destructor take care of), and 1.78 + // then providing it to the DwarfCUToModule instance for each 1.79 + // compilation unit we process in that file. 1.80 + struct FileContext { 1.81 + FileContext(const string &filename_arg, Module *module_arg); 1.82 + ~FileContext(); 1.83 + 1.84 + // The name of this file, for use in error messages. 1.85 + string filename; 1.86 + 1.87 + // A map of this file's sections, used for finding other DWARF 1.88 + // sections that the .debug_info section may refer to. 1.89 + dwarf2reader::SectionMap section_map; 1.90 + 1.91 + // The Module to which we're contributing definitions. 1.92 + Module *module; 1.93 + 1.94 + // Inter-compilation unit data used internally by the handlers. 1.95 + FilePrivate *file_private; 1.96 + }; 1.97 + 1.98 + // An abstract base class for handlers that handle DWARF line data 1.99 + // for DwarfCUToModule. DwarfCUToModule could certainly just use 1.100 + // dwarf2reader::LineInfo itself directly, but decoupling things 1.101 + // this way makes unit testing a little easier. 1.102 + class LineToModuleHandler { 1.103 + public: 1.104 + LineToModuleHandler() { } 1.105 + virtual ~LineToModuleHandler() { } 1.106 + 1.107 + // Called at the beginning of a new compilation unit, prior to calling 1.108 + // ReadProgram(). compilation_dir will indicate the path that the 1.109 + // current compilation unit was compiled in, consistent with the 1.110 + // DW_AT_comp_dir DIE. 1.111 + virtual void StartCompilationUnit(const string& compilation_dir) = 0; 1.112 + 1.113 + // Populate MODULE and LINES with source file names and code/line 1.114 + // mappings, given a pointer to some DWARF line number data 1.115 + // PROGRAM, and an overestimate of its size. Add no zero-length 1.116 + // lines to LINES. 1.117 + virtual void ReadProgram(const char *program, uint64 length, 1.118 + Module *module, vector<Module::Line> *lines) = 0; 1.119 + }; 1.120 + 1.121 + // The interface DwarfCUToModule uses to report warnings. The member 1.122 + // function definitions for this class write messages to stderr, but 1.123 + // you can override them if you'd like to detect or report these 1.124 + // conditions yourself. 1.125 + class WarningReporter { 1.126 + public: 1.127 + // Warn about problems in the DWARF file FILENAME, in the 1.128 + // compilation unit at OFFSET. 1.129 + WarningReporter(const string &filename, uint64 cu_offset) 1.130 + : filename_(filename), cu_offset_(cu_offset), printed_cu_header_(false), 1.131 + printed_unpaired_header_(false), 1.132 + uncovered_warnings_enabled_(false) { } 1.133 + virtual ~WarningReporter() { } 1.134 + 1.135 + // Set the name of the compilation unit we're processing to NAME. 1.136 + virtual void SetCUName(const string &name) { cu_name_ = name; } 1.137 + 1.138 + // Accessor and setter for uncovered_warnings_enabled_. 1.139 + // UncoveredFunction and UncoveredLine only report a problem if that is 1.140 + // true. By default, these warnings are disabled, because those 1.141 + // conditions occur occasionally in healthy code. 1.142 + virtual bool uncovered_warnings_enabled() const { 1.143 + return uncovered_warnings_enabled_; 1.144 + } 1.145 + virtual void set_uncovered_warnings_enabled(bool value) { 1.146 + uncovered_warnings_enabled_ = value; 1.147 + } 1.148 + 1.149 + // A DW_AT_specification in the DIE at OFFSET refers to a DIE we 1.150 + // haven't processed yet, or that wasn't marked as a declaration, 1.151 + // at TARGET. 1.152 + virtual void UnknownSpecification(uint64 offset, uint64 target); 1.153 + 1.154 + // A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we 1.155 + // haven't processed yet, or that wasn't marked as inline, at TARGET. 1.156 + virtual void UnknownAbstractOrigin(uint64 offset, uint64 target); 1.157 + 1.158 + // We were unable to find the DWARF section named SECTION_NAME. 1.159 + virtual void MissingSection(const string §ion_name); 1.160 + 1.161 + // The CU's DW_AT_stmt_list offset OFFSET is bogus. 1.162 + virtual void BadLineInfoOffset(uint64 offset); 1.163 + 1.164 + // FUNCTION includes code covered by no line number data. 1.165 + virtual void UncoveredFunction(const Module::Function &function); 1.166 + 1.167 + // Line number NUMBER in LINE_FILE, of length LENGTH, includes code 1.168 + // covered by no function. 1.169 + virtual void UncoveredLine(const Module::Line &line); 1.170 + 1.171 + // The DW_TAG_subprogram DIE at OFFSET has no name specified directly 1.172 + // in the DIE, nor via a DW_AT_specification or DW_AT_abstract_origin 1.173 + // link. 1.174 + virtual void UnnamedFunction(uint64 offset); 1.175 + 1.176 + protected: 1.177 + string filename_; 1.178 + uint64 cu_offset_; 1.179 + string cu_name_; 1.180 + bool printed_cu_header_; 1.181 + bool printed_unpaired_header_; 1.182 + bool uncovered_warnings_enabled_; 1.183 + 1.184 + private: 1.185 + // Print a per-CU heading, once. 1.186 + void CUHeading(); 1.187 + // Print an unpaired function/line heading, once. 1.188 + void UncoveredHeading(); 1.189 + }; 1.190 + 1.191 + // Create a DWARF debugging info handler for a compilation unit 1.192 + // within FILE_CONTEXT. This uses information received from the 1.193 + // dwarf2reader::CompilationUnit DWARF parser to populate 1.194 + // FILE_CONTEXT->module. Use LINE_READER to handle the compilation 1.195 + // unit's line number data. Use REPORTER to report problems with the 1.196 + // data we find. 1.197 + DwarfCUToModule(FileContext *file_context, 1.198 + LineToModuleHandler *line_reader, 1.199 + WarningReporter *reporter); 1.200 + ~DwarfCUToModule(); 1.201 + 1.202 + void ProcessAttributeSigned(enum DwarfAttribute attr, 1.203 + enum DwarfForm form, 1.204 + int64 data); 1.205 + void ProcessAttributeUnsigned(enum DwarfAttribute attr, 1.206 + enum DwarfForm form, 1.207 + uint64 data); 1.208 + void ProcessAttributeString(enum DwarfAttribute attr, 1.209 + enum DwarfForm form, 1.210 + const string &data); 1.211 + bool EndAttributes(); 1.212 + DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag); 1.213 + 1.214 + // Assign all our source Lines to the Functions that cover their 1.215 + // addresses, and then add them to module_. 1.216 + void Finish(); 1.217 + 1.218 + bool StartCompilationUnit(uint64 offset, uint8 address_size, 1.219 + uint8 offset_size, uint64 cu_length, 1.220 + uint8 dwarf_version); 1.221 + bool StartRootDIE(uint64 offset, enum DwarfTag tag); 1.222 + 1.223 + private: 1.224 + 1.225 + // Used internally by the handler. Full definitions are in 1.226 + // dwarf_cu_to_module.cc. 1.227 + struct FilePrivate; 1.228 + struct Specification; 1.229 + struct CUContext; 1.230 + struct DIEContext; 1.231 + class GenericDIEHandler; 1.232 + class FuncHandler; 1.233 + class NamedScopeHandler; 1.234 + 1.235 + // A map from section offsets to specifications. 1.236 + typedef map<uint64, Specification> SpecificationByOffset; 1.237 + 1.238 + // Set this compilation unit's source language to LANGUAGE. 1.239 + void SetLanguage(DwarfLanguage language); 1.240 + 1.241 + // Read source line information at OFFSET in the .debug_line 1.242 + // section. Record source files in module_, but record source lines 1.243 + // in lines_; we apportion them to functions in 1.244 + // AssignLinesToFunctions. 1.245 + void ReadSourceLines(uint64 offset); 1.246 + 1.247 + // Assign the lines in lines_ to the individual line lists of the 1.248 + // functions in functions_. (DWARF line information maps an entire 1.249 + // compilation unit at a time, and gives no indication of which 1.250 + // lines belong to which functions, beyond their addresses.) 1.251 + void AssignLinesToFunctions(); 1.252 + 1.253 + // The only reason cu_context_ and child_context_ are pointers is 1.254 + // that we want to keep their definitions private to 1.255 + // dwarf_cu_to_module.cc, instead of listing them all here. They are 1.256 + // owned by this DwarfCUToModule: the constructor sets them, and the 1.257 + // destructor deletes them. 1.258 + 1.259 + // The handler to use to handle line number data. 1.260 + LineToModuleHandler *line_reader_; 1.261 + 1.262 + // This compilation unit's context. 1.263 + CUContext *cu_context_; 1.264 + 1.265 + // A context for our children. 1.266 + DIEContext *child_context_; 1.267 + 1.268 + // True if this compilation unit has source line information. 1.269 + bool has_source_line_info_; 1.270 + 1.271 + // The offset of this compilation unit's line number information in 1.272 + // the .debug_line section. 1.273 + uint64 source_line_offset_; 1.274 + 1.275 + // The line numbers we have seen thus far. We accumulate these here 1.276 + // during parsing. Then, in Finish, we call AssignLinesToFunctions 1.277 + // to dole them out to the appropriate functions. 1.278 + vector<Module::Line> lines_; 1.279 +}; 1.280 + 1.281 +} // namespace google_breakpad 1.282 + 1.283 +#endif // COMMON_LINUX_DWARF_CU_TO_MODULE_H__