diff options
author | Ian Lance Taylor <ian@airs.com> | 2008-08-04 22:22:13 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2008-08-04 22:22:13 +0000 |
commit | 42a95d053219d627d2d7e137f33736502d4991e6 (patch) | |
tree | d08e02d7f2203afd4fcd0eb228a9441a9828f1e6 | |
parent | 09d11ab54f6f3f29e29e172c38ce2c9fb542d9b2 (diff) | |
download | gdb-42a95d053219d627d2d7e137f33736502d4991e6.tar.gz |
* symtab.h (Symbol::use_plt_offset): New function.
* i386.cc (Relocate::relocate): Call Symbol::use_plt_offset.
* powerpc.cc (Relocate::relocate): Likewise.
* sparc.cc (Relocate::relocate): Likewise.
* x86_64.cc (Relocate::relocate): Likewise.
* testsuite/weak_plt.sh: New test.
* testsuite/weak_plt_main.cc: New test.
* testsuite/weak_plt_shared.cc: New test.
* testsuite/Makefile.am (check_SCRIPTS): Add weak_plt.sh.
(check_PROGRAMS): Add weak_plt.
(check_DATA): Add weak_plt_shared.so.
(weak_plt_main_pic.o, weak_plt): New targets.
(weak_plt_shared_pic.o, weak_plt_shared.so): New targets.
* testsuite/Makefile.in: Rebuild.
* testsuite/Makefile.am (weak_alias_test_1.so): Depend upon
gcctestdir/ld.
(weak_alias_test_2.so, weak_alias_test_4.so): Likewise.
* testsuite/Makefile.in: Rebuild.
-rw-r--r-- | gold/ChangeLog | 22 | ||||
-rw-r--r-- | gold/i386.cc | 2610 | ||||
-rw-r--r-- | gold/powerpc.cc | 1973 | ||||
-rw-r--r-- | gold/sparc.cc | 3200 | ||||
-rw-r--r-- | gold/symtab.h | 1603 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 893 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 2300 | ||||
-rwxr-xr-x | gold/testsuite/weak_plt.sh | 28 | ||||
-rw-r--r-- | gold/testsuite/weak_plt_main.cc | 33 | ||||
-rw-r--r-- | gold/testsuite/weak_plt_shared.cc | 29 | ||||
-rw-r--r-- | gold/x86_64.cc | 2608 |
11 files changed, 15299 insertions, 0 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 858845d7dea..9b491a2f35e 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,25 @@ +2008-08-04 Ian Lance Taylor <iant@google.com> + + * symtab.h (Symbol::use_plt_offset): New function. + * i386.cc (Relocate::relocate): Call Symbol::use_plt_offset. + * powerpc.cc (Relocate::relocate): Likewise. + * sparc.cc (Relocate::relocate): Likewise. + * x86_64.cc (Relocate::relocate): Likewise. + * testsuite/weak_plt.sh: New test. + * testsuite/weak_plt_main.cc: New test. + * testsuite/weak_plt_shared.cc: New test. + * testsuite/Makefile.am (check_SCRIPTS): Add weak_plt.sh. + (check_PROGRAMS): Add weak_plt. + (check_DATA): Add weak_plt_shared.so. + (weak_plt_main_pic.o, weak_plt): New targets. + (weak_plt_shared_pic.o, weak_plt_shared.so): New targets. + * testsuite/Makefile.in: Rebuild. + + * testsuite/Makefile.am (weak_alias_test_1.so): Depend upon + gcctestdir/ld. + (weak_alias_test_2.so, weak_alias_test_4.so): Likewise. + * testsuite/Makefile.in: Rebuild. + 2008-08-04 Alan Modra <amodra@bigpond.net.au> * Makefile.am (POTFILES.in): Set LC_ALL=C. diff --git a/gold/i386.cc b/gold/i386.cc new file mode 100644 index 00000000000..54f123333b7 --- /dev/null +++ b/gold/i386.cc @@ -0,0 +1,2610 @@ +// i386.cc -- i386 target support for gold. + +// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstring> + +#include "elfcpp.h" +#include "parameters.h" +#include "reloc.h" +#include "i386.h" +#include "object.h" +#include "symtab.h" +#include "layout.h" +#include "output.h" +#include "copy-relocs.h" +#include "target.h" +#include "target-reloc.h" +#include "target-select.h" +#include "tls.h" + +namespace +{ + +using namespace gold; + +class Output_data_plt_i386; + +// The i386 target class. +// TLS info comes from +// http://people.redhat.com/drepper/tls.pdf +// http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt + +class Target_i386 : public Sized_target<32, false> +{ + public: + typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section; + + Target_i386() + : Sized_target<32, false>(&i386_info), + got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL), + copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL), + got_mod_index_offset_(-1U), tls_base_symbol_defined_(false) + { } + + // Scan the relocations to look for symbol adjustments. + void + scan_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + + // Finalize the sections. + void + do_finalize_sections(Layout*); + + // Return the value to use for a dynamic which requires special + // treatment. + uint64_t + do_dynsym_value(const Symbol*) const; + + // Relocate a section. + void + relocate_section(const Relocate_info<32, false>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr view_address, + section_size_type view_size); + + // Scan the relocs during a relocatable link. + void + scan_relocatable_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs*); + + // Relocate a section during a relocatable link. + void + relocate_for_relocatable(const Relocate_info<32, false>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); + + // Return a string used to fill a code section with nops. + std::string + do_code_fill(section_size_type length) const; + + // Return whether SYM is defined by the ABI. + bool + do_is_defined_by_abi(Symbol* sym) const + { return strcmp(sym->name(), "___tls_get_addr") == 0; } + + // Return the size of the GOT section. + section_size_type + got_size() + { + gold_assert(this->got_ != NULL); + return this->got_->data_size(); + } + + private: + // The class which scans relocations. + struct Scan + { + inline void + local(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_i386* target, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, false>& reloc, unsigned int r_type, + const elfcpp::Sym<32, false>& lsym); + + inline void + global(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_i386* target, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, false>& reloc, unsigned int r_type, + Symbol* gsym); + + static void + unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type); + + static void + unsupported_reloc_global(Sized_relobj<32, false>*, unsigned int r_type, + Symbol*); + }; + + // The class which implements relocation. + class Relocate + { + public: + Relocate() + : skip_call_tls_get_addr_(false), + local_dynamic_type_(LOCAL_DYNAMIC_NONE) + { } + + ~Relocate() + { + if (this->skip_call_tls_get_addr_) + { + // FIXME: This needs to specify the location somehow. + gold_error(_("missing expected TLS relocation")); + } + } + + // Return whether the static relocation needs to be applied. + inline bool + should_apply_static_reloc(const Sized_symbol<32>* gsym, + int ref_flags, + bool is_32bit); + + // Do a relocation. Return false if the caller should not issue + // any warnings about this relocation. + inline bool + relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum, + const elfcpp::Rel<32, false>&, + unsigned int r_type, const Sized_symbol<32>*, + const Symbol_value<32>*, + unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, + section_size_type); + + private: + // Do a TLS relocation. + inline void + relocate_tls(const Relocate_info<32, false>*, Target_i386* target, + size_t relnum, const elfcpp::Rel<32, false>&, + unsigned int r_type, const Sized_symbol<32>*, + const Symbol_value<32>*, + unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, + section_size_type); + + // Do a TLS General-Dynamic to Initial-Exec transition. + inline void + tls_gd_to_ie(const Relocate_info<32, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>&, unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS General-Dynamic to Local-Exec transition. + inline void + tls_gd_to_le(const Relocate_info<32, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>&, unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS_GOTDESC or TLS_DESC_CALL General-Dynamic to Initial-Exec + // transition. + inline void + tls_desc_gd_to_ie(const Relocate_info<32, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>&, unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS_GOTDESC or TLS_DESC_CALL General-Dynamic to Local-Exec + // transition. + inline void + tls_desc_gd_to_le(const Relocate_info<32, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>&, unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS Local-Dynamic to Local-Exec transition. + inline void + tls_ld_to_le(const Relocate_info<32, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>&, unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS Initial-Exec to Local-Exec transition. + static inline void + tls_ie_to_le(const Relocate_info<32, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>&, unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // We need to keep track of which type of local dynamic relocation + // we have seen, so that we can optimize R_386_TLS_LDO_32 correctly. + enum Local_dynamic_type + { + LOCAL_DYNAMIC_NONE, + LOCAL_DYNAMIC_SUN, + LOCAL_DYNAMIC_GNU + }; + + // This is set if we should skip the next reloc, which should be a + // PLT32 reloc against ___tls_get_addr. + bool skip_call_tls_get_addr_; + // The type of local dynamic relocation we have seen in the section + // being relocated, if any. + Local_dynamic_type local_dynamic_type_; + }; + + // A class which returns the size required for a relocation type, + // used while scanning relocs during a relocatable link. + class Relocatable_size_for_reloc + { + public: + unsigned int + get_size_for_reloc(unsigned int, Relobj*); + }; + + // Adjust TLS relocation type based on the options and whether this + // is a local symbol. + static tls::Tls_optimization + optimize_tls_reloc(bool is_final, int r_type); + + // Get the GOT section, creating it if necessary. + Output_data_got<32, false>* + got_section(Symbol_table*, Layout*); + + // Get the GOT PLT section. + Output_data_space* + got_plt_section() const + { + gold_assert(this->got_plt_ != NULL); + return this->got_plt_; + } + + // Create a PLT entry for a global symbol. + void + make_plt_entry(Symbol_table*, Layout*, Symbol*); + + // Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. + void + define_tls_base_symbol(Symbol_table*, Layout*); + + // Create a GOT entry for the TLS module index. + unsigned int + got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<32, false>* object); + + // Get the PLT section. + const Output_data_plt_i386* + plt_section() const + { + gold_assert(this->plt_ != NULL); + return this->plt_; + } + + // Get the dynamic reloc section, creating it if necessary. + Reloc_section* + rel_dyn_section(Layout*); + + // Return true if the symbol may need a COPY relocation. + // References from an executable object to non-function symbols + // defined in a dynamic object may need a COPY relocation. + bool + may_need_copy_reloc(Symbol* gsym) + { + return (!parameters->options().shared() + && gsym->is_from_dynobj() + && gsym->type() != elfcpp::STT_FUNC); + } + + // Add a potential copy relocation. + void + copy_reloc(Symbol_table* symtab, Layout* layout, + Sized_relobj<32, false>* object, + unsigned int shndx, Output_section* output_section, + Symbol* sym, const elfcpp::Rel<32, false>& reloc) + { + this->copy_relocs_.copy_reloc(symtab, layout, + symtab->get_sized_symbol<32>(sym), + object, shndx, output_section, reloc, + this->rel_dyn_section(layout)); + } + + // Information about this specific target which we pass to the + // general Target structure. + static const Target::Target_info i386_info; + + // The types of GOT entries needed for this platform. + enum Got_type + { + GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol + GOT_TYPE_TLS_NOFFSET = 1, // GOT entry for negative TLS offset + GOT_TYPE_TLS_OFFSET = 2, // GOT entry for positive TLS offset + GOT_TYPE_TLS_PAIR = 3, // GOT entry for TLS module/offset pair + GOT_TYPE_TLS_DESC = 4 // GOT entry for TLS_DESC pair + }; + + // The GOT section. + Output_data_got<32, false>* got_; + // The PLT section. + Output_data_plt_i386* plt_; + // The GOT PLT section. + Output_data_space* got_plt_; + // The dynamic reloc section. + Reloc_section* rel_dyn_; + // Relocs saved to avoid a COPY reloc. + Copy_relocs<elfcpp::SHT_REL, 32, false> copy_relocs_; + // Space for variables copied with a COPY reloc. + Output_data_space* dynbss_; + // Offset of the GOT entry for the TLS module index. + unsigned int got_mod_index_offset_; + // True if the _TLS_MODULE_BASE_ symbol has been defined. + bool tls_base_symbol_defined_; +}; + +const Target::Target_info Target_i386::i386_info = +{ + 32, // size + false, // is_big_endian + elfcpp::EM_386, // machine_code + false, // has_make_symbol + false, // has_resolve + true, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/libc.so.1", // dynamic_linker + 0x08048000, // default_text_segment_address + 0x1000, // abi_pagesize (overridable by -z max-page-size) + 0x1000 // common_pagesize (overridable by -z common-page-size) +}; + +// Get the GOT section, creating it if necessary. + +Output_data_got<32, false>* +Target_i386::got_section(Symbol_table* symtab, Layout* layout) +{ + if (this->got_ == NULL) + { + gold_assert(symtab != NULL && layout != NULL); + + this->got_ = new Output_data_got<32, false>(); + + Output_section* os; + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_); + os->set_is_relro(); + + // The old GNU linker creates a .got.plt section. We just + // create another set of data in the .got section. Note that we + // always create a PLT if we create a GOT, although the PLT + // might be empty. + this->got_plt_ = new Output_data_space(4, "** GOT PLT"); + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_plt_); + os->set_is_relro(); + + // The first three entries are reserved. + this->got_plt_->set_current_data_size(3 * 4); + + // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + this->got_plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + return this->got_; +} + +// Get the dynamic reloc section, creating it if necessary. + +Target_i386::Reloc_section* +Target_i386::rel_dyn_section(Layout* layout) +{ + if (this->rel_dyn_ == NULL) + { + gold_assert(layout != NULL); + this->rel_dyn_ = new Reloc_section(parameters->options().combreloc()); + layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL, + elfcpp::SHF_ALLOC, this->rel_dyn_); + } + return this->rel_dyn_; +} + +// A class to handle the PLT data. + +class Output_data_plt_i386 : public Output_section_data +{ + public: + typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section; + + Output_data_plt_i386(Layout*, Output_data_space*); + + // Add an entry to the PLT. + void + add_entry(Symbol* gsym); + + // Return the .rel.plt section data. + const Reloc_section* + rel_plt() const + { return this->rel_; } + + protected: + void + do_adjust_output_section(Output_section* os); + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, _("** PLT")); } + + private: + // The size of an entry in the PLT. + static const int plt_entry_size = 16; + + // The first entry in the PLT for an executable. + static unsigned char exec_first_plt_entry[plt_entry_size]; + + // The first entry in the PLT for a shared object. + static unsigned char dyn_first_plt_entry[plt_entry_size]; + + // Other entries in the PLT for an executable. + static unsigned char exec_plt_entry[plt_entry_size]; + + // Other entries in the PLT for a shared object. + static unsigned char dyn_plt_entry[plt_entry_size]; + + // Set the final size. + void + set_final_data_size() + { this->set_data_size((this->count_ + 1) * plt_entry_size); } + + // Write out the PLT data. + void + do_write(Output_file*); + + // The reloc section. + Reloc_section* rel_; + // The .got.plt section. + Output_data_space* got_plt_; + // The number of PLT entries. + unsigned int count_; +}; + +// Create the PLT section. The ordinary .got section is an argument, +// since we need to refer to the start. We also create our own .got +// section just for PLT entries. + +Output_data_plt_i386::Output_data_plt_i386(Layout* layout, + Output_data_space* got_plt) + : Output_section_data(4), got_plt_(got_plt), count_(0) +{ + this->rel_ = new Reloc_section(false); + layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, + elfcpp::SHF_ALLOC, this->rel_); +} + +void +Output_data_plt_i386::do_adjust_output_section(Output_section* os) +{ + // UnixWare sets the entsize of .plt to 4, and so does the old GNU + // linker, and so do we. + os->set_entsize(4); +} + +// Add an entry to the PLT. + +void +Output_data_plt_i386::add_entry(Symbol* gsym) +{ + gold_assert(!gsym->has_plt_offset()); + + // Note that when setting the PLT offset we skip the initial + // reserved PLT entry. + gsym->set_plt_offset((this->count_ + 1) * plt_entry_size); + + ++this->count_; + + section_offset_type got_offset = this->got_plt_->current_data_size(); + + // Every PLT entry needs a GOT entry which points back to the PLT + // entry (this will be changed by the dynamic linker, normally + // lazily when the function is called). + this->got_plt_->set_current_data_size(got_offset + 4); + + // Every PLT entry needs a reloc. + gsym->set_needs_dynsym_entry(); + this->rel_->add_global(gsym, elfcpp::R_386_JUMP_SLOT, this->got_plt_, + got_offset); + + // Note that we don't need to save the symbol. The contents of the + // PLT are independent of which symbols are used. The symbols only + // appear in the relocations. +} + +// The first entry in the PLT for an executable. + +unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] = +{ + 0xff, 0x35, // pushl contents of memory address + 0, 0, 0, 0, // replaced with address of .got + 4 + 0xff, 0x25, // jmp indirect + 0, 0, 0, 0, // replaced with address of .got + 8 + 0, 0, 0, 0 // unused +}; + +// The first entry in the PLT for a shared object. + +unsigned char Output_data_plt_i386::dyn_first_plt_entry[plt_entry_size] = +{ + 0xff, 0xb3, 4, 0, 0, 0, // pushl 4(%ebx) + 0xff, 0xa3, 8, 0, 0, 0, // jmp *8(%ebx) + 0, 0, 0, 0 // unused +}; + +// Subsequent entries in the PLT for an executable. + +unsigned char Output_data_plt_i386::exec_plt_entry[plt_entry_size] = +{ + 0xff, 0x25, // jmp indirect + 0, 0, 0, 0, // replaced with address of symbol in .got + 0x68, // pushl immediate + 0, 0, 0, 0, // replaced with offset into relocation table + 0xe9, // jmp relative + 0, 0, 0, 0 // replaced with offset to start of .plt +}; + +// Subsequent entries in the PLT for a shared object. + +unsigned char Output_data_plt_i386::dyn_plt_entry[plt_entry_size] = +{ + 0xff, 0xa3, // jmp *offset(%ebx) + 0, 0, 0, 0, // replaced with offset of symbol in .got + 0x68, // pushl immediate + 0, 0, 0, 0, // replaced with offset into relocation table + 0xe9, // jmp relative + 0, 0, 0, 0 // replaced with offset to start of .plt +}; + +// Write out the PLT. This uses the hand-coded instructions above, +// and adjusts them as needed. This is all specified by the i386 ELF +// Processor Supplement. + +void +Output_data_plt_i386::do_write(Output_file* of) +{ + const off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + const off_t got_file_offset = this->got_plt_->offset(); + const section_size_type got_size = + convert_to_section_size_type(this->got_plt_->data_size()); + unsigned char* const got_view = of->get_output_view(got_file_offset, + got_size); + + unsigned char* pov = oview; + + elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address(); + elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address(); + + if (parameters->options().shared()) + memcpy(pov, dyn_first_plt_entry, plt_entry_size); + else + { + memcpy(pov, exec_first_plt_entry, plt_entry_size); + elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4); + elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8); + } + pov += plt_entry_size; + + unsigned char* got_pov = got_view; + + memset(got_pov, 0, 12); + got_pov += 12; + + const int rel_size = elfcpp::Elf_sizes<32>::rel_size; + + unsigned int plt_offset = plt_entry_size; + unsigned int plt_rel_offset = 0; + unsigned int got_offset = 12; + const unsigned int count = this->count_; + for (unsigned int i = 0; + i < count; + ++i, + pov += plt_entry_size, + got_pov += 4, + plt_offset += plt_entry_size, + plt_rel_offset += rel_size, + got_offset += 4) + { + // Set and adjust the PLT entry itself. + + if (parameters->options().shared()) + { + memcpy(pov, dyn_plt_entry, plt_entry_size); + elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset); + } + else + { + memcpy(pov, exec_plt_entry, plt_entry_size); + elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, + (got_address + + got_offset)); + } + + elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset); + elfcpp::Swap<32, false>::writeval(pov + 12, + - (plt_offset + plt_entry_size)); + + // Set the entry in the GOT. + elfcpp::Swap<32, false>::writeval(got_pov, plt_address + plt_offset + 6); + } + + gold_assert(static_cast<section_size_type>(pov - oview) == oview_size); + gold_assert(static_cast<section_size_type>(got_pov - got_view) == got_size); + + of->write_output_view(offset, oview_size, oview); + of->write_output_view(got_file_offset, got_size, got_view); +} + +// Create a PLT entry for a global symbol. + +void +Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym) +{ + if (gsym->has_plt_offset()) + return; + + if (this->plt_ == NULL) + { + // Create the GOT sections first. + this->got_section(symtab, layout); + + this->plt_ = new Output_data_plt_i386(layout, this->got_plt_); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR), + this->plt_); + } + + this->plt_->add_entry(gsym); +} + +// Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. + +void +Target_i386::define_tls_base_symbol(Symbol_table* symtab, Layout* layout) +{ + if (this->tls_base_symbol_defined_) + return; + + Output_segment* tls_segment = layout->tls_segment(); + if (tls_segment != NULL) + { + symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL, + tls_segment, 0, 0, + elfcpp::STT_TLS, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + Symbol::SEGMENT_END, true); + } + this->tls_base_symbol_defined_ = true; +} + +// Create a GOT entry for the TLS module index. + +unsigned int +Target_i386::got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<32, false>* object) +{ + if (this->got_mod_index_offset_ == -1U) + { + gold_assert(symtab != NULL && layout != NULL && object != NULL); + Reloc_section* rel_dyn = this->rel_dyn_section(layout); + Output_data_got<32, false>* got = this->got_section(symtab, layout); + unsigned int got_offset = got->add_constant(0); + rel_dyn->add_local(object, 0, elfcpp::R_386_TLS_DTPMOD32, got, + got_offset); + got->add_constant(0); + this->got_mod_index_offset_ = got_offset; + } + return this->got_mod_index_offset_; +} + +// Optimize the TLS relocation type based on what we know about the +// symbol. IS_FINAL is true if the final address of this symbol is +// known at link time. + +tls::Tls_optimization +Target_i386::optimize_tls_reloc(bool is_final, int r_type) +{ + // If we are generating a shared library, then we can't do anything + // in the linker. + if (parameters->options().shared()) + return tls::TLSOPT_NONE; + + switch (r_type) + { + case elfcpp::R_386_TLS_GD: + case elfcpp::R_386_TLS_GOTDESC: + case elfcpp::R_386_TLS_DESC_CALL: + // These are General-Dynamic which permits fully general TLS + // access. Since we know that we are generating an executable, + // we can convert this to Initial-Exec. If we also know that + // this is a local symbol, we can further switch to Local-Exec. + if (is_final) + return tls::TLSOPT_TO_LE; + return tls::TLSOPT_TO_IE; + + case elfcpp::R_386_TLS_LDM: + // This is Local-Dynamic, which refers to a local symbol in the + // dynamic TLS block. Since we know that we generating an + // executable, we can switch to Local-Exec. + return tls::TLSOPT_TO_LE; + + case elfcpp::R_386_TLS_LDO_32: + // Another type of Local-Dynamic relocation. + return tls::TLSOPT_TO_LE; + + case elfcpp::R_386_TLS_IE: + case elfcpp::R_386_TLS_GOTIE: + case elfcpp::R_386_TLS_IE_32: + // These are Initial-Exec relocs which get the thread offset + // from the GOT. If we know that we are linking against the + // local symbol, we can switch to Local-Exec, which links the + // thread offset into the instruction. + if (is_final) + return tls::TLSOPT_TO_LE; + return tls::TLSOPT_NONE; + + case elfcpp::R_386_TLS_LE: + case elfcpp::R_386_TLS_LE_32: + // When we already have Local-Exec, there is nothing further we + // can do. + return tls::TLSOPT_NONE; + + default: + gold_unreachable(); + } +} + +// Report an unsupported relocation against a local symbol. + +void +Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object, + unsigned int r_type) +{ + gold_error(_("%s: unsupported reloc %u against local symbol"), + object->name().c_str(), r_type); +} + +// Scan a relocation for a local symbol. + +inline void +Target_i386::Scan::local(const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_i386* target, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, false>& reloc, + unsigned int r_type, + const elfcpp::Sym<32, false>& lsym) +{ + switch (r_type) + { + case elfcpp::R_386_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + break; + + case elfcpp::R_386_32: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. The relocation applied at link time will + // apply the link-time value, so we flag the location with + // an R_386_RELATIVE relocation so the dynamic loader can + // relocate it easily. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + rel_dyn->add_local_relative(object, r_sym, elfcpp::R_386_RELATIVE, + output_section, data_shndx, + reloc.get_r_offset()); + } + break; + + case elfcpp::R_386_16: + case elfcpp::R_386_8: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. Because the addend needs to remain in the + // data section, we need to be careful not to apply this + // relocation statically. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + if (lsym.get_st_type() != elfcpp::STT_SECTION) + rel_dyn->add_local(object, r_sym, r_type, output_section, + data_shndx, reloc.get_r_offset()); + else + { + gold_assert(lsym.get_st_value() == 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, + &is_ordinary); + if (!is_ordinary) + object->error(_("section symbol %u has bad shndx %u"), + r_sym, shndx); + else + rel_dyn->add_local_section(object, shndx, + r_type, output_section, + data_shndx, reloc.get_r_offset()); + } + } + break; + + case elfcpp::R_386_PC32: + case elfcpp::R_386_PC16: + case elfcpp::R_386_PC8: + break; + + case elfcpp::R_386_PLT32: + // Since we know this is a local symbol, we can handle this as a + // PC32 reloc. + break; + + case elfcpp::R_386_GOTOFF: + case elfcpp::R_386_GOTPC: + // We need a GOT section. + target->got_section(symtab, layout); + break; + + case elfcpp::R_386_GOT32: + { + // The symbol requires a GOT entry. + Output_data_got<32, false>* got = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + if (got->add_local(object, r_sym, GOT_TYPE_STANDARD)) + { + // If we are generating a shared object, we need to add a + // dynamic RELATIVE relocation for this symbol's GOT entry. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + rel_dyn->add_local_relative( + object, r_sym, elfcpp::R_386_RELATIVE, got, + object->local_got_offset(r_sym, GOT_TYPE_STANDARD)); + } + } + } + break; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_386_COPY: + case elfcpp::R_386_GLOB_DAT: + case elfcpp::R_386_JUMP_SLOT: + case elfcpp::R_386_RELATIVE: + case elfcpp::R_386_TLS_TPOFF: + case elfcpp::R_386_TLS_DTPMOD32: + case elfcpp::R_386_TLS_DTPOFF32: + case elfcpp::R_386_TLS_TPOFF32: + case elfcpp::R_386_TLS_DESC: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + // These are initial TLS relocs, which are expected when + // linking. + case elfcpp::R_386_TLS_GD: // Global-dynamic + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_386_TLS_DESC_CALL: + case elfcpp::R_386_TLS_LDM: // Local-dynamic + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_IE_32: + case elfcpp::R_386_TLS_GOTIE: + case elfcpp::R_386_TLS_LE: // Local-exec + case elfcpp::R_386_TLS_LE_32: + { + bool output_is_shared = parameters->options().shared(); + const tls::Tls_optimization optimized_type + = Target_i386::optimize_tls_reloc(!output_is_shared, r_type); + switch (r_type) + { + case elfcpp::R_386_TLS_GD: // Global-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rel(object, r_sym, shndx, + GOT_TYPE_TLS_PAIR, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_DTPMOD32, 0); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva) + target->define_tls_base_symbol(symtab, layout); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a double GOT entry with an R_386_TLS_DESC reloc. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rel(object, r_sym, shndx, + GOT_TYPE_TLS_DESC, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_DESC, 0); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_386_TLS_DESC_CALL: + break; + + case elfcpp::R_386_TLS_LDM: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + break; + + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_IE_32: + case elfcpp::R_386_TLS_GOTIE: + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // For the R_386_TLS_IE relocation, we need to create a + // dynamic relocation when building a shared library. + if (r_type == elfcpp::R_386_TLS_IE + && parameters->options().shared()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym + = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + rel_dyn->add_local_relative(object, r_sym, + elfcpp::R_386_RELATIVE, + output_section, data_shndx, + reloc.get_r_offset()); + } + // Create a GOT entry for the tp-relative offset. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32 + ? elfcpp::R_386_TLS_TPOFF32 + : elfcpp::R_386_TLS_TPOFF); + unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32 + ? GOT_TYPE_TLS_OFFSET + : GOT_TYPE_TLS_NOFFSET); + got->add_local_with_rel(object, r_sym, got_type, + target->rel_dyn_section(layout), + dyn_r_type); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_386_TLS_LE: // Local-exec + case elfcpp::R_386_TLS_LE_32: + layout->set_has_static_tls(); + if (output_is_shared) + { + // We need to create a dynamic relocation. + gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32 + ? elfcpp::R_386_TLS_TPOFF32 + : elfcpp::R_386_TLS_TPOFF); + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_local(object, r_sym, dyn_r_type, output_section, + data_shndx, reloc.get_r_offset()); + } + break; + + default: + gold_unreachable(); + } + } + break; + + case elfcpp::R_386_32PLT: + case elfcpp::R_386_TLS_GD_32: + case elfcpp::R_386_TLS_GD_PUSH: + case elfcpp::R_386_TLS_GD_CALL: + case elfcpp::R_386_TLS_GD_POP: + case elfcpp::R_386_TLS_LDM_32: + case elfcpp::R_386_TLS_LDM_PUSH: + case elfcpp::R_386_TLS_LDM_CALL: + case elfcpp::R_386_TLS_LDM_POP: + case elfcpp::R_386_USED_BY_INTEL_200: + default: + unsupported_reloc_local(object, r_type); + break; + } +} + +// Report an unsupported relocation against a global symbol. + +void +Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object, + unsigned int r_type, + Symbol* gsym) +{ + gold_error(_("%s: unsupported reloc %u against global symbol %s"), + object->name().c_str(), r_type, gsym->demangled_name().c_str()); +} + +// Scan a relocation for a global symbol. + +inline void +Target_i386::Scan::global(const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_i386* target, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, false>& reloc, + unsigned int r_type, + Symbol* gsym) +{ + switch (r_type) + { + case elfcpp::R_386_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + break; + + case elfcpp::R_386_32: + case elfcpp::R_386_16: + case elfcpp::R_386_8: + { + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + { + target->make_plt_entry(symtab, layout, gsym); + // Since this is not a PC-relative relocation, we may be + // taking the address of a function. In that case we need to + // set the entry in the dynamic symbol table to the address of + // the PLT entry. + if (gsym->is_from_dynobj() && !parameters->options().shared()) + gsym->set_needs_dynsym_value(); + } + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else if (r_type == elfcpp::R_386_32 + && gsym->can_use_relative_reloc(false)) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE, + output_section, object, + data_shndx, reloc.get_r_offset()); + } + else + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset()); + } + } + } + break; + + case elfcpp::R_386_PC32: + case elfcpp::R_386_PC16: + case elfcpp::R_386_PC8: + { + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + { + // These relocations are used for function calls only in + // non-PIC code. For a 32-bit relocation in a shared library, + // we'll need a text relocation anyway, so we can skip the + // PLT entry and let the dynamic linker bind the call directly + // to the target. For smaller relocations, we should use a + // PLT entry to ensure that the call can reach. + if (!parameters->options().shared() + || r_type != elfcpp::R_386_PC32) + target->make_plt_entry(symtab, layout, gsym); + } + // Make a dynamic relocation if necessary. + int flags = Symbol::NON_PIC_REF; + if (gsym->type() == elfcpp::STT_FUNC) + flags |= Symbol::FUNCTION_CALL; + if (gsym->needs_dynamic_reloc(flags)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset()); + } + } + } + break; + + case elfcpp::R_386_GOT32: + { + // The symbol requires a GOT entry. + Output_data_got<32, false>* got = target->got_section(symtab, layout); + if (gsym->final_value_is_known()) + got->add_global(gsym, GOT_TYPE_STANDARD); + else + { + // If this symbol is not fully resolved, we need to add a + // GOT entry with a dynamic relocation. + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, + rel_dyn, elfcpp::R_386_GLOB_DAT); + else + { + if (got->add_global(gsym, GOT_TYPE_STANDARD)) + rel_dyn->add_global_relative( + gsym, elfcpp::R_386_RELATIVE, got, + gsym->got_offset(GOT_TYPE_STANDARD)); + } + } + } + break; + + case elfcpp::R_386_PLT32: + // If the symbol is fully resolved, this is just a PC32 reloc. + // Otherwise we need a PLT entry. + if (gsym->final_value_is_known()) + break; + // If building a shared library, we can also skip the PLT entry + // if the symbol is defined in the output file and is protected + // or hidden. + if (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible()) + break; + target->make_plt_entry(symtab, layout, gsym); + break; + + case elfcpp::R_386_GOTOFF: + case elfcpp::R_386_GOTPC: + // We need a GOT section. + target->got_section(symtab, layout); + break; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_386_COPY: + case elfcpp::R_386_GLOB_DAT: + case elfcpp::R_386_JUMP_SLOT: + case elfcpp::R_386_RELATIVE: + case elfcpp::R_386_TLS_TPOFF: + case elfcpp::R_386_TLS_DTPMOD32: + case elfcpp::R_386_TLS_DTPOFF32: + case elfcpp::R_386_TLS_TPOFF32: + case elfcpp::R_386_TLS_DESC: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + // These are initial tls relocs, which are expected when + // linking. + case elfcpp::R_386_TLS_GD: // Global-dynamic + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_386_TLS_DESC_CALL: + case elfcpp::R_386_TLS_LDM: // Local-dynamic + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_IE_32: + case elfcpp::R_386_TLS_GOTIE: + case elfcpp::R_386_TLS_LE: // Local-exec + case elfcpp::R_386_TLS_LE_32: + { + const bool is_final = gsym->final_value_is_known(); + const tls::Tls_optimization optimized_type + = Target_i386::optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_386_TLS_GD: // Global-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_DTPMOD32, + elfcpp::R_386_TLS_DTPOFF32); + } + else if (optimized_type == tls::TLSOPT_TO_IE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_TPOFF); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (~oliva url) + target->define_tls_base_symbol(symtab, layout); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a double GOT entry with an R_386_TLS_DESC reloc. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_DESC, 0); + } + else if (optimized_type == tls::TLSOPT_TO_IE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET, + target->rel_dyn_section(layout), + elfcpp::R_386_TLS_TPOFF); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_386_TLS_DESC_CALL: + break; + + case elfcpp::R_386_TLS_LDM: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + break; + + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_IE_32: + case elfcpp::R_386_TLS_GOTIE: + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // For the R_386_TLS_IE relocation, we need to create a + // dynamic relocation when building a shared library. + if (r_type == elfcpp::R_386_TLS_IE + && parameters->options().shared()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE, + output_section, object, + data_shndx, + reloc.get_r_offset()); + } + // Create a GOT entry for the tp-relative offset. + Output_data_got<32, false>* got + = target->got_section(symtab, layout); + unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32 + ? elfcpp::R_386_TLS_TPOFF32 + : elfcpp::R_386_TLS_TPOFF); + unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32 + ? GOT_TYPE_TLS_OFFSET + : GOT_TYPE_TLS_NOFFSET); + got->add_global_with_rel(gsym, got_type, + target->rel_dyn_section(layout), + dyn_r_type); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_386_TLS_LE: // Local-exec + case elfcpp::R_386_TLS_LE_32: + layout->set_has_static_tls(); + if (parameters->options().shared()) + { + // We need to create a dynamic relocation. + unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32 + ? elfcpp::R_386_TLS_TPOFF32 + : elfcpp::R_386_TLS_TPOFF); + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global(gsym, dyn_r_type, output_section, object, + data_shndx, reloc.get_r_offset()); + } + break; + + default: + gold_unreachable(); + } + } + break; + + case elfcpp::R_386_32PLT: + case elfcpp::R_386_TLS_GD_32: + case elfcpp::R_386_TLS_GD_PUSH: + case elfcpp::R_386_TLS_GD_CALL: + case elfcpp::R_386_TLS_GD_POP: + case elfcpp::R_386_TLS_LDM_32: + case elfcpp::R_386_TLS_LDM_PUSH: + case elfcpp::R_386_TLS_LDM_CALL: + case elfcpp::R_386_TLS_LDM_POP: + case elfcpp::R_386_USED_BY_INTEL_200: + default: + unsupported_reloc_global(object, r_type, gsym); + break; + } +} + +// Scan relocations for a section. + +void +Target_i386::scan_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + if (sh_type == elfcpp::SHT_RELA) + { + gold_error(_("%s: unsupported RELA reloc section"), + object->name().c_str()); + return; + } + + gold::scan_relocs<32, false, Target_i386, elfcpp::SHT_REL, + Target_i386::Scan>( + options, + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + +// Finalize the sections. + +void +Target_i386::do_finalize_sections(Layout* layout) +{ + // Fill in some more dynamic tags. + Output_data_dynamic* const odyn = layout->dynamic_data(); + if (odyn != NULL) + { + if (this->got_plt_ != NULL) + odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); + + if (this->plt_ != NULL) + { + const Output_data* od = this->plt_->rel_plt(); + odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); + odyn->add_section_address(elfcpp::DT_JMPREL, od); + odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); + } + + if (this->rel_dyn_ != NULL) + { + const Output_data* od = this->rel_dyn_; + odyn->add_section_address(elfcpp::DT_REL, od); + odyn->add_section_size(elfcpp::DT_RELSZ, od); + odyn->add_constant(elfcpp::DT_RELENT, + elfcpp::Elf_sizes<32>::rel_size); + } + + if (!parameters->options().shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } + } + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. + if (this->copy_relocs_.any_saved_relocs()) + this->copy_relocs_.emit(this->rel_dyn_section(layout)); +} + +// Return whether a direct absolute static relocation needs to be applied. +// In cases where Scan::local() or Scan::global() has created +// a dynamic relocation other than R_386_RELATIVE, the addend +// of the relocation is carried in the data, and we must not +// apply the static relocation. + +inline bool +Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym, + int ref_flags, + bool is_32bit) +{ + // For local symbols, we will have created a non-RELATIVE dynamic + // relocation only if (a) the output is position independent, + // (b) the relocation is absolute (not pc- or segment-relative), and + // (c) the relocation is not 32 bits wide. + if (gsym == NULL) + return !(parameters->options().output_is_position_independent() + && (ref_flags & Symbol::ABSOLUTE_REF) + && !is_32bit); + + // For global symbols, we use the same helper routines used in the + // scan pass. If we did not create a dynamic relocation, or if we + // created a RELATIVE dynamic relocation, we should apply the static + // relocation. + bool has_dyn = gsym->needs_dynamic_reloc(ref_flags); + bool is_rel = (ref_flags & Symbol::ABSOLUTE_REF) + && gsym->can_use_relative_reloc(ref_flags + & Symbol::FUNCTION_CALL); + return !has_dyn || is_rel; +} + +// Perform a relocation. + +inline bool +Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, + Target_i386* target, + size_t relnum, + const elfcpp::Rel<32, false>& rel, + unsigned int r_type, + const Sized_symbol<32>* gsym, + const Symbol_value<32>* psymval, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr address, + section_size_type view_size) +{ + if (this->skip_call_tls_get_addr_) + { + if (r_type != elfcpp::R_386_PLT32 + || gsym == NULL + || strcmp(gsym->name(), "___tls_get_addr") != 0) + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("missing expected TLS relocation")); + else + { + this->skip_call_tls_get_addr_ = false; + return false; + } + } + + // Pick the value to use for symbols defined in shared objects. + Symbol_value<32> symval; + if (gsym != NULL + && gsym->use_plt_offset(r_type == elfcpp::R_386_PC8 + || r_type == elfcpp::R_386_PC16 + || r_type == elfcpp::R_386_PC32)) + { + symval.set_output_value(target->plt_section()->address() + + gsym->plt_offset()); + psymval = &symval; + } + + const Sized_relobj<32, false>* object = relinfo->object; + + // Get the GOT offset if needed. + // The GOT pointer points to the end of the GOT section. + // We need to subtract the size of the GOT section to get + // the actual offset to use in the relocation. + bool have_got_offset = false; + unsigned int got_offset = 0; + switch (r_type) + { + case elfcpp::R_386_GOT32: + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = (gsym->got_offset(GOT_TYPE_STANDARD) + - target->got_size()); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); + got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD) + - target->got_size()); + } + have_got_offset = true; + break; + + default: + break; + } + + switch (r_type) + { + case elfcpp::R_386_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + break; + + case elfcpp::R_386_32: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true)) + Relocate_functions<32, false>::rel32(view, object, psymval); + break; + + case elfcpp::R_386_PC32: + { + int ref_flags = Symbol::NON_PIC_REF; + if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC) + ref_flags |= Symbol::FUNCTION_CALL; + if (should_apply_static_reloc(gsym, ref_flags, true)) + Relocate_functions<32, false>::pcrel32(view, object, psymval, address); + } + break; + + case elfcpp::R_386_16: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false)) + Relocate_functions<32, false>::rel16(view, object, psymval); + break; + + case elfcpp::R_386_PC16: + { + int ref_flags = Symbol::NON_PIC_REF; + if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC) + ref_flags |= Symbol::FUNCTION_CALL; + if (should_apply_static_reloc(gsym, ref_flags, false)) + Relocate_functions<32, false>::pcrel16(view, object, psymval, address); + } + break; + + case elfcpp::R_386_8: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false)) + Relocate_functions<32, false>::rel8(view, object, psymval); + break; + + case elfcpp::R_386_PC8: + { + int ref_flags = Symbol::NON_PIC_REF; + if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC) + ref_flags |= Symbol::FUNCTION_CALL; + if (should_apply_static_reloc(gsym, ref_flags, false)) + Relocate_functions<32, false>::pcrel8(view, object, psymval, address); + } + break; + + case elfcpp::R_386_PLT32: + gold_assert(gsym == NULL + || gsym->has_plt_offset() + || gsym->final_value_is_known() + || (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible())); + Relocate_functions<32, false>::pcrel32(view, object, psymval, address); + break; + + case elfcpp::R_386_GOT32: + gold_assert(have_got_offset); + Relocate_functions<32, false>::rel32(view, got_offset); + break; + + case elfcpp::R_386_GOTOFF: + { + elfcpp::Elf_types<32>::Elf_Addr value; + value = (psymval->value(object, 0) + - target->got_plt_section()->address()); + Relocate_functions<32, false>::rel32(view, value); + } + break; + + case elfcpp::R_386_GOTPC: + { + elfcpp::Elf_types<32>::Elf_Addr value; + value = target->got_plt_section()->address(); + Relocate_functions<32, false>::pcrel32(view, value, address); + } + break; + + case elfcpp::R_386_COPY: + case elfcpp::R_386_GLOB_DAT: + case elfcpp::R_386_JUMP_SLOT: + case elfcpp::R_386_RELATIVE: + // These are outstanding tls relocs, which are unexpected when + // linking. + case elfcpp::R_386_TLS_TPOFF: + case elfcpp::R_386_TLS_DTPMOD32: + case elfcpp::R_386_TLS_DTPOFF32: + case elfcpp::R_386_TLS_TPOFF32: + case elfcpp::R_386_TLS_DESC: + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unexpected reloc %u in object file"), + r_type); + break; + + // These are initial tls relocs, which are expected when + // linking. + case elfcpp::R_386_TLS_GD: // Global-dynamic + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_386_TLS_DESC_CALL: + case elfcpp::R_386_TLS_LDM: // Local-dynamic + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_IE_32: + case elfcpp::R_386_TLS_GOTIE: + case elfcpp::R_386_TLS_LE: // Local-exec + case elfcpp::R_386_TLS_LE_32: + this->relocate_tls(relinfo, target, relnum, rel, r_type, gsym, psymval, + view, address, view_size); + break; + + case elfcpp::R_386_32PLT: + case elfcpp::R_386_TLS_GD_32: + case elfcpp::R_386_TLS_GD_PUSH: + case elfcpp::R_386_TLS_GD_CALL: + case elfcpp::R_386_TLS_GD_POP: + case elfcpp::R_386_TLS_LDM_32: + case elfcpp::R_386_TLS_LDM_PUSH: + case elfcpp::R_386_TLS_LDM_CALL: + case elfcpp::R_386_TLS_LDM_POP: + case elfcpp::R_386_USED_BY_INTEL_200: + default: + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + } + + return true; +} + +// Perform a TLS relocation. + +inline void +Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo, + Target_i386* target, + size_t relnum, + const elfcpp::Rel<32, false>& rel, + unsigned int r_type, + const Sized_symbol<32>* gsym, + const Symbol_value<32>* psymval, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr, + section_size_type view_size) +{ + Output_segment* tls_segment = relinfo->layout->tls_segment(); + + const Sized_relobj<32, false>* object = relinfo->object; + + elfcpp::Elf_types<32>::Elf_Addr value = psymval->value(object, 0); + + const bool is_final = + (gsym == NULL + ? !parameters->options().output_is_position_independent() + : gsym->final_value_is_known()); + const tls::Tls_optimization optimized_type + = Target_i386::optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_386_TLS_GD: // Global-dynamic + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + this->tls_gd_to_le(relinfo, relnum, tls_segment, + rel, r_type, value, view, + view_size); + break; + } + else + { + unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE + ? GOT_TYPE_TLS_NOFFSET + : GOT_TYPE_TLS_PAIR); + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type) - target->got_size(); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = (object->local_got_offset(r_sym, got_type) + - target->got_size()); + } + if (optimized_type == tls::TLSOPT_TO_IE) + { + gold_assert(tls_segment != NULL); + this->tls_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type, + got_offset, view, view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the pair of GOT + // entries. + Relocate_functions<32, false>::rel32(view, got_offset); + break; + } + } + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_386_TLS_DESC_CALL: + this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU; + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + this->tls_desc_gd_to_le(relinfo, relnum, tls_segment, + rel, r_type, value, view, + view_size); + break; + } + else + { + unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE + ? GOT_TYPE_TLS_NOFFSET + : GOT_TYPE_TLS_DESC); + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type) - target->got_size(); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = (object->local_got_offset(r_sym, got_type) + - target->got_size()); + } + if (optimized_type == tls::TLSOPT_TO_IE) + { + gold_assert(tls_segment != NULL); + this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type, + got_offset, view, view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + if (r_type == elfcpp::R_386_TLS_GOTDESC) + { + // Relocate the field with the offset of the pair of GOT + // entries. + Relocate_functions<32, false>::rel32(view, got_offset); + } + break; + } + } + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + case elfcpp::R_386_TLS_LDM: // Local-dynamic + if (this->local_dynamic_type_ == LOCAL_DYNAMIC_SUN) + { + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("both SUN and GNU model " + "TLS relocations")); + break; + } + this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU; + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + this->tls_ld_to_le(relinfo, relnum, tls_segment, rel, r_type, + value, view, view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the module index. + unsigned int got_offset; + got_offset = (target->got_mod_index_entry(NULL, NULL, NULL) + - target->got_size()); + Relocate_functions<32, false>::rel32(view, got_offset); + break; + } + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + // This reloc can appear in debugging sections, in which case we + // won't see the TLS_LDM reloc. The local_dynamic_type field + // tells us this. + if (optimized_type == tls::TLSOPT_TO_LE + && this->local_dynamic_type_ != LOCAL_DYNAMIC_NONE) + { + gold_assert(tls_segment != NULL); + value -= tls_segment->memsz(); + } + Relocate_functions<32, false>::rel32(view, value); + break; + + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_GOTIE: + case elfcpp::R_386_TLS_IE_32: + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + Target_i386::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment, + rel, r_type, value, view, + view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the tp-relative offset of the symbol. + unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32 + ? GOT_TYPE_TLS_OFFSET + : GOT_TYPE_TLS_NOFFSET); + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = object->local_got_offset(r_sym, got_type); + } + // For the R_386_TLS_IE relocation, we need to apply the + // absolute address of the GOT entry. + if (r_type == elfcpp::R_386_TLS_IE) + got_offset += target->got_plt_section()->address(); + // All GOT offsets are relative to the end of the GOT. + got_offset -= target->got_size(); + Relocate_functions<32, false>::rel32(view, got_offset); + break; + } + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + case elfcpp::R_386_TLS_LE: // Local-exec + // If we're creating a shared library, a dynamic relocation will + // have been created for this location, so do not apply it now. + if (!parameters->options().shared()) + { + gold_assert(tls_segment != NULL); + value -= tls_segment->memsz(); + Relocate_functions<32, false>::rel32(view, value); + } + break; + + case elfcpp::R_386_TLS_LE_32: + // If we're creating a shared library, a dynamic relocation will + // have been created for this location, so do not apply it now. + if (!parameters->options().shared()) + { + gold_assert(tls_segment != NULL); + value = tls_segment->memsz() - value; + Relocate_functions<32, false>::rel32(view, value); + } + break; + } +} + +// Do a relocation in which we convert a TLS General-Dynamic to a +// Local-Exec. + +inline void +Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo, + size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>& rel, + unsigned int, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + // leal foo(,%reg,1),%eax; call ___tls_get_addr + // ==> movl %gs:0,%eax; subl $foo@tpoff,%eax + // leal foo(%reg),%eax; call ___tls_get_addr + // ==> movl %gs:0,%eax; subl $foo@tpoff,%eax + + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 9); + + unsigned char op1 = view[-1]; + unsigned char op2 = view[-2]; + + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + op2 == 0x8d || op2 == 0x04); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8); + + int roff = 5; + + if (op2 == 0x04) + { + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + ((op1 & 0xc7) == 0x05 && op1 != (4 << 3))); + memcpy(view - 3, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); + } + else + { + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + (op1 & 0xf8) == 0x80 && (op1 & 7) != 4); + if (rel.get_r_offset() + 9 < view_size + && view[9] == 0x90) + { + // There is a trailing nop. Use the size byte subl. + memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); + roff = 6; + } + else + { + // Use the five byte subl. + memcpy(view - 2, "\x65\xa1\0\0\0\0\x2d\0\0\0", 11); + } + } + + value = tls_segment->memsz() - value; + Relocate_functions<32, false>::rel32(view + roff, value); + + // The next reloc should be a PLT32 reloc against __tls_get_addr. + // We can skip it. + this->skip_call_tls_get_addr_ = true; +} + +// Do a relocation in which we convert a TLS General-Dynamic to an +// Initial-Exec. + +inline void +Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo, + size_t relnum, + Output_segment*, + const elfcpp::Rel<32, false>& rel, + unsigned int, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + // leal foo(,%ebx,1),%eax; call ___tls_get_addr + // ==> movl %gs:0,%eax; addl foo@gotntpoff(%ebx),%eax + + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 9); + + unsigned char op1 = view[-1]; + unsigned char op2 = view[-2]; + + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + op2 == 0x8d || op2 == 0x04); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8); + + int roff = 5; + + // FIXME: For now, support only the first (SIB) form. + tls::check_tls(relinfo, relnum, rel.get_r_offset(), op2 == 0x04); + + if (op2 == 0x04) + { + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + ((op1 & 0xc7) == 0x05 && op1 != (4 << 3))); + memcpy(view - 3, "\x65\xa1\0\0\0\0\x03\x83\0\0\0", 12); + } + else + { + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + (op1 & 0xf8) == 0x80 && (op1 & 7) != 4); + if (rel.get_r_offset() + 9 < view_size + && view[9] == 0x90) + { + // FIXME: This is not the right instruction sequence. + // There is a trailing nop. Use the size byte subl. + memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); + roff = 6; + } + else + { + // FIXME: This is not the right instruction sequence. + // Use the five byte subl. + memcpy(view - 2, "\x65\xa1\0\0\0\0\x2d\0\0\0", 11); + } + } + + Relocate_functions<32, false>::rel32(view + roff, value); + + // The next reloc should be a PLT32 reloc against __tls_get_addr. + // We can skip it. + this->skip_call_tls_get_addr_ = true; +} + +// Do a relocation in which we convert a TLS_GOTDESC or TLS_DESC_CALL +// General-Dynamic to a Local-Exec. + +inline void +Target_i386::Relocate::tls_desc_gd_to_le( + const Relocate_info<32, false>* relinfo, + size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>& rel, + unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + if (r_type == elfcpp::R_386_TLS_GOTDESC) + { + // leal foo@TLSDESC(%ebx), %eax + // ==> leal foo@NTPOFF, %eax + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + view[-2] == 0x8d && view[-1] == 0x83); + view[-1] = 0x05; + value -= tls_segment->memsz(); + Relocate_functions<32, false>::rel32(view, value); + } + else + { + // call *foo@TLSCALL(%eax) + // ==> nop; nop + gold_assert(r_type == elfcpp::R_386_TLS_DESC_CALL); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 2); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + view[0] == 0xff && view[1] == 0x10); + view[0] = 0x66; + view[1] = 0x90; + } +} + +// Do a relocation in which we convert a TLS_GOTDESC or TLS_DESC_CALL +// General-Dynamic to an Initial-Exec. + +inline void +Target_i386::Relocate::tls_desc_gd_to_ie( + const Relocate_info<32, false>* relinfo, + size_t relnum, + Output_segment*, + const elfcpp::Rel<32, false>& rel, + unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + if (r_type == elfcpp::R_386_TLS_GOTDESC) + { + // leal foo@TLSDESC(%ebx), %eax + // ==> movl foo@GOTNTPOFF(%ebx), %eax + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + view[-2] == 0x8d && view[-1] == 0x83); + view[-2] = 0x8b; + Relocate_functions<32, false>::rel32(view, value); + } + else + { + // call *foo@TLSCALL(%eax) + // ==> nop; nop + gold_assert(r_type == elfcpp::R_386_TLS_DESC_CALL); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 2); + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + view[0] == 0xff && view[1] == 0x10); + view[0] = 0x66; + view[1] = 0x90; + } +} + +// Do a relocation in which we convert a TLS Local-Dynamic to a +// Local-Exec. + +inline void +Target_i386::Relocate::tls_ld_to_le(const Relocate_info<32, false>* relinfo, + size_t relnum, + Output_segment*, + const elfcpp::Rel<32, false>& rel, + unsigned int, + elfcpp::Elf_types<32>::Elf_Addr, + unsigned char* view, + section_size_type view_size) +{ + // leal foo(%reg), %eax; call ___tls_get_addr + // ==> movl %gs:0,%eax; nop; leal 0(%esi,1),%esi + + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 9); + + // FIXME: Does this test really always pass? + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + view[-2] == 0x8d && view[-1] == 0x83); + + tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8); + + memcpy(view - 2, "\x65\xa1\0\0\0\0\x90\x8d\x74\x26\0", 11); + + // The next reloc should be a PLT32 reloc against __tls_get_addr. + // We can skip it. + this->skip_call_tls_get_addr_ = true; +} + +// Do a relocation in which we convert a TLS Initial-Exec to a +// Local-Exec. + +inline void +Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo, + size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rel<32, false>& rel, + unsigned int r_type, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + // We have to actually change the instructions, which means that we + // need to examine the opcodes to figure out which instruction we + // are looking at. + if (r_type == elfcpp::R_386_TLS_IE) + { + // movl %gs:XX,%eax ==> movl $YY,%eax + // movl %gs:XX,%reg ==> movl $YY,%reg + // addl %gs:XX,%reg ==> addl $YY,%reg + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -1); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4); + + unsigned char op1 = view[-1]; + if (op1 == 0xa1) + { + // movl XX,%eax ==> movl $YY,%eax + view[-1] = 0xb8; + } + else + { + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + + unsigned char op2 = view[-2]; + if (op2 == 0x8b) + { + // movl XX,%reg ==> movl $YY,%reg + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + (op1 & 0xc7) == 0x05); + view[-2] = 0xc7; + view[-1] = 0xc0 | ((op1 >> 3) & 7); + } + else if (op2 == 0x03) + { + // addl XX,%reg ==> addl $YY,%reg + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + (op1 & 0xc7) == 0x05); + view[-2] = 0x81; + view[-1] = 0xc0 | ((op1 >> 3) & 7); + } + else + tls::check_tls(relinfo, relnum, rel.get_r_offset(), 0); + } + } + else + { + // subl %gs:XX(%reg1),%reg2 ==> subl $YY,%reg2 + // movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2 + // addl %gs:XX(%reg1),%reg2 ==> addl $YY,$reg2 + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2); + tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4); + + unsigned char op1 = view[-1]; + unsigned char op2 = view[-2]; + tls::check_tls(relinfo, relnum, rel.get_r_offset(), + (op1 & 0xc0) == 0x80 && (op1 & 7) != 4); + if (op2 == 0x8b) + { + // movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2 + view[-2] = 0xc7; + view[-1] = 0xc0 | ((op1 >> 3) & 7); + } + else if (op2 == 0x2b) + { + // subl %gs:XX(%reg1),%reg2 ==> subl $YY,%reg2 + view[-2] = 0x81; + view[-1] = 0xe8 | ((op1 >> 3) & 7); + } + else if (op2 == 0x03) + { + // addl %gs:XX(%reg1),%reg2 ==> addl $YY,$reg2 + view[-2] = 0x81; + view[-1] = 0xc0 | ((op1 >> 3) & 7); + } + else + tls::check_tls(relinfo, relnum, rel.get_r_offset(), 0); + } + + value = tls_segment->memsz() - value; + if (r_type == elfcpp::R_386_TLS_IE || r_type == elfcpp::R_386_TLS_GOTIE) + value = - value; + + Relocate_functions<32, false>::rel32(view, value); +} + +// Relocate section data. + +void +Target_i386::relocate_section(const Relocate_info<32, false>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr address, + section_size_type view_size) +{ + gold_assert(sh_type == elfcpp::SHT_REL); + + gold::relocate_section<32, false, Target_i386, elfcpp::SHT_REL, + Target_i386::Relocate>( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size); +} + +// Return the size of a relocation while scanning during a relocatable +// link. + +unsigned int +Target_i386::Relocatable_size_for_reloc::get_size_for_reloc( + unsigned int r_type, + Relobj* object) +{ + switch (r_type) + { + case elfcpp::R_386_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + case elfcpp::R_386_TLS_GD: // Global-dynamic + case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_386_TLS_DESC_CALL: + case elfcpp::R_386_TLS_LDM: // Local-dynamic + case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic + case elfcpp::R_386_TLS_IE: // Initial-exec + case elfcpp::R_386_TLS_IE_32: + case elfcpp::R_386_TLS_GOTIE: + case elfcpp::R_386_TLS_LE: // Local-exec + case elfcpp::R_386_TLS_LE_32: + return 0; + + case elfcpp::R_386_32: + case elfcpp::R_386_PC32: + case elfcpp::R_386_GOT32: + case elfcpp::R_386_PLT32: + case elfcpp::R_386_GOTOFF: + case elfcpp::R_386_GOTPC: + return 4; + + case elfcpp::R_386_16: + case elfcpp::R_386_PC16: + return 2; + + case elfcpp::R_386_8: + case elfcpp::R_386_PC8: + return 1; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_386_COPY: + case elfcpp::R_386_GLOB_DAT: + case elfcpp::R_386_JUMP_SLOT: + case elfcpp::R_386_RELATIVE: + case elfcpp::R_386_TLS_TPOFF: + case elfcpp::R_386_TLS_DTPMOD32: + case elfcpp::R_386_TLS_DTPOFF32: + case elfcpp::R_386_TLS_TPOFF32: + case elfcpp::R_386_TLS_DESC: + object->error(_("unexpected reloc %u in object file"), r_type); + return 0; + + case elfcpp::R_386_32PLT: + case elfcpp::R_386_TLS_GD_32: + case elfcpp::R_386_TLS_GD_PUSH: + case elfcpp::R_386_TLS_GD_CALL: + case elfcpp::R_386_TLS_GD_POP: + case elfcpp::R_386_TLS_LDM_32: + case elfcpp::R_386_TLS_LDM_PUSH: + case elfcpp::R_386_TLS_LDM_CALL: + case elfcpp::R_386_TLS_LDM_POP: + case elfcpp::R_386_USED_BY_INTEL_200: + default: + object->error(_("unsupported reloc %u in object file"), r_type); + return 0; + } +} + +// Scan the relocs during a relocatable link. + +void +Target_i386::scan_relocatable_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) +{ + gold_assert(sh_type == elfcpp::SHT_REL); + + typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL, + Relocatable_size_for_reloc> Scan_relocatable_relocs; + + gold::scan_relocatable_relocs<32, false, elfcpp::SHT_REL, + Scan_relocatable_relocs>( + options, + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); +} + +// Relocate a section during a relocatable link. + +void +Target_i386::relocate_for_relocatable( + const Relocate_info<32, false>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs* rr, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size) +{ + gold_assert(sh_type == elfcpp::SHT_REL); + + gold::relocate_for_relocatable<32, false, elfcpp::SHT_REL>( + relinfo, + prelocs, + reloc_count, + output_section, + offset_in_output_section, + rr, + view, + view_address, + view_size, + reloc_view, + reloc_view_size); +} + +// Return the value to use for a dynamic which requires special +// treatment. This is how we support equality comparisons of function +// pointers across shared library boundaries, as described in the +// processor specific ABI supplement. + +uint64_t +Target_i386::do_dynsym_value(const Symbol* gsym) const +{ + gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset()); + return this->plt_section()->address() + gsym->plt_offset(); +} + +// Return a string used to fill a code section with nops to take up +// the specified length. + +std::string +Target_i386::do_code_fill(section_size_type length) const +{ + if (length >= 16) + { + // Build a jmp instruction to skip over the bytes. + unsigned char jmp[5]; + jmp[0] = 0xe9; + elfcpp::Swap_unaligned<32, false>::writeval(jmp + 1, length - 5); + return (std::string(reinterpret_cast<char*>(&jmp[0]), 5) + + std::string(length - 5, '\0')); + } + + // Nop sequences of various lengths. + const char nop1[1] = { 0x90 }; // nop + const char nop2[2] = { 0x66, 0x90 }; // xchg %ax %ax + const char nop3[3] = { 0x8d, 0x76, 0x00 }; // leal 0(%esi),%esi + const char nop4[4] = { 0x8d, 0x74, 0x26, 0x00}; // leal 0(%esi,1),%esi + const char nop5[5] = { 0x90, 0x8d, 0x74, 0x26, // nop + 0x00 }; // leal 0(%esi,1),%esi + const char nop6[6] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + 0x00, 0x00 }; + const char nop7[7] = { 0x8d, 0xb4, 0x26, 0x00, // leal 0L(%esi,1),%esi + 0x00, 0x00, 0x00 }; + const char nop8[8] = { 0x90, 0x8d, 0xb4, 0x26, // nop + 0x00, 0x00, 0x00, 0x00 }; // leal 0L(%esi,1),%esi + const char nop9[9] = { 0x89, 0xf6, 0x8d, 0xbc, // movl %esi,%esi + 0x27, 0x00, 0x00, 0x00, // leal 0L(%edi,1),%edi + 0x00 }; + const char nop10[10] = { 0x8d, 0x76, 0x00, 0x8d, // leal 0(%esi),%esi + 0xbc, 0x27, 0x00, 0x00, // leal 0L(%edi,1),%edi + 0x00, 0x00 }; + const char nop11[11] = { 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi + 0x8d, 0xbc, 0x27, 0x00, // leal 0L(%edi,1),%edi + 0x00, 0x00, 0x00 }; + const char nop12[12] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + 0x00, 0x00, 0x8d, 0xbf, // leal 0L(%edi),%edi + 0x00, 0x00, 0x00, 0x00 }; + const char nop13[13] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + 0x00, 0x00, 0x8d, 0xbc, // leal 0L(%edi,1),%edi + 0x27, 0x00, 0x00, 0x00, + 0x00 }; + const char nop14[14] = { 0x8d, 0xb4, 0x26, 0x00, // leal 0L(%esi,1),%esi + 0x00, 0x00, 0x00, 0x8d, // leal 0L(%edi,1),%edi + 0xbc, 0x27, 0x00, 0x00, + 0x00, 0x00 }; + const char nop15[15] = { 0xeb, 0x0d, 0x90, 0x90, // jmp .+15 + 0x90, 0x90, 0x90, 0x90, // nop,nop,nop,... + 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90 }; + + const char* nops[16] = { + NULL, + nop1, nop2, nop3, nop4, nop5, nop6, nop7, + nop8, nop9, nop10, nop11, nop12, nop13, nop14, nop15 + }; + + return std::string(nops[length], length); +} + +// The selector for i386 object files. + +class Target_selector_i386 : public Target_selector +{ +public: + Target_selector_i386() + : Target_selector(elfcpp::EM_386, 32, false, "elf32-i386") + { } + + Target* + do_instantiate_target() + { return new Target_i386(); } +}; + +Target_selector_i386 target_selector_i386; + +} // End anonymous namespace. diff --git a/gold/powerpc.cc b/gold/powerpc.cc new file mode 100644 index 00000000000..421cfdb206a --- /dev/null +++ b/gold/powerpc.cc @@ -0,0 +1,1973 @@ +// powerpc.cc -- powerpc target support for gold. + +// Copyright 2008 Free Software Foundation, Inc. +// Written by David S. Miller <davem@davemloft.net> +// and David Edelsohn <edelsohn@gnu.org> + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include "elfcpp.h" +#include "parameters.h" +#include "reloc.h" +#include "powerpc.h" +#include "object.h" +#include "symtab.h" +#include "layout.h" +#include "output.h" +#include "copy-relocs.h" +#include "target.h" +#include "target-reloc.h" +#include "target-select.h" +#include "tls.h" +#include "errors.h" + +namespace +{ + +using namespace gold; + +template<int size, bool big_endian> +class Output_data_plt_powerpc; + +template<int size, bool big_endian> +class Target_powerpc : public Sized_target<size, big_endian> +{ + public: + typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Reloc_section; + + Target_powerpc() + : Sized_target<size, big_endian>(&powerpc_info), + got_(NULL), got2_(NULL), toc_(NULL), + plt_(NULL), rela_dyn_(NULL), + copy_relocs_(elfcpp::R_POWERPC_COPY), + dynbss_(NULL), got_mod_index_offset_(-1U) + { + } + + // Scan the relocations to look for symbol adjustments. + void + scan_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + // Finalize the sections. + void + do_finalize_sections(Layout*); + + // Return the value to use for a dynamic which requires special + // treatment. + uint64_t + do_dynsym_value(const Symbol*) const; + + // Relocate a section. + void + relocate_section(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size); + + // Scan the relocs during a relocatable link. + void + scan_relocatable_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs*); + + // Relocate a section during a relocatable link. + void + relocate_for_relocatable(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); + + // Return whether SYM is defined by the ABI. + bool + do_is_defined_by_abi(Symbol* sym) const + { + return strcmp(sym->name(), "___tls_get_addr") == 0; + } + + // Return the size of the GOT section. + section_size_type + got_size() + { + gold_assert(this->got_ != NULL); + return this->got_->data_size(); + } + + private: + + // The class which scans relocations. + class Scan + { + public: + Scan() + : issued_non_pic_error_(false) + { } + + inline void + local(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_powerpc* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type, + const elfcpp::Sym<size, big_endian>& lsym); + + inline void + global(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_powerpc* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type, + Symbol* gsym); + + private: + static void + unsupported_reloc_local(Sized_relobj<size, big_endian>*, + unsigned int r_type); + + static void + unsupported_reloc_global(Sized_relobj<size, big_endian>*, + unsigned int r_type, Symbol*); + + static void + generate_tls_call(Symbol_table* symtab, Layout* layout, + Target_powerpc* target); + + void + check_non_pic(Relobj*, unsigned int r_type); + + // Whether we have issued an error about a non-PIC compilation. + bool issued_non_pic_error_; + }; + + // The class which implements relocation. + class Relocate + { + public: + // Do a relocation. Return false if the caller should not issue + // any warnings about this relocation. + inline bool + relocate(const Relocate_info<size, big_endian>*, Target_powerpc*, + size_t relnum, const elfcpp::Rela<size, big_endian>&, + unsigned int r_type, const Sized_symbol<size>*, + const Symbol_value<size>*, + unsigned char*, + typename elfcpp::Elf_types<size>::Elf_Addr, + section_size_type); + + private: + // Do a TLS relocation. + inline void + relocate_tls(const Relocate_info<size, big_endian>*, + Target_powerpc* target, + size_t relnum, const elfcpp::Rela<size, big_endian>&, + unsigned int r_type, const Sized_symbol<size>*, + const Symbol_value<size>*, + unsigned char*, + typename elfcpp::Elf_types<size>::Elf_Addr, + section_size_type); + }; + + // A class which returns the size required for a relocation type, + // used while scanning relocs during a relocatable link. + class Relocatable_size_for_reloc + { + public: + unsigned int + get_size_for_reloc(unsigned int, Relobj*); + }; + + // Get the GOT section, creating it if necessary. + Output_data_got<size, big_endian>* + got_section(Symbol_table*, Layout*); + + Output_data_space* + got2_section() const + { + gold_assert (this->got2_ != NULL); + return this->got2_; + } + + // Get the TOC section. + Output_data_space* + toc_section() const + { + gold_assert (this->toc_ != NULL); + return this->toc_; + } + + // Create a PLT entry for a global symbol. + void + make_plt_entry(Symbol_table*, Layout*, Symbol*); + + // Create a GOT entry for the TLS module index. + unsigned int + got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<size, big_endian>* object); + + // Get the PLT section. + const Output_data_plt_powerpc<size, big_endian>* + plt_section() const + { + gold_assert(this->plt_ != NULL); + return this->plt_; + } + + // Get the dynamic reloc section, creating it if necessary. + Reloc_section* + rela_dyn_section(Layout*); + + // Return true if the symbol may need a COPY relocation. + // References from an executable object to non-function symbols + // defined in a dynamic object may need a COPY relocation. + bool + may_need_copy_reloc(Symbol* gsym) + { + return (!parameters->options().shared() + && gsym->is_from_dynobj() + && gsym->type() != elfcpp::STT_FUNC); + } + + // Copy a relocation against a global symbol. + void + copy_reloc(Symbol_table* symtab, Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int shndx, Output_section* output_section, + Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc) + { + this->copy_relocs_.copy_reloc(symtab, layout, + symtab->get_sized_symbol<size>(sym), + object, shndx, output_section, + reloc, this->rela_dyn_section(layout)); + } + + // Information about this specific target which we pass to the + // general Target structure. + static Target::Target_info powerpc_info; + + // The types of GOT entries needed for this platform. + enum Got_type + { + GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol + GOT_TYPE_TLS_OFFSET = 1, // GOT entry for TLS offset + GOT_TYPE_TLS_PAIR = 2, // GOT entry for TLS module/offset pair + }; + + // The GOT section. + Output_data_got<size, big_endian>* got_; + // The GOT2 section. + Output_data_space* got2_; + // The TOC section. + Output_data_space* toc_; + // The PLT section. + Output_data_plt_powerpc<size, big_endian>* plt_; + // The dynamic reloc section. + Reloc_section* rela_dyn_; + // Relocs saved to avoid a COPY reloc. + Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_; + // Space for variables copied with a COPY reloc. + Output_data_space* dynbss_; + // Offset of the GOT entry for the TLS module index; + unsigned int got_mod_index_offset_; +}; + +template<> +Target::Target_info Target_powerpc<32, true>::powerpc_info = +{ + 32, // size + true, // is_big_endian + elfcpp::EM_PPC, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/ld.so.1", // dynamic_linker + 0x10000000, // default_text_segment_address + 64 * 1024, // abi_pagesize (overridable by -z max-page-size) + 4 * 1024 // common_pagesize (overridable by -z common-page-size) +}; + +template<> +Target::Target_info Target_powerpc<32, false>::powerpc_info = +{ + 32, // size + false, // is_big_endian + elfcpp::EM_PPC, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/ld.so.1", // dynamic_linker + 0x10000000, // default_text_segment_address + 64 * 1024, // abi_pagesize (overridable by -z max-page-size) + 4 * 1024 // common_pagesize (overridable by -z common-page-size) +}; + +template<> +Target::Target_info Target_powerpc<64, true>::powerpc_info = +{ + 64, // size + true, // is_big_endian + elfcpp::EM_PPC64, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/ld.so.1", // dynamic_linker + 0x10000000, // default_text_segment_address + 64 * 1024, // abi_pagesize (overridable by -z max-page-size) + 8 * 1024 // common_pagesize (overridable by -z common-page-size) +}; + +template<> +Target::Target_info Target_powerpc<64, false>::powerpc_info = +{ + 64, // size + false, // is_big_endian + elfcpp::EM_PPC64, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/ld.so.1", // dynamic_linker + 0x10000000, // default_text_segment_address + 64 * 1024, // abi_pagesize (overridable by -z max-page-size) + 8 * 1024 // common_pagesize (overridable by -z common-page-size) +}; + +template<int size, bool big_endian> +class Powerpc_relocate_functions +{ +private: + // Do a simple relocation with the addend in the relocation. + template<int valsize> + static inline void + rela(unsigned char* view, + unsigned int right_shift, + elfcpp::Elf_Xword dst_mask, + typename elfcpp::Swap<size, big_endian>::Valtype value, + typename elfcpp::Swap<size, big_endian>::Valtype addend) + { + typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv); + Valtype reloc = ((value + addend) >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap<valsize, big_endian>::writeval(wv, val | reloc); + } + + // Do a simple relocation using a symbol value with the addend in + // the relocation. + template<int valsize> + static inline void + rela(unsigned char* view, + unsigned int right_shift, + elfcpp::Elf_Xword dst_mask, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<valsize, big_endian>::Valtype addend) + { + typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv); + Valtype reloc = (psymval->value(object, addend) >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap<valsize, big_endian>::writeval(wv, val | reloc); + } + + // Do a simple relocation using a symbol value with the addend in + // the relocation, unaligned. + template<int valsize> + static inline void + rela_ua(unsigned char* view, unsigned int right_shift, + elfcpp::Elf_Xword dst_mask, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<size, big_endian>::Valtype addend) + { + typedef typename elfcpp::Swap_unaligned<valsize, + big_endian>::Valtype Valtype; + unsigned char* wv = view; + Valtype val = elfcpp::Swap_unaligned<valsize, big_endian>::readval(wv); + Valtype reloc = (psymval->value(object, addend) >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap_unaligned<valsize, big_endian>::writeval(wv, val | reloc); + } + + // Do a simple PC relative relocation with a Symbol_value with the + // addend in the relocation. + template<int valsize> + static inline void + pcrela(unsigned char* view, unsigned int right_shift, + elfcpp::Elf_Xword dst_mask, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<size, big_endian>::Valtype addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv); + Valtype reloc = ((psymval->value(object, addend) - address) + >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap<valsize, big_endian>::writeval(wv, val | reloc); + } + + template<int valsize> + static inline void + pcrela_unaligned(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<size, big_endian>::Valtype addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + typedef typename elfcpp::Swap_unaligned<valsize, + big_endian>::Valtype Valtype; + unsigned char* wv = view; + Valtype reloc = (psymval->value(object, addend) - address); + + elfcpp::Swap_unaligned<valsize, big_endian>::writeval(wv, reloc); + } + + typedef Powerpc_relocate_functions<size, big_endian> This; + typedef Relocate_functions<size, big_endian> This_reloc; +public: + // R_POWERPC_REL32: (Symbol + Addend - Address) + static inline void + rel32(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { This_reloc::pcrela32(view, object, psymval, addend, address); } + + // R_POWERPC_REL24: (Symbol + Addend - Address) & 0x3fffffc + static inline void + rel24(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela<32>(view, 0, 0x03fffffc, object, + psymval, addend, address); + } + + // R_POWERPC_REL14: (Symbol + Addend - Address) & 0xfffc + static inline void + rel14(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela<32>(view, 0, 0x0000fffc, object, + psymval, addend, address); + } + + // R_POWERPC_ADDR16: (Symbol + Addend) & 0xffff + static inline void + addr16(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { This_reloc::rela16(view, value, addend); } + + static inline void + addr16(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { This_reloc::rela16(view, object, psymval, addend); } + + // R_POWERPC_ADDR16_DS: (Symbol + Addend) & 0xfffc + static inline void + addr16_ds(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This::template rela<16>(view, 0, 0xfffc, value, addend); + } + + // R_POWERPC_ADDR16_LO: (Symbol + Addend) & 0xffff + static inline void + addr16_lo(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { This_reloc::rela16(view, value, addend); } + + static inline void + addr16_lo(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { This_reloc::rela16(view, object, psymval, addend); } + + // R_POWERPC_ADDR16_HI: ((Symbol + Addend) >> 16) & 0xffff + static inline void + addr16_hi(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This::template rela<16>(view, 16, 0xffff, value, addend); + } + + static inline void + addr16_hi(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This::template rela<16>(view, 16, 0xffff, object, psymval, addend); + } + + // R_POWERPC_ADDR16_HA: Same as R_POWERPC_ADDR16_HI except that if the + // final value of the low 16 bits of the + // relocation is negative, add one. + static inline void + addr16_ha(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typename elfcpp::Elf_types<size>::Elf_Addr reloc; + + reloc = value + addend; + + if (reloc & 0x8000) + reloc += 0x10000; + reloc >>= 16; + + elfcpp::Swap<16, big_endian>::writeval(view, reloc); + } + + static inline void + addr16_ha(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typename elfcpp::Elf_types<size>::Elf_Addr reloc; + + reloc = psymval->value(object, addend); + + if (reloc & 0x8000) + reloc += 0x10000; + reloc >>= 16; + + elfcpp::Swap<16, big_endian>::writeval(view, reloc); + } + + // R_PPC_REL16: (Symbol + Addend - Address) & 0xffff + static inline void + rel16(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { This_reloc::pcrela16(view, object, psymval, addend, address); } + + // R_PPC_REL16_LO: (Symbol + Addend - Address) & 0xffff + static inline void + rel16_lo(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { This_reloc::pcrela16(view, object, psymval, addend, address); } + + // R_PPC_REL16_HI: ((Symbol + Addend - Address) >> 16) & 0xffff + static inline void + rel16_hi(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela<16>(view, 16, 0xffff, object, + psymval, addend, address); + } + + // R_PPC_REL16_HA: Same as R_PPC_REL16_HI except that if the + // final value of the low 16 bits of the + // relocation is negative, add one. + static inline void + rel16_ha(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + typedef typename elfcpp::Swap<16, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<16, true>::readval(wv); + typename elfcpp::Elf_types<size>::Elf_Addr reloc; + + reloc = (psymval->value(object, addend) - address); + if (reloc & 0x8000) + reloc += 0x10000; + reloc >>= 16; + + val &= ~static_cast<Valtype>(0xffff); + reloc &= static_cast<Valtype>(0xffff); + + elfcpp::Swap<16, true>::writeval(wv, val | reloc); + } +}; + +// Get the GOT section, creating it if necessary. + +template<int size, bool big_endian> +Output_data_got<size, big_endian>* +Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, + Layout* layout) +{ + if (this->got_ == NULL) + { + gold_assert(symtab != NULL && layout != NULL); + + this->got_ = new Output_data_got<size, big_endian>(); + + layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->got_); + + // Create the GOT2 or TOC in the .got section. + if (size == 32) + { + this->got2_ = new Output_data_space(4, "** GOT2"); + layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE, + this->got2_); + } + else + { + this->toc_ = new Output_data_space(8, "** TOC"); + layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE, + this->toc_); + } + + // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + this->got_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + return this->got_; +} + +// Get the dynamic reloc section, creating it if necessary. + +template<int size, bool big_endian> +typename Target_powerpc<size, big_endian>::Reloc_section* +Target_powerpc<size, big_endian>::rela_dyn_section(Layout* layout) +{ + if (this->rela_dyn_ == NULL) + { + gold_assert(layout != NULL); + this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); + layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->rela_dyn_); + } + return this->rela_dyn_; +} + +// A class to handle the PLT data. + +template<int size, bool big_endian> +class Output_data_plt_powerpc : public Output_section_data +{ + public: + typedef Output_data_reloc<elfcpp::SHT_RELA, true, + size, big_endian> Reloc_section; + + Output_data_plt_powerpc(Layout*); + + // Add an entry to the PLT. + void add_entry(Symbol* gsym); + + // Return the .rela.plt section data. + const Reloc_section* rel_plt() const + { + return this->rel_; + } + + protected: + void do_adjust_output_section(Output_section* os); + + private: + // The size of an entry in the PLT. + static const int base_plt_entry_size = (size == 32 ? 16 : 24); + + // Set the final size. + void + set_final_data_size() + { + unsigned int full_count = this->count_ + 4; + + this->set_data_size(full_count * base_plt_entry_size); + } + + // Write out the PLT data. + void + do_write(Output_file*); + + // The reloc section. + Reloc_section* rel_; + // The number of PLT entries. + unsigned int count_; +}; + +// Create the PLT section. The ordinary .got section is an argument, +// since we need to refer to the start. + +template<int size, bool big_endian> +Output_data_plt_powerpc<size, big_endian>::Output_data_plt_powerpc(Layout* layout) + : Output_section_data(size == 32 ? 4 : 8), count_(0) +{ + this->rel_ = new Reloc_section(false); + layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->rel_); +} + +template<int size, bool big_endian> +void +Output_data_plt_powerpc<size, big_endian>::do_adjust_output_section(Output_section* os) +{ + os->set_entsize(0); +} + +// Add an entry to the PLT. + +template<int size, bool big_endian> +void +Output_data_plt_powerpc<size, big_endian>::add_entry(Symbol* gsym) +{ + gold_assert(!gsym->has_plt_offset()); + unsigned int index = this->count_+ + 4; + section_offset_type plt_offset; + + if (index < 8192) + plt_offset = index * base_plt_entry_size; + else + gold_unreachable(); + + gsym->set_plt_offset(plt_offset); + + ++this->count_; + + gsym->set_needs_dynsym_entry(); + this->rel_->add_global(gsym, elfcpp::R_POWERPC_JMP_SLOT, this, + plt_offset, 0); +} + +static const unsigned int addis_11_11 = 0x3d6b0000; +static const unsigned int addis_11_30 = 0x3d7e0000; +static const unsigned int addis_12_12 = 0x3d8c0000; +static const unsigned int addi_11_11 = 0x396b0000; +static const unsigned int add_0_11_11 = 0x7c0b5a14; +static const unsigned int add_11_0_11 = 0x7d605a14; +static const unsigned int b = 0x48000000; +static const unsigned int bcl_20_31 = 0x429f0005; +static const unsigned int bctr = 0x4e800420; +static const unsigned int lis_11 = 0x3d600000; +static const unsigned int lis_12 = 0x3d800000; +static const unsigned int lwzu_0_12 = 0x840c0000; +static const unsigned int lwz_0_12 = 0x800c0000; +static const unsigned int lwz_11_11 = 0x816b0000; +static const unsigned int lwz_11_30 = 0x817e0000; +static const unsigned int lwz_12_12 = 0x818c0000; +static const unsigned int mflr_0 = 0x7c0802a6; +static const unsigned int mflr_12 = 0x7d8802a6; +static const unsigned int mtctr_0 = 0x7c0903a6; +static const unsigned int mtctr_11 = 0x7d6903a6; +static const unsigned int mtlr_0 = 0x7c0803a6; +static const unsigned int nop = 0x60000000; +static const unsigned int sub_11_11_12 = 0x7d6c5850; + +static const unsigned int addis_r12_r2 = 0x3d820000; /* addis %r12,%r2,xxx@ha */ +static const unsigned int std_r2_40r1 = 0xf8410028; /* std %r2,40(%r1) */ +static const unsigned int ld_r11_0r12 = 0xe96c0000; /* ld %r11,xxx+0@l(%r12) */ +static const unsigned int ld_r2_0r12 = 0xe84c0000; /* ld %r2,xxx+8@l(%r12) */ + /* ld %r11,xxx+16@l(%r12) */ + + +// Write out the PLT. + +template<int size, bool big_endian> +void +Output_data_plt_powerpc<size, big_endian>::do_write(Output_file* of) +{ + const off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + unsigned char* pov = oview; + + memset(pov, 0, base_plt_entry_size * 4); + pov += base_plt_entry_size * 4; + + unsigned int plt_offset = base_plt_entry_size * 4; + const unsigned int count = this->count_; + + if (size == 64) + { + for (unsigned int i = 0; i < count; i++) + { + } + } + else + { + for (unsigned int i = 0; i < count; i++) + { + elfcpp::Swap<32, true>::writeval(pov + 0x00, + lwz_11_30 + plt_offset); + elfcpp::Swap<32, true>::writeval(pov + 0x04, mtctr_11); + elfcpp::Swap<32, true>::writeval(pov + 0x08, bctr); + elfcpp::Swap<32, true>::writeval(pov + 0x0c, nop); + pov += base_plt_entry_size; + plt_offset += base_plt_entry_size; + } + } + + gold_assert(static_cast<section_size_type>(pov - oview) == oview_size); + + of->write_output_view(offset, oview_size, oview); +} + +// Create a PLT entry for a global symbol. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab, + Layout* layout, + Symbol* gsym) +{ + if (gsym->has_plt_offset()) + return; + + if (this->plt_ == NULL) + { + // Create the GOT section first. + this->got_section(symtab, layout); + + this->plt_ = new Output_data_plt_powerpc<size, big_endian>(layout); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR + | elfcpp::SHF_WRITE), + this->plt_); + + // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. + symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, + this->plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + this->plt_->add_entry(gsym); +} + +// Create a GOT entry for the TLS module index. + +template<int size, bool big_endian> +unsigned int +Target_powerpc<size, big_endian>::got_mod_index_entry(Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object) +{ + if (this->got_mod_index_offset_ == -1U) + { + gold_assert(symtab != NULL && layout != NULL && object != NULL); + Reloc_section* rela_dyn = this->rela_dyn_section(layout); + Output_data_got<size, big_endian>* got; + unsigned int got_offset; + + got = this->got_section(symtab, layout); + got_offset = got->add_constant(0); + rela_dyn->add_local(object, 0, elfcpp::R_POWERPC_DTPMOD, got, + got_offset, 0); + got->add_constant(0); + this->got_mod_index_offset_ = got_offset; + } + return this->got_mod_index_offset_; +} + +// Optimize the TLS relocation type based on what we know about the +// symbol. IS_FINAL is true if the final address of this symbol is +// known at link time. + +static tls::Tls_optimization +optimize_tls_reloc(bool /* is_final */, int r_type) +{ + // If we are generating a shared library, then we can't do anything + // in the linker. + if (parameters->options().shared()) + return tls::TLSOPT_NONE; + switch (r_type) + { + // XXX + default: + gold_unreachable(); + } +} + +// Report an unsupported relocation against a local symbol. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::Scan::unsupported_reloc_local( + Sized_relobj<size, big_endian>* object, + unsigned int r_type) +{ + gold_error(_("%s: unsupported reloc %u against local symbol"), + object->name().c_str(), r_type); +} + +// We are about to emit a dynamic relocation of type R_TYPE. If the +// dynamic linker does not support it, issue an error. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object, + unsigned int r_type) +{ + gold_assert(r_type != elfcpp::R_POWERPC_NONE); + + // These are the relocation types supported by glibc for both 32-bit + // and 64-bit powerpc. + switch (r_type) + { + case elfcpp::R_POWERPC_RELATIVE: + case elfcpp::R_POWERPC_GLOB_DAT: + case elfcpp::R_POWERPC_DTPMOD: + case elfcpp::R_POWERPC_DTPREL: + case elfcpp::R_POWERPC_TPREL: + case elfcpp::R_POWERPC_JMP_SLOT: + case elfcpp::R_POWERPC_COPY: + case elfcpp::R_POWERPC_ADDR32: + case elfcpp::R_POWERPC_ADDR24: + case elfcpp::R_POWERPC_REL24: + return; + + default: + break; + } + + if (size == 64) + { + switch (r_type) + { + // These are the relocation types supported only on 64-bit. + case elfcpp::R_PPC64_ADDR64: + case elfcpp::R_PPC64_TPREL16_LO_DS: + case elfcpp::R_PPC64_TPREL16_DS: + case elfcpp::R_POWERPC_TPREL16: + case elfcpp::R_POWERPC_TPREL16_LO: + case elfcpp::R_POWERPC_TPREL16_HI: + case elfcpp::R_POWERPC_TPREL16_HA: + case elfcpp::R_PPC64_TPREL16_HIGHER: + case elfcpp::R_PPC64_TPREL16_HIGHEST: + case elfcpp::R_PPC64_TPREL16_HIGHERA: + case elfcpp::R_PPC64_TPREL16_HIGHESTA: + case elfcpp::R_PPC64_ADDR16_LO_DS: + case elfcpp::R_POWERPC_ADDR16_LO: + case elfcpp::R_POWERPC_ADDR16_HI: + case elfcpp::R_POWERPC_ADDR16_HA: + case elfcpp::R_POWERPC_ADDR30: + case elfcpp::R_PPC64_UADDR64: + case elfcpp::R_POWERPC_UADDR32: + case elfcpp::R_POWERPC_ADDR16: + case elfcpp::R_POWERPC_UADDR16: + case elfcpp::R_PPC64_ADDR16_DS: + case elfcpp::R_PPC64_ADDR16_HIGHER: + case elfcpp::R_PPC64_ADDR16_HIGHEST: + case elfcpp::R_PPC64_ADDR16_HIGHERA: + case elfcpp::R_PPC64_ADDR16_HIGHESTA: + case elfcpp::R_POWERPC_ADDR14_BRTAKEN: + case elfcpp::R_POWERPC_ADDR14_BRNTAKEN: + case elfcpp::R_POWERPC_REL32: + case elfcpp::R_PPC64_REL64: + return; + + default: + break; + } + } + else + { + switch (r_type) + { + // These are the relocation types supported only on 32-bit. + + default: + break; + } + } + + // This prevents us from issuing more than one error per reloc + // section. But we can still wind up issuing more than one + // error per object file. + if (this->issued_non_pic_error_) + return; + object->error(_("requires unsupported dynamic reloc; " + "recompile with -fPIC")); + this->issued_non_pic_error_ = true; + return; +} + +// Scan a relocation for a local symbol. + +template<int size, bool big_endian> +inline void +Target_powerpc<size, big_endian>::Scan::local( + const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_powerpc<size, big_endian>* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, + unsigned int r_type, + const elfcpp::Sym<size, big_endian>& lsym) +{ + switch (r_type) + { + case elfcpp::R_POWERPC_NONE: + case elfcpp::R_POWERPC_GNU_VTINHERIT: + case elfcpp::R_POWERPC_GNU_VTENTRY: + break; + + case elfcpp::R_PPC64_ADDR64: + case elfcpp::R_POWERPC_ADDR32: + case elfcpp::R_POWERPC_ADDR16_HA: + case elfcpp::R_POWERPC_ADDR16_LO: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + + check_non_pic(object, r_type); + if (lsym.get_st_type() != elfcpp::STT_SECTION) + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + rela_dyn->add_local(object, r_sym, r_type, output_section, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + gold_assert(lsym.get_st_value() == 0); + rela_dyn->add_local_relative(object, r_sym, r_type, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + break; + + case elfcpp::R_POWERPC_REL24: + case elfcpp::R_PPC_LOCAL24PC: + case elfcpp::R_POWERPC_REL32: + case elfcpp::R_PPC_REL16_LO: + case elfcpp::R_PPC_REL16_HA: + break; + + case elfcpp::R_POWERPC_GOT16: + case elfcpp::R_POWERPC_GOT16_LO: + case elfcpp::R_POWERPC_GOT16_HI: + case elfcpp::R_POWERPC_GOT16_HA: + case elfcpp::R_PPC64_TOC16: + case elfcpp::R_PPC64_TOC16_LO: + case elfcpp::R_PPC64_TOC16_HI: + case elfcpp::R_PPC64_TOC16_HA: + case elfcpp::R_PPC64_TOC16_DS: + case elfcpp::R_PPC64_TOC16_LO_DS: + { + // The symbol requires a GOT entry. + Output_data_got<size, big_endian>* got; + unsigned int r_sym; + + got = target->got_section(symtab, layout); + r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + + // If we are generating a shared object, we need to add a + // dynamic relocation for this symbol's GOT entry. + if (parameters->options().output_is_position_independent()) + { + if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int off; + + off = got->add_constant(0); + object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off); + rela_dyn->add_local_relative(object, r_sym, + elfcpp::R_POWERPC_RELATIVE, + got, off, 0); + } + } + else + got->add_local(object, r_sym, GOT_TYPE_STANDARD); + } + break; + + case elfcpp::R_PPC64_TOC: + // We need a GOT section. + target->got_section(symtab, layout); + break; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_POWERPC_COPY: + case elfcpp::R_POWERPC_GLOB_DAT: + case elfcpp::R_POWERPC_JMP_SLOT: + case elfcpp::R_POWERPC_RELATIVE: + case elfcpp::R_POWERPC_DTPMOD: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + default: + unsupported_reloc_local(object, r_type); + break; + } +} + +// Report an unsupported relocation against a global symbol. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::Scan::unsupported_reloc_global( + Sized_relobj<size, big_endian>* object, + unsigned int r_type, + Symbol* gsym) +{ + gold_error(_("%s: unsupported reloc %u against global symbol %s"), + object->name().c_str(), r_type, gsym->demangled_name().c_str()); +} + +// Scan a relocation for a global symbol. + +template<int size, bool big_endian> +inline void +Target_powerpc<size, big_endian>::Scan::global( + const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_powerpc<size, big_endian>* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, + unsigned int r_type, + Symbol* gsym) +{ + switch (r_type) + { + case elfcpp::R_POWERPC_NONE: + case elfcpp::R_POWERPC_GNU_VTINHERIT: + case elfcpp::R_POWERPC_GNU_VTENTRY: + break; + + case elfcpp::R_PPC_PLTREL24: + // If the symbol is fully resolved, this is just a PC32 reloc. + // Otherwise we need a PLT entry. + if (gsym->final_value_is_known()) + break; + // If building a shared library, we can also skip the PLT entry + // if the symbol is defined in the output file and is protected + // or hidden. + if (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible()) + break; + target->make_plt_entry(symtab, layout, gsym); + break; + + case elfcpp::R_POWERPC_ADDR16: + case elfcpp::R_POWERPC_ADDR16_LO: + case elfcpp::R_POWERPC_ADDR16_HI: + case elfcpp::R_POWERPC_ADDR16_HA: + case elfcpp::R_POWERPC_ADDR32: + case elfcpp::R_PPC64_ADDR64: + { + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + { + target->make_plt_entry(symtab, layout, gsym); + // Since this is not a PC-relative relocation, we may be + // taking the address of a function. In that case we need to + // set the entry in the dynamic symbol table to the address of + // the PLT entry. + if (gsym->is_from_dynobj() && !parameters->options().shared()) + gsym->set_needs_dynsym_value(); + } + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else if ((r_type == elfcpp::R_POWERPC_ADDR32 + || r_type == elfcpp::R_PPC64_ADDR64) + && gsym->can_use_relative_reloc(false)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, + output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + + check_non_pic(object, r_type); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + rela_dyn->add_global(gsym, r_type, output_section, + object, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + else + rela_dyn->add_global_relative(gsym, r_type, + output_section, object, + data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + } + break; + + case elfcpp::R_POWERPC_REL24: + case elfcpp::R_PPC_LOCAL24PC: + case elfcpp::R_PPC_REL16: + case elfcpp::R_PPC_REL16_LO: + case elfcpp::R_PPC_REL16_HI: + case elfcpp::R_PPC_REL16_HA: + { + if (gsym->needs_plt_entry()) + target->make_plt_entry(symtab, layout, gsym); + // Make a dynamic relocation if necessary. + int flags = Symbol::NON_PIC_REF; + if (gsym->type() == elfcpp::STT_FUNC) + flags |= Symbol::FUNCTION_CALL; + if (gsym->needs_dynamic_reloc(flags)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, + reloc); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + check_non_pic(object, r_type); + rela_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + } + break; + + case elfcpp::R_POWERPC_GOT16: + case elfcpp::R_POWERPC_GOT16_LO: + case elfcpp::R_POWERPC_GOT16_HI: + case elfcpp::R_POWERPC_GOT16_HA: + case elfcpp::R_PPC64_TOC16: + case elfcpp::R_PPC64_TOC16_LO: + case elfcpp::R_PPC64_TOC16_HI: + case elfcpp::R_PPC64_TOC16_HA: + case elfcpp::R_PPC64_TOC16_DS: + case elfcpp::R_PPC64_TOC16_LO_DS: + { + // The symbol requires a GOT entry. + Output_data_got<size, big_endian>* got; + + got = target->got_section(symtab, layout); + if (gsym->final_value_is_known()) + got->add_global(gsym, GOT_TYPE_STANDARD); + else + { + // If this symbol is not fully resolved, we need to add a + // dynamic relocation for it. + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_POWERPC_GLOB_DAT); + else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) + { + unsigned int off = got->add_constant(0); + + gsym->set_got_offset(GOT_TYPE_STANDARD, off); + rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, + got, off, 0); + } + } + } + break; + + case elfcpp::R_PPC64_TOC: + // We need a GOT section. + target->got_section(symtab, layout); + break; + + case elfcpp::R_POWERPC_GOT_TPREL16: + case elfcpp::R_POWERPC_TLS: + // XXX TLS + break; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_POWERPC_COPY: + case elfcpp::R_POWERPC_GLOB_DAT: + case elfcpp::R_POWERPC_JMP_SLOT: + case elfcpp::R_POWERPC_RELATIVE: + case elfcpp::R_POWERPC_DTPMOD: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + default: + unsupported_reloc_global(object, r_type, gsym); + break; + } +} + +// Scan relocations for a section. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::scan_relocs( + const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + typedef Target_powerpc<size, big_endian> Powerpc; + typedef typename Target_powerpc<size, big_endian>::Scan Scan; + static Output_data_space* sdata; + + if (sh_type == elfcpp::SHT_REL) + { + gold_error(_("%s: unsupported REL reloc section"), + object->name().c_str()); + return; + } + + // Define _SDA_BASE_ at the start of the .sdata section. + if (sdata == NULL) + { + // layout->find_output_section(".sdata") == NULL + sdata = new Output_data_space(4, "** sdata"); + Output_section* os = layout->add_output_section_data(".sdata", 0, + elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE, + sdata); + symtab->define_in_output_data("_SDA_BASE_", NULL, + os, + 32768, 0, + elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + gold::scan_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>( + options, + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + +// Finalize the sections. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::do_finalize_sections(Layout* layout) +{ + // Fill in some more dynamic tags. + Output_data_dynamic* const odyn = layout->dynamic_data(); + if (odyn != NULL) + { + if (this->plt_ != NULL) + { + const Output_data* od = this->plt_->rel_plt(); + odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); + odyn->add_section_address(elfcpp::DT_JMPREL, od); + odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); + + odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); + } + + if (this->rela_dyn_ != NULL) + { + const Output_data* od = this->rela_dyn_; + odyn->add_section_address(elfcpp::DT_RELA, od); + odyn->add_section_size(elfcpp::DT_RELASZ, od); + odyn->add_constant(elfcpp::DT_RELAENT, + elfcpp::Elf_sizes<size>::rela_size); + } + + if (!parameters->options().shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } + } + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. + if (this->copy_relocs_.any_saved_relocs()) + this->copy_relocs_.emit(this->rela_dyn_section(layout)); +} + +// Perform a relocation. + +template<int size, bool big_endian> +inline bool +Target_powerpc<size, big_endian>::Relocate::relocate( + const Relocate_info<size, big_endian>* relinfo, + Target_powerpc* target, + size_t relnum, + const elfcpp::Rela<size, big_endian>& rela, + unsigned int r_type, + const Sized_symbol<size>* gsym, + const Symbol_value<size>* psymval, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr address, + section_size_type /* view_size */) +{ + const unsigned int toc_base_offset = 0x8000; + typedef Powerpc_relocate_functions<size, big_endian> Reloc; + + // Pick the value to use for symbols defined in shared objects. + Symbol_value<size> symval; + if (gsym != NULL + && gsym->use_plt_offset(r_type == elfcpp::R_POWERPC_REL24 + || r_type == elfcpp::R_PPC_LOCAL24PC + || r_type == elfcpp::R_PPC_REL16 + || r_type == elfcpp::R_PPC_REL16_LO + || r_type == elfcpp::R_PPC_REL16_HI + || r_type == elfcpp::R_PPC_REL16_HA)) + { + elfcpp::Elf_Xword value; + + value = target->plt_section()->address() + gsym->plt_offset(); + + symval.set_output_value(value); + + psymval = &symval; + } + + const Sized_relobj<size, big_endian>* object = relinfo->object; + elfcpp::Elf_Xword addend = rela.get_r_addend(); + + // Get the GOT offset if needed. Unlike i386 and x86_64, our GOT + // pointer points to the beginning, not the end, of the table. + // So we just use the plain offset. + bool have_got_offset = false; + unsigned int got_offset = 0; + unsigned int got2_offset = 0; + switch (r_type) + { + case elfcpp::R_PPC64_TOC16: + case elfcpp::R_PPC64_TOC16_LO: + case elfcpp::R_PPC64_TOC16_HI: + case elfcpp::R_PPC64_TOC16_HA: + case elfcpp::R_PPC64_TOC16_DS: + case elfcpp::R_PPC64_TOC16_LO_DS: + // Subtract the TOC base address. + addend -= target->toc_section()->address() + toc_base_offset; + /* FALLTHRU */ + + case elfcpp::R_POWERPC_GOT16: + case elfcpp::R_POWERPC_GOT16_LO: + case elfcpp::R_POWERPC_GOT16_HI: + case elfcpp::R_POWERPC_GOT16_HA: + case elfcpp::R_PPC64_GOT16_DS: + case elfcpp::R_PPC64_GOT16_LO_DS: + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = gsym->got_offset(GOT_TYPE_STANDARD); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); + got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD); + } + have_got_offset = true; + break; + + // R_PPC_PLTREL24 is rather special. If non-zero, + // the addend specifies the GOT pointer offset within .got2. + case elfcpp::R_PPC_PLTREL24: + if (addend >= 32768) + { + Output_data_space* got2; + got2 = target->got2_section(); + got2_offset = got2->offset(); + addend += got2_offset; + } + have_got_offset = true; + break; + + default: + break; + } + + switch (r_type) + { + case elfcpp::R_POWERPC_NONE: + case elfcpp::R_POWERPC_GNU_VTINHERIT: + case elfcpp::R_POWERPC_GNU_VTENTRY: + break; + + case elfcpp::R_POWERPC_REL32: + Reloc::rel32(view, object, psymval, addend, address); + break; + + case elfcpp::R_POWERPC_REL24: + Reloc::rel24(view, object, psymval, addend, address); + break; + + case elfcpp::R_POWERPC_REL14: + Reloc::rel14(view, object, psymval, addend, address); + break; + + case elfcpp::R_PPC_PLTREL24: + Reloc::rel24(view, object, psymval, addend, address); + break; + + case elfcpp::R_PPC_LOCAL24PC: + Reloc::rel24(view, object, psymval, addend, address); + break; + + case elfcpp::R_PPC64_ADDR64: + if (!parameters->options().output_is_position_independent()) + Relocate_functions<size, big_endian>::rela64(view, object, + psymval, addend); + break; + + case elfcpp::R_POWERPC_ADDR32: + if (!parameters->options().output_is_position_independent()) + Relocate_functions<size, big_endian>::rela32(view, object, + psymval, addend); + break; + + case elfcpp::R_POWERPC_ADDR16_LO: + Reloc::addr16_lo(view, object, psymval, addend); + break; + + case elfcpp::R_POWERPC_ADDR16_HI: + Reloc::addr16_hi(view, object, psymval, addend); + break; + + case elfcpp::R_POWERPC_ADDR16_HA: + Reloc::addr16_ha(view, object, psymval, addend); + break; + + case elfcpp::R_PPC_REL16_LO: + Reloc::rel16_lo(view, object, psymval, addend, address); + break; + + case elfcpp::R_PPC_REL16_HI: + Reloc::rel16_lo(view, object, psymval, addend, address); + break; + + case elfcpp::R_PPC_REL16_HA: + Reloc::rel16_lo(view, object, psymval, addend, address); + break; + + case elfcpp::R_POWERPC_GOT16: + Reloc::addr16(view, got_offset, addend); + break; + + case elfcpp::R_POWERPC_GOT16_LO: + Reloc::addr16_lo(view, got_offset, addend); + break; + + case elfcpp::R_POWERPC_GOT16_HI: + Reloc::addr16_hi(view, got_offset, addend); + break; + + case elfcpp::R_POWERPC_GOT16_HA: + Reloc::addr16_ha(view, got_offset, addend); + break; + + case elfcpp::R_PPC64_TOC16: + Reloc::addr16(view, got_offset, addend); + break; + + case elfcpp::R_PPC64_TOC16_LO: + Reloc::addr16_lo(view, got_offset, addend); + break; + + case elfcpp::R_PPC64_TOC16_HI: + Reloc::addr16_hi(view, got_offset, addend); + break; + + case elfcpp::R_PPC64_TOC16_HA: + Reloc::addr16_ha(view, got_offset, addend); + break; + + case elfcpp::R_PPC64_TOC16_DS: + case elfcpp::R_PPC64_TOC16_LO_DS: + Reloc::addr16_ds(view, got_offset, addend); + break; + + case elfcpp::R_PPC64_TOC: + { + elfcpp::Elf_types<64>::Elf_Addr value; + value = target->toc_section()->address() + toc_base_offset; + Relocate_functions<64, false>::rela64(view, value, addend); + } + break; + + case elfcpp::R_POWERPC_COPY: + case elfcpp::R_POWERPC_GLOB_DAT: + case elfcpp::R_POWERPC_JMP_SLOT: + case elfcpp::R_POWERPC_RELATIVE: + // This is an outstanding tls reloc, which is unexpected when + // linking. + case elfcpp::R_POWERPC_DTPMOD: + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unexpected reloc %u in object file"), + r_type); + break; + + default: + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + } + + return true; +} + +// Perform a TLS relocation. + +template<int size, bool big_endian> +inline void +Target_powerpc<size, big_endian>::Relocate::relocate_tls( + const Relocate_info<size, big_endian>* relinfo, + Target_powerpc<size, big_endian>* target, + size_t relnum, + const elfcpp::Rela<size, big_endian>& rela, + unsigned int r_type, + const Sized_symbol<size>* gsym, + const Symbol_value<size>* psymval, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr address, + section_size_type) +{ + Output_segment* tls_segment = relinfo->layout->tls_segment(); + typedef Powerpc_relocate_functions<size, big_endian> Reloc; + const Sized_relobj<size, big_endian>* object = relinfo->object; + + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + typename elfcpp::Elf_types<size>::Elf_Addr value = psymval->value(object, 0); + + const bool is_final = + (gsym == NULL + ? !parameters->options().output_is_position_independent() + : gsym->final_value_is_known()); + const tls::Tls_optimization optimized_type + = optimize_tls_reloc(is_final, r_type); + + switch (r_type) + { + // XXX + } +} + +// Relocate section data. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::relocate_section( + const Relocate_info<size, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr address, + section_size_type view_size) +{ + typedef Target_powerpc<size, big_endian> Powerpc; + typedef typename Target_powerpc<size, big_endian>::Relocate Powerpc_relocate; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_section<size, big_endian, Powerpc, elfcpp::SHT_RELA, + Powerpc_relocate>( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size); +} + +// Return the size of a relocation while scanning during a relocatable +// link. + +template<int size, bool big_endian> +unsigned int +Target_powerpc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc( + unsigned int, + Relobj*) +{ + // We are always SHT_RELA, so we should never get here. + gold_unreachable(); + return 0; +} + +// Scan the relocs during a relocatable link. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::scan_relocatable_relocs( + const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA, + Relocatable_size_for_reloc> Scan_relocatable_relocs; + + gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA, + Scan_relocatable_relocs>( + options, + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); +} + +// Relocate a section during a relocatable link. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::relocate_for_relocatable( + const Relocate_info<size, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs* rr, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_for_relocatable<size, big_endian, elfcpp::SHT_RELA>( + relinfo, + prelocs, + reloc_count, + output_section, + offset_in_output_section, + rr, + view, + view_address, + view_size, + reloc_view, + reloc_view_size); +} + +// Return the value to use for a dynamic which requires special +// treatment. This is how we support equality comparisons of function +// pointers across shared library boundaries, as described in the +// processor specific ABI supplement. + +template<int size, bool big_endian> +uint64_t +Target_powerpc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const +{ + gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset()); + return this->plt_section()->address() + gsym->plt_offset(); +} + +// The selector for powerpc object files. + +template<int size, bool big_endian> +class Target_selector_powerpc : public Target_selector +{ +public: + Target_selector_powerpc() + : Target_selector(elfcpp::EM_NONE, size, big_endian, + (size == 64 ? + (big_endian ? "elf64-powerpc" : "elf64-powerpcle") : + (big_endian ? "elf32-powerpc" : "elf32-powerpcle"))) + { } + + Target* instantiated_target_; + + Target* do_recognize(int machine, int, int) + { + switch (size) + { + case 64: + if (machine != elfcpp::EM_PPC64) + return NULL; + break; + + case 32: + if (machine != elfcpp::EM_PPC) + return NULL; + break; + + default: + return NULL; + } + + return do_instantiate_target(); + } + + Target* do_instantiate_target() + { + if (this->instantiated_target_ == NULL) + this->instantiated_target_ = new Target_powerpc<size, big_endian>(); + return this->instantiated_target_; + } +}; + +Target_selector_powerpc<32, true> target_selector_ppc32; +Target_selector_powerpc<32, false> target_selector_ppc32le; +Target_selector_powerpc<64, true> target_selector_ppc64; +Target_selector_powerpc<64, false> target_selector_ppc64le; + +} // End anonymous namespace. diff --git a/gold/sparc.cc b/gold/sparc.cc new file mode 100644 index 00000000000..7da59dd3f84 --- /dev/null +++ b/gold/sparc.cc @@ -0,0 +1,3200 @@ +// sparc.cc -- sparc target support for gold. + +// Copyright 2008 Free Software Foundation, Inc. +// Written by David S. Miller <davem@davemloft.net>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstdlib> +#include <cstdio> +#include <cstring> + +#include "elfcpp.h" +#include "parameters.h" +#include "reloc.h" +#include "sparc.h" +#include "object.h" +#include "symtab.h" +#include "layout.h" +#include "output.h" +#include "copy-relocs.h" +#include "target.h" +#include "target-reloc.h" +#include "target-select.h" +#include "tls.h" +#include "errors.h" + +namespace +{ + +using namespace gold; + +template<int size, bool big_endian> +class Output_data_plt_sparc; + +template<int size, bool big_endian> +class Target_sparc : public Sized_target<size, big_endian> +{ + public: + typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Reloc_section; + + Target_sparc() + : Sized_target<size, big_endian>(&sparc_info), + got_(NULL), plt_(NULL), rela_dyn_(NULL), + copy_relocs_(elfcpp::R_SPARC_COPY), dynbss_(NULL), + got_mod_index_offset_(-1U), tls_get_addr_sym_(NULL) + { + } + + // Scan the relocations to look for symbol adjustments. + void + scan_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + // Finalize the sections. + void + do_finalize_sections(Layout*); + + // Return the value to use for a dynamic which requires special + // treatment. + uint64_t + do_dynsym_value(const Symbol*) const; + + // Relocate a section. + void + relocate_section(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size); + + // Scan the relocs during a relocatable link. + void + scan_relocatable_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs*); + + // Relocate a section during a relocatable link. + void + relocate_for_relocatable(const Relocate_info<size, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); + // Return whether SYM is defined by the ABI. + bool + do_is_defined_by_abi(Symbol* sym) const + { + // XXX Really need to support this better... + if (sym->type() == elfcpp::STT_SPARC_REGISTER) + return 1; + + return strcmp(sym->name(), "___tls_get_addr") == 0; + } + + // Return the size of the GOT section. + section_size_type + got_size() + { + gold_assert(this->got_ != NULL); + return this->got_->data_size(); + } + + private: + + // The class which scans relocations. + class Scan + { + public: + Scan() + : issued_non_pic_error_(false) + { } + + inline void + local(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_sparc* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type, + const elfcpp::Sym<size, big_endian>& lsym); + + inline void + global(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_sparc* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type, + Symbol* gsym); + + private: + static void + unsupported_reloc_local(Sized_relobj<size, big_endian>*, + unsigned int r_type); + + static void + unsupported_reloc_global(Sized_relobj<size, big_endian>*, + unsigned int r_type, Symbol*); + + static void + generate_tls_call(Symbol_table* symtab, Layout* layout, + Target_sparc* target); + + void + check_non_pic(Relobj*, unsigned int r_type); + + // Whether we have issued an error about a non-PIC compilation. + bool issued_non_pic_error_; + }; + + // The class which implements relocation. + class Relocate + { + public: + Relocate() + : ignore_gd_add_(false) + { } + + ~Relocate() + { + if (this->ignore_gd_add_) + { + // FIXME: This needs to specify the location somehow. + gold_error(_("missing expected TLS relocation")); + } + } + + // Do a relocation. Return false if the caller should not issue + // any warnings about this relocation. + inline bool + relocate(const Relocate_info<size, big_endian>*, Target_sparc*, + size_t relnum, const elfcpp::Rela<size, big_endian>&, + unsigned int r_type, const Sized_symbol<size>*, + const Symbol_value<size>*, + unsigned char*, + typename elfcpp::Elf_types<size>::Elf_Addr, + section_size_type); + + private: + // Do a TLS relocation. + inline void + relocate_tls(const Relocate_info<size, big_endian>*, Target_sparc* target, + size_t relnum, const elfcpp::Rela<size, big_endian>&, + unsigned int r_type, const Sized_symbol<size>*, + const Symbol_value<size>*, + unsigned char*, + typename elfcpp::Elf_types<size>::Elf_Addr, + section_size_type); + + // Ignore the next relocation which should be R_SPARC_TLS_GD_ADD + bool ignore_gd_add_; + }; + + // A class which returns the size required for a relocation type, + // used while scanning relocs during a relocatable link. + class Relocatable_size_for_reloc + { + public: + unsigned int + get_size_for_reloc(unsigned int, Relobj*); + }; + + // Get the GOT section, creating it if necessary. + Output_data_got<size, big_endian>* + got_section(Symbol_table*, Layout*); + + // Create a PLT entry for a global symbol. + void + make_plt_entry(Symbol_table*, Layout*, Symbol*); + + // Create a GOT entry for the TLS module index. + unsigned int + got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<size, big_endian>* object); + + // Return the gsym for "__tls_get_addr". Cache if not already + // cached. + Symbol* + tls_get_addr_sym(Symbol_table* symtab) + { + if (!this->tls_get_addr_sym_) + this->tls_get_addr_sym_ = symtab->lookup("__tls_get_addr", NULL); + gold_assert(this->tls_get_addr_sym_); + return this->tls_get_addr_sym_; + } + + // Get the PLT section. + const Output_data_plt_sparc<size, big_endian>* + plt_section() const + { + gold_assert(this->plt_ != NULL); + return this->plt_; + } + + // Get the dynamic reloc section, creating it if necessary. + Reloc_section* + rela_dyn_section(Layout*); + + // Return true if the symbol may need a COPY relocation. + // References from an executable object to non-function symbols + // defined in a dynamic object may need a COPY relocation. + bool + may_need_copy_reloc(Symbol* gsym) + { + return (!parameters->options().shared() + && gsym->is_from_dynobj() + && gsym->type() != elfcpp::STT_FUNC); + } + + // Copy a relocation against a global symbol. + void + copy_reloc(Symbol_table* symtab, Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int shndx, Output_section* output_section, + Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc) + { + this->copy_relocs_.copy_reloc(symtab, layout, + symtab->get_sized_symbol<size>(sym), + object, shndx, output_section, + reloc, this->rela_dyn_section(layout)); + } + + // Information about this specific target which we pass to the + // general Target structure. + static Target::Target_info sparc_info; + + // The types of GOT entries needed for this platform. + enum Got_type + { + GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol + GOT_TYPE_TLS_OFFSET = 1, // GOT entry for TLS offset + GOT_TYPE_TLS_PAIR = 2, // GOT entry for TLS module/offset pair + }; + + // The GOT section. + Output_data_got<size, big_endian>* got_; + // The PLT section. + Output_data_plt_sparc<size, big_endian>* plt_; + // The dynamic reloc section. + Reloc_section* rela_dyn_; + // Relocs saved to avoid a COPY reloc. + Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_; + // Space for variables copied with a COPY reloc. + Output_data_space* dynbss_; + // Offset of the GOT entry for the TLS module index; + unsigned int got_mod_index_offset_; + // Cached pointer to __tls_get_addr symbol + Symbol* tls_get_addr_sym_; +}; + +template<> +Target::Target_info Target_sparc<32, true>::sparc_info = +{ + 32, // size + true, // is_big_endian + elfcpp::EM_SPARC, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/ld.so.1", // dynamic_linker + 0x00010000, // default_text_segment_address + 64 * 1024, // abi_pagesize (overridable by -z max-page-size) + 8 * 1024 // common_pagesize (overridable by -z common-page-size) +}; + +template<> +Target::Target_info Target_sparc<64, true>::sparc_info = +{ + 64, // size + true, // is_big_endian + elfcpp::EM_SPARCV9, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/sparcv9/ld.so.1", // dynamic_linker + 0x100000, // default_text_segment_address + 64 * 1024, // abi_pagesize (overridable by -z max-page-size) + 8 * 1024 // common_pagesize (overridable by -z common-page-size) +}; + +// We have to take care here, even when operating in little-endian +// mode, sparc instructions are still big endian. +template<int size, bool big_endian> +class Sparc_relocate_functions +{ +private: + // Do a simple relocation with the addend in the relocation. + template<int valsize> + static inline void + rela(unsigned char* view, + unsigned int right_shift, + typename elfcpp::Elf_types<valsize>::Elf_Addr dst_mask, + typename elfcpp::Swap<size, big_endian>::Valtype value, + typename elfcpp::Swap<size, big_endian>::Valtype addend) + { + typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv); + Valtype reloc = ((value + addend) >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap<valsize, big_endian>::writeval(wv, val | reloc); + } + + // Do a simple relocation using a symbol value with the addend in + // the relocation. + template<int valsize> + static inline void + rela(unsigned char* view, + unsigned int right_shift, + typename elfcpp::Elf_types<valsize>::Elf_Addr dst_mask, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<valsize, big_endian>::Valtype addend) + { + typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv); + Valtype reloc = (psymval->value(object, addend) >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap<valsize, big_endian>::writeval(wv, val | reloc); + } + + // Do a simple relocation using a symbol value with the addend in + // the relocation, unaligned. + template<int valsize> + static inline void + rela_ua(unsigned char* view, + unsigned int right_shift, elfcpp::Elf_Xword dst_mask, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<size, big_endian>::Valtype addend) + { + typedef typename elfcpp::Swap_unaligned<valsize, + big_endian>::Valtype Valtype; + unsigned char* wv = view; + Valtype val = elfcpp::Swap_unaligned<valsize, big_endian>::readval(wv); + Valtype reloc = (psymval->value(object, addend) >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap_unaligned<valsize, big_endian>::writeval(wv, val | reloc); + } + + // Do a simple PC relative relocation with a Symbol_value with the + // addend in the relocation. + template<int valsize> + static inline void + pcrela(unsigned char* view, + unsigned int right_shift, + typename elfcpp::Elf_types<valsize>::Elf_Addr dst_mask, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<size, big_endian>::Valtype addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv); + Valtype reloc = ((psymval->value(object, addend) - address) + >> right_shift); + + val &= ~dst_mask; + reloc &= dst_mask; + + elfcpp::Swap<valsize, big_endian>::writeval(wv, val | reloc); + } + + template<int valsize> + static inline void + pcrela_unaligned(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Swap<size, big_endian>::Valtype addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + typedef typename elfcpp::Swap_unaligned<valsize, + big_endian>::Valtype Valtype; + unsigned char* wv = view; + Valtype reloc = (psymval->value(object, addend) - address); + + elfcpp::Swap_unaligned<valsize, big_endian>::writeval(wv, reloc); + } + + typedef Sparc_relocate_functions<size, big_endian> This; + typedef Sparc_relocate_functions<size, true> This_insn; + +public: + // R_SPARC_WDISP30: (Symbol + Addend - Address) >> 2 + static inline void + wdisp30(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 2, 0x3fffffff, object, + psymval, addend, address); + } + + // R_SPARC_WDISP22: (Symbol + Addend - Address) >> 2 + static inline void + wdisp22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 2, 0x003fffff, object, + psymval, addend, address); + } + + // R_SPARC_WDISP19: (Symbol + Addend - Address) >> 2 + static inline void + wdisp19(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 2, 0x0007ffff, object, + psymval, addend, address); + } + + // R_SPARC_WDISP16: (Symbol + Addend - Address) >> 2 + static inline void + wdisp16(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = ((psymval->value(object, addend) - address) + >> 2); + + // The relocation value is split between the low 14 bits, + // and bits 20-21. + val &= ~((0x3 << 20) | 0x3fff); + reloc = (((reloc & 0xc000) << (20 - 14)) + | (reloc & 0x3ffff)); + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } + + // R_SPARC_PC22: (Symbol + Addend - Address) >> 10 + static inline void + pc22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 10, 0x003fffff, object, + psymval, addend, address); + } + + // R_SPARC_PC10: (Symbol + Addend - Address) & 0x3ff + static inline void + pc10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 0, 0x000003ff, object, + psymval, addend, address); + } + + // R_SPARC_HI22: (Symbol + Addend) >> 10 + static inline void + hi22(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 10, 0x003fffff, value, addend); + } + + // R_SPARC_HI22: (Symbol + Addend) >> 10 + static inline void + hi22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 10, 0x003fffff, object, psymval, addend); + } + + // R_SPARC_PCPLT22: (Symbol + Addend - Address) >> 10 + static inline void + pcplt22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 10, 0x003fffff, object, + psymval, addend, address); + } + + // R_SPARC_LO10: (Symbol + Addend) & 0x3ff + static inline void + lo10(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x000003ff, value, addend); + } + + // R_SPARC_LO10: (Symbol + Addend) & 0x3ff + static inline void + lo10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x000003ff, object, psymval, addend); + } + + // R_SPARC_LO10: (Symbol + Addend) & 0x3ff + static inline void + lo10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 0, 0x000003ff, object, + psymval, addend, address); + } + + // R_SPARC_OLO10: ((Symbol + Addend) & 0x3ff) + Addend2 + static inline void + olo10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr addend2) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = psymval->value(object, addend); + + val &= ~0x1fff; + reloc &= 0x3ff; + reloc += addend2; + reloc &= 0x1fff; + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } + + // R_SPARC_22: (Symbol + Addend) + static inline void + rela32_22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x003fffff, object, psymval, addend); + } + + // R_SPARC_13: (Symbol + Addend) + static inline void + rela32_13(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x00001fff, value, addend); + } + + // R_SPARC_13: (Symbol + Addend) + static inline void + rela32_13(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x00001fff, object, psymval, addend); + } + + // R_SPARC_UA16: (Symbol + Addend) + static inline void + ua16(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This::template rela_ua<16>(view, 0, 0xffff, object, psymval, addend); + } + + // R_SPARC_UA32: (Symbol + Addend) + static inline void + ua32(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This::template rela_ua<32>(view, 0, 0xffffffff, object, psymval, addend); + } + + // R_SPARC_UA64: (Symbol + Addend) + static inline void + ua64(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This::template rela_ua<64>(view, 0, ~(elfcpp::Elf_Xword) 0, + object, psymval, addend); + } + + // R_SPARC_DISP8: (Symbol + Addend - Address) + static inline void + disp8(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela_unaligned<8>(view, object, psymval, + addend, address); + } + + // R_SPARC_DISP16: (Symbol + Addend - Address) + static inline void + disp16(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela_unaligned<16>(view, object, psymval, + addend, address); + } + + // R_SPARC_DISP32: (Symbol + Addend - Address) + static inline void + disp32(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela_unaligned<32>(view, object, psymval, + addend, address); + } + + // R_SPARC_DISP64: (Symbol + Addend - Address) + static inline void + disp64(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + elfcpp::Elf_Xword addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This::template pcrela_unaligned<64>(view, object, psymval, + addend, address); + } + + // R_SPARC_H44: (Symbol + Addend) >> 22 + static inline void + h44(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 22, 0x003fffff, object, psymval, addend); + } + + // R_SPARC_M44: ((Symbol + Addend) >> 12) & 0x3ff + static inline void + m44(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 12, 0x000003ff, object, psymval, addend); + } + + // R_SPARC_L44: (Symbol + Addend) & 0xfff + static inline void + l44(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x00000fff, object, psymval, addend); + } + + // R_SPARC_HH22: (Symbol + Addend) >> 42 + static inline void + hh22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 42, 0x003fffff, object, psymval, addend); + } + + // R_SPARC_PC_HH22: (Symbol + Addend - Address) >> 42 + static inline void + pc_hh22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 42, 0x003fffff, object, + psymval, addend, address); + } + + // R_SPARC_HM10: ((Symbol + Addend) >> 32) & 0x3ff + static inline void + hm10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 32, 0x000003ff, object, psymval, addend); + } + + // R_SPARC_PC_HM10: ((Symbol + Addend - Address) >> 32) & 0x3ff + static inline void + pc_hm10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend, + typename elfcpp::Elf_types<size>::Elf_Addr address) + { + This_insn::template pcrela<32>(view, 32, 0x000003ff, object, + psymval, addend, address); + } + + // R_SPARC_11: (Symbol + Addend) + static inline void + rela32_11(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x000007ff, object, psymval, addend); + } + + // R_SPARC_10: (Symbol + Addend) + static inline void + rela32_10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x000003ff, object, psymval, addend); + } + + // R_SPARC_7: (Symbol + Addend) + static inline void + rela32_7(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x0000007f, object, psymval, addend); + } + + // R_SPARC_6: (Symbol + Addend) + static inline void + rela32_6(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x0000003f, object, psymval, addend); + } + + // R_SPARC_5: (Symbol + Addend) + static inline void + rela32_5(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::template rela<32>(view, 0, 0x0000001f, object, psymval, addend); + } + + // R_SPARC_TLS_LDO_HIX22: @dtpoff(Symbol + Addend) >> 10 + static inline void + ldo_hix22(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + This_insn::hi22(view, value, addend); + } + + // R_SPARC_TLS_LDO_LOX10: @dtpoff(Symbol + Addend) & 0x3ff + static inline void + ldo_lox10(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = (value + addend); + + val &= ~0x1fff; + reloc &= 0x3ff; + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } + + // R_SPARC_TLS_LE_HIX22: (@tpoff(Symbol + Addend) ^ 0xffffffffffffffff) >> 10 + static inline void + hix22(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = (value + addend); + + val &= ~0x3fffff; + + reloc ^= ~(Valtype)0; + reloc >>= 10; + + reloc &= 0x3fffff; + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } + + // R_SPARC_HIX22: ((Symbol + Addend) ^ 0xffffffffffffffff) >> 10 + static inline void + hix22(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = psymval->value(object, addend); + + val &= ~0x3fffff; + + reloc ^= ~(Valtype)0; + reloc >>= 10; + + reloc &= 0x3fffff; + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } + + + // R_SPARC_TLS_LE_LOX10: (@tpoff(Symbol + Addend) & 0x3ff) | 0x1c00 + static inline void + lox10(unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = (value + addend); + + val &= ~0x1fff; + reloc &= 0x3ff; + reloc |= 0x1c00; + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } + + // R_SPARC_LOX10: ((Symbol + Addend) & 0x3ff) | 0x1c00 + static inline void + lox10(unsigned char* view, + const Sized_relobj<size, big_endian>* object, + const Symbol_value<size>* psymval, + typename elfcpp::Elf_types<size>::Elf_Addr addend) + { + typedef typename elfcpp::Swap<32, true>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, true>::readval(wv); + Valtype reloc = psymval->value(object, addend); + + val &= ~0x1fff; + reloc &= 0x3ff; + reloc |= 0x1c00; + + elfcpp::Swap<32, true>::writeval(wv, val | reloc); + } +}; + +// Get the GOT section, creating it if necessary. + +template<int size, bool big_endian> +Output_data_got<size, big_endian>* +Target_sparc<size, big_endian>::got_section(Symbol_table* symtab, + Layout* layout) +{ + if (this->got_ == NULL) + { + gold_assert(symtab != NULL && layout != NULL); + + this->got_ = new Output_data_got<size, big_endian>(); + + Output_section* os; + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_); + os->set_is_relro(); + + // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + this->got_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + return this->got_; +} + +// Get the dynamic reloc section, creating it if necessary. + +template<int size, bool big_endian> +typename Target_sparc<size, big_endian>::Reloc_section* +Target_sparc<size, big_endian>::rela_dyn_section(Layout* layout) +{ + if (this->rela_dyn_ == NULL) + { + gold_assert(layout != NULL); + this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); + layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->rela_dyn_); + } + return this->rela_dyn_; +} + +// A class to handle the PLT data. + +template<int size, bool big_endian> +class Output_data_plt_sparc : public Output_section_data +{ + public: + typedef Output_data_reloc<elfcpp::SHT_RELA, true, + size, big_endian> Reloc_section; + + Output_data_plt_sparc(Layout*); + + // Add an entry to the PLT. + void add_entry(Symbol* gsym); + + // Return the .rela.plt section data. + const Reloc_section* rel_plt() const + { + return this->rel_; + } + + protected: + void do_adjust_output_section(Output_section* os); + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, _("** PLT")); } + + private: + // The size of an entry in the PLT. + static const int base_plt_entry_size = (size == 32 ? 12 : 32); + + static const unsigned int plt_entries_per_block = 160; + static const unsigned int plt_insn_chunk_size = 24; + static const unsigned int plt_pointer_chunk_size = 8; + static const unsigned int plt_block_size = + (plt_entries_per_block + * (plt_insn_chunk_size + plt_pointer_chunk_size)); + + // Set the final size. + void + set_final_data_size() + { + unsigned int full_count = this->count_ + 4; + unsigned int extra = (size == 32 ? 4 : 0); + + if (size == 32 || full_count < 32768) + this->set_data_size((full_count * base_plt_entry_size) + extra); + else + { + unsigned int ext_cnt = full_count - 32768; + + this->set_data_size((32768 * base_plt_entry_size) + + (ext_cnt + * (plt_insn_chunk_size + + plt_pointer_chunk_size))); + } + } + + // Write out the PLT data. + void + do_write(Output_file*); + + // The reloc section. + Reloc_section* rel_; + // The number of PLT entries. + unsigned int count_; +}; + +// Define the constants as required by C++ standard. + +template<int size, bool big_endian> +const int Output_data_plt_sparc<size, big_endian>::base_plt_entry_size; + +template<int size, bool big_endian> +const unsigned int +Output_data_plt_sparc<size, big_endian>::plt_entries_per_block; + +template<int size, bool big_endian> +const unsigned int Output_data_plt_sparc<size, big_endian>::plt_insn_chunk_size; + +template<int size, bool big_endian> +const unsigned int +Output_data_plt_sparc<size, big_endian>::plt_pointer_chunk_size; + +template<int size, bool big_endian> +const unsigned int Output_data_plt_sparc<size, big_endian>::plt_block_size; + +// Create the PLT section. The ordinary .got section is an argument, +// since we need to refer to the start. + +template<int size, bool big_endian> +Output_data_plt_sparc<size, big_endian>::Output_data_plt_sparc(Layout* layout) + : Output_section_data(size == 32 ? 4 : 8), count_(0) +{ + this->rel_ = new Reloc_section(false); + layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->rel_); +} + +template<int size, bool big_endian> +void +Output_data_plt_sparc<size, big_endian>::do_adjust_output_section(Output_section* os) +{ + os->set_entsize(0); +} + +// Add an entry to the PLT. + +template<int size, bool big_endian> +void +Output_data_plt_sparc<size, big_endian>::add_entry(Symbol* gsym) +{ + gold_assert(!gsym->has_plt_offset()); + + unsigned int index = this->count_ + 4; + section_offset_type plt_offset; + + if (size == 32 || index < 32768) + plt_offset = index * base_plt_entry_size; + else + { + unsigned int ext_index = index - 32768; + + plt_offset = (32768 * base_plt_entry_size) + + ((ext_index / plt_entries_per_block) + * plt_block_size) + + ((ext_index % plt_entries_per_block) + * plt_insn_chunk_size); + } + + gsym->set_plt_offset(plt_offset); + + ++this->count_; + + // Every PLT entry needs a reloc. + gsym->set_needs_dynsym_entry(); + this->rel_->add_global(gsym, elfcpp::R_SPARC_JMP_SLOT, this, + plt_offset, 0); + + // Note that we don't need to save the symbol. The contents of the + // PLT are independent of which symbols are used. The symbols only + // appear in the relocations. +} + +static const unsigned int sparc_nop = 0x01000000; +static const unsigned int sparc_sethi_g1 = 0x03000000; +static const unsigned int sparc_branch_always = 0x30800000; +static const unsigned int sparc_branch_always_pt = 0x30680000; +static const unsigned int sparc_mov = 0x80100000; +static const unsigned int sparc_mov_g0_o0 = 0x90100000; +static const unsigned int sparc_mov_o7_g5 = 0x8a10000f; +static const unsigned int sparc_call_plus_8 = 0x40000002; +static const unsigned int sparc_ldx_o7_imm_g1 = 0xc25be000; +static const unsigned int sparc_jmpl_o7_g1_g1 = 0x83c3c001; +static const unsigned int sparc_mov_g5_o7 = 0x9e100005; + +// Write out the PLT. + +template<int size, bool big_endian> +void +Output_data_plt_sparc<size, big_endian>::do_write(Output_file* of) +{ + const off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + unsigned char* pov = oview; + + memset(pov, 0, base_plt_entry_size * 4); + pov += base_plt_entry_size * 4; + + unsigned int plt_offset = base_plt_entry_size * 4; + const unsigned int count = this->count_; + + if (size == 64) + { + unsigned int limit; + + limit = (count > 32768 ? 32768 : count); + + for (unsigned int i = 0; i < limit; ++i) + { + elfcpp::Swap<32, true>::writeval(pov + 0x00, + sparc_sethi_g1 + plt_offset); + elfcpp::Swap<32, true>::writeval(pov + 0x04, + sparc_branch_always_pt + + (((base_plt_entry_size - + (plt_offset + 4)) >> 2) & + 0x7ffff)); + elfcpp::Swap<32, true>::writeval(pov + 0x08, sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x0c, sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x10, sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x14, sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x18, sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x1c, sparc_nop); + + pov += base_plt_entry_size; + plt_offset += base_plt_entry_size; + } + + if (count > 32768) + { + unsigned int ext_cnt = count - 32768; + unsigned int blks = ext_cnt / plt_entries_per_block; + + for (unsigned int i = 0; i < blks; ++i) + { + unsigned int data_off = (plt_entries_per_block + * plt_insn_chunk_size) - 4; + + for (unsigned int j = 0; j < plt_entries_per_block; ++j) + { + elfcpp::Swap<32, true>::writeval(pov + 0x00, + sparc_mov_o7_g5); + elfcpp::Swap<32, true>::writeval(pov + 0x04, + sparc_call_plus_8); + elfcpp::Swap<32, true>::writeval(pov + 0x08, + sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x0c, + sparc_ldx_o7_imm_g1 + + (data_off & 0x1fff)); + elfcpp::Swap<32, true>::writeval(pov + 0x10, + sparc_jmpl_o7_g1_g1); + elfcpp::Swap<32, true>::writeval(pov + 0x14, + sparc_mov_g5_o7); + + elfcpp::Swap<64, big_endian>::writeval( + pov + 0x4 + data_off, + (elfcpp::Elf_Xword) (oview - (pov + 0x04))); + + pov += plt_insn_chunk_size; + data_off -= 16; + } + } + + unsigned int sub_blk_cnt = ext_cnt % plt_entries_per_block; + for (unsigned int i = 0; i < sub_blk_cnt; ++i) + { + unsigned int data_off = (sub_blk_cnt + * plt_insn_chunk_size) - 4; + + for (unsigned int j = 0; j < plt_entries_per_block; ++j) + { + elfcpp::Swap<32, true>::writeval(pov + 0x00, + sparc_mov_o7_g5); + elfcpp::Swap<32, true>::writeval(pov + 0x04, + sparc_call_plus_8); + elfcpp::Swap<32, true>::writeval(pov + 0x08, + sparc_nop); + elfcpp::Swap<32, true>::writeval(pov + 0x0c, + sparc_ldx_o7_imm_g1 + + (data_off & 0x1fff)); + elfcpp::Swap<32, true>::writeval(pov + 0x10, + sparc_jmpl_o7_g1_g1); + elfcpp::Swap<32, true>::writeval(pov + 0x14, + sparc_mov_g5_o7); + + elfcpp::Swap<64, big_endian>::writeval( + pov + 0x4 + data_off, + (elfcpp::Elf_Xword) (oview - (pov + 0x04))); + + pov += plt_insn_chunk_size; + data_off -= 16; + } + } + } + } + else + { + for (unsigned int i = 0; i < count; ++i) + { + elfcpp::Swap<32, true>::writeval(pov + 0x00, + sparc_sethi_g1 + plt_offset); + elfcpp::Swap<32, true>::writeval(pov + 0x04, + sparc_branch_always + + (((- (plt_offset + 4)) >> 2) & + 0x003fffff)); + elfcpp::Swap<32, true>::writeval(pov + 0x08, sparc_nop); + + pov += base_plt_entry_size; + plt_offset += base_plt_entry_size; + } + + elfcpp::Swap<32, true>::writeval(pov, sparc_nop); + pov += 4; + } + + gold_assert(static_cast<section_size_type>(pov - oview) == oview_size); + + of->write_output_view(offset, oview_size, oview); +} + +// Create a PLT entry for a global symbol. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab, + Layout* layout, + Symbol* gsym) +{ + if (gsym->has_plt_offset()) + return; + + if (this->plt_ == NULL) + { + // Create the GOT sections first. + this->got_section(symtab, layout); + + this->plt_ = new Output_data_plt_sparc<size, big_endian>(layout); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR + | elfcpp::SHF_WRITE), + this->plt_); + + // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. + symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, + this->plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + this->plt_->add_entry(gsym); +} + +// Create a GOT entry for the TLS module index. + +template<int size, bool big_endian> +unsigned int +Target_sparc<size, big_endian>::got_mod_index_entry(Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object) +{ + if (this->got_mod_index_offset_ == -1U) + { + gold_assert(symtab != NULL && layout != NULL && object != NULL); + Reloc_section* rela_dyn = this->rela_dyn_section(layout); + Output_data_got<size, big_endian>* got; + unsigned int got_offset; + + got = this->got_section(symtab, layout); + got_offset = got->add_constant(0); + rela_dyn->add_local(object, 0, + (size == 64 ? + elfcpp::R_SPARC_TLS_DTPMOD64 : + elfcpp::R_SPARC_TLS_DTPMOD32), got, + got_offset, 0); + got->add_constant(0); + this->got_mod_index_offset_ = got_offset; + } + return this->got_mod_index_offset_; +} + +// Optimize the TLS relocation type based on what we know about the +// symbol. IS_FINAL is true if the final address of this symbol is +// known at link time. + +static tls::Tls_optimization +optimize_tls_reloc(bool is_final, int r_type) +{ + // If we are generating a shared library, then we can't do anything + // in the linker. + if (parameters->options().shared()) + return tls::TLSOPT_NONE; + + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + // These are General-Dynamic which permits fully general TLS + // access. Since we know that we are generating an executable, + // we can convert this to Initial-Exec. If we also know that + // this is a local symbol, we can further switch to Local-Exec. + if (is_final) + return tls::TLSOPT_TO_LE; + return tls::TLSOPT_TO_IE; + + case elfcpp::R_SPARC_TLS_LDM_HI22: // Local-dynamic + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + // This is Local-Dynamic, which refers to a local symbol in the + // dynamic TLS block. Since we know that we generating an + // executable, we can switch to Local-Exec. + return tls::TLSOPT_TO_LE; + + case elfcpp::R_SPARC_TLS_LDO_HIX22: // Alternate local-dynamic + case elfcpp::R_SPARC_TLS_LDO_LOX10: + case elfcpp::R_SPARC_TLS_LDO_ADD: + // Another type of Local-Dynamic relocation. + return tls::TLSOPT_TO_LE; + + case elfcpp::R_SPARC_TLS_IE_HI22: // Initial-exec + case elfcpp::R_SPARC_TLS_IE_LO10: + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + // These are Initial-Exec relocs which get the thread offset + // from the GOT. If we know that we are linking against the + // local symbol, we can switch to Local-Exec, which links the + // thread offset into the instruction. + if (is_final) + return tls::TLSOPT_TO_LE; + return tls::TLSOPT_NONE; + + case elfcpp::R_SPARC_TLS_LE_HIX22: // Local-exec + case elfcpp::R_SPARC_TLS_LE_LOX10: + // When we already have Local-Exec, there is nothing further we + // can do. + return tls::TLSOPT_NONE; + + default: + gold_unreachable(); + } +} + +// Generate a PLT entry slot for a call to __tls_get_addr +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::Scan::generate_tls_call(Symbol_table* symtab, + Layout* layout, + Target_sparc<size, big_endian>* target) +{ + Symbol* gsym = target->tls_get_addr_sym(symtab); + + target->make_plt_entry(symtab, layout, gsym); +} + +// Report an unsupported relocation against a local symbol. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::Scan::unsupported_reloc_local( + Sized_relobj<size, big_endian>* object, + unsigned int r_type) +{ + gold_error(_("%s: unsupported reloc %u against local symbol"), + object->name().c_str(), r_type); +} + +// We are about to emit a dynamic relocation of type R_TYPE. If the +// dynamic linker does not support it, issue an error. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int r_type) +{ + gold_assert(r_type != elfcpp::R_SPARC_NONE); + + if (size == 64) + { + switch (r_type) + { + // These are the relocation types supported by glibc for sparc 64-bit. + case elfcpp::R_SPARC_RELATIVE: + case elfcpp::R_SPARC_COPY: + case elfcpp::R_SPARC_64: + case elfcpp::R_SPARC_GLOB_DAT: + case elfcpp::R_SPARC_JMP_SLOT: + case elfcpp::R_SPARC_TLS_DTPMOD64: + case elfcpp::R_SPARC_TLS_DTPOFF64: + case elfcpp::R_SPARC_TLS_TPOFF64: + case elfcpp::R_SPARC_TLS_LE_HIX22: + case elfcpp::R_SPARC_TLS_LE_LOX10: + case elfcpp::R_SPARC_8: + case elfcpp::R_SPARC_16: + case elfcpp::R_SPARC_DISP8: + case elfcpp::R_SPARC_DISP16: + case elfcpp::R_SPARC_DISP32: + case elfcpp::R_SPARC_WDISP30: + case elfcpp::R_SPARC_LO10: + case elfcpp::R_SPARC_HI22: + case elfcpp::R_SPARC_OLO10: + case elfcpp::R_SPARC_H44: + case elfcpp::R_SPARC_M44: + case elfcpp::R_SPARC_L44: + case elfcpp::R_SPARC_HH22: + case elfcpp::R_SPARC_HM10: + case elfcpp::R_SPARC_LM22: + case elfcpp::R_SPARC_UA16: + case elfcpp::R_SPARC_UA32: + case elfcpp::R_SPARC_UA64: + return; + + default: + break; + } + } + else + { + switch (r_type) + { + // These are the relocation types supported by glibc for sparc 32-bit. + case elfcpp::R_SPARC_RELATIVE: + case elfcpp::R_SPARC_COPY: + case elfcpp::R_SPARC_GLOB_DAT: + case elfcpp::R_SPARC_32: + case elfcpp::R_SPARC_JMP_SLOT: + case elfcpp::R_SPARC_TLS_DTPMOD32: + case elfcpp::R_SPARC_TLS_DTPOFF32: + case elfcpp::R_SPARC_TLS_TPOFF32: + case elfcpp::R_SPARC_TLS_LE_HIX22: + case elfcpp::R_SPARC_TLS_LE_LOX10: + case elfcpp::R_SPARC_8: + case elfcpp::R_SPARC_16: + case elfcpp::R_SPARC_DISP8: + case elfcpp::R_SPARC_DISP16: + case elfcpp::R_SPARC_DISP32: + case elfcpp::R_SPARC_LO10: + case elfcpp::R_SPARC_WDISP30: + case elfcpp::R_SPARC_HI22: + case elfcpp::R_SPARC_UA16: + case elfcpp::R_SPARC_UA32: + return; + + default: + break; + } + } + + // This prevents us from issuing more than one error per reloc + // section. But we can still wind up issuing more than one + // error per object file. + if (this->issued_non_pic_error_) + return; + object->error(_("requires unsupported dynamic reloc; " + "recompile with -fPIC")); + this->issued_non_pic_error_ = true; + return; +} + +// Scan a relocation for a local symbol. + +template<int size, bool big_endian> +inline void +Target_sparc<size, big_endian>::Scan::local( + const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_sparc<size, big_endian>* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, + unsigned int r_type, + const elfcpp::Sym<size, big_endian>& lsym) +{ + unsigned int orig_r_type = r_type; + + r_type &= 0xff; + switch (r_type) + { + case elfcpp::R_SPARC_NONE: + case elfcpp::R_SPARC_REGISTER: + case elfcpp::R_SPARC_GNU_VTINHERIT: + case elfcpp::R_SPARC_GNU_VTENTRY: + break; + + case elfcpp::R_SPARC_64: + case elfcpp::R_SPARC_32: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. The relocation applied at link time will + // apply the link-time value, so we flag the location with + // an R_SPARC_RELATIVE relocation so the dynamic loader can + // relocate it easily. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + } + break; + + case elfcpp::R_SPARC_HIX22: + case elfcpp::R_SPARC_LOX10: + case elfcpp::R_SPARC_H44: + case elfcpp::R_SPARC_M44: + case elfcpp::R_SPARC_L44: + case elfcpp::R_SPARC_HH22: + case elfcpp::R_SPARC_HM10: + case elfcpp::R_SPARC_LM22: + case elfcpp::R_SPARC_UA64: + case elfcpp::R_SPARC_UA32: + case elfcpp::R_SPARC_UA16: + case elfcpp::R_SPARC_HI22: + case elfcpp::R_SPARC_LO10: + case elfcpp::R_SPARC_OLO10: + case elfcpp::R_SPARC_16: + case elfcpp::R_SPARC_11: + case elfcpp::R_SPARC_10: + case elfcpp::R_SPARC_8: + case elfcpp::R_SPARC_7: + case elfcpp::R_SPARC_6: + case elfcpp::R_SPARC_5: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + + check_non_pic(object, r_type); + if (lsym.get_st_type() != elfcpp::STT_SECTION) + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + rela_dyn->add_local(object, r_sym, orig_r_type, output_section, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + gold_assert(lsym.get_st_value() == 0); + rela_dyn->add_local_relative(object, r_sym, orig_r_type, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + break; + + case elfcpp::R_SPARC_WDISP30: + case elfcpp::R_SPARC_WDISP22: + case elfcpp::R_SPARC_WDISP19: + case elfcpp::R_SPARC_WDISP16: + case elfcpp::R_SPARC_DISP8: + case elfcpp::R_SPARC_DISP16: + case elfcpp::R_SPARC_DISP32: + case elfcpp::R_SPARC_DISP64: + case elfcpp::R_SPARC_PC10: + case elfcpp::R_SPARC_PC22: + break; + + case elfcpp::R_SPARC_GOT10: + case elfcpp::R_SPARC_GOT13: + case elfcpp::R_SPARC_GOT22: + { + // The symbol requires a GOT entry. + Output_data_got<size, big_endian>* got; + unsigned int r_sym; + + got = target->got_section(symtab, layout); + r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + + // If we are generating a shared object, we need to add a + // dynamic relocation for this symbol's GOT entry. + if (parameters->options().output_is_position_independent()) + { + if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int off; + + off = got->add_constant(0); + object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off); + rela_dyn->add_local_relative(object, r_sym, + elfcpp::R_SPARC_RELATIVE, + got, off, 0); + } + } + else + got->add_local(object, r_sym, GOT_TYPE_STANDARD); + } + break; + + // These are initial TLS relocs, which are expected when + // linking. + case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + case elfcpp::R_SPARC_TLS_LDM_HI22 : // Local-dynamic + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + case elfcpp::R_SPARC_TLS_LDO_HIX22: // Alternate local-dynamic + case elfcpp::R_SPARC_TLS_LDO_LOX10: + case elfcpp::R_SPARC_TLS_LDO_ADD: + case elfcpp::R_SPARC_TLS_IE_HI22: // Initial-exec + case elfcpp::R_SPARC_TLS_IE_LO10: + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_LE_HIX22: // Local-exec + case elfcpp::R_SPARC_TLS_LE_LOX10: + { + bool output_is_shared = parameters->options().shared(); + const tls::Tls_optimization optimized_type + = optimize_tls_reloc(!output_is_shared, r_type); + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Output_data_got<size, big_endian>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rela(object, r_sym, + lsym.get_st_shndx(), + GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + (size == 64 + ? elfcpp::R_SPARC_TLS_DTPMOD64 + : elfcpp::R_SPARC_TLS_DTPMOD32), + 0); + if (r_type == elfcpp::R_SPARC_TLS_GD_CALL) + generate_tls_call(symtab, layout, target); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_SPARC_TLS_LDM_HI22 : // Local-dynamic + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + + if (r_type == elfcpp::R_SPARC_TLS_LDM_CALL) + generate_tls_call(symtab, layout, target); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_SPARC_TLS_LDO_HIX22: // Alternate local-dynamic + case elfcpp::R_SPARC_TLS_LDO_LOX10: + case elfcpp::R_SPARC_TLS_LDO_ADD: + break; + + case elfcpp::R_SPARC_TLS_IE_HI22: // Initial-exec + case elfcpp::R_SPARC_TLS_IE_LO10: + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<size, big_endian>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + + if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int off = got->add_constant(0); + + object->set_local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET, + off); + rela_dyn->add_local_relative(object, r_sym, + (size == 64 ? + elfcpp::R_SPARC_TLS_TPOFF64 : + elfcpp::R_SPARC_TLS_TPOFF32), + got, off, 0); + } + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_SPARC_TLS_LE_HIX22: // Local-exec + case elfcpp::R_SPARC_TLS_LE_LOX10: + layout->set_has_static_tls(); + if (output_is_shared) + { + // We need to create a dynamic relocation. + gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_local_relative(object, r_sym, r_type, + output_section, data_shndx, + reloc.get_r_offset(), 0); + } + break; + } + } + break; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_SPARC_COPY: + case elfcpp::R_SPARC_GLOB_DAT: + case elfcpp::R_SPARC_JMP_SLOT: + case elfcpp::R_SPARC_RELATIVE: + case elfcpp::R_SPARC_TLS_DTPMOD64: + case elfcpp::R_SPARC_TLS_DTPMOD32: + case elfcpp::R_SPARC_TLS_DTPOFF64: + case elfcpp::R_SPARC_TLS_DTPOFF32: + case elfcpp::R_SPARC_TLS_TPOFF64: + case elfcpp::R_SPARC_TLS_TPOFF32: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + default: + unsupported_reloc_local(object, r_type); + break; + } +} + +// Report an unsupported relocation against a global symbol. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::Scan::unsupported_reloc_global( + Sized_relobj<size, big_endian>* object, + unsigned int r_type, + Symbol* gsym) +{ + gold_error(_("%s: unsupported reloc %u against global symbol %s"), + object->name().c_str(), r_type, gsym->demangled_name().c_str()); +} + +// Scan a relocation for a global symbol. + +template<int size, bool big_endian> +inline void +Target_sparc<size, big_endian>::Scan::global( + const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_sparc<size, big_endian>* target, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<size, big_endian>& reloc, + unsigned int r_type, + Symbol* gsym) +{ + unsigned int orig_r_type = r_type; + + r_type &= 0xff; + switch (r_type) + { + case elfcpp::R_SPARC_NONE: + case elfcpp::R_SPARC_REGISTER: + case elfcpp::R_SPARC_GNU_VTINHERIT: + case elfcpp::R_SPARC_GNU_VTENTRY: + break; + + case elfcpp::R_SPARC_PLT64: + case elfcpp::R_SPARC_PLT32: + case elfcpp::R_SPARC_HIPLT22: + case elfcpp::R_SPARC_LOPLT10: + case elfcpp::R_SPARC_PCPLT32: + case elfcpp::R_SPARC_PCPLT22: + case elfcpp::R_SPARC_PCPLT10: + case elfcpp::R_SPARC_WPLT30: + // If the symbol is fully resolved, this is just a PC32 reloc. + // Otherwise we need a PLT entry. + if (gsym->final_value_is_known()) + break; + // If building a shared library, we can also skip the PLT entry + // if the symbol is defined in the output file and is protected + // or hidden. + if (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible()) + break; + target->make_plt_entry(symtab, layout, gsym); + break; + + case elfcpp::R_SPARC_DISP8: + case elfcpp::R_SPARC_DISP16: + case elfcpp::R_SPARC_DISP32: + case elfcpp::R_SPARC_DISP64: + case elfcpp::R_SPARC_PC_HH22: + case elfcpp::R_SPARC_PC_HM10: + case elfcpp::R_SPARC_PC_LM22: + case elfcpp::R_SPARC_PC10: + case elfcpp::R_SPARC_PC22: + case elfcpp::R_SPARC_WDISP30: + case elfcpp::R_SPARC_WDISP22: + case elfcpp::R_SPARC_WDISP19: + case elfcpp::R_SPARC_WDISP16: + { + if (gsym->needs_plt_entry()) + target->make_plt_entry(symtab, layout, gsym); + // Make a dynamic relocation if necessary. + int flags = Symbol::NON_PIC_REF; + if (gsym->type() == elfcpp::STT_FUNC) + flags |= Symbol::FUNCTION_CALL; + if (gsym->needs_dynamic_reloc(flags)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, + reloc); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + check_non_pic(object, r_type); + rela_dyn->add_global(gsym, orig_r_type, output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + } + break; + + case elfcpp::R_SPARC_UA64: + case elfcpp::R_SPARC_64: + case elfcpp::R_SPARC_HIX22: + case elfcpp::R_SPARC_LOX10: + case elfcpp::R_SPARC_H44: + case elfcpp::R_SPARC_M44: + case elfcpp::R_SPARC_L44: + case elfcpp::R_SPARC_HH22: + case elfcpp::R_SPARC_HM10: + case elfcpp::R_SPARC_LM22: + case elfcpp::R_SPARC_HI22: + case elfcpp::R_SPARC_LO10: + case elfcpp::R_SPARC_OLO10: + case elfcpp::R_SPARC_UA32: + case elfcpp::R_SPARC_32: + case elfcpp::R_SPARC_UA16: + case elfcpp::R_SPARC_16: + case elfcpp::R_SPARC_11: + case elfcpp::R_SPARC_10: + case elfcpp::R_SPARC_8: + case elfcpp::R_SPARC_7: + case elfcpp::R_SPARC_6: + case elfcpp::R_SPARC_5: + { + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + { + target->make_plt_entry(symtab, layout, gsym); + // Since this is not a PC-relative relocation, we may be + // taking the address of a function. In that case we need to + // set the entry in the dynamic symbol table to the address of + // the PLT entry. + if (gsym->is_from_dynobj() && !parameters->options().shared()) + gsym->set_needs_dynsym_value(); + } + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else if ((r_type == elfcpp::R_SPARC_32 + || r_type == elfcpp::R_SPARC_64) + && gsym->can_use_relative_reloc(false)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE, + output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + + check_non_pic(object, r_type); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + rela_dyn->add_global(gsym, orig_r_type, output_section, + object, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + else + rela_dyn->add_global_relative(gsym, orig_r_type, + output_section, object, + data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + } + break; + + case elfcpp::R_SPARC_GOT10: + case elfcpp::R_SPARC_GOT13: + case elfcpp::R_SPARC_GOT22: + { + // The symbol requires a GOT entry. + Output_data_got<size, big_endian>* got; + + got = target->got_section(symtab, layout); + if (gsym->final_value_is_known()) + got->add_global(gsym, GOT_TYPE_STANDARD); + else + { + // If this symbol is not fully resolved, we need to add a + // dynamic relocation for it. + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_SPARC_GLOB_DAT); + else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) + { + unsigned int off = got->add_constant(0); + + gsym->set_got_offset(GOT_TYPE_STANDARD, off); + rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE, + got, off, 0); + } + } + } + break; + + // These are initial tls relocs, which are expected when + // linking. + case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + case elfcpp::R_SPARC_TLS_LDM_HI22: // Local-dynamic + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + case elfcpp::R_SPARC_TLS_LDO_HIX22: // Alternate local-dynamic + case elfcpp::R_SPARC_TLS_LDO_LOX10: + case elfcpp::R_SPARC_TLS_LDO_ADD: + case elfcpp::R_SPARC_TLS_LE_HIX22: + case elfcpp::R_SPARC_TLS_LE_LOX10: + case elfcpp::R_SPARC_TLS_IE_HI22: // Initial-exec + case elfcpp::R_SPARC_TLS_IE_LO10: + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + { + const bool is_final = gsym->final_value_is_known(); + const tls::Tls_optimization optimized_type + = optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Output_data_got<size, big_endian>* got + = target->got_section(symtab, layout); + got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + (size == 64 ? + elfcpp::R_SPARC_TLS_DTPMOD64 : + elfcpp::R_SPARC_TLS_DTPMOD32), + (size == 64 ? + elfcpp::R_SPARC_TLS_DTPOFF64 : + elfcpp::R_SPARC_TLS_DTPOFF32)); + + // Emit R_SPARC_WPLT30 against "__tls_get_addr" + if (r_type == elfcpp::R_SPARC_TLS_GD_CALL) + generate_tls_call(symtab, layout, target); + } + else if (optimized_type == tls::TLSOPT_TO_IE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<size, big_endian>* got + = target->got_section(symtab, layout); + got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + (size == 64 ? + elfcpp::R_SPARC_TLS_TPOFF64 : + elfcpp::R_SPARC_TLS_TPOFF32)); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_SPARC_TLS_LDM_HI22: // Local-dynamic + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + + if (r_type == elfcpp::R_SPARC_TLS_LDM_CALL) + generate_tls_call(symtab, layout, target); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_SPARC_TLS_LDO_HIX22: // Alternate local-dynamic + case elfcpp::R_SPARC_TLS_LDO_LOX10: + case elfcpp::R_SPARC_TLS_LDO_ADD: + break; + + case elfcpp::R_SPARC_TLS_LE_HIX22: + case elfcpp::R_SPARC_TLS_LE_LOX10: + layout->set_has_static_tls(); + if (parameters->options().shared()) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global_relative(gsym, orig_r_type, + output_section, object, + data_shndx, reloc.get_r_offset(), + 0); + } + break; + + case elfcpp::R_SPARC_TLS_IE_HI22: // Initial-exec + case elfcpp::R_SPARC_TLS_IE_LO10: + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<size, big_endian>* got + = target->got_section(symtab, layout); + got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + (size == 64 ? + elfcpp::R_SPARC_TLS_TPOFF64 : + elfcpp::R_SPARC_TLS_TPOFF32)); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + } + } + break; + + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + case elfcpp::R_SPARC_COPY: + case elfcpp::R_SPARC_GLOB_DAT: + case elfcpp::R_SPARC_JMP_SLOT: + case elfcpp::R_SPARC_RELATIVE: + case elfcpp::R_SPARC_TLS_DTPMOD64: + case elfcpp::R_SPARC_TLS_DTPMOD32: + case elfcpp::R_SPARC_TLS_DTPOFF64: + case elfcpp::R_SPARC_TLS_DTPOFF32: + case elfcpp::R_SPARC_TLS_TPOFF64: + case elfcpp::R_SPARC_TLS_TPOFF32: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + default: + unsupported_reloc_global(object, r_type, gsym); + break; + } +} + +// Scan relocations for a section. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::scan_relocs( + const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + typedef Target_sparc<size, big_endian> Sparc; + typedef typename Target_sparc<size, big_endian>::Scan Scan; + + if (sh_type == elfcpp::SHT_REL) + { + gold_error(_("%s: unsupported REL reloc section"), + object->name().c_str()); + return; + } + + gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>( + options, + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + +// Finalize the sections. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::do_finalize_sections(Layout* layout) +{ + // Fill in some more dynamic tags. + Output_data_dynamic* const odyn = layout->dynamic_data(); + if (odyn != NULL) + { + if (this->plt_ != NULL) + { + const Output_data* od = this->plt_->rel_plt(); + odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); + odyn->add_section_address(elfcpp::DT_JMPREL, od); + odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); + + odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); + } + + if (this->rela_dyn_ != NULL) + { + const Output_data* od = this->rela_dyn_; + odyn->add_section_address(elfcpp::DT_RELA, od); + odyn->add_section_size(elfcpp::DT_RELASZ, od); + odyn->add_constant(elfcpp::DT_RELAENT, + elfcpp::Elf_sizes<size>::rela_size); + } + + if (!parameters->options().shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } + } + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. + if (this->copy_relocs_.any_saved_relocs()) + this->copy_relocs_.emit(this->rela_dyn_section(layout)); +} + +// Perform a relocation. + +template<int size, bool big_endian> +inline bool +Target_sparc<size, big_endian>::Relocate::relocate( + const Relocate_info<size, big_endian>* relinfo, + Target_sparc* target, + size_t relnum, + const elfcpp::Rela<size, big_endian>& rela, + unsigned int r_type, + const Sized_symbol<size>* gsym, + const Symbol_value<size>* psymval, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr address, + section_size_type view_size) +{ + r_type &= 0xff; + + if (this->ignore_gd_add_) + { + if (r_type != elfcpp::R_SPARC_TLS_GD_ADD) + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("missing expected TLS relocation")); + else + { + this->ignore_gd_add_ = false; + return false; + } + } + + typedef Sparc_relocate_functions<size, big_endian> Reloc; + + // Pick the value to use for symbols defined in shared objects. + Symbol_value<size> symval; + if (gsym != NULL + && gsym->use_plt_offset(r_type == elfcpp::R_SPARC_DISP8 + || r_type == elfcpp::R_SPARC_DISP16 + || r_type == elfcpp::R_SPARC_DISP32 + || r_type == elfcpp::R_SPARC_DISP64 + || r_type == elfcpp::R_SPARC_PC_HH22 + || r_type == elfcpp::R_SPARC_PC_HM10 + || r_type == elfcpp::R_SPARC_PC_LM22 + || r_type == elfcpp::R_SPARC_PC10 + || r_type == elfcpp::R_SPARC_PC22 + || r_type == elfcpp::R_SPARC_WDISP30 + || r_type == elfcpp::R_SPARC_WDISP22 + || r_type == elfcpp::R_SPARC_WDISP19 + || r_type == elfcpp::R_SPARC_WDISP16)) + { + elfcpp::Elf_Xword value; + + value = target->plt_section()->address() + gsym->plt_offset(); + + symval.set_output_value(value); + + psymval = &symval; + } + + const Sized_relobj<size, big_endian>* object = relinfo->object; + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + + // Get the GOT offset if needed. Unlike i386 and x86_64, our GOT + // pointer points to the beginning, not the end, of the table. + // So we just use the plain offset. + bool have_got_offset = false; + unsigned int got_offset = 0; + switch (r_type) + { + case elfcpp::R_SPARC_GOT10: + case elfcpp::R_SPARC_GOT13: + case elfcpp::R_SPARC_GOT22: + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = gsym->got_offset(GOT_TYPE_STANDARD); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); + got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD); + } + have_got_offset = true; + break; + + default: + break; + } + + switch (r_type) + { + case elfcpp::R_SPARC_NONE: + case elfcpp::R_SPARC_REGISTER: + case elfcpp::R_SPARC_GNU_VTINHERIT: + case elfcpp::R_SPARC_GNU_VTENTRY: + break; + + case elfcpp::R_SPARC_8: + Relocate_functions<size, big_endian>::rela8(view, object, + psymval, addend); + break; + + case elfcpp::R_SPARC_16: + Relocate_functions<size, big_endian>::rela16(view, object, + psymval, addend); + break; + + case elfcpp::R_SPARC_32: + if (!parameters->options().output_is_position_independent()) + Relocate_functions<size, big_endian>::rela32(view, object, + psymval, addend); + break; + + case elfcpp::R_SPARC_DISP8: + Reloc::disp8(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_DISP16: + Reloc::disp16(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_DISP32: + Reloc::disp32(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_DISP64: + Reloc::disp64(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_WDISP30: + case elfcpp::R_SPARC_WPLT30: + Reloc::wdisp30(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_WDISP22: + Reloc::wdisp22(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_WDISP19: + Reloc::wdisp19(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_WDISP16: + Reloc::wdisp16(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_HI22: + Reloc::hi22(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_22: + Reloc::rela32_22(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_13: + Reloc::rela32_13(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_LO10: + Reloc::lo10(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_GOT10: + Reloc::lo10(view, got_offset, addend); + break; + + case elfcpp::R_SPARC_GOT13: + Reloc::rela32_13(view, got_offset, addend); + break; + + case elfcpp::R_SPARC_GOT22: + Reloc::hi22(view, got_offset, addend); + break; + + case elfcpp::R_SPARC_PC10: + Reloc::pc10(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_PC22: + Reloc::pc22(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_TLS_DTPOFF32: + case elfcpp::R_SPARC_UA32: + Reloc::ua32(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_PLT64: + Relocate_functions<size, big_endian>::rela64(view, object, + psymval, addend); + break; + + case elfcpp::R_SPARC_PLT32: + Relocate_functions<size, big_endian>::rela32(view, object, + psymval, addend); + break; + + case elfcpp::R_SPARC_HIPLT22: + Reloc::hi22(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_LOPLT10: + Reloc::lo10(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_PCPLT32: + Reloc::disp32(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_PCPLT22: + Reloc::pcplt22(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_PCPLT10: + Reloc::lo10(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_64: + if (!parameters->options().output_is_position_independent()) + Relocate_functions<size, big_endian>::rela64(view, object, + psymval, addend); + break; + + case elfcpp::R_SPARC_OLO10: + { + unsigned int addend2 = rela.get_r_info() & 0xffffffff; + addend2 = ((addend2 >> 8) ^ 0x800000) - 0x800000; + Reloc::olo10(view, object, psymval, addend, addend2); + } + break; + + case elfcpp::R_SPARC_HH22: + Reloc::hh22(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_PC_HH22: + Reloc::pc_hh22(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_HM10: + Reloc::hm10(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_PC_HM10: + Reloc::pc_hm10(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_LM22: + Reloc::hi22(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_PC_LM22: + Reloc::pcplt22(view, object, psymval, addend, address); + break; + + case elfcpp::R_SPARC_11: + Reloc::rela32_11(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_10: + Reloc::rela32_10(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_7: + Reloc::rela32_7(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_6: + Reloc::rela32_6(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_5: + Reloc::rela32_5(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_HIX22: + Reloc::hix22(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_LOX10: + Reloc::lox10(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_H44: + Reloc::h44(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_M44: + Reloc::m44(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_L44: + Reloc::l44(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_TLS_DTPOFF64: + case elfcpp::R_SPARC_UA64: + Reloc::ua64(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_UA16: + Reloc::ua16(view, object, psymval, addend); + break; + + case elfcpp::R_SPARC_TLS_GD_HI22: + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + case elfcpp::R_SPARC_TLS_LDM_HI22: + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + case elfcpp::R_SPARC_TLS_LDO_HIX22: + case elfcpp::R_SPARC_TLS_LDO_LOX10: + case elfcpp::R_SPARC_TLS_LDO_ADD: + case elfcpp::R_SPARC_TLS_IE_HI22: + case elfcpp::R_SPARC_TLS_IE_LO10: + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_LE_HIX22: + case elfcpp::R_SPARC_TLS_LE_LOX10: + this->relocate_tls(relinfo, target, relnum, rela, + r_type, gsym, psymval, view, + address, view_size); + break; + + case elfcpp::R_SPARC_COPY: + case elfcpp::R_SPARC_GLOB_DAT: + case elfcpp::R_SPARC_JMP_SLOT: + case elfcpp::R_SPARC_RELATIVE: + // These are outstanding tls relocs, which are unexpected when + // linking. + case elfcpp::R_SPARC_TLS_DTPMOD64: + case elfcpp::R_SPARC_TLS_DTPMOD32: + case elfcpp::R_SPARC_TLS_TPOFF64: + case elfcpp::R_SPARC_TLS_TPOFF32: + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unexpected reloc %u in object file"), + r_type); + break; + + default: + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + } + + return true; +} + +// Perform a TLS relocation. + +template<int size, bool big_endian> +inline void +Target_sparc<size, big_endian>::Relocate::relocate_tls( + const Relocate_info<size, big_endian>* relinfo, + Target_sparc<size, big_endian>* target, + size_t relnum, + const elfcpp::Rela<size, big_endian>& rela, + unsigned int r_type, + const Sized_symbol<size>* gsym, + const Symbol_value<size>* psymval, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr address, + section_size_type) +{ + Output_segment* tls_segment = relinfo->layout->tls_segment(); + typedef Sparc_relocate_functions<size, big_endian> Reloc; + const Sized_relobj<size, big_endian>* object = relinfo->object; + typedef typename elfcpp::Swap<32, true>::Valtype Insntype; + + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + typename elfcpp::Elf_types<size>::Elf_Addr value = psymval->value(object, 0); + + const bool is_final = + (gsym == NULL + ? !parameters->options().output_is_position_independent() + : gsym->final_value_is_known()); + const tls::Tls_optimization optimized_type + = optimize_tls_reloc(is_final, r_type); + + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: + case elfcpp::R_SPARC_TLS_GD_LO10: + case elfcpp::R_SPARC_TLS_GD_ADD: + case elfcpp::R_SPARC_TLS_GD_CALL: + if (optimized_type == tls::TLSOPT_TO_LE) + { + Insntype* wv = reinterpret_cast<Insntype*>(view); + Insntype val; + + value -= tls_segment->memsz(); + + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: + // TLS_GD_HI22 --> TLS_LE_HIX22 + Reloc::hix22(view, value, addend); + break; + + case elfcpp::R_SPARC_TLS_GD_LO10: + // TLS_GD_LO10 --> TLS_LE_LOX10 + Reloc::lox10(view, value, addend); + break; + + case elfcpp::R_SPARC_TLS_GD_ADD: + // add %reg1, %reg2, %reg3 --> mov %g7, %reg2, %reg3 + val = elfcpp::Swap<32, true>::readval(wv); + val = (val & ~0x7c000) | 0x1c000; + elfcpp::Swap<32, true>::writeval(wv, val); + break; + case elfcpp::R_SPARC_TLS_GD_CALL: + // call __tls_get_addr --> nop + elfcpp::Swap<32, true>::writeval(wv, sparc_nop); + break; + } + break; + } + else + { + unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE + ? GOT_TYPE_TLS_OFFSET + : GOT_TYPE_TLS_PAIR); + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + value = gsym->got_offset(got_type); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + value = object->local_got_offset(r_sym, got_type); + } + if (optimized_type == tls::TLSOPT_TO_IE) + { + Insntype* wv = reinterpret_cast<Insntype*>(view); + Insntype val; + + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: + // TLS_GD_HI22 --> TLS_IE_HI22 + Reloc::hi22(view, value, addend); + break; + + case elfcpp::R_SPARC_TLS_GD_LO10: + // TLS_GD_LO10 --> TLS_IE_LO10 + Reloc::lo10(view, value, addend); + break; + + case elfcpp::R_SPARC_TLS_GD_ADD: + // add %reg1, %reg2, %reg3 --> ld [%reg1 + %reg2], %reg3 + val = elfcpp::Swap<32, true>::readval(wv); + + if (size == 64) + val |= 0xc0580000; + else + val |= 0xc0000000; + + elfcpp::Swap<32, true>::writeval(wv, val); + break; + + case elfcpp::R_SPARC_TLS_GD_CALL: + // The compiler can put the TLS_GD_ADD instruction + // into the delay slot of the call. If so, we need + // to transpose the two instructions so that the + // the new sequence works properly. + // + // The test we use is if the instruction in the + // delay slot is an add with destination register + // equal to %o0 + val = elfcpp::Swap<32, true>::readval(wv + 1); + if ((val & 0x81f80000) == 0x80000000 + && ((val >> 25) & 0x1f) == 0x8) + { + if (size == 64) + val |= 0xc0580000; + else + val |= 0xc0000000; + + elfcpp::Swap<32, true>::writeval(wv, val); + + wv += 1; + this->ignore_gd_add_ = true; + } + + // call __tls_get_addr --> add %g7, %o0, %o0 + elfcpp::Swap<32, true>::writeval(wv, 0x9001c008); + break; + } + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + switch (r_type) + { + case elfcpp::R_SPARC_TLS_GD_HI22: + Reloc::hi22(view, value, addend); + break; + case elfcpp::R_SPARC_TLS_GD_LO10: + Reloc::lo10(view, value, addend); + break; + case elfcpp::R_SPARC_TLS_GD_ADD: + break; + case elfcpp::R_SPARC_TLS_GD_CALL: + { + Symbol_value<size> symval; + elfcpp::Elf_Xword value; + Symbol* tsym; + + tsym = target->tls_get_addr_sym_; + gold_assert(tsym); + value = (target->plt_section()->address() + + tsym->plt_offset()); + symval.set_output_value(value); + Reloc::wdisp30(view, object, &symval, addend, address); + } + break; + } + break; + } + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + case elfcpp::R_SPARC_TLS_LDM_HI22: + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + case elfcpp::R_SPARC_TLS_LDM_CALL: + if (optimized_type == tls::TLSOPT_TO_LE) + { + Insntype* wv = reinterpret_cast<Insntype*>(view); + + switch (r_type) + { + case elfcpp::R_SPARC_TLS_LDM_HI22: + case elfcpp::R_SPARC_TLS_LDM_LO10: + case elfcpp::R_SPARC_TLS_LDM_ADD: + elfcpp::Swap<32, true>::writeval(wv, sparc_nop); + break; + + case elfcpp::R_SPARC_TLS_LDM_CALL: + elfcpp::Swap<32, true>::writeval(wv, sparc_mov_g0_o0); + break; + } + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the module index. + unsigned int got_offset; + + got_offset = target->got_mod_index_entry(NULL, NULL, NULL); + switch (r_type) + { + case elfcpp::R_SPARC_TLS_LDM_HI22: + Reloc::hi22(view, got_offset, addend); + break; + case elfcpp::R_SPARC_TLS_LDM_LO10: + Reloc::lo10(view, got_offset, addend); + break; + case elfcpp::R_SPARC_TLS_LDM_ADD: + break; + case elfcpp::R_SPARC_TLS_LDM_CALL: + { + Symbol_value<size> symval; + elfcpp::Elf_Xword value; + Symbol* tsym; + + tsym = target->tls_get_addr_sym_; + gold_assert(tsym); + value = (target->plt_section()->address() + + tsym->plt_offset()); + symval.set_output_value(value); + Reloc::wdisp30(view, object, &symval, addend, address); + } + break; + } + break; + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + // These relocs can appear in debugging sections, in which case + // we won't see the TLS_LDM relocs. The local_dynamic_type + // field tells us this. + case elfcpp::R_SPARC_TLS_LDO_HIX22: + if (optimized_type == tls::TLSOPT_TO_LE) + { + value -= tls_segment->memsz(); + Reloc::hix22(view, value, addend); + } + else + Reloc::ldo_hix22(view, value, addend); + break; + case elfcpp::R_SPARC_TLS_LDO_LOX10: + if (optimized_type == tls::TLSOPT_TO_LE) + { + value -= tls_segment->memsz(); + Reloc::lox10(view, value, addend); + } + else + Reloc::ldo_lox10(view, value, addend); + break; + case elfcpp::R_SPARC_TLS_LDO_ADD: + if (optimized_type == tls::TLSOPT_TO_LE) + { + Insntype* wv = reinterpret_cast<Insntype*>(view); + Insntype val; + + // add %reg1, %reg2, %reg3 --> add %g7, %reg2, %reg3 + val = elfcpp::Swap<32, true>::readval(wv); + val = (val & ~0x7c000) | 0x1c000; + elfcpp::Swap<32, true>::writeval(wv, val); + } + break; + + // When optimizing IE --> LE, the only relocation that is handled + // differently is R_SPARC_TLS_IE_LD, it is rewritten from + // 'ld{,x} [rs1 + rs2], rd' into 'mov rs2, rd' or simply a NOP is + // rs2 and rd are the same. + case elfcpp::R_SPARC_TLS_IE_LD: + case elfcpp::R_SPARC_TLS_IE_LDX: + if (optimized_type == tls::TLSOPT_TO_LE) + { + Insntype* wv = reinterpret_cast<Insntype*>(view); + Insntype val = elfcpp::Swap<32, true>::readval(wv); + Insntype rs2 = val & 0x1f; + Insntype rd = (val >> 25) & 0x1f; + + if (rs2 == rd) + val = sparc_nop; + else + val = sparc_mov | (val & 0x3e00001f); + + elfcpp::Swap<32, true>::writeval(wv, val); + } + break; + + case elfcpp::R_SPARC_TLS_IE_HI22: + case elfcpp::R_SPARC_TLS_IE_LO10: + if (optimized_type == tls::TLSOPT_TO_LE) + { + value -= tls_segment->memsz(); + switch (r_type) + { + case elfcpp::R_SPARC_TLS_IE_HI22: + // IE_HI22 --> LE_HIX22 + Reloc::hix22(view, value, addend); + break; + case elfcpp::R_SPARC_TLS_IE_LO10: + // IE_LO10 --> LE_LOX10 + Reloc::lox10(view, value, addend); + break; + } + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the tp-relative offset of the symbol. + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET)); + value = gsym->got_offset(GOT_TYPE_TLS_OFFSET); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, + GOT_TYPE_TLS_OFFSET)); + value = object->local_got_offset(r_sym, + GOT_TYPE_TLS_OFFSET); + } + switch (r_type) + { + case elfcpp::R_SPARC_TLS_IE_HI22: + Reloc::hi22(view, value, addend); + break; + case elfcpp::R_SPARC_TLS_IE_LO10: + Reloc::lo10(view, value, addend); + break; + } + break; + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + + case elfcpp::R_SPARC_TLS_LE_HIX22: + // If we're creating a shared library, a dynamic relocation will + // have been created for this location, so do not apply it now. + if (!parameters->options().shared()) + { + value -= tls_segment->memsz(); + Reloc::hix22(view, value, addend); + } + break; + + case elfcpp::R_SPARC_TLS_LE_LOX10: + // If we're creating a shared library, a dynamic relocation will + // have been created for this location, so do not apply it now. + if (!parameters->options().shared()) + { + value -= tls_segment->memsz(); + Reloc::lox10(view, value, addend); + } + break; + } +} + +// Relocate section data. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::relocate_section( + const Relocate_info<size, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr address, + section_size_type view_size) +{ + typedef Target_sparc<size, big_endian> Sparc; + typedef typename Target_sparc<size, big_endian>::Relocate Sparc_relocate; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_section<size, big_endian, Sparc, elfcpp::SHT_RELA, + Sparc_relocate>( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size); +} + +// Return the size of a relocation while scanning during a relocatable +// link. + +template<int size, bool big_endian> +unsigned int +Target_sparc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc( + unsigned int, + Relobj*) +{ + // We are always SHT_RELA, so we should never get here. + gold_unreachable(); + return 0; +} + +// Scan the relocs during a relocatable link. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::scan_relocatable_relocs( + const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA, + Relocatable_size_for_reloc> Scan_relocatable_relocs; + + gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA, + Scan_relocatable_relocs>( + options, + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); +} + +// Relocate a section during a relocatable link. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::relocate_for_relocatable( + const Relocate_info<size, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs* rr, + unsigned char* view, + typename elfcpp::Elf_types<size>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_for_relocatable<size, big_endian, elfcpp::SHT_RELA>( + relinfo, + prelocs, + reloc_count, + output_section, + offset_in_output_section, + rr, + view, + view_address, + view_size, + reloc_view, + reloc_view_size); +} + +// Return the value to use for a dynamic which requires special +// treatment. This is how we support equality comparisons of function +// pointers across shared library boundaries, as described in the +// processor specific ABI supplement. + +template<int size, bool big_endian> +uint64_t +Target_sparc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const +{ + gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset()); + return this->plt_section()->address() + gsym->plt_offset(); +} + +// The selector for sparc object files. + +template<int size, bool big_endian> +class Target_selector_sparc : public Target_selector +{ +public: + Target_selector_sparc() + : Target_selector(elfcpp::EM_NONE, size, big_endian, + (size == 64 ? "elf64-sparc" : "elf32-sparc")) + { } + + Target* instantiated_target_; + + Target* do_recognize(int machine, int, int) + { + switch (size) + { + case 64: + if (machine != elfcpp::EM_SPARCV9) + return NULL; + break; + + case 32: + if (machine != elfcpp::EM_SPARC + && machine != elfcpp::EM_SPARC32PLUS) + return NULL; + break; + + default: + return NULL; + } + + return do_instantiate_target(); + } + + Target* do_instantiate_target() + { + if (this->instantiated_target_ == NULL) + this->instantiated_target_ = new Target_sparc<size, big_endian>(); + return this->instantiated_target_; + } +}; + +Target_selector_sparc<32, true> target_selector_sparc32; +Target_selector_sparc<64, true> target_selector_sparc64; + +} // End anonymous namespace. diff --git a/gold/symtab.h b/gold/symtab.h new file mode 100644 index 00000000000..043fb50f228 --- /dev/null +++ b/gold/symtab.h @@ -0,0 +1,1603 @@ +// symtab.h -- the gold symbol table -*- C++ -*- + +// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// Symbol_table +// The symbol table. + +#include <string> +#include <utility> +#include <vector> + +#include "elfcpp.h" +#include "parameters.h" +#include "stringpool.h" +#include "object.h" + +#ifndef GOLD_SYMTAB_H +#define GOLD_SYMTAB_H + +namespace gold +{ + +class Mapfile; +class Object; +class Relobj; +template<int size, bool big_endian> +class Sized_relobj; +class Dynobj; +template<int size, bool big_endian> +class Sized_dynobj; +class Versions; +class Version_script_info; +class Input_objects; +class Output_data; +class Output_section; +class Output_segment; +class Output_file; +class Output_symtab_xindex; + +// 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. +// Size dependent fields can be found in the template class +// Sized_symbol. Targets may support their own derived classes. + +class Symbol +{ + public: + // Because we want the class to be small, we don't use any virtual + // functions. But because symbols can be defined in different + // places, we need to classify them. This enum is the different + // sources of symbols we support. + enum Source + { + // Symbol defined in a relocatable or dynamic input file--this is + // the most common case. + FROM_OBJECT, + // Symbol defined in an Output_data, a special section created by + // the target. + IN_OUTPUT_DATA, + // Symbol defined in an Output_segment, with no associated + // section. + IN_OUTPUT_SEGMENT, + // Symbol value is constant. + IS_CONSTANT, + // Symbol is undefined. + IS_UNDEFINED + }; + + // When the source is IN_OUTPUT_SEGMENT, we need to describe what + // the offset means. + enum Segment_offset_base + { + // From the start of the segment. + SEGMENT_START, + // From the end of the segment. + SEGMENT_END, + // From the filesz of the segment--i.e., after the loaded bytes + // but before the bytes which are allocated but zeroed. + SEGMENT_BSS + }; + + // Return the symbol name. + const char* + name() const + { return this->name_; } + + // Return the (ANSI) demangled version of the name, if + // parameters.demangle() is true. Otherwise, return the name. This + // is intended to be used only for logging errors, so it's not + // super-efficient. + std::string + demangled_name() const; + + // Return the symbol version. This will return NULL for an + // unversioned symbol. + const char* + version() const + { return this->version_; } + + // 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. + bool + is_default() const + { + gold_assert(this->version_ != NULL); + return this->is_def_; + } + + // Set that this version is the default for this symbol name. + void + set_is_default() + { this->is_def_ = true; } + + // Return the symbol source. + Source + source() const + { return this->source_; } + + // Return the object with which this symbol is associated. + Object* + object() const + { + gold_assert(this->source_ == FROM_OBJECT); + return this->u_.from_object.object; + } + + // Return the index of the section in the input relocatable or + // dynamic object file. + unsigned int + shndx(bool* is_ordinary) const + { + gold_assert(this->source_ == FROM_OBJECT); + *is_ordinary = this->is_ordinary_shndx_; + return this->u_.from_object.shndx; + } + + // Return the output data section with which this symbol is + // associated, if the symbol was specially defined with respect to + // an output data section. + Output_data* + output_data() const + { + gold_assert(this->source_ == IN_OUTPUT_DATA); + return this->u_.in_output_data.output_data; + } + + // If this symbol was defined with respect to an output data + // section, return whether the value is an offset from end. + bool + offset_is_from_end() const + { + gold_assert(this->source_ == IN_OUTPUT_DATA); + return this->u_.in_output_data.offset_is_from_end; + } + + // Return the output segment with which this symbol is associated, + // if the symbol was specially defined with respect to an output + // segment. + Output_segment* + output_segment() const + { + gold_assert(this->source_ == IN_OUTPUT_SEGMENT); + return this->u_.in_output_segment.output_segment; + } + + // If this symbol was defined with respect to an output segment, + // return the offset base. + Segment_offset_base + offset_base() const + { + gold_assert(this->source_ == IN_OUTPUT_SEGMENT); + return this->u_.in_output_segment.offset_base; + } + + // Return the symbol binding. + elfcpp::STB + binding() const + { return this->binding_; } + + // Return the symbol type. + elfcpp::STT + type() const + { return this->type_; } + + // Return the symbol visibility. + elfcpp::STV + visibility() const + { return this->visibility_; } + + // Return the non-visibility part of the st_other field. + unsigned char + nonvis() const + { return this->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. + bool + is_forwarder() const + { return this->is_forwarder_; } + + // Mark this symbol as a forwarder. + void + 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 + needs_dynsym_entry() const + { + return (this->needs_dynsym_entry_ + || (this->in_reg() && this->in_dyn())); + } + + // Mark this symbol as needing an entry in the dynamic symbol table. + void + 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 + { return this->in_reg_; } + + // Mark this symbol as having been seen in a regular object. + void + set_in_reg() + { this->in_reg_ = true; } + + // Return whether this symbol has been seen in a dynamic object. + bool + in_dyn() const + { return this->in_dyn_; } + + // Mark this symbol as having been seen in a dynamic object. + void + set_in_dyn() + { this->in_dyn_ = true; } + + // Return the index of this symbol in the output file symbol table. + // A value of -1U means that this symbol is not going into the + // output file. This starts out as zero, and is set to a non-zero + // value by Symbol_table::finalize. It is an error to ask for the + // symbol table index before it has been set. + unsigned int + symtab_index() const + { + gold_assert(this->symtab_index_ != 0); + return this->symtab_index_; + } + + // Set the index of the symbol in the output file symbol table. + void + set_symtab_index(unsigned int index) + { + gold_assert(index != 0); + this->symtab_index_ = index; + } + + // Return whether this symbol already has an index in the output + // file symbol table. + bool + has_symtab_index() const + { return this->symtab_index_ != 0; } + + // Return the index of this symbol in the dynamic symbol table. A + // value of -1U means that this symbol is not going into the dynamic + // symbol table. This starts out as zero, and is set to a non-zero + // during Layout::finalize. It is an error to ask for the dynamic + // symbol table index before it has been set. + unsigned int + dynsym_index() const + { + gold_assert(this->dynsym_index_ != 0); + return this->dynsym_index_; + } + + // Set the index of the symbol in the dynamic symbol table. + void + set_dynsym_index(unsigned int index) + { + gold_assert(index != 0); + this->dynsym_index_ = index; + } + + // Return whether this symbol already has an index in the dynamic + // symbol table. + bool + has_dynsym_index() const + { return this->dynsym_index_ != 0; } + + // Return whether this symbol has an entry in the GOT section. + // For a TLS symbol, this GOT entry will hold its tp-relative offset. + bool + has_got_offset(unsigned int got_type) const + { return this->got_offsets_.get_offset(got_type) != -1U; } + + // Return the offset into the GOT section of this symbol. + unsigned int + got_offset(unsigned int got_type) const + { + unsigned int got_offset = this->got_offsets_.get_offset(got_type); + gold_assert(got_offset != -1U); + return got_offset; + } + + // Set the GOT offset of this symbol. + void + set_got_offset(unsigned int got_type, unsigned int got_offset) + { this->got_offsets_.set_offset(got_type, got_offset); } + + // Return whether this symbol has an entry in the PLT section. + bool + has_plt_offset() const + { return this->has_plt_offset_; } + + // Return the offset into the PLT section of this symbol. + unsigned int + plt_offset() const + { + gold_assert(this->has_plt_offset()); + return this->plt_offset_; + } + + // Set the PLT offset of this symbol. + void + set_plt_offset(unsigned int plt_offset) + { + this->has_plt_offset_ = true; + this->plt_offset_ = plt_offset; + } + + // Return whether this dynamic symbol needs a special value in the + // dynamic symbol table. + bool + needs_dynsym_value() const + { return this->needs_dynsym_value_; } + + // Set that this dynamic symbol needs a special value in the dynamic + // symbol table. + void + set_needs_dynsym_value() + { + gold_assert(this->object()->is_dynamic()); + this->needs_dynsym_value_ = true; + } + + // Return true if the final value of this symbol is known at link + // time. + bool + final_value_is_known() const; + + // Return whether this is a defined symbol (not undefined or + // common). + bool + is_defined() const + { + bool is_ordinary; + if (this->source_ != FROM_OBJECT) + return this->source_ != IS_UNDEFINED; + unsigned int shndx = this->shndx(&is_ordinary); + return (is_ordinary + ? shndx != elfcpp::SHN_UNDEF + : shndx != elfcpp::SHN_COMMON); + } + + // Return true if this symbol is from a dynamic object. + bool + is_from_dynobj() const + { + return this->source_ == FROM_OBJECT && this->object()->is_dynamic(); + } + + // Return whether this is an undefined symbol. + bool + is_undefined() const + { + bool is_ordinary; + return ((this->source_ == FROM_OBJECT + && this->shndx(&is_ordinary) == elfcpp::SHN_UNDEF + && is_ordinary) + || this->source_ == IS_UNDEFINED); + } + + // Return whether this is a weak undefined symbol. + bool + is_weak_undefined() const + { return this->is_undefined() && this->binding() == elfcpp::STB_WEAK; } + + // Return whether this is an absolute symbol. + bool + is_absolute() const + { + bool is_ordinary; + return ((this->source_ == FROM_OBJECT + && this->shndx(&is_ordinary) == elfcpp::SHN_ABS + && !is_ordinary) + || this->source_ == IS_CONSTANT); + } + + // Return whether this is a common symbol. + bool + is_common() const + { + bool is_ordinary; + return (this->source_ == FROM_OBJECT + && ((this->shndx(&is_ordinary) == elfcpp::SHN_COMMON + && !is_ordinary) + || this->type_ == elfcpp::STT_COMMON)); + } + + // Return whether this symbol can be seen outside this object. + bool + is_externally_visible() const + { + return (this->visibility_ == elfcpp::STV_DEFAULT + || 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()); + + // It doesn't make sense to ask whether an undefined symbol + // is preemptible. + gold_assert(!this->is_undefined()); + + // If a symbol does not have default visibility, it can not be + // seen outside this link unit and therefore is not preemptible. + if (this->visibility_ != elfcpp::STV_DEFAULT) + return false; + + // If this symbol has been forced to be a local symbol by a + // version script, then it is not visible outside this link unit + // and is not preemptible. + if (this->is_forced_local_) + return false; + + // If we are not producing a shared library, then nothing is + // preemptible. + if (!parameters->options().shared()) + return false; + + // If the user used -Bsymbolic, then nothing is preemptible. + if (parameters->options().Bsymbolic()) + return false; + + // If the user used -Bsymbolic-functions, then functions are not + // preemptible. We explicitly check for not being STT_OBJECT, + // rather than for being STT_FUNC, because that is what the GNU + // linker does. + if (this->type() != elfcpp::STT_OBJECT + && parameters->options().Bsymbolic_functions()) + return false; + + // Otherwise the symbol is preemptible. + return true; + } + + // 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. If we're doing a + // static link, we don't create PLT entries. + bool + needs_plt_entry() const + { + return (!parameters->doing_static_link() + && this->type() == elfcpp::STT_FUNC + && (this->is_from_dynobj() + || this->is_undefined() + || this->is_preemptible())); + } + + // When determining whether a reference to a symbol needs a dynamic + // relocation, we need to know several things about the reference. + // These flags may be or'ed together. + enum Reference_flags + { + // Reference to the symbol's absolute address. + ABSOLUTE_REF = 1, + // A non-PIC reference. + NON_PIC_REF = 2, + // A function call. + FUNCTION_CALL = 4 + }; + + // 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(int flags) const + { + // No dynamic relocations in a static link! + if (parameters->doing_static_link()) + return false; + + // A reference to a weak undefined symbol from an executable should be + // statically resolved to 0, and does not need a dynamic relocation. + // This matches gnu ld behavior. + if (this->is_weak_undefined() && !parameters->options().shared()) + return false; + + // A reference to an absolute symbol does not need a dynamic relocation. + if (this->is_absolute()) + return false; + + // An absolute reference within a position-independent output file + // will need a dynamic relocation. + if ((flags & ABSOLUTE_REF) + && parameters->options().output_is_position_independent()) + return true; + + // A function call that can branch to a local PLT entry does not need + // a dynamic relocation. A non-pic pc-relative function call in a + // shared library cannot use a PLT entry. + if ((flags & FUNCTION_CALL) + && this->has_plt_offset() + && !((flags & NON_PIC_REF) && parameters->options().shared())) + return false; + + // 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() + && 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_undefined() + || this->is_preemptible()) + return true; + + // For all other cases, return FALSE. + return false; + } + + // Whether we should use the PLT offset associated with a symbol for + // a relocation. IS_NON_PIC_REFERENCE is true if this is a non-PIC + // reloc--the same set of relocs for which we would pass NON_PIC_REF + // to the needs_dynamic_reloc function. + + bool + use_plt_offset(bool is_non_pic_reference) const + { + // If the symbol doesn't have a PLT offset, then naturally we + // don't want to use it. + if (!this->has_plt_offset()) + return false; + + // If we are going to generate a dynamic relocation, then we will + // wind up using that, so no need to use the PLT entry. + if (this->needs_dynamic_reloc(FUNCTION_CALL + | (is_non_pic_reference + ? NON_PIC_REF + : 0))) + return false; + + // If the symbol is from a dynamic object, we need to use the PLT + // entry. + if (this->is_from_dynobj()) + return true; + + // If we are generating a shared object, and this symbol is + // undefined or preemptible, we need to use the PLT entry. + if (parameters->options().shared() + && (this->is_undefined() || this->is_preemptible())) + return true; + + // If this is a weak undefined symbol, we need to use the PLT + // entry; the symbol may be defined by a library loaded at + // runtime. + if (this->is_weak_undefined()) + return true; + + // Otherwise we can use the regular definition. + 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_undefined() + || this->is_preemptible()) + return false; + + // For all other cases, return TRUE. + return true; + } + + // Return the output section where this symbol is defined. Return + // NULL if the symbol has an absolute value. + Output_section* + output_section() const; + + // Set the symbol's output section. This is used for symbols + // defined in scripts. This should only be called after the symbol + // table has been finalized. + void + set_output_section(Output_section*); + + // Return whether there should be a warning for references to this + // symbol. + bool + has_warning() const + { return this->has_warning_; } + + // Mark this symbol as having a warning. + void + 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; } + + // Return whether this symbol is forced to visibility STB_LOCAL + // by a "local:" entry in a version script. + bool + is_forced_local() const + { return this->is_forced_local_; } + + // Mark this symbol as forced to STB_LOCAL visibility. + void + set_is_forced_local() + { this->is_forced_local_ = true; } + + protected: + // Instances of this class should always be created at a specific + // size. + Symbol() + { memset(this, 0, sizeof *this); } + + // Initialize the general fields. + void + init_fields(const char* name, const char* version, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis); + + // Initialize fields from an ELF symbol in OBJECT. ST_SHNDX is the + // section index, IS_ORDINARY is whether it is a normal section + // index rather than a special code. + template<int size, bool big_endian> + void + init_base_object(const char *name, const char* version, Object* object, + const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary); + + // Initialize fields for an Output_data. + 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); + + // Initialize fields for an Output_segment. + void + init_base_output_segment(const char* name, const char* version, + Output_segment* os, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis, + Segment_offset_base offset_base); + + // 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); + + // Initialize fields for an undefined symbol. + void + init_base_undefined(const char* name, const char* version, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis); + + // Override existing symbol. + template<int size, bool big_endian> + void + override_base(const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary, Object* object, const char* version); + + // Override existing symbol with a special symbol. + void + override_base_with_special(const Symbol* from); + + // Override symbol version. + void + override_version(const char* version); + + // Allocate a common symbol by giving it a location in the output + // file. + void + allocate_base_common(Output_data*); + + private: + Symbol(const Symbol&); + Symbol& operator=(const Symbol&); + + // Symbol name (expected to point into a Stringpool). + const char* name_; + // Symbol version (expected to point into a Stringpool). This may + // be NULL. + const char* version_; + + union + { + // This struct is used if SOURCE_ == FROM_OBJECT. + struct + { + // Object in which symbol is defined, or in which it was first + // seen. + Object* object; + // Section number in object_ in which symbol is defined. + unsigned int shndx; + } from_object; + + // This struct is used if SOURCE_ == IN_OUTPUT_DATA. + struct + { + // Output_data in which symbol is defined. Before + // Layout::finalize the symbol's value is an offset within the + // Output_data. + Output_data* output_data; + // True if the offset is from the end, false if the offset is + // from the beginning. + bool offset_is_from_end; + } in_output_data; + + // This struct is used if SOURCE_ == IN_OUTPUT_SEGMENT. + struct + { + // Output_segment in which the symbol is defined. Before + // Layout::finalize the symbol's value is an offset. + Output_segment* output_segment; + // The base to use for the offset before Layout::finalize. + Segment_offset_base offset_base; + } in_output_segment; + } u_; + + // The index of this symbol in the output file. If the symbol is + // not going into the output file, this value is -1U. This field + // starts as always holding zero. It is set to a non-zero value by + // Symbol_table::finalize. + unsigned int symtab_index_; + + // The index of this symbol in the dynamic symbol table. If the + // symbol is not going into the dynamic symbol table, this value is + // -1U. This field starts as always holding zero. It is set to a + // non-zero value during Layout::finalize. + unsigned int dynsym_index_; + + // If this symbol has an entry in the GOT section (has_got_offset_ + // is true), this holds the offset from the start of the GOT section. + // A symbol may have more than one GOT offset (e.g., when mixing + // modules compiled with two different TLS models), but will usually + // have at most one. + Got_offset_list got_offsets_; + + // If this symbol has an entry in the PLT section (has_plt_offset_ + // is true), then this is the offset from the start of the PLT + // section. + unsigned int plt_offset_; + + // Symbol type (bits 0 to 3). + elfcpp::STT type_ : 4; + // Symbol binding (bits 4 to 7). + elfcpp::STB binding_ : 4; + // Symbol visibility (bits 8 to 9). + elfcpp::STV visibility_ : 2; + // Rest of symbol st_other field (bits 10 to 15). + unsigned int nonvis_ : 6; + // The type of symbol (bits 16 to 18). + Source source_ : 3; + // True if this symbol always requires special target-specific + // handling (bit 19). + bool is_target_special_ : 1; + // True if this is the default version of the symbol (bit 20). + bool is_def_ : 1; + // True if this symbol really forwards to another symbol. This is + // used when we discover after the fact that two different entries + // in the hash table really refer to the same symbol. This will + // never be set for a symbol found in the hash table, but may be set + // for a symbol found in the list of symbols attached to an Object. + // It forwards to the symbol found in the forwarders_ map of + // Symbol_table (bit 21). + bool is_forwarder_ : 1; + // True if the symbol has an alias in the weak_aliases table in + // Symbol_table (bit 22). + bool has_alias_ : 1; + // True if this symbol needs to be in the dynamic symbol table (bit + // 23). + bool needs_dynsym_entry_ : 1; + // True if we've seen this symbol in a regular object (bit 24). + bool in_reg_ : 1; + // True if we've seen this symbol in a dynamic object (bit 25). + bool in_dyn_ : 1; + // True if the symbol has an entry in the PLT section (bit 26). + bool has_plt_offset_ : 1; + // True if this is a dynamic symbol which needs a special value in + // the dynamic symbol table (bit 27). + bool needs_dynsym_value_ : 1; + // True if there is a warning for this symbol (bit 28). + 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 (bit 29). + bool is_copied_from_dynobj_ : 1; + // True if this symbol was forced to local visibility by a version + // script (bit 30). + bool is_forced_local_ : 1; + // True if the field u_.from_object.shndx is an ordinary section + // index, not one of the special codes from SHN_LORESERVE to + // SHN_HIRESERVE. + bool is_ordinary_shndx_ : 1; +}; + +// The parts of a symbol which are size specific. Using a template +// derived class like this helps us use less space on a 32-bit system. + +template<int size> +class Sized_symbol : public Symbol +{ + public: + typedef typename elfcpp::Elf_types<size>::Elf_Addr Value_type; + typedef typename elfcpp::Elf_types<size>::Elf_WXword Size_type; + + Sized_symbol() + { } + + // Initialize fields from an ELF symbol in OBJECT. ST_SHNDX is the + // section index, IS_ORDINARY is whether it is a normal section + // index rather than a special code. + template<bool big_endian> + void + init_object(const char *name, const char* version, Object* object, + const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary); + + // Initialize fields for an Output_data. + void + 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); + + // 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); + + // 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); + + // Initialize fields for an undefined symbol. + void + init_undefined(const char* name, const char* version, elfcpp::STT, + elfcpp::STB, elfcpp::STV, unsigned char nonvis); + + // Override existing symbol. + template<bool big_endian> + void + override(const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary, Object* object, const char* version); + + // Override existing symbol with a special symbol. + void + override_with_special(const Sized_symbol<size>*); + + // Return the symbol's value. + Value_type + value() const + { return this->value_; } + + // Return the symbol's size (we can't call this 'size' because that + // is a template parameter). + Size_type + symsize() const + { return this->symsize_; } + + // Set the symbol size. This is used when resolving common symbols. + void + set_symsize(Size_type symsize) + { this->symsize_ = symsize; } + + // Set the symbol value. This is called when we store the final + // values of the symbols into the symbol table. + void + set_value(Value_type value) + { this->value_ = value; } + + // Allocate a common symbol by giving it a location in the output + // file. + void + allocate_common(Output_data*, Value_type value); + + private: + Sized_symbol(const Sized_symbol&); + Sized_symbol& operator=(const Sized_symbol&); + + // Symbol value. Before Layout::finalize this is the offset in the + // input section. This is set to the final value during + // Layout::finalize. + Value_type value_; + // Symbol size. + Size_type symsize_; +}; + +// A struct describing a symbol defined by the linker, where the value +// of the symbol is defined based on an output section. This is used +// for symbols defined by the linker, like "_init_array_start". + +struct Define_symbol_in_section +{ + // The symbol name. + const char* name; + // The name of the output section with which this symbol should be + // associated. If there is no output section with that name, the + // symbol will be defined as zero. + const char* output_section; + // The offset of the symbol within the output section. This is an + // offset from the start of the output section, unless start_at_end + // is true, in which case this is an offset from the end of the + // output section. + uint64_t value; + // The size of the symbol. + uint64_t size; + // The symbol type. + elfcpp::STT type; + // The symbol binding. + elfcpp::STB binding; + // The symbol visibility. + elfcpp::STV visibility; + // The rest of the st_other field. + unsigned char nonvis; + // If true, the value field is an offset from the end of the output + // section. + bool offset_is_from_end; + // If true, this symbol is defined only if we see a reference to it. + bool only_if_ref; +}; + +// A struct describing a symbol defined by the linker, where the value +// of the symbol is defined based on a segment. This is used for +// symbols defined by the linker, like "_end". We describe the +// segment with which the symbol should be associated by its +// characteristics. If no segment meets these characteristics, the +// symbol will be defined as zero. If there is more than one segment +// which meets these characteristics, we will use the first one. + +struct Define_symbol_in_segment +{ + // The symbol name. + const char* name; + // The segment type where the symbol should be defined, typically + // PT_LOAD. + elfcpp::PT segment_type; + // Bitmask of segment flags which must be set. + elfcpp::PF segment_flags_set; + // Bitmask of segment flags which must be clear. + elfcpp::PF segment_flags_clear; + // The offset of the symbol within the segment. The offset is + // calculated from the position set by offset_base. + uint64_t value; + // The size of the symbol. + uint64_t size; + // The symbol type. + elfcpp::STT type; + // The symbol binding. + elfcpp::STB binding; + // The symbol visibility. + elfcpp::STV visibility; + // The rest of the st_other field. + unsigned char nonvis; + // The base from which we compute the offset. + Symbol::Segment_offset_base offset_base; + // If true, this symbol is defined only if we see a reference to it. + bool only_if_ref; +}; + +// 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 +// will issue a warning for any relocation against SYM from a +// different object file. The text of the warning is the contents of +// the section. This is not precisely the definition used by the old +// GNU linker; the old GNU linker treated an occurrence of +// .gnu.warning.SYM as defining a warning symbol. A warning symbol +// would trigger a warning on any reference. However, it was +// inconsistent in that a warning in a dynamic object only triggered +// if there was no definition in a regular object. This linker is +// different in that we only issue a warning if we use the symbol +// definition from the same object file as the warning section. + +class Warnings +{ + public: + Warnings() + : warnings_() + { } + + // Add a warning for symbol NAME in object OBJ. WARNING is the text + // of the warning. + void + add_warning(Symbol_table* symtab, const char* name, Object* obj, + const std::string& warning); + + // For each symbol for which we should give a warning, make a note + // on the symbol. + void + note_warnings(Symbol_table* symtab); + + // 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 Relocate_info<size, big_endian>*, + size_t relnum, off_t reloffset) const; + + private: + Warnings(const Warnings&); + Warnings& operator=(const Warnings&); + + // What we need to know to get the warning text. + struct Warning_location + { + // The object the warning is in. + Object* object; + // The warning text. + std::string text; + + Warning_location() + : object(NULL), text() + { } + + void + set(Object* o, const std::string& t) + { + this->object = o; + this->text = t; + } + }; + + // A mapping from warning symbol names (canonicalized in + // Symbol_table's namepool_ field) to warning information. + typedef Unordered_map<const char*, Warning_location> Warning_table; + + Warning_table warnings_; +}; + +// The main linker symbol table. + +class Symbol_table +{ + public: + // COUNT is an estimate of how many symbosl will be inserted in the + // symbol table. It's ok to put 0 if you don't know; a correct + // guess will just save some CPU by reducing hashtable resizes. + Symbol_table(unsigned int count, const Version_script_info& version_script); + + ~Symbol_table(); + + // Add COUNT external symbols from the relocatable object RELOBJ to + // the symbol table. SYMS is the symbols, SYMNDX_OFFSET is the + // offset in the symbol table of the first symbol, SYM_NAMES is + // their names, SYM_NAME_SIZE is the size of SYM_NAMES. This sets + // SYMPOINTERS to point to the symbols in the symbol table. It sets + // *DEFINED to the number of defined symbols. + template<int size, bool big_endian> + void + add_from_relobj(Sized_relobj<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*, + size_t* defined); + + // Add COUNT dynamic symbols from the dynamic object DYNOBJ to the + // symbol table. SYMS is the symbols. SYM_NAMES is their names. + // SYM_NAME_SIZE is the size of SYM_NAMES. The other parameters are + // symbol version data. + template<int size, bool big_endian> + void + add_from_dynobj(Sized_dynobj<size, big_endian>* dynobj, + const unsigned char* syms, size_t count, + 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*, + size_t* defined); + + // Define a special symbol based on an Output_data. It is a + // multiple definition error if this symbol is already defined. + Symbol* + define_in_output_data(const char* name, const char* version, + Output_data*, uint64_t value, uint64_t symsize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + bool offset_is_from_end, bool only_if_ref); + + // Define a special symbol based on an Output_segment. It is a + // multiple definition error if this symbol is already defined. + Symbol* + define_in_output_segment(const char* name, const char* version, + Output_segment*, uint64_t value, uint64_t symsize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + Symbol::Segment_offset_base, bool only_if_ref); + + // Define a special symbol with a constant value. It is a multiple + // definition error if this symbol is already defined. + Symbol* + define_as_constant(const char* name, const char* version, + uint64_t value, uint64_t symsize, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis, bool only_if_ref, + bool force_override); + + // Define a set of symbols in output sections. If ONLY_IF_REF is + // true, only define them if they are referenced. + void + define_symbols(const Layout*, int count, const Define_symbol_in_section*, + bool only_if_ref); + + // Define a set of symbols in output segments. If ONLY_IF_REF is + // true, only defined them if they are referenced. + void + define_symbols(const Layout*, int count, const Define_symbol_in_segment*, + bool only_if_ref); + + // 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(Sized_symbol<size>* sym, Output_data* posd, + typename elfcpp::Elf_types<size>::Elf_Addr); + + // Look up a symbol. + Symbol* + lookup(const char*, const char* version = NULL) const; + + // Return the real symbol associated with the forwarder symbol FROM. + Symbol* + resolve_forwards(const Symbol* from) const; + + // Return the sized version of a symbol in this table. + template<int size> + Sized_symbol<size>* + get_sized_symbol(Symbol*) const; + + template<int size> + const Sized_symbol<size>* + get_sized_symbol(const Symbol*) const; + + // Return the count of undefined symbols seen. + int + saw_undefined() const + { return this->saw_undefined_; } + + // Allocate the common symbols + void + allocate_commons(Layout*, Mapfile*); + + // Add a warning for symbol NAME in object OBJ. WARNING is the text + // of the warning. + void + add_warning(const char* name, Object* obj, const std::string& warning) + { this->warnings_.add_warning(this, name, obj, warning); } + + // Canonicalize a symbol name for use in the hash table. + const char* + canonicalize_name(const char* name) + { 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 Relocate_info<size, big_endian>* relinfo, + size_t relnum, off_t reloffset) const + { this->warnings_.issue_warning(sym, relinfo, relnum, reloffset); } + + // Check candidate_odr_violations_ to find symbols with the same name + // but apparently different definitions (different source-file/line-no). + void + detect_odr_violations(const Task*, const char* output_file_name) const; + + // Add any undefined symbols named on the command line to the symbol + // table. + void + add_undefined_symbols_from_command_line(); + + // 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(unsigned int index, std::vector<Symbol*>*, + Stringpool*, Versions*); + + // Finalize the symbol table after we have set the final addresses + // of all the input sections. This sets the final symbol indexes, + // values and adds the names to *POOL. *PLOCAL_SYMCOUNT is the + // index of the first global symbol. OFF is the file offset of the + // global symbol table, DYNOFF is the offset of the globals in the + // dynamic symbol table, DYN_GLOBAL_INDEX is the index of the first + // global dynamic symbol, and DYNCOUNT is the number of global + // dynamic symbols. This records the parameters, and returns the + // new file offset. It updates *PLOCAL_SYMCOUNT if it created any + // local symbols. + off_t + finalize(off_t off, off_t dynoff, size_t dyn_global_index, size_t dyncount, + Stringpool* pool, unsigned int *plocal_symcount); + + // Write out the global symbols. + void + write_globals(const Input_objects*, const Stringpool*, const Stringpool*, + Output_symtab_xindex*, Output_symtab_xindex*, + Output_file*) const; + + // Write out a section symbol. Return the updated offset. + void + write_section_symbol(const Output_section*, Output_symtab_xindex*, + Output_file*, off_t) const; + + // Dump statistical information to stderr. + void + print_stats() const; + + // Return the version script information. + const Version_script_info& + version_script() const + { return version_script_; } + + private: + Symbol_table(const Symbol_table&); + Symbol_table& operator=(const Symbol_table&); + + // The type of the list of common symbols. + typedef std::vector<Symbol*> Commons_type; + + // Make FROM a forwarder symbol to TO. + void + make_forwarder(Symbol* from, Symbol* to); + + // Add a symbol. + template<int size, bool big_endian> + 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, + unsigned int st_shndx, bool is_ordinary, + unsigned int orig_st_shndx); + + // Resolve symbols. + template<int size, bool big_endian> + void + resolve(Sized_symbol<size>* to, + const elfcpp::Sym<size, big_endian>& sym, + unsigned int st_shndx, bool is_ordinary, + unsigned int orig_st_shndx, + Object*, const char* version); + + template<int size, bool big_endian> + void + resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from); + + // Record that a symbol is forced to be local by a version script. + void + force_local(Symbol*); + + // Adjust NAME and *NAME_KEY for wrapping. + const char* + wrap_symbol(Object* object, const char*, Stringpool::Key* name_key); + + // Whether we should override a symbol, based on flags in + // resolve.cc. + static 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, + unsigned int st_shndx, bool is_ordinary, + 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>* + define_special_symbol(const char** pname, const char** pversion, + bool only_if_ref, Sized_symbol<size>** poldsym); + + // Define a symbol in an Output_data, sized version. + template<int size> + Sized_symbol<size>* + do_define_in_output_data(const char* name, const char* version, Output_data*, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_WXword ssize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + bool offset_is_from_end, bool only_if_ref); + + // Define a symbol in an Output_segment, sized version. + template<int size> + Sized_symbol<size>* + do_define_in_output_segment( + const char* name, const char* version, Output_segment* os, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_WXword ssize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + Symbol::Segment_offset_base offset_base, bool only_if_ref); + + // Define a symbol as a constant, sized version. + template<int size> + Sized_symbol<size>* + do_define_as_constant( + const char* name, const char* version, + typename elfcpp::Elf_types<size>::Elf_Addr value, + typename elfcpp::Elf_types<size>::Elf_WXword ssize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + bool only_if_ref, bool force_override); + + // Add any undefined symbols named on the command line to the symbol + // table, sized version. + template<int size> + void + do_add_undefined_symbols_from_command_line(); + + // Allocate the common symbols, sized version. + template<int size> + void + do_allocate_commons(Layout*, Mapfile*); + + // Allocate the common symbols from one list. + template<int size> + void + do_allocate_commons_list(Layout*, bool is_tls, Commons_type*, Mapfile*); + + // Implement detect_odr_violations. + template<int size, bool big_endian> + void + sized_detect_odr_violations() const; + + // Finalize symbols specialized for size. + template<int size> + off_t + sized_finalize(off_t, Stringpool*, unsigned int*); + + // Finalize a symbol. Return whether it should be added to the + // symbol table. + template<int size> + bool + sized_finalize_symbol(Symbol*); + + // Add a symbol the final symtab by setting its index. + template<int size> + void + add_to_final_symtab(Symbol*, Stringpool*, unsigned int* pindex, off_t* poff); + + // Write globals specialized for size and endianness. + template<int size, bool big_endian> + void + sized_write_globals(const Input_objects*, const Stringpool*, + const Stringpool*, Output_symtab_xindex*, + Output_symtab_xindex*, Output_file*) const; + + // Write out a symbol to P. + template<int size, bool big_endian> + void + sized_write_symbol(Sized_symbol<size>*, + typename elfcpp::Elf_types<size>::Elf_Addr value, + unsigned int shndx, + const Stringpool*, unsigned char* p) const; + + // Possibly warn about an undefined symbol from a dynamic object. + void + warn_about_undefined_dynobj_symbol(const Input_objects*, Symbol*) const; + + // Write out a section symbol, specialized for size and endianness. + template<int size, bool big_endian> + void + sized_write_section_symbol(const Output_section*, Output_symtab_xindex*, + Output_file*, off_t) const; + + // The type of the symbol hash table. + + typedef std::pair<Stringpool::Key, Stringpool::Key> Symbol_table_key; + + struct Symbol_table_hash + { + size_t + operator()(const Symbol_table_key&) const; + }; + + struct Symbol_table_eq + { + bool + operator()(const Symbol_table_key&, const Symbol_table_key&) const; + }; + + typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash, + Symbol_table_eq> Symbol_table_type; + + // The type of the list of symbols which have been forced local. + typedef std::vector<Symbol*> Forced_locals; + + // A map from symbols with COPY relocs to the dynamic objects where + // they are defined. + typedef Unordered_map<const Symbol*, Dynobj*> Copied_symbol_dynobjs; + + // A map from symbol name (as a pointer into the namepool) to all + // 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 + { return reinterpret_cast<uintptr_t>(loc.object) ^ loc.offset ^ loc.shndx; } + }; + + typedef Unordered_map<const char*, + Unordered_set<Symbol_location, Symbol_location_hash> > + Odr_map; + + // 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. + unsigned int 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. + unsigned int 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_; + // This is like the commons_ field, except that it holds TLS common + // symbols. + Commons_type tls_commons_; + // A list of symbols which have been forced to be local. We don't + // expect there to be very many of them, so we keep a list of them + // rather than walking the whole table to find them. + Forced_locals forced_locals_; + // Manage symbol warnings. + Warnings warnings_; + // Manage potential One Definition Rule (ODR) violations. + Odr_map candidate_odr_violations_; + + // 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_; + // Information parsed from the version script, if any. + const Version_script_info& version_script_; +}; + +// We inline get_sized_symbol for efficiency. + +template<int size> +Sized_symbol<size>* +Symbol_table::get_sized_symbol(Symbol* sym) const +{ + gold_assert(size == parameters->target().get_size()); + return static_cast<Sized_symbol<size>*>(sym); +} + +template<int size> +const Sized_symbol<size>* +Symbol_table::get_sized_symbol(const Symbol* sym) const +{ + gold_assert(size == parameters->target().get_size()); + return static_cast<const Sized_symbol<size>*>(sym); +} + +} // End namespace gold. + +#endif // !defined(GOLD_SYMTAB_H) diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am new file mode 100644 index 00000000000..df986770a09 --- /dev/null +++ b/gold/testsuite/Makefile.am @@ -0,0 +1,893 @@ +# Process this file with automake to generate Makefile.in + +# As far as I can tell automake testing support assumes that the build +# system and the host system are the same. So these tests will not +# work when building with a cross-compiler. + +AUTOMAKE_OPTIONS = + +# The two_file_test tests -fmerge-constants, so we simply always turn +# it on. This may need to be controlled by a configure option +# eventually. +AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) -fmerge-constants + +INCLUDES = \ + -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \ + -I$(srcdir)/../../elfcpp -I.. \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + @INCINTL@ + +TEST_READELF = $(top_builddir)/../binutils/readelf +TEST_OBJDUMP = $(top_builddir)/../binutils/objdump +TEST_CXXFILT = $(top_builddir)/../binutils/cxxfilt +TEST_STRIP = $(top_builddir)/../binutils/strip-new + +if THREADS +THREADSLIB = -lpthread +endif + +if OMP_SUPPORT +TLS_TEST_C_CFLAGS = -fopenmp +endif + +# 'make clean' is good about deleting some intermediate files (such as +# .o's), but not all of them (such as .so's and .err files). We +# improve on that here. automake-1.9 info docs say "mostlyclean" is +# the right choice for files 'make' builds that people rebuild. +MOSTLYCLEANFILES = *.so + + +# We will add to these later, for each individual test. Note +# that we add each test under check_SCRIPTS or check_PROGRAMS; +# the TESTS variable is automatically populated from these. +check_SCRIPTS = +check_DATA = +check_PROGRAMS = +BUILT_SOURCES = + +TESTS = $(check_SCRIPTS) $(check_PROGRAMS) + +# --------------------------------------------------------------------- +# These tests test the internals of gold (unittests). + +# Infrastucture needed for the unittests +check_LIBRARIES = libgoldtest.a +libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc + +DEPENDENCIES = \ + libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP) +LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ + $(THREADSLIB) + + +# The unittests themselves +check_PROGRAMS += object_unittest +object_unittest_SOURCES = object_unittest.cc + +check_PROGRAMS += binary_unittest +binary_unittest_SOURCES = binary_unittest.cc + + +# --------------------------------------------------------------------- +# These tests test the output of gold (end-to-end tests). In +# particular, they make sure that gold can link "difficult" object +# files, and the resulting object files run correctly. These can only +# run if we've built ld-new for the native architecture (that is, +# we're not cross-compiling it), since we run ld-new as part of these +# tests. We use the gcc-specific flag '-B' to use our linker instead +# of the default linker, which is why we only run our tests under gcc. + +if NATIVE_LINKER +if GCC + +# Infrastucture needed for the unittests: a directory where the linker +# is named 'ld'. This is because the -B flag appends 'ld' to its arg. +gcctestdir/ld: ../ld-new + test -d gcctestdir || mkdir -p gcctestdir + rm -f gcctestdir/ld + (cd gcctestdir && $(LN_S) ../../ld-new ld) + +# Each of these .o's is a useful, small complete program. They're +# particularly useful for making sure ld-new's flags do what they're +# supposed to (hence their names), but are used for many tests that +# don't actually involve analyzing input data. +flagstest_debug.o: constructor_test.cc + $(CXXCOMPILE) -O0 -g -c -o $@ $< +flagstest_ndebug.o: constructor_test.cc + $(CXXCOMPILE) -O0 -c -o $@ $< + + +check_PROGRAMS += basic_test +check_PROGRAMS += basic_static_test +check_PROGRAMS += basic_pic_test +check_PROGRAMS += basic_static_pic_test +basic_test.o: basic_test.cc + $(CXXCOMPILE) -O0 -c -o $@ $< +basic_test: basic_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ basic_test.o +basic_static_test: basic_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -static basic_test.o + +basic_pic_test.o: basic_test.cc + $(CXXCOMPILE) -O0 -c -fpic -o $@ $< +basic_pic_test: basic_pic_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ basic_pic_test.o +basic_static_pic_test: basic_pic_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -static basic_pic_test.o + + +check_PROGRAMS += constructor_test +check_PROGRAMS += constructor_static_test +constructor_test_SOURCES = constructor_test.cc +constructor_test_DEPENDENCIES = gcctestdir/ld +constructor_test_LDFLAGS = -Bgcctestdir/ + +constructor_static_test_SOURCES = $(constructor_test_SOURCES) +constructor_static_test_DEPENDENCIES = $(constructor_test_DEPENDENCIES) +constructor_static_test_LDFLAGS = $(constructor_test_LDFLAGS) -static + + +check_PROGRAMS += two_file_test +check_PROGRAMS += two_file_static_test +check_PROGRAMS += two_file_pic_test +two_file_test_SOURCES = \ + two_file_test_1.cc \ + two_file_test_1b.cc \ + two_file_test_2.cc \ + two_file_test_main.cc \ + two_file_test.h +two_file_test_DEPENDENCIES = gcctestdir/ld +two_file_test_LDFLAGS = -Bgcctestdir/ + +two_file_static_test_SOURCES = $(two_file_test_SOURCES) +two_file_static_test_DEPENDENCIES = $(two_file_test_DEPENDENCIES) +two_file_static_test_LDFLAGS = $(two_file_test_LDFLAGS) -static + +two_file_pic_test_SOURCES = two_file_test_main.cc +two_file_pic_test_DEPENDENCIES = \ + gcctestdir/ld two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o +two_file_pic_test_LDFLAGS = -Bgcctestdir/ +two_file_pic_test_LDADD = two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o + + +check_PROGRAMS += two_file_shared_1_test +check_PROGRAMS += two_file_shared_2_test +check_PROGRAMS += two_file_shared_1_pic_2_test +check_PROGRAMS += two_file_shared_2_pic_1_test +check_PROGRAMS += two_file_same_shared_test +check_PROGRAMS += two_file_separate_shared_12_test +check_PROGRAMS += two_file_separate_shared_21_test +two_file_test_1_pic.o: two_file_test_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +two_file_test_1b_pic.o: two_file_test_1b.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +two_file_test_2_pic.o: two_file_test_2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +two_file_shared_1.so: two_file_test_1_pic.o two_file_test_1b_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o +two_file_shared_2.so: two_file_test_2_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_2_pic.o +two_file_shared.so: two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o + +two_file_shared_1_test_SOURCES = two_file_test_2.cc two_file_test_main.cc +two_file_shared_1_test_DEPENDENCIES = gcctestdir/ld two_file_shared_1.so +two_file_shared_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_shared_1_test_LDADD = two_file_shared_1.so + +two_file_shared_2_test_SOURCES = two_file_test_1.cc two_file_test_1b.cc two_file_test_main.cc +two_file_shared_2_test_DEPENDENCIES = gcctestdir/ld two_file_shared_2.so +two_file_shared_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_shared_2_test_LDADD = two_file_shared_2.so + +two_file_shared_1_pic_2_test_SOURCES = two_file_test_main.cc +two_file_shared_1_pic_2_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_1.so two_file_test_1_pic.o two_file_test_1b_pic.o +two_file_shared_1_pic_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_shared_1_pic_2_test_LDADD = two_file_test_1_pic.o two_file_test_1b_pic.o two_file_shared_2.so + +two_file_shared_2_pic_1_test_SOURCES = two_file_test_main.cc +two_file_shared_2_pic_1_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_2.so two_file_test_2_pic.o +two_file_shared_2_pic_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_shared_2_pic_1_test_LDADD = two_file_test_2_pic.o two_file_shared_1.so + +two_file_same_shared_test_SOURCES = two_file_test_main.cc +two_file_same_shared_test_DEPENDENCIES = gcctestdir/ld two_file_shared.so +two_file_same_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_same_shared_test_LDADD = two_file_shared.so + +two_file_separate_shared_12_test_SOURCES = two_file_test_main.cc +two_file_separate_shared_12_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_1.so two_file_shared_2.so +two_file_separate_shared_12_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_separate_shared_12_test_LDADD = \ + two_file_shared_1.so two_file_shared_2.so + +two_file_separate_shared_21_test_SOURCES = two_file_test_main.cc +two_file_separate_shared_21_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_1.so two_file_shared_2.so +two_file_separate_shared_21_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_separate_shared_21_test_LDADD = \ + two_file_shared_2.so two_file_shared_1.so + +check_PROGRAMS += two_file_relocatable_test +two_file_relocatable_test_SOURCES = two_file_test_main.cc +two_file_relocatable_test_DEPENDENCIES = \ + gcctestdir/ld two_file_relocatable.o +two_file_relocatable_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_relocatable_test_LDADD = two_file_relocatable.o +two_file_relocatable.o: gcctestdir/ld two_file_test_1.o two_file_test_1b.o two_file_test_2.o + gcctestdir/ld -r -o $@ two_file_test_1.o two_file_test_1b.o two_file_test_2.o + +# The nonpic tests will fail on platforms which can not put non-PIC +# code into shared libraries, so we just don't run them in that case. +if FN_PTRS_IN_SO_WITHOUT_PIC + +check_PROGRAMS += two_file_shared_1_nonpic_test +check_PROGRAMS += two_file_shared_2_nonpic_test +check_PROGRAMS += two_file_same_shared_nonpic_test +check_PROGRAMS += two_file_separate_shared_12_nonpic_test +check_PROGRAMS += two_file_separate_shared_21_nonpic_test +check_PROGRAMS += two_file_mixed_shared_test +check_PROGRAMS += two_file_mixed_2_shared_test +two_file_shared_1_nonpic.so: two_file_test_1.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b.o +two_file_shared_2_nonpic.so: two_file_test_2.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_2.o +two_file_shared_nonpic.so: two_file_test_1.o two_file_test_1b.o two_file_test_2.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b.o two_file_test_2.o +two_file_shared_mixed.so: two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2.o +two_file_shared_mixed_1.so: two_file_test_1.o two_file_test_1b_pic.o two_file_shared_2.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b_pic.o two_file_shared_2.so + +two_file_shared_1_nonpic_test_SOURCES = \ + two_file_test_2.cc two_file_test_main.cc +two_file_shared_1_nonpic_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_1_nonpic.so +two_file_shared_1_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_shared_1_nonpic_test_LDADD = two_file_shared_1_nonpic.so + +two_file_shared_2_nonpic_test_SOURCES = \ + two_file_test_1.cc two_file_test_1b.cc two_file_test_main.cc +two_file_shared_2_nonpic_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_2_nonpic.so +two_file_shared_2_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_shared_2_nonpic_test_LDADD = two_file_shared_2_nonpic.so + +two_file_same_shared_nonpic_test_SOURCES = two_file_test_main.cc +two_file_same_shared_nonpic_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_nonpic.so +two_file_same_shared_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_same_shared_nonpic_test_LDADD = two_file_shared_nonpic.so + +two_file_separate_shared_12_nonpic_test_SOURCES = two_file_test_main.cc +two_file_separate_shared_12_nonpic_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_1_nonpic.so two_file_shared_2_nonpic.so +two_file_separate_shared_12_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_separate_shared_12_nonpic_test_LDADD = \ + two_file_shared_1_nonpic.so two_file_shared_2_nonpic.so + +two_file_separate_shared_21_nonpic_test_SOURCES = two_file_test_main.cc +two_file_separate_shared_21_nonpic_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_1_nonpic.so two_file_shared_2_nonpic.so +two_file_separate_shared_21_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_separate_shared_21_nonpic_test_LDADD = \ + two_file_shared_2_nonpic.so two_file_shared_1_nonpic.so + +two_file_mixed_shared_test_SOURCES = two_file_test_main.cc +two_file_mixed_shared_test_DEPENDENCIES = gcctestdir/ld two_file_shared_mixed.so +two_file_mixed_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_mixed_shared_test_LDADD = two_file_shared_mixed.so + +two_file_mixed_2_shared_test_SOURCES = two_file_test_main.cc +two_file_mixed_2_shared_test_DEPENDENCIES = gcctestdir/ld two_file_shared_mixed_1.so two_file_shared_2.so +two_file_mixed_2_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +two_file_mixed_2_shared_test_LDADD = two_file_shared_mixed_1.so two_file_shared_2.so + +endif FN_PTRS_IN_SO_WITHOUT_PIC + +check_PROGRAMS += two_file_strip_test +two_file_strip_test: two_file_test + $(TEST_STRIP) -o two_file_strip_test two_file_test + +check_PROGRAMS += two_file_same_shared_strip_test +two_file_same_shared_strip_test_SOURCES = two_file_test_main.cc +two_file_same_shared_strip_test_DEPENDENCIES = \ + gcctestdir/ld two_file_shared_strip.so +two_file_same_shared_strip_test_LDFLAGS = -Bgcctestdir/ -Wl,-R. +two_file_same_shared_strip_test_LDADD = two_file_shared_strip.so +two_file_shared_strip.so: two_file_shared.so + $(TEST_STRIP) -S -o two_file_shared_strip.so two_file_shared.so + +check_PROGRAMS += common_test_1 +common_test_1_SOURCES = common_test_1.c +common_test_1_DEPENDENCIES = gcctestdir/ld +common_test_1_LDFLAGS = -Bgcctestdir/ + +check_PROGRAMS += exception_test +check_PROGRAMS += exception_static_test +check_PROGRAMS += exception_shared_1_test +check_PROGRAMS += exception_shared_2_test +check_PROGRAMS += exception_same_shared_test +check_PROGRAMS += exception_separate_shared_12_test +check_PROGRAMS += exception_separate_shared_21_test +exception_test_1_pic.o: exception_test_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +exception_test_2_pic.o: exception_test_2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +exception_shared_1.so: exception_test_1_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared exception_test_1_pic.o +exception_shared_2.so: exception_test_2_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared exception_test_2_pic.o +exception_shared.so: exception_test_1_pic.o exception_test_2_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared exception_test_1_pic.o exception_test_2_pic.o + +exception_test_SOURCES = \ + exception_test_main.cc \ + exception_test_1.cc \ + exception_test_2.cc \ + exception_test.h +exception_test_DEPENDENCIES = gcctestdir/ld +exception_test_LDFLAGS = -Bgcctestdir/ + +exception_static_test_SOURCES = $(exception_test_SOURCES) +exception_static_test_DEPENDENCIES = $(exception_test_DEPENDENCIES) +exception_static_test_LDFLAGS = $(exception_test_LDFLAGS) -static + +exception_shared_1_test_SOURCES = exception_test_2.cc exception_test_main.cc +exception_shared_1_test_DEPENDENCIES = gcctestdir/ld exception_shared_1.so +exception_shared_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +exception_shared_1_test_LDADD = exception_shared_1.so + +exception_shared_2_test_SOURCES = exception_test_1.cc exception_test_main.cc +exception_shared_2_test_DEPENDENCIES = gcctestdir/ld exception_shared_2.so +exception_shared_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +exception_shared_2_test_LDADD = exception_shared_2.so + +exception_same_shared_test_SOURCES = exception_test_main.cc +exception_same_shared_test_DEPENDENCIES = gcctestdir/ld exception_shared.so +exception_same_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +exception_same_shared_test_LDADD = exception_shared.so + +exception_separate_shared_12_test_SOURCES = exception_test_main.cc +exception_separate_shared_12_test_DEPENDENCIES = \ + gcctestdir/ld exception_shared_1.so exception_shared_2.so +exception_separate_shared_12_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +exception_separate_shared_12_test_LDADD = \ + exception_shared_1.so exception_shared_2.so + +exception_separate_shared_21_test_SOURCES = exception_test_main.cc +exception_separate_shared_21_test_DEPENDENCIES = \ + gcctestdir/ld exception_shared_1.so exception_shared_2.so +exception_separate_shared_21_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +exception_separate_shared_21_test_LDADD = \ + exception_shared_2.so exception_shared_1.so + + +check_PROGRAMS += weak_test +weak_test_SOURCES = weak_test.cc +weak_test_DEPENDENCIES = gcctestdir/ld +weak_test_LDFLAGS = -Bgcctestdir/ + +check_PROGRAMS += weak_undef_test +weak_undef_test_SOURCES = weak_undef_test.cc +weak_undef_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib.so alt/weak_undef_lib.so +weak_undef_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt +weak_undef_test_LDADD = -L . weak_undef_lib.so +weak_undef_file1.o: weak_undef_file1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_undef_file2.o: weak_undef_file2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_undef_lib.so: weak_undef_file1.o + $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file1.o +alt/weak_undef_lib.so: weak_undef_file2.o + test -d alt || mkdir -p alt + $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file2.o + +if FN_PTRS_IN_SO_WITHOUT_PIC +check_PROGRAMS += weak_undef_nonpic_test +weak_undef_nonpic_test_SOURCES = weak_undef_test.cc +weak_undef_nonpic_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib_nonpic.so alt/weak_undef_lib_nonpic.so +weak_undef_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt +weak_undef_nonpic_test_LDADD = -L . weak_undef_lib_nonpic.so +weak_undef_file1_nonpic.o: weak_undef_file1.cc + $(CXXCOMPILE) -c -o $@ $< +weak_undef_file2_nonpic.o: weak_undef_file2.cc + $(CXXCOMPILE) -c -o $@ $< +weak_undef_lib_nonpic.so: weak_undef_file1_nonpic.o + $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file1_nonpic.o +alt/weak_undef_lib_nonpic.so: weak_undef_file2_nonpic.o + test -d alt || mkdir -p alt + $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file2_nonpic.o +endif FN_PTRS_IN_SO_WITHOUT_PIC + + +check_PROGRAMS += weak_alias_test +weak_alias_test_SOURCES = weak_alias_test_main.cc +weak_alias_test_DEPENDENCIES = \ + gcctestdir/ld weak_alias_test_1.so weak_alias_test_2.so \ + weak_alias_test_3.o weak_alias_test_4.so +weak_alias_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +weak_alias_test_LDADD = \ + weak_alias_test_1.so weak_alias_test_2.so weak_alias_test_3.o \ + weak_alias_test_4.so +weak_alias_test_1_pic.o: weak_alias_test_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_alias_test_1.so: weak_alias_test_1_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared weak_alias_test_1_pic.o +weak_alias_test_2_pic.o: weak_alias_test_2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_alias_test_2.so: weak_alias_test_2_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared weak_alias_test_2_pic.o +weak_alias_test_3.o: weak_alias_test_3.cc + $(CXXCOMPILE) -c -o $@ $< +weak_alias_test_4_pic.o: weak_alias_test_4.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_alias_test_4.so: weak_alias_test_4_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared weak_alias_test_4_pic.o + +check_SCRIPTS += weak_plt.sh +check_PROGRAMS += weak_plt +check_DATA += weak_plt_shared.so +weak_plt_main_pic.o: weak_plt_main.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_plt: weak_plt_main_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ weak_plt_main_pic.o +weak_plt_shared_pic.o: weak_plt_shared.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +weak_plt_shared.so: weak_plt_shared_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared weak_plt_shared_pic.o + +check_PROGRAMS += copy_test +copy_test_SOURCES = copy_test.cc +copy_test_DEPENDENCIES = gcctestdir/ld copy_test_1.so copy_test_2.so +copy_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +copy_test_LDADD = copy_test_1.so copy_test_2.so +copy_test_1_pic.o: copy_test_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +copy_test_1.so: gcctestdir/ld copy_test_1_pic.o + $(CXXLINK) -Bgcctestdir/ -shared copy_test_1_pic.o +copy_test_2_pic.o: copy_test_2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +copy_test_2.so: gcctestdir/ld copy_test_2_pic.o + $(CXXLINK) -Bgcctestdir/ -shared copy_test_2_pic.o + +if TLS + +check_PROGRAMS += tls_test +check_PROGRAMS += tls_pic_test +check_PROGRAMS += tls_shared_test +check_PROGRAMS += tls_shared_ie_test +check_PROGRAMS += tls_shared_gd_to_ie_test +tls_test_pic.o: tls_test.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +tls_test_file2_pic.o: tls_test_file2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +tls_test_c_pic.o: tls_test_c.c + $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $< +tls_test_shared.so: tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o +tls_test_shared2.so: tls_test_file2_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_pic.o + +tls_test_pic_ie.o: tls_test.cc + $(CXXCOMPILE) -c -fpic -ftls-model=initial-exec -o $@ $< +tls_test_file2_pic_ie.o: tls_test_file2.cc + $(CXXCOMPILE) -c -fpic -ftls-model=initial-exec -o $@ $< +tls_test_c_pic_ie.o: tls_test_c.c + $(COMPILE) -c -fpic -ftls-model=initial-exec $(TLS_TEST_C_CFLAGS) -o $@ $< +tls_test_ie_shared.so: tls_test_pic_ie.o tls_test_file2_pic_ie.o tls_test_c_pic_ie.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic_ie.o tls_test_file2_pic_ie.o tls_test_c_pic_ie.o + +tls_test_SOURCES = tls_test.cc tls_test_file2.cc tls_test_main.cc tls_test.h +tls_test_DEPENDENCIES = gcctestdir/ld tls_test_c.o +tls_test_LDFLAGS = -Bgcctestdir/ +tls_test_LDADD = tls_test_c.o -lpthread +tls_test_c.o: tls_test_c.c + $(COMPILE) -c $(TLS_TEST_C_CFLAGS) -o $@ $< + +tls_pic_test_SOURCES = tls_test_main.cc +tls_pic_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o tls_test_file2_pic.o \ + tls_test_c_pic.o +tls_pic_test_LDFLAGS = -Bgcctestdir/ +tls_pic_test_LDADD = tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o \ + -lpthread + +tls_shared_test_SOURCES = tls_test_main.cc +tls_shared_test_DEPENDENCIES = gcctestdir/ld tls_test_shared.so +tls_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +tls_shared_test_LDADD = tls_test_shared.so -lpthread + +tls_shared_ie_test_SOURCES = tls_test_main.cc +tls_shared_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_ie_shared.so +tls_shared_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +tls_shared_ie_test_LDADD = tls_test_ie_shared.so -lpthread + +tls_shared_gd_to_ie_test_SOURCES = tls_test_main.cc +tls_shared_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o \ + tls_test_c_pic.o tls_test_shared2.so +tls_shared_gd_to_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +tls_shared_gd_to_ie_test_LDADD = tls_test_pic.o tls_test_c_pic.o \ + tls_test_shared2.so -lpthread + +if TLS_GNU2_DIALECT + +check_PROGRAMS += tls_shared_gnu2_gd_to_ie_test + +tls_test_gnu2.o: tls_test.cc + $(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $< +tls_test_file2_gnu2.o: tls_test_file2.cc + $(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $< +tls_test_c_gnu2.o: tls_test_c.c + $(COMPILE) -c -fpic -mtls-dialect=gnu2 $(TLS_TEST_C_CFLAGS) -o $@ $< +tls_test_gnu2_shared2.so: tls_test_file2_gnu2.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_gnu2.o + +tls_shared_gnu2_gd_to_ie_test_SOURCES = tls_test_main.cc +tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2.o \ + tls_test_c_gnu2.o tls_test_gnu2_shared2.so +tls_shared_gnu2_gd_to_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +tls_shared_gnu2_gd_to_ie_test_LDADD = tls_test_gnu2.o tls_test_c_gnu2.o \ + tls_test_gnu2_shared2.so -lpthread + +if TLS_DESCRIPTORS + +check_PROGRAMS += tls_shared_gnu2_test + +tls_test_gnu2_shared.so: tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o + +tls_shared_gnu2_test_SOURCES = tls_test_main.cc +tls_shared_gnu2_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2_shared.so +tls_shared_gnu2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +tls_shared_gnu2_test_LDADD = tls_test_gnu2_shared.so -lpthread + +endif TLS_DESCRIPTORS + +endif TLS_GNU2_DIALECT + +if STATIC_TLS +check_PROGRAMS += tls_static_test +check_PROGRAMS += tls_static_pic_test + +tls_static_test_SOURCES = $(tls_test_SOURCES) +tls_static_test_DEPENDENCIES = $(tls_test_DEPENDENCIES) +tls_static_test_LDFLAGS = $(tls_test_LDFLAGS) -static +tls_static_test_LDADD = $(tls_test_LDADD) + +tls_static_pic_test_SOURCES = $(tls_pic_test_SOURCES) +tls_static_pic_test_DEPENDENCIES = $(tls_pic_test_DEPENDENCIES) +tls_static_pic_test_LDFLAGS = $(tls_pic_test_LDFLAGS) -static +tls_static_pic_test_LDADD = $(tls_pic_test_LDADD) +endif + +if FN_PTRS_IN_SO_WITHOUT_PIC +check_PROGRAMS += tls_shared_nonpic_test +tls_test_shared_nonpic.so: tls_test.o tls_test_file2.o tls_test_c.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared tls_test.o tls_test_file2.o tls_test_c.o + +tls_shared_nonpic_test_SOURCES = tls_test_main.cc +tls_shared_nonpic_test_DEPENDENCIES = gcctestdir/ld tls_test_shared_nonpic.so +tls_shared_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +tls_shared_nonpic_test_LDADD = tls_test_shared_nonpic.so -lpthread +endif FN_PTRS_IN_SO_WITHOUT_PIC + +endif TLS + +check_PROGRAMS += many_sections_test +many_sections_test_SOURCES = many_sections_test.cc +many_sections_test_DEPENDENCIES = gcctestdir/ld +many_sections_test_LDFLAGS = -Bgcctestdir/ -rdynamic + +BUILT_SOURCES += many_sections_define.h +many_sections_define.h: + (for i in `seq 1 70000`; do \ + echo "int var_$$i __attribute__((section(\"section_$$i\"))) = $$i;"; \ + done) > $@.tmp + mv -f $@.tmp $@ + +BUILT_SOURCES += many_sections_check.h +many_sections_check.h: + (for i in `seq 1 1000 70000`; do \ + echo "assert(var_$$i == $$i);"; \ + done) > $@.tmp + mv -f $@.tmp $@ + +check_PROGRAMS += many_sections_r_test +many_sections_r_test.o: many_sections_test.o gcctestdir/ld + gcctestdir/ld -r -o $@ many_sections_test.o +many_sections_r_test: many_sections_r_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ many_sections_r_test.o $(LIBS) + +if CONSTRUCTOR_PRIORITY + +check_PROGRAMS += initpri1 +initpri1_SOURCES = initpri1.c +initpri1_DEPENDENCIES = gcctestdir/ld +initpri1_LDFLAGS = -Bgcctestdir/ + +endif + + +# Test --detect-odr-violations +check_SCRIPTS += debug_msg.sh + +# Create the data files that debug_msg.sh analyzes. +check_DATA += debug_msg.err +MOSTLYCLEANFILES += debug_msg.err +debug_msg.o: debug_msg.cc + $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc +odr_violation1.o: odr_violation1.cc + $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation1.cc +odr_violation2.o: odr_violation2.cc + $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation2.cc +debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o gcctestdir/ld + @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o 2>$@; \ + then \ + echo 1>&2 "Link of debug_msg should have failed"; \ + rm -f $@; \ + exit 1; \ + fi + +# See if we can also detect problems when we're linking .so's, not .o's. +check_DATA += debug_msg_so.err +MOSTLYCLEANFILES += debug_msg_so.err +debug_msg.so: debug_msg.cc gcctestdir/ld + $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -shared -fPIC -w -o $@ $(srcdir)/debug_msg.cc +odr_violation1.so: odr_violation1.cc gcctestdir/ld + $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -shared -fPIC -w -o $@ $(srcdir)/odr_violation1.cc +odr_violation2.so: odr_violation2.cc gcctestdir/ld + $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -shared -fPIC -w -o $@ $(srcdir)/odr_violation2.cc +debug_msg_so.err: debug_msg.so odr_violation1.so odr_violation2.so gcctestdir/ld + @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_so debug_msg.so odr_violation1.so odr_violation2.so "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_so debug_msg.so odr_violation1.so odr_violation2.so 2>$@; \ + then \ + echo 1>&2 "Link of debug_msg_so should have failed"; \ + rm -f $@; \ + exit 1; \ + fi + +# We also want to make sure we do something reasonable when there's no +# debug info available. For the best test, we use .so's. +check_DATA += debug_msg_ndebug.err +MOSTLYCLEANFILES += debug_msg_ndebug.err +debug_msg_ndebug.so: debug_msg.cc gcctestdir/ld + $(CXXCOMPILE) -Bgcctestdir/ -O0 -g0 -shared -fPIC -w -o $@ $(srcdir)/debug_msg.cc +odr_violation1_ndebug.so: odr_violation1.cc gcctestdir/ld + $(CXXCOMPILE) -Bgcctestdir/ -O0 -g0 -shared -fPIC -w -o $@ $(srcdir)/odr_violation1.cc +odr_violation2_ndebug.so: odr_violation2.cc gcctestdir/ld + $(CXXCOMPILE) -Bgcctestdir/ -O0 -g0 -shared -fPIC -w -o $@ $(srcdir)/odr_violation2.cc +debug_msg_ndebug.err: debug_msg_ndebug.so odr_violation1_ndebug.so odr_violation2_ndebug.so gcctestdir/ld + @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_ndebug debug_msg_ndebug.so odr_violation1_ndebug.so odr_violation2_ndebug.so "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_ndebug debug_msg_ndebug.so odr_violation1_ndebug.so odr_violation2_ndebug.so 2>$@; \ + then \ + echo 1>&2 "Link of debug_msg_ndebug should have failed"; \ + rm -f $@; \ + exit 1; \ + fi + + +# Similar to --detect-odr-violations: check for undefined symbols in .so's +check_SCRIPTS += undef_symbol.sh +check_DATA += undef_symbol.err +MOSTLYCLEANFILES += undef_symbol.err +undef_symbol.o: undef_symbol.cc + $(CXXCOMPILE) -O0 -g -c -fPIC $< +undef_symbol.so: undef_symbol.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared undef_symbol.o +undef_symbol.err: undef_symbol_main.o undef_symbol.so gcctestdir/ld + @echo $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so 2>$@; \ + then \ + echo 1>&2 "Link of undef_symbol_test should have failed"; \ + rm -f $@; \ + exit 1; \ + fi + + +# Test -o when emitting to a special file (such as something in /dev). +check_PROGRAMS += flagstest_o_specialfile +flagstest_o_specialfile: flagstest_debug.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -o /dev/stdout $< 2>&1 | cat > $@ + chmod a+x $@ + test -s $@ + +if HAVE_ZLIB + +# Test --compress-debug-sections. FIXME: check we actually compress. +check_PROGRAMS += flagstest_compress_debug_sections +flagstest_compress_debug_sections: flagstest_debug.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -o $@ $< -Wl,--compress-debug-sections=zlib + test -s $@ + + +# The specialfile output has a tricky case when we also compress debug +# sections, because it requires output-file resizing. +check_PROGRAMS += flagstest_o_specialfile_and_compress_debug_sections +flagstest_o_specialfile_and_compress_debug_sections: flagstest_debug.o \ + gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -o /dev/stdout $< -Wl,--compress-debug-sections=zlib 2>&1 | cat > $@ + chmod a+x $@ + test -s $@ + +endif HAVE_ZLIB + +# Test symbol versioning. +check_PROGRAMS += ver_test +ver_test_SOURCES = ver_test_main.cc +ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so +ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +ver_test_LDADD = ver_test_1.so ver_test_2.so ver_test_4.so +ver_test_1.so: ver_test_1.o ver_test_2.so ver_test_3.o ver_test_4.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared ver_test_1.o ver_test_2.so ver_test_3.o ver_test_4.so +ver_test_2.so: ver_test_2.o $(srcdir)/ver_test_2.script ver_test_4.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_2.script ver_test_2.o ver_test_4.so +ver_test_4.so: ver_test_4.o $(srcdir)/ver_test_4.script gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_4.script ver_test_4.o +ver_test_1.o: ver_test_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +ver_test_2.o: ver_test_2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +ver_test_3.o: ver_test_3.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +ver_test_4.o: ver_test_4.cc + $(CXXCOMPILE) -c -fpic -o $@ $< + +check_PROGRAMS += ver_test_2 +ver_test_2_SOURCES = ver_test_main_2.cc +ver_test_2_DEPENDENCIES = gcctestdir/ld ver_test_4.so ver_test_2.so +ver_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +ver_test_2_LDADD = ver_test_4.so ver_test_2.so + +check_SCRIPTS += ver_test_2.sh +check_DATA += ver_test_2.syms +ver_test_2.syms: ver_test_2 + $(TEST_READELF) -s $< >$@ 2>/dev/null + +check_SCRIPTS += ver_test_4.sh +check_DATA += ver_test_4.syms +ver_test_4.syms: ver_test_4.so + $(TEST_READELF) -s $< >$@ 2>/dev/null + +ver_test_5.so: ver_test_5.o $(srcdir)/ver_test_5.script ver_test_4.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_5.script ver_test_5.o ver_test_4.so +ver_test_5.o: ver_test_5.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +check_SCRIPTS += ver_test_5.sh +check_DATA += ver_test_5.syms +ver_test_5.syms: ver_test_5.so + $(TEST_READELF) -s $< >$@ 2>/dev/null + +check_PROGRAMS += ver_test_6 +ver_test_6_SOURCES = ver_test_6.c +ver_test_6_DEPENDENCIES = gcctestdir/ld ver_test_2.so +ver_test_6_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +ver_test_6_LDADD = ver_test_2.so + +ver_test_7.so: ver_test_4.o $(srcdir)/ver_test_4.script ver_test_7.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_4.script ver_test_4.o ver_test_7.o +ver_test_7.o: ver_test_7.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +check_SCRIPTS += ver_test_7.sh +check_DATA += ver_test_7.syms +ver_test_7.syms: ver_test_7.so + $(TEST_READELF) -s $< >$@ 2>/dev/null + +check_PROGRAMS += ver_test_8 +ver_test_8_SOURCES = two_file_test_main.cc +ver_test_8_DEPENDENCIES = gcctestdir/ld ver_test_8_1.so ver_test_8_2.so +ver_test_8_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +ver_test_8_LDADD = ver_test_8_1.so ver_test_8_2.so +ver_test_8_1.so: two_file_test_1_pic.o two_file_test_1b_pic.o ver_test_8_2.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o ver_test_8_2.so +ver_test_8_2.so: two_file_test_2_pic.o $(srcdir)/ver_test_8.script gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_8.script two_file_test_2_pic.o + +check_PROGRAMS += ver_test_9 +ver_test_9_SOURCES = ver_test_main.cc +ver_test_9_DEPENDENCIES = gcctestdir/ld ver_test_9.so +ver_test_9_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +ver_test_9_LDADD = ver_test_9.so +ver_test_9.so: ver_test_9.o ver_test_4.so ver_test_5.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -shared ver_test_9.o ver_test_5.so ver_test_4.so +ver_test_9.o: ver_test_9.cc + $(CXXCOMPILE) -c -fpic -o $@ $< + +check_SCRIPTS += ver_test_10.sh +check_DATA += ver_test_10.syms +ver_test_10.syms: ver_test_10.so + $(TEST_READELF) -s $< >$@ 2>/dev/null +ver_test_10.so: gcctestdir/ld ver_test_2.o ver_test_10.script + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_10.script ver_test_2.o + +check_PROGRAMS += protected_1 +protected_1_SOURCES = \ + protected_main_1.cc protected_main_2.cc protected_main_3.cc +protected_1_DEPENDENCIES = gcctestdir/ld protected_1.so +protected_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +protected_1_LDADD = protected_1.so + +protected_1.so: gcctestdir/ld protected_1_pic.o protected_2_pic.o protected_3_pic.o + $(CXXLINK) -Bgcctestdir/ -shared protected_1_pic.o protected_2_pic.o protected_3_pic.o +protected_1_pic.o: protected_1.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +protected_2_pic.o: protected_2.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +protected_3_pic.o: protected_3.cc + $(CXXCOMPILE) -c -fpic -o $@ $< + +check_PROGRAMS += protected_2 +protected_2_SOURCES = protected_main_1.cc protected_3.cc +protected_2_DEPENDENCIES = gcctestdir/ld protected_1.so +protected_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +protected_2_LDADD = protected_1.so + +check_PROGRAMS += relro_test +relro_test_SOURCES = relro_test_main.cc +relro_test_DEPENDENCIES = gcctestdir/ld relro_test.so +relro_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +relro_test_LDADD = relro_test.so +relro_test.so: gcctestdir/ld relro_test_pic.o + $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro relro_test_pic.o +relro_test_pic.o: relro_test.cc + $(CXXCOMPILE) -c -fpic -o $@ $< + +check_PROGRAMS += script_test_1 +script_test_1_SOURCES = script_test_1.cc +script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t +script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t + +check_PROGRAMS += script_test_2 +script_test_2_SOURCES = script_test_2.cc script_test_2a.cc script_test_2b.cc +script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t +script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t + +check_PROGRAMS += justsyms +justsyms_SOURCES = justsyms_1.cc +justsyms_DEPENDENCIES = gcctestdir/ld justsyms_2r.o +justsyms_LDFLAGS = -Bgcctestdir/ -Wl,-R,justsyms_2r.o +justsyms_2.o: justsyms_2.cc + $(CXXCOMPILE) -c -o $@ $< +justsyms_2r.o: justsyms_2.o gcctestdir/ld $(srcdir)/justsyms.t + gcctestdir/ld -o $@ -r -T $(srcdir)/justsyms.t justsyms_2.o + +check_PROGRAMS += binary_test +binary_test_SOURCES = binary_test.cc +binary_test_DEPENDENCIES = gcctestdir/ld binary.txt +binary_test_LDFLAGS = -Bgcctestdir/ -Wl,--format,binary,binary.txt,--format,elf +# Copy the file to the build directory to avoid worrying about the +# full pathname in the generated symbols. +binary.txt: $(srcdir)/binary.in + rm -f $@ + $(LN_S) $< $@ + +check_SCRIPTS += ver_matching_test.sh +check_DATA += ver_matching_test.stdout +MOSTLYCLEANFILES += ver_matching_test.stdout +ver_matching_def.so: ver_matching_def.cc gcctestdir/ld + $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map +ver_matching_test.stdout: ver_matching_def.so + $(TEST_OBJDUMP) -T ver_matching_def.so | $(TEST_CXXFILT) > ver_matching_test.stdout + +check_PROGRAMS += script_test_3 +check_SCRIPTS += script_test_3.sh +check_DATA += script_test_3.stdout +MOSTLYCLEANFILES += script_test_3.stdout +script_test_3: basic_test.o gcctestdir/ld script_test_3.t + $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_3.t +script_test_3.stdout: script_test_3 + $(TEST_READELF) -SlW script_test_3 > script_test_3.stdout + +check_SCRIPTS += script_test_4.sh +check_DATA += script_test_4.stdout +MOSTLYCLEANFILES += script_test_4.stdout +script_test_4: basic_test.o gcctestdir/ld $(srcdir)/script_test_4.t + $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_4.t +script_test_4.stdout: script_test_4 + $(TEST_READELF) -SlW script_test_4 > script_test_4.stdout + +endif GCC +endif NATIVE_LINKER diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in new file mode 100644 index 00000000000..c5e929a9cf3 --- /dev/null +++ b/gold/testsuite/Makefile.in @@ -0,0 +1,2300 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to generate Makefile.in + +# As far as I can tell automake testing support assumes that the build +# system and the host system are the same. So these tests will not +# work when building with a cross-compiler. +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ + $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ + $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \ + $(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \ + $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = basic_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test basic_pic_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_static_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_static_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_pic_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_pic_2_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_pic_1_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_relocatable_test +@GCC_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@constructor_static_test_DEPENDENCIES = libgoldtest.a \ +@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@constructor_static_test_DEPENDENCIES = \ +@NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ +@NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@two_file_static_test_DEPENDENCIES = libgoldtest.a \ +@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@two_file_static_test_DEPENDENCIES = \ +@NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ +@NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) + +# The nonpic tests will fail on platforms which can not put non-PIC +# code into shared libraries, so we just don't run them in that case. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_2 = two_file_shared_1_nonpic_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_nonpic_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_nonpic_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_nonpic_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_mixed_shared_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_mixed_2_shared_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = two_file_strip_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_strip_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1 exception_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_static_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_1_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_2_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_same_shared_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_12_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_21_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_test weak_undef_test +@GCC_FALSE@common_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@common_test_1_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@exception_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@exception_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@exception_static_test_DEPENDENCIES = libgoldtest.a \ +@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@exception_static_test_DEPENDENCIES = \ +@NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ +@NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@weak_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@weak_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = weak_undef_nonpic_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_5 = weak_alias_test weak_plt \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ copy_test + +# Test --detect-odr-violations + +# Similar to --detect-odr-violations: check for undefined symbols in .so's +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_6 = weak_plt.sh debug_msg.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_2.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh + +# Create the data files that debug_msg.sh analyzes. + +# See if we can also detect problems when we're linking .so's, not .o's. + +# We also want to make sure we do something reasonable when there's no +# debug info available. For the best test, we use .so's. +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_7 = weak_plt_shared.so \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.err debug_msg_so.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_2.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.syms ver_test_5.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.syms ver_test_10.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_8 = tls_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pic_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_ie_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_gd_to_ie_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__append_9 = tls_shared_gnu2_gd_to_ie_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__append_10 = tls_shared_gnu2_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am__append_11 = tls_static_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@ tls_static_pic_test +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_12 = tls_shared_nonpic_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_13 = many_sections_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test +@GCC_FALSE@many_sections_test_DEPENDENCIES = libgoldtest.a \ +@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@many_sections_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_14 = many_sections_define.h \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_check.h +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_15 = initpri1 +@CONSTRUCTOR_PRIORITY_FALSE@initpri1_DEPENDENCIES = libgoldtest.a \ +@CONSTRUCTOR_PRIORITY_FALSE@ ../libgold.a \ +@CONSTRUCTOR_PRIORITY_FALSE@ ../../libiberty/libiberty.a \ +@CONSTRUCTOR_PRIORITY_FALSE@ $(am__DEPENDENCIES_1) \ +@CONSTRUCTOR_PRIORITY_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@initpri1_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@initpri1_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = debug_msg.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout + +# Test -o when emitting to a special file (such as something in /dev). +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = flagstest_o_specialfile + +# Test --compress-debug-sections. FIXME: check we actually compress. + +# The specialfile output has a tricky case when we also compress debug +# sections, because it requires output-file resizing. +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_18 = flagstest_compress_debug_sections \ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections + +# Test symbol versioning. +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = ver_test ver_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6 ver_test_8 ver_test_9 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1 protected_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test script_test_1 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2 justsyms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test script_test_3 +@GCC_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@script_test_2_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@script_test_2_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@justsyms_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@justsyms_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@binary_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) +@NATIVE_LINKER_FALSE@binary_test_DEPENDENCIES = libgoldtest.a \ +@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +subdir = testsuite +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/gettext-sister.m4 \ + $(top_srcdir)/../config/lead-dot.m4 \ + $(top_srcdir)/../config/nls.m4 \ + $(top_srcdir)/../config/override.m4 \ + $(top_srcdir)/../config/po.m4 \ + $(top_srcdir)/../config/proginstall.m4 \ + $(top_srcdir)/../config/progtest.m4 \ + $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +AR = ar +ARFLAGS = cru +libgoldtest_a_AR = $(AR) $(ARFLAGS) +libgoldtest_a_LIBADD = +am_libgoldtest_a_OBJECTS = test.$(OBJEXT) testmain.$(OBJEXT) \ + testfile.$(OBJEXT) +libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_1 = basic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_static_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_static_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_pic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_pic_2_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_pic_1_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_relocatable_test$(EXEEXT) +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_2 = two_file_shared_1_nonpic_test$(EXEEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic_test$(EXEEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_nonpic_test$(EXEEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_nonpic_test$(EXEEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_nonpic_test$(EXEEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_mixed_shared_test$(EXEEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_mixed_2_shared_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_3 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_strip_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_strip_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_static_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_1_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_2_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_same_shared_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_12_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_21_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test$(EXEEXT) +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_4 = weak_undef_nonpic_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_5 = weak_alias_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ copy_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__EXEEXT_6 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_ie_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_gd_to_ie_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__EXEEXT_7 = tls_shared_gnu2_gd_to_ie_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__EXEEXT_8 = tls_shared_gnu2_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am__EXEEXT_9 = tls_static_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@ tls_static_pic_test$(EXEEXT) +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__EXEEXT_10 = tls_shared_nonpic_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_11 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test$(EXEEXT) +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_12 = initpri1$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_13 = flagstest_o_specialfile$(EXEEXT) +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_14 = flagstest_compress_debug_sections$(EXEEXT) \ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_15 = ver_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_2$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_8$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_9$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_2$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3$(EXEEXT) +basic_pic_test_SOURCES = basic_pic_test.c +basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT) +basic_pic_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +basic_pic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +basic_static_pic_test_SOURCES = basic_static_pic_test.c +basic_static_pic_test_OBJECTS = basic_static_pic_test.$(OBJEXT) +basic_static_pic_test_LDADD = $(LDADD) +basic_static_pic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +basic_static_test_SOURCES = basic_static_test.c +basic_static_test_OBJECTS = basic_static_test.$(OBJEXT) +basic_static_test_LDADD = $(LDADD) +basic_static_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +basic_test_SOURCES = basic_test.c +basic_test_OBJECTS = basic_test.$(OBJEXT) +basic_test_LDADD = $(LDADD) +basic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__binary_test_SOURCES_DIST = binary_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_binary_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test.$(OBJEXT) +binary_test_OBJECTS = $(am_binary_test_OBJECTS) +binary_test_LDADD = $(LDADD) +am_binary_unittest_OBJECTS = binary_unittest.$(OBJEXT) +binary_unittest_OBJECTS = $(am_binary_unittest_OBJECTS) +binary_unittest_LDADD = $(LDADD) +binary_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__common_test_1_SOURCES_DIST = common_test_1.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_common_test_1_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1.$(OBJEXT) +common_test_1_OBJECTS = $(am_common_test_1_OBJECTS) +common_test_1_LDADD = $(LDADD) +am__constructor_static_test_SOURCES_DIST = constructor_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__objects_1 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test.$(OBJEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_constructor_static_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(am__objects_1) +constructor_static_test_OBJECTS = \ + $(am_constructor_static_test_OBJECTS) +constructor_static_test_LDADD = $(LDADD) +am__constructor_test_SOURCES_DIST = constructor_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_constructor_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test.$(OBJEXT) +constructor_test_OBJECTS = $(am_constructor_test_OBJECTS) +constructor_test_LDADD = $(LDADD) +am__copy_test_SOURCES_DIST = copy_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_copy_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ copy_test.$(OBJEXT) +copy_test_OBJECTS = $(am_copy_test_OBJECTS) +am__exception_same_shared_test_SOURCES_DIST = exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_same_shared_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) +exception_same_shared_test_OBJECTS = \ + $(am_exception_same_shared_test_OBJECTS) +am__exception_separate_shared_12_test_SOURCES_DIST = \ + exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_separate_shared_12_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) +exception_separate_shared_12_test_OBJECTS = \ + $(am_exception_separate_shared_12_test_OBJECTS) +am__exception_separate_shared_21_test_SOURCES_DIST = \ + exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_separate_shared_21_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) +exception_separate_shared_21_test_OBJECTS = \ + $(am_exception_separate_shared_21_test_OBJECTS) +am__exception_shared_1_test_SOURCES_DIST = exception_test_2.cc \ + exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_shared_1_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) +exception_shared_1_test_OBJECTS = \ + $(am_exception_shared_1_test_OBJECTS) +am__exception_shared_2_test_SOURCES_DIST = exception_test_1.cc \ + exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_shared_2_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) +exception_shared_2_test_OBJECTS = \ + $(am_exception_shared_2_test_OBJECTS) +am__exception_static_test_SOURCES_DIST = exception_test_main.cc \ + exception_test_1.cc exception_test_2.cc exception_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__objects_2 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_2.$(OBJEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_static_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(am__objects_2) +exception_static_test_OBJECTS = $(am_exception_static_test_OBJECTS) +exception_static_test_LDADD = $(LDADD) +am__exception_test_SOURCES_DIST = exception_test_main.cc \ + exception_test_1.cc exception_test_2.cc exception_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_2.$(OBJEXT) +exception_test_OBJECTS = $(am_exception_test_OBJECTS) +exception_test_LDADD = $(LDADD) +flagstest_compress_debug_sections_SOURCES = \ + flagstest_compress_debug_sections.c +flagstest_compress_debug_sections_OBJECTS = \ + flagstest_compress_debug_sections.$(OBJEXT) +flagstest_compress_debug_sections_LDADD = $(LDADD) +flagstest_compress_debug_sections_DEPENDENCIES = libgoldtest.a \ + ../libgold.a ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +flagstest_o_specialfile_SOURCES = flagstest_o_specialfile.c +flagstest_o_specialfile_OBJECTS = flagstest_o_specialfile.$(OBJEXT) +flagstest_o_specialfile_LDADD = $(LDADD) +flagstest_o_specialfile_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +flagstest_o_specialfile_and_compress_debug_sections_SOURCES = \ + flagstest_o_specialfile_and_compress_debug_sections.c +flagstest_o_specialfile_and_compress_debug_sections_OBJECTS = \ + flagstest_o_specialfile_and_compress_debug_sections.$(OBJEXT) +flagstest_o_specialfile_and_compress_debug_sections_LDADD = $(LDADD) +flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES = \ + libgoldtest.a ../libgold.a ../../libiberty/libiberty.a \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__initpri1_SOURCES_DIST = initpri1.c +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_initpri1_OBJECTS = initpri1.$(OBJEXT) +initpri1_OBJECTS = $(am_initpri1_OBJECTS) +initpri1_LDADD = $(LDADD) +am__justsyms_SOURCES_DIST = justsyms_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_justsyms_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT) +justsyms_OBJECTS = $(am_justsyms_OBJECTS) +justsyms_LDADD = $(LDADD) +many_sections_r_test_SOURCES = many_sections_r_test.c +many_sections_r_test_OBJECTS = many_sections_r_test.$(OBJEXT) +many_sections_r_test_LDADD = $(LDADD) +many_sections_r_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__many_sections_test_SOURCES_DIST = many_sections_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_many_sections_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_test.$(OBJEXT) +many_sections_test_OBJECTS = $(am_many_sections_test_OBJECTS) +many_sections_test_LDADD = $(LDADD) +am_object_unittest_OBJECTS = object_unittest.$(OBJEXT) +object_unittest_OBJECTS = $(am_object_unittest_OBJECTS) +object_unittest_LDADD = $(LDADD) +object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__protected_1_SOURCES_DIST = protected_main_1.cc protected_main_2.cc \ + protected_main_3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_protected_1_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_3.$(OBJEXT) +protected_1_OBJECTS = $(am_protected_1_OBJECTS) +am__protected_2_SOURCES_DIST = protected_main_1.cc protected_3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_protected_2_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_3.$(OBJEXT) +protected_2_OBJECTS = $(am_protected_2_OBJECTS) +am__relro_test_SOURCES_DIST = relro_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_relro_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test_main.$(OBJEXT) +relro_test_OBJECTS = $(am_relro_test_OBJECTS) +am__script_test_1_SOURCES_DIST = script_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_1_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1.$(OBJEXT) +script_test_1_OBJECTS = $(am_script_test_1_OBJECTS) +script_test_1_LDADD = $(LDADD) +am__script_test_2_SOURCES_DIST = script_test_2.cc script_test_2a.cc \ + script_test_2b.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_2_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2a.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2b.$(OBJEXT) +script_test_2_OBJECTS = $(am_script_test_2_OBJECTS) +script_test_2_LDADD = $(LDADD) +script_test_3_SOURCES = script_test_3.c +script_test_3_OBJECTS = script_test_3.$(OBJEXT) +script_test_3_LDADD = $(LDADD) +script_test_3_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__tls_pic_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_pic_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_pic_test_OBJECTS = $(am_tls_pic_test_OBJECTS) +am__tls_shared_gd_to_ie_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_gd_to_ie_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_shared_gd_to_ie_test_OBJECTS = \ + $(am_tls_shared_gd_to_ie_test_OBJECTS) +am__tls_shared_gnu2_gd_to_ie_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am_tls_shared_gnu2_gd_to_ie_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_shared_gnu2_gd_to_ie_test_OBJECTS = \ + $(am_tls_shared_gnu2_gd_to_ie_test_OBJECTS) +am__tls_shared_gnu2_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am_tls_shared_gnu2_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_shared_gnu2_test_OBJECTS = $(am_tls_shared_gnu2_test_OBJECTS) +am__tls_shared_ie_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_ie_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_shared_ie_test_OBJECTS = $(am_tls_shared_ie_test_OBJECTS) +am__tls_shared_nonpic_test_SOURCES_DIST = tls_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_nonpic_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_shared_nonpic_test_OBJECTS = $(am_tls_shared_nonpic_test_OBJECTS) +am__tls_shared_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_test_OBJECTS = tls_test_main.$(OBJEXT) +tls_shared_test_OBJECTS = $(am_tls_shared_test_OBJECTS) +am__tls_static_pic_test_SOURCES_DIST = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__objects_3 = tls_test_main.$(OBJEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am_tls_static_pic_test_OBJECTS = $(am__objects_3) +tls_static_pic_test_OBJECTS = $(am_tls_static_pic_test_OBJECTS) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__DEPENDENCIES_2 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_file2_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c_pic.o +am__tls_static_test_SOURCES_DIST = tls_test.cc tls_test_file2.cc \ + tls_test_main.cc tls_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__objects_4 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_file2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_main.$(OBJEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am_tls_static_test_OBJECTS = $(am__objects_4) +tls_static_test_OBJECTS = $(am_tls_static_test_OBJECTS) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__DEPENDENCIES_3 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c.o +am__tls_test_SOURCES_DIST = tls_test.cc tls_test_file2.cc \ + tls_test_main.cc tls_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_file2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_main.$(OBJEXT) +tls_test_OBJECTS = $(am_tls_test_OBJECTS) +am__two_file_mixed_2_shared_test_SOURCES_DIST = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_mixed_2_shared_test_OBJECTS = two_file_test_main.$(OBJEXT) +two_file_mixed_2_shared_test_OBJECTS = \ + $(am_two_file_mixed_2_shared_test_OBJECTS) +am__two_file_mixed_shared_test_SOURCES_DIST = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_mixed_shared_test_OBJECTS = two_file_test_main.$(OBJEXT) +two_file_mixed_shared_test_OBJECTS = \ + $(am_two_file_mixed_shared_test_OBJECTS) +am__two_file_pic_test_SOURCES_DIST = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_pic_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_pic_test_OBJECTS = $(am_two_file_pic_test_OBJECTS) +am__two_file_relocatable_test_SOURCES_DIST = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_relocatable_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_relocatable_test_OBJECTS = \ + $(am_two_file_relocatable_test_OBJECTS) +am__two_file_same_shared_nonpic_test_SOURCES_DIST = \ + two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT) +two_file_same_shared_nonpic_test_OBJECTS = \ + $(am_two_file_same_shared_nonpic_test_OBJECTS) +am__two_file_same_shared_strip_test_SOURCES_DIST = \ + two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_strip_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_same_shared_strip_test_OBJECTS = \ + $(am_two_file_same_shared_strip_test_OBJECTS) +am__two_file_same_shared_test_SOURCES_DIST = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_same_shared_test_OBJECTS = \ + $(am_two_file_same_shared_test_OBJECTS) +am__two_file_separate_shared_12_nonpic_test_SOURCES_DIST = \ + two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_12_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT) +two_file_separate_shared_12_nonpic_test_OBJECTS = \ + $(am_two_file_separate_shared_12_nonpic_test_OBJECTS) +am__two_file_separate_shared_12_test_SOURCES_DIST = \ + two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_12_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_separate_shared_12_test_OBJECTS = \ + $(am_two_file_separate_shared_12_test_OBJECTS) +am__two_file_separate_shared_21_nonpic_test_SOURCES_DIST = \ + two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_21_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT) +two_file_separate_shared_21_nonpic_test_OBJECTS = \ + $(am_two_file_separate_shared_21_nonpic_test_OBJECTS) +am__two_file_separate_shared_21_test_SOURCES_DIST = \ + two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_21_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_separate_shared_21_test_OBJECTS = \ + $(am_two_file_separate_shared_21_test_OBJECTS) +am__two_file_shared_1_nonpic_test_SOURCES_DIST = two_file_test_2.cc \ + two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_1_nonpic_test_OBJECTS = two_file_test_2.$(OBJEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_shared_1_nonpic_test_OBJECTS = \ + $(am_two_file_shared_1_nonpic_test_OBJECTS) +am__two_file_shared_1_pic_2_test_SOURCES_DIST = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_1_pic_2_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_shared_1_pic_2_test_OBJECTS = \ + $(am_two_file_shared_1_pic_2_test_OBJECTS) +am__two_file_shared_1_test_SOURCES_DIST = two_file_test_2.cc \ + two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_1_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_shared_1_test_OBJECTS = $(am_two_file_shared_1_test_OBJECTS) +am__two_file_shared_2_nonpic_test_SOURCES_DIST = two_file_test_1.cc \ + two_file_test_1b.cc two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_2_nonpic_test_OBJECTS = two_file_test_1.$(OBJEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.$(OBJEXT) \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_shared_2_nonpic_test_OBJECTS = \ + $(am_two_file_shared_2_nonpic_test_OBJECTS) +am__two_file_shared_2_pic_1_test_SOURCES_DIST = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_2_pic_1_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_shared_2_pic_1_test_OBJECTS = \ + $(am_two_file_shared_2_pic_1_test_OBJECTS) +am__two_file_shared_2_test_SOURCES_DIST = two_file_test_1.cc \ + two_file_test_1b.cc two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_2_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_shared_2_test_OBJECTS = $(am_two_file_shared_2_test_OBJECTS) +am__two_file_static_test_SOURCES_DIST = two_file_test_1.cc \ + two_file_test_1b.cc two_file_test_2.cc two_file_test_main.cc \ + two_file_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__objects_5 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_static_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(am__objects_5) +two_file_static_test_OBJECTS = $(am_two_file_static_test_OBJECTS) +two_file_static_test_LDADD = $(LDADD) +two_file_strip_test_SOURCES = two_file_strip_test.c +two_file_strip_test_OBJECTS = two_file_strip_test.$(OBJEXT) +two_file_strip_test_LDADD = $(LDADD) +two_file_strip_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__two_file_test_SOURCES_DIST = two_file_test_1.cc \ + two_file_test_1b.cc two_file_test_2.cc two_file_test_main.cc \ + two_file_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.$(OBJEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +two_file_test_OBJECTS = $(am_two_file_test_OBJECTS) +two_file_test_LDADD = $(LDADD) +am__ver_test_SOURCES_DIST = ver_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main.$(OBJEXT) +ver_test_OBJECTS = $(am_ver_test_OBJECTS) +am__ver_test_2_SOURCES_DIST = ver_test_main_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_2_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main_2.$(OBJEXT) +ver_test_2_OBJECTS = $(am_ver_test_2_OBJECTS) +am__ver_test_6_SOURCES_DIST = ver_test_6.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_6_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6.$(OBJEXT) +ver_test_6_OBJECTS = $(am_ver_test_6_OBJECTS) +am__ver_test_8_SOURCES_DIST = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_8_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) +ver_test_8_OBJECTS = $(am_ver_test_8_OBJECTS) +am__ver_test_9_SOURCES_DIST = ver_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_9_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main.$(OBJEXT) +ver_test_9_OBJECTS = $(am_ver_test_9_OBJECTS) +am__weak_alias_test_SOURCES_DIST = weak_alias_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_alias_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_alias_test_main.$(OBJEXT) +weak_alias_test_OBJECTS = $(am_weak_alias_test_OBJECTS) +weak_plt_SOURCES = weak_plt.c +weak_plt_OBJECTS = weak_plt.$(OBJEXT) +weak_plt_LDADD = $(LDADD) +weak_plt_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__weak_test_SOURCES_DIST = weak_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_test.$(OBJEXT) +weak_test_OBJECTS = $(am_weak_test_OBJECTS) +weak_test_LDADD = $(LDADD) +am__weak_undef_nonpic_test_SOURCES_DIST = weak_undef_test.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_undef_nonpic_test_OBJECTS = weak_undef_test.$(OBJEXT) +weak_undef_nonpic_test_OBJECTS = $(am_weak_undef_nonpic_test_OBJECTS) +am__weak_undef_test_SOURCES_DIST = weak_undef_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_undef_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test.$(OBJEXT) +weak_undef_test_OBJECTS = $(am_weak_undef_test_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/../depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ + basic_static_pic_test.c basic_static_test.c basic_test.c \ + $(binary_test_SOURCES) $(binary_unittest_SOURCES) \ + $(common_test_1_SOURCES) $(constructor_static_test_SOURCES) \ + $(constructor_test_SOURCES) $(copy_test_SOURCES) \ + $(exception_same_shared_test_SOURCES) \ + $(exception_separate_shared_12_test_SOURCES) \ + $(exception_separate_shared_21_test_SOURCES) \ + $(exception_shared_1_test_SOURCES) \ + $(exception_shared_2_test_SOURCES) \ + $(exception_static_test_SOURCES) $(exception_test_SOURCES) \ + flagstest_compress_debug_sections.c flagstest_o_specialfile.c \ + flagstest_o_specialfile_and_compress_debug_sections.c \ + $(initpri1_SOURCES) $(justsyms_SOURCES) many_sections_r_test.c \ + $(many_sections_test_SOURCES) $(object_unittest_SOURCES) \ + $(protected_1_SOURCES) $(protected_2_SOURCES) \ + $(relro_test_SOURCES) $(script_test_1_SOURCES) \ + $(script_test_2_SOURCES) script_test_3.c \ + $(tls_pic_test_SOURCES) $(tls_shared_gd_to_ie_test_SOURCES) \ + $(tls_shared_gnu2_gd_to_ie_test_SOURCES) \ + $(tls_shared_gnu2_test_SOURCES) $(tls_shared_ie_test_SOURCES) \ + $(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \ + $(tls_static_pic_test_SOURCES) $(tls_static_test_SOURCES) \ + $(tls_test_SOURCES) $(two_file_mixed_2_shared_test_SOURCES) \ + $(two_file_mixed_shared_test_SOURCES) \ + $(two_file_pic_test_SOURCES) \ + $(two_file_relocatable_test_SOURCES) \ + $(two_file_same_shared_nonpic_test_SOURCES) \ + $(two_file_same_shared_strip_test_SOURCES) \ + $(two_file_same_shared_test_SOURCES) \ + $(two_file_separate_shared_12_nonpic_test_SOURCES) \ + $(two_file_separate_shared_12_test_SOURCES) \ + $(two_file_separate_shared_21_nonpic_test_SOURCES) \ + $(two_file_separate_shared_21_test_SOURCES) \ + $(two_file_shared_1_nonpic_test_SOURCES) \ + $(two_file_shared_1_pic_2_test_SOURCES) \ + $(two_file_shared_1_test_SOURCES) \ + $(two_file_shared_2_nonpic_test_SOURCES) \ + $(two_file_shared_2_pic_1_test_SOURCES) \ + $(two_file_shared_2_test_SOURCES) \ + $(two_file_static_test_SOURCES) two_file_strip_test.c \ + $(two_file_test_SOURCES) $(ver_test_SOURCES) \ + $(ver_test_2_SOURCES) $(ver_test_6_SOURCES) \ + $(ver_test_8_SOURCES) $(ver_test_9_SOURCES) \ + $(weak_alias_test_SOURCES) weak_plt.c $(weak_test_SOURCES) \ + $(weak_undef_nonpic_test_SOURCES) $(weak_undef_test_SOURCES) +DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ + basic_static_pic_test.c basic_static_test.c basic_test.c \ + $(am__binary_test_SOURCES_DIST) $(binary_unittest_SOURCES) \ + $(am__common_test_1_SOURCES_DIST) \ + $(am__constructor_static_test_SOURCES_DIST) \ + $(am__constructor_test_SOURCES_DIST) \ + $(am__copy_test_SOURCES_DIST) \ + $(am__exception_same_shared_test_SOURCES_DIST) \ + $(am__exception_separate_shared_12_test_SOURCES_DIST) \ + $(am__exception_separate_shared_21_test_SOURCES_DIST) \ + $(am__exception_shared_1_test_SOURCES_DIST) \ + $(am__exception_shared_2_test_SOURCES_DIST) \ + $(am__exception_static_test_SOURCES_DIST) \ + $(am__exception_test_SOURCES_DIST) \ + flagstest_compress_debug_sections.c flagstest_o_specialfile.c \ + flagstest_o_specialfile_and_compress_debug_sections.c \ + $(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \ + many_sections_r_test.c $(am__many_sections_test_SOURCES_DIST) \ + $(object_unittest_SOURCES) $(am__protected_1_SOURCES_DIST) \ + $(am__protected_2_SOURCES_DIST) $(am__relro_test_SOURCES_DIST) \ + $(am__script_test_1_SOURCES_DIST) \ + $(am__script_test_2_SOURCES_DIST) script_test_3.c \ + $(am__tls_pic_test_SOURCES_DIST) \ + $(am__tls_shared_gd_to_ie_test_SOURCES_DIST) \ + $(am__tls_shared_gnu2_gd_to_ie_test_SOURCES_DIST) \ + $(am__tls_shared_gnu2_test_SOURCES_DIST) \ + $(am__tls_shared_ie_test_SOURCES_DIST) \ + $(am__tls_shared_nonpic_test_SOURCES_DIST) \ + $(am__tls_shared_test_SOURCES_DIST) \ + $(am__tls_static_pic_test_SOURCES_DIST) \ + $(am__tls_static_test_SOURCES_DIST) \ + $(am__tls_test_SOURCES_DIST) \ + $(am__two_file_mixed_2_shared_test_SOURCES_DIST) \ + $(am__two_file_mixed_shared_test_SOURCES_DIST) \ + $(am__two_file_pic_test_SOURCES_DIST) \ + $(am__two_file_relocatable_test_SOURCES_DIST) \ + $(am__two_file_same_shared_nonpic_test_SOURCES_DIST) \ + $(am__two_file_same_shared_strip_test_SOURCES_DIST) \ + $(am__two_file_same_shared_test_SOURCES_DIST) \ + $(am__two_file_separate_shared_12_nonpic_test_SOURCES_DIST) \ + $(am__two_file_separate_shared_12_test_SOURCES_DIST) \ + $(am__two_file_separate_shared_21_nonpic_test_SOURCES_DIST) \ + $(am__two_file_separate_shared_21_test_SOURCES_DIST) \ + $(am__two_file_shared_1_nonpic_test_SOURCES_DIST) \ + $(am__two_file_shared_1_pic_2_test_SOURCES_DIST) \ + $(am__two_file_shared_1_test_SOURCES_DIST) \ + $(am__two_file_shared_2_nonpic_test_SOURCES_DIST) \ + $(am__two_file_shared_2_pic_1_test_SOURCES_DIST) \ + $(am__two_file_shared_2_test_SOURCES_DIST) \ + $(am__two_file_static_test_SOURCES_DIST) two_file_strip_test.c \ + $(am__two_file_test_SOURCES_DIST) $(am__ver_test_SOURCES_DIST) \ + $(am__ver_test_2_SOURCES_DIST) $(am__ver_test_6_SOURCES_DIST) \ + $(am__ver_test_8_SOURCES_DIST) $(am__ver_test_9_SOURCES_DIST) \ + $(am__weak_alias_test_SOURCES_DIST) weak_plt.c \ + $(am__weak_test_SOURCES_DIST) \ + $(am__weak_undef_nonpic_test_SOURCES_DIST) \ + $(am__weak_undef_test_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CONSTRUCTOR_PRIORITY_FALSE = @CONSTRUCTOR_PRIORITY_FALSE@ +CONSTRUCTOR_PRIORITY_TRUE = @CONSTRUCTOR_PRIORITY_TRUE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FN_PTRS_IN_SO_WITHOUT_PIC_FALSE = @FN_PTRS_IN_SO_WITHOUT_PIC_FALSE@ +FN_PTRS_IN_SO_WITHOUT_PIC_TRUE = @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@ +GCC_FALSE = @GCC_FALSE@ +GCC_TRUE = @GCC_TRUE@ +GENCAT = @GENCAT@ +GMSGFMT = @GMSGFMT@ +HAVE_ZLIB_FALSE = @HAVE_ZLIB_FALSE@ +HAVE_ZLIB_TRUE = @HAVE_ZLIB_TRUE@ +INCINTL = @INCINTL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +LDFLAGS = @LDFLAGS@ +LFS_CFLAGS = @LFS_CFLAGS@ +LIBINTL = @LIBINTL@ +LIBINTL_DEP = @LIBINTL_DEP@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +NATIVE_LINKER_FALSE = @NATIVE_LINKER_FALSE@ +NATIVE_LINKER_TRUE = @NATIVE_LINKER_TRUE@ +NO_WERROR = @NO_WERROR@ +OBJEXT = @OBJEXT@ +OMP_SUPPORT_FALSE = @OMP_SUPPORT_FALSE@ +OMP_SUPPORT_TRUE = @OMP_SUPPORT_TRUE@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +RANDOM_SEED_CFLAGS = @RANDOM_SEED_CFLAGS@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STATIC_TLS_FALSE = @STATIC_TLS_FALSE@ +STATIC_TLS_TRUE = @STATIC_TLS_TRUE@ +STRIP = @STRIP@ +TARGETOBJS = @TARGETOBJS@ +THREADS_FALSE = @THREADS_FALSE@ +THREADS_TRUE = @THREADS_TRUE@ +TLS_DESCRIPTORS_FALSE = @TLS_DESCRIPTORS_FALSE@ +TLS_DESCRIPTORS_TRUE = @TLS_DESCRIPTORS_TRUE@ +TLS_FALSE = @TLS_FALSE@ +TLS_GNU2_DIALECT_FALSE = @TLS_GNU2_DIALECT_FALSE@ +TLS_GNU2_DIALECT_TRUE = @TLS_GNU2_DIALECT_TRUE@ +TLS_TRUE = @TLS_TRUE@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_CXXFLAGS = @WARN_CXXFLAGS@ +XGETTEXT = @XGETTEXT@ +YACC = @YACC@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +AUTOMAKE_OPTIONS = + +# The two_file_test tests -fmerge-constants, so we simply always turn +# it on. This may need to be controlled by a configure option +# eventually. +AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) -fmerge-constants +INCLUDES = \ + -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \ + -I$(srcdir)/../../elfcpp -I.. \ + -DLOCALEDIR="\"$(datadir)/locale\"" \ + @INCINTL@ + +TEST_READELF = $(top_builddir)/../binutils/readelf +TEST_OBJDUMP = $(top_builddir)/../binutils/objdump +TEST_CXXFILT = $(top_builddir)/../binutils/cxxfilt +TEST_STRIP = $(top_builddir)/../binutils/strip-new +@THREADS_TRUE@THREADSLIB = -lpthread +@OMP_SUPPORT_TRUE@TLS_TEST_C_CFLAGS = -fopenmp + +# 'make clean' is good about deleting some intermediate files (such as +# .o's), but not all of them (such as .so's and .err files). We +# improve on that here. automake-1.9 info docs say "mostlyclean" is +# the right choice for files 'make' builds that people rebuild. +MOSTLYCLEANFILES = *.so $(am__append_16) + +# We will add to these later, for each individual test. Note +# that we add each test under check_SCRIPTS or check_PROGRAMS; +# the TESTS variable is automatically populated from these. +check_SCRIPTS = $(am__append_6) +check_DATA = $(am__append_7) +BUILT_SOURCES = $(am__append_14) +TESTS = $(check_SCRIPTS) $(check_PROGRAMS) + +# --------------------------------------------------------------------- +# These tests test the internals of gold (unittests). + +# Infrastucture needed for the unittests +check_LIBRARIES = libgoldtest.a +libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc +DEPENDENCIES = \ + libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP) + +LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ + $(THREADSLIB) + +object_unittest_SOURCES = object_unittest.cc +binary_unittest_SOURCES = binary_unittest.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_SOURCES = constructor_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_SOURCES = $(constructor_test_SOURCES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_DEPENDENCIES = $(constructor_test_DEPENDENCIES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_LDFLAGS = $(constructor_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_SOURCES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test.h + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_SOURCES = $(two_file_test_SOURCES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_DEPENDENCIES = $(two_file_test_DEPENDENCIES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_LDFLAGS = $(two_file_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pic_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pic_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pic_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pic_test_LDADD = two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_test_SOURCES = two_file_test_2.cc two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_test_DEPENDENCIES = gcctestdir/ld two_file_shared_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_test_LDADD = two_file_shared_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_test_SOURCES = two_file_test_1.cc two_file_test_1b.cc two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_test_DEPENDENCIES = gcctestdir/ld two_file_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_test_LDADD = two_file_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1.so two_file_test_1_pic.o two_file_test_1b_pic.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_LDADD = two_file_test_1_pic.o two_file_test_1b_pic.o two_file_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_pic_1_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_pic_1_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_2.so two_file_test_2_pic.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_pic_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_pic_1_test_LDADD = two_file_test_2_pic.o two_file_shared_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_test_DEPENDENCIES = gcctestdir/ld two_file_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_test_LDADD = two_file_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1.so two_file_shared_2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_test_LDADD = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1.so two_file_shared_2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1.so two_file_shared_2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_test_LDADD = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2.so two_file_shared_1.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_relocatable_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_relocatable_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_relocatable.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_relocatable_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_relocatable_test_LDADD = two_file_relocatable.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_nonpic_test_SOURCES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.cc two_file_test_main.cc + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_nonpic_test_DEPENDENCIES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_nonpic_test_LDADD = two_file_shared_1_nonpic.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_nonpic_test_SOURCES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1.cc two_file_test_1b.cc two_file_test_main.cc + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_nonpic_test_DEPENDENCIES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_2_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_nonpic_test_LDADD = two_file_shared_2_nonpic.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_nonpic_test_SOURCES = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_nonpic_test_DEPENDENCIES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_nonpic_test_LDADD = two_file_shared_nonpic.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_nonpic_test_SOURCES = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_nonpic_test_DEPENDENCIES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1_nonpic.so two_file_shared_2_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_12_nonpic_test_LDADD = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_nonpic.so two_file_shared_2_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_nonpic_test_SOURCES = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_nonpic_test_DEPENDENCIES = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1_nonpic.so two_file_shared_2_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_separate_shared_21_nonpic_test_LDADD = \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic.so two_file_shared_1_nonpic.so + +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_shared_test_SOURCES = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_shared_test_DEPENDENCIES = gcctestdir/ld two_file_shared_mixed.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_shared_test_LDADD = two_file_shared_mixed.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_2_shared_test_SOURCES = two_file_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_2_shared_test_DEPENDENCIES = gcctestdir/ld two_file_shared_mixed_1.so two_file_shared_2.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_2_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_mixed_2_shared_test_LDADD = two_file_shared_mixed_1.so two_file_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_strip_test_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_strip_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_strip.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_strip_test_LDFLAGS = -Bgcctestdir/ -Wl,-R. +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_same_shared_strip_test_LDADD = two_file_shared_strip.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_SOURCES = common_test_1.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_SOURCES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_1.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_2.cc \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test.h + +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_SOURCES = $(exception_test_SOURCES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_DEPENDENCIES = $(exception_test_DEPENDENCIES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_LDFLAGS = $(exception_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_SOURCES = exception_test_2.cc exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_DEPENDENCIES = gcctestdir/ld exception_shared_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_LDADD = exception_shared_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_2_test_SOURCES = exception_test_1.cc exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_2_test_DEPENDENCIES = gcctestdir/ld exception_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_2_test_LDADD = exception_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_same_shared_test_SOURCES = exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_same_shared_test_DEPENDENCIES = gcctestdir/ld exception_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_same_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_same_shared_test_LDADD = exception_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_12_test_SOURCES = exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_12_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld exception_shared_1.so exception_shared_2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_12_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_12_test_LDADD = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_1.so exception_shared_2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_21_test_SOURCES = exception_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_21_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld exception_shared_1.so exception_shared_2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_21_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_separate_shared_21_test_LDADD = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_2.so exception_shared_1.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_SOURCES = weak_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_SOURCES = weak_undef_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib.so alt/weak_undef_lib.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_LDADD = -L . weak_undef_lib.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_SOURCES = weak_undef_test.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib_nonpic.so alt/weak_undef_lib_nonpic.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_LDADD = -L . weak_undef_lib_nonpic.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_SOURCES = weak_alias_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_DEPENDENCIES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld weak_alias_test_1.so weak_alias_test_2.so \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_alias_test_3.o weak_alias_test_4.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_LDADD = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_alias_test_1.so weak_alias_test_2.so weak_alias_test_3.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_alias_test_4.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_SOURCES = copy_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_DEPENDENCIES = gcctestdir/ld copy_test_1.so copy_test_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_LDADD = copy_test_1.so copy_test_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_SOURCES = tls_test.cc tls_test_file2.cc tls_test_main.cc tls_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_DEPENDENCIES = gcctestdir/ld tls_test_c.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_LDADD = tls_test_c.o -lpthread +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_pic_test_SOURCES = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_pic_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o tls_test_file2_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c_pic.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_pic_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_pic_test_LDADD = tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ -lpthread + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_test_SOURCES = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_test_DEPENDENCIES = gcctestdir/ld tls_test_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_test_LDADD = tls_test_shared.so -lpthread +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_ie_test_SOURCES = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_ie_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_ie_test_LDADD = tls_test_ie_shared.so -lpthread +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_gd_to_ie_test_SOURCES = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c_pic.o tls_test_shared2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_gd_to_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_gd_to_ie_test_LDADD = tls_test_pic.o tls_test_c_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_shared2.so -lpthread + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_gd_to_ie_test_SOURCES = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ tls_test_c_gnu2.o tls_test_gnu2_shared2.so + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_gd_to_ie_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_gd_to_ie_test_LDADD = tls_test_gnu2.o tls_test_c_gnu2.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ tls_test_gnu2_shared2.so -lpthread + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_test_SOURCES = tls_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_test_DEPENDENCIES = gcctestdir/ld tls_test_gnu2_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_shared_gnu2_test_LDADD = tls_test_gnu2_shared.so -lpthread +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_test_SOURCES = $(tls_test_SOURCES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_test_DEPENDENCIES = $(tls_test_DEPENDENCIES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_test_LDFLAGS = $(tls_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_test_LDADD = $(tls_test_LDADD) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_pic_test_SOURCES = $(tls_pic_test_SOURCES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_pic_test_DEPENDENCIES = $(tls_pic_test_DEPENDENCIES) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_pic_test_LDFLAGS = $(tls_pic_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@tls_static_pic_test_LDADD = $(tls_pic_test_LDADD) +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_SOURCES = tls_test_main.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_DEPENDENCIES = gcctestdir/ld tls_test_shared_nonpic.so +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_shared_nonpic_test_LDADD = tls_test_shared_nonpic.so -lpthread +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_SOURCES = many_sections_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_LDFLAGS = -Bgcctestdir/ -rdynamic +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_SOURCES = initpri1.c +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_DEPENDENCIES = gcctestdir/ld +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_SOURCES = ver_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDADD = ver_test_1.so ver_test_2.so ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2_SOURCES = ver_test_main_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2_DEPENDENCIES = gcctestdir/ld ver_test_4.so ver_test_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2_LDADD = ver_test_4.so ver_test_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_6_SOURCES = ver_test_6.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_6_DEPENDENCIES = gcctestdir/ld ver_test_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_6_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_6_LDADD = ver_test_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_8_SOURCES = two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_8_DEPENDENCIES = gcctestdir/ld ver_test_8_1.so ver_test_8_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_8_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_8_LDADD = ver_test_8_1.so ver_test_8_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_SOURCES = ver_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_DEPENDENCIES = gcctestdir/ld ver_test_9.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_LDADD = ver_test_9.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1_SOURCES = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.cc protected_main_2.cc protected_main_3.cc + +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1_DEPENDENCIES = gcctestdir/ld protected_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1_LDADD = protected_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_SOURCES = protected_main_1.cc protected_3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_DEPENDENCIES = gcctestdir/ld protected_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_LDADD = protected_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_SOURCES = relro_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_DEPENDENCIES = gcctestdir/ld relro_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_LDADD = relro_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_SOURCES = script_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_SOURCES = script_test_2.cc script_test_2a.cc script_test_2b.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_SOURCES = justsyms_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_DEPENDENCIES = gcctestdir/ld justsyms_2r.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_LDFLAGS = -Bgcctestdir/ -Wl,-R,justsyms_2r.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_SOURCES = binary_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_DEPENDENCIES = gcctestdir/ld binary.txt +@GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_LDFLAGS = -Bgcctestdir/ -Wl,--format,binary,binary.txt,--format,elf +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .cc .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign testsuite/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-checkLIBRARIES: + -test -z "$(check_LIBRARIES)" || rm -f $(check_LIBRARIES) +libgoldtest.a: $(libgoldtest_a_OBJECTS) $(libgoldtest_a_DEPENDENCIES) + -rm -f libgoldtest.a + $(libgoldtest_a_AR) libgoldtest.a $(libgoldtest_a_OBJECTS) $(libgoldtest_a_LIBADD) + $(RANLIB) libgoldtest.a + +clean-checkPROGRAMS: + -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) +@GCC_FALSE@basic_pic_test$(EXEEXT): $(basic_pic_test_OBJECTS) $(basic_pic_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f basic_pic_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(basic_pic_test_LDFLAGS) $(basic_pic_test_OBJECTS) $(basic_pic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@basic_pic_test$(EXEEXT): $(basic_pic_test_OBJECTS) $(basic_pic_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f basic_pic_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_pic_test_LDFLAGS) $(basic_pic_test_OBJECTS) $(basic_pic_test_LDADD) $(LIBS) +@GCC_FALSE@basic_static_pic_test$(EXEEXT): $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f basic_static_pic_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(basic_static_pic_test_LDFLAGS) $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@basic_static_pic_test$(EXEEXT): $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f basic_static_pic_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_static_pic_test_LDFLAGS) $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_LDADD) $(LIBS) +@GCC_FALSE@basic_static_test$(EXEEXT): $(basic_static_test_OBJECTS) $(basic_static_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f basic_static_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(basic_static_test_LDFLAGS) $(basic_static_test_OBJECTS) $(basic_static_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@basic_static_test$(EXEEXT): $(basic_static_test_OBJECTS) $(basic_static_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f basic_static_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_static_test_LDFLAGS) $(basic_static_test_OBJECTS) $(basic_static_test_LDADD) $(LIBS) +@GCC_FALSE@basic_test$(EXEEXT): $(basic_test_OBJECTS) $(basic_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f basic_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(basic_test_LDFLAGS) $(basic_test_OBJECTS) $(basic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@basic_test$(EXEEXT): $(basic_test_OBJECTS) $(basic_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f basic_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_test_LDFLAGS) $(basic_test_OBJECTS) $(basic_test_LDADD) $(LIBS) +binary_test$(EXEEXT): $(binary_test_OBJECTS) $(binary_test_DEPENDENCIES) + @rm -f binary_test$(EXEEXT) + $(CXXLINK) $(binary_test_LDFLAGS) $(binary_test_OBJECTS) $(binary_test_LDADD) $(LIBS) +binary_unittest$(EXEEXT): $(binary_unittest_OBJECTS) $(binary_unittest_DEPENDENCIES) + @rm -f binary_unittest$(EXEEXT) + $(CXXLINK) $(binary_unittest_LDFLAGS) $(binary_unittest_OBJECTS) $(binary_unittest_LDADD) $(LIBS) +common_test_1$(EXEEXT): $(common_test_1_OBJECTS) $(common_test_1_DEPENDENCIES) + @rm -f common_test_1$(EXEEXT) + $(LINK) $(common_test_1_LDFLAGS) $(common_test_1_OBJECTS) $(common_test_1_LDADD) $(LIBS) +constructor_static_test$(EXEEXT): $(constructor_static_test_OBJECTS) $(constructor_static_test_DEPENDENCIES) + @rm -f constructor_static_test$(EXEEXT) + $(CXXLINK) $(constructor_static_test_LDFLAGS) $(constructor_static_test_OBJECTS) $(constructor_static_test_LDADD) $(LIBS) +constructor_test$(EXEEXT): $(constructor_test_OBJECTS) $(constructor_test_DEPENDENCIES) + @rm -f constructor_test$(EXEEXT) + $(CXXLINK) $(constructor_test_LDFLAGS) $(constructor_test_OBJECTS) $(constructor_test_LDADD) $(LIBS) +copy_test$(EXEEXT): $(copy_test_OBJECTS) $(copy_test_DEPENDENCIES) + @rm -f copy_test$(EXEEXT) + $(CXXLINK) $(copy_test_LDFLAGS) $(copy_test_OBJECTS) $(copy_test_LDADD) $(LIBS) +exception_same_shared_test$(EXEEXT): $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_DEPENDENCIES) + @rm -f exception_same_shared_test$(EXEEXT) + $(CXXLINK) $(exception_same_shared_test_LDFLAGS) $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_LDADD) $(LIBS) +exception_separate_shared_12_test$(EXEEXT): $(exception_separate_shared_12_test_OBJECTS) $(exception_separate_shared_12_test_DEPENDENCIES) + @rm -f exception_separate_shared_12_test$(EXEEXT) + $(CXXLINK) $(exception_separate_shared_12_test_LDFLAGS) $(exception_separate_shared_12_test_OBJECTS) $(exception_separate_shared_12_test_LDADD) $(LIBS) +exception_separate_shared_21_test$(EXEEXT): $(exception_separate_shared_21_test_OBJECTS) $(exception_separate_shared_21_test_DEPENDENCIES) + @rm -f exception_separate_shared_21_test$(EXEEXT) + $(CXXLINK) $(exception_separate_shared_21_test_LDFLAGS) $(exception_separate_shared_21_test_OBJECTS) $(exception_separate_shared_21_test_LDADD) $(LIBS) +exception_shared_1_test$(EXEEXT): $(exception_shared_1_test_OBJECTS) $(exception_shared_1_test_DEPENDENCIES) + @rm -f exception_shared_1_test$(EXEEXT) + $(CXXLINK) $(exception_shared_1_test_LDFLAGS) $(exception_shared_1_test_OBJECTS) $(exception_shared_1_test_LDADD) $(LIBS) +exception_shared_2_test$(EXEEXT): $(exception_shared_2_test_OBJECTS) $(exception_shared_2_test_DEPENDENCIES) + @rm -f exception_shared_2_test$(EXEEXT) + $(CXXLINK) $(exception_shared_2_test_LDFLAGS) $(exception_shared_2_test_OBJECTS) $(exception_shared_2_test_LDADD) $(LIBS) +exception_static_test$(EXEEXT): $(exception_static_test_OBJECTS) $(exception_static_test_DEPENDENCIES) + @rm -f exception_static_test$(EXEEXT) + $(CXXLINK) $(exception_static_test_LDFLAGS) $(exception_static_test_OBJECTS) $(exception_static_test_LDADD) $(LIBS) +exception_test$(EXEEXT): $(exception_test_OBJECTS) $(exception_test_DEPENDENCIES) + @rm -f exception_test$(EXEEXT) + $(CXXLINK) $(exception_test_LDFLAGS) $(exception_test_OBJECTS) $(exception_test_LDADD) $(LIBS) +@GCC_FALSE@flagstest_compress_debug_sections$(EXEEXT): $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_DEPENDENCIES) +@GCC_FALSE@ @rm -f flagstest_compress_debug_sections$(EXEEXT) +@GCC_FALSE@ $(LINK) $(flagstest_compress_debug_sections_LDFLAGS) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) +@HAVE_ZLIB_FALSE@flagstest_compress_debug_sections$(EXEEXT): $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_DEPENDENCIES) +@HAVE_ZLIB_FALSE@ @rm -f flagstest_compress_debug_sections$(EXEEXT) +@HAVE_ZLIB_FALSE@ $(LINK) $(flagstest_compress_debug_sections_LDFLAGS) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@flagstest_compress_debug_sections$(EXEEXT): $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f flagstest_compress_debug_sections$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_compress_debug_sections_LDFLAGS) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) +@GCC_FALSE@flagstest_o_specialfile$(EXEEXT): $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_DEPENDENCIES) +@GCC_FALSE@ @rm -f flagstest_o_specialfile$(EXEEXT) +@GCC_FALSE@ $(LINK) $(flagstest_o_specialfile_LDFLAGS) $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@flagstest_o_specialfile$(EXEEXT): $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f flagstest_o_specialfile$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_LDFLAGS) $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_LDADD) $(LIBS) +@GCC_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES) +@GCC_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) +@GCC_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) +@HAVE_ZLIB_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES) +@HAVE_ZLIB_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) +@HAVE_ZLIB_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) +initpri1$(EXEEXT): $(initpri1_OBJECTS) $(initpri1_DEPENDENCIES) + @rm -f initpri1$(EXEEXT) + $(LINK) $(initpri1_LDFLAGS) $(initpri1_OBJECTS) $(initpri1_LDADD) $(LIBS) +justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES) + @rm -f justsyms$(EXEEXT) + $(CXXLINK) $(justsyms_LDFLAGS) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS) +@GCC_FALSE@many_sections_r_test$(EXEEXT): $(many_sections_r_test_OBJECTS) $(many_sections_r_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f many_sections_r_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(many_sections_r_test_LDFLAGS) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@many_sections_r_test$(EXEEXT): $(many_sections_r_test_OBJECTS) $(many_sections_r_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f many_sections_r_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(many_sections_r_test_LDFLAGS) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) +many_sections_test$(EXEEXT): $(many_sections_test_OBJECTS) $(many_sections_test_DEPENDENCIES) + @rm -f many_sections_test$(EXEEXT) + $(CXXLINK) $(many_sections_test_LDFLAGS) $(many_sections_test_OBJECTS) $(many_sections_test_LDADD) $(LIBS) +object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES) + @rm -f object_unittest$(EXEEXT) + $(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS) +protected_1$(EXEEXT): $(protected_1_OBJECTS) $(protected_1_DEPENDENCIES) + @rm -f protected_1$(EXEEXT) + $(CXXLINK) $(protected_1_LDFLAGS) $(protected_1_OBJECTS) $(protected_1_LDADD) $(LIBS) +protected_2$(EXEEXT): $(protected_2_OBJECTS) $(protected_2_DEPENDENCIES) + @rm -f protected_2$(EXEEXT) + $(CXXLINK) $(protected_2_LDFLAGS) $(protected_2_OBJECTS) $(protected_2_LDADD) $(LIBS) +relro_test$(EXEEXT): $(relro_test_OBJECTS) $(relro_test_DEPENDENCIES) + @rm -f relro_test$(EXEEXT) + $(CXXLINK) $(relro_test_LDFLAGS) $(relro_test_OBJECTS) $(relro_test_LDADD) $(LIBS) +script_test_1$(EXEEXT): $(script_test_1_OBJECTS) $(script_test_1_DEPENDENCIES) + @rm -f script_test_1$(EXEEXT) + $(CXXLINK) $(script_test_1_LDFLAGS) $(script_test_1_OBJECTS) $(script_test_1_LDADD) $(LIBS) +script_test_2$(EXEEXT): $(script_test_2_OBJECTS) $(script_test_2_DEPENDENCIES) + @rm -f script_test_2$(EXEEXT) + $(CXXLINK) $(script_test_2_LDFLAGS) $(script_test_2_OBJECTS) $(script_test_2_LDADD) $(LIBS) +@GCC_FALSE@script_test_3$(EXEEXT): $(script_test_3_OBJECTS) $(script_test_3_DEPENDENCIES) +@GCC_FALSE@ @rm -f script_test_3$(EXEEXT) +@GCC_FALSE@ $(LINK) $(script_test_3_LDFLAGS) $(script_test_3_OBJECTS) $(script_test_3_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@script_test_3$(EXEEXT): $(script_test_3_OBJECTS) $(script_test_3_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f script_test_3$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(script_test_3_LDFLAGS) $(script_test_3_OBJECTS) $(script_test_3_LDADD) $(LIBS) +tls_pic_test$(EXEEXT): $(tls_pic_test_OBJECTS) $(tls_pic_test_DEPENDENCIES) + @rm -f tls_pic_test$(EXEEXT) + $(CXXLINK) $(tls_pic_test_LDFLAGS) $(tls_pic_test_OBJECTS) $(tls_pic_test_LDADD) $(LIBS) +tls_shared_gd_to_ie_test$(EXEEXT): $(tls_shared_gd_to_ie_test_OBJECTS) $(tls_shared_gd_to_ie_test_DEPENDENCIES) + @rm -f tls_shared_gd_to_ie_test$(EXEEXT) + $(CXXLINK) $(tls_shared_gd_to_ie_test_LDFLAGS) $(tls_shared_gd_to_ie_test_OBJECTS) $(tls_shared_gd_to_ie_test_LDADD) $(LIBS) +tls_shared_gnu2_gd_to_ie_test$(EXEEXT): $(tls_shared_gnu2_gd_to_ie_test_OBJECTS) $(tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES) + @rm -f tls_shared_gnu2_gd_to_ie_test$(EXEEXT) + $(CXXLINK) $(tls_shared_gnu2_gd_to_ie_test_LDFLAGS) $(tls_shared_gnu2_gd_to_ie_test_OBJECTS) $(tls_shared_gnu2_gd_to_ie_test_LDADD) $(LIBS) +tls_shared_gnu2_test$(EXEEXT): $(tls_shared_gnu2_test_OBJECTS) $(tls_shared_gnu2_test_DEPENDENCIES) + @rm -f tls_shared_gnu2_test$(EXEEXT) + $(CXXLINK) $(tls_shared_gnu2_test_LDFLAGS) $(tls_shared_gnu2_test_OBJECTS) $(tls_shared_gnu2_test_LDADD) $(LIBS) +tls_shared_ie_test$(EXEEXT): $(tls_shared_ie_test_OBJECTS) $(tls_shared_ie_test_DEPENDENCIES) + @rm -f tls_shared_ie_test$(EXEEXT) + $(CXXLINK) $(tls_shared_ie_test_LDFLAGS) $(tls_shared_ie_test_OBJECTS) $(tls_shared_ie_test_LDADD) $(LIBS) +tls_shared_nonpic_test$(EXEEXT): $(tls_shared_nonpic_test_OBJECTS) $(tls_shared_nonpic_test_DEPENDENCIES) + @rm -f tls_shared_nonpic_test$(EXEEXT) + $(CXXLINK) $(tls_shared_nonpic_test_LDFLAGS) $(tls_shared_nonpic_test_OBJECTS) $(tls_shared_nonpic_test_LDADD) $(LIBS) +tls_shared_test$(EXEEXT): $(tls_shared_test_OBJECTS) $(tls_shared_test_DEPENDENCIES) + @rm -f tls_shared_test$(EXEEXT) + $(CXXLINK) $(tls_shared_test_LDFLAGS) $(tls_shared_test_OBJECTS) $(tls_shared_test_LDADD) $(LIBS) +tls_static_pic_test$(EXEEXT): $(tls_static_pic_test_OBJECTS) $(tls_static_pic_test_DEPENDENCIES) + @rm -f tls_static_pic_test$(EXEEXT) + $(CXXLINK) $(tls_static_pic_test_LDFLAGS) $(tls_static_pic_test_OBJECTS) $(tls_static_pic_test_LDADD) $(LIBS) +tls_static_test$(EXEEXT): $(tls_static_test_OBJECTS) $(tls_static_test_DEPENDENCIES) + @rm -f tls_static_test$(EXEEXT) + $(CXXLINK) $(tls_static_test_LDFLAGS) $(tls_static_test_OBJECTS) $(tls_static_test_LDADD) $(LIBS) +tls_test$(EXEEXT): $(tls_test_OBJECTS) $(tls_test_DEPENDENCIES) + @rm -f tls_test$(EXEEXT) + $(CXXLINK) $(tls_test_LDFLAGS) $(tls_test_OBJECTS) $(tls_test_LDADD) $(LIBS) +two_file_mixed_2_shared_test$(EXEEXT): $(two_file_mixed_2_shared_test_OBJECTS) $(two_file_mixed_2_shared_test_DEPENDENCIES) + @rm -f two_file_mixed_2_shared_test$(EXEEXT) + $(CXXLINK) $(two_file_mixed_2_shared_test_LDFLAGS) $(two_file_mixed_2_shared_test_OBJECTS) $(two_file_mixed_2_shared_test_LDADD) $(LIBS) +two_file_mixed_shared_test$(EXEEXT): $(two_file_mixed_shared_test_OBJECTS) $(two_file_mixed_shared_test_DEPENDENCIES) + @rm -f two_file_mixed_shared_test$(EXEEXT) + $(CXXLINK) $(two_file_mixed_shared_test_LDFLAGS) $(two_file_mixed_shared_test_OBJECTS) $(two_file_mixed_shared_test_LDADD) $(LIBS) +two_file_pic_test$(EXEEXT): $(two_file_pic_test_OBJECTS) $(two_file_pic_test_DEPENDENCIES) + @rm -f two_file_pic_test$(EXEEXT) + $(CXXLINK) $(two_file_pic_test_LDFLAGS) $(two_file_pic_test_OBJECTS) $(two_file_pic_test_LDADD) $(LIBS) +two_file_relocatable_test$(EXEEXT): $(two_file_relocatable_test_OBJECTS) $(two_file_relocatable_test_DEPENDENCIES) + @rm -f two_file_relocatable_test$(EXEEXT) + $(CXXLINK) $(two_file_relocatable_test_LDFLAGS) $(two_file_relocatable_test_OBJECTS) $(two_file_relocatable_test_LDADD) $(LIBS) +two_file_same_shared_nonpic_test$(EXEEXT): $(two_file_same_shared_nonpic_test_OBJECTS) $(two_file_same_shared_nonpic_test_DEPENDENCIES) + @rm -f two_file_same_shared_nonpic_test$(EXEEXT) + $(CXXLINK) $(two_file_same_shared_nonpic_test_LDFLAGS) $(two_file_same_shared_nonpic_test_OBJECTS) $(two_file_same_shared_nonpic_test_LDADD) $(LIBS) +two_file_same_shared_strip_test$(EXEEXT): $(two_file_same_shared_strip_test_OBJECTS) $(two_file_same_shared_strip_test_DEPENDENCIES) + @rm -f two_file_same_shared_strip_test$(EXEEXT) + $(CXXLINK) $(two_file_same_shared_strip_test_LDFLAGS) $(two_file_same_shared_strip_test_OBJECTS) $(two_file_same_shared_strip_test_LDADD) $(LIBS) +two_file_same_shared_test$(EXEEXT): $(two_file_same_shared_test_OBJECTS) $(two_file_same_shared_test_DEPENDENCIES) + @rm -f two_file_same_shared_test$(EXEEXT) + $(CXXLINK) $(two_file_same_shared_test_LDFLAGS) $(two_file_same_shared_test_OBJECTS) $(two_file_same_shared_test_LDADD) $(LIBS) +two_file_separate_shared_12_nonpic_test$(EXEEXT): $(two_file_separate_shared_12_nonpic_test_OBJECTS) $(two_file_separate_shared_12_nonpic_test_DEPENDENCIES) + @rm -f two_file_separate_shared_12_nonpic_test$(EXEEXT) + $(CXXLINK) $(two_file_separate_shared_12_nonpic_test_LDFLAGS) $(two_file_separate_shared_12_nonpic_test_OBJECTS) $(two_file_separate_shared_12_nonpic_test_LDADD) $(LIBS) +two_file_separate_shared_12_test$(EXEEXT): $(two_file_separate_shared_12_test_OBJECTS) $(two_file_separate_shared_12_test_DEPENDENCIES) + @rm -f two_file_separate_shared_12_test$(EXEEXT) + $(CXXLINK) $(two_file_separate_shared_12_test_LDFLAGS) $(two_file_separate_shared_12_test_OBJECTS) $(two_file_separate_shared_12_test_LDADD) $(LIBS) +two_file_separate_shared_21_nonpic_test$(EXEEXT): $(two_file_separate_shared_21_nonpic_test_OBJECTS) $(two_file_separate_shared_21_nonpic_test_DEPENDENCIES) + @rm -f two_file_separate_shared_21_nonpic_test$(EXEEXT) + $(CXXLINK) $(two_file_separate_shared_21_nonpic_test_LDFLAGS) $(two_file_separate_shared_21_nonpic_test_OBJECTS) $(two_file_separate_shared_21_nonpic_test_LDADD) $(LIBS) +two_file_separate_shared_21_test$(EXEEXT): $(two_file_separate_shared_21_test_OBJECTS) $(two_file_separate_shared_21_test_DEPENDENCIES) + @rm -f two_file_separate_shared_21_test$(EXEEXT) + $(CXXLINK) $(two_file_separate_shared_21_test_LDFLAGS) $(two_file_separate_shared_21_test_OBJECTS) $(two_file_separate_shared_21_test_LDADD) $(LIBS) +two_file_shared_1_nonpic_test$(EXEEXT): $(two_file_shared_1_nonpic_test_OBJECTS) $(two_file_shared_1_nonpic_test_DEPENDENCIES) + @rm -f two_file_shared_1_nonpic_test$(EXEEXT) + $(CXXLINK) $(two_file_shared_1_nonpic_test_LDFLAGS) $(two_file_shared_1_nonpic_test_OBJECTS) $(two_file_shared_1_nonpic_test_LDADD) $(LIBS) +two_file_shared_1_pic_2_test$(EXEEXT): $(two_file_shared_1_pic_2_test_OBJECTS) $(two_file_shared_1_pic_2_test_DEPENDENCIES) + @rm -f two_file_shared_1_pic_2_test$(EXEEXT) + $(CXXLINK) $(two_file_shared_1_pic_2_test_LDFLAGS) $(two_file_shared_1_pic_2_test_OBJECTS) $(two_file_shared_1_pic_2_test_LDADD) $(LIBS) +two_file_shared_1_test$(EXEEXT): $(two_file_shared_1_test_OBJECTS) $(two_file_shared_1_test_DEPENDENCIES) + @rm -f two_file_shared_1_test$(EXEEXT) + $(CXXLINK) $(two_file_shared_1_test_LDFLAGS) $(two_file_shared_1_test_OBJECTS) $(two_file_shared_1_test_LDADD) $(LIBS) +two_file_shared_2_nonpic_test$(EXEEXT): $(two_file_shared_2_nonpic_test_OBJECTS) $(two_file_shared_2_nonpic_test_DEPENDENCIES) + @rm -f two_file_shared_2_nonpic_test$(EXEEXT) + $(CXXLINK) $(two_file_shared_2_nonpic_test_LDFLAGS) $(two_file_shared_2_nonpic_test_OBJECTS) $(two_file_shared_2_nonpic_test_LDADD) $(LIBS) +two_file_shared_2_pic_1_test$(EXEEXT): $(two_file_shared_2_pic_1_test_OBJECTS) $(two_file_shared_2_pic_1_test_DEPENDENCIES) + @rm -f two_file_shared_2_pic_1_test$(EXEEXT) + $(CXXLINK) $(two_file_shared_2_pic_1_test_LDFLAGS) $(two_file_shared_2_pic_1_test_OBJECTS) $(two_file_shared_2_pic_1_test_LDADD) $(LIBS) +two_file_shared_2_test$(EXEEXT): $(two_file_shared_2_test_OBJECTS) $(two_file_shared_2_test_DEPENDENCIES) + @rm -f two_file_shared_2_test$(EXEEXT) + $(CXXLINK) $(two_file_shared_2_test_LDFLAGS) $(two_file_shared_2_test_OBJECTS) $(two_file_shared_2_test_LDADD) $(LIBS) +two_file_static_test$(EXEEXT): $(two_file_static_test_OBJECTS) $(two_file_static_test_DEPENDENCIES) + @rm -f two_file_static_test$(EXEEXT) + $(CXXLINK) $(two_file_static_test_LDFLAGS) $(two_file_static_test_OBJECTS) $(two_file_static_test_LDADD) $(LIBS) +@GCC_FALSE@two_file_strip_test$(EXEEXT): $(two_file_strip_test_OBJECTS) $(two_file_strip_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f two_file_strip_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(two_file_strip_test_LDFLAGS) $(two_file_strip_test_OBJECTS) $(two_file_strip_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@two_file_strip_test$(EXEEXT): $(two_file_strip_test_OBJECTS) $(two_file_strip_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f two_file_strip_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(two_file_strip_test_LDFLAGS) $(two_file_strip_test_OBJECTS) $(two_file_strip_test_LDADD) $(LIBS) +two_file_test$(EXEEXT): $(two_file_test_OBJECTS) $(two_file_test_DEPENDENCIES) + @rm -f two_file_test$(EXEEXT) + $(CXXLINK) $(two_file_test_LDFLAGS) $(two_file_test_OBJECTS) $(two_file_test_LDADD) $(LIBS) +ver_test$(EXEEXT): $(ver_test_OBJECTS) $(ver_test_DEPENDENCIES) + @rm -f ver_test$(EXEEXT) + $(CXXLINK) $(ver_test_LDFLAGS) $(ver_test_OBJECTS) $(ver_test_LDADD) $(LIBS) +ver_test_2$(EXEEXT): $(ver_test_2_OBJECTS) $(ver_test_2_DEPENDENCIES) + @rm -f ver_test_2$(EXEEXT) + $(CXXLINK) $(ver_test_2_LDFLAGS) $(ver_test_2_OBJECTS) $(ver_test_2_LDADD) $(LIBS) +ver_test_6$(EXEEXT): $(ver_test_6_OBJECTS) $(ver_test_6_DEPENDENCIES) + @rm -f ver_test_6$(EXEEXT) + $(LINK) $(ver_test_6_LDFLAGS) $(ver_test_6_OBJECTS) $(ver_test_6_LDADD) $(LIBS) +ver_test_8$(EXEEXT): $(ver_test_8_OBJECTS) $(ver_test_8_DEPENDENCIES) + @rm -f ver_test_8$(EXEEXT) + $(CXXLINK) $(ver_test_8_LDFLAGS) $(ver_test_8_OBJECTS) $(ver_test_8_LDADD) $(LIBS) +ver_test_9$(EXEEXT): $(ver_test_9_OBJECTS) $(ver_test_9_DEPENDENCIES) + @rm -f ver_test_9$(EXEEXT) + $(CXXLINK) $(ver_test_9_LDFLAGS) $(ver_test_9_OBJECTS) $(ver_test_9_LDADD) $(LIBS) +weak_alias_test$(EXEEXT): $(weak_alias_test_OBJECTS) $(weak_alias_test_DEPENDENCIES) + @rm -f weak_alias_test$(EXEEXT) + $(CXXLINK) $(weak_alias_test_LDFLAGS) $(weak_alias_test_OBJECTS) $(weak_alias_test_LDADD) $(LIBS) +@GCC_FALSE@weak_plt$(EXEEXT): $(weak_plt_OBJECTS) $(weak_plt_DEPENDENCIES) +@GCC_FALSE@ @rm -f weak_plt$(EXEEXT) +@GCC_FALSE@ $(LINK) $(weak_plt_LDFLAGS) $(weak_plt_OBJECTS) $(weak_plt_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@weak_plt$(EXEEXT): $(weak_plt_OBJECTS) $(weak_plt_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f weak_plt$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(weak_plt_LDFLAGS) $(weak_plt_OBJECTS) $(weak_plt_LDADD) $(LIBS) +weak_test$(EXEEXT): $(weak_test_OBJECTS) $(weak_test_DEPENDENCIES) + @rm -f weak_test$(EXEEXT) + $(CXXLINK) $(weak_test_LDFLAGS) $(weak_test_OBJECTS) $(weak_test_LDADD) $(LIBS) +weak_undef_nonpic_test$(EXEEXT): $(weak_undef_nonpic_test_OBJECTS) $(weak_undef_nonpic_test_DEPENDENCIES) + @rm -f weak_undef_nonpic_test$(EXEEXT) + $(CXXLINK) $(weak_undef_nonpic_test_LDFLAGS) $(weak_undef_nonpic_test_OBJECTS) $(weak_undef_nonpic_test_LDADD) $(LIBS) +weak_undef_test$(EXEEXT): $(weak_undef_test_OBJECTS) $(weak_undef_test_DEPENDENCIES) + @rm -f weak_undef_test$(EXEEXT) + $(CXXLINK) $(weak_undef_test_LDFLAGS) $(weak_undef_test_OBJECTS) $(weak_undef_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_pic_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_static_pic_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_static_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binary_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binary_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_test_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constructor_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copy_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_compress_debug_sections.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_r_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relro_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2a.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2b.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testfile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test_file2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_strip_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_test_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_test_1b.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_test_2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ver_test_6.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ver_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ver_test_main_2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_alias_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_plt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_undef_test.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.cc.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_LIBRARIES) $(check_PROGRAMS) \ + $(check_SCRIPTS) $(check_DATA) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-checkLIBRARIES clean-checkPROGRAMS clean-generic \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-checkLIBRARIES clean-checkPROGRAMS clean-generic ctags \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am + + +# --------------------------------------------------------------------- +# These tests test the output of gold (end-to-end tests). In +# particular, they make sure that gold can link "difficult" object +# files, and the resulting object files run correctly. These can only +# run if we've built ld-new for the native architecture (that is, +# we're not cross-compiling it), since we run ld-new as part of these +# tests. We use the gcc-specific flag '-B' to use our linker instead +# of the default linker, which is why we only run our tests under gcc. + +# Infrastucture needed for the unittests: a directory where the linker +# is named 'ld'. This is because the -B flag appends 'ld' to its arg. +@GCC_TRUE@@NATIVE_LINKER_TRUE@gcctestdir/ld: ../ld-new +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d gcctestdir || mkdir -p gcctestdir +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (cd gcctestdir && $(LN_S) ../../ld-new ld) + +# Each of these .o's is a useful, small complete program. They're +# particularly useful for making sure ld-new's flags do what they're +# supposed to (hence their names), but are used for many tests that +# don't actually involve analyzing input data. +@GCC_TRUE@@NATIVE_LINKER_TRUE@flagstest_debug.o: constructor_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@flagstest_ndebug.o: constructor_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test: basic_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_static_test: basic_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -static basic_test.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_pic_test.o: basic_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_pic_test: basic_pic_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_pic_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_static_pic_test: basic_pic_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -static basic_pic_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_1_pic.o: two_file_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_1b_pic.o: two_file_test_1b.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_2_pic.o: two_file_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1.so: two_file_test_1_pic.o two_file_test_1b_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2.so: two_file_test_2_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared.so: two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_relocatable.o: gcctestdir/ld two_file_test_1.o two_file_test_1b.o two_file_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -r -o $@ two_file_test_1.o two_file_test_1b.o two_file_test_2.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_nonpic.so: two_file_test_1.o gcctestdir/ld +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_nonpic.so: two_file_test_2.o gcctestdir/ld +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_2.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_nonpic.so: two_file_test_1.o two_file_test_1b.o two_file_test_2.o gcctestdir/ld +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b.o two_file_test_2.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_mixed.so: two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2.o gcctestdir/ld +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_mixed_1.so: two_file_test_1.o two_file_test_1b_pic.o two_file_shared_2.so gcctestdir/ld +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b_pic.o two_file_shared_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_strip_test: two_file_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_STRIP) -o two_file_strip_test two_file_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_strip.so: two_file_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_STRIP) -S -o two_file_shared_strip.so two_file_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_1_pic.o: exception_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_2_pic.o: exception_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1.so: exception_test_1_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared exception_test_1_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_2.so: exception_test_2_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared exception_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared.so: exception_test_1_pic.o exception_test_2_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared exception_test_1_pic.o exception_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file1.o: weak_undef_file1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file2.o: weak_undef_file2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_lib.so: weak_undef_file1.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file1.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/weak_undef_lib.so: weak_undef_file2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file2.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file1_nonpic.o: weak_undef_file1.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file2_nonpic.o: weak_undef_file2.cc +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_lib_nonpic.so: weak_undef_file1_nonpic.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file1_nonpic.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/weak_undef_lib_nonpic.so: weak_undef_file2_nonpic.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file2_nonpic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_1_pic.o: weak_alias_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_1.so: weak_alias_test_1_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_alias_test_1_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_2_pic.o: weak_alias_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_2.so: weak_alias_test_2_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_alias_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_3.o: weak_alias_test_3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_4_pic.o: weak_alias_test_4.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_alias_test_4.so: weak_alias_test_4_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_alias_test_4_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_plt_main_pic.o: weak_plt_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_plt: weak_plt_main_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ weak_plt_main_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_plt_shared_pic.o: weak_plt_shared.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_plt_shared.so: weak_plt_shared_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_plt_shared_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_1_pic.o: copy_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_1.so: gcctestdir/ld copy_test_1_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared copy_test_1_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_2_pic.o: copy_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@copy_test_2.so: gcctestdir/ld copy_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared copy_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_pic.o: tls_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_file2_pic.o: tls_test_file2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_c_pic.o: tls_test_c.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_shared.so: tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_shared2.so: tls_test_file2_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_pic.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_pic_ie.o: tls_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -ftls-model=initial-exec -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_file2_pic_ie.o: tls_test_file2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -ftls-model=initial-exec -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_c_pic_ie.o: tls_test_c.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(COMPILE) -c -fpic -ftls-model=initial-exec $(TLS_TEST_C_CFLAGS) -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_ie_shared.so: tls_test_pic_ie.o tls_test_file2_pic_ie.o tls_test_c_pic_ie.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic_ie.o tls_test_file2_pic_ie.o tls_test_c_pic_ie.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_c.o: tls_test_c.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(COMPILE) -c $(TLS_TEST_C_CFLAGS) -o $@ $< + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2.o: tls_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_file2_gnu2.o: tls_test_file2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_c_gnu2.o: tls_test_c.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(COMPILE) -c -fpic -mtls-dialect=gnu2 $(TLS_TEST_C_CFLAGS) -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2_shared2.so: tls_test_file2_gnu2.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_gnu2.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2_shared.so: tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_gnu2.o tls_test_file2_gnu2.o tls_test_c_gnu2.o +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_shared_nonpic.so: tls_test.o tls_test_file2.o tls_test_c.o gcctestdir/ld +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test.o tls_test_file2.o tls_test_c.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_define.h: +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (for i in `seq 1 70000`; do \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "int var_$$i __attribute__((section(\"section_$$i\"))) = $$i;"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ done) > $@.tmp +@GCC_TRUE@@NATIVE_LINKER_TRUE@ mv -f $@.tmp $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_check.h: +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (for i in `seq 1 1000 70000`; do \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "assert(var_$$i == $$i);"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ done) > $@.tmp +@GCC_TRUE@@NATIVE_LINKER_TRUE@ mv -f $@.tmp $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test.o: many_sections_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -r -o $@ many_sections_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_r_test: many_sections_r_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ many_sections_r_test.o $(LIBS) +@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg.o: debug_msg.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation1.o: odr_violation1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation2.o: odr_violation2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o "2>$@" +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o 2>$@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of debug_msg should have failed"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi +@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg.so: debug_msg.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -shared -fPIC -w -o $@ $(srcdir)/debug_msg.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation1.so: odr_violation1.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -shared -fPIC -w -o $@ $(srcdir)/odr_violation1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation2.so: odr_violation2.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -shared -fPIC -w -o $@ $(srcdir)/odr_violation2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg_so.err: debug_msg.so odr_violation1.so odr_violation2.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_so debug_msg.so odr_violation1.so odr_violation2.so "2>$@" +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_so debug_msg.so odr_violation1.so odr_violation2.so 2>$@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of debug_msg_so should have failed"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi +@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg_ndebug.so: debug_msg.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g0 -shared -fPIC -w -o $@ $(srcdir)/debug_msg.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation1_ndebug.so: odr_violation1.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g0 -shared -fPIC -w -o $@ $(srcdir)/odr_violation1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation2_ndebug.so: odr_violation2.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g0 -shared -fPIC -w -o $@ $(srcdir)/odr_violation2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg_ndebug.err: debug_msg_ndebug.so odr_violation1_ndebug.so odr_violation2_ndebug.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_ndebug debug_msg_ndebug.so odr_violation1_ndebug.so odr_violation2_ndebug.so "2>$@" +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg_ndebug debug_msg_ndebug.so odr_violation1_ndebug.so odr_violation2_ndebug.so 2>$@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of debug_msg_ndebug should have failed"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi +@GCC_TRUE@@NATIVE_LINKER_TRUE@undef_symbol.o: undef_symbol.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -fPIC $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@undef_symbol.so: undef_symbol.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared undef_symbol.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@undef_symbol.err: undef_symbol_main.o undef_symbol.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so "2>$@" +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so 2>$@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of undef_symbol_test should have failed"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi +@GCC_TRUE@@NATIVE_LINKER_TRUE@flagstest_o_specialfile: flagstest_debug.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -o /dev/stdout $< 2>&1 | cat > $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ chmod a+x $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -s $@ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@flagstest_compress_debug_sections: flagstest_debug.o gcctestdir/ld +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -o $@ $< -Wl,--compress-debug-sections=zlib +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ test -s $@ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@flagstest_o_specialfile_and_compress_debug_sections: flagstest_debug.o \ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -o /dev/stdout $< -Wl,--compress-debug-sections=zlib 2>&1 | cat > $@ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ chmod a+x $@ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ test -s $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_1.so: ver_test_1.o ver_test_2.so ver_test_3.o ver_test_4.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared ver_test_1.o ver_test_2.so ver_test_3.o ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2.so: ver_test_2.o $(srcdir)/ver_test_2.script ver_test_4.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_2.script ver_test_2.o ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.so: ver_test_4.o $(srcdir)/ver_test_4.script gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_4.script ver_test_4.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_1.o: ver_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2.o: ver_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_3.o: ver_test_3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.o: ver_test_4.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2.syms: ver_test_2 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.syms: ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null + +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_5.so: ver_test_5.o $(srcdir)/ver_test_5.script ver_test_4.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_5.script ver_test_5.o ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_5.o: ver_test_5.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_5.syms: ver_test_5.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null + +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_7.so: ver_test_4.o $(srcdir)/ver_test_4.script ver_test_7.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_4.script ver_test_4.o ver_test_7.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_7.o: ver_test_7.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_7.syms: ver_test_7.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_8_1.so: two_file_test_1_pic.o two_file_test_1b_pic.o ver_test_8_2.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o ver_test_8_2.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_8_2.so: two_file_test_2_pic.o $(srcdir)/ver_test_8.script gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_8.script two_file_test_2_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9.so: ver_test_9.o ver_test_4.so ver_test_5.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared ver_test_9.o ver_test_5.so ver_test_4.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9.o: ver_test_9.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_10.syms: ver_test_10.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_10.so: gcctestdir/ld ver_test_2.o ver_test_10.script +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_10.script ver_test_2.o + +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1.so: gcctestdir/ld protected_1_pic.o protected_2_pic.o protected_3_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared protected_1_pic.o protected_2_pic.o protected_3_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1_pic.o: protected_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_pic.o: protected_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_3_pic.o: protected_3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test.so: gcctestdir/ld relro_test_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro relro_test_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_pic.o: relro_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2.o: justsyms_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2r.o: justsyms_2.o gcctestdir/ld $(srcdir)/justsyms.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ -r -T $(srcdir)/justsyms.t justsyms_2.o +# Copy the file to the build directory to avoid worrying about the +# full pathname in the generated symbols. +@GCC_TRUE@@NATIVE_LINKER_TRUE@binary.txt: $(srcdir)/binary.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LN_S) $< $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_def.so: ver_matching_def.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_test.stdout: ver_matching_def.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -T ver_matching_def.so | $(TEST_CXXFILT) > ver_matching_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_3: basic_test.o gcctestdir/ld script_test_3.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_3.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_3.stdout: script_test_3 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_3 > script_test_3.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_4: basic_test.o gcctestdir/ld $(srcdir)/script_test_4.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_4.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_4.stdout: script_test_4 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_4 > script_test_4.stdout +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gold/testsuite/weak_plt.sh b/gold/testsuite/weak_plt.sh new file mode 100755 index 00000000000..6c419b8095a --- /dev/null +++ b/gold/testsuite/weak_plt.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# weak_plt.sh -- test calling a weak undefined function. + +# Copyright 2008 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This tests a call to a weak undefined function. We use LD_PRELOAD +# to force the function to be defined. + +LD_PRELOAD=./weak_plt_shared.so ./weak_plt diff --git a/gold/testsuite/weak_plt_main.cc b/gold/testsuite/weak_plt_main.cc new file mode 100644 index 00000000000..33cb35eb10f --- /dev/null +++ b/gold/testsuite/weak_plt_main.cc @@ -0,0 +1,33 @@ +// weak_plt_main.cc -- test call to weak undefined function for gold + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include <cstdio> + +extern int weak_function() __attribute__((weak)); + +int +main() +{ + if (weak_function) + return weak_function(); + return 0; +} diff --git a/gold/testsuite/weak_plt_shared.cc b/gold/testsuite/weak_plt_shared.cc new file mode 100644 index 00000000000..8d82005d55a --- /dev/null +++ b/gold/testsuite/weak_plt_shared.cc @@ -0,0 +1,29 @@ +// weak_plt_shared.cc -- test call to weak undefined function for gold + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include <cstdio> + +int +weak_function() +{ + return 0; +} diff --git a/gold/x86_64.cc b/gold/x86_64.cc new file mode 100644 index 00000000000..cbbd5ccf368 --- /dev/null +++ b/gold/x86_64.cc @@ -0,0 +1,2608 @@ +// x86_64.cc -- x86_64 target support for gold. + +// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstring> + +#include "elfcpp.h" +#include "parameters.h" +#include "reloc.h" +#include "x86_64.h" +#include "object.h" +#include "symtab.h" +#include "layout.h" +#include "output.h" +#include "copy-relocs.h" +#include "target.h" +#include "target-reloc.h" +#include "target-select.h" +#include "tls.h" + +namespace +{ + +using namespace gold; + +class Output_data_plt_x86_64; + +// The x86_64 target class. +// See the ABI at +// http://www.x86-64.org/documentation/abi.pdf +// TLS info comes from +// http://people.redhat.com/drepper/tls.pdf +// http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt + +class Target_x86_64 : public Sized_target<64, false> +{ + public: + // In the x86_64 ABI (p 68), it says "The AMD64 ABI architectures + // uses only Elf64_Rela relocation entries with explicit addends." + typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section; + + Target_x86_64() + : Sized_target<64, false>(&x86_64_info), + got_(NULL), plt_(NULL), got_plt_(NULL), rela_dyn_(NULL), + copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL), + got_mod_index_offset_(-1U), tls_base_symbol_defined_(false) + { } + + // Scan the relocations to look for symbol adjustments. + void + scan_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + + // Finalize the sections. + void + do_finalize_sections(Layout*); + + // Return the value to use for a dynamic which requires special + // treatment. + uint64_t + do_dynsym_value(const Symbol*) const; + + // Relocate a section. + void + relocate_section(const Relocate_info<64, false>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr view_address, + section_size_type view_size); + + // Scan the relocs during a relocatable link. + void + scan_relocatable_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs*); + + // Relocate a section during a relocatable link. + void + relocate_for_relocatable(const Relocate_info<64, false>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); + + // Return a string used to fill a code section with nops. + std::string + do_code_fill(section_size_type length) const; + + // Return whether SYM is defined by the ABI. + bool + do_is_defined_by_abi(Symbol* sym) const + { return strcmp(sym->name(), "__tls_get_addr") == 0; } + + // Return the size of the GOT section. + section_size_type + got_size() + { + gold_assert(this->got_ != NULL); + return this->got_->data_size(); + } + + private: + // The class which scans relocations. + class Scan + { + public: + Scan() + : issued_non_pic_error_(false) + { } + + inline void + local(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_x86_64* target, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<64, false>& reloc, unsigned int r_type, + const elfcpp::Sym<64, false>& lsym); + + inline void + global(const General_options& options, Symbol_table* symtab, + Layout* layout, Target_x86_64* target, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<64, false>& reloc, unsigned int r_type, + Symbol* gsym); + + private: + static void + unsupported_reloc_local(Sized_relobj<64, false>*, unsigned int r_type); + + static void + unsupported_reloc_global(Sized_relobj<64, false>*, unsigned int r_type, + Symbol*); + + void + check_non_pic(Relobj*, unsigned int r_type); + + // Whether we have issued an error about a non-PIC compilation. + bool issued_non_pic_error_; + }; + + // The class which implements relocation. + class Relocate + { + public: + Relocate() + : skip_call_tls_get_addr_(false), saw_tls_block_reloc_(false) + { } + + ~Relocate() + { + if (this->skip_call_tls_get_addr_) + { + // FIXME: This needs to specify the location somehow. + gold_error(_("missing expected TLS relocation")); + } + } + + // Do a relocation. Return false if the caller should not issue + // any warnings about this relocation. + inline bool + relocate(const Relocate_info<64, false>*, Target_x86_64*, size_t relnum, + const elfcpp::Rela<64, false>&, + unsigned int r_type, const Sized_symbol<64>*, + const Symbol_value<64>*, + unsigned char*, elfcpp::Elf_types<64>::Elf_Addr, + section_size_type); + + private: + // Do a TLS relocation. + inline void + relocate_tls(const Relocate_info<64, false>*, Target_x86_64*, + size_t relnum, const elfcpp::Rela<64, false>&, + unsigned int r_type, const Sized_symbol<64>*, + const Symbol_value<64>*, + unsigned char*, elfcpp::Elf_types<64>::Elf_Addr, + section_size_type); + + // Do a TLS General-Dynamic to Initial-Exec transition. + inline void + tls_gd_to_ie(const Relocate_info<64, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>&, unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr, + section_size_type view_size); + + // Do a TLS General-Dynamic to Local-Exec transition. + inline void + tls_gd_to_le(const Relocate_info<64, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>&, unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLSDESC-style General-Dynamic to Initial-Exec transition. + inline void + tls_desc_gd_to_ie(const Relocate_info<64, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>&, unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr, + section_size_type view_size); + + // Do a TLSDESC-style General-Dynamic to Local-Exec transition. + inline void + tls_desc_gd_to_le(const Relocate_info<64, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>&, unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS Local-Dynamic to Local-Exec transition. + inline void + tls_ld_to_le(const Relocate_info<64, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>&, unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // Do a TLS Initial-Exec to Local-Exec transition. + static inline void + tls_ie_to_le(const Relocate_info<64, false>*, size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>&, unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size); + + // This is set if we should skip the next reloc, which should be a + // PLT32 reloc against ___tls_get_addr. + bool skip_call_tls_get_addr_; + + // This is set if we see a relocation which could load the address + // of the TLS block. Whether we see such a relocation determines + // how we handle the R_X86_64_DTPOFF32 relocation, which is used + // in debugging sections. + bool saw_tls_block_reloc_; + }; + + // A class which returns the size required for a relocation type, + // used while scanning relocs during a relocatable link. + class Relocatable_size_for_reloc + { + public: + unsigned int + get_size_for_reloc(unsigned int, Relobj*); + }; + + // Adjust TLS relocation type based on the options and whether this + // is a local symbol. + static tls::Tls_optimization + optimize_tls_reloc(bool is_final, int r_type); + + // Get the GOT section, creating it if necessary. + Output_data_got<64, false>* + got_section(Symbol_table*, Layout*); + + // Get the GOT PLT section. + Output_data_space* + got_plt_section() const + { + gold_assert(this->got_plt_ != NULL); + return this->got_plt_; + } + + // Create the PLT section. + void + make_plt_section(Symbol_table* symtab, Layout* layout); + + // Create a PLT entry for a global symbol. + void + make_plt_entry(Symbol_table*, Layout*, Symbol*); + + // Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. + void + define_tls_base_symbol(Symbol_table*, Layout*); + + // Create the reserved PLT and GOT entries for the TLS descriptor resolver. + void + reserve_tlsdesc_entries(Symbol_table* symtab, Layout* layout); + + // Create a GOT entry for the TLS module index. + unsigned int + got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<64, false>* object); + + // Get the PLT section. + Output_data_plt_x86_64* + plt_section() const + { + gold_assert(this->plt_ != NULL); + return this->plt_; + } + + // Get the dynamic reloc section, creating it if necessary. + Reloc_section* + rela_dyn_section(Layout*); + + // Return true if the symbol may need a COPY relocation. + // References from an executable object to non-function symbols + // defined in a dynamic object may need a COPY relocation. + bool + may_need_copy_reloc(Symbol* gsym) + { + return (!parameters->options().shared() + && gsym->is_from_dynobj() + && gsym->type() != elfcpp::STT_FUNC); + } + + // Add a potential copy relocation. + void + copy_reloc(Symbol_table* symtab, Layout* layout, + Sized_relobj<64, false>* object, + unsigned int shndx, Output_section* output_section, + Symbol* sym, const elfcpp::Rela<64, false>& reloc) + { + this->copy_relocs_.copy_reloc(symtab, layout, + symtab->get_sized_symbol<64>(sym), + object, shndx, output_section, + reloc, this->rela_dyn_section(layout)); + } + + // Information about this specific target which we pass to the + // general Target structure. + static const Target::Target_info x86_64_info; + + enum Got_type + { + GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol + GOT_TYPE_TLS_OFFSET = 1, // GOT entry for TLS offset + GOT_TYPE_TLS_PAIR = 2, // GOT entry for TLS module/offset pair + GOT_TYPE_TLS_DESC = 3 // GOT entry for TLS_DESC pair + }; + + // The GOT section. + Output_data_got<64, false>* got_; + // The PLT section. + Output_data_plt_x86_64* plt_; + // The GOT PLT section. + Output_data_space* got_plt_; + // The dynamic reloc section. + Reloc_section* rela_dyn_; + // Relocs saved to avoid a COPY reloc. + Copy_relocs<elfcpp::SHT_RELA, 64, false> copy_relocs_; + // Space for variables copied with a COPY reloc. + Output_data_space* dynbss_; + // Offset of the GOT entry for the TLS module index. + unsigned int got_mod_index_offset_; + // True if the _TLS_MODULE_BASE_ symbol has been defined. + bool tls_base_symbol_defined_; +}; + +const Target::Target_info Target_x86_64::x86_64_info = +{ + 64, // size + false, // is_big_endian + elfcpp::EM_X86_64, // machine_code + false, // has_make_symbol + false, // has_resolve + true, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/lib/ld64.so.1", // program interpreter + 0x400000, // default_text_segment_address + 0x1000, // abi_pagesize (overridable by -z max-page-size) + 0x1000 // common_pagesize (overridable by -z common-page-size) +}; + +// Get the GOT section, creating it if necessary. + +Output_data_got<64, false>* +Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) +{ + if (this->got_ == NULL) + { + gold_assert(symtab != NULL && layout != NULL); + + this->got_ = new Output_data_got<64, false>(); + + Output_section* os; + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_); + os->set_is_relro(); + + // The old GNU linker creates a .got.plt section. We just + // create another set of data in the .got section. Note that we + // always create a PLT if we create a GOT, although the PLT + // might be empty. + this->got_plt_ = new Output_data_space(8, "** GOT PLT"); + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_plt_); + os->set_is_relro(); + + // The first three entries are reserved. + this->got_plt_->set_current_data_size(3 * 8); + + // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + this->got_plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + + return this->got_; +} + +// Get the dynamic reloc section, creating it if necessary. + +Target_x86_64::Reloc_section* +Target_x86_64::rela_dyn_section(Layout* layout) +{ + if (this->rela_dyn_ == NULL) + { + gold_assert(layout != NULL); + this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); + layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->rela_dyn_); + } + return this->rela_dyn_; +} + +// A class to handle the PLT data. + +class Output_data_plt_x86_64 : public Output_section_data +{ + public: + typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section; + + Output_data_plt_x86_64(Layout*, Output_data_got<64, false>*, + Output_data_space*); + + // Add an entry to the PLT. + void + add_entry(Symbol* gsym); + + // Add the reserved TLSDESC_PLT entry to the PLT. + void + reserve_tlsdesc_entry(unsigned int got_offset) + { this->tlsdesc_got_offset_ = got_offset; } + + // Return true if a TLSDESC_PLT entry has been reserved. + bool + has_tlsdesc_entry() const + { return this->tlsdesc_got_offset_ != -1U; } + + // Return the GOT offset for the reserved TLSDESC_PLT entry. + unsigned int + get_tlsdesc_got_offset() const + { return this->tlsdesc_got_offset_; } + + // Return the offset of the reserved TLSDESC_PLT entry. + unsigned int + get_tlsdesc_plt_offset() const + { return (this->count_ + 1) * plt_entry_size; } + + // Return the .rel.plt section data. + const Reloc_section* + rel_plt() const + { return this->rel_; } + + protected: + void + do_adjust_output_section(Output_section* os); + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, _("** PLT")); } + + private: + // The size of an entry in the PLT. + static const int plt_entry_size = 16; + + // The first entry in the PLT. + // From the AMD64 ABI: "Unlike Intel386 ABI, this ABI uses the same + // procedure linkage table for both programs and shared objects." + static unsigned char first_plt_entry[plt_entry_size]; + + // Other entries in the PLT for an executable. + static unsigned char plt_entry[plt_entry_size]; + + // The reserved TLSDESC entry in the PLT for an executable. + static unsigned char tlsdesc_plt_entry[plt_entry_size]; + + // Set the final size. + void + set_final_data_size(); + + // Write out the PLT data. + void + do_write(Output_file*); + + // The reloc section. + Reloc_section* rel_; + // The .got section. + Output_data_got<64, false>* got_; + // The .got.plt section. + Output_data_space* got_plt_; + // The number of PLT entries. + unsigned int count_; + // Offset of the reserved TLSDESC_GOT entry when needed. + unsigned int tlsdesc_got_offset_; +}; + +// Create the PLT section. The ordinary .got section is an argument, +// since we need to refer to the start. We also create our own .got +// section just for PLT entries. + +Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout, + Output_data_got<64, false>* got, + Output_data_space* got_plt) + : Output_section_data(8), got_(got), got_plt_(got_plt), count_(0), + tlsdesc_got_offset_(-1U) +{ + this->rel_ = new Reloc_section(false); + layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->rel_); +} + +void +Output_data_plt_x86_64::do_adjust_output_section(Output_section* os) +{ + // UnixWare sets the entsize of .plt to 4, and so does the old GNU + // linker, and so do we. + os->set_entsize(4); +} + +// Add an entry to the PLT. + +void +Output_data_plt_x86_64::add_entry(Symbol* gsym) +{ + gold_assert(!gsym->has_plt_offset()); + + // Note that when setting the PLT offset we skip the initial + // reserved PLT entry. + gsym->set_plt_offset((this->count_ + 1) * plt_entry_size); + + ++this->count_; + + section_offset_type got_offset = this->got_plt_->current_data_size(); + + // Every PLT entry needs a GOT entry which points back to the PLT + // entry (this will be changed by the dynamic linker, normally + // lazily when the function is called). + this->got_plt_->set_current_data_size(got_offset + 8); + + // Every PLT entry needs a reloc. + gsym->set_needs_dynsym_entry(); + this->rel_->add_global(gsym, elfcpp::R_X86_64_JUMP_SLOT, this->got_plt_, + got_offset, 0); + + // Note that we don't need to save the symbol. The contents of the + // PLT are independent of which symbols are used. The symbols only + // appear in the relocations. +} + +// Set the final size. +void +Output_data_plt_x86_64::set_final_data_size() +{ + unsigned int count = this->count_; + if (this->has_tlsdesc_entry()) + ++count; + this->set_data_size((count + 1) * plt_entry_size); +} + +// The first entry in the PLT for an executable. + +unsigned char Output_data_plt_x86_64::first_plt_entry[plt_entry_size] = +{ + // From AMD64 ABI Draft 0.98, page 76 + 0xff, 0x35, // pushq contents of memory address + 0, 0, 0, 0, // replaced with address of .got + 8 + 0xff, 0x25, // jmp indirect + 0, 0, 0, 0, // replaced with address of .got + 16 + 0x90, 0x90, 0x90, 0x90 // noop (x4) +}; + +// Subsequent entries in the PLT for an executable. + +unsigned char Output_data_plt_x86_64::plt_entry[plt_entry_size] = +{ + // From AMD64 ABI Draft 0.98, page 76 + 0xff, 0x25, // jmpq indirect + 0, 0, 0, 0, // replaced with address of symbol in .got + 0x68, // pushq immediate + 0, 0, 0, 0, // replaced with offset into relocation table + 0xe9, // jmpq relative + 0, 0, 0, 0 // replaced with offset to start of .plt +}; + +// The reserved TLSDESC entry in the PLT for an executable. + +unsigned char Output_data_plt_x86_64::tlsdesc_plt_entry[plt_entry_size] = +{ + // From Alexandre Oliva, "Thread-Local Storage Descriptors for IA32 + // and AMD64/EM64T", Version 0.9.4 (2005-10-10). + 0xff, 0x35, // pushq x(%rip) + 0, 0, 0, 0, // replaced with address of linkmap GOT entry (at PLTGOT + 8) + 0xff, 0x25, // jmpq *y(%rip) + 0, 0, 0, 0, // replaced with offset of reserved TLSDESC_GOT entry + 0x0f, 0x1f, // nop + 0x40, 0 +}; + +// Write out the PLT. This uses the hand-coded instructions above, +// and adjusts them as needed. This is specified by the AMD64 ABI. + +void +Output_data_plt_x86_64::do_write(Output_file* of) +{ + const off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + const off_t got_file_offset = this->got_plt_->offset(); + const section_size_type got_size = + convert_to_section_size_type(this->got_plt_->data_size()); + unsigned char* const got_view = of->get_output_view(got_file_offset, + got_size); + + unsigned char* pov = oview; + + // The base address of the .plt section. + elfcpp::Elf_types<64>::Elf_Addr plt_address = this->address(); + // The base address of the .got section. + elfcpp::Elf_types<64>::Elf_Addr got_base = this->got_->address(); + // The base address of the PLT portion of the .got section, + // which is where the GOT pointer will point, and where the + // three reserved GOT entries are located. + elfcpp::Elf_types<64>::Elf_Addr got_address = this->got_plt_->address(); + + memcpy(pov, first_plt_entry, plt_entry_size); + // We do a jmp relative to the PC at the end of this instruction. + elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, + (got_address + 8 + - (plt_address + 6))); + elfcpp::Swap<32, false>::writeval(pov + 8, + (got_address + 16 + - (plt_address + 12))); + pov += plt_entry_size; + + unsigned char* got_pov = got_view; + + memset(got_pov, 0, 24); + got_pov += 24; + + unsigned int plt_offset = plt_entry_size; + unsigned int got_offset = 24; + const unsigned int count = this->count_; + for (unsigned int plt_index = 0; + plt_index < count; + ++plt_index, + pov += plt_entry_size, + got_pov += 8, + plt_offset += plt_entry_size, + got_offset += 8) + { + // Set and adjust the PLT entry itself. + memcpy(pov, plt_entry, plt_entry_size); + elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, + (got_address + got_offset + - (plt_address + plt_offset + + 6))); + + elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_index); + elfcpp::Swap<32, false>::writeval(pov + 12, + - (plt_offset + plt_entry_size)); + + // Set the entry in the GOT. + elfcpp::Swap<64, false>::writeval(got_pov, plt_address + plt_offset + 6); + } + + if (this->has_tlsdesc_entry()) + { + // Set and adjust the reserved TLSDESC PLT entry. + unsigned int tlsdesc_got_offset = this->get_tlsdesc_got_offset(); + memcpy(pov, tlsdesc_plt_entry, plt_entry_size); + elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, + (got_address + 8 + - (plt_address + plt_offset + + 6))); + elfcpp::Swap_unaligned<32, false>::writeval(pov + 8, + (got_base + + tlsdesc_got_offset + - (plt_address + plt_offset + + 12))); + pov += plt_entry_size; + } + + gold_assert(static_cast<section_size_type>(pov - oview) == oview_size); + gold_assert(static_cast<section_size_type>(got_pov - got_view) == got_size); + + of->write_output_view(offset, oview_size, oview); + of->write_output_view(got_file_offset, got_size, got_view); +} + +// Create the PLT section. + +void +Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout) +{ + if (this->plt_ == NULL) + { + // Create the GOT sections first. + this->got_section(symtab, layout); + + this->plt_ = new Output_data_plt_x86_64(layout, this->got_, + this->got_plt_); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR), + this->plt_); + } +} + +// Create a PLT entry for a global symbol. + +void +Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout, + Symbol* gsym) +{ + if (gsym->has_plt_offset()) + return; + + if (this->plt_ == NULL) + this->make_plt_section(symtab, layout); + + this->plt_->add_entry(gsym); +} + +// Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. + +void +Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout) +{ + if (this->tls_base_symbol_defined_) + return; + + Output_segment* tls_segment = layout->tls_segment(); + if (tls_segment != NULL) + { + symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL, + tls_segment, 0, 0, + elfcpp::STT_TLS, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + Symbol::SEGMENT_END, true); + } + this->tls_base_symbol_defined_ = true; +} + +// Create the reserved PLT and GOT entries for the TLS descriptor resolver. + +void +Target_x86_64::reserve_tlsdesc_entries(Symbol_table* symtab, + Layout* layout) +{ + if (this->plt_ == NULL) + this->make_plt_section(symtab, layout); + + if (!this->plt_->has_tlsdesc_entry()) + { + // Allocate the TLSDESC_GOT entry. + Output_data_got<64, false>* got = this->got_section(symtab, layout); + unsigned int got_offset = got->add_constant(0); + + // Allocate the TLSDESC_PLT entry. + this->plt_->reserve_tlsdesc_entry(got_offset); + } +} + +// Create a GOT entry for the TLS module index. + +unsigned int +Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<64, false>* object) +{ + if (this->got_mod_index_offset_ == -1U) + { + gold_assert(symtab != NULL && layout != NULL && object != NULL); + Reloc_section* rela_dyn = this->rela_dyn_section(layout); + Output_data_got<64, false>* got = this->got_section(symtab, layout); + unsigned int got_offset = got->add_constant(0); + rela_dyn->add_local(object, 0, elfcpp::R_X86_64_DTPMOD64, got, + got_offset, 0); + got->add_constant(0); + this->got_mod_index_offset_ = got_offset; + } + return this->got_mod_index_offset_; +} + +// Optimize the TLS relocation type based on what we know about the +// symbol. IS_FINAL is true if the final address of this symbol is +// known at link time. + +tls::Tls_optimization +Target_x86_64::optimize_tls_reloc(bool is_final, int r_type) +{ + // If we are generating a shared library, then we can't do anything + // in the linker. + if (parameters->options().shared()) + return tls::TLSOPT_NONE; + + switch (r_type) + { + case elfcpp::R_X86_64_TLSGD: + case elfcpp::R_X86_64_GOTPC32_TLSDESC: + case elfcpp::R_X86_64_TLSDESC_CALL: + // These are General-Dynamic which permits fully general TLS + // access. Since we know that we are generating an executable, + // we can convert this to Initial-Exec. If we also know that + // this is a local symbol, we can further switch to Local-Exec. + if (is_final) + return tls::TLSOPT_TO_LE; + return tls::TLSOPT_TO_IE; + + case elfcpp::R_X86_64_TLSLD: + // This is Local-Dynamic, which refers to a local symbol in the + // dynamic TLS block. Since we know that we generating an + // executable, we can switch to Local-Exec. + return tls::TLSOPT_TO_LE; + + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + // Another Local-Dynamic reloc. + return tls::TLSOPT_TO_LE; + + case elfcpp::R_X86_64_GOTTPOFF: + // These are Initial-Exec relocs which get the thread offset + // from the GOT. If we know that we are linking against the + // local symbol, we can switch to Local-Exec, which links the + // thread offset into the instruction. + if (is_final) + return tls::TLSOPT_TO_LE; + return tls::TLSOPT_NONE; + + case elfcpp::R_X86_64_TPOFF32: + // When we already have Local-Exec, there is nothing further we + // can do. + return tls::TLSOPT_NONE; + + default: + gold_unreachable(); + } +} + +// Report an unsupported relocation against a local symbol. + +void +Target_x86_64::Scan::unsupported_reloc_local(Sized_relobj<64, false>* object, + unsigned int r_type) +{ + gold_error(_("%s: unsupported reloc %u against local symbol"), + object->name().c_str(), r_type); +} + +// We are about to emit a dynamic relocation of type R_TYPE. If the +// dynamic linker does not support it, issue an error. The GNU linker +// only issues a non-PIC error for an allocated read-only section. +// Here we know the section is allocated, but we don't know that it is +// read-only. But we check for all the relocation types which the +// glibc dynamic linker supports, so it seems appropriate to issue an +// error even if the section is not read-only. + +void +Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type) +{ + switch (r_type) + { + // These are the relocation types supported by glibc for x86_64. + case elfcpp::R_X86_64_RELATIVE: + case elfcpp::R_X86_64_GLOB_DAT: + case elfcpp::R_X86_64_JUMP_SLOT: + case elfcpp::R_X86_64_DTPMOD64: + case elfcpp::R_X86_64_DTPOFF64: + case elfcpp::R_X86_64_TPOFF64: + case elfcpp::R_X86_64_64: + case elfcpp::R_X86_64_32: + case elfcpp::R_X86_64_PC32: + case elfcpp::R_X86_64_COPY: + return; + + default: + // This prevents us from issuing more than one error per reloc + // section. But we can still wind up issuing more than one + // error per object file. + if (this->issued_non_pic_error_) + return; + object->error(_("requires unsupported dynamic reloc; " + "recompile with -fPIC")); + this->issued_non_pic_error_ = true; + return; + + case elfcpp::R_X86_64_NONE: + gold_unreachable(); + } +} + +// Scan a relocation for a local symbol. + +inline void +Target_x86_64::Scan::local(const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_x86_64* target, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<64, false>& reloc, + unsigned int r_type, + const elfcpp::Sym<64, false>& lsym) +{ + switch (r_type) + { + case elfcpp::R_X86_64_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + break; + + case elfcpp::R_X86_64_64: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for this + // location. The relocation applied at link time will apply the + // link-time value, so we flag the location with an + // R_X86_64_RELATIVE relocation so the dynamic loader can + // relocate it easily. + if (parameters->options().output_is_position_independent()) + { + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_local_relative(object, r_sym, + elfcpp::R_X86_64_RELATIVE, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + } + break; + + case elfcpp::R_X86_64_32: + case elfcpp::R_X86_64_32S: + case elfcpp::R_X86_64_16: + case elfcpp::R_X86_64_8: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for this + // location. We can't use an R_X86_64_RELATIVE relocation + // because that is always a 64-bit relocation. + if (parameters->options().output_is_position_independent()) + { + this->check_non_pic(object, r_type); + + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); + if (lsym.get_st_type() != elfcpp::STT_SECTION) + rela_dyn->add_local(object, r_sym, r_type, output_section, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + else + { + gold_assert(lsym.get_st_value() == 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, + &is_ordinary); + if (!is_ordinary) + object->error(_("section symbol %u has bad shndx %u"), + r_sym, shndx); + else + rela_dyn->add_local_section(object, shndx, + r_type, output_section, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + break; + + case elfcpp::R_X86_64_PC64: + case elfcpp::R_X86_64_PC32: + case elfcpp::R_X86_64_PC16: + case elfcpp::R_X86_64_PC8: + break; + + case elfcpp::R_X86_64_PLT32: + // Since we know this is a local symbol, we can handle this as a + // PC32 reloc. + break; + + case elfcpp::R_X86_64_GOTPC32: + case elfcpp::R_X86_64_GOTOFF64: + case elfcpp::R_X86_64_GOTPC64: + case elfcpp::R_X86_64_PLTOFF64: + // We need a GOT section. + target->got_section(symtab, layout); + // For PLTOFF64, we'd normally want a PLT section, but since we + // know this is a local symbol, no PLT is needed. + break; + + case elfcpp::R_X86_64_GOT64: + case elfcpp::R_X86_64_GOT32: + case elfcpp::R_X86_64_GOTPCREL64: + case elfcpp::R_X86_64_GOTPCREL: + case elfcpp::R_X86_64_GOTPLT64: + { + // The symbol requires a GOT entry. + Output_data_got<64, false>* got = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); + if (got->add_local(object, r_sym, GOT_TYPE_STANDARD)) + { + // If we are generating a shared object, we need to add a + // dynamic relocation for this symbol's GOT entry. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + // R_X86_64_RELATIVE assumes a 64-bit relocation. + if (r_type != elfcpp::R_X86_64_GOT32) + rela_dyn->add_local_relative( + object, r_sym, elfcpp::R_X86_64_RELATIVE, got, + object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0); + else + { + this->check_non_pic(object, r_type); + + gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); + rela_dyn->add_local( + object, r_sym, r_type, got, + object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0); + } + } + } + // For GOTPLT64, we'd normally want a PLT section, but since + // we know this is a local symbol, no PLT is needed. + } + break; + + case elfcpp::R_X86_64_COPY: + case elfcpp::R_X86_64_GLOB_DAT: + case elfcpp::R_X86_64_JUMP_SLOT: + case elfcpp::R_X86_64_RELATIVE: + // These are outstanding tls relocs, which are unexpected when linking + case elfcpp::R_X86_64_TPOFF64: + case elfcpp::R_X86_64_DTPMOD64: + case elfcpp::R_X86_64_TLSDESC: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + // These are initial tls relocs, which are expected when linking + case elfcpp::R_X86_64_TLSGD: // Global-dynamic + case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_TLSDESC_CALL: + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_TPOFF32: // Local-exec + { + bool output_is_shared = parameters->options().shared(); + const tls::Tls_optimization optimized_type + = Target_x86_64::optimize_tls_reloc(!output_is_shared, r_type); + switch (r_type) + { + case elfcpp::R_X86_64_TLSGD: // General-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rela(object, r_sym, + shndx, + GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_DTPMOD64, 0); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_X86_64_GOTPC32_TLSDESC: + target->define_tls_base_symbol(symtab, layout); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create reserved PLT and GOT entries for the resolver. + target->reserve_tlsdesc_entries(symtab, layout); + + // Generate a double GOT entry with an R_X86_64_TLSDESC reloc. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + else + got->add_local_pair_with_rela(object, r_sym, + shndx, + GOT_TYPE_TLS_DESC, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TLSDESC, 0); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_X86_64_TLSDESC_CALL: + break; + + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + break; + + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); + got->add_local_with_rela(object, r_sym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_local(object, r_type); + break; + + case elfcpp::R_X86_64_TPOFF32: // Local-exec + layout->set_has_static_tls(); + if (output_is_shared) + unsupported_reloc_local(object, r_type); + break; + + default: + gold_unreachable(); + } + } + break; + + case elfcpp::R_X86_64_SIZE32: + case elfcpp::R_X86_64_SIZE64: + default: + gold_error(_("%s: unsupported reloc %u against local symbol"), + object->name().c_str(), r_type); + break; + } +} + + +// Report an unsupported relocation against a global symbol. + +void +Target_x86_64::Scan::unsupported_reloc_global(Sized_relobj<64, false>* object, + unsigned int r_type, + Symbol* gsym) +{ + gold_error(_("%s: unsupported reloc %u against global symbol %s"), + object->name().c_str(), r_type, gsym->demangled_name().c_str()); +} + +// Scan a relocation for a global symbol. + +inline void +Target_x86_64::Scan::global(const General_options&, + Symbol_table* symtab, + Layout* layout, + Target_x86_64* target, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<64, false>& reloc, + unsigned int r_type, + Symbol* gsym) +{ + switch (r_type) + { + case elfcpp::R_X86_64_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + break; + + case elfcpp::R_X86_64_64: + case elfcpp::R_X86_64_32: + case elfcpp::R_X86_64_32S: + case elfcpp::R_X86_64_16: + case elfcpp::R_X86_64_8: + { + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + { + target->make_plt_entry(symtab, layout, gsym); + // Since this is not a PC-relative relocation, we may be + // taking the address of a function. In that case we need to + // set the entry in the dynamic symbol table to the address of + // the PLT entry. + if (gsym->is_from_dynobj() && !parameters->options().shared()) + gsym->set_needs_dynsym_value(); + } + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else if (r_type == elfcpp::R_X86_64_64 + && gsym->can_use_relative_reloc(false)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE, + output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + else + { + this->check_non_pic(object, r_type); + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + } + break; + + case elfcpp::R_X86_64_PC64: + case elfcpp::R_X86_64_PC32: + case elfcpp::R_X86_64_PC16: + case elfcpp::R_X86_64_PC8: + { + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + target->make_plt_entry(symtab, layout, gsym); + // Make a dynamic relocation if necessary. + int flags = Symbol::NON_PIC_REF; + if (gsym->type() == elfcpp::STT_FUNC) + flags |= Symbol::FUNCTION_CALL; + if (gsym->needs_dynamic_reloc(flags)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else + { + this->check_non_pic(object, r_type); + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset(), + reloc.get_r_addend()); + } + } + } + break; + + case elfcpp::R_X86_64_GOT64: + case elfcpp::R_X86_64_GOT32: + case elfcpp::R_X86_64_GOTPCREL64: + case elfcpp::R_X86_64_GOTPCREL: + case elfcpp::R_X86_64_GOTPLT64: + { + // The symbol requires a GOT entry. + Output_data_got<64, false>* got = target->got_section(symtab, layout); + if (gsym->final_value_is_known()) + got->add_global(gsym, GOT_TYPE_STANDARD); + else + { + // If this symbol is not fully resolved, we need to add a + // dynamic relocation for it. + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_X86_64_GLOB_DAT); + else + { + if (got->add_global(gsym, GOT_TYPE_STANDARD)) + rela_dyn->add_global_relative( + gsym, elfcpp::R_X86_64_RELATIVE, got, + gsym->got_offset(GOT_TYPE_STANDARD), 0); + } + } + // For GOTPLT64, we also need a PLT entry (but only if the + // symbol is not fully resolved). + if (r_type == elfcpp::R_X86_64_GOTPLT64 + && !gsym->final_value_is_known()) + target->make_plt_entry(symtab, layout, gsym); + } + break; + + case elfcpp::R_X86_64_PLT32: + // If the symbol is fully resolved, this is just a PC32 reloc. + // Otherwise we need a PLT entry. + if (gsym->final_value_is_known()) + break; + // If building a shared library, we can also skip the PLT entry + // if the symbol is defined in the output file and is protected + // or hidden. + if (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible()) + break; + target->make_plt_entry(symtab, layout, gsym); + break; + + case elfcpp::R_X86_64_GOTPC32: + case elfcpp::R_X86_64_GOTOFF64: + case elfcpp::R_X86_64_GOTPC64: + case elfcpp::R_X86_64_PLTOFF64: + // We need a GOT section. + target->got_section(symtab, layout); + // For PLTOFF64, we also need a PLT entry (but only if the + // symbol is not fully resolved). + if (r_type == elfcpp::R_X86_64_PLTOFF64 + && !gsym->final_value_is_known()) + target->make_plt_entry(symtab, layout, gsym); + break; + + case elfcpp::R_X86_64_COPY: + case elfcpp::R_X86_64_GLOB_DAT: + case elfcpp::R_X86_64_JUMP_SLOT: + case elfcpp::R_X86_64_RELATIVE: + // These are outstanding tls relocs, which are unexpected when linking + case elfcpp::R_X86_64_TPOFF64: + case elfcpp::R_X86_64_DTPMOD64: + case elfcpp::R_X86_64_TLSDESC: + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + // These are initial tls relocs, which are expected for global() + case elfcpp::R_X86_64_TLSGD: // Global-dynamic + case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_TLSDESC_CALL: + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_TPOFF32: // Local-exec + { + const bool is_final = gsym->final_value_is_known(); + const tls::Tls_optimization optimized_type + = Target_x86_64::optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_X86_64_TLSGD: // General-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_DTPMOD64, + elfcpp::R_X86_64_DTPOFF64); + } + else if (optimized_type == tls::TLSOPT_TO_IE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_X86_64_GOTPC32_TLSDESC: + target->define_tls_base_symbol(symtab, layout); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create reserved PLT and GOT entries for the resolver. + target->reserve_tlsdesc_entries(symtab, layout); + + // Create a double GOT entry with an R_X86_64_TLSDESC reloc. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TLSDESC, 0); + } + else if (optimized_type == tls::TLSOPT_TO_IE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_X86_64_TLSDESC_CALL: + break; + + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + break; + + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the tp-relative offset. + Output_data_got<64, false>* got + = target->got_section(symtab, layout); + got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); + } + else if (optimized_type != tls::TLSOPT_TO_LE) + unsupported_reloc_global(object, r_type, gsym); + break; + + case elfcpp::R_X86_64_TPOFF32: // Local-exec + layout->set_has_static_tls(); + if (parameters->options().shared()) + unsupported_reloc_local(object, r_type); + break; + + default: + gold_unreachable(); + } + } + break; + + case elfcpp::R_X86_64_SIZE32: + case elfcpp::R_X86_64_SIZE64: + default: + gold_error(_("%s: unsupported reloc %u against global symbol %s"), + object->name().c_str(), r_type, + gsym->demangled_name().c_str()); + break; + } +} + +// Scan relocations for a section. + +void +Target_x86_64::scan_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + if (sh_type == elfcpp::SHT_REL) + { + gold_error(_("%s: unsupported REL reloc section"), + object->name().c_str()); + return; + } + + gold::scan_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA, + Target_x86_64::Scan>( + options, + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + +// Finalize the sections. + +void +Target_x86_64::do_finalize_sections(Layout* layout) +{ + // Fill in some more dynamic tags. + Output_data_dynamic* const odyn = layout->dynamic_data(); + if (odyn != NULL) + { + if (this->got_plt_ != NULL) + odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); + + if (this->plt_ != NULL) + { + const Output_data* od = this->plt_->rel_plt(); + odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); + odyn->add_section_address(elfcpp::DT_JMPREL, od); + odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); + if (this->plt_->has_tlsdesc_entry()) + { + unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); + unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); + this->got_->finalize_data_size(); + odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, + this->plt_, plt_offset); + odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, + this->got_, got_offset); + } + } + + if (this->rela_dyn_ != NULL) + { + const Output_data* od = this->rela_dyn_; + odyn->add_section_address(elfcpp::DT_RELA, od); + odyn->add_section_size(elfcpp::DT_RELASZ, od); + odyn->add_constant(elfcpp::DT_RELAENT, + elfcpp::Elf_sizes<64>::rela_size); + } + + if (!parameters->options().shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } + } + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. + if (this->copy_relocs_.any_saved_relocs()) + this->copy_relocs_.emit(this->rela_dyn_section(layout)); +} + +// Perform a relocation. + +inline bool +Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo, + Target_x86_64* target, + size_t relnum, + const elfcpp::Rela<64, false>& rela, + unsigned int r_type, + const Sized_symbol<64>* gsym, + const Symbol_value<64>* psymval, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr address, + section_size_type view_size) +{ + if (this->skip_call_tls_get_addr_) + { + if (r_type != elfcpp::R_X86_64_PLT32 + || gsym == NULL + || strcmp(gsym->name(), "__tls_get_addr") != 0) + { + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("missing expected TLS relocation")); + } + else + { + this->skip_call_tls_get_addr_ = false; + return false; + } + } + + // Pick the value to use for symbols defined in shared objects. + Symbol_value<64> symval; + if (gsym != NULL + && gsym->use_plt_offset(r_type == elfcpp::R_X86_64_PC64 + || r_type == elfcpp::R_X86_64_PC32 + || r_type == elfcpp::R_X86_64_PC16 + || r_type == elfcpp::R_X86_64_PC8)) + { + symval.set_output_value(target->plt_section()->address() + + gsym->plt_offset()); + psymval = &symval; + } + + const Sized_relobj<64, false>* object = relinfo->object; + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + + // Get the GOT offset if needed. + // The GOT pointer points to the end of the GOT section. + // We need to subtract the size of the GOT section to get + // the actual offset to use in the relocation. + bool have_got_offset = false; + unsigned int got_offset = 0; + switch (r_type) + { + case elfcpp::R_X86_64_GOT32: + case elfcpp::R_X86_64_GOT64: + case elfcpp::R_X86_64_GOTPLT64: + case elfcpp::R_X86_64_GOTPCREL: + case elfcpp::R_X86_64_GOTPCREL64: + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size(); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); + got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD) + - target->got_size()); + } + have_got_offset = true; + break; + + default: + break; + } + + switch (r_type) + { + case elfcpp::R_X86_64_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + break; + + case elfcpp::R_X86_64_64: + Relocate_functions<64, false>::rela64(view, object, psymval, addend); + break; + + case elfcpp::R_X86_64_PC64: + Relocate_functions<64, false>::pcrela64(view, object, psymval, addend, + address); + break; + + case elfcpp::R_X86_64_32: + // FIXME: we need to verify that value + addend fits into 32 bits: + // uint64_t x = value + addend; + // x == static_cast<uint64_t>(static_cast<uint32_t>(x)) + // Likewise for other <=32-bit relocations (but see R_X86_64_32S). + Relocate_functions<64, false>::rela32(view, object, psymval, addend); + break; + + case elfcpp::R_X86_64_32S: + // FIXME: we need to verify that value + addend fits into 32 bits: + // int64_t x = value + addend; // note this quantity is signed! + // x == static_cast<int64_t>(static_cast<int32_t>(x)) + Relocate_functions<64, false>::rela32(view, object, psymval, addend); + break; + + case elfcpp::R_X86_64_PC32: + Relocate_functions<64, false>::pcrela32(view, object, psymval, addend, + address); + break; + + case elfcpp::R_X86_64_16: + Relocate_functions<64, false>::rela16(view, object, psymval, addend); + break; + + case elfcpp::R_X86_64_PC16: + Relocate_functions<64, false>::pcrela16(view, object, psymval, addend, + address); + break; + + case elfcpp::R_X86_64_8: + Relocate_functions<64, false>::rela8(view, object, psymval, addend); + break; + + case elfcpp::R_X86_64_PC8: + Relocate_functions<64, false>::pcrela8(view, object, psymval, addend, + address); + break; + + case elfcpp::R_X86_64_PLT32: + gold_assert(gsym == NULL + || gsym->has_plt_offset() + || gsym->final_value_is_known() + || (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible())); + // Note: while this code looks the same as for R_X86_64_PC32, it + // behaves differently because psymval was set to point to + // the PLT entry, rather than the symbol, in Scan::global(). + Relocate_functions<64, false>::pcrela32(view, object, psymval, addend, + address); + break; + + case elfcpp::R_X86_64_PLTOFF64: + { + gold_assert(gsym); + gold_assert(gsym->has_plt_offset() + || gsym->final_value_is_known()); + elfcpp::Elf_types<64>::Elf_Addr got_address; + got_address = target->got_section(NULL, NULL)->address(); + Relocate_functions<64, false>::rela64(view, object, psymval, + addend - got_address); + } + + case elfcpp::R_X86_64_GOT32: + gold_assert(have_got_offset); + Relocate_functions<64, false>::rela32(view, got_offset, addend); + break; + + case elfcpp::R_X86_64_GOTPC32: + { + gold_assert(gsym); + elfcpp::Elf_types<64>::Elf_Addr value; + value = target->got_plt_section()->address(); + Relocate_functions<64, false>::pcrela32(view, value, addend, address); + } + break; + + case elfcpp::R_X86_64_GOT64: + // The ABI doc says "Like GOT64, but indicates a PLT entry is needed." + // Since we always add a PLT entry, this is equivalent. + case elfcpp::R_X86_64_GOTPLT64: + gold_assert(have_got_offset); + Relocate_functions<64, false>::rela64(view, got_offset, addend); + break; + + case elfcpp::R_X86_64_GOTPC64: + { + gold_assert(gsym); + elfcpp::Elf_types<64>::Elf_Addr value; + value = target->got_plt_section()->address(); + Relocate_functions<64, false>::pcrela64(view, value, addend, address); + } + break; + + case elfcpp::R_X86_64_GOTOFF64: + { + elfcpp::Elf_types<64>::Elf_Addr value; + value = (psymval->value(object, 0) + - target->got_plt_section()->address()); + Relocate_functions<64, false>::rela64(view, value, addend); + } + break; + + case elfcpp::R_X86_64_GOTPCREL: + { + gold_assert(have_got_offset); + elfcpp::Elf_types<64>::Elf_Addr value; + value = target->got_plt_section()->address() + got_offset; + Relocate_functions<64, false>::pcrela32(view, value, addend, address); + } + break; + + case elfcpp::R_X86_64_GOTPCREL64: + { + gold_assert(have_got_offset); + elfcpp::Elf_types<64>::Elf_Addr value; + value = target->got_plt_section()->address() + got_offset; + Relocate_functions<64, false>::pcrela64(view, value, addend, address); + } + break; + + case elfcpp::R_X86_64_COPY: + case elfcpp::R_X86_64_GLOB_DAT: + case elfcpp::R_X86_64_JUMP_SLOT: + case elfcpp::R_X86_64_RELATIVE: + // These are outstanding tls relocs, which are unexpected when linking + case elfcpp::R_X86_64_TPOFF64: + case elfcpp::R_X86_64_DTPMOD64: + case elfcpp::R_X86_64_TLSDESC: + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unexpected reloc %u in object file"), + r_type); + break; + + // These are initial tls relocs, which are expected when linking + case elfcpp::R_X86_64_TLSGD: // Global-dynamic + case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_TLSDESC_CALL: + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_TPOFF32: // Local-exec + this->relocate_tls(relinfo, target, relnum, rela, r_type, gsym, psymval, + view, address, view_size); + break; + + case elfcpp::R_X86_64_SIZE32: + case elfcpp::R_X86_64_SIZE64: + default: + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), + r_type); + break; + } + + return true; +} + +// Perform a TLS relocation. + +inline void +Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, + Target_x86_64* target, + size_t relnum, + const elfcpp::Rela<64, false>& rela, + unsigned int r_type, + const Sized_symbol<64>* gsym, + const Symbol_value<64>* psymval, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr address, + section_size_type view_size) +{ + Output_segment* tls_segment = relinfo->layout->tls_segment(); + + const Sized_relobj<64, false>* object = relinfo->object; + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + + elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0); + + const bool is_final = (gsym == NULL + ? !parameters->options().output_is_position_independent() + : gsym->final_value_is_known()); + const tls::Tls_optimization optimized_type + = Target_x86_64::optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_X86_64_TLSGD: // Global-dynamic + this->saw_tls_block_reloc_ = true; + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + this->tls_gd_to_le(relinfo, relnum, tls_segment, + rela, r_type, value, view, + view_size); + break; + } + else + { + unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE + ? GOT_TYPE_TLS_OFFSET + : GOT_TYPE_TLS_PAIR); + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type) - target->got_size(); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = (object->local_got_offset(r_sym, got_type) + - target->got_size()); + } + if (optimized_type == tls::TLSOPT_TO_IE) + { + gold_assert(tls_segment != NULL); + value = target->got_plt_section()->address() + got_offset; + this->tls_gd_to_ie(relinfo, relnum, tls_segment, rela, r_type, + value, view, address, view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the pair of GOT + // entries. + value = target->got_plt_section()->address() + got_offset; + Relocate_functions<64, false>::pcrela32(view, value, addend, + address); + break; + } + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), r_type); + break; + + case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_TLSDESC_CALL: + this->saw_tls_block_reloc_ = true; + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + this->tls_desc_gd_to_le(relinfo, relnum, tls_segment, + rela, r_type, value, view, + view_size); + break; + } + else + { + unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE + ? GOT_TYPE_TLS_OFFSET + : GOT_TYPE_TLS_DESC); + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type) - target->got_size(); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = (object->local_got_offset(r_sym, got_type) + - target->got_size()); + } + if (optimized_type == tls::TLSOPT_TO_IE) + { + gold_assert(tls_segment != NULL); + value = target->got_plt_section()->address() + got_offset; + this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment, + rela, r_type, value, view, address, + view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) + { + // Relocate the field with the offset of the pair of GOT + // entries. + value = target->got_plt_section()->address() + got_offset; + Relocate_functions<64, false>::pcrela32(view, value, addend, + address); + } + break; + } + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), r_type); + break; + + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + this->saw_tls_block_reloc_ = true; + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + this->tls_ld_to_le(relinfo, relnum, tls_segment, rela, r_type, + value, view, view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the module index. + unsigned int got_offset; + got_offset = (target->got_mod_index_entry(NULL, NULL, NULL) + - target->got_size()); + value = target->got_plt_section()->address() + got_offset; + Relocate_functions<64, false>::pcrela32(view, value, addend, + address); + break; + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc %u"), r_type); + break; + + case elfcpp::R_X86_64_DTPOFF32: + gold_assert(tls_segment != NULL); + if (optimized_type == tls::TLSOPT_TO_LE) + { + // This relocation type is used in debugging information. + // In that case we need to not optimize the value. If we + // haven't seen a TLSLD reloc, then we assume we should not + // optimize this reloc. + if (this->saw_tls_block_reloc_) + value -= tls_segment->memsz(); + } + Relocate_functions<64, false>::rela32(view, value, 0); + break; + + case elfcpp::R_X86_64_DTPOFF64: + gold_assert(tls_segment != NULL); + if (optimized_type == tls::TLSOPT_TO_LE) + { + // See R_X86_64_DTPOFF32, just above, for why we test this. + if (this->saw_tls_block_reloc_) + value -= tls_segment->memsz(); + } + Relocate_functions<64, false>::rela64(view, value, 0); + break; + + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + if (optimized_type == tls::TLSOPT_TO_LE) + { + gold_assert(tls_segment != NULL); + Target_x86_64::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment, + rela, r_type, value, view, + view_size); + break; + } + else if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the tp-relative offset of the symbol. + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET)); + got_offset = (gsym->got_offset(GOT_TYPE_TLS_OFFSET) + - target->got_size()); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, + GOT_TYPE_TLS_OFFSET)); + got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET) + - target->got_size()); + } + value = target->got_plt_section()->address() + got_offset; + Relocate_functions<64, false>::pcrela32(view, value, addend, address); + break; + } + gold_error_at_location(relinfo, relnum, rela.get_r_offset(), + _("unsupported reloc type %u"), + r_type); + break; + + case elfcpp::R_X86_64_TPOFF32: // Local-exec + value -= tls_segment->memsz(); + Relocate_functions<64, false>::rela32(view, value, 0); + break; + } +} + +// Do a relocation in which we convert a TLS General-Dynamic to an +// Initial-Exec. + +inline void +Target_x86_64::Relocate::tls_gd_to_ie(const Relocate_info<64, false>* relinfo, + size_t relnum, + Output_segment*, + const elfcpp::Rela<64, false>& rela, + unsigned int, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr address, + section_size_type view_size) +{ + // .byte 0x66; leaq foo@tlsgd(%rip),%rdi; + // .word 0x6666; rex64; call __tls_get_addr + // ==> movq %fs:0,%rax; addq x@gottpoff(%rip),%rax + + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -4); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12); + + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + (memcmp(view - 4, "\x66\x48\x8d\x3d", 4) == 0)); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0)); + + memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0\0", 16); + + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + Relocate_functions<64, false>::pcrela32(view + 8, value, addend - 8, address); + + // The next reloc should be a PLT32 reloc against __tls_get_addr. + // We can skip it. + this->skip_call_tls_get_addr_ = true; +} + +// Do a relocation in which we convert a TLS General-Dynamic to a +// Local-Exec. + +inline void +Target_x86_64::Relocate::tls_gd_to_le(const Relocate_info<64, false>* relinfo, + size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>& rela, + unsigned int, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + // .byte 0x66; leaq foo@tlsgd(%rip),%rdi; + // .word 0x6666; rex64; call __tls_get_addr + // ==> movq %fs:0,%rax; leaq x@tpoff(%rax),%rax + + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -4); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12); + + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + (memcmp(view - 4, "\x66\x48\x8d\x3d", 4) == 0)); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0)); + + memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0\0", 16); + + value -= tls_segment->memsz(); + Relocate_functions<64, false>::rela32(view + 8, value, 0); + + // The next reloc should be a PLT32 reloc against __tls_get_addr. + // We can skip it. + this->skip_call_tls_get_addr_ = true; +} + +// Do a TLSDESC-style General-Dynamic to Initial-Exec transition. + +inline void +Target_x86_64::Relocate::tls_desc_gd_to_ie( + const Relocate_info<64, false>* relinfo, + size_t relnum, + Output_segment*, + const elfcpp::Rela<64, false>& rela, + unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr address, + section_size_type view_size) +{ + if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) + { + // leaq foo@tlsdesc(%rip), %rax + // ==> movq foo@gottpoff(%rip), %rax + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05); + view[-2] = 0x8b; + const elfcpp::Elf_Xword addend = rela.get_r_addend(); + Relocate_functions<64, false>::pcrela32(view, value, addend, address); + } + else + { + // call *foo@tlscall(%rax) + // ==> nop; nop + gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + view[0] == 0xff && view[1] == 0x10); + view[0] = 0x66; + view[1] = 0x90; + } +} + +// Do a TLSDESC-style General-Dynamic to Local-Exec transition. + +inline void +Target_x86_64::Relocate::tls_desc_gd_to_le( + const Relocate_info<64, false>* relinfo, + size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>& rela, + unsigned int r_type, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) + { + // leaq foo@tlsdesc(%rip), %rax + // ==> movq foo@tpoff, %rax + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05); + view[-2] = 0xc7; + view[-1] = 0xc0; + value -= tls_segment->memsz(); + Relocate_functions<64, false>::rela32(view, value, 0); + } + else + { + // call *foo@tlscall(%rax) + // ==> nop; nop + gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + view[0] == 0xff && view[1] == 0x10); + view[0] = 0x66; + view[1] = 0x90; + } +} + +inline void +Target_x86_64::Relocate::tls_ld_to_le(const Relocate_info<64, false>* relinfo, + size_t relnum, + Output_segment*, + const elfcpp::Rela<64, false>& rela, + unsigned int, + elfcpp::Elf_types<64>::Elf_Addr, + unsigned char* view, + section_size_type view_size) +{ + // leaq foo@tlsld(%rip),%rdi; call __tls_get_addr@plt; + // ... leq foo@dtpoff(%rax),%reg + // ==> .word 0x6666; .byte 0x66; movq %fs:0,%rax ... leaq x@tpoff(%rax),%rdx + + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 9); + + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x3d); + + tls::check_tls(relinfo, relnum, rela.get_r_offset(), view[4] == 0xe8); + + memcpy(view - 3, "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0\0", 12); + + // The next reloc should be a PLT32 reloc against __tls_get_addr. + // We can skip it. + this->skip_call_tls_get_addr_ = true; +} + +// Do a relocation in which we convert a TLS Initial-Exec to a +// Local-Exec. + +inline void +Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo, + size_t relnum, + Output_segment* tls_segment, + const elfcpp::Rela<64, false>& rela, + unsigned int, + elfcpp::Elf_types<64>::Elf_Addr value, + unsigned char* view, + section_size_type view_size) +{ + // We need to examine the opcodes to figure out which instruction we + // are looking at. + + // movq foo@gottpoff(%rip),%reg ==> movq $YY,%reg + // addq foo@gottpoff(%rip),%reg ==> addq $YY,%reg + + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); + + unsigned char op1 = view[-3]; + unsigned char op2 = view[-2]; + unsigned char op3 = view[-1]; + unsigned char reg = op3 >> 3; + + if (op2 == 0x8b) + { + // movq + if (op1 == 0x4c) + view[-3] = 0x49; + view[-2] = 0xc7; + view[-1] = 0xc0 | reg; + } + else if (reg == 4) + { + // Special handling for %rsp. + if (op1 == 0x4c) + view[-3] = 0x49; + view[-2] = 0x81; + view[-1] = 0xc0 | reg; + } + else + { + // addq + if (op1 == 0x4c) + view[-3] = 0x4d; + view[-2] = 0x8d; + view[-1] = 0x80 | reg | (reg << 3); + } + + value -= tls_segment->memsz(); + Relocate_functions<64, false>::rela32(view, value, 0); +} + +// Relocate section data. + +void +Target_x86_64::relocate_section(const Relocate_info<64, false>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr address, + section_size_type view_size) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_section<64, false, Target_x86_64, elfcpp::SHT_RELA, + Target_x86_64::Relocate>( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size); +} + +// Return the size of a relocation while scanning during a relocatable +// link. + +unsigned int +Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc( + unsigned int r_type, + Relobj* object) +{ + switch (r_type) + { + case elfcpp::R_X86_64_NONE: + case elfcpp::R_386_GNU_VTINHERIT: + case elfcpp::R_386_GNU_VTENTRY: + case elfcpp::R_X86_64_TLSGD: // Global-dynamic + case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_TLSDESC_CALL: + case elfcpp::R_X86_64_TLSLD: // Local-dynamic + case elfcpp::R_X86_64_DTPOFF32: + case elfcpp::R_X86_64_DTPOFF64: + case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_TPOFF32: // Local-exec + return 0; + + case elfcpp::R_X86_64_64: + case elfcpp::R_X86_64_PC64: + case elfcpp::R_X86_64_GOTOFF64: + case elfcpp::R_X86_64_GOTPC64: + case elfcpp::R_X86_64_PLTOFF64: + case elfcpp::R_X86_64_GOT64: + case elfcpp::R_X86_64_GOTPCREL64: + case elfcpp::R_X86_64_GOTPCREL: + case elfcpp::R_X86_64_GOTPLT64: + return 8; + + case elfcpp::R_X86_64_32: + case elfcpp::R_X86_64_32S: + case elfcpp::R_X86_64_PC32: + case elfcpp::R_X86_64_PLT32: + case elfcpp::R_X86_64_GOTPC32: + case elfcpp::R_X86_64_GOT32: + return 4; + + case elfcpp::R_X86_64_16: + case elfcpp::R_X86_64_PC16: + return 2; + + case elfcpp::R_X86_64_8: + case elfcpp::R_X86_64_PC8: + return 1; + + case elfcpp::R_X86_64_COPY: + case elfcpp::R_X86_64_GLOB_DAT: + case elfcpp::R_X86_64_JUMP_SLOT: + case elfcpp::R_X86_64_RELATIVE: + // These are outstanding tls relocs, which are unexpected when linking + case elfcpp::R_X86_64_TPOFF64: + case elfcpp::R_X86_64_DTPMOD64: + case elfcpp::R_X86_64_TLSDESC: + object->error(_("unexpected reloc %u in object file"), r_type); + return 0; + + case elfcpp::R_X86_64_SIZE32: + case elfcpp::R_X86_64_SIZE64: + default: + object->error(_("unsupported reloc %u against local symbol"), r_type); + return 0; + } +} + +// Scan the relocs during a relocatable link. + +void +Target_x86_64::scan_relocatable_relocs(const General_options& options, + Symbol_table* symtab, + Layout* layout, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA, + Relocatable_size_for_reloc> Scan_relocatable_relocs; + + gold::scan_relocatable_relocs<64, false, elfcpp::SHT_RELA, + Scan_relocatable_relocs>( + options, + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); +} + +// Relocate a section during a relocatable link. + +void +Target_x86_64::relocate_for_relocatable( + const Relocate_info<64, false>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs* rr, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size) +{ + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_for_relocatable<64, false, elfcpp::SHT_RELA>( + relinfo, + prelocs, + reloc_count, + output_section, + offset_in_output_section, + rr, + view, + view_address, + view_size, + reloc_view, + reloc_view_size); +} + +// Return the value to use for a dynamic which requires special +// treatment. This is how we support equality comparisons of function +// pointers across shared library boundaries, as described in the +// processor specific ABI supplement. + +uint64_t +Target_x86_64::do_dynsym_value(const Symbol* gsym) const +{ + gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset()); + return this->plt_section()->address() + gsym->plt_offset(); +} + +// Return a string used to fill a code section with nops to take up +// the specified length. + +std::string +Target_x86_64::do_code_fill(section_size_type length) const +{ + if (length >= 16) + { + // Build a jmpq instruction to skip over the bytes. + unsigned char jmp[5]; + jmp[0] = 0xe9; + elfcpp::Swap_unaligned<32, false>::writeval(jmp + 1, length - 5); + return (std::string(reinterpret_cast<char*>(&jmp[0]), 5) + + std::string(length - 5, '\0')); + } + + // Nop sequences of various lengths. + const char nop1[1] = { 0x90 }; // nop + const char nop2[2] = { 0x66, 0x90 }; // xchg %ax %ax + const char nop3[3] = { 0x8d, 0x76, 0x00 }; // leal 0(%esi),%esi + const char nop4[4] = { 0x8d, 0x74, 0x26, 0x00}; // leal 0(%esi,1),%esi + const char nop5[5] = { 0x90, 0x8d, 0x74, 0x26, // nop + 0x00 }; // leal 0(%esi,1),%esi + const char nop6[6] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + 0x00, 0x00 }; + const char nop7[7] = { 0x8d, 0xb4, 0x26, 0x00, // leal 0L(%esi,1),%esi + 0x00, 0x00, 0x00 }; + const char nop8[8] = { 0x90, 0x8d, 0xb4, 0x26, // nop + 0x00, 0x00, 0x00, 0x00 }; // leal 0L(%esi,1),%esi + const char nop9[9] = { 0x89, 0xf6, 0x8d, 0xbc, // movl %esi,%esi + 0x27, 0x00, 0x00, 0x00, // leal 0L(%edi,1),%edi + 0x00 }; + const char nop10[10] = { 0x8d, 0x76, 0x00, 0x8d, // leal 0(%esi),%esi + 0xbc, 0x27, 0x00, 0x00, // leal 0L(%edi,1),%edi + 0x00, 0x00 }; + const char nop11[11] = { 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi + 0x8d, 0xbc, 0x27, 0x00, // leal 0L(%edi,1),%edi + 0x00, 0x00, 0x00 }; + const char nop12[12] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + 0x00, 0x00, 0x8d, 0xbf, // leal 0L(%edi),%edi + 0x00, 0x00, 0x00, 0x00 }; + const char nop13[13] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + 0x00, 0x00, 0x8d, 0xbc, // leal 0L(%edi,1),%edi + 0x27, 0x00, 0x00, 0x00, + 0x00 }; + const char nop14[14] = { 0x8d, 0xb4, 0x26, 0x00, // leal 0L(%esi,1),%esi + 0x00, 0x00, 0x00, 0x8d, // leal 0L(%edi,1),%edi + 0xbc, 0x27, 0x00, 0x00, + 0x00, 0x00 }; + const char nop15[15] = { 0xeb, 0x0d, 0x90, 0x90, // jmp .+15 + 0x90, 0x90, 0x90, 0x90, // nop,nop,nop,... + 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90 }; + + const char* nops[16] = { + NULL, + nop1, nop2, nop3, nop4, nop5, nop6, nop7, + nop8, nop9, nop10, nop11, nop12, nop13, nop14, nop15 + }; + + return std::string(nops[length], length); +} + +// The selector for x86_64 object files. + +class Target_selector_x86_64 : public Target_selector +{ +public: + Target_selector_x86_64() + : Target_selector(elfcpp::EM_X86_64, 64, false, "elf64-x86-64") + { } + + Target* + do_instantiate_target() + { return new Target_x86_64(); } +}; + +Target_selector_x86_64 target_selector_x86_64; + +} // End anonymous namespace. |