LCOV - app.info - toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc

LCOV - code coverage report
| Current view: | directory - toolkit/crashreporter/google-breakpad/src/common - stabs_reader.cc (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 119 | 0 | 0.0 %
| Date: | 2012-04-07 | Functions: | 7 | 0 | 0.0 %

           1                 : // Copyright (c) 2010 Google Inc. All Rights Reserved.
           2                 : //
           3                 : // Redistribution and use in source and binary forms, with or without
           4                 : // modification, are permitted provided that the following conditions are
           5                 : // met:
           6                 : //
           7                 : //     * Redistributions of source code must retain the above copyright
           8                 : // notice, this list of conditions and the following disclaimer.
           9                 : //     * Redistributions in binary form must reproduce the above
          10                 : // copyright notice, this list of conditions and the following disclaimer
          11                 : // in the documentation and/or other materials provided with the
          12                 : // distribution.
          13                 : //     * Neither the name of Google Inc. nor the names of its
          14                 : // contributors may be used to endorse or promote products derived from
          15                 : // this software without specific prior written permission.
          16                 : //
          17                 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
          18                 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
          19                 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
          20                 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
          21                 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
          22                 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
          23                 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
          24                 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
          25                 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
          26                 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
          27                 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
          28                 :
          29                 : // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
          30                 :
          31                 : // This file implements the google_breakpad::StabsReader class.
          32                 : // See stabs_reader.h.
          33                 :
          34                 : #include "common/stabs_reader.h"
          35                 :
          36                 : #include <assert.h>
          37                 : #include <stab.h>
          38                 : #include <string.h>
          39                 :
          40                 : using std::vector;
          41                 :
          42                 : namespace google_breakpad {
          43                 :
          44               0 : StabsReader::EntryIterator::EntryIterator(const ByteBuffer *buffer,
          45                 :                                           bool big_endian, size_t value_size)
          46               0 :     : value_size_(value_size), cursor_(buffer, big_endian) {
          47                 :   // Actually, we could handle weird sizes just fine, but they're
          48                 :   // probably mistakes --- expressed in bits, say.
          49               0 :   assert(value_size == 4 || value_size == 8);
          50               0 :   entry_.index = 0;
          51               0 :   Fetch();
          52               0 : }
          53                 :
          54               0 : void StabsReader::EntryIterator::Fetch() {
          55                 :   cursor_
          56               0 :       .Read(4, false, &entry_.name_offset)
          57               0 :       .Read(1, false, &entry_.type)
          58               0 :       .Read(1, false, &entry_.other)
          59               0 :       .Read(2, false, &entry_.descriptor)
          60               0 :       .Read(value_size_, false, &entry_.value);
          61               0 :   entry_.at_end = !cursor_;
          62               0 : }
          63                 :
          64               0 : StabsReader::StabsReader(const uint8_t *stab,    size_t stab_size,
          65                 :                          const uint8_t *stabstr, size_t stabstr_size,
          66                 :                          bool big_endian, size_t value_size, bool unitized,
          67                 :                          StabsHandler *handler)
          68                 :     : entries_(stab, stab_size),
          69                 :       strings_(stabstr, stabstr_size),
          70                 :       iterator_(&entries_, big_endian, value_size),
          71                 :       unitized_(unitized),
          72                 :       handler_(handler),
          73                 :       string_offset_(0),
          74                 :       next_cu_string_offset_(0),
          75               0 :       current_source_file_(NULL) { }
          76                 :
          77               0 : const char *StabsReader::SymbolString() {
          78               0 :   ptrdiff_t offset = string_offset_ + iterator_->name_offset;
          79               0 :   if (offset < 0 || (size_t) offset >= strings_.Size()) {
          80                 :     handler_->Warning("symbol %d: name offset outside the string section\n",
          81               0 :                       iterator_->index);
          82                 :     // Return our null string, to keep our promise about all names being
          83                 :     // taken from the string section.
          84               0 :     offset = 0;
          85                 :   }
          86               0 :   return reinterpret_cast<const char *>(strings_.start + offset);
          87                 : }
          88                 :
          89               0 : bool StabsReader::Process() {
          90               0 :   while (!iterator_->at_end) {
          91               0 :     if (iterator_->type == N_SO) {
          92               0 :       if (! ProcessCompilationUnit())
          93               0 :         return false;
          94               0 :     } else if (iterator_->type == N_UNDF && unitized_) {
          95                 :       // In unitized STABS (including Linux STABS, and pretty much anything
          96                 :       // else that puts STABS data in sections), at the head of each
          97                 :       // compilation unit's entries there is an N_UNDF stab giving the
          98                 :       // number of symbols in the compilation unit, and the number of bytes
          99                 :       // that compilation unit's strings take up in the .stabstr section.
         100                 :       // Each CU's strings are separate; the n_strx values are offsets
         101                 :       // within the current CU's portion of the .stabstr section.
         102                 :       //
         103                 :       // As an optimization, the GNU linker combines all the
         104                 :       // compilation units into one, with a single N_UNDF at the
         105                 :       // beginning. However, other linkers, like Gold, do not perform
         106                 :       // this optimization.
         107               0 :       string_offset_ = next_cu_string_offset_;
         108               0 :       next_cu_string_offset_ = iterator_->value;
         109               0 :       ++iterator_;
         110                 :     } else
         111               0 :       ++iterator_;
         112                 :   }
         113               0 :   return true;
         114                 : }
         115                 :
         116               0 : bool StabsReader::ProcessCompilationUnit() {
         117               0 :   assert(!iterator_->at_end && iterator_->type == N_SO);
         118                 :
         119                 :   // There may be an N_SO entry whose name ends with a slash,
         120                 :   // indicating the directory in which the compilation occurred.
         121                 :   // The build directory defaults to NULL.
         122               0 :   const char *build_directory = NULL;
         123                 :   {
         124               0 :     const char *name = SymbolString();
         125               0 :     if (name[0] && name[strlen(name) - 1] == '/') {
         126               0 :       build_directory = name;
         127               0 :       ++iterator_;
         128                 :     }
         129                 :   }
         130                 :
         131                 :   // We expect to see an N_SO entry with a filename next, indicating
         132                 :   // the start of the compilation unit.
         133                 :   {
         134               0 :     if (iterator_->at_end || iterator_->type != N_SO)
         135               0 :       return true;
         136               0 :     const char *name = SymbolString();
         137               0 :     if (name[0] == '\0') {
         138                 :       // This seems to be a stray end-of-compilation-unit marker;
         139                 :       // consume it, but don't report the end, since we didn't see a
         140                 :       // beginning.
         141               0 :       ++iterator_;
         142               0 :       return true;
         143                 :     }
         144               0 :     current_source_file_ = name;
         145                 :   }
         146                 :
         147               0 :   if (! handler_->StartCompilationUnit(current_source_file_,
         148               0 :                                        iterator_->value,
         149               0 :                                        build_directory))
         150               0 :     return false;
         151                 :
         152               0 :   ++iterator_;
         153                 :
         154                 :   // The STABS documentation says that some compilers may emit
         155                 :   // additional N_SO entries with names immediately following the
         156                 :   // first, and that they should be ignored.  However, the original
         157                 :   // Breakpad STABS reader doesn't ignore them, so we won't either.
         158                 :
         159                 :   // Process the body of the compilation unit, up to the next N_SO.
         160               0 :   while (!iterator_->at_end && iterator_->type != N_SO) {
         161               0 :     if (iterator_->type == N_FUN) {
         162               0 :       if (! ProcessFunction())
         163               0 :         return false;
         164               0 :     } else if (iterator_->type == N_SLINE) {
         165                 :       // Mac OS X STABS place SLINE records before functions.
         166                 :       Line line;
         167                 :       // The value of an N_SLINE entry that appears outside a function is
         168                 :       // the absolute address of the line.
         169               0 :       line.address = iterator_->value;
         170               0 :       line.filename = current_source_file_;
         171                 :       // The n_desc of a N_SLINE entry is the line number.  It's a
         172                 :       // signed 16-bit field; line numbers from 32768 to 65535 are
         173                 :       // stored as n-65536.
         174               0 :       line.number = (uint16_t) iterator_->descriptor;
         175               0 :       queued_lines_.push_back(line);
         176               0 :       ++iterator_;
         177               0 :     } else if (iterator_->type == N_SOL) {
         178               0 :       current_source_file_ = SymbolString();
         179               0 :       ++iterator_;
         180                 :     } else {
         181                 :       // Ignore anything else.
         182               0 :       ++iterator_;
         183                 :     }
         184                 :   }
         185                 :
         186                 :   // An N_SO with an empty name indicates the end of the compilation
         187                 :   // unit.  Default to zero.
         188               0 :   uint64_t ending_address = 0;
         189               0 :   if (!iterator_->at_end) {
         190               0 :     assert(iterator_->type == N_SO);
         191               0 :     const char *name = SymbolString();
         192               0 :     if (name[0] == '\0') {
         193               0 :       ending_address = iterator_->value;
         194               0 :       ++iterator_;
         195                 :     }
         196                 :   }
         197                 :
         198               0 :   if (! handler_->EndCompilationUnit(ending_address))
         199               0 :     return false;
         200                 :
         201               0 :   queued_lines_.clear();
         202                 :
         203               0 :   return true;
         204                 : }
         205                 :
         206               0 : bool StabsReader::ProcessFunction() {
         207               0 :   assert(!iterator_->at_end && iterator_->type == N_FUN);
         208                 :
         209               0 :   uint64_t function_address = iterator_->value;
         210                 :   // The STABS string for an N_FUN entry is the name of the function,
         211                 :   // followed by a colon, followed by type information for the
         212                 :   // function.  We want to pass the name alone to StartFunction.
         213               0 :   const char *stab_string = SymbolString();
         214               0 :   const char *name_end = strchr(stab_string, ':');
         215               0 :   if (! name_end)
         216               0 :     name_end = stab_string + strlen(stab_string);
         217               0 :   std::string name(stab_string, name_end - stab_string);
         218               0 :   if (! handler_->StartFunction(name, function_address))
         219               0 :     return false;
         220               0 :   ++iterator_;
         221                 :
         222                 :   // If there were any SLINE records given before the function, report them now.
         223               0 :   for (vector<Line>::const_iterator it = queued_lines_.begin();
         224               0 :        it != queued_lines_.end(); it++) {
         225               0 :     if (!handler_->Line(it->address, it->filename, it->number))
         226               0 :       return false;
         227                 :   }
         228               0 :   queued_lines_.clear();
         229                 :
         230               0 :   while (!iterator_->at_end) {
         231               0 :     if (iterator_->type == N_SO || iterator_->type == N_FUN)
         232               0 :       break;
         233               0 :     else if (iterator_->type == N_SLINE) {
         234                 :       // The value of an N_SLINE entry is the offset of the line from
         235                 :       // the function's start address.
         236               0 :       uint64_t line_address = function_address + iterator_->value;
         237                 :       // The n_desc of a N_SLINE entry is the line number.  It's a
         238                 :       // signed 16-bit field; line numbers from 32768 to 65535 are
         239                 :       // stored as n-65536.
         240               0 :       uint16_t line_number = iterator_->descriptor;
         241               0 :       if (! handler_->Line(line_address, current_source_file_, line_number))
         242               0 :         return false;
         243               0 :       ++iterator_;
         244               0 :     } else if (iterator_->type == N_SOL) {
         245               0 :       current_source_file_ = SymbolString();
         246               0 :       ++iterator_;
         247                 :     } else
         248                 :       // Ignore anything else.
         249               0 :       ++iterator_;
         250                 :   }
         251                 :
         252                 :   // We've reached the end of the function. See if we can figure out its
         253                 :   // ending address.
         254               0 :   uint64_t ending_address = 0;
         255               0 :   if (!iterator_->at_end) {
         256               0 :     assert(iterator_->type == N_SO || iterator_->type == N_FUN);
         257               0 :     if (iterator_->type == N_FUN) {
         258               0 :       const char *name = SymbolString();
         259               0 :       if (name[0] == '\0') {
         260                 :         // An N_FUN entry with no name is a terminator for this function;
         261                 :         // its value is the function's size.
         262               0 :         ending_address = function_address + iterator_->value;
         263               0 :         ++iterator_;
         264                 :       } else {
         265                 :         // An N_FUN entry with a name is the next function, and we can take
         266                 :         // its value as our ending address. Don't advance the iterator, as
         267                 :         // we'll use this symbol to start the next function as well.
         268               0 :         ending_address = iterator_->value;
         269                 :       }
         270                 :     } else {
         271                 :       // An N_SO entry could be an end-of-compilation-unit marker, or the
         272                 :       // start of the next compilation unit, but in either case, its value
         273                 :       // is our ending address. We don't advance the iterator;
         274                 :       // ProcessCompilationUnit will decide what to do with this symbol.
         275               0 :       ending_address = iterator_->value;
         276                 :     }
         277                 :   }
         278                 :
         279               0 :   if (! handler_->EndFunction(ending_address))
         280               0 :     return false;
         281                 :
         282               0 :   return true;
         283                 : }
         284                 :
         285                 : } // namespace google_breakpad

Generated by: LCOV version 1.7