| // -*- mode: c++ -*- |
| |
| // Copyright (c) 2010 Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
| |
| // module.h: Define google_breakpad::Module. A Module holds debugging |
| // information, and can write that information out as a Breakpad |
| // symbol file. |
| |
| #ifndef COMMON_LINUX_MODULE_H__ |
| #define COMMON_LINUX_MODULE_H__ |
| |
| #include <iostream> |
| #include <limits> |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "common/symbol_data.h" |
| #include "common/using_std_string.h" |
| #include "google_breakpad/common/breakpad_types.h" |
| |
| namespace google_breakpad { |
| |
| using std::set; |
| using std::vector; |
| using std::map; |
| |
| // A Module represents the contents of a module, and supports methods |
| // for adding information produced by parsing STABS or DWARF data |
| // --- possibly both from the same file --- and then writing out the |
| // unified contents as a Breakpad-format symbol file. |
| class Module { |
| public: |
| // The type of addresses and sizes in a symbol table. |
| typedef uint64_t Address; |
| static constexpr uint64_t kMaxAddress = std::numeric_limits<Address>::max(); |
| struct File; |
| struct Function; |
| struct Line; |
| struct Extern; |
| |
| // Addresses appearing in File, Function, and Line structures are |
| // absolute, not relative to the the module's load address. That |
| // is, if the module were loaded at its nominal load address, the |
| // addresses would be correct. |
| |
| // A source file. |
| struct File { |
| explicit File(const string& name_input) : name(name_input), source_id(0) {} |
| |
| // The name of the source file. |
| const string name; |
| |
| // The file's source id. The Write member function clears this |
| // field and assigns source ids a fresh, so any value placed here |
| // before calling Write will be lost. |
| int source_id; |
| }; |
| |
| // An address range. |
| struct Range { |
| Range(const Address address_input, const Address size_input) : |
| address(address_input), size(size_input) { } |
| |
| Address address; |
| Address size; |
| }; |
| |
| // A function. |
| struct Function { |
| Function(const string& name_input, const Address& address_input) : |
| name(name_input), address(address_input), parameter_size(0) {} |
| |
| // For sorting by address. (Not style-guide compliant, but it's |
| // stupid not to put this in the struct.) |
| static bool CompareByAddress(const Function* x, const Function* y) { |
| return x->address < y->address; |
| } |
| |
| // The function's name. |
| string name; |
| |
| // The start address and the address ranges covered by the function. |
| const Address address; |
| vector<Range> ranges; |
| |
| // The function's parameter size. |
| Address parameter_size; |
| |
| // Source lines belonging to this function, sorted by increasing |
| // address. |
| vector<Line> lines; |
| }; |
| |
| // A source line. |
| struct Line { |
| // For sorting by address. (Not style-guide compliant, but it's |
| // stupid not to put this in the struct.) |
| static bool CompareByAddress(const Module::Line& x, const Module::Line& y) { |
| return x.address < y.address; |
| } |
| |
| Address address, size; // The address and size of the line's code. |
| File* file; // The source file. |
| int number; // The source line number. |
| }; |
| |
| // An exported symbol. |
| struct Extern { |
| explicit Extern(const Address& address_input) : address(address_input) {} |
| const Address address; |
| string name; |
| }; |
| |
| // A map from register names to postfix expressions that recover |
| // their their values. This can represent a complete set of rules to |
| // follow at some address, or a set of changes to be applied to an |
| // extant set of rules. |
| typedef map<string, string> RuleMap; |
| |
| // A map from addresses to RuleMaps, representing changes that take |
| // effect at given addresses. |
| typedef map<Address, RuleMap> RuleChangeMap; |
| |
| // A range of 'STACK CFI' stack walking information. An instance of |
| // this structure corresponds to a 'STACK CFI INIT' record and the |
| // subsequent 'STACK CFI' records that fall within its range. |
| struct StackFrameEntry { |
| // The starting address and number of bytes of machine code this |
| // entry covers. |
| Address address, size; |
| |
| // The initial register recovery rules, in force at the starting |
| // address. |
| RuleMap initial_rules; |
| |
| // A map from addresses to rule changes. To find the rules in |
| // force at a given address, start with initial_rules, and then |
| // apply the changes given in this map for all addresses up to and |
| // including the address you're interested in. |
| RuleChangeMap rule_changes; |
| }; |
| |
| struct FunctionCompare { |
| bool operator() (const Function* lhs, const Function* rhs) const { |
| if (lhs->address == rhs->address) |
| return lhs->name < rhs->name; |
| return lhs->address < rhs->address; |
| } |
| }; |
| |
| struct ExternCompare { |
| bool operator() (const Extern* lhs, const Extern* rhs) const { |
| return lhs->address < rhs->address; |
| } |
| }; |
| |
| // Create a new module with the given name, operating system, |
| // architecture, and ID string. |
| Module(const string& name, const string& os, const string& architecture, |
| const string& id, const string& code_id = ""); |
| ~Module(); |
| |
| // Set the module's load address to LOAD_ADDRESS; addresses given |
| // for functions and lines will be written to the Breakpad symbol |
| // file as offsets from this address. Construction initializes this |
| // module's load address to zero: addresses written to the symbol |
| // file will be the same as they appear in the Function, Line, and |
| // StackFrameEntry structures. |
| // |
| // Note that this member function has no effect on addresses stored |
| // in the data added to this module; the Write member function |
| // simply subtracts off the load address from addresses before it |
| // prints them. Only the last load address given before calling |
| // Write is used. |
| void SetLoadAddress(Address load_address); |
| |
| // Sets address filtering on elements added to the module. This allows |
| // libraries with extraneous debug symbols to generate symbol files containing |
| // only relevant symbols. For example, an LLD-generated partition library may |
| // contain debug information pertaining to all partitions derived from a |
| // single "combined" library. Filtering applies only to elements added after |
| // this method is called. |
| void SetAddressRanges(const vector<Range>& ranges); |
| |
| // Add FUNCTION to the module. FUNCTION's name must not be empty. |
| // This module owns all Function objects added with this function: |
| // destroying the module destroys them as well. |
| void AddFunction(Function* function); |
| |
| // Add all the functions in [BEGIN,END) to the module. |
| // This module owns all Function objects added with this function: |
| // destroying the module destroys them as well. |
| void AddFunctions(vector<Function*>::iterator begin, |
| vector<Function*>::iterator end); |
| |
| // Add STACK_FRAME_ENTRY to the module. |
| // This module owns all StackFrameEntry objects added with this |
| // function: destroying the module destroys them as well. |
| void AddStackFrameEntry(StackFrameEntry* stack_frame_entry); |
| |
| // Add PUBLIC to the module. |
| // This module owns all Extern objects added with this function: |
| // destroying the module destroys them as well. |
| void AddExtern(Extern* ext); |
| |
| // If this module has a file named NAME, return a pointer to it. If |
| // it has none, then create one and return a pointer to the new |
| // file. This module owns all File objects created using these |
| // functions; destroying the module destroys them as well. |
| File* FindFile(const string& name); |
| File* FindFile(const char* name); |
| |
| // If this module has a file named NAME, return a pointer to it. |
| // Otherwise, return NULL. |
| File* FindExistingFile(const string& name); |
| |
| // Insert pointers to the functions added to this module at I in |
| // VEC. The pointed-to Functions are still owned by this module. |
| // (Since this is effectively a copy of the function list, this is |
| // mostly useful for testing; other uses should probably get a more |
| // appropriate interface.) |
| void GetFunctions(vector<Function*>* vec, vector<Function*>::iterator i); |
| |
| // Insert pointers to the externs added to this module at I in |
| // VEC. The pointed-to Externs are still owned by this module. |
| // (Since this is effectively a copy of the extern list, this is |
| // mostly useful for testing; other uses should probably get a more |
| // appropriate interface.) |
| void GetExterns(vector<Extern*>* vec, vector<Extern*>::iterator i); |
| |
| // Clear VEC and fill it with pointers to the Files added to this |
| // module, sorted by name. The pointed-to Files are still owned by |
| // this module. (Since this is effectively a copy of the file list, |
| // this is mostly useful for testing; other uses should probably get |
| // a more appropriate interface.) |
| void GetFiles(vector<File*>* vec); |
| |
| // Clear VEC and fill it with pointers to the StackFrameEntry |
| // objects that have been added to this module. (Since this is |
| // effectively a copy of the stack frame entry list, this is mostly |
| // useful for testing; other uses should probably get |
| // a more appropriate interface.) |
| void GetStackFrameEntries(vector<StackFrameEntry*>* vec) const; |
| |
| // Find those files in this module that are actually referred to by |
| // functions' line number data, and assign them source id numbers. |
| // Set the source id numbers for all other files --- unused by the |
| // source line data --- to -1. We do this before writing out the |
| // symbol file, at which point we omit any unused files. |
| void AssignSourceIds(); |
| |
| // Call AssignSourceIds, and write this module to STREAM in the |
| // breakpad symbol format. Return true if all goes well, or false if |
| // an error occurs. This method writes out: |
| // - a header based on the values given to the constructor, |
| // If symbol_data is not ONLY_CFI then: |
| // - the source files added via FindFile, |
| // - the functions added via AddFunctions, each with its lines, |
| // - all public records, |
| // If symbol_data is not NO_CFI then: |
| // - all CFI records. |
| // Addresses in the output are all relative to the load address |
| // established by SetLoadAddress. |
| bool Write(std::ostream& stream, SymbolData symbol_data); |
| |
| string name() const { return name_; } |
| string os() const { return os_; } |
| string architecture() const { return architecture_; } |
| string identifier() const { return id_; } |
| string code_identifier() const { return code_id_; } |
| |
| private: |
| // Report an error that has occurred writing the symbol file, using |
| // errno to find the appropriate cause. Return false. |
| static bool ReportError(); |
| |
| // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI' |
| // records, without a final newline. Return true if all goes well; |
| // if an error occurs, return false, and leave errno set. |
| static bool WriteRuleMap(const RuleMap& rule_map, std::ostream& stream); |
| |
| // Returns true of the specified address resides with an specified address |
| // range, or if no ranges have been specified. |
| bool AddressIsInModule(Address address) const; |
| |
| // Module header entries. |
| string name_, os_, architecture_, id_, code_id_; |
| |
| // The module's nominal load address. Addresses for functions and |
| // lines are absolute, assuming the module is loaded at this |
| // address. |
| Address load_address_; |
| |
| // The set of valid address ranges of the module. If specified, attempts to |
| // add elements residing outside these ranges will be silently filtered. |
| vector<Range> address_ranges_; |
| |
| // Relation for maps whose keys are strings shared with some other |
| // structure. |
| struct CompareStringPtrs { |
| bool operator()(const string* x, const string* y) const { return *x < *y; } |
| }; |
| |
| // A map from filenames to File structures. The map's keys are |
| // pointers to the Files' names. |
| typedef map<const string*, File*, CompareStringPtrs> FileByNameMap; |
| |
| // A set containing Function structures, sorted by address. |
| typedef set<Function*, FunctionCompare> FunctionSet; |
| |
| // A set containing Extern structures, sorted by address. |
| typedef set<Extern*, ExternCompare> ExternSet; |
| |
| // The module owns all the files and functions that have been added |
| // to it; destroying the module frees the Files and Functions these |
| // point to. |
| FileByNameMap files_; // This module's source files. |
| FunctionSet functions_; // This module's functions. |
| |
| // The module owns all the call frame info entries that have been |
| // added to it. |
| vector<StackFrameEntry*> stack_frame_entries_; |
| |
| // The module owns all the externs that have been added to it; |
| // destroying the module frees the Externs these point to. |
| ExternSet externs_; |
| }; |
| |
| } // namespace google_breakpad |
| |
| #endif // COMMON_LINUX_MODULE_H__ |