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-06-02 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           23149 :   for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); it++)
      51           23025 :     delete it->second;
      52          606036 :   for (FunctionSet::iterator it = functions_.begin();
      53          303018 :        it != functions_.end(); it++)
      54          302894 :     delete *it;
      55         1383692 :   for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin();
      56          691846 :        it != stack_frame_entries_.end(); it++)
      57          691722 :     delete *it;
      58             124 : }
      59                 : 
      60             124 : void Module::SetLoadAddress(Address address) {
      61             124 :   load_address_ = address;
      62             124 : }
      63                 : 
      64          617615 : void Module::AddFunction(Function *function) {
      65          617615 :   std::pair<FunctionSet::iterator,bool> ret = functions_.insert(function);
      66          617615 :   if (!ret.second) {
      67                 :     // Free the duplicate we failed to insert because we own it.
      68          314721 :     delete function;
      69                 :   }
      70          617615 : }
      71                 : 
      72            4723 : void Module::AddFunctions(vector<Function *>::iterator begin,
      73                 :                           vector<Function *>::iterator end) {
      74          622338 :   for (vector<Function *>::iterator it = begin; it != end; it++)
      75          617615 :     AddFunction(*it);
      76            4723 : }
      77                 : 
      78          691722 : void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) {
      79          691722 :   stack_frame_entries_.push_back(stack_frame_entry);
      80          691722 : }
      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          357415 : 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          357415 :   FileByNameMap::iterator destiny = files_.lower_bound(&name);
      99          713965 :   if (destiny == files_.end()
     100          356550 :       || *destiny->first != name) {  // Repeated string comparison, boo hoo.
     101           23025 :     File *file = new File;
     102           23025 :     file->name = name;
     103           23025 :     file->source_id = -1;
     104                 :     destiny = files_.insert(destiny,
     105           23025 :                             FileByNameMap::value_type(&file->name, file));
     106                 :   }
     107          357415 :   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           46298 :   for (FileByNameMap::iterator file_it = files_.begin();
     133           23149 :        file_it != files_.end(); file_it++)
     134           23025 :     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          606036 :   for (FunctionSet::const_iterator func_it = functions_.begin();
     139          303018 :        func_it != functions_.end(); func_it++) {
     140          302894 :     Function *func = *func_it;
     141         5850318 :     for (vector<Line>::iterator line_it = func->lines.begin();
     142         2925159 :          line_it != func->lines.end(); line_it++)
     143         2622265 :       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           46298 :   for (FileByNameMap::iterator file_it = files_.begin();
     152           23149 :        file_it != files_.end(); file_it++)
     153           23025 :     if (!file_it->second->source_id)
     154           10812 :       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         4114800 : bool Module::WriteRuleMap(const RuleMap &rule_map, FILE *stream) {
     164        20880074 :   for (RuleMap::const_iterator it = rule_map.begin();
     165        10440037 :        it != rule_map.end(); it++) {
     166         8535674 :     if (it != rule_map.begin() &&
     167         2210437 :         0 > putc(' ', stream))
     168               0 :       return false;
     169         6325237 :     if (0 > fprintf(stream, "%s: %s", it->first.c_str(), it->second.c_str()))
     170               0 :       return false;
     171                 :   }
     172         4114800 :   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           46298 :   for (FileByNameMap::iterator file_it = files_.begin();
     185           23149 :        file_it != files_.end(); file_it++) {
     186           23025 :     File *file = file_it->second;
     187           23025 :     if (file->source_id >= 0) {
     188           10812 :       if (0 > fprintf(stream, "FILE %d %s\n",
     189           10812 :                       file->source_id, file->name.c_str()))
     190               0 :         return ReportError();
     191                 :     }
     192                 :   }
     193                 : 
     194                 :   // Write out functions and their lines.
     195          606036 :   for (FunctionSet::const_iterator func_it = functions_.begin();
     196          303018 :        func_it != functions_.end(); func_it++) {
     197          302894 :     Function *func = *func_it;
     198          302894 :     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          302894 :                     func->name.c_str()))
     203               0 :       return ReportError();
     204         5850318 :     for (vector<Line>::iterator line_it = func->lines.begin();
     205         2925159 :          line_it != func->lines.end(); line_it++)
     206         2622265 :       if (0 > fprintf(stream, "%llx %llx %d %d\n",
     207         2622265 :                       (unsigned long long) (line_it->address - load_address_),
     208         2622265 :                       (unsigned long long) line_it->size,
     209         2622265 :                       line_it->number,
     210        10489060 :                       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         1383692 :   for (frame_it = stack_frame_entries_.begin();
     217          691846 :        frame_it != stack_frame_entries_.end(); frame_it++) {
     218          691722 :     StackFrameEntry *entry = *frame_it;
     219         2075166 :     if (0 > fprintf(stream, "STACK CFI INIT %llx %llx ",
     220                 :                     (unsigned long long) entry->address - load_address_,
     221          691722 :                     (unsigned long long) entry->size)
     222          691722 :         || !WriteRuleMap(entry->initial_rules, stream)
     223          691722 :         || 0 > putc('\n', stream))
     224               0 :       return ReportError();
     225                 : 
     226                 :     // Write out this entry's delta rules as 'STACK CFI' records.
     227         8229600 :     for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin();
     228         4114800 :          delta_it != entry->rule_changes.end(); delta_it++) {
     229        10269234 :       if (0 > fprintf(stream, "STACK CFI %llx ",
     230         3423078 :                       (unsigned long long) delta_it->first - load_address_)
     231         3423078 :           || !WriteRuleMap(delta_it->second, stream)
     232         3423078 :           || 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