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

LCOV - code coverage report
| Current view: | directory - toolkit/crashreporter/google-breakpad/src/common - module.cc (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 124 | 96 | 77.4 %
| Date: | 2012-04-07 | Functions: | 16 | 10 | 62.5 %

           1                 : // Copyright (c) 2010 Google Inc.
           2                 : // All rights reserved.
           3                 : //
           4                 : // Redistribution and use in source and binary forms, with or without
           5                 : // modification, are permitted provided that the following conditions are
           6                 : // met:
           7                 : //
           8                 : //     * Redistributions of source code must retain the above copyright
           9                 : // notice, this list of conditions and the following disclaimer.
          10                 : //     * Redistributions in binary form must reproduce the above
          11                 : // copyright notice, this list of conditions and the following disclaimer
          12                 : // in the documentation and/or other materials provided with the
          13                 : // distribution.
          14                 : //     * Neither the name of Google Inc. nor the names of its
          15                 : // contributors may be used to endorse or promote products derived from
          16                 : // this software without specific prior written permission.
          17                 : //
          18                 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
          19                 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
          20                 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
          21                 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
          22                 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
          23                 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
          24                 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
          25                 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
          26                 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
          27                 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
          28                 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
          29                 :
          30                 : // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
          31                 :
          32                 : // module.cc: Implement google_breakpad::Module.  See module.h.
          33                 :
          34                 : #include "common/module.h"
          35                 :
          36                 : #include <errno.h>
          37                 : #include <string.h>
          38                 :
          39                 : namespace google_breakpad {
          40                 :
          41             124 : Module::Module(const string &name, const string &os,
          42                 :                const string &architecture, const string &id) :
          43                 :     name_(name),
          44                 :     os_(os),
          45                 :     architecture_(architecture),
          46                 :     id_(id),
          47             124 :     load_address_(0) { }
          48                 :
          49             248 : Module::~Module() {
          50           23195 :   for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); it++)
          51           23071 :     delete it->second;
          52          618702 :   for (FunctionSet::iterator it = functions_.begin();
          53          309351 :        it != functions_.end(); it++)
          54          309227 :     delete *it;
          55         1412974 :   for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin();
          56          706487 :        it != stack_frame_entries_.end(); it++)
          57          706363 :     delete *it;
          58             124 : }
          59                 :
          60             124 : void Module::SetLoadAddress(Address address) {
          61             124 :   load_address_ = address;
          62             124 : }
          63                 :
          64          628546 : void Module::AddFunction(Function *function) {
          65          628546 :   std::pair<FunctionSet::iterator,bool> ret = functions_.insert(function);
          66          628546 :   if (!ret.second) {
          67                 :     // Free the duplicate we failed to insert because we own it.
          68          319319 :     delete function;
          69                 :   }
          70          628546 : }
          71                 :
          72            4845 : void Module::AddFunctions(vector<Function *>::iterator begin,
          73                 :                           vector<Function *>::iterator end) {
          74          633391 :   for (vector<Function *>::iterator it = begin; it != end; it++)
          75          628546 :     AddFunction(*it);
          76            4845 : }
          77                 :
          78          706363 : void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) {
          79          706363 :   stack_frame_entries_.push_back(stack_frame_entry);
          80          706363 : }
          81                 :
          82               0 : void Module::GetFunctions(vector<Function *> *vec,
          83                 :                           vector<Function *>::iterator i) {
          84               0 :   vec->insert(i, functions_.begin(), functions_.end());
          85               0 : }
          86                 :
          87          366538 : Module::File *Module::FindFile(const string &name) {
          88                 :   // A tricky bit here.  The key of each map entry needs to be a
          89                 :   // pointer to the entry's File's name string.  This means that we
          90                 :   // can't do the initial lookup with any operation that would create
          91                 :   // an empty entry for us if the name isn't found (like, say,
          92                 :   // operator[] or insert do), because such a created entry's key will
          93                 :   // be a pointer the string passed as our argument.  Since the key of
          94                 :   // a map's value type is const, we can't fix it up once we've
          95                 :   // created our file.  lower_bound does the lookup without doing an
          96                 :   // insertion, and returns a good hint iterator to pass to insert.
          97                 :   // Our "destiny" is where we belong, whether we're there or not now.
          98          366538 :   FileByNameMap::iterator destiny = files_.lower_bound(&name);
          99          732213 :   if (destiny == files_.end()
         100          365675 :       || *destiny->first != name) {  // Repeated string comparison, boo hoo.
         101           23071 :     File *file = new File;
         102           23071 :     file->name = name;
         103           23071 :     file->source_id = -1;
         104                 :     destiny = files_.insert(destiny,
         105           23071 :                             FileByNameMap::value_type(&file->name, file));
         106                 :   }
         107          366538 :   return destiny->second;
         108                 : }
         109                 :
         110               0 : Module::File *Module::FindFile(const char *name) {
         111               0 :   string name_string = name;
         112               0 :   return FindFile(name_string);
         113                 : }
         114                 :
         115               0 : Module::File *Module::FindExistingFile(const string &name) {
         116               0 :   FileByNameMap::iterator it = files_.find(&name);
         117               0 :   return (it == files_.end()) ? NULL : it->second;
         118                 : }
         119                 :
         120               0 : void Module::GetFiles(vector<File *> *vec) {
         121               0 :   vec->clear();
         122               0 :   for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); it++)
         123               0 :     vec->push_back(it->second);
         124               0 : }
         125                 :
         126               0 : void Module::GetStackFrameEntries(vector<StackFrameEntry *> *vec) {
         127               0 :   *vec = stack_frame_entries_;
         128               0 : }
         129                 :
         130             124 : void Module::AssignSourceIds() {
         131                 :   // First, give every source file an id of -1.
         132           46390 :   for (FileByNameMap::iterator file_it = files_.begin();
         133           23195 :        file_it != files_.end(); file_it++)
         134           23071 :     file_it->second->source_id = -1;
         135                 :
         136                 :   // Next, mark all files actually cited by our functions' line number
         137                 :   // info, by setting each one's source id to zero.
         138          618702 :   for (FunctionSet::const_iterator func_it = functions_.begin();
         139          309351 :        func_it != functions_.end(); func_it++) {
         140          309227 :     Function *func = *func_it;
         141         5915176 :     for (vector<Line>::iterator line_it = func->lines.begin();
         142         2957588 :          line_it != func->lines.end(); line_it++)
         143         2648361 :       line_it->file->source_id = 0;
         144                 :   }
         145                 :
         146                 :   // Finally, assign source ids to those files that have been marked.
         147                 :   // We could have just assigned source id numbers while traversing
         148                 :   // the line numbers, but doing it this way numbers the files in
         149                 :   // lexicographical order by name, which is neat.
         150             124 :   int next_source_id = 0;
         151           46390 :   for (FileByNameMap::iterator file_it = files_.begin();
         152           23195 :        file_it != files_.end(); file_it++)
         153           23071 :     if (!file_it->second->source_id)
         154           10887 :       file_it->second->source_id = next_source_id++;
         155             124 : }
         156                 :
         157               0 : bool Module::ReportError() {
         158                 :   fprintf(stderr, "error writing symbol file: %s\n",
         159               0 :           strerror(errno));
         160               0 :   return false;
         161                 : }
         162                 :
         163         4189641 : bool Module::WriteRuleMap(const RuleMap &rule_map, FILE *stream) {
         164        21264740 :   for (RuleMap::const_iterator it = rule_map.begin();
         165        10632370 :        it != rule_map.end(); it++) {
         166         8695817 :     if (it != rule_map.begin() &&
         167         2253088 :         0 > putc(' ', stream))
         168               0 :       return false;
         169         6442729 :     if (0 > fprintf(stream, "%s: %s", it->first.c_str(), it->second.c_str()))
         170               0 :       return false;
         171                 :   }
         172         4189641 :   return true;
         173                 : }
         174                 :
         175             124 : bool Module::Write(FILE *stream) {
         176             124 :   if (0 > fprintf(stream, "MODULE %s %s %s %s\n",
         177                 :                   os_.c_str(), architecture_.c_str(), id_.c_str(),
         178             124 :                   name_.c_str()))
         179               0 :     return ReportError();
         180                 :
         181             124 :   AssignSourceIds();
         182                 :
         183                 :   // Write out files.
         184           46390 :   for (FileByNameMap::iterator file_it = files_.begin();
         185           23195 :        file_it != files_.end(); file_it++) {
         186           23071 :     File *file = file_it->second;
         187           23071 :     if (file->source_id >= 0) {
         188           10887 :       if (0 > fprintf(stream, "FILE %d %s\n",
         189           10887 :                       file->source_id, file->name.c_str()))
         190               0 :         return ReportError();
         191                 :     }
         192                 :   }
         193                 :
         194                 :   // Write out functions and their lines.
         195          618702 :   for (FunctionSet::const_iterator func_it = functions_.begin();
         196          309351 :        func_it != functions_.end(); func_it++) {
         197          309227 :     Function *func = *func_it;
         198          309227 :     if (0 > fprintf(stream, "FUNC %llx %llx %llx %s\n",
         199                 :                     (unsigned long long) (func->address - load_address_),
         200                 :                     (unsigned long long) func->size,
         201                 :                     (unsigned long long) func->parameter_size,
         202          309227 :                     func->name.c_str()))
         203               0 :       return ReportError();
         204         5915176 :     for (vector<Line>::iterator line_it = func->lines.begin();
         205         2957588 :          line_it != func->lines.end(); line_it++)
         206         2648361 :       if (0 > fprintf(stream, "%llx %llx %d %d\n",
         207         2648361 :                       (unsigned long long) (line_it->address - load_address_),
         208         2648361 :                       (unsigned long long) line_it->size,
         209         2648361 :                       line_it->number,
         210        10593444 :                       line_it->file->source_id))
         211               0 :         return ReportError();
         212                 :   }
         213                 :
         214                 :   // Write out 'STACK CFI INIT' and 'STACK CFI' records.
         215             124 :   vector<StackFrameEntry *>::const_iterator frame_it;
         216         1412974 :   for (frame_it = stack_frame_entries_.begin();
         217          706487 :        frame_it != stack_frame_entries_.end(); frame_it++) {
         218          706363 :     StackFrameEntry *entry = *frame_it;
         219         2119089 :     if (0 > fprintf(stream, "STACK CFI INIT %llx %llx ",
         220                 :                     (unsigned long long) entry->address - load_address_,
         221          706363 :                     (unsigned long long) entry->size)
         222          706363 :         || !WriteRuleMap(entry->initial_rules, stream)
         223          706363 :         || 0 > putc('\n', stream))
         224               0 :       return ReportError();
         225                 :
         226                 :     // Write out this entry's delta rules as 'STACK CFI' records.
         227         8379282 :     for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin();
         228         4189641 :          delta_it != entry->rule_changes.end(); delta_it++) {
         229        10449834 :       if (0 > fprintf(stream, "STACK CFI %llx ",
         230         3483278 :                       (unsigned long long) delta_it->first - load_address_)
         231         3483278 :           || !WriteRuleMap(delta_it->second, stream)
         232         3483278 :           || 0 > putc('\n', stream))
         233               0 :         return ReportError();
         234                 :     }
         235                 :   }
         236                 :
         237             124 :   return true;
         238                 : }
         239                 :
         240                 : } // namespace google_breakpad

Generated by: LCOV version 1.7