|
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__ |