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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // -*- mode: c++ -*-
     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.
    32 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    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.
    38 #ifndef COMMON_LINUX_MODULE_H__
    39 #define COMMON_LINUX_MODULE_H__
    41 #include <iostream>
    42 #include <map>
    43 #include <set>
    44 #include <string>
    45 #include <vector>
    47 #include <assert.h>
    48 #include <stdlib.h>
    49 #include <stdio.h>
    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"
    56 namespace google_breakpad {
    58 using std::set;
    59 using std::vector;
    60 using std::map;
    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;
    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.
    80   // A source file.
    81   struct File {
    82     // The name of the source file.
    83     string name;
    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   };
    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     }
    99     // The function's name.
   100     string name;
   102     // The start address and length of the function's code.
   103     Address address, size;
   105     // The function's parameter size.
   106     Address parameter_size;
   108     // Source lines belonging to this function, sorted by increasing
   109     // address.
   110     vector<Line> lines;
   111   };
   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     }
   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   };
   126   // An exported symbol.
   127   struct Extern {
   128     Address address;
   129     string name;
   130   };
   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; }
   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     }
   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     }
   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     }
   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     }
   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_;
   264     friend std::ostream& operator<<(std::ostream& stream, const Expr& expr);
   265   };
   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;
   273   // A map from addresses to RuleMaps, representing changes that take
   274   // effect at given addresses.
   275   typedef map<Address, RuleMap> RuleChangeMap;
   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;
   285     // The initial register recovery rules, in force at the starting
   286     // address.
   287     RuleMap initial_rules;
   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   };
   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   };
   305   struct ExternCompare {
   306     bool operator() (const Extern *lhs,
   307                      const Extern *rhs) const {
   308       return lhs->address < rhs->address;
   309     }
   310   };
   312   struct StackFrameEntryCompare {
   313     bool operator() (const StackFrameEntry* lhs,
   314                      const StackFrameEntry* rhs) const {
   315       return lhs->address < rhs->address;
   316     }
   317   };
   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();
   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);
   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);
   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);
   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);
   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);
   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);
   367   // If this module has a file named NAME, return a pointer to it.
   368   // Otherwise, return NULL.
   369   File *FindExistingFile(const string &name);
   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);
   378   // If this module has a function at ADDRESS, return a pointer to it.
   379   // Otherwise, return NULL.
   380   Function* FindFunctionByAddress(Address address);
   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);
   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);
   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);
   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);
   407   // If this module has a StackFrameEntry whose address range covers
   408   // ADDRESS, return it. Otherwise return NULL.
   409   StackFrameEntry* FindStackFrameEntryByAddress(Address address);
   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();
   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);
   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();
   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);
   442   // Module header entries.
   443   string name_, os_, architecture_, id_;
   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_;
   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   };
   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;
   460   // A set containing Function structures, sorted by address.
   461   typedef set<Function *, FunctionCompare> FunctionSet;
   463   // A set containing Extern structures, sorted by address.
   464   typedef set<Extern *, ExternCompare> ExternSet;
   466   // A set containing StackFrameEntry structures, sorted by address.
   467   typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet;
   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.
   475   // The module owns all the call frame info entries that have been
   476   // added to it.
   477   StackFrameEntrySet stack_frame_entries_;
   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 };
   484 }  // namespace google_breakpad
   486 #endif  // COMMON_LINUX_MODULE_H__

mercurial