mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-10-13 23:27:46 +00:00
Move dead submodules in-tree
Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
parent
c0cceff365
commit
6c655321e6
4081 changed files with 1185566 additions and 45 deletions
519
externals/breakpad/src/common/module.h
vendored
Normal file
519
externals/breakpad/src/common/module.h
vendored
Normal file
|
@ -0,0 +1,519 @@
|
|||
// -*- mode: c++ -*-
|
||||
|
||||
// Copyright 2010 Google LLC
|
||||
//
|
||||
// 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 LLC 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 <functional>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/string_view.h"
|
||||
#include "common/symbol_data.h"
|
||||
#include "common/unordered.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 InlineOrigin;
|
||||
struct Inline;
|
||||
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(StringView 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.
|
||||
StringView 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;
|
||||
|
||||
// Inlined call sites belonging to this functions.
|
||||
vector<std::unique_ptr<Inline>> inlines;
|
||||
|
||||
// If this symbol has been folded with other symbols in the linked binary.
|
||||
bool is_multiple = false;
|
||||
|
||||
// If the function's name should be filled out from a matching Extern,
|
||||
// should they not match.
|
||||
bool prefer_extern_name = false;
|
||||
};
|
||||
|
||||
struct InlineOrigin {
|
||||
explicit InlineOrigin(StringView name) : id(-1), name(name) {}
|
||||
|
||||
// A unique id for each InlineOrigin object. INLINE records use the id to
|
||||
// refer to its INLINE_ORIGIN record.
|
||||
int id;
|
||||
|
||||
// The inlined function's name.
|
||||
StringView name;
|
||||
};
|
||||
|
||||
// A inlined call site.
|
||||
struct Inline {
|
||||
Inline(InlineOrigin* origin,
|
||||
const vector<Range>& ranges,
|
||||
int call_site_line,
|
||||
int call_site_file_id,
|
||||
int inline_nest_level,
|
||||
vector<std::unique_ptr<Inline>> child_inlines)
|
||||
: origin(origin),
|
||||
ranges(ranges),
|
||||
call_site_line(call_site_line),
|
||||
call_site_file_id(call_site_file_id),
|
||||
call_site_file(nullptr),
|
||||
inline_nest_level(inline_nest_level),
|
||||
child_inlines(std::move(child_inlines)) {}
|
||||
|
||||
InlineOrigin* origin;
|
||||
|
||||
// The list of addresses and sizes.
|
||||
vector<Range> ranges;
|
||||
|
||||
int call_site_line;
|
||||
|
||||
// The id is only meanful inside a CU. It's only used for looking up real
|
||||
// File* after scanning a CU.
|
||||
int call_site_file_id;
|
||||
|
||||
File* call_site_file;
|
||||
|
||||
int inline_nest_level;
|
||||
|
||||
// A list of inlines which are children of this inline.
|
||||
vector<std::unique_ptr<Inline>> child_inlines;
|
||||
|
||||
int getCallSiteFileID() const {
|
||||
return call_site_file ? call_site_file->source_id : -1;
|
||||
}
|
||||
|
||||
static void InlineDFS(
|
||||
vector<std::unique_ptr<Module::Inline>>& inlines,
|
||||
std::function<void(std::unique_ptr<Module::Inline>&)> const& forEach) {
|
||||
for (std::unique_ptr<Module::Inline>& in : inlines) {
|
||||
forEach(in);
|
||||
InlineDFS(in->child_inlines, forEach);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef map<uint64_t, InlineOrigin*> InlineOriginByOffset;
|
||||
|
||||
class InlineOriginMap {
|
||||
public:
|
||||
// Add INLINE ORIGIN to the module. Return a pointer to origin .
|
||||
InlineOrigin* GetOrCreateInlineOrigin(uint64_t offset, StringView name);
|
||||
|
||||
// offset is the offset of a DW_TAG_subprogram. specification_offset is the
|
||||
// value of its DW_AT_specification or equals to offset if
|
||||
// DW_AT_specification doesn't exist in that DIE.
|
||||
void SetReference(uint64_t offset, uint64_t specification_offset);
|
||||
|
||||
~InlineOriginMap() {
|
||||
for (const auto& iter : inline_origins_) {
|
||||
delete iter.second;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// A map from a DW_TAG_subprogram's offset to the DW_TAG_subprogram.
|
||||
InlineOriginByOffset inline_origins_;
|
||||
|
||||
// A map from a DW_TAG_subprogram's offset to the offset of its
|
||||
// specification or abstract origin subprogram. The set of values in this
|
||||
// map should always be the same set of keys in inline_origins_.
|
||||
map<uint64_t, uint64_t> references_;
|
||||
};
|
||||
|
||||
map<std::string, InlineOriginMap> inline_origin_maps;
|
||||
|
||||
// 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;
|
||||
// If this symbol has been folded with other symbols in the linked binary.
|
||||
bool is_multiple = false;
|
||||
};
|
||||
|
||||
// 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 InlineOriginCompare {
|
||||
bool operator()(const InlineOrigin* lhs, const InlineOrigin* rhs) const {
|
||||
return lhs->name < rhs->name;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExternCompare {
|
||||
// Defining is_transparent allows
|
||||
// std::set<std::unique_ptr<Extern>, ExternCompare>::find() to be called
|
||||
// with an Extern* and have set use the overloads below.
|
||||
using is_transparent = void;
|
||||
bool operator() (const std::unique_ptr<Extern>& lhs,
|
||||
const std::unique_ptr<Extern>& rhs) const {
|
||||
return lhs->address < rhs->address;
|
||||
}
|
||||
bool operator() (const Extern* lhs, const std::unique_ptr<Extern>& rhs) const {
|
||||
return lhs->address < rhs->address;
|
||||
}
|
||||
bool operator() (const std::unique_ptr<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.
|
||||
// NB: `enable_multiple_field` is temporary while transitioning to enabling
|
||||
// writing the multiple field permanently.
|
||||
Module(const string& name,
|
||||
const string& os,
|
||||
const string& architecture,
|
||||
const string& id,
|
||||
const string& code_id = "",
|
||||
bool enable_multiple_field = false,
|
||||
bool prefer_extern_name = false);
|
||||
~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.
|
||||
// Return false if the function is duplicate and needs to be freed.
|
||||
bool AddFunction(Function* function);
|
||||
|
||||
// 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(std::unique_ptr<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(std::unique_ptr<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();
|
||||
|
||||
// This function should be called before AssignSourceIds() to get the set of
|
||||
// valid InlineOrigins*.
|
||||
void CreateInlineOrigins(
|
||||
set<InlineOrigin*, InlineOriginCompare>& inline_origins);
|
||||
|
||||
// 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 CFI then:
|
||||
// - the source files added via FindFile,
|
||||
// - the functions added via AddFunctions, each with its lines,
|
||||
// - all public records,
|
||||
// If symbol_data is 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);
|
||||
|
||||
// Place the name in the global set of strings. Return a StringView points to
|
||||
// a string inside the pool.
|
||||
StringView AddStringToPool(const string& str) {
|
||||
auto result = common_strings_.insert(str);
|
||||
return *(result.first);
|
||||
}
|
||||
|
||||
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<std::unique_ptr<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.
|
||||
// Used to quickly look up whether a function exists at a particular address.
|
||||
unordered_set<Address> function_addresses_;
|
||||
|
||||
// The module owns all the call frame info entries that have been
|
||||
// added to it.
|
||||
vector<std::unique_ptr<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_;
|
||||
|
||||
unordered_set<string> common_strings_;
|
||||
|
||||
// Whether symbols sharing an address should be collapsed into a single entry
|
||||
// and marked with an `m` in the output. See
|
||||
// https://bugs.chromium.org/p/google-breakpad/issues/detail?id=751 and docs
|
||||
// at
|
||||
// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md#records-3
|
||||
bool enable_multiple_field_;
|
||||
|
||||
// If a Function and an Extern share the same address but have a different
|
||||
// name, prefer the name of the Extern.
|
||||
//
|
||||
// Use this when dumping Mach-O .dSYMs built with -gmlt (Minimum Line Tables),
|
||||
// as the Function's fully-qualified name will only be present in the STABS
|
||||
// (which are placed in the Extern), not in the DWARF symbols (which are
|
||||
// placed in the Function).
|
||||
bool prefer_extern_name_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_MODULE_H__
|
Loading…
Add table
Add a link
Reference in a new issue