aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/breakpad/src/common/module.h
diff options
context:
space:
mode:
authoriddqd <iddqd@yandex-team.com>2024-12-19 10:46:06 +0300
committeriddqd <iddqd@yandex-team.com>2024-12-19 10:59:56 +0300
commitbb0840c0025a75dd3b85b746ebcec7deb7d9fe1c (patch)
tree85bc5522e873d9d5c37df278f0300c26fe9e729e /contrib/libs/breakpad/src/common/module.h
parent1353077f79bb3547792b2fc86c22a695f0bc76f9 (diff)
downloadydb-bb0840c0025a75dd3b85b746ebcec7deb7d9fe1c.tar.gz
Add contib/libs/breakpad to export
commit_hash:9d85255f8d9249f14105e4626bf4484805b8aed4
Diffstat (limited to 'contrib/libs/breakpad/src/common/module.h')
-rw-r--r--contrib/libs/breakpad/src/common/module.h479
1 files changed, 479 insertions, 0 deletions
diff --git a/contrib/libs/breakpad/src/common/module.h b/contrib/libs/breakpad/src/common/module.h
new file mode 100644
index 0000000000..01ecfa8aae
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/module.h
@@ -0,0 +1,479 @@
+// -*- 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 <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;
+ };
+
+ 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;
+
+ File* file;
+
+ int getFileID() const { return file ? file->source_id : -1; }
+ };
+
+ // 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_;
+ };
+
+ InlineOriginMap inline_origin_map;
+
+ // 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 InlineOriginCompare {
+ bool operator()(const InlineOrigin* lhs, const InlineOrigin* rhs) const {
+ return lhs->name < rhs->name;
+ }
+ };
+
+ 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.
+ // 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(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(set<InlineOrigin*, InlineOriginCompare>& inline_origins);
+
+ // 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<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_;
+
+ unordered_set<string> common_strings_;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_MODULE_H__