toolkit/crashreporter/google-breakpad/src/common/module.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:4b5e9cc17b7a
1 // -*- mode: c++ -*-
2
3 // Copyright (c) 2010 Google Inc.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 // * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
33
34 // module.h: Define google_breakpad::Module. A Module holds debugging
35 // information, and can write that information out as a Breakpad
36 // symbol file.
37
38 #ifndef COMMON_LINUX_MODULE_H__
39 #define COMMON_LINUX_MODULE_H__
40
41 #include <iostream>
42 #include <map>
43 #include <set>
44 #include <string>
45 #include <vector>
46
47 #include <assert.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50
51 #include "common/symbol_data.h"
52 #include "common/using_std_string.h"
53 #include "common/unique_string.h"
54 #include "google_breakpad/common/breakpad_types.h"
55
56 namespace google_breakpad {
57
58 using std::set;
59 using std::vector;
60 using std::map;
61
62 // A Module represents the contents of a module, and supports methods
63 // for adding information produced by parsing STABS or DWARF data
64 // --- possibly both from the same file --- and then writing out the
65 // unified contents as a Breakpad-format symbol file.
66 class Module {
67 public:
68 // The type of addresses and sizes in a symbol table.
69 typedef uint64_t Address;
70 struct File;
71 struct Function;
72 struct Line;
73 struct Extern;
74
75 // Addresses appearing in File, Function, and Line structures are
76 // absolute, not relative to the the module's load address. That
77 // is, if the module were loaded at its nominal load address, the
78 // addresses would be correct.
79
80 // A source file.
81 struct File {
82 // The name of the source file.
83 string name;
84
85 // The file's source id. The Write member function clears this
86 // field and assigns source ids a fresh, so any value placed here
87 // before calling Write will be lost.
88 int source_id;
89 };
90
91 // A function.
92 struct Function {
93 // For sorting by address. (Not style-guide compliant, but it's
94 // stupid not to put this in the struct.)
95 static bool CompareByAddress(const Function *x, const Function *y) {
96 return x->address < y->address;
97 }
98
99 // The function's name.
100 string name;
101
102 // The start address and length of the function's code.
103 Address address, size;
104
105 // The function's parameter size.
106 Address parameter_size;
107
108 // Source lines belonging to this function, sorted by increasing
109 // address.
110 vector<Line> lines;
111 };
112
113 // A source line.
114 struct Line {
115 // For sorting by address. (Not style-guide compliant, but it's
116 // stupid not to put this in the struct.)
117 static bool CompareByAddress(const Module::Line &x, const Module::Line &y) {
118 return x.address < y.address;
119 }
120
121 Address address, size; // The address and size of the line's code.
122 File *file; // The source file.
123 int number; // The source line number.
124 };
125
126 // An exported symbol.
127 struct Extern {
128 Address address;
129 string name;
130 };
131
132 // Representation of an expression. This can either be a postfix
133 // expression, in which case it is stored as a string, or a simple
134 // expression of the form (identifier + imm) or *(identifier + imm).
135 // It can also be invalid (denoting "no value").
136 enum ExprHow {
137 kExprInvalid = 1,
138 kExprPostfix,
139 kExprSimple,
140 kExprSimpleMem
141 };
142 struct Expr {
143 // Construct a simple-form expression
144 Expr(const UniqueString* ident, long offset, bool deref) {
145 if (ident == ustr__empty()) {
146 Expr();
147 } else {
148 postfix_ = "";
149 ident_ = ident;
150 offset_ = offset;
151 how_ = deref ? kExprSimpleMem : kExprSimple;
152 }
153 }
154 // Construct an expression from a postfix string
155 Expr(string postfix) {
156 if (postfix.empty()) {
157 Expr();
158 } else {
159 postfix_ = postfix;
160 ident_ = NULL;
161 offset_ = 0;
162 how_ = kExprPostfix;
163 }
164 }
165 // Construct an invalid expression
166 Expr() {
167 postfix_ = "";
168 ident_ = NULL;
169 offset_ = 0;
170 how_ = kExprInvalid;
171 }
172 bool isExprInvalid() const { return how_ == kExprInvalid; }
173
174 // Return the postfix expression string, either directly,
175 // if this is a postfix expression, or by synthesising it
176 // for a simple expression.
177 string getExprPostfix() const {
178 switch (how_) {
179 case kExprPostfix:
180 return postfix_;
181 case kExprSimple:
182 case kExprSimpleMem: {
183 char buf[40];
184 sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+',
185 how_ == kExprSimple ? "" : " ^");
186 return string(FromUniqueString(ident_)) + string(buf);
187 }
188 case kExprInvalid:
189 default:
190 assert(0 && "getExprPostfix: invalid Module::Expr type");
191 return "Expr::genExprPostfix: kExprInvalid";
192 }
193 }
194
195 bool operator==(const Expr& other) const {
196 return how_ == other.how_ &&
197 ident_ == other.ident_ &&
198 offset_ == other.offset_ &&
199 postfix_ == other.postfix_;
200 }
201
202 // Returns an Expr which evaluates to |this| + |delta|
203 Expr add_delta(long delta) {
204 if (delta == 0) {
205 return *this;
206 }
207 // If it's a simple form expression of the form "identifier + offset",
208 // simply add |delta| on to |offset|. In the other two possible
209 // cases:
210 // *(identifier + offset)
211 // completely arbitrary postfix expression string
212 // the only option is to "downgrade" it to a postfix expression and add
213 // "+/- delta" at the end of the string, since the result can't be
214 // represented in the simple form.
215 switch (how_) {
216 case kExprSimpleMem:
217 case kExprPostfix: {
218 char buf[40];
219 sprintf(buf, " %ld %c", labs(delta), delta < 0 ? '-' : '+');
220 return Expr(getExprPostfix() + string(buf));
221 }
222 case kExprSimple:
223 return Expr(ident_, offset_ + delta, false);
224 case kExprInvalid:
225 default:
226 assert(0 && "add_delta: invalid Module::Expr type");
227 // Invalid inputs produce an invalid result
228 return Expr();
229 }
230 }
231
232 // Returns an Expr which evaluates to *|this|
233 Expr deref() {
234 // In the simplest case, a kExprSimple can be changed into a
235 // kExprSimpleMem. In all other cases it has to be dumped as a
236 // postfix string, and " ^" added at the end.
237 switch (how_) {
238 case kExprSimple: {
239 Expr t = *this;
240 t.how_ = kExprSimpleMem;
241 return t;
242 }
243 case kExprSimpleMem:
244 case kExprPostfix: {
245 return Expr(getExprPostfix() + " ^");
246 }
247 case kExprInvalid:
248 default:
249 assert(0 && "deref: invalid Module::Expr type");
250 // Invalid inputs produce an invalid result
251 return Expr();
252 }
253 }
254
255 // The identifier that gives the starting value for simple expressions.
256 const UniqueString* ident_;
257 // The offset to add for simple expressions.
258 long offset_;
259 // The Postfix expression string to evaluate for non-simple expressions.
260 string postfix_;
261 // The operation expressed by this expression.
262 ExprHow how_;
263
264 friend std::ostream& operator<<(std::ostream& stream, const Expr& expr);
265 };
266
267 // A map from register names to expressions that recover
268 // their values. This can represent a complete set of rules to
269 // follow at some address, or a set of changes to be applied to an
270 // extant set of rules.
271 typedef map<const UniqueString*, Expr> RuleMap;
272
273 // A map from addresses to RuleMaps, representing changes that take
274 // effect at given addresses.
275 typedef map<Address, RuleMap> RuleChangeMap;
276
277 // A range of 'STACK CFI' stack walking information. An instance of
278 // this structure corresponds to a 'STACK CFI INIT' record and the
279 // subsequent 'STACK CFI' records that fall within its range.
280 struct StackFrameEntry {
281 // The starting address and number of bytes of machine code this
282 // entry covers.
283 Address address, size;
284
285 // The initial register recovery rules, in force at the starting
286 // address.
287 RuleMap initial_rules;
288
289 // A map from addresses to rule changes. To find the rules in
290 // force at a given address, start with initial_rules, and then
291 // apply the changes given in this map for all addresses up to and
292 // including the address you're interested in.
293 RuleChangeMap rule_changes;
294 };
295
296 struct FunctionCompare {
297 bool operator() (const Function *lhs,
298 const Function *rhs) const {
299 if (lhs->address == rhs->address)
300 return lhs->name < rhs->name;
301 return lhs->address < rhs->address;
302 }
303 };
304
305 struct ExternCompare {
306 bool operator() (const Extern *lhs,
307 const Extern *rhs) const {
308 return lhs->address < rhs->address;
309 }
310 };
311
312 struct StackFrameEntryCompare {
313 bool operator() (const StackFrameEntry* lhs,
314 const StackFrameEntry* rhs) const {
315 return lhs->address < rhs->address;
316 }
317 };
318
319 // Create a new module with the given name, operating system,
320 // architecture, and ID string.
321 Module(const string &name, const string &os, const string &architecture,
322 const string &id);
323 ~Module();
324
325 // Set the module's load address to LOAD_ADDRESS; addresses given
326 // for functions and lines will be written to the Breakpad symbol
327 // file as offsets from this address. Construction initializes this
328 // module's load address to zero: addresses written to the symbol
329 // file will be the same as they appear in the Function, Line, and
330 // StackFrameEntry structures.
331 //
332 // Note that this member function has no effect on addresses stored
333 // in the data added to this module; the Write member function
334 // simply subtracts off the load address from addresses before it
335 // prints them. Only the last load address given before calling
336 // Write is used.
337 void SetLoadAddress(Address load_address);
338
339 // Add FUNCTION to the module. FUNCTION's name must not be empty.
340 // This module owns all Function objects added with this function:
341 // destroying the module destroys them as well.
342 void AddFunction(Function *function);
343
344 // Add all the functions in [BEGIN,END) to the module.
345 // This module owns all Function objects added with this function:
346 // destroying the module destroys them as well.
347 void AddFunctions(vector<Function *>::iterator begin,
348 vector<Function *>::iterator end);
349
350 // Add STACK_FRAME_ENTRY to the module.
351 // This module owns all StackFrameEntry objects added with this
352 // function: destroying the module destroys them as well.
353 void AddStackFrameEntry(StackFrameEntry *stack_frame_entry);
354
355 // Add PUBLIC to the module.
356 // This module owns all Extern objects added with this function:
357 // destroying the module destroys them as well.
358 void AddExtern(Extern *ext);
359
360 // If this module has a file named NAME, return a pointer to it. If
361 // it has none, then create one and return a pointer to the new
362 // file. This module owns all File objects created using these
363 // functions; destroying the module destroys them as well.
364 File *FindFile(const string &name);
365 File *FindFile(const char *name);
366
367 // If this module has a file named NAME, return a pointer to it.
368 // Otherwise, return NULL.
369 File *FindExistingFile(const string &name);
370
371 // Insert pointers to the functions added to this module at I in
372 // VEC. The pointed-to Functions are still owned by this module.
373 // (Since this is effectively a copy of the function list, this is
374 // mostly useful for testing; other uses should probably get a more
375 // appropriate interface.)
376 void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
377
378 // If this module has a function at ADDRESS, return a pointer to it.
379 // Otherwise, return NULL.
380 Function* FindFunctionByAddress(Address address);
381
382 // Insert pointers to the externs added to this module at I in
383 // VEC. The pointed-to Externs are still owned by this module.
384 // (Since this is effectively a copy of the extern list, this is
385 // mostly useful for testing; other uses should probably get a more
386 // appropriate interface.)
387 void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
388
389 // If this module has an extern whose base address is less than ADDRESS,
390 // return a pointer to it. Otherwise, return NULL.
391 Extern* FindExternByAddress(Address address);
392
393 // Clear VEC and fill it with pointers to the Files added to this
394 // module, sorted by name. The pointed-to Files are still owned by
395 // this module. (Since this is effectively a copy of the file list,
396 // this is mostly useful for testing; other uses should probably get
397 // a more appropriate interface.)
398 void GetFiles(vector<File *> *vec);
399
400 // Clear VEC and fill it with pointers to the StackFrameEntry
401 // objects that have been added to this module. (Since this is
402 // effectively a copy of the stack frame entry list, this is mostly
403 // useful for testing; other uses should probably get
404 // a more appropriate interface.)
405 void GetStackFrameEntries(vector<StackFrameEntry *> *vec);
406
407 // If this module has a StackFrameEntry whose address range covers
408 // ADDRESS, return it. Otherwise return NULL.
409 StackFrameEntry* FindStackFrameEntryByAddress(Address address);
410
411 // Find those files in this module that are actually referred to by
412 // functions' line number data, and assign them source id numbers.
413 // Set the source id numbers for all other files --- unused by the
414 // source line data --- to -1. We do this before writing out the
415 // symbol file, at which point we omit any unused files.
416 void AssignSourceIds();
417
418 // Call AssignSourceIds, and write this module to STREAM in the
419 // breakpad symbol format. Return true if all goes well, or false if
420 // an error occurs. This method writes out:
421 // - a header based on the values given to the constructor,
422 // If symbol_data is not ONLY_CFI then:
423 // - the source files added via FindFile,
424 // - the functions added via AddFunctions, each with its lines,
425 // - all public records,
426 // If symbol_data is not NO_CFI then:
427 // - all CFI records.
428 // Addresses in the output are all relative to the load address
429 // established by SetLoadAddress.
430 bool Write(std::ostream &stream, SymbolData symbol_data);
431
432 private:
433 // Report an error that has occurred writing the symbol file, using
434 // errno to find the appropriate cause. Return false.
435 static bool ReportError();
436
437 // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI'
438 // records, without a final newline. Return true if all goes well;
439 // if an error occurs, return false, and leave errno set.
440 static bool WriteRuleMap(const RuleMap &rule_map, std::ostream &stream);
441
442 // Module header entries.
443 string name_, os_, architecture_, id_;
444
445 // The module's nominal load address. Addresses for functions and
446 // lines are absolute, assuming the module is loaded at this
447 // address.
448 Address load_address_;
449
450 // Relation for maps whose keys are strings shared with some other
451 // structure.
452 struct CompareStringPtrs {
453 bool operator()(const string *x, const string *y) const { return *x < *y; }
454 };
455
456 // A map from filenames to File structures. The map's keys are
457 // pointers to the Files' names.
458 typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
459
460 // A set containing Function structures, sorted by address.
461 typedef set<Function *, FunctionCompare> FunctionSet;
462
463 // A set containing Extern structures, sorted by address.
464 typedef set<Extern *, ExternCompare> ExternSet;
465
466 // A set containing StackFrameEntry structures, sorted by address.
467 typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet;
468
469 // The module owns all the files and functions that have been added
470 // to it; destroying the module frees the Files and Functions these
471 // point to.
472 FileByNameMap files_; // This module's source files.
473 FunctionSet functions_; // This module's functions.
474
475 // The module owns all the call frame info entries that have been
476 // added to it.
477 StackFrameEntrySet stack_frame_entries_;
478
479 // The module owns all the externs that have been added to it;
480 // destroying the module frees the Externs these point to.
481 ExternSet externs_;
482 };
483
484 } // namespace google_breakpad
485
486 #endif // COMMON_LINUX_MODULE_H__

mercurial