aboutsummaryrefslogtreecommitdiff
path: root/src/common/module.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/module.h')
-rw-r--r--src/common/module.h231
1 files changed, 189 insertions, 42 deletions
diff --git a/src/common/module.h b/src/common/module.h
index 7309cedd..c1fd9f59 100644
--- a/src/common/module.h
+++ b/src/common/module.h
@@ -1,7 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010 Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -13,7 +12,7 @@
// 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
+// * 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.
//
@@ -38,13 +37,18 @@
#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"
@@ -62,8 +66,11 @@ 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;
@@ -74,7 +81,7 @@ class Module {
// A source file.
struct File {
- explicit File(const string &name_input) : name(name_input), source_id(0) {}
+ explicit File(const string& name_input) : name(name_input), source_id(0) {}
// The name of the source file.
const string name;
@@ -96,17 +103,17 @@ class Module {
// A function.
struct Function {
- Function(const string &name_input, const Address &address_input) :
+ 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) {
+ static bool CompareByAddress(const Function* x, const Function* y) {
return x->address < y->address;
}
// The function's name.
- string name;
+ StringView name;
// The start address and the address ranges covered by the function.
const Address address;
@@ -118,26 +125,127 @@ class Module {
// 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;
+ };
+
+ 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) {
+ 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.
+ 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) {}
+ 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
@@ -170,25 +278,46 @@ class Module {
};
struct FunctionCompare {
- bool operator() (const Function *lhs,
- const Function *rhs) const {
+ 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 {
+ // 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.
- Module(const string &name, const string &os, const string &architecture,
- const string &id, const string &code_id = "");
+ // 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);
~Module();
// Set the module's load address to LOAD_ADDRESS; addresses given
@@ -216,83 +345,90 @@ class Module {
// 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);
+ // 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);
+ 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(Extern *ext);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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;
+ 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();
+ 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 ONLY_CFI then:
+ // 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 not NO_CFI then:
+ // 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);
+ 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_; }
@@ -308,7 +444,7 @@ class Module {
// 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);
+ 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.
@@ -329,32 +465,43 @@ class Module {
// 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; }
+ 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;
+ typedef map<const string*, File*, CompareStringPtrs> FileByNameMap;
// A set containing Function structures, sorted by address.
- typedef set<Function *, FunctionCompare> FunctionSet;
+ typedef set<Function*, FunctionCompare> FunctionSet;
// A set containing Extern structures, sorted by address.
- typedef set<Extern *, ExternCompare> ExternSet;
+ 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<StackFrameEntry *> stack_frame_entries_;
+ 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_;
};
} // namespace google_breakpad