OLD | NEW |
| (Empty) |
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 // dump_stabs.cc --- implement the DumpStabsHandler class. | |
33 | |
34 #include <cstdarg> | |
35 //#include <cxxabi.h> | |
36 | |
37 #include <algorithm> | |
38 #include <cassert> | |
39 | |
40 #include "common/dump_stabs.h" | |
41 | |
42 namespace google_breakpad { | |
43 | |
44 using std::string; | |
45 | |
46 // Demangle using abi call. | |
47 // Older GCC may not support it. | |
48 static string Demangle(const string &mangled) { | |
49 int status = 0; | |
50 char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); | |
51 if (status == 0 && demangled != NULL) { | |
52 string str(demangled); | |
53 free(demangled); | |
54 return str; | |
55 } | |
56 return string(mangled); | |
57 } | |
58 | |
59 bool DumpStabsHandler::StartCompilationUnit(const char *name, uint64_t address, | |
60 const char *build_directory) { | |
61 assert(!in_compilation_unit_); | |
62 in_compilation_unit_ = true; | |
63 current_source_file_name_ = name; | |
64 current_source_file_ = module_->FindFile(name); | |
65 comp_unit_base_address_ = address; | |
66 boundaries_.push_back(static_cast<Module::Address>(address)); | |
67 return true; | |
68 } | |
69 | |
70 bool DumpStabsHandler::EndCompilationUnit(uint64_t address) { | |
71 assert(in_compilation_unit_); | |
72 in_compilation_unit_ = false; | |
73 comp_unit_base_address_ = 0; | |
74 current_source_file_ = NULL; | |
75 current_source_file_name_ = NULL; | |
76 if (address) | |
77 boundaries_.push_back(static_cast<Module::Address>(address)); | |
78 return true; | |
79 } | |
80 | |
81 bool DumpStabsHandler::StartFunction(const string &name, | |
82 uint64_t address) { | |
83 assert(!current_function_); | |
84 Module::Function *f = new Module::Function; | |
85 f->name = Demangle(name); | |
86 f->address = address; | |
87 f->size = 0; // We compute this in DumpStabsHandler::Finalize(). | |
88 f->parameter_size = 0; // We don't provide this information. | |
89 current_function_ = f; | |
90 boundaries_.push_back(static_cast<Module::Address>(address)); | |
91 return true; | |
92 } | |
93 | |
94 bool DumpStabsHandler::EndFunction(uint64_t address) { | |
95 assert(current_function_); | |
96 // Functions in this compilation unit should have address bigger | |
97 // than the compilation unit's starting address. There may be a lot | |
98 // of duplicated entries for functions in the STABS data; only one | |
99 // entry can meet this requirement. | |
100 // | |
101 // (I don't really understand the above comment; just bringing it | |
102 // along from the previous code, and leaving the behaivor unchanged. | |
103 // If you know the whole story, please patch this comment. --jimb) | |
104 if (current_function_->address >= comp_unit_base_address_) | |
105 functions_.push_back(current_function_); | |
106 else | |
107 delete current_function_; | |
108 current_function_ = NULL; | |
109 if (address) | |
110 boundaries_.push_back(static_cast<Module::Address>(address)); | |
111 return true; | |
112 } | |
113 | |
114 bool DumpStabsHandler::Line(uint64_t address, const char *name, int number) { | |
115 assert(current_function_); | |
116 assert(current_source_file_); | |
117 if (name != current_source_file_name_) { | |
118 current_source_file_ = module_->FindFile(name); | |
119 current_source_file_name_ = name; | |
120 } | |
121 Module::Line line; | |
122 line.address = address; | |
123 line.size = 0; // We compute this in DumpStabsHandler::Finalize(). | |
124 line.file = current_source_file_; | |
125 line.number = number; | |
126 current_function_->lines.push_back(line); | |
127 return true; | |
128 } | |
129 | |
130 void DumpStabsHandler::Warning(const char *format, ...) { | |
131 va_list args; | |
132 va_start(args, format); | |
133 vfprintf(stderr, format, args); | |
134 va_end(args); | |
135 } | |
136 | |
137 void DumpStabsHandler::Finalize() { | |
138 // Sort our boundary list, so we can search it quickly. | |
139 sort(boundaries_.begin(), boundaries_.end()); | |
140 // Sort all functions by address, just for neatness. | |
141 sort(functions_.begin(), functions_.end(), | |
142 Module::Function::CompareByAddress); | |
143 for (vector<Module::Function *>::iterator func_it = functions_.begin(); | |
144 func_it != functions_.end(); | |
145 func_it++) { | |
146 Module::Function *f = *func_it; | |
147 // Compute the function f's size. | |
148 vector<Module::Address>::iterator boundary | |
149 = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address); | |
150 if (boundary != boundaries_.end()) | |
151 f->size = *boundary - f->address; | |
152 else | |
153 // If this is the last function in the module, and the STABS | |
154 // reader was unable to give us its ending address, then assign | |
155 // it a bogus, very large value. This will happen at most once | |
156 // per module: since we've added all functions' addresses to the | |
157 // boundary table, only one can be the last. | |
158 f->size = kFallbackSize; | |
159 | |
160 // Compute sizes for each of the function f's lines --- if it has any. | |
161 if (!f->lines.empty()) { | |
162 stable_sort(f->lines.begin(), f->lines.end(), | |
163 Module::Line::CompareByAddress); | |
164 vector<Module::Line>::iterator last_line = f->lines.end() - 1; | |
165 for (vector<Module::Line>::iterator line_it = f->lines.begin(); | |
166 line_it != last_line; line_it++) | |
167 line_it[0].size = line_it[1].address - line_it[0].address; | |
168 // Compute the size of the last line from f's end address. | |
169 last_line->size = (f->address + f->size) - last_line->address; | |
170 } | |
171 } | |
172 // Now that everything has a size, add our functions to the module, and | |
173 // dispose of our private list. | |
174 module_->AddFunctions(functions_.begin(), functions_.end()); | |
175 functions_.clear(); | |
176 } | |
177 | |
178 } // namespace google_breakpad | |
OLD | NEW |