X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=gold%2Fsymtab.cc;h=24430237d62865b7ef9544916517df8d9c54cb6c;hb=3728821ffcf74858b028948e224e1dc4695d9112;hp=5237b8cb916d107596c301fd4f2b47cebb35fc70;hpb=9e2dcb779c27737af88468b29aa1d2a15b0b770f;p=binutils-gdb.git diff --git a/gold/symtab.cc b/gold/symtab.cc index 5237b8cb916..24430237d62 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -23,10 +23,12 @@ #include "gold.h" #include +#include #include #include #include "object.h" +#include "dwarf_reader.h" #include "dynobj.h" #include "output.h" #include "target.h" @@ -59,12 +61,15 @@ Symbol::init_fields(const char* name, const char* version, this->is_target_special_ = false; this->is_def_ = false; this->is_forwarder_ = false; + this->has_alias_ = false; this->needs_dynsym_entry_ = false; this->in_reg_ = false; this->in_dyn_ = false; this->has_got_offset_ = false; this->has_plt_offset_ = false; this->has_warning_ = false; + this->is_copied_from_dynobj_ = false; + this->needs_value_in_got_ = false; } // Initialize the fields in the base class Symbol for SYM in OBJECT. @@ -187,6 +192,27 @@ Sized_symbol::init(const char* name, Value_type value, Size_type symsize, this->symsize_ = symsize; } +// Return true if this symbol should be added to the dynamic symbol +// table. + +inline bool +Symbol::should_add_dynsym_entry() const +{ + // If the symbol is used by a dynamic relocation, we need to add it. + if (this->needs_dynsym_entry()) + return true; + + // If exporting all symbols or building a shared library, + // and the symbol is defined in a regular object and is + // externally visible, we need to add it. + if ((parameters->export_dynamic() || parameters->output_is_shared()) + && !this->is_from_dynobj() + && this->is_externally_visible()) + return true; + + return false; +} + // Return true if the final value of this symbol is known at link // time. @@ -319,7 +345,7 @@ Symbol_table::resolve(Sized_symbol* to, const Sized_symbol* from, esym.put_st_info(from->binding(), from->type()); esym.put_st_other(from->visibility(), from->nonvis()); esym.put_st_shndx(from->shndx()); - Symbol_table::resolve(to, esym.sym(), from->object(), version); + this->resolve(to, esym.sym(), esym.sym(), from->object(), version); if (from->in_reg()) to->set_in_reg(); if (from->in_dyn()) @@ -348,16 +374,22 @@ Symbol_table::resolve(Sized_symbol* to, const Sized_symbol* from, // object file as a forwarder, and record it in the forwarders_ map. // Note that entries in the hash table will never be marked as // forwarders. +// +// SYM and ORIG_SYM are almost always the same. ORIG_SYM is the +// symbol exactly as it existed in the input file. SYM is usually +// that as well, but can be modified, for instance if we determine +// it's in a to-be-discarded section. template -Symbol* +Sized_symbol* Symbol_table::add_from_object(Object* object, const char *name, Stringpool::Key name_key, const char *version, Stringpool::Key version_key, bool def, - const elfcpp::Sym& sym) + const elfcpp::Sym& sym, + const elfcpp::Sym& orig_sym) { Symbol* const snull = NULL; std::pair ins = @@ -392,7 +424,7 @@ Symbol_table::add_from_object(Object* object, was_undefined = ret->is_undefined(); was_common = ret->is_common(); - Symbol_table::resolve(ret, sym, object, version); + this->resolve(ret, sym, orig_sym, object, version); if (def) { @@ -432,7 +464,7 @@ Symbol_table::add_from_object(Object* object, ret = this->get_sized_symbol SELECT_SIZE_NAME(size) ( insdef.first->second SELECT_SIZE(size)); - Symbol_table::resolve(ret, sym, object, version); + this->resolve(ret, sym, orig_sym, object, version); ins.first->second = ret; } else @@ -498,7 +530,7 @@ Symbol_table::add_from_relobj( size_t count, const char* sym_names, size_t sym_name_size, - Symbol** sympointers) + typename Sized_relobj::Symbols* sympointers) { gold_assert(size == relobj->target()->get_size()); gold_assert(size == parameters->get_size()); @@ -514,11 +546,9 @@ Symbol_table::add_from_relobj( unsigned int st_name = psym->get_st_name(); if (st_name >= sym_name_size) { - fprintf(stderr, - _("%s: %s: bad global symbol name offset %u at %lu\n"), - program_name, relobj->name().c_str(), st_name, - static_cast(i)); - gold_exit(false); + relobj->error(_("bad global symbol name offset %u at %zu"), + st_name, i); + continue; } const char* name = sym_names + st_name; @@ -543,18 +573,18 @@ Symbol_table::add_from_relobj( // this is the default version. const char* ver = strchr(name, '@'); - Symbol* res; + Sized_symbol* res; if (ver == NULL) { Stringpool::Key name_key; - name = this->namepool_.add(name, &name_key); + name = this->namepool_.add(name, true, &name_key); res = this->add_from_object(relobj, name, name_key, NULL, 0, - false, *psym); + false, *psym, sym); } else { Stringpool::Key name_key; - name = this->namepool_.add(name, ver - name, &name_key); + name = this->namepool_.add_prefix(name, ver - name, &name_key); bool def = false; ++ver; @@ -565,13 +595,13 @@ Symbol_table::add_from_relobj( } Stringpool::Key ver_key; - ver = this->namepool_.add(ver, &ver_key); + ver = this->namepool_.add(ver, true, &ver_key); res = this->add_from_object(relobj, name, name_key, ver, ver_key, - def, *psym); + def, *psym, sym); } - *sympointers++ = res; + (*sympointers)[i] = res; } } @@ -594,13 +624,22 @@ Symbol_table::add_from_dynobj( if (versym != NULL && versym_size / 2 < count) { - fprintf(stderr, _("%s: %s: too few symbol versions\n"), - program_name, dynobj->name().c_str()); - gold_exit(false); + dynobj->error(_("too few symbol versions")); + return; } const int sym_size = elfcpp::Elf_sizes::sym_size; + // We keep a list of all STT_OBJECT symbols, so that we can resolve + // weak aliases. This is necessary because if the dynamic object + // provides the same variable under two names, one of which is a + // weak definition, and the regular object refers to the weak + // definition, we have to put both the weak definition and the + // strong definition into the dynamic symbol table. Given a weak + // definition, the only way that we can find the corresponding + // strong definition, if any, is to search the symbol table. + std::vector*> object_symbols; + const unsigned char* p = syms; const unsigned char* vs = versym; for (size_t i = 0; i < count; ++i, p += sym_size, vs += 2) @@ -614,90 +653,179 @@ Symbol_table::add_from_dynobj( unsigned int st_name = sym.get_st_name(); if (st_name >= sym_name_size) { - fprintf(stderr, _("%s: %s: bad symbol name offset %u at %lu\n"), - program_name, dynobj->name().c_str(), st_name, - static_cast(i)); - gold_exit(false); + dynobj->error(_("bad symbol name offset %u at %zu"), + st_name, i); + continue; } const char* name = sym_names + st_name; + Sized_symbol* res; + if (versym == NULL) { Stringpool::Key name_key; - name = this->namepool_.add(name, &name_key); - this->add_from_object(dynobj, name, name_key, NULL, 0, - false, sym); - continue; + name = this->namepool_.add(name, true, &name_key); + res = this->add_from_object(dynobj, name, name_key, NULL, 0, + false, sym, sym); } + else + { + // Read the version information. - // Read the version information. + unsigned int v = elfcpp::Swap<16, big_endian>::readval(vs); - unsigned int v = elfcpp::Swap<16, big_endian>::readval(vs); + bool hidden = (v & elfcpp::VERSYM_HIDDEN) != 0; + v &= elfcpp::VERSYM_VERSION; - bool hidden = (v & elfcpp::VERSYM_HIDDEN) != 0; - v &= elfcpp::VERSYM_VERSION; + // The Sun documentation says that V can be VER_NDX_LOCAL, + // or VER_NDX_GLOBAL, or a version index. The meaning of + // VER_NDX_LOCAL is defined as "Symbol has local scope." + // The old GNU linker will happily generate VER_NDX_LOCAL + // for an undefined symbol. I don't know what the Sun + // linker will generate. - // The Sun documentation says that V can be VER_NDX_LOCAL, or - // VER_NDX_GLOBAL, or a version index. The meaning of - // VER_NDX_LOCAL is defined as "Symbol has local scope." The - // old GNU linker will happily generate VER_NDX_LOCAL for an - // undefined symbol. I don't know what the Sun linker will - // generate. + if (v == static_cast(elfcpp::VER_NDX_LOCAL) + && sym.get_st_shndx() != elfcpp::SHN_UNDEF) + { + // This symbol should not be visible outside the object. + continue; + } - if (v == static_cast(elfcpp::VER_NDX_LOCAL) - && sym.get_st_shndx() != elfcpp::SHN_UNDEF) - { - // This symbol should not be visible outside the object. - continue; - } + // At this point we are definitely going to add this symbol. + Stringpool::Key name_key; + name = this->namepool_.add(name, true, &name_key); - // At this point we are definitely going to add this symbol. - Stringpool::Key name_key; - name = this->namepool_.add(name, &name_key); + if (v == static_cast(elfcpp::VER_NDX_LOCAL) + || v == static_cast(elfcpp::VER_NDX_GLOBAL)) + { + // This symbol does not have a version. + res = this->add_from_object(dynobj, name, name_key, NULL, 0, + false, sym, sym); + } + else + { + if (v >= version_map->size()) + { + dynobj->error(_("versym for symbol %zu out of range: %u"), + i, v); + continue; + } - if (v == static_cast(elfcpp::VER_NDX_LOCAL) - || v == static_cast(elfcpp::VER_NDX_GLOBAL)) - { - // This symbol does not have a version. - this->add_from_object(dynobj, name, name_key, NULL, 0, false, sym); - continue; - } + const char* version = (*version_map)[v]; + if (version == NULL) + { + dynobj->error(_("versym for symbol %zu has no name: %u"), + i, v); + continue; + } - if (v >= version_map->size()) - { - fprintf(stderr, - _("%s: %s: versym for symbol %zu out of range: %u\n"), - program_name, dynobj->name().c_str(), i, v); - gold_exit(false); + Stringpool::Key version_key; + version = this->namepool_.add(version, true, &version_key); + + // If this is an absolute symbol, and the version name + // and symbol name are the same, then this is the + // version definition symbol. These symbols exist to + // support using -u to pull in particular versions. We + // do not want to record a version for them. + if (sym.get_st_shndx() == elfcpp::SHN_ABS + && name_key == version_key) + res = this->add_from_object(dynobj, name, name_key, NULL, 0, + false, sym, sym); + else + { + const bool def = (!hidden + && (sym.get_st_shndx() + != elfcpp::SHN_UNDEF)); + res = this->add_from_object(dynobj, name, name_key, version, + version_key, def, sym, sym); + } + } } - const char* version = (*version_map)[v]; - if (version == NULL) - { - fprintf(stderr, _("%s: %s: versym for symbol %zu has no name: %u\n"), - program_name, dynobj->name().c_str(), i, v); - gold_exit(false); - } + if (sym.get_st_shndx() != elfcpp::SHN_UNDEF + && sym.get_st_type() == elfcpp::STT_OBJECT) + object_symbols.push_back(res); + } + + this->record_weak_aliases(&object_symbols); +} + +// This is used to sort weak aliases. We sort them first by section +// index, then by offset, then by weak ahead of strong. + +template +class Weak_alias_sorter +{ + public: + bool operator()(const Sized_symbol*, const Sized_symbol*) const; +}; + +template +bool +Weak_alias_sorter::operator()(const Sized_symbol* s1, + const Sized_symbol* s2) const +{ + if (s1->shndx() != s2->shndx()) + return s1->shndx() < s2->shndx(); + if (s1->value() != s2->value()) + return s1->value() < s2->value(); + if (s1->binding() != s2->binding()) + { + if (s1->binding() == elfcpp::STB_WEAK) + return true; + if (s2->binding() == elfcpp::STB_WEAK) + return false; + } + return std::string(s1->name()) < std::string(s2->name()); +} - Stringpool::Key version_key; - version = this->namepool_.add(version, &version_key); +// SYMBOLS is a list of object symbols from a dynamic object. Look +// for any weak aliases, and record them so that if we add the weak +// alias to the dynamic symbol table, we also add the corresponding +// strong symbol. - // If this is an absolute symbol, and the version name and - // symbol name are the same, then this is the version definition - // symbol. These symbols exist to support using -u to pull in - // particular versions. We do not want to record a version for - // them. - if (sym.get_st_shndx() == elfcpp::SHN_ABS && name_key == version_key) +template +void +Symbol_table::record_weak_aliases(std::vector*>* symbols) +{ + // Sort the vector by section index, then by offset, then by weak + // ahead of strong. + std::sort(symbols->begin(), symbols->end(), Weak_alias_sorter()); + + // Walk through the vector. For each weak definition, record + // aliases. + for (typename std::vector*>::const_iterator p = + symbols->begin(); + p != symbols->end(); + ++p) + { + if ((*p)->binding() != elfcpp::STB_WEAK) + continue; + + // Build a circular list of weak aliases. Each symbol points to + // the next one in the circular list. + + Sized_symbol* from_sym = *p; + typename std::vector*>::const_iterator q; + for (q = p + 1; q != symbols->end(); ++q) { - this->add_from_object(dynobj, name, name_key, NULL, 0, false, sym); - continue; + if ((*q)->shndx() != from_sym->shndx() + || (*q)->value() != from_sym->value()) + break; + + this->weak_aliases_[from_sym] = *q; + from_sym->set_has_alias(); + from_sym = *q; } - const bool def = !hidden && sym.get_st_shndx() != elfcpp::SHN_UNDEF; + if (from_sym != *p) + { + this->weak_aliases_[from_sym] = *p; + from_sym->set_has_alias(); + } - this->add_from_object(dynobj, name, name_key, version, version_key, - def, sym); + p = q - 1; } } @@ -731,11 +859,11 @@ Symbol_table::define_special_symbol(const Target* target, const char** pname, { // Canonicalize NAME and VERSION. Stringpool::Key name_key; - *pname = this->namepool_.add(*pname, &name_key); + *pname = this->namepool_.add(*pname, true, &name_key); Stringpool::Key version_key = 0; if (*pversion != NULL) - *pversion = this->namepool_.add(*pversion, &version_key); + *pversion = this->namepool_.add(*pversion, true, &version_key); Symbol* const snull = NULL; std::pair ins = @@ -875,7 +1003,7 @@ Symbol_table::do_define_in_output_data( if (oldsym != NULL && Symbol_table::should_override_with_special(oldsym)) - oldsym->override_with_special(sym); + this->override_with_special(oldsym, sym); return sym; } @@ -969,7 +1097,7 @@ Symbol_table::do_define_in_output_segment( if (oldsym != NULL && Symbol_table::should_override_with_special(oldsym)) - oldsym->override_with_special(sym); + this->override_with_special(oldsym, sym); return sym; } @@ -1056,7 +1184,7 @@ Symbol_table::do_define_as_constant( if (oldsym != NULL && Symbol_table::should_override_with_special(oldsym)) - oldsym->override_with_special(sym); + this->override_with_special(oldsym, sym); return sym; } @@ -1105,14 +1233,77 @@ Symbol_table::define_symbols(const Layout* layout, const Target* target, } } +// Define CSYM 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 +void +Symbol_table::define_with_copy_reloc(const Target* target, + Sized_symbol* csym, + Output_data* posd, uint64_t value) +{ + gold_assert(csym->is_from_dynobj()); + gold_assert(!csym->is_copied_from_dynobj()); + Object* object = csym->object(); + gold_assert(object->is_dynamic()); + Dynobj* dynobj = static_cast(object); + + // Our copied variable has to override any variable in a shared + // library. + elfcpp::STB binding = csym->binding(); + if (binding == elfcpp::STB_WEAK) + binding = elfcpp::STB_GLOBAL; + + this->define_in_output_data(target, csym->name(), csym->version(), + posd, value, csym->symsize(), + csym->type(), binding, + csym->visibility(), csym->nonvis(), + false, false); + + csym->set_is_copied_from_dynobj(); + csym->set_needs_dynsym_entry(); + + this->copied_symbol_dynobjs_[csym] = dynobj; + + // We have now defined all aliases, but we have not entered them all + // in the copied_symbol_dynobjs_ map. + if (csym->has_alias()) + { + Symbol* sym = csym; + while (true) + { + sym = this->weak_aliases_[sym]; + if (sym == csym) + break; + gold_assert(sym->output_data() == posd); + + sym->set_is_copied_from_dynobj(); + this->copied_symbol_dynobjs_[sym] = dynobj; + } + } +} + +// SYM is defined using a COPY reloc. Return the dynamic object where +// the original definition was found. + +Dynobj* +Symbol_table::get_copy_source(const Symbol* sym) const +{ + gold_assert(sym->is_copied_from_dynobj()); + Copied_symbol_dynobjs::const_iterator p = + this->copied_symbol_dynobjs_.find(sym); + gold_assert(p != this->copied_symbol_dynobjs_.end()); + return p->second; +} + // Set the dynamic symbol indexes. INDEX is the index of the first // global dynamic symbol. Pointers to the symbols are stored into the // vector SYMS. The names are added to DYNPOOL. This returns an // updated dynamic symbol index. unsigned int -Symbol_table::set_dynsym_indexes(const General_options* options, - const Target* target, +Symbol_table::set_dynsym_indexes(const Target* target, unsigned int index, std::vector* syms, Stringpool* dynpool, @@ -1128,21 +1319,18 @@ Symbol_table::set_dynsym_indexes(const General_options* options, // some symbols appear more than once in the symbol table, with // and without a version. - if (!sym->needs_dynsym_entry() - && (!options->export_dynamic() - || !sym->in_reg() - || !sym->is_externally_visible())) + if (!sym->should_add_dynsym_entry()) sym->set_dynsym_index(-1U); else if (!sym->has_dynsym_index()) { sym->set_dynsym_index(index); ++index; syms->push_back(sym); - dynpool->add(sym->name(), NULL); + dynpool->add(sym->name(), false, NULL); // Record any version information. if (sym->version() != NULL) - versions->record_version(options, dynpool, sym); + versions->record_version(this, dynpool, sym); } } @@ -1245,9 +1433,9 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) if (shndx >= elfcpp::SHN_LORESERVE && shndx != elfcpp::SHN_ABS) { - fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"), - program_name, sym->name(), shndx); - gold_exit(false); + gold_error(_("%s: unsupported symbol section 0x%x"), + sym->name(), shndx); + shndx = elfcpp::SHN_UNDEF; } Object* symobj = sym->object(); @@ -1322,7 +1510,7 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) else { sym->set_symtab_index(index); - pool->add(sym->name(), NULL); + pool->add(sym->name(), false, NULL); ++index; off += sym_size; } @@ -1411,6 +1599,27 @@ Symbol_table::sized_write_globals(const Target* target, { Sized_symbol* sym = static_cast*>(p->second); + // Optionally check for unresolved symbols in shared libraries. + // This is controlled by the --allow-shlib-undefined option. We + // only warn about libraries for which we have seen all the + // DT_NEEDED entries. We don't try to track down DT_NEEDED + // entries which were not seen in this link. If we didn't see a + // DT_NEEDED entry, we aren't going to be able to reliably + // report whether the symbol is undefined. + if (sym->source() == Symbol::FROM_OBJECT + && sym->object()->is_dynamic() + && sym->shndx() == elfcpp::SHN_UNDEF + && sym->binding() != elfcpp::STB_WEAK + && !parameters->allow_shlib_undefined() + && !target->is_always_defined(sym)) + { + // A very ugly cast. + Dynobj* dynobj = static_cast(sym->object()); + if (!dynobj->has_unknown_needed_entries()) + gold_error(_("%s: undefined reference to '%s'"), + sym->object()->name().c_str(), sym->name()); + } + unsigned int sym_index = sym->symtab_index(); unsigned int dynsym_index; if (dynamic_view == NULL) @@ -1448,28 +1657,31 @@ Symbol_table::sized_write_globals(const Target* target, if (in_shndx >= elfcpp::SHN_LORESERVE && in_shndx != elfcpp::SHN_ABS) { - fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"), - program_name, sym->name(), in_shndx); - gold_exit(false); + gold_error(_("%s: unsupported symbol section 0x%x"), + sym->name(), in_shndx); + shndx = in_shndx; } - - Object* symobj = sym->object(); - if (symobj->is_dynamic()) - { - if (sym->needs_dynsym_value()) - value = target->dynsym_value(sym); - shndx = elfcpp::SHN_UNDEF; - } - else if (in_shndx == elfcpp::SHN_UNDEF - || in_shndx == elfcpp::SHN_ABS) - shndx = in_shndx; else { - Relobj* relobj = static_cast(symobj); - off_t secoff; - Output_section* os = relobj->output_section(in_shndx, &secoff); - gold_assert(os != NULL); - shndx = os->out_shndx(); + Object* symobj = sym->object(); + if (symobj->is_dynamic()) + { + if (sym->needs_dynsym_value()) + value = target->dynsym_value(sym); + shndx = elfcpp::SHN_UNDEF; + } + else if (in_shndx == elfcpp::SHN_UNDEF + || in_shndx == elfcpp::SHN_ABS) + shndx = in_shndx; + else + { + Relobj* relobj = static_cast(symobj); + off_t secoff; + Output_section* os = relobj->output_section(in_shndx, + &secoff); + gold_assert(os != NULL); + shndx = os->out_shndx(); + } } } break; @@ -1611,6 +1823,49 @@ Symbol_table::sized_write_section_symbol(const Output_section* os, of->write_output_view(offset, sym_size, pov); } +// Check candidate_odr_violations_ to find symbols with the same name +// but apparently different definitions (different source-file/line-no). + +void +Symbol_table::detect_odr_violations() const +{ + for (Odr_map::const_iterator it = candidate_odr_violations_.begin(); + it != candidate_odr_violations_.end(); + ++it) + { + const char* symbol_name = it->first; + // We use a sorted set so the output is deterministic. + std::set line_nums; + + Unordered_set::const_iterator + locs; + for (locs = it->second.begin(); locs != it->second.end(); ++locs) + { + // We need to lock the object in order to read it. This + // means that we can not run inside a Task. If we want to + // run this in a Task for better performance, we will need + // one Task for object, plus appropriate locking to ensure + // that we don't conflict with other uses of the object. + locs->object->lock(); + std::string lineno = Dwarf_line_info::one_addr2line( + locs->object, locs->shndx, locs->offset); + locs->object->unlock(); + if (!lineno.empty()) + line_nums.insert(lineno); + } + + if (line_nums.size() > 1) + { + gold_warning(_("symbol %s defined in multiple places " + "(possible ODR violation):"), symbol_name); + for (std::set::const_iterator it2 = line_nums.begin(); + it2 != line_nums.end(); + ++it2) + fprintf(stderr, " %s\n", it2->c_str()); + } + } +} + // Warnings functions. // Add a new warning. @@ -1662,14 +1917,17 @@ Warnings::note_warnings(Symbol_table* symtab) // Issue a warning. This is called when we see a relocation against a // symbol for which has a warning. +template void -Warnings::issue_warning(const Symbol* sym, const std::string& location) const +Warnings::issue_warning(const Symbol* sym, + const Relocate_info* relinfo, + size_t relnum, off_t reloffset) const { gold_assert(sym->has_warning()); Warning_table::const_iterator p = this->warnings_.find(sym->name()); gold_assert(p != this->warnings_.end()); - fprintf(stderr, _("%s: %s: warning: %s\n"), program_name, location.c_str(), - p->second.text.c_str()); + gold_warning_at_location(relinfo, relnum, reloffset, + "%s", p->second.text.c_str()); } // Instantiate the templates we need. We could use the configure @@ -1685,7 +1943,7 @@ Symbol_table::add_from_relobj<32, false>( size_t count, const char* sym_names, size_t sym_name_size, - Symbol** sympointers); + Sized_relobj<32, true>::Symbols* sympointers); #endif #ifdef HAVE_TARGET_32_BIG @@ -1697,7 +1955,7 @@ Symbol_table::add_from_relobj<32, true>( size_t count, const char* sym_names, size_t sym_name_size, - Symbol** sympointers); + Sized_relobj<32, false>::Symbols* sympointers); #endif #ifdef HAVE_TARGET_64_LITTLE @@ -1709,7 +1967,7 @@ Symbol_table::add_from_relobj<64, false>( size_t count, const char* sym_names, size_t sym_name_size, - Symbol** sympointers); + Sized_relobj<64, true>::Symbols* sympointers); #endif #ifdef HAVE_TARGET_64_BIG @@ -1721,7 +1979,7 @@ Symbol_table::add_from_relobj<64, true>( size_t count, const char* sym_names, size_t sym_name_size, - Symbol** sympointers); + Sized_relobj<64, false>::Symbols* sympointers); #endif #ifdef HAVE_TARGET_32_LITTLE @@ -1780,4 +2038,52 @@ Symbol_table::add_from_dynobj<64, true>( const std::vector* version_map); #endif +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) +template +void +Symbol_table::define_with_copy_reloc<32>(const Target* target, + Sized_symbol<32>* sym, + Output_data* posd, uint64_t value); +#endif + +#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) +template +void +Symbol_table::define_with_copy_reloc<64>(const Target* target, + Sized_symbol<64>* sym, + Output_data* posd, uint64_t value); +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template +void +Warnings::issue_warning<32, false>(const Symbol* sym, + const Relocate_info<32, false>* relinfo, + size_t relnum, off_t reloffset) const; +#endif + +#ifdef HAVE_TARGET_32_BIG +template +void +Warnings::issue_warning<32, true>(const Symbol* sym, + const Relocate_info<32, true>* relinfo, + size_t relnum, off_t reloffset) const; +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +void +Warnings::issue_warning<64, false>(const Symbol* sym, + const Relocate_info<64, false>* relinfo, + size_t relnum, off_t reloffset) const; +#endif + +#ifdef HAVE_TARGET_64_BIG +template +void +Warnings::issue_warning<64, true>(const Symbol* sym, + const Relocate_info<64, true>* relinfo, + size_t relnum, off_t reloffset) const; +#endif + } // End namespace gold.