summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/gold/symtab.cc
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.25/gold/symtab.cc')
-rw-r--r--binutils-2.25/gold/symtab.cc95
1 files changed, 88 insertions, 7 deletions
diff --git a/binutils-2.25/gold/symtab.cc b/binutils-2.25/gold/symtab.cc
index 2e17529b..70fb3f04 100644
--- a/binutils-2.25/gold/symtab.cc
+++ b/binutils-2.25/gold/symtab.cc
@@ -1,6 +1,6 @@
// symtab.cc -- the gold symbol table
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2006-2014 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -334,7 +334,7 @@ Sized_symbol<size>::allocate_common(Output_data* od, Value_type value)
// Return true if this symbol should be added to the dynamic symbol
// table.
-inline bool
+bool
Symbol::should_add_dynsym_entry(Symbol_table* symtab) const
{
// If the symbol is only present on plugin files, the plugin decided we
@@ -527,6 +527,31 @@ Symbol::set_output_section(Output_section* os)
}
}
+// 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
+Symbol::set_output_segment(Output_segment* os, Segment_offset_base base)
+{
+ gold_assert(this->is_predefined_);
+ this->source_ = IN_OUTPUT_SEGMENT;
+ this->u_.in_output_segment.output_segment = os;
+ this->u_.in_output_segment.offset_base = 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
+Symbol::set_undefined()
+{
+ gold_assert(this->is_predefined_);
+ this->source_ = IS_UNDEFINED;
+ this->is_predefined_ = false;
+}
+
// Class Symbol_table.
Symbol_table::Symbol_table(unsigned int count,
@@ -955,7 +980,8 @@ Symbol_table::add_from_object(Object* object,
gold_assert(ret != NULL);
was_undefined = ret->is_undefined();
- was_common = ret->is_common();
+ // Commons from plugins are just placeholders.
+ was_common = ret->is_common() && ret->object()->pluginobj() == NULL;
this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
version);
@@ -978,7 +1004,8 @@ Symbol_table::add_from_object(Object* object,
ret = this->get_sized_symbol<size>(insdefault.first->second);
was_undefined = ret->is_undefined();
- was_common = ret->is_common();
+ // Commons from plugins are just placeholders.
+ was_common = ret->is_common() && ret->object()->pluginobj() == NULL;
this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
version);
@@ -1041,8 +1068,10 @@ Symbol_table::add_from_object(Object* object,
}
// Keep track of common symbols, to speed up common symbol
- // allocation.
- if (!was_common && ret->is_common())
+ // allocation. Don't record commons from plugin objects;
+ // we need to wait until we see the real symbol in the
+ // replacement file.
+ if (!was_common && ret->is_common() && ret->object()->pluginobj() == NULL)
{
if (ret->type() == elfcpp::STT_TLS)
this->tls_commons_.push_back(ret);
@@ -1108,6 +1137,10 @@ Symbol_table::add_from_relobj(
const char* name = sym_names + st_name;
+ if (strcmp (name, "__gnu_lto_slim") == 0)
+ gold_info(_("%s: plugin needed to handle lto object"),
+ relobj->name().c_str());
+
bool is_ordinary;
unsigned int st_shndx = relobj->adjust_sym_shndx(i + symndx_offset,
sym.get_st_shndx(),
@@ -1258,7 +1291,8 @@ Symbol_table::add_from_relobj(
&& res->is_externally_visible()
&& !res->is_from_dynobj()
&& (parameters->options().shared()
- || parameters->options().export_dynamic()))
+ || parameters->options().export_dynamic()
+ || parameters->options().in_dynamic_list(res->name())))
this->gc_mark_symbol(res);
if (is_defined_in_discarded_section)
@@ -2370,6 +2404,25 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
{
std::vector<Symbol*> as_needed_sym;
+ // Allow a target to set dynsym indexes.
+ if (parameters->target().has_custom_set_dynsym_indexes())
+ {
+ std::vector<Symbol*> dyn_symbols;
+ for (Symbol_table_type::iterator p = this->table_.begin();
+ p != this->table_.end();
+ ++p)
+ {
+ Symbol* sym = p->second;
+ if (!sym->should_add_dynsym_entry(this))
+ sym->set_dynsym_index(-1U);
+ else
+ dyn_symbols.push_back(sym);
+ }
+
+ return parameters->target().set_dynsym_indexes(&dyn_symbols, index, syms,
+ dynpool, versions, this);
+ }
+
for (Symbol_table_type::iterator p = this->table_.begin();
p != this->table_.end();
++p)
@@ -2992,6 +3045,8 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
this->sized_write_symbol<size, big_endian>(sym, dynsym_value, shndx,
binding, dynpool, pd);
+ // Allow a target to adjust dynamic symbol value.
+ parameters->target().adjust_dyn_symbol(sym, pd);
}
}
@@ -3622,6 +3677,32 @@ Symbol_table::define_with_copy_reloc<64>(
elfcpp::Elf_types<64>::Elf_Addr value);
#endif
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
+template
+void
+Sized_symbol<32>::init_output_data(const char* name, const char* version,
+ Output_data* od, Value_type value,
+ Size_type symsize, elfcpp::STT type,
+ elfcpp::STB binding,
+ elfcpp::STV visibility,
+ unsigned char nonvis,
+ bool offset_is_from_end,
+ bool is_predefined);
+#endif
+
+#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
+template
+void
+Sized_symbol<64>::init_output_data(const char* name, const char* version,
+ Output_data* od, Value_type value,
+ Size_type symsize, elfcpp::STT type,
+ elfcpp::STB binding,
+ elfcpp::STV visibility,
+ unsigned char nonvis,
+ bool offset_is_from_end,
+ bool is_predefined);
+#endif
+
#ifdef HAVE_TARGET_32_LITTLE
template
void