1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/module.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,486 @@ 1.4 +// -*- mode: c++ -*- 1.5 + 1.6 +// Copyright (c) 2010 Google Inc. 1.7 +// All rights reserved. 1.8 +// 1.9 +// Redistribution and use in source and binary forms, with or without 1.10 +// modification, are permitted provided that the following conditions are 1.11 +// met: 1.12 +// 1.13 +// * Redistributions of source code must retain the above copyright 1.14 +// notice, this list of conditions and the following disclaimer. 1.15 +// * Redistributions in binary form must reproduce the above 1.16 +// copyright notice, this list of conditions and the following disclaimer 1.17 +// in the documentation and/or other materials provided with the 1.18 +// distribution. 1.19 +// * Neither the name of Google Inc. nor the names of its 1.20 +// contributors may be used to endorse or promote products derived from 1.21 +// this software without specific prior written permission. 1.22 +// 1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 + 1.35 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.36 + 1.37 +// module.h: Define google_breakpad::Module. A Module holds debugging 1.38 +// information, and can write that information out as a Breakpad 1.39 +// symbol file. 1.40 + 1.41 +#ifndef COMMON_LINUX_MODULE_H__ 1.42 +#define COMMON_LINUX_MODULE_H__ 1.43 + 1.44 +#include <iostream> 1.45 +#include <map> 1.46 +#include <set> 1.47 +#include <string> 1.48 +#include <vector> 1.49 + 1.50 +#include <assert.h> 1.51 +#include <stdlib.h> 1.52 +#include <stdio.h> 1.53 + 1.54 +#include "common/symbol_data.h" 1.55 +#include "common/using_std_string.h" 1.56 +#include "common/unique_string.h" 1.57 +#include "google_breakpad/common/breakpad_types.h" 1.58 + 1.59 +namespace google_breakpad { 1.60 + 1.61 +using std::set; 1.62 +using std::vector; 1.63 +using std::map; 1.64 + 1.65 +// A Module represents the contents of a module, and supports methods 1.66 +// for adding information produced by parsing STABS or DWARF data 1.67 +// --- possibly both from the same file --- and then writing out the 1.68 +// unified contents as a Breakpad-format symbol file. 1.69 +class Module { 1.70 + public: 1.71 + // The type of addresses and sizes in a symbol table. 1.72 + typedef uint64_t Address; 1.73 + struct File; 1.74 + struct Function; 1.75 + struct Line; 1.76 + struct Extern; 1.77 + 1.78 + // Addresses appearing in File, Function, and Line structures are 1.79 + // absolute, not relative to the the module's load address. That 1.80 + // is, if the module were loaded at its nominal load address, the 1.81 + // addresses would be correct. 1.82 + 1.83 + // A source file. 1.84 + struct File { 1.85 + // The name of the source file. 1.86 + string name; 1.87 + 1.88 + // The file's source id. The Write member function clears this 1.89 + // field and assigns source ids a fresh, so any value placed here 1.90 + // before calling Write will be lost. 1.91 + int source_id; 1.92 + }; 1.93 + 1.94 + // A function. 1.95 + struct Function { 1.96 + // For sorting by address. (Not style-guide compliant, but it's 1.97 + // stupid not to put this in the struct.) 1.98 + static bool CompareByAddress(const Function *x, const Function *y) { 1.99 + return x->address < y->address; 1.100 + } 1.101 + 1.102 + // The function's name. 1.103 + string name; 1.104 + 1.105 + // The start address and length of the function's code. 1.106 + Address address, size; 1.107 + 1.108 + // The function's parameter size. 1.109 + Address parameter_size; 1.110 + 1.111 + // Source lines belonging to this function, sorted by increasing 1.112 + // address. 1.113 + vector<Line> lines; 1.114 + }; 1.115 + 1.116 + // A source line. 1.117 + struct Line { 1.118 + // For sorting by address. (Not style-guide compliant, but it's 1.119 + // stupid not to put this in the struct.) 1.120 + static bool CompareByAddress(const Module::Line &x, const Module::Line &y) { 1.121 + return x.address < y.address; 1.122 + } 1.123 + 1.124 + Address address, size; // The address and size of the line's code. 1.125 + File *file; // The source file. 1.126 + int number; // The source line number. 1.127 + }; 1.128 + 1.129 + // An exported symbol. 1.130 + struct Extern { 1.131 + Address address; 1.132 + string name; 1.133 + }; 1.134 + 1.135 + // Representation of an expression. This can either be a postfix 1.136 + // expression, in which case it is stored as a string, or a simple 1.137 + // expression of the form (identifier + imm) or *(identifier + imm). 1.138 + // It can also be invalid (denoting "no value"). 1.139 + enum ExprHow { 1.140 + kExprInvalid = 1, 1.141 + kExprPostfix, 1.142 + kExprSimple, 1.143 + kExprSimpleMem 1.144 + }; 1.145 + struct Expr { 1.146 + // Construct a simple-form expression 1.147 + Expr(const UniqueString* ident, long offset, bool deref) { 1.148 + if (ident == ustr__empty()) { 1.149 + Expr(); 1.150 + } else { 1.151 + postfix_ = ""; 1.152 + ident_ = ident; 1.153 + offset_ = offset; 1.154 + how_ = deref ? kExprSimpleMem : kExprSimple; 1.155 + } 1.156 + } 1.157 + // Construct an expression from a postfix string 1.158 + Expr(string postfix) { 1.159 + if (postfix.empty()) { 1.160 + Expr(); 1.161 + } else { 1.162 + postfix_ = postfix; 1.163 + ident_ = NULL; 1.164 + offset_ = 0; 1.165 + how_ = kExprPostfix; 1.166 + } 1.167 + } 1.168 + // Construct an invalid expression 1.169 + Expr() { 1.170 + postfix_ = ""; 1.171 + ident_ = NULL; 1.172 + offset_ = 0; 1.173 + how_ = kExprInvalid; 1.174 + } 1.175 + bool isExprInvalid() const { return how_ == kExprInvalid; } 1.176 + 1.177 + // Return the postfix expression string, either directly, 1.178 + // if this is a postfix expression, or by synthesising it 1.179 + // for a simple expression. 1.180 + string getExprPostfix() const { 1.181 + switch (how_) { 1.182 + case kExprPostfix: 1.183 + return postfix_; 1.184 + case kExprSimple: 1.185 + case kExprSimpleMem: { 1.186 + char buf[40]; 1.187 + sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+', 1.188 + how_ == kExprSimple ? "" : " ^"); 1.189 + return string(FromUniqueString(ident_)) + string(buf); 1.190 + } 1.191 + case kExprInvalid: 1.192 + default: 1.193 + assert(0 && "getExprPostfix: invalid Module::Expr type"); 1.194 + return "Expr::genExprPostfix: kExprInvalid"; 1.195 + } 1.196 + } 1.197 + 1.198 + bool operator==(const Expr& other) const { 1.199 + return how_ == other.how_ && 1.200 + ident_ == other.ident_ && 1.201 + offset_ == other.offset_ && 1.202 + postfix_ == other.postfix_; 1.203 + } 1.204 + 1.205 + // Returns an Expr which evaluates to |this| + |delta| 1.206 + Expr add_delta(long delta) { 1.207 + if (delta == 0) { 1.208 + return *this; 1.209 + } 1.210 + // If it's a simple form expression of the form "identifier + offset", 1.211 + // simply add |delta| on to |offset|. In the other two possible 1.212 + // cases: 1.213 + // *(identifier + offset) 1.214 + // completely arbitrary postfix expression string 1.215 + // the only option is to "downgrade" it to a postfix expression and add 1.216 + // "+/- delta" at the end of the string, since the result can't be 1.217 + // represented in the simple form. 1.218 + switch (how_) { 1.219 + case kExprSimpleMem: 1.220 + case kExprPostfix: { 1.221 + char buf[40]; 1.222 + sprintf(buf, " %ld %c", labs(delta), delta < 0 ? '-' : '+'); 1.223 + return Expr(getExprPostfix() + string(buf)); 1.224 + } 1.225 + case kExprSimple: 1.226 + return Expr(ident_, offset_ + delta, false); 1.227 + case kExprInvalid: 1.228 + default: 1.229 + assert(0 && "add_delta: invalid Module::Expr type"); 1.230 + // Invalid inputs produce an invalid result 1.231 + return Expr(); 1.232 + } 1.233 + } 1.234 + 1.235 + // Returns an Expr which evaluates to *|this| 1.236 + Expr deref() { 1.237 + // In the simplest case, a kExprSimple can be changed into a 1.238 + // kExprSimpleMem. In all other cases it has to be dumped as a 1.239 + // postfix string, and " ^" added at the end. 1.240 + switch (how_) { 1.241 + case kExprSimple: { 1.242 + Expr t = *this; 1.243 + t.how_ = kExprSimpleMem; 1.244 + return t; 1.245 + } 1.246 + case kExprSimpleMem: 1.247 + case kExprPostfix: { 1.248 + return Expr(getExprPostfix() + " ^"); 1.249 + } 1.250 + case kExprInvalid: 1.251 + default: 1.252 + assert(0 && "deref: invalid Module::Expr type"); 1.253 + // Invalid inputs produce an invalid result 1.254 + return Expr(); 1.255 + } 1.256 + } 1.257 + 1.258 + // The identifier that gives the starting value for simple expressions. 1.259 + const UniqueString* ident_; 1.260 + // The offset to add for simple expressions. 1.261 + long offset_; 1.262 + // The Postfix expression string to evaluate for non-simple expressions. 1.263 + string postfix_; 1.264 + // The operation expressed by this expression. 1.265 + ExprHow how_; 1.266 + 1.267 + friend std::ostream& operator<<(std::ostream& stream, const Expr& expr); 1.268 + }; 1.269 + 1.270 + // A map from register names to expressions that recover 1.271 + // their values. This can represent a complete set of rules to 1.272 + // follow at some address, or a set of changes to be applied to an 1.273 + // extant set of rules. 1.274 + typedef map<const UniqueString*, Expr> RuleMap; 1.275 + 1.276 + // A map from addresses to RuleMaps, representing changes that take 1.277 + // effect at given addresses. 1.278 + typedef map<Address, RuleMap> RuleChangeMap; 1.279 + 1.280 + // A range of 'STACK CFI' stack walking information. An instance of 1.281 + // this structure corresponds to a 'STACK CFI INIT' record and the 1.282 + // subsequent 'STACK CFI' records that fall within its range. 1.283 + struct StackFrameEntry { 1.284 + // The starting address and number of bytes of machine code this 1.285 + // entry covers. 1.286 + Address address, size; 1.287 + 1.288 + // The initial register recovery rules, in force at the starting 1.289 + // address. 1.290 + RuleMap initial_rules; 1.291 + 1.292 + // A map from addresses to rule changes. To find the rules in 1.293 + // force at a given address, start with initial_rules, and then 1.294 + // apply the changes given in this map for all addresses up to and 1.295 + // including the address you're interested in. 1.296 + RuleChangeMap rule_changes; 1.297 + }; 1.298 + 1.299 + struct FunctionCompare { 1.300 + bool operator() (const Function *lhs, 1.301 + const Function *rhs) const { 1.302 + if (lhs->address == rhs->address) 1.303 + return lhs->name < rhs->name; 1.304 + return lhs->address < rhs->address; 1.305 + } 1.306 + }; 1.307 + 1.308 + struct ExternCompare { 1.309 + bool operator() (const Extern *lhs, 1.310 + const Extern *rhs) const { 1.311 + return lhs->address < rhs->address; 1.312 + } 1.313 + }; 1.314 + 1.315 + struct StackFrameEntryCompare { 1.316 + bool operator() (const StackFrameEntry* lhs, 1.317 + const StackFrameEntry* rhs) const { 1.318 + return lhs->address < rhs->address; 1.319 + } 1.320 + }; 1.321 + 1.322 + // Create a new module with the given name, operating system, 1.323 + // architecture, and ID string. 1.324 + Module(const string &name, const string &os, const string &architecture, 1.325 + const string &id); 1.326 + ~Module(); 1.327 + 1.328 + // Set the module's load address to LOAD_ADDRESS; addresses given 1.329 + // for functions and lines will be written to the Breakpad symbol 1.330 + // file as offsets from this address. Construction initializes this 1.331 + // module's load address to zero: addresses written to the symbol 1.332 + // file will be the same as they appear in the Function, Line, and 1.333 + // StackFrameEntry structures. 1.334 + // 1.335 + // Note that this member function has no effect on addresses stored 1.336 + // in the data added to this module; the Write member function 1.337 + // simply subtracts off the load address from addresses before it 1.338 + // prints them. Only the last load address given before calling 1.339 + // Write is used. 1.340 + void SetLoadAddress(Address load_address); 1.341 + 1.342 + // Add FUNCTION to the module. FUNCTION's name must not be empty. 1.343 + // This module owns all Function objects added with this function: 1.344 + // destroying the module destroys them as well. 1.345 + void AddFunction(Function *function); 1.346 + 1.347 + // Add all the functions in [BEGIN,END) to the module. 1.348 + // This module owns all Function objects added with this function: 1.349 + // destroying the module destroys them as well. 1.350 + void AddFunctions(vector<Function *>::iterator begin, 1.351 + vector<Function *>::iterator end); 1.352 + 1.353 + // Add STACK_FRAME_ENTRY to the module. 1.354 + // This module owns all StackFrameEntry objects added with this 1.355 + // function: destroying the module destroys them as well. 1.356 + void AddStackFrameEntry(StackFrameEntry *stack_frame_entry); 1.357 + 1.358 + // Add PUBLIC to the module. 1.359 + // This module owns all Extern objects added with this function: 1.360 + // destroying the module destroys them as well. 1.361 + void AddExtern(Extern *ext); 1.362 + 1.363 + // If this module has a file named NAME, return a pointer to it. If 1.364 + // it has none, then create one and return a pointer to the new 1.365 + // file. This module owns all File objects created using these 1.366 + // functions; destroying the module destroys them as well. 1.367 + File *FindFile(const string &name); 1.368 + File *FindFile(const char *name); 1.369 + 1.370 + // If this module has a file named NAME, return a pointer to it. 1.371 + // Otherwise, return NULL. 1.372 + File *FindExistingFile(const string &name); 1.373 + 1.374 + // Insert pointers to the functions added to this module at I in 1.375 + // VEC. The pointed-to Functions are still owned by this module. 1.376 + // (Since this is effectively a copy of the function list, this is 1.377 + // mostly useful for testing; other uses should probably get a more 1.378 + // appropriate interface.) 1.379 + void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i); 1.380 + 1.381 + // If this module has a function at ADDRESS, return a pointer to it. 1.382 + // Otherwise, return NULL. 1.383 + Function* FindFunctionByAddress(Address address); 1.384 + 1.385 + // Insert pointers to the externs added to this module at I in 1.386 + // VEC. The pointed-to Externs are still owned by this module. 1.387 + // (Since this is effectively a copy of the extern list, this is 1.388 + // mostly useful for testing; other uses should probably get a more 1.389 + // appropriate interface.) 1.390 + void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i); 1.391 + 1.392 + // If this module has an extern whose base address is less than ADDRESS, 1.393 + // return a pointer to it. Otherwise, return NULL. 1.394 + Extern* FindExternByAddress(Address address); 1.395 + 1.396 + // Clear VEC and fill it with pointers to the Files added to this 1.397 + // module, sorted by name. The pointed-to Files are still owned by 1.398 + // this module. (Since this is effectively a copy of the file list, 1.399 + // this is mostly useful for testing; other uses should probably get 1.400 + // a more appropriate interface.) 1.401 + void GetFiles(vector<File *> *vec); 1.402 + 1.403 + // Clear VEC and fill it with pointers to the StackFrameEntry 1.404 + // objects that have been added to this module. (Since this is 1.405 + // effectively a copy of the stack frame entry list, this is mostly 1.406 + // useful for testing; other uses should probably get 1.407 + // a more appropriate interface.) 1.408 + void GetStackFrameEntries(vector<StackFrameEntry *> *vec); 1.409 + 1.410 + // If this module has a StackFrameEntry whose address range covers 1.411 + // ADDRESS, return it. Otherwise return NULL. 1.412 + StackFrameEntry* FindStackFrameEntryByAddress(Address address); 1.413 + 1.414 + // Find those files in this module that are actually referred to by 1.415 + // functions' line number data, and assign them source id numbers. 1.416 + // Set the source id numbers for all other files --- unused by the 1.417 + // source line data --- to -1. We do this before writing out the 1.418 + // symbol file, at which point we omit any unused files. 1.419 + void AssignSourceIds(); 1.420 + 1.421 + // Call AssignSourceIds, and write this module to STREAM in the 1.422 + // breakpad symbol format. Return true if all goes well, or false if 1.423 + // an error occurs. This method writes out: 1.424 + // - a header based on the values given to the constructor, 1.425 + // If symbol_data is not ONLY_CFI then: 1.426 + // - the source files added via FindFile, 1.427 + // - the functions added via AddFunctions, each with its lines, 1.428 + // - all public records, 1.429 + // If symbol_data is not NO_CFI then: 1.430 + // - all CFI records. 1.431 + // Addresses in the output are all relative to the load address 1.432 + // established by SetLoadAddress. 1.433 + bool Write(std::ostream &stream, SymbolData symbol_data); 1.434 + 1.435 + private: 1.436 + // Report an error that has occurred writing the symbol file, using 1.437 + // errno to find the appropriate cause. Return false. 1.438 + static bool ReportError(); 1.439 + 1.440 + // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI' 1.441 + // records, without a final newline. Return true if all goes well; 1.442 + // if an error occurs, return false, and leave errno set. 1.443 + static bool WriteRuleMap(const RuleMap &rule_map, std::ostream &stream); 1.444 + 1.445 + // Module header entries. 1.446 + string name_, os_, architecture_, id_; 1.447 + 1.448 + // The module's nominal load address. Addresses for functions and 1.449 + // lines are absolute, assuming the module is loaded at this 1.450 + // address. 1.451 + Address load_address_; 1.452 + 1.453 + // Relation for maps whose keys are strings shared with some other 1.454 + // structure. 1.455 + struct CompareStringPtrs { 1.456 + bool operator()(const string *x, const string *y) const { return *x < *y; } 1.457 + }; 1.458 + 1.459 + // A map from filenames to File structures. The map's keys are 1.460 + // pointers to the Files' names. 1.461 + typedef map<const string *, File *, CompareStringPtrs> FileByNameMap; 1.462 + 1.463 + // A set containing Function structures, sorted by address. 1.464 + typedef set<Function *, FunctionCompare> FunctionSet; 1.465 + 1.466 + // A set containing Extern structures, sorted by address. 1.467 + typedef set<Extern *, ExternCompare> ExternSet; 1.468 + 1.469 + // A set containing StackFrameEntry structures, sorted by address. 1.470 + typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet; 1.471 + 1.472 + // The module owns all the files and functions that have been added 1.473 + // to it; destroying the module frees the Files and Functions these 1.474 + // point to. 1.475 + FileByNameMap files_; // This module's source files. 1.476 + FunctionSet functions_; // This module's functions. 1.477 + 1.478 + // The module owns all the call frame info entries that have been 1.479 + // added to it. 1.480 + StackFrameEntrySet stack_frame_entries_; 1.481 + 1.482 + // The module owns all the externs that have been added to it; 1.483 + // destroying the module frees the Externs these point to. 1.484 + ExternSet externs_; 1.485 +}; 1.486 + 1.487 +} // namespace google_breakpad 1.488 + 1.489 +#endif // COMMON_LINUX_MODULE_H__