michael@0: // -*- mode: C++ -*- michael@0: michael@0: // Copyright (c) 2010 Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: // Original author: Jim Blandy michael@0: michael@0: // dump_stabs.h: Define the StabsToModule class, which receives michael@0: // STABS debugging information from a parser and adds it to a Breakpad michael@0: // symbol file. michael@0: michael@0: #ifndef BREAKPAD_COMMON_STABS_TO_MODULE_H_ michael@0: #define BREAKPAD_COMMON_STABS_TO_MODULE_H_ michael@0: michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "common/module.h" michael@0: #include "common/stabs_reader.h" michael@0: #include "common/using_std_string.h" michael@0: michael@0: namespace google_breakpad { michael@0: michael@0: using std::vector; michael@0: michael@0: // A StabsToModule is a handler that receives parsed STABS debugging michael@0: // information from a StabsReader, and uses that to populate michael@0: // a Module. (All classes are in the google_breakpad namespace.) A michael@0: // Module represents the contents of a Breakpad symbol file, and knows michael@0: // how to write itself out as such. A StabsToModule thus acts as michael@0: // the bridge between STABS and Breakpad data. michael@0: // When processing Darwin Mach-O files, this also receives public linker michael@0: // symbols, like those found in system libraries. michael@0: class StabsToModule: public google_breakpad::StabsHandler { michael@0: public: michael@0: // Receive parsed debugging information from a StabsReader, and michael@0: // store it all in MODULE. michael@0: StabsToModule(Module *module) : michael@0: module_(module), michael@0: in_compilation_unit_(false), michael@0: comp_unit_base_address_(0), michael@0: current_function_(NULL), michael@0: current_source_file_(NULL), michael@0: current_source_file_name_(NULL) { } michael@0: ~StabsToModule(); michael@0: michael@0: // The standard StabsHandler virtual member functions. michael@0: bool StartCompilationUnit(const char *name, uint64_t address, michael@0: const char *build_directory); michael@0: bool EndCompilationUnit(uint64_t address); michael@0: bool StartFunction(const string &name, uint64_t address); michael@0: bool EndFunction(uint64_t address); michael@0: bool Line(uint64_t address, const char *name, int number); michael@0: bool Extern(const string &name, uint64_t address); michael@0: void Warning(const char *format, ...); michael@0: michael@0: // Do any final processing necessary to make module_ contain all the michael@0: // data provided by the STABS reader. michael@0: // michael@0: // Because STABS does not provide reliable size information for michael@0: // functions and lines, we need to make a pass over the data after michael@0: // processing all the STABS to compute those sizes. We take care of michael@0: // that here. michael@0: void Finalize(); michael@0: michael@0: private: michael@0: michael@0: // An arbitrary, but very large, size to use for functions whose michael@0: // size we can't compute properly. michael@0: static const uint64_t kFallbackSize = 0x10000000; michael@0: michael@0: // The module we're contributing debugging info to. michael@0: Module *module_; michael@0: michael@0: // The functions we've generated so far. We don't add these to michael@0: // module_ as we parse them. Instead, we wait until we've computed michael@0: // their ending address, and their lines' ending addresses. michael@0: // michael@0: // We could just stick them in module_ from the outset, but if michael@0: // module_ already contains data gathered from other debugging michael@0: // formats, that would complicate the size computation. michael@0: vector functions_; michael@0: michael@0: // Boundary addresses. STABS doesn't necessarily supply sizes for michael@0: // functions and lines, so we need to compute them ourselves by michael@0: // finding the next object. michael@0: vector boundaries_; michael@0: michael@0: // True if we are currently within a compilation unit: we have gotten a michael@0: // StartCompilationUnit call, but no matching EndCompilationUnit call michael@0: // yet. We use this for sanity checks. michael@0: bool in_compilation_unit_; michael@0: michael@0: // The base address of the current compilation unit. We use this to michael@0: // recognize functions we should omit from the symbol file. (If you michael@0: // know the details of why we omit these, please patch this michael@0: // comment.) michael@0: Module::Address comp_unit_base_address_; michael@0: michael@0: // The function we're currently contributing lines to. michael@0: Module::Function *current_function_; michael@0: michael@0: // The last Module::File we got a line number in. michael@0: Module::File *current_source_file_; michael@0: michael@0: // The pointer in the .stabstr section of the name that michael@0: // current_source_file_ is built from. This allows us to quickly michael@0: // recognize when the current line is in the same file as the michael@0: // previous one (which it usually is). michael@0: const char *current_source_file_name_; michael@0: }; michael@0: michael@0: } // namespace google_breakpad michael@0: michael@0: #endif // BREAKPAD_COMMON_STABS_TO_MODULE_H_