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 | // 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_t 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_t file_num, |
74 | uint32_t dir_num, uint64_t mod_time, |
75 | uint64_t 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_t address, uint64_t length, |
107 | uint32_t file_num, uint32_t line_num, |
108 | uint32_t 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 | |