blob: 408e620b2663809d3fd3356d297dc8d8a5c55e66 [file] [log] [blame] [edit]
// -*- 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__