This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gold] PATCH: Initial x32 support


On Tue, Jan 3, 2012 at 4:25 PM, Cary Coutant <ccoutant@google.com> wrote:
>>> 2012-01-03 ?Cary Coutant ?<ccoutant@google.com>
>>>
>>> ? ? ? * gold/incremental.cc (Sized_incremental_binary::do_process_got_plt):
>>> ? ? ? Use abstract base class for GOT.
>>> ? ? ? * gold/output.h (class Output_data_got_base): New abstract base class.
>>> ? ? ? (class Output_data_got): Derive from new base class, adjust ctors.
>>> ? ? ? (Output_data_got::reserve_slot): Make virtual; rename to
>>> ? ? ? do_reserve_slot; Adjust callers.
>>> ? ? ? * gold/target.h (Sized_target::init_got_plt_for_update): Return
>>> ? ? ? pointer to abstract base class.
>>> ? ? ? * gold/x86_64.cc (Target_x86_64::init_got_plt_for_update): Likewise.
>>>
>>> + ?// Reserve a slot in the GOT.
>>> + ?void
>>> + ?reserve_slot(unsigned int i)
>>> + ?{ this->do_reserve_slot(i); }
>>
>> Have the comment explain the meaning of the parameter 'i'.
>>
>> This is OK with that change.
>
> Done, and committed. Thanks.
>
> HJ, please let me know if this solved your problem.
>

It works great.  Here is the initial x32 support in gold.
I just added template<int size> to replace <64>. It can
generate a simple x32 binary.  OK to install?

I have more follow up patches to fix other issues.

Thanks.


-- 
H.J.
---
2012-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* x86_64.cc: Initial support for x32.
2012-01-04  H.J. Lu  <hongjiu.lu@intel.com>

	* x86_64.cc: Initial support for x32.

diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index eeb532b..1fa2423 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -49,10 +49,11 @@ using namespace gold;
 
 // A class to handle the PLT data.
 
+template<int size>
 class Output_data_plt_x86_64 : public Output_section_data
 {
  public:
-  typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section;
+  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
 
   Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got,
 			 Output_data_space* got_plt,
@@ -90,7 +91,7 @@ class Output_data_plt_x86_64 : public Output_section_data
   // Add an entry to the PLT for a local STT_GNU_IFUNC symbol.
   unsigned int
   add_local_ifunc_entry(Symbol_table* symtab, Layout*,
-			Sized_relobj_file<64, false>* relobj,
+			Sized_relobj_file<size, false>* relobj,
 			unsigned int local_sym_index);
 
   // Add the relocation for a PLT entry.
@@ -242,15 +243,16 @@ class Output_data_plt_x86_64 : public Output_section_data
 //   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>
+template<int size>
+class Target_x86_64 : public Sized_target<size, 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;
+  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
 
   Target_x86_64()
-    : Sized_target<64, false>(&x86_64_info),
+    : Sized_target<size, false>(&x86_64_info),
       got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
       got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL),
       rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY),
