Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // Copyright (c) 2011 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.
30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
32 // module.cc: Implement google_breakpad::Module. See module.h.
34 #include "common/module.h"
36 #include <assert.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <string.h>
41 #include <algorithm>
42 #include <iostream>
43 #include <utility>
45 namespace google_breakpad {
47 using std::dec;
48 using std::endl;
49 using std::hex;
52 Module::Module(const string &name, const string &os,
53 const string &architecture, const string &id) :
54 name_(name),
55 os_(os),
56 architecture_(architecture),
57 id_(id),
58 load_address_(0) { }
60 Module::~Module() {
61 for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
62 delete it->second;
63 for (FunctionSet::iterator it = functions_.begin();
64 it != functions_.end(); ++it) {
65 delete *it;
66 }
67 for (StackFrameEntrySet::iterator it = stack_frame_entries_.begin();
68 it != stack_frame_entries_.end(); ++it) {
69 delete *it;
70 }
71 for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it)
72 delete *it;
73 }
75 void Module::SetLoadAddress(Address address) {
76 load_address_ = address;
77 }
79 void Module::AddFunction(Function *function) {
80 // FUNC lines must not hold an empty name, so catch the problem early if
81 // callers try to add one.
82 assert(!function->name.empty());
83 std::pair<FunctionSet::iterator,bool> ret = functions_.insert(function);
84 if (!ret.second) {
85 // Free the duplicate that was not inserted because this Module
86 // now owns it.
87 delete function;
88 }
89 }
91 void Module::AddFunctions(vector<Function *>::iterator begin,
92 vector<Function *>::iterator end) {
93 for (vector<Function *>::iterator it = begin; it != end; ++it)
94 AddFunction(*it);
95 }
97 void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) {
98 std::pair<StackFrameEntrySet::iterator,bool> ret =
99 stack_frame_entries_.insert(stack_frame_entry);
100 if (!ret.second) {
101 // Free the duplicate that was not inserted because this Module
102 // now owns it.
103 delete stack_frame_entry;
104 }
105 }
107 void Module::AddExtern(Extern *ext) {
108 std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext);
109 if (!ret.second) {
110 // Free the duplicate that was not inserted because this Module
111 // now owns it.
112 delete ext;
113 }
114 }
116 void Module::GetFunctions(vector<Function *> *vec,
117 vector<Function *>::iterator i) {
118 vec->insert(i, functions_.begin(), functions_.end());
119 }
121 template<typename T>
122 bool EntryContainsAddress(T entry, Module::Address address) {
123 return entry->address <= address && address < entry->address + entry->size;
124 }
126 Module::Function* Module::FindFunctionByAddress(Address address) {
127 Function search;
128 search.address = address;
129 // Ensure that name always sorts higher than the function name,
130 // so that upper_bound always returns the function just after
131 // the function containing this address.
132 search.name = "\xFF";
133 FunctionSet::iterator it = functions_.upper_bound(&search);
134 if (it == functions_.begin())
135 return NULL;
137 it--;
139 if (EntryContainsAddress(*it, address))
140 return *it;
142 return NULL;
143 }
145 void Module::GetExterns(vector<Extern *> *vec,
146 vector<Extern *>::iterator i) {
147 vec->insert(i, externs_.begin(), externs_.end());
148 }
150 Module::Extern* Module::FindExternByAddress(Address address) {
151 Extern search;
152 search.address = address;
153 ExternSet::iterator it = externs_.upper_bound(&search);
155 if (it == externs_.begin())
156 return NULL;
158 it--;
159 if ((*it)->address > address)
160 return NULL;
162 return *it;
163 }
165 Module::File *Module::FindFile(const string &name) {
166 // A tricky bit here. The key of each map entry needs to be a
167 // pointer to the entry's File's name string. This means that we
168 // can't do the initial lookup with any operation that would create
169 // an empty entry for us if the name isn't found (like, say,
170 // operator[] or insert do), because such a created entry's key will
171 // be a pointer the string passed as our argument. Since the key of
172 // a map's value type is const, we can't fix it up once we've
173 // created our file. lower_bound does the lookup without doing an
174 // insertion, and returns a good hint iterator to pass to insert.
175 // Our "destiny" is where we belong, whether we're there or not now.
176 FileByNameMap::iterator destiny = files_.lower_bound(&name);
177 if (destiny == files_.end()
178 || *destiny->first != name) { // Repeated string comparison, boo hoo.
179 File *file = new File;
180 file->name = name;
181 file->source_id = -1;
182 destiny = files_.insert(destiny,
183 FileByNameMap::value_type(&file->name, file));
184 }
185 return destiny->second;
186 }
188 Module::File *Module::FindFile(const char *name) {
189 string name_string = name;
190 return FindFile(name_string);
191 }
193 Module::File *Module::FindExistingFile(const string &name) {
194 FileByNameMap::iterator it = files_.find(&name);
195 return (it == files_.end()) ? NULL : it->second;
196 }
198 void Module::GetFiles(vector<File *> *vec) {
199 vec->clear();
200 for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
201 vec->push_back(it->second);
202 }
204 void Module::GetStackFrameEntries(vector<StackFrameEntry *>* vec) {
205 vec->clear();
206 vec->insert(vec->begin(), stack_frame_entries_.begin(),
207 stack_frame_entries_.end());
208 }
210 Module::StackFrameEntry* Module::FindStackFrameEntryByAddress(Address address) {
211 StackFrameEntry search;
212 search.address = address;
213 StackFrameEntrySet::iterator it = stack_frame_entries_.upper_bound(&search);
215 if (it == stack_frame_entries_.begin())
216 return NULL;
218 it--;
219 if (EntryContainsAddress(*it, address))
220 return *it;
222 return NULL;
223 }
225 void Module::AssignSourceIds() {
226 // First, give every source file an id of -1.
227 for (FileByNameMap::iterator file_it = files_.begin();
228 file_it != files_.end(); ++file_it) {
229 file_it->second->source_id = -1;
230 }
232 // Next, mark all files actually cited by our functions' line number
233 // info, by setting each one's source id to zero.
234 for (FunctionSet::const_iterator func_it = functions_.begin();
235 func_it != functions_.end(); ++func_it) {
236 Function *func = *func_it;
237 for (vector<Line>::iterator line_it = func->lines.begin();
238 line_it != func->lines.end(); ++line_it)
239 line_it->file->source_id = 0;
240 }
242 // Finally, assign source ids to those files that have been marked.
243 // We could have just assigned source id numbers while traversing
244 // the line numbers, but doing it this way numbers the files in
245 // lexicographical order by name, which is neat.
246 int next_source_id = 0;
247 for (FileByNameMap::iterator file_it = files_.begin();
248 file_it != files_.end(); ++file_it) {
249 if (!file_it->second->source_id)
250 file_it->second->source_id = next_source_id++;
251 }
252 }
254 bool Module::ReportError() {
255 fprintf(stderr, "error writing symbol file: %s\n",
256 strerror(errno));
257 return false;
258 }
260 std::ostream& operator<<(std::ostream& stream, const Module::Expr& expr) {
261 assert(!expr.isExprInvalid());
262 switch (expr.how_) {
263 case Module::kExprSimple:
264 stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " +";
265 break;
266 case Module::kExprSimpleMem:
267 stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " + ^";
268 break;
269 case Module::kExprPostfix:
270 stream << expr.postfix_; break;
271 case Module::kExprInvalid:
272 default:
273 break;
274 }
275 return stream;
276 }
278 bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) {
279 // Visit the register rules in alphabetical order. Because
280 // rule_map has the elements in some arbitrary order,
281 // get the names out into a vector, sort them, and visit in
282 // sorted order.
283 std::vector<const UniqueString*> rr_names;
284 for (RuleMap::const_iterator it = rule_map.begin();
285 it != rule_map.end(); ++it) {
286 rr_names.push_back(it->first);
287 }
289 std::sort(rr_names.begin(), rr_names.end(), LessThan_UniqueString);
291 // Now visit the register rules in alphabetical order.
292 for (std::vector<const UniqueString*>::const_iterator name = rr_names.begin();
293 name != rr_names.end();
294 ++name) {
295 if (name != rr_names.begin())
296 stream << " ";
297 stream << FromUniqueString(*name) << ": " << rule_map.find(*name)->second;
298 }
299 return stream.good();
300 }
302 bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
303 stream << "MODULE " << os_ << " " << architecture_ << " "
304 << id_ << " " << name_ << endl;
305 if (!stream.good())
306 return ReportError();
308 if (symbol_data != ONLY_CFI) {
309 AssignSourceIds();
311 // Write out files.
312 for (FileByNameMap::iterator file_it = files_.begin();
313 file_it != files_.end(); ++file_it) {
314 File *file = file_it->second;
315 if (file->source_id >= 0) {
316 stream << "FILE " << file->source_id << " " << file->name << endl;
317 if (!stream.good())
318 return ReportError();
319 }
320 }
322 // Write out functions and their lines.
323 for (FunctionSet::const_iterator func_it = functions_.begin();
324 func_it != functions_.end(); ++func_it) {
325 Function *func = *func_it;
326 stream << "FUNC " << hex
327 << (func->address - load_address_) << " "
328 << func->size << " "
329 << func->parameter_size << " "
330 << func->name << dec << endl;
331 if (!stream.good())
332 return ReportError();
334 for (vector<Line>::iterator line_it = func->lines.begin();
335 line_it != func->lines.end(); ++line_it) {
336 stream << hex
337 << (line_it->address - load_address_) << " "
338 << line_it->size << " "
339 << dec
340 << line_it->number << " "
341 << line_it->file->source_id << endl;
342 if (!stream.good())
343 return ReportError();
344 }
345 }
347 // Write out 'PUBLIC' records.
348 for (ExternSet::const_iterator extern_it = externs_.begin();
349 extern_it != externs_.end(); ++extern_it) {
350 Extern *ext = *extern_it;
351 stream << "PUBLIC " << hex
352 << (ext->address - load_address_) << " 0 "
353 << ext->name << dec << endl;
354 }
355 }
357 if (symbol_data != NO_CFI) {
358 // Write out 'STACK CFI INIT' and 'STACK CFI' records.
359 StackFrameEntrySet::const_iterator frame_it;
360 for (frame_it = stack_frame_entries_.begin();
361 frame_it != stack_frame_entries_.end(); ++frame_it) {
362 StackFrameEntry *entry = *frame_it;
363 stream << "STACK CFI INIT " << hex
364 << (entry->address - load_address_) << " "
365 << entry->size << " " << dec;
366 if (!stream.good()
367 || !WriteRuleMap(entry->initial_rules, stream))
368 return ReportError();
370 stream << endl;
372 // Write out this entry's delta rules as 'STACK CFI' records.
373 for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin();
374 delta_it != entry->rule_changes.end(); ++delta_it) {
375 stream << "STACK CFI " << hex
376 << (delta_it->first - load_address_) << " " << dec;
377 if (!stream.good()
378 || !WriteRuleMap(delta_it->second, stream))
379 return ReportError();
381 stream << endl;
382 }
383 }
384 }
386 return true;
387 }
389 } // namespace google_breakpad