// symtab.h -- the gold symbol table -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2006-2015 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
class Object;
class Relobj;
template<int size, bool big_endian>
-class Sized_relobj;
+class Sized_relobj_file;
template<int size, bool big_endian>
class Sized_pluginobj;
class Dynobj;
class Icf;
// The base class of an entry in the symbol table. The symbol table
-// can have a lot of entries, so we don't want this class to big.
+// can have a lot of entries, so we don't want this class too big.
// Size dependent fields can be found in the template class
// Sized_symbol. Targets may support their own derived classes.
version() const
{ return this->version_; }
+ void
+ clear_version()
+ { this->version_ = NULL; }
+
// Return whether this version is the default for this symbol name
// (eg, "foo@@V2" is a default version; "foo@V1" is not). Only
// meaningful for versioned symbols.
set_is_default()
{ this->is_def_ = true; }
+ // Return the symbol's name as name@version (or name@@version).
+ std::string
+ versioned_name() const;
+
// Return the symbol source.
Source
source() const
type() const
{ return this->type_; }
+ // Set the symbol type.
+ void
+ set_type(elfcpp::STT type)
+ { this->type_ = type; }
+
// Return true for function symbol.
bool
is_func() const
override_visibility(elfcpp::STV);
// Set whether the symbol was originally a weak undef or a regular undef
- // when resolved by a dynamic def.
+ // when resolved by a dynamic def or by a special symbol.
inline void
set_undef_binding(elfcpp::STB bind)
{
}
}
- // Return TRUE if a weak undef was resolved by a dynamic def.
+ // Return TRUE if a weak undef was resolved by a dynamic def or
+ // by a special symbol.
inline bool
is_undef_binding_weak() const
{ return this->undef_binding_weak_; }
nonvis() const
{ return this->nonvis_; }
+ // Set the non-visibility part of the st_other field.
+ void
+ set_nonvis(unsigned int nonvis)
+ { this->nonvis_ = nonvis; }
+
// Return whether this symbol is a forwarder. This will never be
// true of a symbol found in the hash table, but may be true of
// symbol pointers attached to object files.
// Return whether this is a weak undefined symbol.
bool
is_weak_undefined() const
- { return this->is_undefined() && this->binding() == elfcpp::STB_WEAK; }
+ {
+ return (this->is_undefined()
+ && (this->binding() == elfcpp::STB_WEAK
+ || this->is_undef_binding_weak()));
+ }
+
+ // Return whether this is a strong undefined symbol.
+ bool
+ is_strong_undefined() const
+ {
+ return (this->is_undefined()
+ && this->binding() != elfcpp::STB_WEAK
+ && !this->is_undef_binding_weak());
+ }
// Return whether this is an absolute symbol.
bool
bool
is_externally_visible() const
{
- return (this->visibility_ == elfcpp::STV_DEFAULT
- || this->visibility_ == elfcpp::STV_PROTECTED);
+ return ((this->visibility_ == elfcpp::STV_DEFAULT
+ || this->visibility_ == elfcpp::STV_PROTECTED)
+ && !this->is_forced_local_);
}
// Return true if this symbol can be preempted by a definition in
if (!parameters->options().shared())
return false;
- // If the user used -Bsymbolic, then nothing is preemptible.
+ // If the symbol was named in a --dynamic-list script, it is preemptible.
+ if (parameters->options().in_dynamic_list(this->name()))
+ return true;
+
+ // If the user used -Bsymbolic, then nothing (else) is preemptible.
if (parameters->options().Bsymbolic())
return false;
// A TLS-related reference.
TLS_REF = 4,
// A reference that can always be treated as a function call.
- FUNCTION_CALL = 8
+ FUNCTION_CALL = 8,
+ // When set, says that dynamic relocations are needed even if a
+ // symbol has a plt entry.
+ FUNC_DESC_ABI = 16,
};
// Given a direct absolute or pc-relative static relocation against
// A reference to any PLT entry in a non-position-independent executable
// does not need a dynamic relocation.
- if (!parameters->options().output_is_position_independent()
+ if (!(flags & FUNC_DESC_ABI)
+ && !parameters->options().output_is_position_independent()
&& this->has_plt_offset())
return false;
void
set_output_section(Output_section*);
+ // Set the symbol's output segment. This is used for pre-defined
+ // symbols whose segments aren't known until after layout is done
+ // (e.g., __ehdr_start).
+ void
+ set_output_segment(Output_segment*, Segment_offset_base);
+
+ // Set the symbol to undefined. This is used for pre-defined
+ // symbols whose segments aren't known until after layout is done
+ // (e.g., __ehdr_start).
+ void
+ set_undefined();
+
// Return whether there should be a warning for references to this
// symbol.
bool
bool
may_need_copy_reloc() const
{
- return (!parameters->options().output_is_position_independent()
- && parameters->options().copyreloc()
+ return (parameters->options().copyreloc()
&& this->is_from_dynobj()
&& !this->is_func());
}
+ // Return true if this symbol was predefined by the linker.
+ bool
+ is_predefined() const
+ { return this->is_predefined_; }
+
+ // Return true if this is a C++ vtable symbol.
+ bool
+ is_cxx_vtable() const
+ { return is_prefix_of("_ZTV", this->name_); }
+
protected:
// Instances of this class should always be created at a specific
// size.
void
init_base_output_data(const char* name, const char* version, Output_data*,
elfcpp::STT, elfcpp::STB, elfcpp::STV,
- unsigned char nonvis, bool offset_is_from_end);
+ unsigned char nonvis, bool offset_is_from_end,
+ bool is_predefined);
// Initialize fields for an Output_segment.
void
Output_segment* os, elfcpp::STT type,
elfcpp::STB binding, elfcpp::STV visibility,
unsigned char nonvis,
- Segment_offset_base offset_base);
+ Segment_offset_base offset_base,
+ bool is_predefined);
// Initialize fields for a constant.
void
init_base_constant(const char* name, const char* version, elfcpp::STT type,
elfcpp::STB binding, elfcpp::STV visibility,
- unsigned char nonvis);
+ unsigned char nonvis, bool is_predefined);
// Initialize fields for an undefined symbol.
void
// index, not one of the special codes from SHN_LORESERVE to
// SHN_HIRESERVE (bit 29).
bool is_ordinary_shndx_ : 1;
- // True if we've seen this symbol in a real ELF object (bit 30).
+ // True if we've seen this symbol in a "real" ELF object (bit 30).
+ // If the symbol has been seen in a relocatable, non-IR, object file,
+ // it's known to be referenced from outside the IR. A reference from
+ // a dynamic object doesn't count as a "real" ELF, and we'll simply
+ // mark the symbol as "visible" from outside the IR. The compiler
+ // can use this distinction to guide its handling of COMDAT symbols.
bool in_real_elf_ : 1;
// True if this symbol is defined in a section which was discarded
// (bit 31).
// True if UNDEF_BINDING_WEAK_ has been set (bit 32).
bool undef_binding_set_ : 1;
// True if this symbol was a weak undef resolved by a dynamic def
- // (bit 33).
+ // or by a special symbol (bit 33).
bool undef_binding_weak_ : 1;
+ // True if this symbol is a predefined linker symbol (bit 34).
+ bool is_predefined_ : 1;
};
// The parts of a symbol which are size specific. Using a template
init_output_data(const char* name, const char* version, Output_data*,
Value_type value, Size_type symsize, elfcpp::STT,
elfcpp::STB, elfcpp::STV, unsigned char nonvis,
- bool offset_is_from_end);
+ bool offset_is_from_end, bool is_predefined);
// Initialize fields for an Output_segment.
void
init_output_segment(const char* name, const char* version, Output_segment*,
Value_type value, Size_type symsize, elfcpp::STT,
elfcpp::STB, elfcpp::STV, unsigned char nonvis,
- Segment_offset_base offset_base);
+ Segment_offset_base offset_base, bool is_predefined);
// Initialize fields for a constant.
void
init_constant(const char* name, const char* version, Value_type value,
Size_type symsize, elfcpp::STT, elfcpp::STB, elfcpp::STV,
- unsigned char nonvis);
+ unsigned char nonvis, bool is_predefined);
// Initialize fields for an undefined symbol.
void
bool only_if_ref;
};
+// Specify an object/section/offset location. Used by ODR code.
+
+struct Symbol_location
+{
+ // Object where the symbol is defined.
+ Object* object;
+ // Section-in-object where the symbol is defined.
+ unsigned int shndx;
+ // For relocatable objects, offset-in-section where the symbol is defined.
+ // For dynamic objects, address where the symbol is defined.
+ off_t offset;
+ bool operator==(const Symbol_location& that) const
+ {
+ return (this->object == that.object
+ && this->shndx == that.shndx
+ && this->offset == that.offset);
+ }
+};
+
// This class manages warnings. Warnings are a GNU extension. When
// we see a section named .gnu.warning.SYM in an object file, and if
// we wind using the definition of SYM from that object file, then we
SCRIPT,
// Predefined by the linker.
PREDEFINED,
+ // Defined by the linker during an incremental base link, but not
+ // a predefined symbol (e.g., common, defined in script).
+ INCREMENTAL_BASE,
};
// The order in which we sort common symbols.
void
gc_mark_undef_symbols(Layout*);
- // During garbage collection, this ensures externally visible symbols
- // are not treated as garbage while building shared objects.
+ // This tells garbage collection that this symbol is referenced.
void
- gc_mark_symbol_for_shlib(Symbol* sym);
+ gc_mark_symbol(Symbol* sym);
// During garbage collection, this keeps sections that correspond to
// symbols seen in dynamic objects.
// *DEFINED to the number of defined symbols.
template<int size, bool big_endian>
void
- add_from_relobj(Sized_relobj<size, big_endian>* relobj,
+ add_from_relobj(Sized_relobj_file<size, big_endian>* relobj,
const unsigned char* syms, size_t count,
size_t symndx_offset, const char* sym_names,
size_t sym_name_size,
- typename Sized_relobj<size, big_endian>::Symbols*,
+ typename Sized_relobj_file<size, big_endian>::Symbols*,
size_t* defined);
// Add one external symbol from the plugin object OBJ to the symbol table.
const char* sym_names, size_t sym_name_size,
const unsigned char* versym, size_t versym_size,
const std::vector<const char*>*,
- typename Sized_relobj<size, big_endian>::Symbols*,
+ typename Sized_relobj_file<size, big_endian>::Symbols*,
size_t* defined);
// Add one external symbol from the incremental object OBJ to the symbol
// table. Returns a pointer to the resolved symbol in the symbol table.
template<int size, bool big_endian>
- Symbol*
+ Sized_symbol<size>*
add_from_incrobj(Object* obj, const char* name,
const char* ver, elfcpp::Sym<size, big_endian>* sym);
// the locations the symbols is (weakly) defined (and certain other
// conditions are met). This map will be used later to detect
// possible One Definition Rule (ODR) violations.
- struct Symbol_location
- {
- Object* object; // Object where the symbol is defined.
- unsigned int shndx; // Section-in-object where the symbol is defined.
- off_t offset; // Offset-in-section where the symbol is defined.
- bool operator==(const Symbol_location& that) const
- {
- return (this->object == that.object
- && this->shndx == that.shndx
- && this->offset == that.offset);
- }
- };
-
struct Symbol_location_hash
{
size_t operator()(const Symbol_location& loc) const
// Whether we should override a symbol, based on flags in
// resolve.cc.
static bool
- should_override(const Symbol*, unsigned int, Defined, Object*, bool*, bool*);
+ should_override(const Symbol*, unsigned int, elfcpp::STT, Defined,
+ Object*, bool*, bool*);
// Report a problem in symbol resolution.
static void
// 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*, Defined);
+ should_override_with_special(const Symbol*, elfcpp::STT, Defined);
// Override a symbol with a special symbol.
template<int size>