Home | History | Annotate | Download | only in common
      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 (at) mozilla.com> <jimb (at) 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 "common/symbol_data.h"
     48 #include "common/using_std_string.h"
     49 #include "google_breakpad/common/breakpad_types.h"
     50 
     51 namespace google_breakpad {
     52 
     53 using std::set;
     54 using std::vector;
     55 using std::map;
     56 
     57 // A Module represents the contents of a module, and supports methods
     58 // for adding information produced by parsing STABS or DWARF data
     59 // --- possibly both from the same file --- and then writing out the
     60 // unified contents as a Breakpad-format symbol file.
     61 class Module {
     62  public:
     63   // The type of addresses and sizes in a symbol table.
     64   typedef uint64_t Address;
     65   struct File;
     66   struct Function;
     67   struct Line;
     68   struct Extern;
     69 
     70   // Addresses appearing in File, Function, and Line structures are
     71   // absolute, not relative to the the module's load address.  That
     72   // is, if the module were loaded at its nominal load address, the
     73   // addresses would be correct.
     74 
     75   // A source file.
     76   struct File {
     77     explicit File(const string &name_input) : name(name_input), source_id(0) {}
     78 
     79     // The name of the source file.
     80     const string name;
     81 
     82     // The file's source id.  The Write member function clears this
     83     // field and assigns source ids a fresh, so any value placed here
     84     // before calling Write will be lost.
     85     int source_id;
     86   };
     87 
     88   // A function.
     89   struct Function {
     90     Function(const string &name_input, const Address &address_input) :
     91         name(name_input), address(address_input), size(0), parameter_size(0) {}
     92 
     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     const string name;
    101 
    102     // The start address and length of the function's code.
    103     const Address address;
    104     Address size;
    105 
    106     // The function's parameter size.
    107     Address parameter_size;
    108 
    109     // Source lines belonging to this function, sorted by increasing
    110     // address.
    111     vector<Line> lines;
    112   };
    113 
    114   // A source line.
    115   struct Line {
    116     // For sorting by address.  (Not style-guide compliant, but it's
    117     // stupid not to put this in the struct.)
    118     static bool CompareByAddress(const Module::Line &x, const Module::Line &y) {
    119       return x.address < y.address;
    120     }
    121 
    122     Address address, size;    // The address and size of the line's code.
    123     File *file;                // The source file.
    124     int number;                // The source line number.
    125   };
    126 
    127   // An exported symbol.
    128   struct Extern {
    129     explicit Extern(const Address &address_input) : address(address_input) {}
    130     const Address address;
    131     string name;
    132   };
    133 
    134   // A map from register names to postfix expressions that recover
    135   // their their values. This can represent a complete set of rules to
    136   // follow at some address, or a set of changes to be applied to an
    137   // extant set of rules.
    138   typedef map<string, string> RuleMap;
    139 
    140   // A map from addresses to RuleMaps, representing changes that take
    141   // effect at given addresses.
    142   typedef map<Address, RuleMap> RuleChangeMap;
    143 
    144   // A range of 'STACK CFI' stack walking information. An instance of
    145   // this structure corresponds to a 'STACK CFI INIT' record and the
    146   // subsequent 'STACK CFI' records that fall within its range.
    147   struct StackFrameEntry {
    148     // The starting address and number of bytes of machine code this
    149     // entry covers.
    150     Address address, size;
    151 
    152     // The initial register recovery rules, in force at the starting
    153     // address.
    154     RuleMap initial_rules;
    155 
    156     // A map from addresses to rule changes. To find the rules in
    157     // force at a given address, start with initial_rules, and then
    158     // apply the changes given in this map for all addresses up to and
    159     // including the address you're interested in.
    160     RuleChangeMap rule_changes;
    161   };
    162 
    163   struct FunctionCompare {
    164     bool operator() (const Function *lhs,
    165                      const Function *rhs) const {
    166       if (lhs->address == rhs->address)
    167         return lhs->name < rhs->name;
    168       return lhs->address < rhs->address;
    169     }
    170   };
    171 
    172   struct ExternCompare {
    173     bool operator() (const Extern *lhs,
    174                      const Extern *rhs) const {
    175       return lhs->address < rhs->address;
    176     }
    177   };
    178 
    179   // Create a new module with the given name, operating system,
    180   // architecture, and ID string.
    181   Module(const string &name, const string &os, const string &architecture,
    182          const string &id);
    183   ~Module();
    184 
    185   // Set the module's load address to LOAD_ADDRESS; addresses given
    186   // for functions and lines will be written to the Breakpad symbol
    187   // file as offsets from this address.  Construction initializes this
    188   // module's load address to zero: addresses written to the symbol
    189   // file will be the same as they appear in the Function, Line, and
    190   // StackFrameEntry structures.
    191   //
    192   // Note that this member function has no effect on addresses stored
    193   // in the data added to this module; the Write member function
    194   // simply subtracts off the load address from addresses before it
    195   // prints them. Only the last load address given before calling
    196   // Write is used.
    197   void SetLoadAddress(Address load_address);
    198 
    199   // Add FUNCTION to the module. FUNCTION's name must not be empty.
    200   // This module owns all Function objects added with this function:
    201   // destroying the module destroys them as well.
    202   void AddFunction(Function *function);
    203 
    204   // Add all the functions in [BEGIN,END) to the module.
    205   // This module owns all Function objects added with this function:
    206   // destroying the module destroys them as well.
    207   void AddFunctions(vector<Function *>::iterator begin,
    208                     vector<Function *>::iterator end);
    209 
    210   // Add STACK_FRAME_ENTRY to the module.
    211   // This module owns all StackFrameEntry objects added with this
    212   // function: destroying the module destroys them as well.
    213   void AddStackFrameEntry(StackFrameEntry *stack_frame_entry);
    214 
    215   // Add PUBLIC to the module.
    216   // This module owns all Extern objects added with this function:
    217   // destroying the module destroys them as well.
    218   void AddExtern(Extern *ext);
    219 
    220   // If this module has a file named NAME, return a pointer to it. If
    221   // it has none, then create one and return a pointer to the new
    222   // file. This module owns all File objects created using these
    223   // functions; destroying the module destroys them as well.
    224   File *FindFile(const string &name);
    225   File *FindFile(const char *name);
    226 
    227   // If this module has a file named NAME, return a pointer to it.
    228   // Otherwise, return NULL.
    229   File *FindExistingFile(const string &name);
    230 
    231   // Insert pointers to the functions added to this module at I in
    232   // VEC. The pointed-to Functions are still owned by this module.
    233   // (Since this is effectively a copy of the function list, this is
    234   // mostly useful for testing; other uses should probably get a more
    235   // appropriate interface.)
    236   void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
    237 
    238   // Insert pointers to the externs added to this module at I in
    239   // VEC. The pointed-to Externs are still owned by this module.
    240   // (Since this is effectively a copy of the extern list, this is
    241   // mostly useful for testing; other uses should probably get a more
    242   // appropriate interface.)
    243   void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
    244 
    245   // Clear VEC and fill it with pointers to the Files added to this
    246   // module, sorted by name. The pointed-to Files are still owned by
    247   // this module. (Since this is effectively a copy of the file list,
    248   // this is mostly useful for testing; other uses should probably get
    249   // a more appropriate interface.)
    250   void GetFiles(vector<File *> *vec);
    251 
    252   // Clear VEC and fill it with pointers to the StackFrameEntry
    253   // objects that have been added to this module. (Since this is
    254   // effectively a copy of the stack frame entry list, this is mostly
    255   // useful for testing; other uses should probably get
    256   // a more appropriate interface.)
    257   void GetStackFrameEntries(vector<StackFrameEntry *> *vec) const;
    258 
    259   // Find those files in this module that are actually referred to by
    260   // functions' line number data, and assign them source id numbers.
    261   // Set the source id numbers for all other files --- unused by the
    262   // source line data --- to -1.  We do this before writing out the
    263   // symbol file, at which point we omit any unused files.
    264   void AssignSourceIds();
    265 
    266   // Call AssignSourceIds, and write this module to STREAM in the
    267   // breakpad symbol format. Return true if all goes well, or false if
    268   // an error occurs. This method writes out:
    269   // - a header based on the values given to the constructor,
    270   // If symbol_data is not ONLY_CFI then:
    271   // - the source files added via FindFile,
    272   // - the functions added via AddFunctions, each with its lines,
    273   // - all public records,
    274   // If symbol_data is not NO_CFI then:
    275   // - all CFI records.
    276   // Addresses in the output are all relative to the load address
    277   // established by SetLoadAddress.
    278   bool Write(std::ostream &stream, SymbolData symbol_data);
    279 
    280   string name() const { return name_; }
    281   string os() const { return os_; }
    282   string architecture() const { return architecture_; }
    283   string identifier() const { return id_; }
    284 
    285  private:
    286   // Report an error that has occurred writing the symbol file, using
    287   // errno to find the appropriate cause.  Return false.
    288   static bool ReportError();
    289 
    290   // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI'
    291   // records, without a final newline. Return true if all goes well;
    292   // if an error occurs, return false, and leave errno set.
    293   static bool WriteRuleMap(const RuleMap &rule_map, std::ostream &stream);
    294 
    295   // Module header entries.
    296   string name_, os_, architecture_, id_;
    297 
    298   // The module's nominal load address.  Addresses for functions and
    299   // lines are absolute, assuming the module is loaded at this
    300   // address.
    301   Address load_address_;
    302 
    303   // Relation for maps whose keys are strings shared with some other
    304   // structure.
    305   struct CompareStringPtrs {
    306     bool operator()(const string *x, const string *y) const { return *x < *y; }
    307   };
    308 
    309   // A map from filenames to File structures.  The map's keys are
    310   // pointers to the Files' names.
    311   typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
    312 
    313   // A set containing Function structures, sorted by address.
    314   typedef set<Function *, FunctionCompare> FunctionSet;
    315 
    316   // A set containing Extern structures, sorted by address.
    317   typedef set<Extern *, ExternCompare> ExternSet;
    318 
    319   // The module owns all the files and functions that have been added
    320   // to it; destroying the module frees the Files and Functions these
    321   // point to.
    322   FileByNameMap files_;    // This module's source files.
    323   FunctionSet functions_;  // This module's functions.
    324 
    325   // The module owns all the call frame info entries that have been
    326   // added to it.
    327   vector<StackFrameEntry *> stack_frame_entries_;
    328 
    329   // The module owns all the externs that have been added to it;
    330   // destroying the module frees the Externs these point to.
    331   ExternSet externs_;
    332 };
    333 
    334 }  // namespace google_breakpad
    335 
    336 #endif  // COMMON_LINUX_MODULE_H__
    337