X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gold%2Fscript.h;h=70e3a59e7b44814caecd08017dacea5f94518a1e;hb=bbb3c81a449f089121b8d6d5527991dcd6dff0d3;hp=257b479dcd1aca89acbcba4761a9853c7f1057fa;hpb=a445fddf828b0e8251fbdce91bc9372e7efd24f0;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/script.h b/gold/script.h index 257b479dcd..70e3a59e7b 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 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -31,6 +31,7 @@ #define GOLD_SCRIPT_H #include +#include #include #include "script-sections.h" @@ -42,7 +43,9 @@ class General_options; class Command_line; class Symbol_table; class Layout; +class Mapfile; class Input_argument; +class Input_arguments; class Input_objects; class Input_group; class Input_file; @@ -52,6 +55,8 @@ class Workqueue; struct Version_dependency_list; struct Version_expression_list; struct Version_tree; +struct Version_expression; +class Lazy_demangler; // This class represents an expression in a linker script. @@ -67,25 +72,37 @@ class Expression { } // Return the value of the expression which is not permitted to - // refer to the dot symbol. + // refer to the dot symbol. CHECK_ASSERTIONS is true if we should + // check whether assertions are true. uint64_t - eval(const Symbol_table*, const Layout*); + eval(const Symbol_table*, const Layout*, bool check_assertions); // Return the value of an expression which is permitted to refer to - // the dot symbol. This sets *IS_ABSOLUTE to indicate whether this - // is an absolute value; it will be false if a non-absolute symbol - // was referenced in the expression; this is used to detect invalid - // uses when setting a section address. + // the dot symbol. DOT_VALUE is the absolute value of the dot + // symbol. DOT_SECTION is the section in which dot is defined; it + // should be NULL if the dot symbol has an absolute value (e.g., is + // defined in a SECTIONS clause outside of any output section + // definition). This sets *RESULT_SECTION to indicate where the + // 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. 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. uint64_t - eval_with_dot(const Symbol_table*, const Layout*, bool dot_has_value, - uint64_t dot_value, bool* is_absolute); + eval_with_dot(const Symbol_table*, const Layout*, bool check_assertions, + uint64_t dot_value, Output_section* dot_section, + Output_section** result_section, uint64_t* result_alignment); // Return the value of an expression which may or may not be // permitted to refer to the dot symbol, depending on // is_dot_available. uint64_t - eval_maybe_dot(const Symbol_table*, const Layout*, bool is_dot_available, - bool dot_has_value, uint64_t dot_value, bool* is_absolute); + 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, uint64_t* result_alignment); // Print the expression to the FILE. This is for debugging. virtual void @@ -116,33 +133,55 @@ class Expression class Version_script_info { public: + // The languages which can be specified in a versionn script. + enum Language + { + LANGUAGE_C, // No demangling. + LANGUAGE_CXX, // C++ demangling. + LANGUAGE_JAVA, // Java demangling. + LANGUAGE_COUNT + }; + + Version_script_info(); + ~Version_script_info(); + // Clear everything. + void + clear(); + + // Finalize the version control information. + void + finalize(); + + // Return whether the information is finalized. + bool + is_finalized() const + { return this->is_finalized_; } + // Return whether any version were defined in the version script. bool empty() const { return this->version_trees_.empty(); } - // Return the version associated with the given symbol name. - // Strings are allocated out of the stringpool given in the - // constructor. Strings are allocated out of the stringpool given - // in the constructor. - const std::string& - get_symbol_version(const char* symbol) const - { return get_symbol_version_helper(symbol, true); } + // If there is a version associated with SYMBOL, return true, and + // 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, + bool* is_global) const; - // Return whether this symbol matches the local: section of a - // version script (it doesn't matter which). + // Return whether this symbol matches the local: section of some + // version. bool symbol_is_local(const char* symbol) const { - return (get_symbol_version(symbol).empty() - && !get_symbol_version_helper(symbol, false).empty()); + bool is_global; + return (this->get_symbol_version(symbol, NULL, &is_global) + && !is_global); } // Return the names of versions defined in the version script. - // Strings are allocated out of the stringpool given in the - // constructor. std::vector get_versions() const; @@ -163,6 +202,15 @@ class Version_script_info struct Version_tree* allocate_version_tree(); + // Build the lookup tables after all data have been read. + 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; @@ -171,12 +219,95 @@ class Version_script_info void print_expression_list(FILE* f, const Version_expression_list*) const; - const std::string& get_symbol_version_helper(const char* symbol, - bool check_global) const; + bool + get_symbol_version_helper(const char* symbol, + bool check_global, + std::string* pversion) const; - std::vector dependency_lists_; - std::vector expression_lists_; - std::vector version_trees_; + // 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() + : expression(NULL), version(NULL), is_global(false) + { } + + Glob(const Version_expression* e, const Version_tree* v, bool ig) + : expression(e), version(v), is_global(ig) + { } + + // 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; + }; + + typedef std::vector Globs; + + bool + unquote(std::string*) const; + + 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*, 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_; + // All the version expressions we allocate. + std::vector expression_lists_; + // The list of versions. + std::vector version_trees_; + // 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_; }; // This class manages assignments to symbols. These can appear in @@ -188,10 +319,10 @@ class Version_script_info class Symbol_assignment { public: - Symbol_assignment(const char* name, size_t namelen, Expression* val, - bool provide, bool hidden) - : name_(name, namelen), val_(val), provide_(provide), hidden_(hidden), - sym_(NULL) + Symbol_assignment(const char* name, size_t namelen, bool is_defsym, + Expression* val, bool provide, bool hidden) + : name_(name, namelen), val_(val), is_defsym_(is_defsym), + provide_(provide), hidden_(hidden), sym_(NULL) { } // Add the symbol to the symbol table. @@ -204,14 +335,15 @@ class Symbol_assignment // Finalize the symbol value when it can refer to the dot symbol. void - finalize_with_dot(Symbol_table*, const Layout*, bool dot_has_value, - uint64_t dot_value); + 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. + // 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, - bool dot_has_value, uint64_t dot_value); + uint64_t dot_value); // Print the assignment to the FILE. This is for debugging. void @@ -221,18 +353,21 @@ class Symbol_assignment // Shared by finalize and finalize_with_dot. void finalize_maybe_dot(Symbol_table*, const Layout*, bool is_dot_available, - bool dot_has_value, uint64_t dot_value); + uint64_t dot_value, Output_section* dot_section); // Sized version of finalize. template void sized_finalize(Symbol_table*, const Layout*, bool is_dot_available, - bool dot_has_value, uint64_t dot_value); + uint64_t dot_value, Output_section*); // Symbol name. std::string name_; // Expression to assign to symbol. Expression* val_; + // True if this symbol is defined by a --defsym, false if it is + // defined in a linker script. + bool is_defsym_; // Whether the assignment should be provided (only set if there is // an undefined reference to the symbol. bool provide_; @@ -283,20 +418,14 @@ class Script_options public: Script_options(); - // The entry address. - const char* - entry() const - { return this->entry_.empty() ? NULL : this->entry_.c_str(); } - - // Set the entry address. + // Add a symbol to be defined. void - set_entry(const char* entry, size_t length) - { this->entry_.assign(entry, length); } + add_symbol_assignment(const char* name, size_t length, bool is_defsym, + Expression* value, bool provide, bool hidden); - // Add a symbol to be defined. + // Add a reference to a symbol. void - add_symbol_assignment(const char* name, size_t length, Expression* value, - bool provide, bool hidden); + add_symbol_reference(const char* name, size_t length); // Add an assertion. void @@ -306,10 +435,40 @@ class Script_options bool define_symbol(const char* definition); + // Create sections required by any linker scripts. + void + create_script_sections(Layout*); + // Add all symbol definitions to the symbol table. 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*); @@ -320,17 +479,30 @@ class Script_options version_script_info() { return &this->version_script_info_; } + const Version_script_info* + version_script_info() const + { return &this->version_script_info_; } + // A SECTIONS clause parsed from a linker script. Everything else // has a pointer to this object. Script_sections* script_sections() { return &this->script_sections_; } + const Script_sections* + script_sections() const + { return &this->script_sections_; } + // Whether we saw a SECTIONS clause. bool saw_sections_clause() const { return this->script_sections_.saw_sections_clause(); } + // Whether we saw a PHDRS clause. + bool + saw_phdrs_clause() const + { return this->script_sections_.saw_phdrs_clause(); } + // Set section addresses using a SECTIONS clause. Return the // segment which should hold the file header and segment headers; // this may return NULL, in which case the headers are not in a @@ -355,6 +527,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. @@ -363,24 +539,43 @@ 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. We've -// already read BYTES of data into P. Return true if the file was -// handled. This has to handle /usr/lib/libc.so on a GNU/Linux -// system. +// 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 +// on a GNU/Linux system. *USED_NEXT_BLOCKER is set to indicate +// whether the function took over NEXT_BLOCKER. bool -read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*, - Dirsearch*, Input_objects*, Input_group*, - const Input_argument*, Input_file*, const unsigned char* p, - off_t bytes, Task_token* this_blocker, - Task_token* next_blocker); +read_input_script(Workqueue*, Symbol_table*, Layout*, Dirsearch*, int, + Input_objects*, Mapfile*, Input_group*, + const Input_argument*, Input_file*, + Task_token* next_blocker, bool* used_next_blocker); // FILE was found as an argument to --script (-T). // Read it as a script, and execute its contents immediately. bool -read_commandline_script(const char* filename, Command_line*); +read_commandline_script(const char* filename, Command_line* cmdline); // FILE was found as an argument to --version-script. Read it as a // version script, and store its contents in @@ -389,6 +584,13 @@ read_commandline_script(const char* filename, Command_line*); bool read_version_script(const char* filename, Command_line* cmdline); +// FILENAME was found as an argument to --dynamic-list. Read it as a +// version script (actually, a versym_node from a version script), and +// store its contents in DYNAMIC_LIST. + +bool +read_dynamic_list(const char* filename, Command_line* cmdline, + Script_options* dynamic_list); } // End namespace gold.