// symtab.cc -- the gold symbol table
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
#include "symtab.h"
#include "script.h"
#include "plugin.h"
+#include "incremental.h"
namespace gold
{
this->is_defined_in_discarded_section_ = false;
this->undef_binding_set_ = false;
this->undef_binding_weak_ = false;
+ this->is_predefined_ = false;
}
// Return the demangled version of the symbol's name, but only
Symbol::init_base_output_data(const char* name, const char* version,
Output_data* od, elfcpp::STT type,
elfcpp::STB binding, elfcpp::STV visibility,
- unsigned char nonvis, bool offset_is_from_end)
+ unsigned char nonvis, bool offset_is_from_end,
+ bool is_predefined)
{
this->init_fields(name, version, type, binding, visibility, nonvis);
this->u_.in_output_data.output_data = od;
this->source_ = IN_OUTPUT_DATA;
this->in_reg_ = true;
this->in_real_elf_ = true;
+ this->is_predefined_ = is_predefined;
}
// Initialize the fields in the base class Symbol for a symbol defined
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)
{
this->init_fields(name, version, type, binding, visibility, nonvis);
this->u_.in_output_segment.output_segment = os;
this->source_ = IN_OUTPUT_SEGMENT;
this->in_reg_ = true;
this->in_real_elf_ = true;
+ this->is_predefined_ = is_predefined;
}
// Initialize the fields in the base class Symbol for a symbol defined
void
Symbol::init_base_constant(const char* name, const char* version,
elfcpp::STT type, elfcpp::STB binding,
- elfcpp::STV visibility, unsigned char nonvis)
+ elfcpp::STV visibility, unsigned char nonvis,
+ bool is_predefined)
{
this->init_fields(name, version, type, binding, visibility, nonvis);
this->source_ = IS_CONSTANT;
this->in_reg_ = true;
this->in_real_elf_ = true;
+ this->is_predefined_ = is_predefined;
}
// Initialize the fields in the base class Symbol for an undefined
elfcpp::STB binding,
elfcpp::STV visibility,
unsigned char nonvis,
- bool offset_is_from_end)
+ bool offset_is_from_end,
+ bool is_predefined)
{
this->init_base_output_data(name, version, od, type, binding, visibility,
- nonvis, offset_is_from_end);
+ nonvis, offset_is_from_end, is_predefined);
this->value_ = value;
this->symsize_ = symsize;
}
elfcpp::STB binding,
elfcpp::STV visibility,
unsigned char nonvis,
- Segment_offset_base offset_base)
+ Segment_offset_base offset_base,
+ bool is_predefined)
{
this->init_base_output_segment(name, version, os, type, binding, visibility,
- nonvis, offset_base);
+ nonvis, offset_base, is_predefined);
this->value_ = value;
this->symsize_ = symsize;
}
Sized_symbol<size>::init_constant(const char* name, const char* version,
Value_type value, Size_type symsize,
elfcpp::STT type, elfcpp::STB binding,
- elfcpp::STV visibility, unsigned char nonvis)
+ elfcpp::STV visibility, unsigned char nonvis,
+ bool is_predefined)
{
- this->init_base_constant(name, version, type, binding, visibility, nonvis);
+ this->init_base_constant(name, version, type, binding, visibility, nonvis,
+ is_predefined);
this->value_ = value;
this->symsize_ = symsize;
}
this->symsize_ = 0;
}
+// Return an allocated string holding the symbol's name as
+// name@version. This is used for relocatable links.
+
+std::string
+Symbol::versioned_name() const
+{
+ gold_assert(this->version_ != NULL);
+ std::string ret = this->name_;
+ ret.push_back('@');
+ if (this->is_def_)
+ ret.push_back('@');
+ ret += this->version_;
+ return ret;
+}
+
// Return true if SHNDX represents a common symbol.
bool
// 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
return false;
}
+ // If the symbol was forced dynamic in a --dynamic-list file
+ // or an --export-dynamic-symbol option, add it.
+ if (!this->is_from_dynobj()
+ && (parameters->options().in_dynamic_list(this->name())
+ || parameters->options().is_export_dynamic_symbol(this->name())))
+ {
+ if (!this->is_forced_local())
+ return true;
+ gold_warning(_("Cannot export local symbol '%s'"),
+ this->demangled_name().c_str());
+ return false;
+ }
+
// If the symbol was forced local in a version script, do not add it.
if (this->is_forced_local())
return false;
- // If the symbol was forced dynamic in a --dynamic-list file, add it.
- if (parameters->options().in_dynamic_list(this->name()))
- return true;
-
// If dynamic-list-data was specified, add any STT_OBJECT.
if (parameters->options().dynamic_list_data()
&& !this->is_from_dynobj()
// externally visible, we need to add it.
if ((parameters->options().export_dynamic() || parameters->options().shared())
&& !this->is_from_dynobj()
+ && !this->is_undefined()
&& this->is_externally_visible())
return true;
}
}
+// 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()
+{
+ this->source_ = IS_UNDEFINED;
+ this->is_predefined_ = false;
+}
+
// Class Symbol_table.
Symbol_table::Symbol_table(unsigned int count,
&& this->icf_->is_section_folded(obj, shndx));
}
-// For symbols that have been listed with -u option, add them to the
-// work list to avoid gc'ing them.
+// For symbols that have been listed with a -u or --export-dynamic-symbol
+// option, add them to the work list to avoid gc'ing them.
void
Symbol_table::gc_mark_undef_symbols(Layout* layout)
if (sym->source() == Symbol::FROM_OBJECT
&& !sym->object()->is_dynamic())
{
- Relobj* obj = static_cast<Relobj*>(sym->object());
- bool is_ordinary;
- unsigned int shndx = sym->shndx(&is_ordinary);
- if (is_ordinary)
- {
- gold_assert(this->gc_ != NULL);
- this->gc_->worklist().push(Section_id(obj, shndx));
- }
+ this->gc_mark_symbol(sym);
+ }
+ }
+
+ for (options::String_set::const_iterator p =
+ parameters->options().export_dynamic_symbol_begin();
+ p != parameters->options().export_dynamic_symbol_end();
+ ++p)
+ {
+ const char* name = p->c_str();
+ Symbol* sym = this->lookup(name);
+ // It's not an error if a symbol named by --export-dynamic-symbol
+ // is undefined.
+ if (sym != NULL
+ && sym->source() == Symbol::FROM_OBJECT
+ && !sym->object()->is_dynamic())
+ {
+ this->gc_mark_symbol(sym);
}
}
if (sym->source() == Symbol::FROM_OBJECT
&& !sym->object()->is_dynamic())
{
- Relobj* obj = static_cast<Relobj*>(sym->object());
- bool is_ordinary;
- unsigned int shndx = sym->shndx(&is_ordinary);
- if (is_ordinary)
- {
- gold_assert(this->gc_ != NULL);
- this->gc_->worklist().push(Section_id(obj, shndx));
- }
+ this->gc_mark_symbol(sym);
}
}
}
void
-Symbol_table::gc_mark_symbol_for_shlib(Symbol* sym)
+Symbol_table::gc_mark_symbol(Symbol* sym)
{
- if (!sym->is_from_dynobj()
- && sym->is_externally_visible())
+ // Add the object and section to the work list.
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
{
- //Add the object and section to the work list.
- Relobj* obj = static_cast<Relobj*>(sym->object());
- bool is_ordinary;
- unsigned int shndx = sym->shndx(&is_ordinary);
- if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
- {
- gold_assert(this->gc_!= NULL);
- this->gc_->worklist().push(Section_id(obj, shndx));
- }
+ gold_assert(this->gc_!= NULL);
+ this->gc_->worklist().push(Section_id(sym->object(), shndx));
}
+ parameters->target().gc_mark_symbol(this, sym);
}
// When doing garbage collection, keep symbols that have been seen in
{
if (sym->in_dyn() && sym->source() == Symbol::FROM_OBJECT
&& !sym->object()->is_dynamic())
- {
- Relobj* obj = static_cast<Relobj*>(sym->object());
- bool is_ordinary;
- unsigned int shndx = sym->shndx(&is_ordinary);
- if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
- {
- gold_assert(this->gc_ != NULL);
- this->gc_->worklist().push(Section_id(obj, shndx));
- }
- }
+ this->gc_mark_symbol(sym);
}
// Make TO a symbol which forwards to FROM.
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);
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);
}
// 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);
template<int size, bool big_endian>
void
Symbol_table::add_from_relobj(
- Sized_relobj<size, big_endian>* 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* sympointers,
+ typename Sized_relobj_file<size, big_endian>::Symbols* sympointers,
size_t* defined)
{
*defined = 0;
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(),
bool is_default_version = false;
bool is_forced_local = false;
+ // FIXME: For incremental links, we don't store version information,
+ // so we need to ignore version symbols for now.
+ if (parameters->incremental_update() && ver != NULL)
+ {
+ namelen = ver - name;
+ ver = NULL;
+ }
+
if (ver != NULL)
{
// The symbol name is of the form foo@VERSION or foo@@VERSION
{
memcpy(symbuf, p, sym_size);
elfcpp::Sym_write<size, big_endian> sw(symbuf);
- if (orig_st_shndx != elfcpp::SHN_UNDEF && is_ordinary)
+ if (orig_st_shndx != elfcpp::SHN_UNDEF
+ && is_ordinary
+ && relobj->e_type() == elfcpp::ET_REL)
{
- // Symbol values in object files are section relative.
- // This is normally what we want, but since here we are
- // converting the symbol to absolute we need to add the
- // section address. The section address in an object
+ // Symbol values in relocatable object files are section
+ // relative. This is normally what we want, but since here
+ // we are converting the symbol to absolute we need to add
+ // the section address. The section address in an object
// file is normally zero, but people can use a linker
// script to change it.
sw.put_st_value(sym.get_st_value()
is_default_version, *psym, st_shndx,
is_ordinary, orig_st_shndx);
- // If building a shared library using garbage collection, do not
- // treat externally visible symbols as garbage.
- if (parameters->options().gc_sections()
- && parameters->options().shared())
- this->gc_mark_symbol_for_shlib(res);
-
if (is_forced_local)
this->force_local(res);
+ // Do not treat this symbol as garbage if this symbol will be
+ // exported to the dynamic symbol table. This is true when
+ // building a shared library or using --export-dynamic and
+ // the symbol is externally visible.
+ if (parameters->options().gc_sections()
+ && res->is_externally_visible()
+ && !res->is_from_dynobj()
+ && (parameters->options().shared()
+ || parameters->options().export_dynamic()
+ || parameters->options().in_dynamic_list(res->name())))
+ this->gc_mark_symbol(res);
+
if (is_defined_in_discarded_section)
res->set_is_defined_in_discarded_section();
const unsigned char* versym,
size_t versym_size,
const std::vector<const char*>* version_map,
- typename Sized_relobj<size, big_endian>::Symbols* sympointers,
+ typename Sized_relobj_file<size, big_endian>::Symbols* sympointers,
size_t* defined)
{
*defined = 0;
return;
}
+ // FIXME: For incremental links, we don't store version information,
+ // so we need to ignore version symbols for now.
+ if (parameters->incremental_update())
+ versym = NULL;
+
if (versym != NULL && versym_size / 2 < count)
{
dynobj->error(_("too few symbol versions"));
this->record_weak_aliases(&object_symbols);
}
+// Add a symbol from a incremental object file.
+
+template<int size, bool big_endian>
+Sized_symbol<size>*
+Symbol_table::add_from_incrobj(
+ Object* obj,
+ const char* name,
+ const char* ver,
+ elfcpp::Sym<size, big_endian>* sym)
+{
+ unsigned int st_shndx = sym->get_st_shndx();
+ bool is_ordinary = st_shndx < elfcpp::SHN_LORESERVE;
+
+ Stringpool::Key ver_key = 0;
+ bool is_default_version = false;
+ bool is_forced_local = false;
+
+ Stringpool::Key name_key;
+ name = this->namepool_.add(name, true, &name_key);
+
+ Sized_symbol<size>* res;
+ res = this->add_from_object(obj, name, name_key, ver, ver_key,
+ is_default_version, *sym, st_shndx,
+ is_ordinary, st_shndx);
+
+ if (is_forced_local)
+ this->force_local(res);
+
+ return res;
+}
+
// This is used to sort weak aliases. We sort them first by section
// index, then by offset, then by weak ahead of strong.
bool* resolve_oldsym)
{
*resolve_oldsym = false;
+ *poldsym = NULL;
// If the caller didn't give us a version, see if we get one from
// the version script.
return NULL;
*pname = oldsym->name();
- if (!is_default_version)
+ if (is_default_version)
+ *pversion = this->namepool_.add(*pversion, true, NULL);
+ else
*pversion = oldsym->version();
}
else
return NULL;
sym->init_output_data(name, version, od, value, symsize, type, binding,
- visibility, nonvis, offset_is_from_end);
+ visibility, nonvis, offset_is_from_end,
+ defined == PREDEFINED);
if (oldsym == NULL)
{
return sym;
}
- if (Symbol_table::should_override_with_special(oldsym, defined))
+ if (Symbol_table::should_override_with_special(oldsym, type, defined))
this->override_with_special(oldsym, sym);
if (resolve_oldsym)
return NULL;
sym->init_output_segment(name, version, os, value, symsize, type, binding,
- visibility, nonvis, offset_base);
+ visibility, nonvis, offset_base,
+ defined == PREDEFINED);
if (oldsym == NULL)
{
return sym;
}
- if (Symbol_table::should_override_with_special(oldsym, defined))
+ if (Symbol_table::should_override_with_special(oldsym, type, defined))
this->override_with_special(oldsym, sym);
if (resolve_oldsym)
return NULL;
sym->init_constant(name, version, value, symsize, type, binding, visibility,
- nonvis);
+ nonvis, defined == PREDEFINED);
if (oldsym == NULL)
{
}
if (force_override
- || Symbol_table::should_override_with_special(oldsym, defined))
+ || Symbol_table::should_override_with_special(oldsym, type, defined))
this->override_with_special(oldsym, sym);
if (resolve_oldsym)
++p)
this->add_undefined_symbol_from_command_line<size>(p->c_str());
+ for (options::String_set::const_iterator p =
+ parameters->options().export_dynamic_symbol_begin();
+ p != parameters->options().export_dynamic_symbol_end();
+ ++p)
+ this->add_undefined_symbol_from_command_line<size>(p->c_str());
+
for (Script_options::referenced_const_iterator p =
layout->script_options()->referenced_begin();
p != layout->script_options()->referenced_end();
Stringpool* dynpool,
Versions* versions)
{
+ 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)
syms->push_back(sym);
dynpool->add(sym->name(), false, NULL);
- // Record any version information.
- if (sym->version() != NULL)
- versions->record_version(this, dynpool, sym);
-
// If the symbol is defined in a dynamic object and is
- // referenced in a regular object, then mark the dynamic
- // object as needed. This is used to implement --as-needed.
- if (sym->is_from_dynobj() && sym->in_reg())
+ // referenced strongly in a regular object, then mark the
+ // dynamic object as needed. This is used to implement
+ // --as-needed.
+ if (sym->is_from_dynobj()
+ && sym->in_reg()
+ && !sym->is_undef_binding_weak())
sym->object()->set_is_needed();
+
+ // Record any version information, except those from
+ // as-needed libraries not seen to be needed. Note that the
+ // is_needed state for such libraries can change in this loop.
+ if (sym->version() != NULL)
+ {
+ if (!sym->is_from_dynobj()
+ || !sym->object()->as_needed()
+ || sym->object()->is_needed())
+ versions->record_version(this, dynpool, sym);
+ else
+ as_needed_sym.push_back(sym);
+ }
}
}
+ // Process version information for symbols from as-needed libraries.
+ for (std::vector<Symbol*>::iterator p = as_needed_sym.begin();
+ p != as_needed_sym.end();
+ ++p)
+ {
+ Symbol* sym = *p;
+
+ if (sym->object()->is_needed())
+ versions->record_version(this, dynpool, sym);
+ else
+ sym->clear_version();
+ }
+
// Finish up the versions. In some cases this may add new dynamic
// symbols.
index = versions->finalize(this, index, syms);
unsigned int* pindex, off_t* poff)
{
sym->set_symtab_index(*pindex);
- pool->add(sym->name(), false, NULL);
+ if (sym->version() == NULL || !parameters->options().relocatable())
+ pool->add(sym->name(), false, NULL);
+ else
+ pool->add(sym->versioned_name(), true, NULL);
++*pindex;
*poff += elfcpp::Elf_sizes<size>::sym_size;
}
typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value();
typename elfcpp::Elf_types<size>::Elf_Addr dynsym_value = sym_value;
elfcpp::STB binding = sym->binding();
+
+ // If --no-gnu-unique is set, change STB_GNU_UNIQUE to STB_GLOBAL.
+ if (binding == elfcpp::STB_GNU_UNIQUE
+ && !parameters->options().gnu_unique())
+ binding = elfcpp::STB_GLOBAL;
+
switch (sym->source())
{
case Symbol::FROM_OBJECT:
break;
case Symbol::IN_OUTPUT_DATA:
- shndx = sym->output_data()->out_shndx();
- if (shndx >= elfcpp::SHN_LORESERVE)
- {
- if (sym_index != -1U)
- symtab_xindex->add(sym_index, shndx);
- if (dynsym_index != -1U)
- dynsym_xindex->add(dynsym_index, shndx);
- shndx = elfcpp::SHN_XINDEX;
- }
+ {
+ Output_data* od = sym->output_data();
+
+ shndx = od->out_shndx();
+ if (shndx >= elfcpp::SHN_LORESERVE)
+ {
+ if (sym_index != -1U)
+ symtab_xindex->add(sym_index, shndx);
+ if (dynsym_index != -1U)
+ dynsym_xindex->add(dynsym_index, shndx);
+ shndx = elfcpp::SHN_XINDEX;
+ }
+
+ // In object files symbol values are section
+ // relative.
+ if (parameters->options().relocatable())
+ sym_value -= od->address();
+ }
break;
case Symbol::IN_OUTPUT_SEGMENT:
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);
}
}
unsigned char* p) const
{
elfcpp::Sym_write<size, big_endian> osym(p);
- osym.put_st_name(pool->get_offset(sym->name()));
+ if (sym->version() == NULL || !parameters->options().relocatable())
+ osym.put_st_name(pool->get_offset(sym->name()));
+ else
+ osym.put_st_name(pool->get_offset(sym->versioned_name()));
osym.put_st_value(value);
// Use a symbol size of zero for undefined symbols from shared libraries.
if (shndx == elfcpp::SHN_UNDEF && sym->is_from_dynobj())
Task_lock_obj<Object> tl(task, loc.object);
std::vector<std::string> result;
+ Symbol_location code_loc = loc;
+ parameters->target().function_location(&code_loc);
// 16 is the size of the object-cache that one_addr2line should use.
std::string canonical_result = Dwarf_line_info::one_addr2line(
- loc.object, loc.shndx, loc.offset, 16, &result);
+ code_loc.object, code_loc.shndx, code_loc.offset, 16, &result);
if (!canonical_result.empty())
result.push_back(canonical_result);
return result;
size_t relnum, off_t reloffset) const
{
gold_assert(sym->has_warning());
+
+ // We don't want to issue a warning for a relocation against the
+ // symbol in the same object file in which the symbol is defined.
+ if (sym->object() == relinfo->object)
+ return;
+
Warning_table::const_iterator p = this->warnings_.find(sym->name());
gold_assert(p != this->warnings_.end());
gold_warning_at_location(relinfo, relnum, reloffset,
template
void
Symbol_table::add_from_relobj<32, false>(
- Sized_relobj<32, false>* relobj,
+ Sized_relobj_file<32, false>* relobj,
const unsigned char* syms,
size_t count,
size_t symndx_offset,
const char* sym_names,
size_t sym_name_size,
- Sized_relobj<32, false>::Symbols* sympointers,
+ Sized_relobj_file<32, false>::Symbols* sympointers,
size_t* defined);
#endif
template
void
Symbol_table::add_from_relobj<32, true>(
- Sized_relobj<32, true>* relobj,
+ Sized_relobj_file<32, true>* relobj,
const unsigned char* syms,
size_t count,
size_t symndx_offset,
const char* sym_names,
size_t sym_name_size,
- Sized_relobj<32, true>::Symbols* sympointers,
+ Sized_relobj_file<32, true>::Symbols* sympointers,
size_t* defined);
#endif
template
void
Symbol_table::add_from_relobj<64, false>(
- Sized_relobj<64, false>* relobj,
+ Sized_relobj_file<64, false>* relobj,
const unsigned char* syms,
size_t count,
size_t symndx_offset,
const char* sym_names,
size_t sym_name_size,
- Sized_relobj<64, false>::Symbols* sympointers,
+ Sized_relobj_file<64, false>::Symbols* sympointers,
size_t* defined);
#endif
template
void
Symbol_table::add_from_relobj<64, true>(
- Sized_relobj<64, true>* relobj,
+ Sized_relobj_file<64, true>* relobj,
const unsigned char* syms,
size_t count,
size_t symndx_offset,
const char* sym_names,
size_t sym_name_size,
- Sized_relobj<64, true>::Symbols* sympointers,
+ Sized_relobj_file<64, true>::Symbols* sympointers,
size_t* defined);
#endif
const unsigned char* versym,
size_t versym_size,
const std::vector<const char*>* version_map,
- Sized_relobj<32, false>::Symbols* sympointers,
+ Sized_relobj_file<32, false>::Symbols* sympointers,
size_t* defined);
#endif
const unsigned char* versym,
size_t versym_size,
const std::vector<const char*>* version_map,
- Sized_relobj<32, true>::Symbols* sympointers,
+ Sized_relobj_file<32, true>::Symbols* sympointers,
size_t* defined);
#endif
const unsigned char* versym,
size_t versym_size,
const std::vector<const char*>* version_map,
- Sized_relobj<64, false>::Symbols* sympointers,
+ Sized_relobj_file<64, false>::Symbols* sympointers,
size_t* defined);
#endif
const unsigned char* versym,
size_t versym_size,
const std::vector<const char*>* version_map,
- Sized_relobj<64, true>::Symbols* sympointers,
+ Sized_relobj_file<64, true>::Symbols* sympointers,
size_t* defined);
#endif
+#ifdef HAVE_TARGET_32_LITTLE
+template
+Sized_symbol<32>*
+Symbol_table::add_from_incrobj(
+ Object* obj,
+ const char* name,
+ const char* ver,
+ elfcpp::Sym<32, false>* sym);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+Sized_symbol<32>*
+Symbol_table::add_from_incrobj(
+ Object* obj,
+ const char* name,
+ const char* ver,
+ elfcpp::Sym<32, true>* sym);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+Sized_symbol<64>*
+Symbol_table::add_from_incrobj(
+ Object* obj,
+ const char* name,
+ const char* ver,
+ elfcpp::Sym<64, false>* sym);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+Sized_symbol<64>*
+Symbol_table::add_from_incrobj(
+ Object* obj,
+ const char* name,
+ const char* ver,
+ elfcpp::Sym<64, true>* sym);
+#endif
+
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
template
void
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