set_forwarder()
{ this->is_forwarder_ = true; }
+ // Return whether this symbol has an alias in the weak aliases table
+ // in Symbol_table.
+ bool
+ has_alias() const
+ { return this->has_alias_; }
+
+ // Mark this symbol as having an alias.
+ void
+ set_has_alias()
+ { this->has_alias_ = true; }
+
// Return whether this symbol needs an entry in the dynamic symbol
// table.
bool
set_needs_dynsym_entry()
{ this->needs_dynsym_entry_ = true; }
+ // Return whether this symbol should be added to the dynamic symbol
+ // table.
+ bool
+ should_add_dynsym_entry() const;
+
// Return whether this symbol has been seen in a regular object.
bool
in_reg() const
|| this->visibility_ == elfcpp::STV_PROTECTED);
}
+ // Return true if this symbol can be preempted by a definition in
+ // another link unit.
+ bool
+ is_preemptible() const
+ {
+ // It doesn't make sense to ask whether a symbol defined in
+ // another object is preemptible.
+ gold_assert(!this->is_from_dynobj());
+
+ return (this->visibility_ != elfcpp::STV_INTERNAL
+ && this->visibility_ != elfcpp::STV_HIDDEN
+ && this->visibility_ != elfcpp::STV_PROTECTED
+ && parameters->output_is_shared()
+ && !parameters->symbolic());
+ }
+
+ // Return true if this symbol is a function that needs a PLT entry.
+ // If the symbol is defined in a dynamic object or if it is subject
+ // to pre-emption, we need to make a PLT entry.
+ bool
+ needs_plt_entry() const
+ {
+ return (this->type() == elfcpp::STT_FUNC
+ && (this->is_from_dynobj() || this->is_preemptible()));
+ }
+
+ // Given a direct absolute or pc-relative static relocation against
+ // the global symbol, this function returns whether a dynamic relocation
+ // is needed.
+
+ bool
+ needs_dynamic_reloc(bool is_absolute_ref, bool is_function_call) const
+ {
+ // An absolute reference within a position-independent output file
+ // will need a dynamic relocaion.
+ if (is_absolute_ref && parameters->output_is_position_independent())
+ return true;
+
+ // A function call that can branch to a local PLT entry does not need
+ // a dynamic relocation.
+ if (is_function_call && this->has_plt_offset())
+ return false;
+
+ // A reference to any PLT entry in a non-position-independent executable
+ // does not need a dynamic relocation.
+ if (!parameters->output_is_position_independent()
+ && this->has_plt_offset())
+ return false;
+
+ // A reference to a symbol defined in a dynamic object or to a
+ // symbol that is preemptible will need a dynamic relocation.
+ if (this->is_from_dynobj() || this->is_preemptible())
+ return true;
+
+ // For all other cases, return FALSE.
+ return false;
+ }
+
+ // Given a direct absolute static relocation against
+ // the global symbol, where a dynamic relocation is needed, this
+ // function returns whether a relative dynamic relocation can be used.
+ // The caller must determine separately whether the static relocation
+ // is compatible with a relative relocation.
+
+ bool
+ can_use_relative_reloc(bool is_function_call) const
+ {
+ // A function call that can branch to a local PLT entry can
+ // use a RELATIVE relocation.
+ if (is_function_call && this->has_plt_offset())
+ return true;
+
+ // A reference to a symbol defined in a dynamic object or to a
+ // symbol that is preemptible can not use a RELATIVE relocaiton.
+ if (this->is_from_dynobj() || this->is_preemptible())
+ return false;
+
+ // For all other cases, return TRUE.
+ return true;
+ }
+
// Return whether there should be a warning for references to this
// symbol.
bool
set_has_warning()
{ this->has_warning_ = true; }
+ // Return whether this symbol is defined by a COPY reloc from a
+ // dynamic object.
+ bool
+ is_copied_from_dynobj() const
+ { return this->is_copied_from_dynobj_; }
+
+ // Mark this symbol as defined by a COPY reloc.
+ void
+ set_is_copied_from_dynobj()
+ { this->is_copied_from_dynobj_ = true; }
+
+ // Mark this symbol as needing its value written to the GOT even when
+ // the value is subject to dynamic relocation (e.g., when the target
+ // uses a RELATIVE relocation for the GOT entry).
+ void
+ set_needs_value_in_got()
+ { this->needs_value_in_got_ = true; }
+
+ // Return whether this symbol needs its value written to the GOT even
+ // when the value is subject to dynamic relocation.
+ bool
+ needs_value_in_got() const
+ { return this->needs_value_in_got_; }
+
protected:
// Instances of this class should always be created at a specific
// size.
// It forwards to the symbol found in the forwarders_ map of
// Symbol_table.
bool is_forwarder_ : 1;
+ // True if the symbol has an alias in the weak_aliases table in
+ // Symbol_table.
+ bool has_alias_ : 1;
// True if this symbol needs to be in the dynamic symbol table.
bool needs_dynsym_entry_ : 1;
// True if we've seen this symbol in a regular object.
bool needs_dynsym_value_ : 1;
// True if there is a warning for this symbol.
bool has_warning_ : 1;
+ // True if we are using a COPY reloc for this symbol, so that the
+ // real definition lives in a dynamic object.
+ bool is_copied_from_dynobj_ : 1;
+ // True if the static value should be written to the GOT even
+ // when the final value is subject to dynamic relocation.
+ bool needs_value_in_got_ : 1;
};
// The parts of a symbol which are size specific. Using a template
void
note_warnings(Symbol_table* symtab);
- // Issue a warning for a reference to SYM at LOCATION.
+ // Issue a warning for a reference to SYM at RELINFO's location.
+ template<int size, bool big_endian>
void
- issue_warning(const Symbol* sym, const std::string& location) const;
+ issue_warning(const Symbol* sym, const Relocate_info<size, big_endian>*,
+ size_t relnum, off_t reloffset) const;
private:
Warnings(const Warnings&);
add_from_relobj(Sized_relobj<size, big_endian>* relobj,
const unsigned char* syms, size_t count,
const char* sym_names, size_t sym_name_size,
- Symbol** sympointers);
+ typename Sized_relobj<size, big_endian>::Symbols*);
// Add COUNT dynamic symbols from the dynamic object DYNOBJ to the
// symbol table. SYMS is the symbols. SYM_NAMES is their names.
define_symbols(const Layout*, const Target*, int count,
const Define_symbol_in_segment*);
+ // Define SYM using a COPY reloc. POSD is the Output_data where the
+ // symbol should be defined--typically a .dyn.bss section. VALUE is
+ // the offset within POSD.
+ template<int size>
+ void
+ define_with_copy_reloc(const Target*, Sized_symbol<size>* sym,
+ Output_data* posd, uint64_t value);
+
// Look up a symbol.
Symbol*
lookup(const char*, const char* version = NULL) const;
// Canonicalize a symbol name for use in the hash table.
const char*
canonicalize_name(const char* name)
- { return this->namepool_.add(name, NULL); }
+ { return this->namepool_.add(name, true, NULL); }
// Possibly issue a warning for a reference to SYM at LOCATION which
// is in OBJ.
+ template<int size, bool big_endian>
void
- issue_warning(const Symbol* sym, const std::string& location) const
- { this->warnings_.issue_warning(sym, location); }
+ issue_warning(const Symbol* sym,
+ const Relocate_info<size, big_endian>* relinfo,
+ size_t relnum, off_t reloffset) const
+ { this->warnings_.issue_warning(sym, relinfo, relnum, reloffset); }
+
+ // SYM is defined using a COPY reloc. Return the dynamic object
+ // where the original definition was found.
+ Dynobj*
+ get_copy_source(const Symbol* sym) const;
// Set the dynamic symbol indexes. INDEX is the index of the first
// global dynamic symbol. Pointers to the symbols are stored into
// the vector. The names are stored into the Stringpool. This
// returns an updated dynamic symbol index.
unsigned int
- set_dynsym_indexes(const General_options*, const Target*, unsigned int index,
+ set_dynsym_indexes(const Target*, unsigned int index,
std::vector<Symbol*>*, Stringpool*, Versions*);
// Finalize the symbol table after we have set the final addresses
// Add a symbol.
template<int size, bool big_endian>
- Symbol*
+ Sized_symbol<size>*
add_from_object(Object*, const char *name, Stringpool::Key name_key,
const char *version, Stringpool::Key version_key,
bool def, const elfcpp::Sym<size, big_endian>& sym);
// Resolve symbols.
template<int size, bool big_endian>
- static void
+ void
resolve(Sized_symbol<size>* to,
const elfcpp::Sym<size, big_endian>& sym,
Object*, const char* version);
template<int size, bool big_endian>
- static void
+ void
resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from,
const char* version ACCEPT_SIZE_ENDIAN);
// Whether we should override a symbol, based on flags in
// resolve.cc.
static bool
- should_override(const Symbol*, unsigned int, bool*);
+ should_override(const Symbol*, unsigned int, Object*, bool*);
+
+ // Override a symbol.
+ template<int size, bool big_endian>
+ void
+ override(Sized_symbol<size>* tosym,
+ const elfcpp::Sym<size, big_endian>& fromsym,
+ Object* object, const char* version);
// Whether we should override a symbol with a special symbol which
// is automatically defined by the linker.
static bool
should_override_with_special(const Symbol*);
+ // Override a symbol with a special symbol.
+ template<int size>
+ void
+ override_with_special(Sized_symbol<size>* tosym,
+ const Sized_symbol<size>* fromsym);
+
+ // Record all weak alias sets for a dynamic object.
+ template<int size>
+ void
+ record_weak_aliases(std::vector<Sized_symbol<size>*>*);
+
// Define a special symbol.
template<int size, bool big_endian>
Sized_symbol<size>*
Symbol_table_eq> Symbol_table_type;
// The type of the list of common symbols.
-
typedef std::vector<Symbol*> Commons_type;
+ // A map from symbols with COPY relocs to the dynamic objects where
+ // they are defined.
+ typedef Unordered_map<const Symbol*, Dynobj*> Copied_symbol_dynobjs;
+
// We increment this every time we see a new undefined symbol, for
// use in archive groups.
int saw_undefined_;
-
// The index of the first global symbol in the output file.
unsigned int first_global_index_;
-
// The file offset within the output symtab section where we should
// write the table.
off_t offset_;
-
// The number of global symbols we want to write out.
size_t output_count_;
-
// The file offset of the global dynamic symbols, or 0 if none.
off_t dynamic_offset_;
-
// The index of the first global dynamic symbol.
unsigned int first_dynamic_global_index_;
-
// The number of global dynamic symbols, or 0 if none.
off_t dynamic_count_;
-
// The symbol hash table.
Symbol_table_type table_;
-
// A pool of symbol names. This is used for all global symbols.
// Entries in the hash table point into this pool.
Stringpool namepool_;
-
// Forwarding symbols.
Unordered_map<const Symbol*, Symbol*> forwarders_;
-
+ // Weak aliases. A symbol in this list points to the next alias.
+ // The aliases point to each other in a circular list.
+ Unordered_map<Symbol*, Symbol*> weak_aliases_;
// We don't expect there to be very many common symbols, so we keep
// a list of them. When we find a common symbol we add it to this
// list. It is possible that by the time we process the list the
// symbol is no longer a common symbol. It may also have become a
// forwarder.
Commons_type commons_;
-
// Manage symbol warnings.
Warnings warnings_;
+ // When we emit a COPY reloc for a symbol, we define it in an
+ // Output_data. When it's time to emit version information for it,
+ // we need to know the dynamic object in which we found the original
+ // definition. This maps symbols with COPY relocs to the dynamic
+ // object where they were defined.
+ Copied_symbol_dynobjs copied_symbol_dynobjs_;
};
// We inline get_sized_symbol for efficiency.