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

changeset 0
6474c204b198
     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__

mercurial