Home | History | Annotate | Download | only in common
      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 (at) mozilla.com> <jimb (at) red-bean.com>
     31 
     32 // dwarf_line_to_module.cc: Implementation of DwarfLineToModule class.
     33 // See dwarf_line_to_module.h for details.
     34 
     35 #include <stdio.h>
     36 
     37 #include <string>
     38 
     39 #include "common/dwarf_line_to_module.h"
     40 #include "common/using_std_string.h"
     41 
     42 // Trying to support Windows paths in a reasonable way adds a lot of
     43 // variations to test; it would be better to just put off dealing with
     44 // it until we actually have to deal with DWARF on Windows.
     45 
     46 // Return true if PATH is an absolute path, false if it is relative.
     47 static bool PathIsAbsolute(const string &path) {
     48   return (path.size() >= 1 && path[0] == '/');
     49 }
     50 
     51 static bool HasTrailingSlash(const string &path) {
     52   return (path.size() >= 1 && path[path.size() - 1] == '/');
     53 }
     54 
     55 // If PATH is an absolute path, return PATH.  If PATH is a relative path,
     56 // treat it as relative to BASE and return the combined path.
     57 static string ExpandPath(const string &path,
     58                          const string &base) {
     59   if (PathIsAbsolute(path) || base.empty())
     60     return path;
     61   return base + (HasTrailingSlash(base) ? "" : "/") + path;
     62 }
     63 
     64 namespace google_breakpad {
     65 
     66 void DwarfLineToModule::DefineDir(const string &name, uint32 dir_num) {
     67   // Directory number zero is reserved to mean the compilation
     68   // directory. Silently ignore attempts to redefine it.
     69   if (dir_num != 0)
     70     directories_[dir_num] = ExpandPath(name, compilation_dir_);
     71 }
     72 
     73 void DwarfLineToModule::DefineFile(const string &name, int32 file_num,
     74                                    uint32 dir_num, uint64 mod_time,
     75                                    uint64 length) {
     76   if (file_num == -1)
     77     file_num = ++highest_file_number_;
     78   else if (file_num > highest_file_number_)
     79     highest_file_number_ = file_num;
     80 
     81   string dir_name;
     82   if (dir_num == 0) {
     83     // Directory number zero is the compilation directory, and is stored as
     84     // an attribute on the compilation unit, rather than in the program table.
     85     dir_name = compilation_dir_;
     86   } else {
     87     DirectoryTable::const_iterator directory_it = directories_.find(dir_num);
     88     if (directory_it != directories_.end()) {
     89       dir_name = directory_it->second;
     90     } else {
     91       if (!warned_bad_directory_number_) {
     92         fprintf(stderr, "warning: DWARF line number data refers to undefined"
     93                 " directory numbers\n");
     94         warned_bad_directory_number_ = true;
     95       }
     96     }
     97   }
     98 
     99   string full_name = ExpandPath(name, dir_name);
    100 
    101   // Find a Module::File object of the given name, and add it to the
    102   // file table.
    103   files_[file_num] = module_->FindFile(full_name);
    104 }
    105 
    106 void DwarfLineToModule::AddLine(uint64 address, uint64 length,
    107                                 uint32 file_num, uint32 line_num,
    108                                 uint32 column_num) {
    109   if (length == 0)
    110     return;
    111 
    112   // Clip lines not to extend beyond the end of the address space.
    113   if (address + length < address)
    114     length = -address;
    115 
    116   // Should we omit this line? (See the comments for omitted_line_end_.)
    117   if (address == 0 || address == omitted_line_end_) {
    118     omitted_line_end_ = address + length;
    119     return;
    120   } else {
    121     omitted_line_end_ = 0;
    122   }
    123 
    124   // Find the source file being referred to.
    125   Module::File *file = files_[file_num];
    126   if (!file) {
    127     if (!warned_bad_file_number_) {
    128       fprintf(stderr, "warning: DWARF line number data refers to "
    129               "undefined file numbers\n");
    130       warned_bad_file_number_ = true;
    131     }
    132     return;
    133   }
    134   Module::Line line;
    135   line.address = address;
    136   // We set the size when we get the next line or the EndSequence call.
    137   line.size = length;
    138   line.file = file;
    139   line.number = line_num;
    140   lines_->push_back(line);
    141 }
    142 
    143 } // namespace google_breakpad
    144