@@ -266,7 +268,7 @@ class Target_x86_64 : public Sized_target<64, false>
   void
   gc_process_relocs(Symbol_table* symtab,
 	            Layout* layout,
-	            Sized_relobj_file<64, false>* object,
+	            Sized_relobj_file<size, false>* object,
 	            unsigned int data_shndx,
 	            unsigned int sh_type,
 	            const unsigned char* prelocs,
@@ -280,7 +282,7 @@ class Target_x86_64 : public Sized_target<64, false>
   void
   scan_relocs(Symbol_table* symtab,
 	      Layout* layout,
-	      Sized_relobj_file<64, false>* object,
+	      Sized_relobj_file<size, false>* object,
 	      unsigned int data_shndx,
 	      unsigned int sh_type,
 	      const unsigned char* prelocs,
@@ -301,14 +303,14 @@ class Target_x86_64 : public Sized_target<64, false>
 
   // Relocate a section.
   void
-  relocate_section(const Relocate_info<64, false>*,
+  relocate_section(const Relocate_info<size, 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,
+		   typename elfcpp::Elf_types<size>::Elf_Addr view_address,
 		   section_size_type view_size,
 		   const Reloc_symbol_changes*);
 
@@ -316,7 +318,7 @@ class Target_x86_64 : public Sized_target<64, false>
   void
   scan_relocatable_relocs(Symbol_table* symtab,
 			  Layout* layout,
-			  Sized_relobj_file<64, false>* object,
+			  Sized_relobj_file<size, false>* object,
 			  unsigned int data_shndx,
 			  unsigned int sh_type,
 			  const unsigned char* prelocs,
@@ -329,7 +331,7 @@ class Target_x86_64 : public Sized_target<64, false>
 
   // Relocate a section during a relocatable link.
   void
-  relocate_for_relocatable(const Relocate_info<64, false>*,
+  relocate_for_relocatable(const Relocate_info<size, false>*,
 			   unsigned int sh_type,
 			   const unsigned char* prelocs,
 			   size_t reloc_count,
@@ -337,7 +339,7 @@ class Target_x86_64 : public Sized_target<64, false>
 			   off_t offset_in_output_section,
 			   const Relocatable_relocs*,
 			   unsigned char* view,
-			   elfcpp::Elf_types<64>::Elf_Addr view_address,
+			   typename elfcpp::Elf_types<size>::Elf_Addr view_address,
 			   section_size_type view_size,
 			   unsigned char* reloc_view,
 			   section_size_type reloc_view_size);
@@ -435,7 +437,7 @@ class Target_x86_64 : public Sized_target<64, false>
   // necessary dynamic relocations.
   void
   reserve_local_got_entry(unsigned int got_index,
-		          Sized_relobj<64, false>* obj,
+		          Sized_relobj<size, false>* obj,
 			  unsigned int r_sym,
 			  unsigned int got_type);
 
@@ -456,18 +458,18 @@ class Target_x86_64 : public Sized_target<64, false>
 
   // Apply an incremental relocation.
   void
-  apply_relocation(const Relocate_info<64, false>* relinfo,
-		   elfcpp::Elf_types<64>::Elf_Addr r_offset,
+  apply_relocation(const Relocate_info<size, false>* relinfo,
+		   typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
 		   unsigned int r_type,
-		   elfcpp::Elf_types<64>::Elf_Swxword r_addend,
+		   typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
 		   const Symbol* gsym,
 		   unsigned char* view,
-		   elfcpp::Elf_types<64>::Elf_Addr address,
+		   typename elfcpp::Elf_types<size>::Elf_Addr address,
 		   section_size_type view_size);
 
   // Add a new reloc argument, returning the index in the vector.
   size_t
-  add_tlsdesc_info(Sized_relobj_file<64, false>* object, unsigned int r_sym)
+  add_tlsdesc_info(Sized_relobj_file<size, false>* object, unsigned int r_sym)
   {
     this->tlsdesc_reloc_info_.push_back(Tlsdesc_info(object, r_sym));
     return this->tlsdesc_reloc_info_.size() - 1;
@@ -487,46 +489,46 @@ class Target_x86_64 : public Sized_target<64, false>
 
     inline void
     local(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
-	  Sized_relobj_file<64, false>* object,
+	  Sized_relobj_file<size, 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);
+	  const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
+	  const elfcpp::Sym<size, false>& lsym);
 
     inline void
     global(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
-	   Sized_relobj_file<64, false>* object,
+	   Sized_relobj_file<size, false>* object,
 	   unsigned int data_shndx,
 	   Output_section* output_section,
-	   const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
+	   const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
 	   Symbol* gsym);
 
     inline bool
     local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
 					Target_x86_64* target,
-			        	Sized_relobj_file<64, false>* object,
+			        	Sized_relobj_file<size, false>* object,
 		  			unsigned int data_shndx,
 		  			Output_section* output_section,
-		  			const elfcpp::Rela<64, false>& reloc,
+		  			const elfcpp::Rela<size, false>& reloc,
 					unsigned int r_type,
-				  	const elfcpp::Sym<64, false>& lsym);
+				  	const elfcpp::Sym<size, false>& lsym);
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
  					 Target_x86_64* target,
-         	   			 Sized_relobj_file<64, false>* object,
+         	   			 Sized_relobj_file<size, false>* object,
         	   			 unsigned int data_shndx,
 		   			 Output_section* output_section,
-		   			 const elfcpp::Rela<64, false>& reloc,
+		   			 const elfcpp::Rela<size, false>& reloc,
 					 unsigned int r_type,
 		  			 Symbol* gsym);
 
   private:
     static void
-    unsupported_reloc_local(Sized_relobj_file<64, false>*, unsigned int r_type);
+    unsupported_reloc_local(Sized_relobj_file<size, false>*, unsigned int r_type);
 
     static void
-    unsupported_reloc_global(Sized_relobj_file<64, false>*, unsigned int r_type,
+    unsupported_reloc_global(Sized_relobj_file<size, false>*, unsigned int r_type,
 			     Symbol*);
 
     void
@@ -536,7 +538,7 @@ class Target_x86_64 : public Sized_target<64, false>
     possible_function_pointer_reloc(unsigned int r_type);
 
     bool
-    reloc_needs_plt_for_ifunc(Sized_relobj_file<64, false>*,
+    reloc_needs_plt_for_ifunc(Sized_relobj_file<size, false>*,
 			      unsigned int r_type);
 
     // Whether we have issued an error about a non-PIC compilation.
@@ -563,76 +565,76 @@ class Target_x86_64 : public Sized_target<64, false>
     // 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*, Output_section*,
-	     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,
+    relocate(const Relocate_info<size, false>*, Target_x86_64*, Output_section*,
+	     size_t relnum, const elfcpp::Rela<size, false>&,
+	     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<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,
+    relocate_tls(const Relocate_info<size, false>*, Target_x86_64*,
+                 size_t relnum, const elfcpp::Rela<size, false>&,
+		 unsigned int r_type, const Sized_symbol<size>*,
+		 const Symbol_value<size>*,
+		 unsigned char*, typename elfcpp::Elf_types<size>::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,
+    tls_gd_to_ie(const Relocate_info<size, false>*, size_t relnum,
 		 Output_segment* tls_segment,
-		 const elfcpp::Rela<64, false>&, unsigned int r_type,
-		 elfcpp::Elf_types<64>::Elf_Addr value,
+		 const elfcpp::Rela<size, false>&, unsigned int r_type,
+		 typename elfcpp::Elf_types<size>::Elf_Addr value,
 		 unsigned char* view,
-		 elfcpp::Elf_types<64>::Elf_Addr,
+		 typename elfcpp::Elf_types<size>::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,
+    tls_gd_to_le(const Relocate_info<size, false>*, size_t relnum,
 		 Output_segment* tls_segment,
-		 const elfcpp::Rela<64, false>&, unsigned int r_type,
-		 elfcpp::Elf_types<64>::Elf_Addr value,
+		 const elfcpp::Rela<size, false>&, unsigned int r_type,
+		 typename elfcpp::Elf_types<size>::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,
+    tls_desc_gd_to_ie(const Relocate_info<size, false>*, size_t relnum,
 		      Output_segment* tls_segment,
-		      const elfcpp::Rela<64, false>&, unsigned int r_type,
-		      elfcpp::Elf_types<64>::Elf_Addr value,
+		      const elfcpp::Rela<size, false>&, unsigned int r_type,
+		      typename elfcpp::Elf_types<size>::Elf_Addr value,
 		      unsigned char* view,
-		      elfcpp::Elf_types<64>::Elf_Addr,
+		      typename elfcpp::Elf_types<size>::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,
+    tls_desc_gd_to_le(const Relocate_info<size, false>*, size_t relnum,
 		      Output_segment* tls_segment,
-		      const elfcpp::Rela<64, false>&, unsigned int r_type,
-		      elfcpp::Elf_types<64>::Elf_Addr value,
+		      const elfcpp::Rela<size, false>&, unsigned int r_type,
+		      typename elfcpp::Elf_types<size>::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,
+    tls_ld_to_le(const Relocate_info<size, false>*, size_t relnum,
 		 Output_segment* tls_segment,
-		 const elfcpp::Rela<64, false>&, unsigned int r_type,
-		 elfcpp::Elf_types<64>::Elf_Addr value,
+		 const elfcpp::Rela<size, false>&, unsigned int r_type,
+		 typename elfcpp::Elf_types<size>::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,
+    tls_ie_to_le(const Relocate_info<size, false>*, size_t relnum,
 		 Output_segment* tls_segment,
-		 const elfcpp::Rela<64, false>&, unsigned int r_type,
-		 elfcpp::Elf_types<64>::Elf_Addr value,
+		 const elfcpp::Rela<size, false>&, unsigned int r_type,
+		 typename elfcpp::Elf_types<size>::Elf_Addr value,
 		 unsigned char* view,
 		 section_size_type view_size);
 
@@ -686,7 +688,7 @@ class Target_x86_64 : public Sized_target<64, false>
   // Create a PLT entry for a local STT_GNU_IFUNC symbol.
   void
   make_local_ifunc_plt_entry(Symbol_table*, Layout*,
-			     Sized_relobj_file<64, false>* relobj,
+			     Sized_relobj_file<size, false>* relobj,
 			     unsigned int local_sym_index);
 
   // Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
@@ -700,10 +702,10 @@ class Target_x86_64 : public Sized_target<64, false>
   // Create a GOT entry for the TLS module index.
   unsigned int
   got_mod_index_entry(Symbol_table* symtab, Layout* layout,
-		      Sized_relobj_file<64, false>* object);
+		      Sized_relobj_file<size, false>* object);
 
   // Get the PLT section.
-  Output_data_plt_x86_64*
+  Output_data_plt_x86_64<size>*
   plt_section() const
   {
     gold_assert(this->plt_ != NULL);
@@ -725,12 +727,12 @@ class Target_x86_64 : public Sized_target<64, false>
   // Add a potential copy relocation.
   void
   copy_reloc(Symbol_table* symtab, Layout* layout,
-             Sized_relobj_file<64, false>* object,
+             Sized_relobj_file<size, false>* object,
 	     unsigned int shndx, Output_section* output_section,
-	     Symbol* sym, const elfcpp::Rela<64, false>& reloc)
+	     Symbol* sym, const elfcpp::Rela<size, false>& reloc)
   {
     this->copy_relocs_.copy_reloc(symtab, layout,
-				  symtab->get_sized_symbol<64>(sym),
+				  symtab->get_sized_symbol<size>(sym),
 				  object, shndx, output_section,
 				  reloc, this->rela_dyn_section(layout));
   }
@@ -756,12 +758,12 @@ class Target_x86_64 : public Sized_target<64, false>
   // R_X86_64_TLSDESC against a local symbol.
   struct Tlsdesc_info
   {
-    Tlsdesc_info(Sized_relobj_file<64, false>* a_object, unsigned int a_r_sym)
+    Tlsdesc_info(Sized_relobj_file<size, false>* a_object, unsigned int a_r_sym)
       : object(a_object), r_sym(a_r_sym)
     { }
 
     // The object in which the local symbol is defined.
-    Sized_relobj_file<64, false>* object;
+    Sized_relobj_file<size, false>* object;
     // The local symbol index in the object.
     unsigned int r_sym;
   };
@@ -769,7 +771,7 @@ class Target_x86_64 : public Sized_target<64, false>
   // The GOT section.
   Output_data_got<64, false>* got_;
   // The PLT section.
-  Output_data_plt_x86_64* plt_;
+  Output_data_plt_x86_64<size>* plt_;
   // The GOT PLT section.
   Output_data_space* got_plt_;
   // The GOT section for IRELATIVE relocations.
@@ -783,7 +785,7 @@ class Target_x86_64 : public Sized_target<64, false>
   // The section to use for IRELATIVE relocs.
   Reloc_section* rela_irelative_;
   // Relocs saved to avoid a COPY reloc.
-  Copy_relocs<elfcpp::SHT_RELA, 64, false> copy_relocs_;
+  Copy_relocs<elfcpp::SHT_RELA, size, 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.
@@ -796,7 +798,8 @@ class Target_x86_64 : public Sized_target<64, false>
   bool tls_base_symbol_defined_;
 };
 
-const Target::Target_info Target_x86_64::x86_64_info =
+template<>
+const Target::Target_info Target_x86_64<64>::x86_64_info =
 {
   64,			// size
   false,		// is_big_endian
@@ -819,11 +822,36 @@ const Target::Target_info Target_x86_64::x86_64_info =
   NULL			// attributes_vendor
 };
 
+template<>
+const Target::Target_info Target_x86_64<32>::x86_64_info =
+{
+  32,			// 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
+  true,			// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/libx32/ldx32.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)
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_X86_64_LCOMMON,	// large_common_shndx
+  0,			// small_common_section_flags
+  elfcpp::SHF_X86_64_LARGE,	// large_common_section_flags
+  NULL,			// attributes_section
+  NULL			// attributes_vendor
+};
+
 // This is called when a new output section is created.  This is where
 // we handle the SHF_X86_64_LARGE.
 
+template<int size>
 void
-Target_x86_64::do_new_output_section(Output_section* os) const
+Target_x86_64<size>::do_new_output_section(Output_section* os) const
 {
   if ((os->flags() & elfcpp::SHF_X86_64_LARGE) != 0)
     os->set_is_large_section();
@@ -831,8 +859,9 @@ Target_x86_64::do_new_output_section(Output_section* os) const
 
 // Get the GOT section, creating it if necessary.
 
+template<int size>
 Output_data_got<64, false>*
-Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::got_section(Symbol_table* symtab, Layout* layout)
 {
   if (this->got_ == NULL)
     {
@@ -906,8 +935,9 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 
 // Get the dynamic reloc section, creating it if necessary.
 
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_dyn_section(Layout* layout)
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_dyn_section(Layout* layout)
 {
   if (this->rela_dyn_ == NULL)
     {
@@ -926,8 +956,9 @@ Target_x86_64::rela_dyn_section(Layout* layout)
 // that they can refer to global variables initialized by those
 // relocs.
 
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_irelative_section(Layout* layout)
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_irelative_section(Layout* layout)
 {
   if (this->rela_irelative_ == NULL)
     {
@@ -945,8 +976,9 @@ Target_x86_64::rela_irelative_section(Layout* layout)
 
 // Initialize the PLT section.
 
+template<int size>
 void
-Output_data_plt_x86_64::init(Layout* layout)
+Output_data_plt_x86_64<size>::init(Layout* layout)
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
@@ -959,17 +991,19 @@ Output_data_plt_x86_64::init(Layout* layout)
 				 plt_eh_frame_fde, plt_eh_frame_fde_size);
 }
 
+template<int size>
 void
-Output_data_plt_x86_64::do_adjust_output_section(Output_section* os)
+Output_data_plt_x86_64<size>::do_adjust_output_section(Output_section* os)
 {
   os->set_entsize(plt_entry_size);
 }
 
 // Add an entry to the PLT.
 
+template<int size>
 void
-Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
-				  Symbol* gsym)
+Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout,
+					Symbol* gsym)
 {
   gold_assert(!gsym->has_plt_offset());
 
@@ -1044,11 +1078,12 @@ Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
 // Add an entry to the PLT for a local STT_GNU_IFUNC symbol.  Return
 // the PLT offset.
 
+template<int size>
 unsigned int
-Output_data_plt_x86_64::add_local_ifunc_entry(
+Output_data_plt_x86_64<size>::add_local_ifunc_entry(
     Symbol_table* symtab,
     Layout* layout,
-    Sized_relobj_file<64, false>* relobj,
+    Sized_relobj_file<size, false>* relobj,
     unsigned int local_sym_index)
 {
   unsigned int plt_offset = this->irelative_count_ * plt_entry_size;
@@ -1071,9 +1106,10 @@ Output_data_plt_x86_64::add_local_ifunc_entry(
 
 // Add the relocation for a PLT entry.
 
+template<int size>
 void
-Output_data_plt_x86_64::add_relocation(Symbol_table* symtab, Layout* layout,
-				       Symbol* gsym, unsigned int got_offset)
+Output_data_plt_x86_64<size>::add_relocation(Symbol_table* symtab, Layout* layout,
+					     Symbol* gsym, unsigned int got_offset)
 {
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
       && gsym->can_use_relative_reloc(false))
@@ -1093,8 +1129,9 @@ Output_data_plt_x86_64::add_relocation(Symbol_table* symtab, Layout* layout,
 // Return where the TLSDESC relocations should go, creating it if
 // necessary.  These follow the JUMP_SLOT relocations.
 
-Output_data_plt_x86_64::Reloc_section*
-Output_data_plt_x86_64::rela_tlsdesc(Layout* layout)
+template<int size>
+typename Output_data_plt_x86_64<size>::Reloc_section*
+Output_data_plt_x86_64<size>::rela_tlsdesc(Layout* layout)
 {
   if (this->tlsdesc_rel_ == NULL)
     {
@@ -1111,8 +1148,10 @@ Output_data_plt_x86_64::rela_tlsdesc(Layout* layout)
 // Return where the IRELATIVE relocations should go in the PLT.  These
 // follow the JUMP_SLOT and the TLSDESC relocations.
 
-Output_data_plt_x86_64::Reloc_section*
-Output_data_plt_x86_64::rela_irelative(Symbol_table* symtab, Layout* layout)
+template<int size>
+typename Output_data_plt_x86_64<size>::Reloc_section*
+Output_data_plt_x86_64<size>::rela_irelative(Symbol_table* symtab,
+					     Layout* layout)
 {
   if (this->irelative_rel_ == NULL)
     {
@@ -1150,8 +1189,9 @@ Output_data_plt_x86_64::rela_irelative(Symbol_table* symtab, Layout* layout)
 
 // Return the PLT address to use for a global symbol.
 
+template<int size>
 uint64_t
-Output_data_plt_x86_64::address_for_global(const Symbol* gsym)
+Output_data_plt_x86_64<size>::address_for_global(const Symbol* gsym)
 {
   uint64_t offset = 0;
   if (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -1163,15 +1203,17 @@ Output_data_plt_x86_64::address_for_global(const Symbol* gsym)
 // Return the PLT address to use for a local symbol.  These are always
 // IRELATIVE relocs.
 
+template<int size>
 uint64_t
-Output_data_plt_x86_64::address_for_local(const Relobj*, unsigned int)
+Output_data_plt_x86_64<size>::address_for_local(const Relobj*, unsigned int)
 {
   return this->address() + (this->count_ + 1) * plt_entry_size;
 }
 
 // Set the final size.
+template<int size>
 void
-Output_data_plt_x86_64::set_final_data_size()
+Output_data_plt_x86_64<size>::set_final_data_size()
 {
   unsigned int count = this->count_ + this->irelative_count_;
   if (this->has_tlsdesc_entry())
@@ -1181,7 +1223,8 @@ Output_data_plt_x86_64::set_final_data_size()
 
 // The first entry in the PLT for an executable.
 
-const unsigned char Output_data_plt_x86_64::first_plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char Output_data_plt_x86_64<size>::first_plt_entry[plt_entry_size] =
 {
   // From AMD64 ABI Draft 0.98, page 76
   0xff, 0x35,	// pushq contents of memory address
@@ -1193,7 +1236,8 @@ const unsigned char Output_data_plt_x86_64::first_plt_entry[plt_entry_size] =
 
 // Subsequent entries in the PLT for an executable.
 
-const unsigned char Output_data_plt_x86_64::plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char Output_data_plt_x86_64<size>::plt_entry[plt_entry_size] =
 {
   // From AMD64 ABI Draft 0.98, page 76
   0xff, 0x25,	// jmpq indirect
@@ -1206,7 +1250,8 @@ const unsigned char Output_data_plt_x86_64::plt_entry[plt_entry_size] =
 
 // The reserved TLSDESC entry in the PLT for an executable.
 
-const unsigned char Output_data_plt_x86_64::tlsdesc_plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char Output_data_plt_x86_64<size>::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).
@@ -1220,8 +1265,9 @@ const unsigned char Output_data_plt_x86_64::tlsdesc_plt_entry[plt_entry_size] =
 
 // The .eh_frame unwind information for the PLT.
 
+template<int size>
 const unsigned char 
-Output_data_plt_x86_64::plt_eh_frame_cie[plt_eh_frame_cie_size] =
+Output_data_plt_x86_64<size>::plt_eh_frame_cie[plt_eh_frame_cie_size] =
 {
   1,				// CIE version.
   'z',				// Augmentation: augmentation size included.
@@ -1239,8 +1285,9 @@ Output_data_plt_x86_64::plt_eh_frame_cie[plt_eh_frame_cie_size] =
   elfcpp::DW_CFA_nop
 };
 
+template<int size>
 const unsigned char
-Output_data_plt_x86_64::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+Output_data_plt_x86_64<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
 {
   0, 0, 0, 0,				// Replaced with offset to .plt.
   0, 0, 0, 0,				// Replaced with size of .plt.
@@ -1269,8 +1316,9 @@ Output_data_plt_x86_64::plt_eh_frame_fde[plt_eh_frame_fde_size] =
 // Write out the PLT.  This uses the hand-coded instructions above,
 // and adjusts them as needed.  This is specified by the AMD64 ABI.
 
+template<int size>
 void
-Output_data_plt_x86_64::do_write(Output_file* of)
+Output_data_plt_x86_64<size>::do_write(Output_file* of)
 {
   const off_t offset = this->offset();
   const section_size_type oview_size =
@@ -1290,13 +1338,13 @@ Output_data_plt_x86_64::do_write(Output_file* of)
   unsigned char* pov = oview;
 
   // The base address of the .plt section.
-  elfcpp::Elf_types<64>::Elf_Addr plt_address = this->address();
+  typename elfcpp::Elf_types<size>::Elf_Addr plt_address = this->address();
   // The base address of the .got section.
-  elfcpp::Elf_types<64>::Elf_Addr got_base = this->got_->address();
+  typename elfcpp::Elf_types<size>::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();
+  typename elfcpp::Elf_types<size>::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.
@@ -1373,17 +1421,18 @@ Output_data_plt_x86_64::do_write(Output_file* of)
 
 // Create the PLT section.
 
+template<int size>
 void
-Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::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_,
-					      this->got_irelative_);
+      this->plt_ = new Output_data_plt_x86_64<size>(layout, this->got_,
+						    this->got_plt_,
+						    this->got_irelative_);
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
@@ -1397,17 +1446,19 @@ Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout)
 
 // Return the section for TLSDESC relocations.
 
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_tlsdesc_section(Layout* layout) const
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_tlsdesc_section(Layout* layout) const
 {
   return this->plt_section()->rela_tlsdesc(layout);
 }
 
 // Create a PLT entry for a global symbol.
 
+template<int size>
 void
-Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout,
-                              Symbol* gsym)
+Target_x86_64<size>::make_plt_entry(Symbol_table* symtab, Layout* layout,
+				    Symbol* gsym)
 {
   if (gsym->has_plt_offset())
     return;
@@ -1420,10 +1471,11 @@ Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout,
 
 // Make a PLT entry for a local STT_GNU_IFUNC symbol.
 
+template<int size>
 void
-Target_x86_64::make_local_ifunc_plt_entry(Symbol_table* symtab, Layout* layout,
-					  Sized_relobj_file<64, false>* relobj,
-					  unsigned int local_sym_index)
+Target_x86_64<size>::make_local_ifunc_plt_entry(Symbol_table* symtab, Layout* layout,
+						Sized_relobj_file<size, false>* relobj,
+						unsigned int local_sym_index)
 {
   if (relobj->local_has_plt_offset(local_sym_index))
     return;
@@ -1437,8 +1489,9 @@ Target_x86_64::make_local_ifunc_plt_entry(Symbol_table* symtab, Layout* layout,
 
 // Return the number of entries in the PLT.
 
+template<int size>
 unsigned int
-Target_x86_64::plt_entry_count() const
+Target_x86_64<size>::plt_entry_count() const
 {
   if (this->plt_ == NULL)
     return 0;
@@ -1447,24 +1500,27 @@ Target_x86_64::plt_entry_count() const
 
 // Return the offset of the first non-reserved PLT entry.
 
+template<int size>
 unsigned int
-Target_x86_64::first_plt_entry_offset() const
+Target_x86_64<size>::first_plt_entry_offset() const
 {
-  return Output_data_plt_x86_64::first_plt_entry_offset();
+  return Output_data_plt_x86_64<size>::first_plt_entry_offset();
 }
 
 // Return the size of each PLT entry.
 
+template<int size>
 unsigned int
-Target_x86_64::plt_entry_size() const
+Target_x86_64<size>::plt_entry_size() const
 {
-  return Output_data_plt_x86_64::get_plt_entry_size();
+  return Output_data_plt_x86_64<size>::get_plt_entry_size();
 }
 
 // Create the GOT and PLT sections for an incremental update.
 
+template<int size>
 Output_data_got_base*
-Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
+Target_x86_64<size>::init_got_plt_for_update(Symbol_table* symtab,
 				       Layout* layout,
 				       unsigned int got_count,
 				       unsigned int plt_count)
@@ -1514,8 +1570,10 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
 				  ORDER_NON_RELRO_FIRST, false);
 
   // Create the PLT section.
-  this->plt_ = new Output_data_plt_x86_64(layout, this->got_, this->got_plt_,
-					  this->got_irelative_, plt_count);
+  this->plt_ = new Output_data_plt_x86_64<size>(layout, this->got_,
+						this->got_plt_,
+						this->got_irelative_,
+						plt_count);
   layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				  elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR,
 				  this->plt_, ORDER_PLT, false);
@@ -1533,10 +1591,11 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
 // Reserve a GOT entry for a local symbol, and regenerate any
 // necessary dynamic relocations.
 
+template<int size>
 void
-Target_x86_64::reserve_local_got_entry(
+Target_x86_64<size>::reserve_local_got_entry(
     unsigned int got_index,
-    Sized_relobj<64, false>* obj,
+    Sized_relobj<size, false>* obj,
     unsigned int r_sym,
     unsigned int got_type)
 {
@@ -1574,9 +1633,11 @@ Target_x86_64::reserve_local_got_entry(
 // Reserve a GOT entry for a global symbol, and regenerate any
 // necessary dynamic relocations.
 
+template<int size>
 void
-Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
-					unsigned int got_type)
+Target_x86_64<size>::reserve_global_got_entry(unsigned int got_index,
+					      Symbol* gsym,
+					      unsigned int got_type)
 {
   unsigned int got_offset = got_index * 8;
   Reloc_section* rela_dyn = this->rela_dyn_section(NULL);
@@ -1621,11 +1682,12 @@ Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
 
 // Register an existing PLT entry for a global symbol.
 
+template<int size>
 void
-Target_x86_64::register_global_plt_entry(Symbol_table* symtab,
-					 Layout* layout,
-					 unsigned int plt_index,
-					 Symbol* gsym)
+Target_x86_64<size>::register_global_plt_entry(Symbol_table* symtab,
+					       Layout* layout,
+					       unsigned int plt_index,
+					       Symbol* gsym)
 {
   gold_assert(this->plt_ != NULL);
   gold_assert(!gsym->has_plt_offset());
@@ -1640,12 +1702,13 @@ Target_x86_64::register_global_plt_entry(Symbol_table* symtab,
 
 // Force a COPY relocation for a given symbol.
 
+template<int size>
 void
-Target_x86_64::emit_copy_reloc(
+Target_x86_64<size>::emit_copy_reloc(
     Symbol_table* symtab, Symbol* sym, Output_section* os, off_t offset)
 {
   this->copy_relocs_.emit_copy_reloc(symtab,
-				     symtab->get_sized_symbol<64>(sym),
+				     symtab->get_sized_symbol<size>(sym),
 				     os,
 				     offset,
 				     this->rela_dyn_section(NULL));
@@ -1653,8 +1716,10 @@ Target_x86_64::emit_copy_reloc(
 
 // Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
 
+template<int size>
 void
-Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::define_tls_base_symbol(Symbol_table* symtab,
+					    Layout* layout)
 {
   if (this->tls_base_symbol_defined_)
     return;
@@ -1679,8 +1744,9 @@ Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
 
 // Create the reserved PLT and GOT entries for the TLS descriptor resolver.
 
+template<int size>
 void
-Target_x86_64::reserve_tlsdesc_entries(Symbol_table* symtab,
+Target_x86_64<size>::reserve_tlsdesc_entries(Symbol_table* symtab,
                                              Layout* layout)
 {
   if (this->plt_ == NULL)
@@ -1699,9 +1765,10 @@ Target_x86_64::reserve_tlsdesc_entries(Symbol_table* symtab,
 
 // Create a GOT entry for the TLS module index.
 
+template<int size>
 unsigned int
-Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
-			           Sized_relobj_file<64, false>* object)
+Target_x86_64<size>::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
+					 Sized_relobj_file<size, false>* object)
 {
   if (this->got_mod_index_offset_ == -1U)
     {
@@ -1721,8 +1788,9 @@ Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
 // symbol.  IS_FINAL is true if the final address of this symbol is
 // known at link time.
 
+template<int size>
 tls::Tls_optimization
-Target_x86_64::optimize_tls_reloc(bool is_final, int r_type)
+Target_x86_64<size>::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.
@@ -1774,8 +1842,9 @@ Target_x86_64::optimize_tls_reloc(bool is_final, int r_type)
 
 // Get the Reference_flags for a particular relocation.
 
+template<int size>
 int
-Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
+Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
 {
   switch (r_type)
     {
@@ -1841,9 +1910,10 @@ Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
 
 // Report an unsupported relocation against a local symbol.
 
+template<int size>
 void
-Target_x86_64::Scan::unsupported_reloc_local(
-     Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::unsupported_reloc_local(
+     Sized_relobj_file<size, false>* object,
      unsigned int r_type)
 {
   gold_error(_("%s: unsupported reloc %u against local symbol"),
@@ -1860,9 +1930,10 @@ Target_x86_64::Scan::unsupported_reloc_local(
 // it is the symbol the relocation is against; if it is NULL, the
 // relocation is against a local symbol.
 
+template<int size>
 void
-Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
-				   Symbol* gsym)
+Target_x86_64<size>::Scan::check_non_pic(Relobj* object, unsigned int r_type,
+					 Symbol* gsym)
 {
   switch (r_type)
     {
@@ -1927,9 +1998,10 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
 // Return whether we need to make a PLT entry for a relocation of the
 // given type against a STT_GNU_IFUNC symbol.
 
+template<int size>
 bool
-Target_x86_64::Scan::reloc_needs_plt_for_ifunc(
-     Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::reloc_needs_plt_for_ifunc(
+     Sized_relobj_file<size, false>* object,
      unsigned int r_type)
 {
   int flags = Scan::get_reference_flags(r_type);
@@ -1941,22 +2013,23 @@ Target_x86_64::Scan::reloc_needs_plt_for_ifunc(
 
 // Scan a relocation for a local symbol.
 
+template<int size>
 inline void
-Target_x86_64::Scan::local(Symbol_table* symtab,
-                           Layout* layout,
-                           Target_x86_64* target,
-                           Sized_relobj_file<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)
+Target_x86_64<size>::Scan::local(Symbol_table* symtab,
+				 Layout* layout,
+				 Target_x86_64* target,
+				 Sized_relobj_file<size, false>* object,
+				 unsigned int data_shndx,
+				 Output_section* output_section,
+				 const elfcpp::Rela<size, false>& reloc,
+				 unsigned int r_type,
+				 const elfcpp::Sym<size, false>& lsym)
 {
   // A local STT_GNU_IFUNC symbol may require a PLT entry.
   bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
   if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type))
     {
-      unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+      unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
       target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
     }
 
@@ -1976,7 +2049,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
       // relocate it easily.
       if (parameters->options().output_is_position_independent())
         {
-          unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+          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,
 				       elfcpp::R_X86_64_RELATIVE,
@@ -1999,7 +2072,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
           this->check_non_pic(object, r_type, NULL);
 
           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
-	  unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+	  unsigned int r_sym = elfcpp::elf_r_sym<size>(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(),
@@ -2052,7 +2125,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
       {
         // 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());
+        unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 
 	// For a STT_GNU_IFUNC symbol we want the PLT offset.  That
 	// lets function pointers compare correctly with shared
@@ -2129,7 +2202,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
                 // 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 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);
@@ -2161,7 +2234,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
 	        // make sure the section has been created.
 		target->got_section(symtab, layout);
                 Output_data_got<64, false>* got = target->got_tlsdesc_section();
-                unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+                unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 		if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
 		  {
 		    unsigned int got_offset = got->add_constant(0);
@@ -2206,7 +2279,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
 	        // 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());
+	        unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 	        got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
 					target->rela_dyn_section(layout),
 					elfcpp::R_X86_64_TPOFF64);
@@ -2239,9 +2312,10 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
 
 // Report an unsupported relocation against a global symbol.
 
+template<int size>
 void
-Target_x86_64::Scan::unsupported_reloc_global(
-    Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::unsupported_reloc_global(
+    Sized_relobj_file<size, false>* object,
     unsigned int r_type,
     Symbol* gsym)
 {
@@ -2250,8 +2324,9 @@ Target_x86_64::Scan::unsupported_reloc_global(
 }
 
 // Returns true if this relocation type could be that of a function pointer.
+template<int size>
 inline bool
-Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
+Target_x86_64<size>::Scan::possible_function_pointer_reloc(unsigned int r_type)
 {
   switch (r_type)
     {
@@ -2276,17 +2351,18 @@ Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
 // corresponds to a function pointer being taken.  In that case mark
 // the function whose pointer was taken as not foldable.
 
+template<int size>
 inline bool
-Target_x86_64::Scan::local_reloc_may_be_function_pointer(
+Target_x86_64<size>::Scan::local_reloc_may_be_function_pointer(
   Symbol_table* ,
   Layout* ,
   Target_x86_64* ,
-  Sized_relobj_file<64, false>* ,
+  Sized_relobj_file<size, false>* ,
   unsigned int ,
   Output_section* ,
-  const elfcpp::Rela<64, false>& ,
+  const elfcpp::Rela<size, false>& ,
   unsigned int r_type,
-  const elfcpp::Sym<64, false>&)
+  const elfcpp::Sym<size, false>&)
 {
   // When building a shared library, do not fold any local symbols as it is
   // not possible to distinguish pointer taken versus a call by looking at
@@ -2299,15 +2375,16 @@ Target_x86_64::Scan::local_reloc_may_be_function_pointer(
 // corresponds to a function pointer being taken.  In that case mark
 // the function whose pointer was taken as not foldable.
 
+template<int size>
 inline bool
-Target_x86_64::Scan::global_reloc_may_be_function_pointer(
+Target_x86_64<size>::Scan::global_reloc_may_be_function_pointer(
   Symbol_table*,
   Layout* ,
   Target_x86_64* ,
-  Sized_relobj_file<64, false>* ,
+  Sized_relobj_file<size, false>* ,
   unsigned int ,
   Output_section* ,
-  const elfcpp::Rela<64, false>& ,
+  const elfcpp::Rela<size, false>& ,
   unsigned int r_type,
   Symbol* gsym)
 {
@@ -2322,14 +2399,15 @@ Target_x86_64::Scan::global_reloc_may_be_function_pointer(
 
 // Scan a relocation for a global symbol.
 
+template<int size>
 inline void
-Target_x86_64::Scan::global(Symbol_table* symtab,
+Target_x86_64<size>::Scan::global(Symbol_table* symtab,
                             Layout* layout,
                             Target_x86_64* target,
-                            Sized_relobj_file<64, false>* object,
+                            Sized_relobj_file<size, false>* object,
                             unsigned int data_shndx,
                             Output_section* output_section,
-                            const elfcpp::Rela<64, false>& reloc,
+                            const elfcpp::Rela<size, false>& reloc,
                             unsigned int r_type,
                             Symbol* gsym)
 {
@@ -2683,18 +2761,19 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
     }
 }
 
+template<int size>
 void
-Target_x86_64::gc_process_relocs(Symbol_table* symtab,
-                                 Layout* layout,
-                                 Sized_relobj_file<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)
+Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
+				       Layout* layout,
+				       Sized_relobj_file<size, 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)
@@ -2702,7 +2781,7 @@ Target_x86_64::gc_process_relocs(Symbol_table* symtab,
       return;
     }
 
-   gold::gc_process_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
+   gold::gc_process_relocs<size, false, Target_x86_64, elfcpp::SHT_RELA,
                            Target_x86_64::Scan,
 			   Target_x86_64::Relocatable_size_for_reloc>(
     symtab,
@@ -2720,18 +2799,19 @@ Target_x86_64::gc_process_relocs(Symbol_table* symtab,
 }
 // Scan relocations for a section.
 
+template<int size>
 void
-Target_x86_64::scan_relocs(Symbol_table* symtab,
-                           Layout* layout,
-                           Sized_relobj_file<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)
+Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
+				 Layout* layout,
+				 Sized_relobj_file<size, 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)
     {
@@ -2740,7 +2820,7 @@ Target_x86_64::scan_relocs(Symbol_table* symtab,
       return;
     }
 
-  gold::scan_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
+  gold::scan_relocs<size, false, Target_x86_64, elfcpp::SHT_RELA,
       Target_x86_64::Scan>(
     symtab,
     layout,
@@ -2757,8 +2837,9 @@ Target_x86_64::scan_relocs(Symbol_table* symtab,
 
 // Finalize the sections.
 
+template<int size>
 void
-Target_x86_64::do_finalize_sections(
+Target_x86_64<size>::do_finalize_sections(
     Layout* layout,
     const Input_objects*,
     Symbol_table* symtab)
@@ -2798,7 +2879,7 @@ Target_x86_64::do_finalize_sections(
   if (sym != NULL)
     {
       uint64_t data_size = this->got_plt_->current_data_size();
-      symtab->get_sized_symbol<64>(sym)->set_symsize(data_size);
+      symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
     }
 
   if (parameters->doing_static_link()
@@ -2845,18 +2926,19 @@ Target_x86_64::do_finalize_sections(
 
 // Perform a relocation.
 
+template<int size>
 inline bool
-Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
-                                  Target_x86_64* target,
-				  Output_section*,
-                                  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)
+Target_x86_64<size>::Relocate::relocate(const Relocate_info<size, false>* relinfo,
+					Target_x86_64* target,
+					Output_section*,
+					size_t relnum,
+					const elfcpp::Rela<size, false>& 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)
 {
   if (this->skip_call_tls_get_addr_)
     {
@@ -2875,10 +2957,10 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
 	}
     }
 
-  const Sized_relobj_file<64, false>* object = relinfo->object;
+  const Sized_relobj_file<size, false>* object = relinfo->object;
 
   // Pick the value to use for symbols defined in the PLT.
-  Symbol_value<64> symval;
+  Symbol_value<size> symval;
   if (gsym != NULL
       && gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
     {
@@ -2888,7 +2970,7 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
     }
   else if (gsym == NULL && psymval->is_ifunc_symbol())
     {
-      unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+      unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
       if (object->local_has_plt_offset(r_sym))
 	{
 	  symval.set_output_value(target->plt_address_for_local(object, r_sym)
@@ -2919,7 +3001,7 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
         }
       else
         {
-          unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+          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)
                         - target->got_size());
@@ -2939,11 +3021,11 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
       break;
 
     case elfcpp::R_X86_64_64:
-      Relocate_functions<64, false>::rela64(view, object, psymval, addend);
+      Relocate_functions<size, false>::rela64(view, object, psymval, addend);
       break;
 
     case elfcpp::R_X86_64_PC64:
-      Relocate_functions<64, false>::pcrela64(view, object, psymval, addend,
+      Relocate_functions<size, false>::pcrela64(view, object, psymval, addend,
                                               address);
       break;
 
@@ -2952,37 +3034,37 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
       //    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);
+      Relocate_functions<size, 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);
+      Relocate_functions<size, false>::rela32(view, object, psymval, addend);
       break;
 
     case elfcpp::R_X86_64_PC32:
-      Relocate_functions<64, false>::pcrela32(view, object, psymval, addend,
-                                              address);
+      Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+						address);
       break;
 
     case elfcpp::R_X86_64_16:
-      Relocate_functions<64, false>::rela16(view, object, psymval, addend);
+      Relocate_functions<size, false>::rela16(view, object, psymval, addend);
       break;
 
     case elfcpp::R_X86_64_PC16:
-      Relocate_functions<64, false>::pcrela16(view, object, psymval, addend,
-                                              address);
+      Relocate_functions<size, false>::pcrela16(view, object, psymval, addend,
+						address);
       break;
 
     case elfcpp::R_X86_64_8:
-      Relocate_functions<64, false>::rela8(view, object, psymval, addend);
+      Relocate_functions<size, false>::rela8(view, object, psymval, addend);
       break;
 
     case elfcpp::R_X86_64_PC8:
-      Relocate_functions<64, false>::pcrela8(view, object, psymval, addend,
-                                             address);
+      Relocate_functions<size, false>::pcrela8(view, object, psymval, addend,
+					       address);
       break;
 
     case elfcpp::R_X86_64_PLT32:
@@ -2995,8 +3077,8 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
       // 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);
+      Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+						address);
       break;
 
     case elfcpp::R_X86_64_PLTOFF64:
@@ -3004,23 +3086,23 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
         gold_assert(gsym);
         gold_assert(gsym->has_plt_offset()
                     || gsym->final_value_is_known());
-	elfcpp::Elf_types<64>::Elf_Addr got_address;
+	typename elfcpp::Elf_types<size>::Elf_Addr got_address;
 	got_address = target->got_section(NULL, NULL)->address();
-	Relocate_functions<64, false>::rela64(view, object, psymval,
-					      addend - got_address);
+	Relocate_functions<size, 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);
+      Relocate_functions<size, false>::rela32(view, got_offset, addend);
       break;
 
     case elfcpp::R_X86_64_GOTPC32:
       {
         gold_assert(gsym);
-	elfcpp::Elf_types<64>::Elf_Addr value;
+	typename elfcpp::Elf_types<size>::Elf_Addr value;
 	value = target->got_plt_section()->address();
-	Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+	Relocate_functions<size, false>::pcrela32(view, value, addend, address);
       }
       break;
 
@@ -3029,42 +3111,42 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
       // 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);
+      Relocate_functions<size, false>::rela64(view, got_offset, addend);
       break;
 
     case elfcpp::R_X86_64_GOTPC64:
       {
         gold_assert(gsym);
-	elfcpp::Elf_types<64>::Elf_Addr value;
+	typename elfcpp::Elf_types<size>::Elf_Addr value;
 	value = target->got_plt_section()->address();
-	Relocate_functions<64, false>::pcrela64(view, value, addend, address);
+	Relocate_functions<size, false>::pcrela64(view, value, addend, address);
       }
       break;
 
     case elfcpp::R_X86_64_GOTOFF64:
       {
-	elfcpp::Elf_types<64>::Elf_Addr value;
+	typename elfcpp::Elf_types<size>::Elf_Addr value;
 	value = (psymval->value(object, 0)
 		 - target->got_plt_section()->address());
-	Relocate_functions<64, false>::rela64(view, value, addend);
+	Relocate_functions<size, false>::rela64(view, value, addend);
       }
       break;
 
     case elfcpp::R_X86_64_GOTPCREL:
       {
         gold_assert(have_got_offset);
-        elfcpp::Elf_types<64>::Elf_Addr value;
+        typename elfcpp::Elf_types<size>::Elf_Addr value;
         value = target->got_plt_section()->address() + got_offset;
-        Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+        Relocate_functions<size, 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;
+        typename elfcpp::Elf_types<size>::Elf_Addr value;
         value = target->got_plt_section()->address() + got_offset;
-        Relocate_functions<64, false>::pcrela64(view, value, addend, address);
+        Relocate_functions<size, false>::pcrela64(view, value, addend, address);
       }
       break;
 
@@ -3109,26 +3191,27 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
 
 // Perform a TLS relocation.
 
+template<int size>
 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)
+Target_x86_64<size>::Relocate::relocate_tls(const Relocate_info<size, false>* relinfo,
+					    Target_x86_64* target,
+					    size_t relnum,
+					    const elfcpp::Rela<size, false>& 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)
 {
   Output_segment* tls_segment = relinfo->layout->tls_segment();
 
-  const Sized_relobj_file<64, false>* object = relinfo->object;
+  const Sized_relobj_file<size, false>* object = relinfo->object;
   const elfcpp::Elf_Xword addend = rela.get_r_addend();
-  elfcpp::Shdr<64, false> data_shdr(relinfo->data_shdr);
+  elfcpp::Shdr<size, false> data_shdr(relinfo->data_shdr);
   bool is_executable = (data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0;
 
-  elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0);
+  typename elfcpp::Elf_types<size>::Elf_Addr value = psymval->value(relinfo->object, 0);
 
   const bool is_final = (gsym == NULL
 			 ? !parameters->options().shared()
@@ -3174,7 +3257,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
             }
           else
             {
-              unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+              unsigned int r_sym = elfcpp::elf_r_sym<size>(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());
@@ -3191,8 +3274,8 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
               // 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);
+              Relocate_functions<size, false>::pcrela32(view, value, addend,
+							address);
               break;
             }
         }
@@ -3242,7 +3325,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
             }
           else
             {
-              unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+              unsigned int r_sym = elfcpp::elf_r_sym<size>(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());
@@ -3268,8 +3351,8 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
                   // 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);
+                  Relocate_functions<size, false>::pcrela32(view, value, addend,
+							    address);
                 }
               break;
             }
@@ -3304,8 +3387,8 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
           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);
+          Relocate_functions<size, false>::pcrela32(view, value, addend,
+						    address);
           break;
         }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
@@ -3329,7 +3412,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
 	    }
 	  value -= tls_segment->memsz();
 	}
-      Relocate_functions<64, false>::rela32(view, value, addend);
+      Relocate_functions<size, false>::rela32(view, value, addend);
       break;
 
     case elfcpp::R_X86_64_DTPOFF64:
@@ -3344,7 +3427,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
 	    }
 	  value -= tls_segment->memsz();
 	}
-      Relocate_functions<64, false>::rela64(view, value, addend);
+      Relocate_functions<size, false>::rela64(view, value, addend);
       break;
 
     case elfcpp::R_X86_64_GOTTPOFF:         // Initial-exec
@@ -3374,14 +3457,14 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
             }
           else
             {
-              unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+              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));
               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);
+          Relocate_functions<size, false>::pcrela32(view, value, addend, address);
           break;
         }
       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
@@ -3397,7 +3480,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
 	  return;
 	}
       value -= tls_segment->memsz();
-      Relocate_functions<64, false>::rela32(view, value, addend);
+      Relocate_functions<size, false>::rela32(view, value, addend);
       break;
     }
 }
@@ -3405,16 +3488,17 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
 // Do a relocation in which we convert a TLS General-Dynamic to an
 // Initial-Exec.
 
+template<int size>
 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)
+Target_x86_64<size>::Relocate::tls_gd_to_ie(const Relocate_info<size, false>* relinfo,
+					    size_t relnum,
+					    Output_segment*,
+					    const elfcpp::Rela<size, false>& rela,
+					    unsigned int,
+					    typename elfcpp::Elf_types<size>::Elf_Addr value,
+					    unsigned char* view,
+					    typename elfcpp::Elf_types<size>::Elf_Addr address,
+					    section_size_type view_size)
 {
   // .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
   // .word 0x6666; rex64; call __tls_get_addr
@@ -3431,7 +3515,7 @@ Target_x86_64::Relocate::tls_gd_to_ie(const Relocate_info<64, false>* relinfo,
   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);
+  Relocate_functions<size, false>::pcrela32(view + 8, value, addend - 8, address);
 
   // The next reloc should be a PLT32 reloc against __tls_get_addr.
   // We can skip it.
@@ -3441,15 +3525,16 @@ Target_x86_64::Relocate::tls_gd_to_ie(const Relocate_info<64, false>* relinfo,
 // Do a relocation in which we convert a TLS General-Dynamic to a
 // Local-Exec.
 
+template<int size>
 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)
+Target_x86_64<size>::Relocate::tls_gd_to_le(const Relocate_info<size, false>* relinfo,
+					    size_t relnum,
+					    Output_segment* tls_segment,
+					    const elfcpp::Rela<size, false>& rela,
+					    unsigned int,
+					    typename elfcpp::Elf_types<size>::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
@@ -3466,7 +3551,7 @@ Target_x86_64::Relocate::tls_gd_to_le(const Relocate_info<64, false>* relinfo,
   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);
+  Relocate_functions<size, false>::rela32(view + 8, value, 0);
 
   // The next reloc should be a PLT32 reloc against __tls_get_addr.
   // We can skip it.
@@ -3475,16 +3560,17 @@ Target_x86_64::Relocate::tls_gd_to_le(const Relocate_info<64, false>* relinfo,
 
 // Do a TLSDESC-style General-Dynamic to Initial-Exec transition.
 
+template<int size>
 inline void
-Target_x86_64::Relocate::tls_desc_gd_to_ie(
-    const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
+    const Relocate_info<size, false>* relinfo,
     size_t relnum,
     Output_segment*,
-    const elfcpp::Rela<64, false>& rela,
+    const elfcpp::Rela<size, false>& rela,
     unsigned int r_type,
-    elfcpp::Elf_types<64>::Elf_Addr value,
+    typename elfcpp::Elf_types<size>::Elf_Addr value,
     unsigned char* view,
-    elfcpp::Elf_types<64>::Elf_Addr address,
+    typename elfcpp::Elf_types<size>::Elf_Addr address,
     section_size_type view_size)
 {
   if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
@@ -3497,7 +3583,7 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie(
                      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);
+      Relocate_functions<size, false>::pcrela32(view, value, addend, address);
     }
   else
     {
@@ -3514,14 +3600,15 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie(
 
 // Do a TLSDESC-style General-Dynamic to Local-Exec transition.
 
+template<int size>
 inline void
-Target_x86_64::Relocate::tls_desc_gd_to_le(
-    const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
+    const Relocate_info<size, false>* relinfo,
     size_t relnum,
     Output_segment* tls_segment,
-    const elfcpp::Rela<64, false>& rela,
+    const elfcpp::Rela<size, false>& rela,
     unsigned int r_type,
-    elfcpp::Elf_types<64>::Elf_Addr value,
+    typename elfcpp::Elf_types<size>::Elf_Addr value,
     unsigned char* view,
     section_size_type view_size)
 {
@@ -3536,7 +3623,7 @@ Target_x86_64::Relocate::tls_desc_gd_to_le(
       view[-2] = 0xc7;
       view[-1] = 0xc0;
       value -= tls_segment->memsz();
-      Relocate_functions<64, false>::rela32(view, value, 0);
+      Relocate_functions<size, false>::rela32(view, value, 0);
     }
   else
     {
@@ -3551,15 +3638,16 @@ Target_x86_64::Relocate::tls_desc_gd_to_le(
     }
 }
 
+template<int size>
 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)
+Target_x86_64<size>::Relocate::tls_ld_to_le(const Relocate_info<size, false>* relinfo,
+					    size_t relnum,
+					    Output_segment*,
+					    const elfcpp::Rela<size, false>& rela,
+					    unsigned int,
+					    typename elfcpp::Elf_types<size>::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
@@ -3583,15 +3671,16 @@ Target_x86_64::Relocate::tls_ld_to_le(const Relocate_info<64, false>* relinfo,
 // Do a relocation in which we convert a TLS Initial-Exec to a
 // Local-Exec.
 
+template<int size>
 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)
+Target_x86_64<size>::Relocate::tls_ie_to_le(const Relocate_info<size, false>* relinfo,
+					    size_t relnum,
+					    Output_segment* tls_segment,
+					    const elfcpp::Rela<size, false>& rela,
+					    unsigned int,
+					    typename elfcpp::Elf_types<size>::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.
@@ -3633,27 +3722,28 @@ Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo,
     }
 
   value -= tls_segment->memsz();
-  Relocate_functions<64, false>::rela32(view, value, 0);
+  Relocate_functions<size, false>::rela32(view, value, 0);
 }
 
 // Relocate section data.
 
+template<int size>
 void
-Target_x86_64::relocate_section(
-    const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::relocate_section(
+    const Relocate_info<size, 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,
+    typename elfcpp::Elf_types<size>::Elf_Addr address,
     section_size_type view_size,
     const Reloc_symbol_changes* reloc_symbol_changes)
 {
   gold_assert(sh_type == elfcpp::SHT_RELA);
 
-  gold::relocate_section<64, false, Target_x86_64, elfcpp::SHT_RELA,
+  gold::relocate_section<size, false, Target_x86_64, elfcpp::SHT_RELA,
 			 Target_x86_64::Relocate>(
     relinfo,
     this,
@@ -3670,18 +3760,19 @@ Target_x86_64::relocate_section(
 // Apply an incremental relocation.  Incremental relocations always refer
 // to global symbols.
 
+template<int size>
 void
-Target_x86_64::apply_relocation(
-    const Relocate_info<64, false>* relinfo,
-    elfcpp::Elf_types<64>::Elf_Addr r_offset,
+Target_x86_64<size>::apply_relocation(
+    const Relocate_info<size, false>* relinfo,
+    typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
     unsigned int r_type,
-    elfcpp::Elf_types<64>::Elf_Swxword r_addend,
+    typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
     const Symbol* gsym,
     unsigned char* view,
-    elfcpp::Elf_types<64>::Elf_Addr address,
+    typename elfcpp::Elf_types<size>::Elf_Addr address,
     section_size_type view_size)
 {
-  gold::apply_relocation<64, false, Target_x86_64, Target_x86_64::Relocate>(
+  gold::apply_relocation<size, false, Target_x86_64, Target_x86_64::Relocate>(
     relinfo,
     this,
     r_offset,
@@ -3696,8 +3787,9 @@ Target_x86_64::apply_relocation(
 // Return the size of a relocation while scanning during a relocatable
 // link.
 
+template<int size>
 unsigned int
-Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc(
+Target_x86_64<size>::Relocatable_size_for_reloc::get_size_for_reloc(
     unsigned int r_type,
     Relobj* object)
 {
@@ -3765,26 +3857,27 @@ Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc(
 
 // Scan the relocs during a relocatable link.
 
+template<int size>
 void
-Target_x86_64::scan_relocatable_relocs(Symbol_table* symtab,
-				       Layout* layout,
-				       Sized_relobj_file<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)
+Target_x86_64<size>::scan_relocatable_relocs(Symbol_table* symtab,
+					     Layout* layout,
+					     Sized_relobj_file<size, 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,
+  gold::scan_relocatable_relocs<size, false, elfcpp::SHT_RELA,
       Scan_relocatable_relocs>(
     symtab,
     layout,
@@ -3801,9 +3894,10 @@ Target_x86_64::scan_relocatable_relocs(Symbol_table* symtab,
 
 // Relocate a section during a relocatable link.
 
+template<int size>
 void
-Target_x86_64::relocate_for_relocatable(
-    const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::relocate_for_relocatable(
+    const Relocate_info<size, false>* relinfo,
     unsigned int sh_type,
     const unsigned char* prelocs,
     size_t reloc_count,
@@ -3811,14 +3905,14 @@ Target_x86_64::relocate_for_relocatable(
     off_t offset_in_output_section,
     const Relocatable_relocs* rr,
     unsigned char* view,
-    elfcpp::Elf_types<64>::Elf_Addr view_address,
+    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<64, false, elfcpp::SHT_RELA>(
+  gold::relocate_for_relocatable<size, false, elfcpp::SHT_RELA>(
     relinfo,
     prelocs,
     reloc_count,
@@ -3837,8 +3931,9 @@ Target_x86_64::relocate_for_relocatable(
 // pointers across shared library boundaries, as described in the
 // processor specific ABI supplement.
 
+template<int size>
 uint64_t
-Target_x86_64::do_dynsym_value(const Symbol* gsym) const
+Target_x86_64<size>::do_dynsym_value(const Symbol* gsym) const
 {
   gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset());
   return this->plt_address_for_global(gsym) + gsym->plt_offset();
@@ -3847,8 +3942,9 @@ Target_x86_64::do_dynsym_value(const Symbol* gsym) const
 // Return a string used to fill a code section with nops to take up
 // the specified length.
 
+template<int size>
 std::string
-Target_x86_64::do_code_fill(section_size_type length) const
+Target_x86_64<size>::do_code_fill(section_size_type length) const
 {
   if (length >= 16)
     {
@@ -3921,15 +4017,16 @@ Target_x86_64::do_code_fill(section_size_type length) const
 // symbol.  We want to set the addend is the offset of the local
 // symbol in the TLS segment.
 
+template<int size>
 uint64_t
-Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type,
-			       uint64_t) const
+Target_x86_64<size>::do_reloc_addend(void* arg, unsigned int r_type,
+				     uint64_t) const
 {
   gold_assert(r_type == elfcpp::R_X86_64_TLSDESC);
   uintptr_t intarg = reinterpret_cast<uintptr_t>(arg);
   gold_assert(intarg < this->tlsdesc_reloc_info_.size());
   const Tlsdesc_info& ti(this->tlsdesc_reloc_info_[intarg]);
-  const Symbol_value<64>* psymval = ti.object->local_symbol(ti.r_sym);
+  const Symbol_value<size>* psymval = ti.object->local_symbol(ti.r_sym);
   gold_assert(psymval->is_tls_symbol());
   // The value of a TLS symbol is the offset in the TLS segment.
   return psymval->value(ti.object, 0);
@@ -3941,12 +4038,13 @@ Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type,
 // different sections, so instead of using a pc-relative value they
 // use an offset from the GOT.
 
+template<int size>
 uint64_t
-Target_x86_64::do_ehframe_datarel_base() const
+Target_x86_64<size>::do_ehframe_datarel_base() const
 {
   gold_assert(this->global_offset_table_ != NULL);
   Symbol* sym = this->global_offset_table_;
-  Sized_symbol<64>* ssym = static_cast<Sized_symbol<64>*>(sym);
+  Sized_symbol<size>* ssym = static_cast<Sized_symbol<size>*>(sym);
   return ssym->value();
 }
 
@@ -3955,14 +4053,15 @@ Target_x86_64::do_ehframe_datarel_base() const
 // code.  We have to change the function so that it always ensures
 // that it has enough stack space to run some random function.
 
+template<int size>
 void
-Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx,
-				  section_offset_type fnoffset,
-				  section_size_type fnsize,
-				  unsigned char* view,
-				  section_size_type view_size,
-				  std::string* from,
-				  std::string* to) const
+Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx,
+					section_offset_type fnoffset,
+					section_size_type fnsize,
+					unsigned char* view,
+					section_size_type view_size,
+					std::string* from,
+					std::string* to) const
 {
   // The function starts with a comparison of the stack pointer and a
   // field in the TCB.  This is followed by a jump.
@@ -4013,20 +4112,27 @@ Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx,
 
 // The selector for x86_64 object files.
 
+template<int size>
 class Target_selector_x86_64 : public Target_selector_freebsd
 {
 public:
   Target_selector_x86_64()
-    : Target_selector_freebsd(elfcpp::EM_X86_64, 64, false, "elf64-x86-64",
-			      "elf64-x86-64-freebsd", "elf_x86_64")
+    : Target_selector_freebsd(elfcpp::EM_X86_64, size, false,
+			      (size == 64 
+			       ? "elf64-x86-64" : "elf32-x86-64"),
+			      (size == 64 
+			       ? "elf64-x86-64-freebsd"
+			       : "elf32-x86-64-freebsd"),
+			      (size == 64 ? "elf_x86_64" : "elf32_x86_64"))
   { }
 
   Target*
   do_instantiate_target()
-  { return new Target_x86_64(); }
+  { return new Target_x86_64<size>(); }
 
 };
 
-Target_selector_x86_64 target_selector_x86_64;
+Target_selector_x86_64<64> target_selector_x86_64;
+Target_selector_x86_64<32> target_selector_x32;
 
 } // End anonymous namespace.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]