X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fscript.h;h=81e45a2df20df2c30f1837537b9d2790dfeb2738;hb=0574b47b73d57f7d78b174aaad01e8d1141bbe32;hp=a7e0186bde4497afc7b61dd310f0ad56781cc827;hpb=6affe781e430bbf2075faf6539fb020564b3a38f;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/script.h b/gold/script.h index a7e0186bde..81e45a2df2 100644 --- a/gold/script.h +++ b/gold/script.h @@ -1,6 +1,6 @@ // script.h -- handle linker scripts for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -34,6 +34,7 @@ #include #include +#include "elfcpp.h" #include "script-sections.h" namespace gold @@ -55,6 +56,9 @@ class Workqueue; struct Version_dependency_list; struct Version_expression_list; struct Version_tree; +struct Version_expression; +class Lazy_demangler; +class Incremental_script_entry; // This class represents an expression in a linker script. @@ -84,20 +88,32 @@ class Expression // value is defined. If the value is absolute *RESULT_SECTION will // be NULL. Note that the returned value is still an absolute // value; to get a section relative value the caller must subtract - // the section address. + // the section address. If RESULT_ALIGNMENT is not NULL, this sets + // *RESULT_ALIGNMENT to the alignment of the value of that alignment + // is larger than *RESULT_ALIGNMENT; this will only be non-zero if + // this is an ALIGN expression. If IS_SECTION_DOT_ASSIGMENT is true, + // we are evaluating an assignment to dot within an output section, + // and an absolute value should be interpreted as an offset within + // the section. uint64_t eval_with_dot(const Symbol_table*, const Layout*, bool check_assertions, uint64_t dot_value, Output_section* dot_section, - Output_section** result_section); + Output_section** result_section, uint64_t* result_alignment, + bool is_section_dot_assignment); // Return the value of an expression which may or may not be // permitted to refer to the dot symbol, depending on - // is_dot_available. + // is_dot_available. If IS_SECTION_DOT_ASSIGMENT is true, + // we are evaluating an assignment to dot within an output section, + // and an absolute value should be interpreted as an offset within + // the section. uint64_t eval_maybe_dot(const Symbol_table*, const Layout*, bool check_assertions, bool is_dot_available, uint64_t dot_value, Output_section* dot_section, - Output_section** result_section); + Output_section** result_section, uint64_t* result_alignment, + elfcpp::STT* type, elfcpp::STV* vis, unsigned char* nonvis, + bool is_section_dot_assignment, bool* is_valid_pointer); // Print the expression to the FILE. This is for debugging. virtual void @@ -113,13 +129,17 @@ class Expression virtual uint64_t value(const Expression_eval_info*) = 0; + // Sets all symbols used in expressions as seen in a real ELF object. + virtual void + set_expr_sym_in_real_elf(Symbol_table*) const + { return; } + private: // May not be copied. Expression(const Expression&); Expression& operator=(const Expression&); }; - // Version_script_info stores information parsed from the version // script, either provided by --version-script or as part of a linker // script. A single Version_script_info object per target is owned by @@ -160,16 +180,21 @@ class Version_script_info { return this->version_trees_.empty(); } // If there is a version associated with SYMBOL, return true, and - // set *VERSION to the version. Otherwise, return false. + // set *VERSION to the version, and *IS_GLOBAL to whether the symbol + // should be global. Otherwise, return false. bool - get_symbol_version(const char* symbol, std::string* version) const - { return this->get_symbol_version_helper(symbol, true, version); } + get_symbol_version(const char* symbol, std::string* version, + bool* is_global) const; // Return whether this symbol matches the local: section of some // version. bool symbol_is_local(const char* symbol) const - { return this->get_symbol_version_helper(symbol, false, NULL); } + { + bool is_global; + return (this->get_symbol_version(symbol, NULL, &is_global) + && !is_global); + } // Return the names of versions defined in the version script. std::vector @@ -196,6 +221,11 @@ class Version_script_info void build_lookup_tables(); + // Give an error if there are any unmatched names in the version + // script. + void + check_unmatched_names(const Symbol_table*) const; + // Print contents to the FILE. This is for debugging. void print(FILE*) const; @@ -209,40 +239,72 @@ class Version_script_info bool check_global, std::string* pversion) const; + // Fast lookup information for a given language. + + // We map from exact match strings to Version_tree's. Historically + // version scripts sometimes have the same symbol multiple times, + // which is ambiguous. We warn about that case by storing the + // second Version_tree we see. + struct Version_tree_match + { + Version_tree_match(const Version_tree* r, bool ig, + const Version_expression* e) + : real(r), is_global(ig), expression(e), ambiguous(NULL) + { } + + // The Version_tree that we return. + const Version_tree* real; + // True if this is a global match for the REAL member, false if it + // is a local match. + bool is_global; + // Point back to the Version_expression for which we created this + // match. + const Version_expression* expression; + // If not NULL, another Version_tree that defines the symbol. + const Version_tree* ambiguous; + }; + + // Map from an exact match string to a Version_tree. + + typedef Unordered_map Exact; + // Fast lookup information for a glob pattern. struct Glob { Glob() - : pattern(NULL), version(NULL) + : expression(NULL), version(NULL), is_global(false) { } - Glob(const char* p, const Version_tree* v) - : pattern(p), version(v) + Glob(const Version_expression* e, const Version_tree* v, bool ig) + : expression(e), version(v), is_global(ig) { } - // A pointer to the glob pattern. The pattern itself lives in a - // Version_expression structure. - const char* pattern; + // A pointer to the version expression holding the pattern to + // match and the language to use for demangling the symbol before + // doing the match. + const Version_expression* expression; // The Version_tree we use if this pattern matches. const Version_tree* version; + // True if this is a global symbol. + bool is_global; }; - // Fast lookup information for a given language. + typedef std::vector Globs; - typedef Unordered_map Exact; + bool + unquote(std::string*) const; - struct Lookup - { - // A hash table of all exact match strings mapping to a - // Version_tree. - Exact exact; - // A vector of glob patterns mapping to Version_trees. - std::vector globs; - }; + void + add_exact_match(const std::string&, const Version_tree*, bool is_global, + const Version_expression*, Exact*); void build_expression_list_lookup(const Version_expression_list*, - const Version_tree*, Lookup**); + const Version_tree*, bool); + + const char* + get_name_to_match(const char*, int, + Lazy_demangler*, Lazy_demangler*) const; // All the version dependencies we allocate. std::vector dependency_lists_; @@ -250,10 +312,15 @@ class Version_script_info std::vector expression_lists_; // The list of versions. std::vector version_trees_; - // Lookup information for global symbols, by language. - Lookup* globals_[LANGUAGE_COUNT]; - // Lookup information for local symbols, by language. - Lookup* locals_[LANGUAGE_COUNT]; + // Exact matches for global symbols, by language. + Exact* exact_[LANGUAGE_COUNT]; + // A vector of glob patterns mapping to Version_trees. + Globs globs_; + // The default version to use, if there is one. This is from a + // pattern of "*". + const Version_tree* default_version_; + // True if the default version is global. + bool default_is_global_; // Whether this has been finalized. bool is_finalized_; }; @@ -281,17 +348,29 @@ class Symbol_assignment void finalize(Symbol_table*, const Layout*); + bool + is_defsym() const + { return is_defsym_; } + + Expression * + value() const + { return val_; } + // Finalize the symbol value when it can refer to the dot symbol. void finalize_with_dot(Symbol_table*, const Layout*, uint64_t dot_value, Output_section* dot_section); - // Set the symbol value, but only if the value is absolute. This is - // used while processing a SECTIONS clause. We assume that dot is - // an absolute value here. We do not check assertions. + // Set the symbol value, but only if the value is absolute or relative to + // DOT_SECTION. This is used while processing a SECTIONS clause. + // We assume that dot is an absolute value here. We do not check assertions. void set_if_absolute(Symbol_table*, const Layout*, bool is_dot_available, - uint64_t dot_value); + uint64_t dot_value, Output_section* dot_section); + + const std::string& + name() const + { return this->name_; } // Print the assignment to the FILE. This is for debugging. void @@ -371,6 +450,14 @@ class Script_options add_symbol_assignment(const char* name, size_t length, bool is_defsym, Expression* value, bool provide, bool hidden); + // Look for an assigned symbol. + bool + is_pending_assignment(const char* name); + + // Add a reference to a symbol. + void + add_symbol_reference(const char* name, size_t length); + // Add an assertion. void add_assertion(Expression* check, const char* message, size_t messagelen); @@ -379,6 +466,13 @@ class Script_options bool define_symbol(const char* definition); + // Populates the set with symbol names used in LHS of defsym. + void + find_defsym_defs(Unordered_set&); + + // Set symbols used in defsym expressions as seen in a real ELF object. + void set_defsym_uses_in_real_elf(Symbol_table*) const; + // Create sections required by any linker scripts. void create_script_sections(Layout*); @@ -387,6 +481,32 @@ class Script_options void add_symbols_to_table(Symbol_table*); + // Used to iterate over symbols which are referenced in expressions + // but not defined. + typedef Unordered_set::const_iterator referenced_const_iterator; + + referenced_const_iterator + referenced_begin() const + { return this->symbol_references_.begin(); } + + referenced_const_iterator + referenced_end() const + { return this->symbol_references_.end(); } + + // Return whether a symbol is referenced but not defined. + bool + is_referenced(const std::string& name) const + { + return (this->symbol_references_.find(name) + != this->symbol_references_.end()); + } + + // Return whether there are any symbols which were referenced but + // not defined. + bool + any_unreferenced() const + { return !this->symbol_references_.empty(); } + // Finalize the symbol values. Also check assertions. void finalize_symbols(Symbol_table*, const Layout*); @@ -437,7 +557,7 @@ class Script_options // SECTIONS clause. typedef std::vector Symbol_assignments; - // We keep a list of all assertions whcih occur outside of a + // We keep a list of all assertions which occur outside of a // SECTIONS clause. typedef std::vector Assertions; @@ -445,6 +565,10 @@ class Script_options std::string entry_; // Symbols to set. Symbol_assignments symbol_assignments_; + // Symbols defined in an expression, for faster lookup. + Unordered_set symbol_definitions_; + // Symbols referenced in an expression. + Unordered_set symbol_references_; // Assertions to check. Assertions assertions_; // Version information parsed from a version script. @@ -453,26 +577,6 @@ class Script_options Script_sections script_sections_; }; -// Information about a script input that will persist during the whole linker -// run. Needed only during an incremental build to retrieve the input files -// added by this script. - -class Script_info -{ - public: - Script_info(Input_arguments* inputs) - : inputs_(inputs) - { } - - // Returns the input files included because of this script. - Input_arguments* - inputs() - { return this->inputs_; } - - private: - Input_arguments* inputs_; -}; - // FILE was found as an argument on the command line, but was not // recognized as an ELF file. Try to read it as a script. Return // true if the file was handled. This has to handle /usr/lib/libc.so