public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
@ 2011-12-15 23:09 H.J. Lu
  2011-12-16  2:38 ` Ian Lance Taylor
  2011-12-16  3:19 ` H.J. Lu
  0 siblings, 2 replies; 17+ messages in thread
From: H.J. Lu @ 2011-12-15 23:09 UTC (permalink / raw)
  To: binutils; +Cc: Ian Lance Taylor

Hi Ian,

This patch adds a parameter, got_entry_size, to Output_data_got
constructor so that a target can have a different GOT entry size.
OK to install?

Thanks.


H.J.
--
2011-12-15  H.J. Lu  <hongjiu.lu@intel.com>

	PR gold/13507
	* arm.cc (Arm_output_data_got): Pass 32 to Output_data_got
	constructor as got_entry_size.
	* i386.cc (Target_i386::got_section): Likewise.
	(Target_i386::got_section): Likewise.

	* output.cc (add_global_pair_with_rel) Replace size with
	this->got_entry_size_.
	(add_global_pair_with_rela): Likewise.
	(add_local_pair_with_rel): Likewise.
	(add_local_pair_with_rela): Likewise.
	(do_write): Likewise.
	(add_got_entry): Likewise.
	(add_got_entry_pair): Likewise.

	* output.h (Output_data_got): Add a parameter, got_entry_size,
	to constructor.  Replace size with with got_entry_size.
	(reserve_slot): Replace size with this->got_entry_size_.
	(got_offset): Likewise.
	(got_entry_size_): New.

	* powerpc.cc (got_section): Pass size to Output_data_got
	constructor as got_entry_size.
	* sparc.cc (got_section): Likewise.

	* x86_64.cc (got_section): Pass 64 to Output_data_got
	constructor as got_entry_size.
	(init_got_plt_for_update): Likewise.

diff --git a/gold/arm.cc b/gold/arm.cc
index 72c3670..55b7595 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -1898,7 +1898,7 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
 {
  public:
   Arm_output_data_got(Symbol_table* symtab, Layout* layout)
-    : Output_data_got<32, big_endian>(), symbol_table_(symtab), layout_(layout)
+    : Output_data_got<32, big_endian>(32), symbol_table_(symtab), layout_(layout)
   { }
 
   // Add a static entry for the GOT entry at OFFSET.  GSYM is a global
diff --git a/gold/i386.cc b/gold/i386.cc
index 191a915..a21cd68 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -713,7 +713,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<32, false>();
+      this->got_ = new Output_data_got<32, false>(32);
 
       // When using -z now, we can treat .got.plt as a relro section.
       // Without -z now, it is modified after program startup by lazy
@@ -768,7 +768,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
 
       // If there are any TLSDESC relocations, they get GOT entries in
       // .got.plt after the jump slot entries.
-      this->got_tlsdesc_ = new Output_data_got<32, false>();
+      this->got_tlsdesc_ = new Output_data_got<32, false>(32);
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_WRITE),
diff --git a/gold/output.cc b/gold/output.cc
index 7633c73..48b3162 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1495,7 +1495,8 @@ Output_data_got<size, big_endian>::add_global_pair_with_rel(
   rel_dyn->add_global(gsym, r_type_1, this, got_offset);
 
   if (r_type_2 != 0)
-    rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
+    rel_dyn->add_global(gsym, r_type_2, this,
+			got_offset + this->got_entry_size_ / 8);
 }
 
 template<int size, bool big_endian>
@@ -1515,7 +1516,8 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
   rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+    rela_dyn->add_global(gsym, r_type_2, this,
+			 got_offset + this->got_entry_size_ / 8, 0);
 }
 
 // Add an entry for a local symbol to the GOT.  This returns true if
@@ -1618,7 +1620,8 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
   rel_dyn->add_output_section(os, r_type_1, this, got_offset);
 
   if (r_type_2 != 0)
-    rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
+    rel_dyn->add_output_section(os, r_type_2, this,
+				got_offset + this->got_entry_size_ / 8);
 }
 
 template<int size, bool big_endian>
@@ -1643,7 +1646,8 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela(
   rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+    rela_dyn->add_output_section(os, r_type_2, this,
+				 got_offset + this->got_entry_size_ / 8, 0);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1679,7 +1683,7 @@ template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::do_write(Output_file* of)
 {
-  const int add = size / 8;
+  const int add = this->got_entry_size_ / 8;
 
   const off_t off = this->offset();
   const off_t oview_size = this->data_size();
@@ -1717,11 +1721,12 @@ Output_data_got<size, big_endian>::add_got_entry(Got_entry got_entry)
   else
     {
       // For an incremental update, find an available slot.
-      off_t got_offset = this->free_list_.allocate(size / 8, size / 8, 0);
+      off_t got_offset = this->free_list_.allocate(this->got_entry_size_ / 8,
+						   this->got_entry_size_ / 8, 0);
       if (got_offset == -1)
 	gold_fallback(_("out of patch space (GOT);"
 			" relink with --incremental-full"));
-      unsigned int got_index = got_offset / (size / 8);
+      unsigned int got_index = got_offset / (this->got_entry_size_ / 8);
       gold_assert(got_index < this->entries_.size());
       this->entries_[got_index] = got_entry;
       return static_cast<unsigned int>(got_offset);
@@ -1747,11 +1752,12 @@ Output_data_got<size, big_endian>::add_got_entry_pair(Got_entry got_entry_1,
   else
     {
       // For an incremental update, find an available pair of slots.
-      off_t got_offset = this->free_list_.allocate(2 * size / 8, size / 8, 0);
+      off_t got_offset = this->free_list_.allocate(2 * this->got_entry_size_ / 8,
+						   this->got_entry_size_ / 8, 0);
       if (got_offset == -1)
 	gold_fallback(_("out of patch space (GOT);"
 			" relink with --incremental-full"));
-      unsigned int got_index = got_offset / (size / 8);
+      unsigned int got_index = got_offset / (this->got_entry_size_ / 8);
       gold_assert(got_index < this->entries_.size());
       this->entries_[got_index] = got_entry_1;
       this->entries_[got_index + 1] = got_entry_2;
diff --git a/gold/output.h b/gold/output.h
index e704213..1acad6b2 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1983,19 +1983,19 @@ class Output_data_got : public Output_section_data_build
   typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
 
-  Output_data_got()
-    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
-      entries_(), free_list_()
+  Output_data_got(int got_entry_size)
+    : Output_section_data_build(Output_data::default_alignment_for_size(got_entry_size)),
+      got_entry_size_(got_entry_size), entries_(), free_list_()
   { }
 
-  Output_data_got(off_t data_size)
+  Output_data_got(off_t data_size, int got_entry_size)
     : Output_section_data_build(data_size,
-				Output_data::default_alignment_for_size(size)),
-      entries_(), free_list_()
+				Output_data::default_alignment_for_size(got_entry_size)),
+      got_entry_size_(got_entry_size), entries_(), free_list_()
   {
     // For an incremental update, we have an existing GOT section.
     // Initialize the list of entries and the free list.
-    this->entries_.resize(data_size / (size / 8));
+    this->entries_.resize(data_size / (got_entry_size / 8));
     this->free_list_.init(data_size, false);
   }
 
@@ -2083,7 +2083,8 @@ class Output_data_got : public Output_section_data_build
   // Reserve a slot in the GOT.
   void
   reserve_slot(unsigned int i)
-  { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
+  { this->free_list_.remove(i * this->got_entry_size_ / 8,
+			    (i + 1) * this->got_entry_size_ / 8); }
 
   // Reserve a slot in the GOT for a local symbol.
   void
@@ -2178,7 +2179,7 @@ class Output_data_got : public Output_section_data_build
   // Return the offset into the GOT of GOT entry I.
   unsigned int
   got_offset(unsigned int i) const
-  { return i * (size / 8); }
+  { return i * (this->got_entry_size_ / 8); }
 
   // Return the offset into the GOT of the last entry added.
   unsigned int
@@ -2190,6 +2191,9 @@ class Output_data_got : public Output_section_data_build
   set_got_size()
   { this->set_current_data_size(this->got_offset(this->entries_.size())); }
 
+  // Allow targets to override GOT entry size.
+  unsigned int got_entry_size_;
+
   // The list of GOT entries.
   Got_entries entries_;
 
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 62a17ca..948333f 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -765,7 +765,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab,
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<size, big_endian>();
+      this->got_ = new Output_data_got<size, big_endian>(size);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 12e1dee..4d88a86 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -1075,7 +1075,7 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab,
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<size, big_endian>();
+      this->got_ = new Output_data_got<size, big_endian>(size);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 0762926..43fc7e6 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -849,7 +849,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 					    ? ORDER_RELRO
 					    : ORDER_NON_RELRO_FIRST);
 
-      this->got_ = new Output_data_got<64, false>();
+      this->got_ = new Output_data_got<64, false>(64);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
@@ -893,7 +893,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 
       // If there are any TLSDESC relocations, they get GOT entries in
       // .got.plt after the jump slot and IRELATIVE entries.
-      this->got_tlsdesc_ = new Output_data_got<64, false>();
+      this->got_tlsdesc_ = new Output_data_got<64, false>(64);
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_WRITE),
@@ -1471,7 +1471,7 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
 {
   gold_assert(this->got_ == NULL);
 
-  this->got_ = new Output_data_got<64, false>(got_count * 8);
+  this->got_ = new Output_data_got<64, false>(got_count * 8, 64);
   layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				  (elfcpp::SHF_ALLOC
 				   | elfcpp::SHF_WRITE),
@@ -1499,7 +1499,7 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
   // If there are any TLSDESC relocations, they get GOT entries in
   // .got.plt after the jump slot entries.
   // FIXME: Get the count for TLSDESC entries.
-  this->got_tlsdesc_ = new Output_data_got<64, false>(0);
+  this->got_tlsdesc_ = new Output_data_got<64, false>(0, 64);
   layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				  elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
 				  this->got_tlsdesc_,

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-15 23:09 PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size H.J. Lu
@ 2011-12-16  2:38 ` Ian Lance Taylor
  2011-12-16  2:58   ` H.J. Lu
  2011-12-16  3:19 ` H.J. Lu
  1 sibling, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2011-12-16  2:38 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

"H.J. Lu" <hongjiu.lu@intel.com> writes:

> This patch adds a parameter, got_entry_size, to Output_data_got
> constructor so that a target can have a different GOT entry size.

Why not just use Output_data_got<got_entry_size, endianness>?

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16  2:38 ` Ian Lance Taylor
@ 2011-12-16  2:58   ` H.J. Lu
  2011-12-16  5:53     ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2011-12-16  2:58 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

On Thu, Dec 15, 2011 at 6:37 PM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hongjiu.lu@intel.com> writes:
>
>> This patch adds a parameter, got_entry_size, to Output_data_got
>> constructor so that a target can have a different GOT entry size.
>
> Why not just use Output_data_got<got_entry_size, endianness>?
>
> Ian

There are

template<int size, bool big_endian>
class Output_data_got : public Output_section_data_build
{
 public:
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
  typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
....
  bool
  add_local(Sized_relobj_file<size, big_endian>* object, unsigned int sym_index,
            unsigned int got_type);

  // Like add_local, but use the PLT offset of the local symbol if it
  // has one.
  bool
  add_local_plt(Sized_relobj_file<size, big_endian>* object,
                unsigned int sym_index,
                unsigned int got_type);

  // Add an entry for a local symbol to the GOT, and add a dynamic
  // relocation of type R_TYPE for the GOT entry.
  void
  add_local_with_rel(Sized_relobj_file<size, big_endian>* object,
                     unsigned int sym_index, unsigned int got_type,
                     Rel_dyn* rel_dyn, unsigned int r_type);

  void
  add_local_with_rela(Sized_relobj_file<size, big_endian>* object,
                      unsigned int sym_index, unsigned int got_type,
                      Rela_dyn* rela_dyn, unsigned int r_type);

The "size" parameter is the ELF class size.  32bit ELF targets
have to use 32.


-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-15 23:09 PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size H.J. Lu
  2011-12-16  2:38 ` Ian Lance Taylor
@ 2011-12-16  3:19 ` H.J. Lu
  1 sibling, 0 replies; 17+ messages in thread
From: H.J. Lu @ 2011-12-16  3:19 UTC (permalink / raw)
  To: binutils, Ian Lance Taylor

On Thu, Dec 15, 2011 at 03:09:19PM -0800, H.J. Lu wrote:
> Hi Ian,
> 
> This patch adds a parameter, got_entry_size, to Output_data_got
> constructor so that a target can have a different GOT entry size.
> OK to install?
> 
> Thanks.
> 
> 

<size> in

template<int size, bool big_endian>
class Output_data_got : public Output_section_data_build
{

is the ELF class size.  That is why I added got_entry_size to
Output_data_got so that target can set its GOT entry size, independent
of the ELF class size.

Here is the updated patch to avoid "/ 8".  Tested on Linux/x86-64.
OK to install?

Thanks.


H.J.
---
2011-12-15  H.J. Lu  <hongjiu.lu@intel.com>

	PR gold/13507
	* arm.cc (Arm_output_data_got): Pass 32 to Output_data_got
	constructor as got_entry_size.
	* i386.cc (Target_i386::got_section): Likewise.
	(Target_i386::got_section): Likewise.

	* output.cc (add_global_pair_with_rel) Replace size with
	this->got_entry_size_.
	(add_global_pair_with_rela): Likewise.
	(add_local_pair_with_rel): Likewise.
	(add_local_pair_with_rela): Likewise.
	(do_write): Likewise.
	(add_got_entry): Likewise.
	(add_got_entry_pair): Likewise.

	* output.h (Output_data_got): Add a parameter, got_entry_size,
	to constructor.  Replace size with with got_entry_size.
	(reserve_slot): Replace size with this->got_entry_size_.
	(got_offset): Likewise.
	(got_entry_size_): New.

	* powerpc.cc (got_section): Pass size to Output_data_got
	constructor as got_entry_size.
	* sparc.cc (got_section): Likewise.

	* x86_64.cc (got_section): Pass 64 to Output_data_got
	constructor as got_entry_size.
	(init_got_plt_for_update): Likewise.

diff --git a/gold/arm.cc b/gold/arm.cc
index 72c3670..55b7595 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -1898,7 +1898,7 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
 {
  public:
   Arm_output_data_got(Symbol_table* symtab, Layout* layout)
-    : Output_data_got<32, big_endian>(), symbol_table_(symtab), layout_(layout)
+    : Output_data_got<32, big_endian>(32), symbol_table_(symtab), layout_(layout)
   { }
 
   // Add a static entry for the GOT entry at OFFSET.  GSYM is a global
diff --git a/gold/i386.cc b/gold/i386.cc
index 191a915..a21cd68 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -713,7 +713,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<32, false>();
+      this->got_ = new Output_data_got<32, false>(32);
 
       // When using -z now, we can treat .got.plt as a relro section.
       // Without -z now, it is modified after program startup by lazy
@@ -768,7 +768,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
 
       // If there are any TLSDESC relocations, they get GOT entries in
       // .got.plt after the jump slot entries.
-      this->got_tlsdesc_ = new Output_data_got<32, false>();
+      this->got_tlsdesc_ = new Output_data_got<32, false>(32);
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_WRITE),
diff --git a/gold/output.cc b/gold/output.cc
index 7633c73..f1b1456 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1495,7 +1495,8 @@ Output_data_got<size, big_endian>::add_global_pair_with_rel(
   rel_dyn->add_global(gsym, r_type_1, this, got_offset);
 
   if (r_type_2 != 0)
-    rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
+    rel_dyn->add_global(gsym, r_type_2, this,
+			got_offset + this->got_entry_size_);
 }
 
 template<int size, bool big_endian>
@@ -1515,7 +1516,8 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
   rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+    rela_dyn->add_global(gsym, r_type_2, this,
+			 got_offset + this->got_entry_size_, 0);
 }
 
 // Add an entry for a local symbol to the GOT.  This returns true if
@@ -1618,7 +1620,8 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
   rel_dyn->add_output_section(os, r_type_1, this, got_offset);
 
   if (r_type_2 != 0)
-    rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
+    rel_dyn->add_output_section(os, r_type_2, this,
+				got_offset + this->got_entry_size_);
 }
 
 template<int size, bool big_endian>
@@ -1643,7 +1646,8 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela(
   rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+    rela_dyn->add_output_section(os, r_type_2, this,
+				 got_offset + this->got_entry_size_, 0);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1679,7 +1683,7 @@ template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::do_write(Output_file* of)
 {
-  const int add = size / 8;
+  const int add = this->got_entry_size_;
 
   const off_t off = this->offset();
   const off_t oview_size = this->data_size();
@@ -1717,11 +1721,12 @@ Output_data_got<size, big_endian>::add_got_entry(Got_entry got_entry)
   else
     {
       // For an incremental update, find an available slot.
-      off_t got_offset = this->free_list_.allocate(size / 8, size / 8, 0);
+      off_t got_offset = this->free_list_.allocate(this->got_entry_size_,
+						   this->got_entry_size_, 0);
       if (got_offset == -1)
 	gold_fallback(_("out of patch space (GOT);"
 			" relink with --incremental-full"));
-      unsigned int got_index = got_offset / (size / 8);
+      unsigned int got_index = got_offset / (this->got_entry_size_);
       gold_assert(got_index < this->entries_.size());
       this->entries_[got_index] = got_entry;
       return static_cast<unsigned int>(got_offset);
@@ -1747,11 +1752,12 @@ Output_data_got<size, big_endian>::add_got_entry_pair(Got_entry got_entry_1,
   else
     {
       // For an incremental update, find an available pair of slots.
-      off_t got_offset = this->free_list_.allocate(2 * size / 8, size / 8, 0);
+      off_t got_offset = this->free_list_.allocate(2 * this->got_entry_size_,
+						   this->got_entry_size_, 0);
       if (got_offset == -1)
 	gold_fallback(_("out of patch space (GOT);"
 			" relink with --incremental-full"));
-      unsigned int got_index = got_offset / (size / 8);
+      unsigned int got_index = got_offset / (this->got_entry_size_);
       gold_assert(got_index < this->entries_.size());
       this->entries_[got_index] = got_entry_1;
       this->entries_[got_index + 1] = got_entry_2;
diff --git a/gold/output.h b/gold/output.h
index e704213..1c3544a 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1983,19 +1983,19 @@ class Output_data_got : public Output_section_data_build
   typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
 
-  Output_data_got()
-    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
-      entries_(), free_list_()
+  Output_data_got(int got_entry_size)
+    : Output_section_data_build(Output_data::default_alignment_for_size(got_entry_size)),
+      got_entry_size_(got_entry_size / 8), entries_(), free_list_()
   { }
 
-  Output_data_got(off_t data_size)
+  Output_data_got(int got_entry_size, off_t data_size)
     : Output_section_data_build(data_size,
-				Output_data::default_alignment_for_size(size)),
-      entries_(), free_list_()
+				Output_data::default_alignment_for_size(got_entry_size)),
+      got_entry_size_(got_entry_size / 8), entries_(), free_list_()
   {
     // For an incremental update, we have an existing GOT section.
     // Initialize the list of entries and the free list.
-    this->entries_.resize(data_size / (size / 8));
+    this->entries_.resize(data_size / (got_entry_size / 8));
     this->free_list_.init(data_size, false);
   }
 
@@ -2083,7 +2083,8 @@ class Output_data_got : public Output_section_data_build
   // Reserve a slot in the GOT.
   void
   reserve_slot(unsigned int i)
-  { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
+  { this->free_list_.remove(i * this->got_entry_size_,
+			    (i + 1) * this->got_entry_size_); }
 
   // Reserve a slot in the GOT for a local symbol.
   void
@@ -2178,7 +2179,7 @@ class Output_data_got : public Output_section_data_build
   // Return the offset into the GOT of GOT entry I.
   unsigned int
   got_offset(unsigned int i) const
-  { return i * (size / 8); }
+  { return i * (this->got_entry_size_); }
 
   // Return the offset into the GOT of the last entry added.
   unsigned int
@@ -2190,6 +2191,9 @@ class Output_data_got : public Output_section_data_build
   set_got_size()
   { this->set_current_data_size(this->got_offset(this->entries_.size())); }
 
+  // GOT entry size in bytes.
+  unsigned int got_entry_size_;
+
   // The list of GOT entries.
   Got_entries entries_;
 
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 62a17ca..948333f 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -765,7 +765,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab,
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<size, big_endian>();
+      this->got_ = new Output_data_got<size, big_endian>(size);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 12e1dee..4d88a86 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -1075,7 +1075,7 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab,
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<size, big_endian>();
+      this->got_ = new Output_data_got<size, big_endian>(size);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 0762926..5a7a807 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -849,7 +849,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 					    ? ORDER_RELRO
 					    : ORDER_NON_RELRO_FIRST);
 
-      this->got_ = new Output_data_got<64, false>();
+      this->got_ = new Output_data_got<64, false>(64);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
@@ -893,7 +893,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 
       // If there are any TLSDESC relocations, they get GOT entries in
       // .got.plt after the jump slot and IRELATIVE entries.
-      this->got_tlsdesc_ = new Output_data_got<64, false>();
+      this->got_tlsdesc_ = new Output_data_got<64, false>(64);
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_WRITE),
@@ -1471,7 +1471,7 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
 {
   gold_assert(this->got_ == NULL);
 
-  this->got_ = new Output_data_got<64, false>(got_count * 8);
+  this->got_ = new Output_data_got<64, false>(64, got_count * 8);
   layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				  (elfcpp::SHF_ALLOC
 				   | elfcpp::SHF_WRITE),
@@ -1499,7 +1499,7 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
   // If there are any TLSDESC relocations, they get GOT entries in
   // .got.plt after the jump slot entries.
   // FIXME: Get the count for TLSDESC entries.
-  this->got_tlsdesc_ = new Output_data_got<64, false>(0);
+  this->got_tlsdesc_ = new Output_data_got<64, false>(64, 0);
   layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				  elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
 				  this->got_tlsdesc_,

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16  2:58   ` H.J. Lu
@ 2011-12-16  5:53     ` Ian Lance Taylor
  2011-12-16 15:39       ` H.J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2011-12-16  5:53 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

"H.J. Lu" <hjl.tools@gmail.com> writes:

> On Thu, Dec 15, 2011 at 6:37 PM, Ian Lance Taylor <iant@google.com> wrote:
>> "H.J. Lu" <hongjiu.lu@intel.com> writes:
>>
>>> This patch adds a parameter, got_entry_size, to Output_data_got
>>> constructor so that a target can have a different GOT entry size.
>>
>> Why not just use Output_data_got<got_entry_size, endianness>?
>>
>> Ian
>
> There are
>
> template<int size, bool big_endian>
> class Output_data_got : public Output_section_data_build
> {
>  public:
>   typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
>   typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
>   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
> ....
>   bool
>   add_local(Sized_relobj_file<size, big_endian>* object, unsigned int sym_index,
>             unsigned int got_type);
>
>   // Like add_local, but use the PLT offset of the local symbol if it
>   // has one.
>   bool
>   add_local_plt(Sized_relobj_file<size, big_endian>* object,
>                 unsigned int sym_index,
>                 unsigned int got_type);
>
>   // Add an entry for a local symbol to the GOT, and add a dynamic
>   // relocation of type R_TYPE for the GOT entry.
>   void
>   add_local_with_rel(Sized_relobj_file<size, big_endian>* object,
>                      unsigned int sym_index, unsigned int got_type,
>                      Rel_dyn* rel_dyn, unsigned int r_type);
>
>   void
>   add_local_with_rela(Sized_relobj_file<size, big_endian>* object,
>                       unsigned int sym_index, unsigned int got_type,
>                       Rela_dyn* rela_dyn, unsigned int r_type);
>
> The "size" parameter is the ELF class size.  32bit ELF targets
> have to use 32.

Ah, I see.  Output_data_got does conflate the GOT entry size with the
Sized_relobj_file<size, big_endian> argument.  Sorry to be a pain, but
that is really an error in how Output_data_got is written.  The size
should be the size of a GOT entry, not the ELF class size.  The
arguments should be Relobj, not Sized_relobj_file.  Of course this will
require some other work as well.

In general I think the size of entries in the GOT ought to be a template
parameter for Output_data_got.

As far as I can tell your patch is incorrect, because you haven't
changed Output_data_got<size, big_endian>::Got_entry::write.  When that
function calls elfcpp::Swap<size, big_endian>::writeval, it has to use
the size of a GOT entry.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16  5:53     ` Ian Lance Taylor
@ 2011-12-16 15:39       ` H.J. Lu
  2011-12-16 16:43         ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2011-12-16 15:39 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

On Thu, Dec 15, 2011 at 9:53 PM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
>> On Thu, Dec 15, 2011 at 6:37 PM, Ian Lance Taylor <iant@google.com> wrote:
>>> "H.J. Lu" <hongjiu.lu@intel.com> writes:
>>>
>>>> This patch adds a parameter, got_entry_size, to Output_data_got
>>>> constructor so that a target can have a different GOT entry size.
>>>
>>> Why not just use Output_data_got<got_entry_size, endianness>?
>>>
>>> Ian
>>
>> There are
>>
>> template<int size, bool big_endian>
>> class Output_data_got : public Output_section_data_build
>> {
>>  public:
>>   typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
>>   typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
>>   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
>> ....
>>   bool
>>   add_local(Sized_relobj_file<size, big_endian>* object, unsigned int sym_index,
>>             unsigned int got_type);
>>
>>   // Like add_local, but use the PLT offset of the local symbol if it
>>   // has one.
>>   bool
>>   add_local_plt(Sized_relobj_file<size, big_endian>* object,
>>                 unsigned int sym_index,
>>                 unsigned int got_type);
>>
>>   // Add an entry for a local symbol to the GOT, and add a dynamic
>>   // relocation of type R_TYPE for the GOT entry.
>>   void
>>   add_local_with_rel(Sized_relobj_file<size, big_endian>* object,
>>                      unsigned int sym_index, unsigned int got_type,
>>                      Rel_dyn* rel_dyn, unsigned int r_type);
>>
>>   void
>>   add_local_with_rela(Sized_relobj_file<size, big_endian>* object,
>>                       unsigned int sym_index, unsigned int got_type,
>>                       Rela_dyn* rela_dyn, unsigned int r_type);
>>
>> The "size" parameter is the ELF class size.  32bit ELF targets
>> have to use 32.
>
> Ah, I see.  Output_data_got does conflate the GOT entry size with the
> Sized_relobj_file<size, big_endian> argument.  Sorry to be a pain, but
> that is really an error in how Output_data_got is written.  The size
> should be the size of a GOT entry, not the ELF class size.  The
> arguments should be Relobj, not Sized_relobj_file.  Of course this will
> require some other work as well.

How do we deal with

typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;

<size> here should be the ELF class size.

> In general I think the size of entries in the GOT ought to be a template
> parameter for Output_data_got.
>
> As far as I can tell your patch is incorrect, because you haven't
> changed Output_data_got<size, big_endian>::Got_entry::write.  When that
> function calls elfcpp::Swap<size, big_endian>::writeval, it has to use
> the size of a GOT entry.

How should it be fixed? Should we add another template parameter just
for GOT entry size?


-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16 15:39       ` H.J. Lu
@ 2011-12-16 16:43         ` Ian Lance Taylor
  2011-12-16 17:08           ` H.J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2011-12-16 16:43 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

"H.J. Lu" <hjl.tools@gmail.com> writes:

> How do we deal with
>
> typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
> typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
> typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
>
> <size> here should be the ELF class size.

As far as I can see in the definition of Valtype the size should be the
size of a GOT entry, not the ELF class size.

The simple way to handle Rel_dyn and Rela_dyn would be to change
Output_data_reloc<>::add_global and add_local to virtual functions, add
them to Output_data_reloc_generic, and use Output_data_reloc_generic in
Output_data_got.  Perhaps that would lead to other issues, I'm not sure.
If that works it would let us eliminate add_global_with_rela and
friends.

Of course since add_global and add_local take addresses it would be
necessary for the generic versions to take uint64_t and for specific
versions to take the appropriate size address, and use convert_types to
make sure that there is no overflow.  Actually it might be simpler to
leave add_global and add_local as they are and add virtual functions
with a different name to Output_data_reloc_generic.



>> In general I think the size of entries in the GOT ought to be a template
>> parameter for Output_data_got.
>>
>> As far as I can tell your patch is incorrect, because you haven't
>> changed Output_data_got<size, big_endian>::Got_entry::write.  When that
>> function calls elfcpp::Swap<size, big_endian>::writeval, it has to use
>> the size of a GOT entry.
>
> How should it be fixed? Should we add another template parameter just
> for GOT entry size?

That would be another approach, yes.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16 16:43         ` Ian Lance Taylor
@ 2011-12-16 17:08           ` H.J. Lu
  2011-12-16 19:00             ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2011-12-16 17:08 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 4062 bytes --]

On Fri, Dec 16, 2011 at 8:43 AM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
>> How do we deal with
>>
>> typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
>> typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
>> typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
>>
>> <size> here should be the ELF class size.
>
> As far as I can see in the definition of Valtype the size should be the
> size of a GOT entry, not the ELF class size.

For 32bit ELF class, address is 32bit. When we use

elfcpp::Swap<64, big_endian>::writeval(pov, val);

to write 64bit GOT entry for 32bit ELF class, we can use ELF class size for
Valtype.

> The simple way to handle Rel_dyn and Rela_dyn would be to change
> Output_data_reloc<>::add_global and add_local to virtual functions, add
> them to Output_data_reloc_generic, and use Output_data_reloc_generic in
> Output_data_got.  Perhaps that would lead to other issues, I'm not sure.
> If that works it would let us eliminate add_global_with_rela and
> friends.
>
> Of course since add_global and add_local take addresses it would be
> necessary for the generic versions to take uint64_t and for specific
> versions to take the appropriate size address, and use convert_types to
> make sure that there is no overflow.  Actually it might be simpler to
> leave add_global and add_local as they are and add virtual functions
> with a different name to Output_data_reloc_generic.
>

Unless we can remove all dependencies on the ELF class from
Output_data_got, I don't see how it will work.

>
>>> In general I think the size of entries in the GOT ought to be a template
>>> parameter for Output_data_got.
>>>
>>> As far as I can tell your patch is incorrect, because you haven't
>>> changed Output_data_got<size, big_endian>::Got_entry::write.  When that
>>> function calls elfcpp::Swap<size, big_endian>::writeval, it has to use
>>> the size of a GOT entry.
>>
>> How should it be fixed? Should we add another template parameter just
>> for GOT entry size?
>
> That would be another approach, yes.

Considering there are codes in Output_data_got like

            Sized_symbol<size>* sgsym;
            // This cast is a bit ugly.  We don't want to put a
            // virtual method in Symbol, because we want Symbol to be
            // as small as possible.
            sgsym = static_cast<Sized_symbol<size>*>(gsym);
            val = sgsym->value();

add another template parameter for GOT entry size is less intrusive.
FWIW, I enclosed a new patch without adding a template parameter for
GOT entry size.  If it isn't acceptable, I will work on a patch to add
a new template parameter, which will be added to most of template
classes.

Thanks.

-- 
H.J
---
.2011-12-16  H.J. Lu  <hongjiu.lu@intel.com>

	PR gold/13507
	* arm.cc (Arm_output_data_got): Pass 32 to Output_data_got
	constructor as got_entry_size.
	* i386.cc (Target_i386::got_section): Likewise.
	(Target_i386::got_section): Likewise.

	* output.cc (write): Add a parameter, got_entry_size, and
	use it to write GOT entry.
	(add_global_pair_with_rel) Replace size with this->got_entry_size_.
	(add_global_pair_with_rela): Likewise.
	(add_local_pair_with_rel): Likewise.
	(add_local_pair_with_rela): Likewise.
	(add_got_entry): Likewise.
	(add_got_entry_pair): Likewise.
	(do_write): Likewise.  Pass this->got_entry_size_ to write.

	* output.h (Output_data_got): Add a parameter, got_entry_size,
	to constructor.  Replace size with with got_entry_size.
	(reserve_slot): Replace size with this->got_entry_size_.
	(got_offset): Likewise.
	(write): Add parameter, got_entry_size.
	(got_entry_size_): New.

	* powerpc.cc (got_section): Pass size to Output_data_got
	constructor as got_entry_size.
	* sparc.cc (got_section): Likewise.

	* x86_64.cc (got_section): Pass 64 to Output_data_got
	constructor as got_entry_size.
	(init_got_plt_for_update): Likewise.

[-- Attachment #2: binutils-pr13507-3.patch --]
[-- Type: text/x-diff, Size: 12721 bytes --]

2011-12-16  H.J. Lu  <hongjiu.lu@intel.com>

	PR gold/13507
	* arm.cc (Arm_output_data_got): Pass 32 to Output_data_got
	constructor as got_entry_size.
	* i386.cc (Target_i386::got_section): Likewise.
	(Target_i386::got_section): Likewise.

	* output.cc (write): Add a parameter, got_entry_size, and
	use it to write GOT entry.
	(add_global_pair_with_rel) Replace size with this->got_entry_size_.
	(add_global_pair_with_rela): Likewise.
	(add_local_pair_with_rel): Likewise.
	(add_local_pair_with_rela): Likewise.
	(add_got_entry): Likewise.
	(add_got_entry_pair): Likewise.
	(do_write): Likewise.  Pass this->got_entry_size_ to write.

	* output.h (Output_data_got): Add a parameter, got_entry_size,
	to constructor.  Replace size with with got_entry_size.
	(reserve_slot): Replace size with this->got_entry_size_.
	(got_offset): Likewise.
	(write): Add parameter, got_entry_size.
	(got_entry_size_): New.

	* powerpc.cc (got_section): Pass size to Output_data_got
	constructor as got_entry_size.
	* sparc.cc (got_section): Likewise.

	* x86_64.cc (got_section): Pass 64 to Output_data_got
	constructor as got_entry_size.
	(init_got_plt_for_update): Likewise.

diff --git a/gold/arm.cc b/gold/arm.cc
index 72c3670..55b7595 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -1898,7 +1898,7 @@ class Arm_output_data_got : public Output_data_got<32, big_endian>
 {
  public:
   Arm_output_data_got(Symbol_table* symtab, Layout* layout)
-    : Output_data_got<32, big_endian>(), symbol_table_(symtab), layout_(layout)
+    : Output_data_got<32, big_endian>(32), symbol_table_(symtab), layout_(layout)
   { }
 
   // Add a static entry for the GOT entry at OFFSET.  GSYM is a global
diff --git a/gold/i386.cc b/gold/i386.cc
index 191a915..a21cd68 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -713,7 +713,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<32, false>();
+      this->got_ = new Output_data_got<32, false>(32);
 
       // When using -z now, we can treat .got.plt as a relro section.
       // Without -z now, it is modified after program startup by lazy
@@ -768,7 +768,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
 
       // If there are any TLSDESC relocations, they get GOT entries in
       // .got.plt after the jump slot entries.
-      this->got_tlsdesc_ = new Output_data_got<32, false>();
+      this->got_tlsdesc_ = new Output_data_got<32, false>(32);
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_WRITE),
diff --git a/gold/output.cc b/gold/output.cc
index 7633c73..f3725e3 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1347,7 +1347,8 @@ Output_data_group<size, big_endian>::do_write(Output_file* of)
 
 template<int size, bool big_endian>
 void
-Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
+Output_data_got<size, big_endian>::Got_entry::write(unsigned int got_entry_size,
+						    unsigned char* pov) const
 {
   Valtype val = 0;
 
@@ -1402,7 +1403,17 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
       break;
     }
 
-  elfcpp::Swap<size, big_endian>::writeval(pov, val);
+  switch (got_entry_size)
+    {
+    case 4:
+      elfcpp::Swap<32, big_endian>::writeval(pov, val);
+      break;
+    case 8:
+      elfcpp::Swap<64, big_endian>::writeval(pov, val);
+      break;
+    default:
+      gold_unreachable();
+    }
 }
 
 // Output_data_got methods.
@@ -1495,7 +1506,8 @@ Output_data_got<size, big_endian>::add_global_pair_with_rel(
   rel_dyn->add_global(gsym, r_type_1, this, got_offset);
 
   if (r_type_2 != 0)
-    rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
+    rel_dyn->add_global(gsym, r_type_2, this,
+			got_offset + this->got_entry_size_);
 }
 
 template<int size, bool big_endian>
@@ -1515,7 +1527,8 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
   rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+    rela_dyn->add_global(gsym, r_type_2, this,
+			 got_offset + this->got_entry_size_, 0);
 }
 
 // Add an entry for a local symbol to the GOT.  This returns true if
@@ -1618,7 +1631,8 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
   rel_dyn->add_output_section(os, r_type_1, this, got_offset);
 
   if (r_type_2 != 0)
-    rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
+    rel_dyn->add_output_section(os, r_type_2, this,
+				got_offset + this->got_entry_size_);
 }
 
 template<int size, bool big_endian>
@@ -1643,7 +1657,8 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela(
   rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+    rela_dyn->add_output_section(os, r_type_2, this,
+				 got_offset + this->got_entry_size_, 0);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1679,7 +1694,7 @@ template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::do_write(Output_file* of)
 {
-  const int add = size / 8;
+  const int add = this->got_entry_size_;
 
   const off_t off = this->offset();
   const off_t oview_size = this->data_size();
@@ -1690,7 +1705,7 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
        p != this->entries_.end();
        ++p)
     {
-      p->write(pov);
+      p->write(this->got_entry_size_, pov);
       pov += add;
     }
 
@@ -1717,11 +1732,12 @@ Output_data_got<size, big_endian>::add_got_entry(Got_entry got_entry)
   else
     {
       // For an incremental update, find an available slot.
-      off_t got_offset = this->free_list_.allocate(size / 8, size / 8, 0);
+      off_t got_offset = this->free_list_.allocate(this->got_entry_size_,
+						   this->got_entry_size_, 0);
       if (got_offset == -1)
 	gold_fallback(_("out of patch space (GOT);"
 			" relink with --incremental-full"));
-      unsigned int got_index = got_offset / (size / 8);
+      unsigned int got_index = got_offset / this->got_entry_size_;
       gold_assert(got_index < this->entries_.size());
       this->entries_[got_index] = got_entry;
       return static_cast<unsigned int>(got_offset);
@@ -1747,11 +1763,12 @@ Output_data_got<size, big_endian>::add_got_entry_pair(Got_entry got_entry_1,
   else
     {
       // For an incremental update, find an available pair of slots.
-      off_t got_offset = this->free_list_.allocate(2 * size / 8, size / 8, 0);
+      off_t got_offset = this->free_list_.allocate(2 * this->got_entry_size_,
+						   this->got_entry_size_, 0);
       if (got_offset == -1)
 	gold_fallback(_("out of patch space (GOT);"
 			" relink with --incremental-full"));
-      unsigned int got_index = got_offset / (size / 8);
+      unsigned int got_index = got_offset / this->got_entry_size_;
       gold_assert(got_index < this->entries_.size());
       this->entries_[got_index] = got_entry_1;
       this->entries_[got_index + 1] = got_entry_2;
diff --git a/gold/output.h b/gold/output.h
index e704213..81ca494 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1983,19 +1983,19 @@ class Output_data_got : public Output_section_data_build
   typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
 
-  Output_data_got()
-    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
-      entries_(), free_list_()
+  Output_data_got(int got_entry_size)
+    : Output_section_data_build(Output_data::default_alignment_for_size(got_entry_size)),
+      got_entry_size_(got_entry_size / 8), entries_(), free_list_()
   { }
 
-  Output_data_got(off_t data_size)
+  Output_data_got(int got_entry_size, off_t data_size)
     : Output_section_data_build(data_size,
-				Output_data::default_alignment_for_size(size)),
-      entries_(), free_list_()
+				Output_data::default_alignment_for_size(got_entry_size)),
+      got_entry_size_(got_entry_size / 8), entries_(), free_list_()
   {
     // For an incremental update, we have an existing GOT section.
     // Initialize the list of entries and the free list.
-    this->entries_.resize(data_size / (size / 8));
+    this->entries_.resize(data_size / (got_entry_size / 8));
     this->free_list_.init(data_size, false);
   }
 
@@ -2083,7 +2083,8 @@ class Output_data_got : public Output_section_data_build
   // Reserve a slot in the GOT.
   void
   reserve_slot(unsigned int i)
-  { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
+  { this->free_list_.remove(i * this->got_entry_size_,
+			    (i + 1) * this->got_entry_size_); }
 
   // Reserve a slot in the GOT for a local symbol.
   void
@@ -2139,7 +2140,7 @@ class Output_data_got : public Output_section_data_build
 
     // Write the GOT entry to an output view.
     void
-    write(unsigned char* pov) const;
+    write(unsigned int got_entry_size, unsigned char* pov) const;
 
    private:
     enum
@@ -2178,7 +2179,7 @@ class Output_data_got : public Output_section_data_build
   // Return the offset into the GOT of GOT entry I.
   unsigned int
   got_offset(unsigned int i) const
-  { return i * (size / 8); }
+  { return i * this->got_entry_size_; }
 
   // Return the offset into the GOT of the last entry added.
   unsigned int
@@ -2190,6 +2191,9 @@ class Output_data_got : public Output_section_data_build
   set_got_size()
   { this->set_current_data_size(this->got_offset(this->entries_.size())); }
 
+  // GOT entry size in bytes.
+  unsigned int got_entry_size_;
+
   // The list of GOT entries.
   Got_entries entries_;
 
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 62a17ca..948333f 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -765,7 +765,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab,
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<size, big_endian>();
+      this->got_ = new Output_data_got<size, big_endian>(size);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 12e1dee..4d88a86 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -1075,7 +1075,7 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab,
     {
       gold_assert(symtab != NULL && layout != NULL);
 
-      this->got_ = new Output_data_got<size, big_endian>();
+      this->got_ = new Output_data_got<size, big_endian>(size);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 0762926..5a7a807 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -849,7 +849,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 					    ? ORDER_RELRO
 					    : ORDER_NON_RELRO_FIRST);
 
-      this->got_ = new Output_data_got<64, false>();
+      this->got_ = new Output_data_got<64, false>(64);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
@@ -893,7 +893,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 
       // If there are any TLSDESC relocations, they get GOT entries in
       // .got.plt after the jump slot and IRELATIVE entries.
-      this->got_tlsdesc_ = new Output_data_got<64, false>();
+      this->got_tlsdesc_ = new Output_data_got<64, false>(64);
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_WRITE),
@@ -1471,7 +1471,7 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
 {
   gold_assert(this->got_ == NULL);
 
-  this->got_ = new Output_data_got<64, false>(got_count * 8);
+  this->got_ = new Output_data_got<64, false>(64, got_count * 8);
   layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				  (elfcpp::SHF_ALLOC
 				   | elfcpp::SHF_WRITE),
@@ -1499,7 +1499,7 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
   // If there are any TLSDESC relocations, they get GOT entries in
   // .got.plt after the jump slot entries.
   // FIXME: Get the count for TLSDESC entries.
-  this->got_tlsdesc_ = new Output_data_got<64, false>(0);
+  this->got_tlsdesc_ = new Output_data_got<64, false>(64, 0);
   layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 				  elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
 				  this->got_tlsdesc_,

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16 17:08           ` H.J. Lu
@ 2011-12-16 19:00             ` Ian Lance Taylor
  2011-12-16 22:10               ` H.J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2011-12-16 19:00 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

"H.J. Lu" <hjl.tools@gmail.com> writes:

> On Fri, Dec 16, 2011 at 8:43 AM, Ian Lance Taylor <iant@google.com> wrote:
>> "H.J. Lu" <hjl.tools@gmail.com> writes:
>>
>>> How do we deal with
>>>
>>> typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
>>> typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
>>> typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
>>>
>>> <size> here should be the ELF class size.
>>
>> As far as I can see in the definition of Valtype the size should be the
>> size of a GOT entry, not the ELF class size.
>
> For 32bit ELF class, address is 32bit. When we use
>
> elfcpp::Swap<64, big_endian>::writeval(pov, val);
>
> to write 64bit GOT entry for 32bit ELF class, we can use ELF class size for
> Valtype.

But if you have 64-bit GOT entries, then when you call add_constant, you
should be able to pass a 64-bit value.


>> The simple way to handle Rel_dyn and Rela_dyn would be to change
>> Output_data_reloc<>::add_global and add_local to virtual functions, add
>> them to Output_data_reloc_generic, and use Output_data_reloc_generic in
>> Output_data_got.  Perhaps that would lead to other issues, I'm not sure.
>> If that works it would let us eliminate add_global_with_rela and
>> friends.
>>
>> Of course since add_global and add_local take addresses it would be
>> necessary for the generic versions to take uint64_t and for specific
>> versions to take the appropriate size address, and use convert_types to
>> make sure that there is no overflow.  Actually it might be simpler to
>> leave add_global and add_local as they are and add virtual functions
>> with a different name to Output_data_reloc_generic.
>>
>
> Unless we can remove all dependencies on the ELF class from
> Output_data_got, I don't see how it will work.

I agree.  That is exactly what I am suggesting.


> Considering there are codes in Output_data_got like
>
>             Sized_symbol<size>* sgsym;
>             // This cast is a bit ugly.  We don't want to put a
>             // virtual method in Symbol, because we want Symbol to be
>             // as small as possible.
>             sgsym = static_cast<Sized_symbol<size>*>(gsym);
>             val = sgsym->value();
>
> add another template parameter for GOT entry size is less intrusive.
> FWIW, I enclosed a new patch without adding a template parameter for
> GOT entry size.  If it isn't acceptable, I will work on a patch to add
> a new template parameter, which will be added to most of template
> classes.

My goal is not the least intrusive change.  My goal is the change which
gives us the best source code going forward.  I'm fairly sure that
passing in the GOT size as a parameter is not the best change.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16 19:00             ` Ian Lance Taylor
@ 2011-12-16 22:10               ` H.J. Lu
  2011-12-17  6:33                 ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2011-12-16 22:10 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

On Fri, Dec 16, 2011 at 10:59 AM, Ian Lance Taylor <iant@google.com> wrote:
>
>>
>> Unless we can remove all dependencies on the ELF class from
>> Output_data_got, I don't see how it will work.
>
> I agree.  That is exactly what I am suggesting.
>
>
>> Considering there are codes in Output_data_got like
>>
>>             Sized_symbol<size>* sgsym;
>>             // This cast is a bit ugly.  We don't want to put a
>>             // virtual method in Symbol, because we want Symbol to be
>>             // as small as possible.
>>             sgsym = static_cast<Sized_symbol<size>*>(gsym);
>>             val = sgsym->value();
>>
>> add another template parameter for GOT entry size is less intrusive.
>> FWIW, I enclosed a new patch without adding a template parameter for
>> GOT entry size.  If it isn't acceptable, I will work on a patch to add
>> a new template parameter, which will be added to most of template
>> classes.
>
> My goal is not the least intrusive change.  My goal is the change which
> gives us the best source code going forward.  I'm fairly sure that
> passing in the GOT size as a parameter is not the best change.
>

Given that it is very unlikely I can remove all dependencies on the ELF
class from Output_data_got, I will prepare a patch to add a new
parameter to class templates for GOT entry size.

-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-16 22:10               ` H.J. Lu
@ 2011-12-17  6:33                 ` Ian Lance Taylor
  2011-12-17 17:11                   ` H.J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2011-12-17  6:33 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 3254 bytes --]

"H.J. Lu" <hjl.tools@gmail.com> writes:

> Given that it is very unlikely I can remove all dependencies on the ELF
> class from Output_data_got, I will prepare a patch to add a new
> parameter to class templates for GOT entry size.

OK, I did it for you.  This patch changes Output_data_got to use a
template parameter of got_size rather than size.  I added virtual
functions and adjusted as necessary.  Committed to mainline.

Ian


2011-12-16  Ian Lance Taylor  <iant@google.com>

	* object.h (Relobj::local_symbol_value): New function.
	(Relobj::local_plt_offset): New function.
	(Relobj::local_has_got_offset): New function.
	(Relobj::local_got_offset): New function.
	(Relobj::set_local_got_offset): New function.
	(Relobj::do_local_symbol_value): New pure virtual function.
	(Relobj::do_local_plt_offset): Likewise.
	(Relobj::do_local_has_got_offset): Likewise.
	(Relobj::do_local_got_offset): Likewise.
	(Relobj::do_set_local_got_offset): Likewise.
	(Sized_relobj::do_local_has_got_offset): Rename from
	local_has_got_offset.
	(Sized_relobj::do_local_got_offset): Rename from local_got_offset.
	(Sized_relobj::do_set_local_got_offset): Rename from
	set_local_got_offset.
	(Sized_relobj_file::do_local_plt_offset): Rename from
	local_plt_offset.
	(Sized_relobj_file::do_local_symbol_value): New function.
	* object.cc (Sized_relobj_file::do_local_plt_offset): Rename from
	local_plt_offset.
	* output.cc (Output_data_got::Got_entry::write): Change object to
	Relobj.  Use local_symbol_value.
	(Output_data_got::add_global_with_rel): Change rel_dyn to
	Output_data_reloc_generic*.  Use add_global_generic.
	(Output_data_got::add_global_with_rela): Remove.  Change all
	callers to use add_global_with_rel.
	(Output_data_got::add_global_pair_with_rel): Change rel_dyn to
	Output_data_reloc_generic*.  Use add_global_generic.
	(Output_data_got::add_global_pair_with_rela): Remove.  Change all
	callers to use add_global_pair_with_rel.
	(Output_data_got::add_local): Change object to Relobj*.
	(Output_data_got::add_local_plt): Likewise.
	(Output_data_got::add_local_with_rel): Change object to Relobj*,
	change rel_dyn to Output_data_reloc_generic*.  Use
	add_local_generic.
	(Output_data_got::add_local_with_rela): Remove.  Change all
	callers to use all_local_with_rel.
	(Output_data_got::add_local_pair_with_rel): Change object to
	Relobj*, change rel_dyn to Output_data_reloc_generic*.  Use
	add_output_section_generic.
	(Output_data_got::add_local_pair_with_rela): Remove.  Change all
	callers to use add_local_pair_with_rel.
	(Output_data_got::reserve_local): Change object to Relobj*.
	* output.h: (class Output_data_reloc_generic): Add pure virtual
	declarations for add_global_generic, add_local_generic,
	add_output_section_generic.
	(class Output_data_reloc) [SHT_REL, SHT_RELA]: Implement new
	functions for Output_data_reloc_generic.  Update declarations for
	changes listed in output.cc.
	(class Output_data_got): Change template parameter to got_size.
	Don't define Rel_dyn or Rela_dyn.  Update declarations per above.
	* incremental.h (Sized_relobj_incr::do_local_symbol_value): New
	function.
	(Sized_relobj_incr::do_local_plt_offset): New function.
	* copy-relocs.cc (Copy_relocs::Copy_reloc_entry::emit): Call
	add_global_generic.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 45889 bytes --]

Index: copy-relocs.cc
===================================================================
RCS file: /cvs/src/src/gold/copy-relocs.cc,v
retrieving revision 1.14
diff -p -u -r1.14 copy-relocs.cc
--- copy-relocs.cc	8 Jun 2011 03:50:10 -0000	1.14
+++ copy-relocs.cc	17 Dec 2011 06:16:38 -0000
@@ -1,6 +1,6 @@
 // copy-relocs.cc -- handle COPY relocations for gold.
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -41,10 +41,10 @@ Copy_relocs<sh_type, size, big_endian>::
   // emitted a COPY relocation, and we do not want to emit this
   // dynamic relocation.
   if (this->sym_->is_from_dynobj())
-    reloc_section->add_global(this->sym_, this->reloc_type_,
-			      this->output_section_, this->relobj_,
-			      this->shndx_, this->address_,
-			      this->addend_);
+    reloc_section->add_global_generic(this->sym_, this->reloc_type_,
+				      this->output_section_, this->relobj_,
+				      this->shndx_, this->address_,
+				      this->addend_);
 }
 
 // Copy_relocs methods.
@@ -115,7 +115,8 @@ Copy_relocs<sh_type, size, big_endian>::
   symtab->define_with_copy_reloc(sym, posd, offset);
 
   // Add the COPY relocation to the dynamic reloc section.
-  reloc_section->add_global(sym, this->copy_reloc_type_, posd, offset, 0);
+  reloc_section->add_global_generic(sym, this->copy_reloc_type_, posd,
+				    offset, 0);
 }
 
 // Make a COPY relocation for SYM and emit it.
Index: expression.cc
===================================================================
RCS file: /cvs/src/src/gold/expression.cc,v
retrieving revision 1.19
diff -p -u -r1.19 expression.cc
--- expression.cc	31 Oct 2011 22:51:03 -0000	1.19
+++ expression.cc	17 Dec 2011 06:16:38 -0000
@@ -1,6 +1,6 @@
 // expression.cc -- expressions in linker scripts for gold
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
Index: incremental.h
===================================================================
RCS file: /cvs/src/src/gold/incremental.h,v
retrieving revision 1.29
diff -p -u -r1.29 incremental.h
--- incremental.h	10 Oct 2011 17:38:07 -0000	1.29
+++ incremental.h	17 Dec 2011 06:16:39 -0000
@@ -1,6 +1,6 @@
 // inremental.h -- incremental linking support for gold   -*- C++ -*-
 
-// Copyright 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Mikolaj Zalewski <mikolajz@google.com>.
 
 // This file is part of gold.
@@ -1924,6 +1924,15 @@ class Sized_relobj_incr : public Sized_r
   do_get_global_symbols() const
   { return &this->symbols_; }
 
+  // Return the value of a local symbol.
+  uint64_t
+  do_local_symbol_value(unsigned int, uint64_t) const
+  { gold_unreachable(); }
+
+  unsigned int
+  do_local_plt_offset(unsigned int) const
+  { gold_unreachable(); }
+
   // Return the number of local symbols.
   unsigned int
   do_local_symbol_count() const
Index: object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.150
diff -p -u -r1.150 object.cc
--- object.cc	18 Sep 2011 15:06:28 -0000	1.150
+++ object.cc	17 Dec 2011 06:16:39 -0000
@@ -1819,7 +1819,8 @@ Sized_relobj_file<size, big_endian>::loc
 
 template<int size, bool big_endian>
 unsigned int
-Sized_relobj_file<size, big_endian>::local_plt_offset(unsigned int symndx) const
+Sized_relobj_file<size, big_endian>::do_local_plt_offset(
+    unsigned int symndx) const
 {
   typename Local_plt_offsets::const_iterator p =
     this->local_plt_offsets_.find(symndx);
Index: object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.113
diff -p -u -r1.113 object.h
--- object.h	1 Aug 2011 18:25:21 -0000	1.113
+++ object.h	17 Dec 2011 06:16:39 -0000
@@ -1009,6 +1009,39 @@ class Relobj : public Object
   scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
   { return this->do_scan_relocs(symtab, layout, rd); }
 
+  // Return the value of the local symbol whose index is SYMNDX, plus
+  // ADDEND.  ADDEND is passed in so that we can correctly handle the
+  // section symbol for a merge section.
+  uint64_t
+  local_symbol_value(unsigned int symndx, uint64_t addend) const
+  { return this->do_local_symbol_value(symndx, addend); }
+
+  // Return the PLT offset for a local symbol.  It is an error to call
+  // this if it doesn't have one.
+  unsigned int
+  local_plt_offset(unsigned int symndx) const
+  { return this->do_local_plt_offset(symndx); }
+
+  // Return whether the local symbol SYMNDX has a GOT offset of type
+  // GOT_TYPE.
+  bool
+  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+  { return this->do_local_has_got_offset(symndx, got_type); }
+
+  // Return the GOT offset of type GOT_TYPE of the local symbol
+  // SYMNDX.  It is an error to call this if the symbol does not have
+  // a GOT offset of the specified type.
+  unsigned int
+  local_got_offset(unsigned int symndx, unsigned int got_type) const
+  { return this->do_local_got_offset(symndx, got_type); }
+
+  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+  // to GOT_OFFSET.
+  void
+  set_local_got_offset(unsigned int symndx, unsigned int got_type,
+		       unsigned int got_offset)
+  { this->do_set_local_got_offset(symndx, got_type, got_offset); }
+
   // The number of local symbols in the input symbol table.
   virtual unsigned int
   local_symbol_count() const
@@ -1167,6 +1200,28 @@ class Relobj : public Object
   virtual void
   do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
 
+  // Return the value of a local symbol.
+  virtual uint64_t
+  do_local_symbol_value(unsigned int symndx, uint64_t addend) const = 0;
+
+  // Return the PLT offset of a local symbol.
+  virtual unsigned int
+  do_local_plt_offset(unsigned int symndx) const = 0;
+
+  // Return whether a local symbol has a GOT offset of a given type.
+  virtual bool
+  do_local_has_got_offset(unsigned int symndx,
+			  unsigned int got_type) const = 0;
+
+  // Return the GOT offset of a given type of a local symbol.
+  virtual unsigned int
+  do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
+
+  // Set the GOT offset with a given type for a local symbol.
+  virtual void
+  do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+			  unsigned int got_offset) = 0;
+
   // Return the number of local symbols--implemented by child class.
   virtual unsigned int
   do_local_symbol_count() const = 0;
@@ -1775,47 +1830,6 @@ class Sized_relobj : public Relobj
     return this->section_offsets_[shndx];
   }
 
-  // Return whether the local symbol SYMNDX has a GOT offset.
-  // For TLS symbols, the GOT entry will hold its tp-relative offset.
-  bool
-  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
-  {
-    Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
-    return (p != this->local_got_offsets_.end()
-            && p->second->get_offset(got_type) != -1U);
-  }
-
-  // Return the GOT offset of the local symbol SYMNDX.
-  unsigned int
-  local_got_offset(unsigned int symndx, unsigned int got_type) const
-  {
-    Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
-    gold_assert(p != this->local_got_offsets_.end());
-    unsigned int off = p->second->get_offset(got_type);
-    gold_assert(off != -1U);
-    return off;
-  }
-
-  // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
-  void
-  set_local_got_offset(unsigned int symndx, unsigned int got_type,
-                       unsigned int got_offset)
-  {
-    Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
-    if (p != this->local_got_offsets_.end())
-      p->second->set_offset(got_type, got_offset);
-    else
-      {
-        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
-        std::pair<Local_got_offsets::iterator, bool> ins =
-            this->local_got_offsets_.insert(std::make_pair(symndx, g));
-        gold_assert(ins.second);
-      }
-  }
-
   // Iterate over local symbols, calling a visitor class V for each GOT offset
   // associated with a local symbol.
   void
@@ -1855,6 +1869,49 @@ class Sized_relobj : public Relobj
        : convert_types<Address, uint64_t>(off));
   }
 
+  // Return whether the local symbol SYMNDX has a GOT offset of type
+  // GOT_TYPE.
+  bool
+  do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    return (p != this->local_got_offsets_.end()
+            && p->second->get_offset(got_type) != -1U);
+  }
+
+  // Return the GOT offset of type GOT_TYPE of the local symbol
+  // SYMNDX.
+  unsigned int
+  do_local_got_offset(unsigned int symndx, unsigned int got_type) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    gold_assert(p != this->local_got_offsets_.end());
+    unsigned int off = p->second->get_offset(got_type);
+    gold_assert(off != -1U);
+    return off;
+  }
+
+  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+  // to GOT_OFFSET.
+  void
+  do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+			  unsigned int got_offset)
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    if (p != this->local_got_offsets_.end())
+      p->second->set_offset(got_type, got_offset);
+    else
+      {
+        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+        std::pair<Local_got_offsets::iterator, bool> ins =
+            this->local_got_offsets_.insert(std::make_pair(symndx, g));
+        gold_assert(ins.second);
+      }
+  }
+
  private:
   // The GOT offsets of local symbols. This map also stores GOT offsets
   // for tp-relative offsets for TLS symbols.
@@ -2000,11 +2057,6 @@ class Sized_relobj_file : public Sized_r
   bool
   local_has_plt_offset(unsigned int symndx) const;
 
-  // Return the PLT offset for a local symbol.  It is an error to call
-  // this if it doesn't have one.
-  unsigned int
-  local_plt_offset(unsigned int symndx) const;
-
   // Set the PLT offset of the local symbol SYMNDX.
   void
   set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
@@ -2050,6 +2102,19 @@ class Sized_relobj_file : public Sized_r
   void
   do_read_symbols(Read_symbols_data*);
 
+  // Return the value of a local symbol.
+  uint64_t
+  do_local_symbol_value(unsigned int symndx, uint64_t addend) const
+  {
+    const Symbol_value<size>* symval = this->local_symbol(symndx);
+    return symval->value(this, addend);
+  }
+
+  // Return the PLT offset for a local symbol.  It is an error to call
+  // this if it doesn't have one.
+  unsigned int
+  do_local_plt_offset(unsigned int symndx) const;
+
   // Return the number of local symbols.
   unsigned int
   do_local_symbol_count() const
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.163
diff -p -u -r1.163 output.cc
--- output.cc	18 Oct 2011 21:36:29 -0000	1.163
+++ output.cc	17 Dec 2011 06:16:41 -0000
@@ -1387,11 +1387,13 @@ Output_data_got<size, big_endian>::Got_e
 
     default:
       {
-	const Sized_relobj_file<size, big_endian>* object = this->u_.object;
+	const Relobj* object = this->u_.object;
         const unsigned int lsi = this->local_sym_index_;
-        const Symbol_value<size>* symval = object->local_symbol(lsi);
 	if (!this->use_plt_offset_)
-	  val = symval->value(this->u_.object, 0);
+	  {
+	    uint64_t lval = object->local_symbol_value(lsi, 0);
+	    val = convert_types<Valtype, uint64_t>(lval);
+	  }
 	else
 	  {
 	    uint64_t plt_address =
@@ -1448,23 +1450,7 @@ void
 Output_data_got<size, big_endian>::add_global_with_rel(
     Symbol* gsym,
     unsigned int got_type,
-    Rel_dyn* rel_dyn,
-    unsigned int r_type)
-{
-  if (gsym->has_got_offset(got_type))
-    return;
-
-  unsigned int got_offset = this->add_got_entry(Got_entry());
-  gsym->set_got_offset(got_type, got_offset);
-  rel_dyn->add_global(gsym, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_with_rela(
-    Symbol* gsym,
-    unsigned int got_type,
-    Rela_dyn* rela_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type)
 {
   if (gsym->has_got_offset(got_type))
@@ -1472,7 +1458,7 @@ Output_data_got<size, big_endian>::add_g
 
   unsigned int got_offset = this->add_got_entry(Got_entry());
   gsym->set_got_offset(got_type, got_offset);
-  rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
+  rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0);
 }
 
 // Add a pair of entries for a global symbol to the GOT, and add
@@ -1483,27 +1469,7 @@ void
 Output_data_got<size, big_endian>::add_global_pair_with_rel(
     Symbol* gsym,
     unsigned int got_type,
-    Rel_dyn* rel_dyn,
-    unsigned int r_type_1,
-    unsigned int r_type_2)
-{
-  if (gsym->has_got_offset(got_type))
-    return;
-
-  unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
-  gsym->set_got_offset(got_type, got_offset);
-  rel_dyn->add_global(gsym, r_type_1, this, got_offset);
-
-  if (r_type_2 != 0)
-    rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_pair_with_rela(
-    Symbol* gsym,
-    unsigned int got_type,
-    Rela_dyn* rela_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type_1,
     unsigned int r_type_2)
 {
@@ -1512,10 +1478,11 @@ Output_data_got<size, big_endian>::add_g
 
   unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
   gsym->set_got_offset(got_type, got_offset);
-  rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
+  rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+    rel_dyn->add_global_generic(gsym, r_type_2, this,
+				got_offset + size / 8, 0);
 }
 
 // Add an entry for a local symbol to the GOT.  This returns true if
@@ -1525,7 +1492,7 @@ Output_data_got<size, big_endian>::add_g
 template<int size, bool big_endian>
 bool
 Output_data_got<size, big_endian>::add_local(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int got_type)
 {
@@ -1543,7 +1510,7 @@ Output_data_got<size, big_endian>::add_l
 template<int size, bool big_endian>
 bool
 Output_data_got<size, big_endian>::add_local_plt(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int got_type)
 {
@@ -1562,27 +1529,10 @@ Output_data_got<size, big_endian>::add_l
 template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::add_local_with_rel(
-    Sized_relobj_file<size, big_endian>* object,
-    unsigned int symndx,
-    unsigned int got_type,
-    Rel_dyn* rel_dyn,
-    unsigned int r_type)
-{
-  if (object->local_has_got_offset(symndx, got_type))
-    return;
-
-  unsigned int got_offset = this->add_got_entry(Got_entry());
-  object->set_local_got_offset(symndx, got_type, got_offset);
-  rel_dyn->add_local(object, symndx, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_with_rela(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int got_type,
-    Rela_dyn* rela_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type)
 {
   if (object->local_has_got_offset(symndx, got_type))
@@ -1590,7 +1540,7 @@ Output_data_got<size, big_endian>::add_l
 
   unsigned int got_offset = this->add_got_entry(Got_entry());
   object->set_local_got_offset(symndx, got_type, got_offset);
-  rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
+  rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
 }
 
 // Add a pair of entries for a local symbol to the GOT, and add
@@ -1599,36 +1549,11 @@ Output_data_got<size, big_endian>::add_l
 template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::add_local_pair_with_rel(
-    Sized_relobj_file<size, big_endian>* object,
-    unsigned int symndx,
-    unsigned int shndx,
-    unsigned int got_type,
-    Rel_dyn* rel_dyn,
-    unsigned int r_type_1,
-    unsigned int r_type_2)
-{
-  if (object->local_has_got_offset(symndx, got_type))
-    return;
-
-  unsigned int got_offset =
-      this->add_got_entry_pair(Got_entry(),
-			       Got_entry(object, symndx, false));
-  object->set_local_got_offset(symndx, got_type, got_offset);
-  Output_section* os = object->output_section(shndx);
-  rel_dyn->add_output_section(os, r_type_1, this, got_offset);
-
-  if (r_type_2 != 0)
-    rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_pair_with_rela(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int shndx,
     unsigned int got_type,
-    Rela_dyn* rela_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type_1,
     unsigned int r_type_2)
 {
@@ -1640,10 +1565,11 @@ Output_data_got<size, big_endian>::add_l
 			       Got_entry(object, symndx, false));
   object->set_local_got_offset(symndx, got_type, got_offset);
   Output_section* os = object->output_section(shndx);
-  rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
+  rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+    rel_dyn->add_output_section_generic(os, r_type_2, this,
+					got_offset + size / 8, 0);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1652,7 +1578,7 @@ template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::reserve_local(
     unsigned int i,
-    Sized_relobj<size, big_endian>* object,
+    Relobj* object,
     unsigned int sym_index,
     unsigned int got_type)
 {
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.131
diff -p -u -r1.131 output.h
--- output.h	16 Dec 2011 23:47:03 -0000	1.131
+++ output.h	17 Dec 2011 06:16:41 -0000
@@ -1397,6 +1397,55 @@ class Output_data_reloc_generic : public
   sort_relocs() const
   { return this->sort_relocs_; }
 
+  // Add a reloc of type TYPE against the global symbol GSYM.  The
+  // relocation applies to the data at offset ADDRESS within OD.
+  virtual void
+  add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+		     uint64_t address, uint64_t addend) = 0;
+
+  // Add a reloc of type TYPE against the global symbol GSYM.  The
+  // relocation applies to data at offset ADDRESS within section SHNDX
+  // of object file RELOBJ.  OD is the associated output section.
+  virtual void
+  add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+		     Relobj* relobj, unsigned int shndx, uint64_t address,
+		     uint64_t addend) = 0;
+
+  // Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX
+  // in RELOBJ.  The relocation applies to the data at offset ADDRESS
+  // within OD.
+  virtual void
+  add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+		    unsigned int type, Output_data* od, uint64_t address,
+		    uint64_t addend) = 0;
+
+  // Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX
+  // in RELOBJ.  The relocation applies to the data at offset ADDRESS
+  // within section SHNDX of RELOBJ.  OD is the associated output
+  // section.
+  virtual void
+  add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+		    unsigned int type, Output_data* od, unsigned int shndx,
+		    uint64_t address, uint64_t addend) = 0;
+
+  // Add a reloc of type TYPE against the STT_SECTION symbol of the
+  // output section OS.  The relocation applies to the data at offset
+  // ADDRESS within OD.
+  virtual void
+  add_output_section_generic(Output_section *os, unsigned int type,
+			     Output_data* od, uint64_t address,
+			     uint64_t addend) = 0;
+
+  // Add a reloc of type TYPE against the STT_SECTION symbol of the
+  // output section OS.  The relocation applies to the data at offset
+  // ADDRESS within section SHNDX of RELOBJ.  OD is the associated
+  // output section.
+  virtual void
+  add_output_section_generic(Output_section* os, unsigned int type,
+			     Output_data* od, Relobj* relobj,
+			     unsigned int shndx, uint64_t address,
+			     uint64_t addend) = 0;
+
  protected:
   // Note that we've added another relative reloc.
   void
@@ -1518,23 +1567,27 @@ class Output_data_reloc<elfcpp::SHT_REL,
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     false, false)); }
 
-  // These are to simplify the Copy_relocs class.
-
   void
-  add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address,
-	     Address addend)
+  add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+		     uint64_t address, uint64_t addend)
   {
     gold_assert(addend == 0);
-    this->add_global(gsym, type, od, address);
+    this->add(od, Output_reloc_type(gsym, type, od,
+				    convert_types<Address, uint64_t>(address),
+				    false, false));
   }
 
   void
-  add_global(Symbol* gsym, unsigned int type, Output_data* od,
-             Sized_relobj<size, big_endian>* relobj,
-	     unsigned int shndx, Address address, Address addend)
+  add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+		     Relobj* relobj, unsigned int shndx, uint64_t address,
+		     uint64_t addend)
   {
     gold_assert(addend == 0);
-    this->add_global(gsym, type, od, relobj, shndx, address);
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian>*>(relobj);
+    this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
+				    convert_types<Address, uint64_t>(address),
+				    false, false));
   }
 
   // Add a RELATIVE reloc against a global symbol.  The final relocation
@@ -1592,6 +1645,32 @@ class Output_data_reloc<elfcpp::SHT_REL,
 				    address, false, false, false, false));
   }
 
+  void
+  add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+		    unsigned int type, Output_data* od, uint64_t address,
+		    uint64_t addend)
+  {
+    gold_assert(addend == 0);
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian> *>(relobj);
+    this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od,
+				    convert_types<Address, uint64_t>(address),
+				    false, false, false, false));
+  }
+
+  void
+  add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+		    unsigned int type, Output_data* od, unsigned int shndx,
+		    uint64_t address, uint64_t addend)
+  {
+    gold_assert(addend == 0);
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian>*>(relobj);
+    this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx,
+				    convert_types<Address, uint64_t>(address),
+				    false, false, false, false));
+  }
+
   // Add a RELATIVE reloc against a local symbol.
 
   void
@@ -1671,6 +1750,29 @@ class Output_data_reloc<elfcpp::SHT_REL,
                      unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
 
+  void
+  add_output_section_generic(Output_section* os, unsigned int type,
+			     Output_data* od, uint64_t address,
+			     uint64_t addend)
+  {
+    gold_assert(addend == 0);
+    this->add(od, Output_reloc_type(os, type, od,
+				    convert_types<Address, uint64_t>(address)));
+  }
+
+  void
+  add_output_section_generic(Output_section* os, unsigned int type,
+			     Output_data* od, Relobj* relobj,
+			     unsigned int shndx, uint64_t address,
+			     uint64_t addend)
+  {
+    gold_assert(addend == 0);
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian>*>(relobj);
+    this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
+				    convert_types<Address, uint64_t>(address)));
+  }
+
   // Add an absolute relocation.
 
   void
@@ -1733,6 +1835,29 @@ class Output_data_reloc<elfcpp::SHT_RELA
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     addend, false, false)); }
 
+  void
+  add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+		     uint64_t address, uint64_t addend)
+  {
+    this->add(od, Output_reloc_type(gsym, type, od,
+				    convert_types<Address, uint64_t>(address),
+				    convert_types<Addend, uint64_t>(addend),
+				    false, false));
+  }
+
+  void
+  add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+		     Relobj* relobj, unsigned int shndx, uint64_t address,
+		     uint64_t addend)
+  {
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian>*>(relobj);
+    this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
+				    convert_types<Address, uint64_t>(address),
+				    convert_types<Addend, uint64_t>(addend),
+				    false, false));
+  }
+
   // Add a RELATIVE reloc against a global symbol.  The final output
   // relocation will not reference the symbol, but we must keep the symbol
   // information long enough to set the addend of the relocation correctly
@@ -1790,6 +1915,32 @@ class Output_data_reloc<elfcpp::SHT_RELA
                                     false));
   }
 
+  void
+  add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+		    unsigned int type, Output_data* od, uint64_t address,
+		    uint64_t addend)
+  {
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian> *>(relobj);
+    this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od,
+				    convert_types<Address, uint64_t>(address),
+				    convert_types<Addend, uint64_t>(addend),
+				    false, false, false, false));
+  }
+
+  void
+  add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+		    unsigned int type, Output_data* od, unsigned int shndx,
+		    uint64_t address, uint64_t addend)
+  {
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian>*>(relobj);
+    this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx,
+				    convert_types<Address, uint64_t>(address),
+				    convert_types<Addend, uint64_t>(addend),
+				    false, false, false, false));
+  }
+
   // Add a RELATIVE reloc against a local symbol.
 
   void
@@ -1875,6 +2026,29 @@ class Output_data_reloc<elfcpp::SHT_RELA
   { this->add(od, Output_reloc_type(os, type, relobj, shndx, address,
                                     addend)); }
 
+  void
+  add_output_section_generic(Output_section* os, unsigned int type,
+			     Output_data* od, uint64_t address,
+			     uint64_t addend)
+  {
+    this->add(od, Output_reloc_type(os, type, od,
+				    convert_types<Address, uint64_t>(address),
+				    convert_types<Addend, uint64_t>(addend)));
+  }
+
+  void
+  add_output_section_generic(Output_section* os, unsigned int type,
+			     Output_data* od, Relobj* relobj,
+			     unsigned int shndx, uint64_t address,
+			     uint64_t addend)
+  {
+    Sized_relobj<size, big_endian>* sized_relobj =
+      static_cast<Sized_relobj<size, big_endian>*>(relobj);
+    this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
+				    convert_types<Address, uint64_t>(address),
+				    convert_types<Addend, uint64_t>(addend)));
+  }
+
   // Add an absolute relocation.
 
   void
@@ -1974,29 +2148,28 @@ class Output_data_group : public Output_
 // Output_data_got is used to manage a GOT.  Each entry in the GOT is
 // for one symbol--either a global symbol or a local symbol in an
 // object.  The target specific code adds entries to the GOT as
-// needed.
+// needed.  The GOT_SIZE template parameter is the size in bits of a
+// GOT entry, typically 32 or 64.
 
-template<int size, bool big_endian>
+template<int got_size, bool big_endian>
 class Output_data_got : public Output_section_data_build
 {
  public:
-  typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
-  typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
-  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
+  typedef typename elfcpp::Elf_types<got_size>::Elf_Addr Valtype;
 
   Output_data_got()
-    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
+    : Output_section_data_build(Output_data::default_alignment_for_size(got_size)),
       entries_(), free_list_()
   { }
 
   Output_data_got(off_t data_size)
     : Output_section_data_build(data_size,
-				Output_data::default_alignment_for_size(size)),
+				Output_data::default_alignment_for_size(got_size)),
       entries_(), free_list_()
   {
     // For an incremental update, we have an existing GOT section.
     // Initialize the list of entries and the free list.
-    this->entries_.resize(data_size / (size / 8));
+    this->entries_.resize(data_size / (got_size / 8));
     this->free_list_.init(data_size, false);
   }
 
@@ -2014,62 +2187,39 @@ class Output_data_got : public Output_se
   // relocation of type R_TYPE for the GOT entry.
   void
   add_global_with_rel(Symbol* gsym, unsigned int got_type,
-                      Rel_dyn* rel_dyn, unsigned int r_type);
-
-  void
-  add_global_with_rela(Symbol* gsym, unsigned int got_type,
-                       Rela_dyn* rela_dyn, unsigned int r_type);
+                      Output_data_reloc_generic* rel_dyn, unsigned int r_type);
 
   // Add a pair of entries for a global symbol to the GOT, and add
   // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
   void
   add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
-                           Rel_dyn* rel_dyn, unsigned int r_type_1,
-                           unsigned int r_type_2);
-
-  void
-  add_global_pair_with_rela(Symbol* gsym, unsigned int got_type,
-                            Rela_dyn* rela_dyn, unsigned int r_type_1,
-                            unsigned int r_type_2);
+                           Output_data_reloc_generic* rel_dyn,
+			   unsigned int r_type_1, unsigned int r_type_2);
 
   // Add an entry for a local symbol to the GOT.  This returns true if
   // this is a new GOT entry, false if the symbol already has a GOT
   // entry.
   bool
-  add_local(Sized_relobj_file<size, big_endian>* object, unsigned int sym_index,
-            unsigned int got_type);
+  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type);
 
   // Like add_local, but use the PLT offset of the local symbol if it
   // has one.
   bool
-  add_local_plt(Sized_relobj_file<size, big_endian>* object,
-		unsigned int sym_index,
-		unsigned int got_type);
+  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type);
 
   // Add an entry for a local symbol to the GOT, and add a dynamic
   // relocation of type R_TYPE for the GOT entry.
   void
-  add_local_with_rel(Sized_relobj_file<size, big_endian>* object,
-                     unsigned int sym_index, unsigned int got_type,
-                     Rel_dyn* rel_dyn, unsigned int r_type);
-
-  void
-  add_local_with_rela(Sized_relobj_file<size, big_endian>* object,
-                      unsigned int sym_index, unsigned int got_type,
-                      Rela_dyn* rela_dyn, unsigned int r_type);
+  add_local_with_rel(Relobj* object, unsigned int sym_index,
+		     unsigned int got_type, Output_data_reloc_generic* rel_dyn,
+		     unsigned int r_type);
 
   // Add a pair of entries for a local symbol to the GOT, and add
   // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
   void
-  add_local_pair_with_rel(Sized_relobj_file<size, big_endian>* object,
-                          unsigned int sym_index, unsigned int shndx,
-                          unsigned int got_type, Rel_dyn* rel_dyn,
-                          unsigned int r_type_1, unsigned int r_type_2);
-
-  void
-  add_local_pair_with_rela(Sized_relobj_file<size, big_endian>* object,
-                          unsigned int sym_index, unsigned int shndx,
-                          unsigned int got_type, Rela_dyn* rela_dyn,
+  add_local_pair_with_rel(Relobj* object, unsigned int sym_index,
+			  unsigned int shndx, unsigned int got_type,
+			  Output_data_reloc_generic* rel_dyn,
                           unsigned int r_type_1, unsigned int r_type_2);
 
   // Add a constant to the GOT.  This returns the offset of the new
@@ -2084,12 +2234,12 @@ class Output_data_got : public Output_se
   // Reserve a slot in the GOT.
   void
   reserve_slot(unsigned int i)
-  { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
+  { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
 
   // Reserve a slot in the GOT for a local symbol.
   void
-  reserve_local(unsigned int i, Sized_relobj<size, big_endian>* object,
-		unsigned int sym_index, unsigned int got_type);
+  reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
+		unsigned int got_type);
 
   // Reserve a slot in the GOT for a global symbol.
   void
@@ -2121,8 +2271,8 @@ class Output_data_got : public Output_se
     { this->u_.gsym = gsym; }
 
     // Create a local symbol entry.
-    Got_entry(Sized_relobj_file<size, big_endian>* object,
-              unsigned int local_sym_index, bool use_plt_offset)
+    Got_entry(Relobj* object, unsigned int local_sym_index,
+	      bool use_plt_offset)
       : local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset)
     {
       gold_assert(local_sym_index != GSYM_CODE
@@ -2153,7 +2303,7 @@ class Output_data_got : public Output_se
     union
     {
       // For a local symbol, the object.
-      Sized_relobj_file<size, big_endian>* object;
+      Relobj* object;
       // For a global symbol, the symbol.
       Symbol* gsym;
       // For a constant, the constant.
@@ -2179,7 +2329,7 @@ class Output_data_got : public Output_se
   // Return the offset into the GOT of GOT entry I.
   unsigned int
   got_offset(unsigned int i) const
-  { return i * (size / 8); }
+  { return i * (got_size / 8); }
 
   // Return the offset into the GOT of the last entry added.
   unsigned int
Index: powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.40
diff -p -u -r1.40 powerpc.cc
--- powerpc.cc	10 Oct 2011 17:29:52 -0000	1.40
+++ powerpc.cc	17 Dec 2011 06:16:41 -0000
@@ -1566,8 +1566,8 @@ Target_powerpc<size, big_endian>::Scan::
             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);
+              got->add_global_with_rel(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);
Index: sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.50
diff -p -u -r1.50 sparc.cc
--- sparc.cc	19 Oct 2011 00:32:24 -0000	1.50
+++ sparc.cc	17 Dec 2011 06:16:41 -0000
@@ -1998,14 +1998,14 @@ Target_sparc<size, big_endian>::Scan::lo
 		  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);
+		  got->add_local_pair_with_rel(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);
 	      }
@@ -2339,8 +2339,8 @@ Target_sparc<size, big_endian>::Scan::gl
             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);
+              got->add_global_with_rel(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);
@@ -2389,14 +2389,14 @@ Target_sparc<size, big_endian>::Scan::gl
                 // 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));
+                got->add_global_pair_with_rel(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)
@@ -2407,11 +2407,11 @@ Target_sparc<size, big_endian>::Scan::gl
                 // 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));
+                got->add_global_with_rel(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);
@@ -2462,11 +2462,11 @@ Target_sparc<size, big_endian>::Scan::gl
 		// 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));
+		got->add_global_with_rel(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);
Index: x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.141
diff -p -u -r1.141 x86_64.cc
--- x86_64.cc	31 Oct 2011 22:33:04 -0000	1.141
+++ x86_64.cc	17 Dec 2011 06:16:42 -0000
@@ -2137,11 +2137,11 @@ Target_x86_64::Scan::local(Symbol_table*
 		  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);
+		  got->add_local_pair_with_rel(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);
@@ -2207,9 +2207,9 @@ Target_x86_64::Scan::local(Symbol_table*
 	        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);
+	        got->add_local_with_rel(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);
@@ -2481,8 +2481,8 @@ Target_x86_64::Scan::global(Symbol_table
 		    && parameters->options().shared())
 		|| (gsym->type() == elfcpp::STT_GNU_IFUNC
 		    && parameters->options().output_is_position_independent()))
-              got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
-                                        elfcpp::R_X86_64_GLOB_DAT);
+              got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+				       elfcpp::R_X86_64_GLOB_DAT);
             else
               {
 		// For a STT_GNU_IFUNC symbol we want to write the PLT
@@ -2580,19 +2580,19 @@ Target_x86_64::Scan::global(Symbol_table
                 // 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);
+                got->add_global_pair_with_rel(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);
+                got->add_global_with_rel(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);
@@ -2613,17 +2613,17 @@ Target_x86_64::Scan::global(Symbol_table
 		target->got_section(symtab, layout);
                 Output_data_got<64, false>* got = target->got_tlsdesc_section();
 		Reloc_section* rt = target->rela_tlsdesc_section(layout);
-                got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
-                                               elfcpp::R_X86_64_TLSDESC, 0);
+                got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
+					      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);
+                got->add_global_with_rel(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);
@@ -2653,9 +2653,9 @@ Target_x86_64::Scan::global(Symbol_table
 	        // 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);
+	        got->add_global_with_rel(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);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2011-12-17  6:33                 ` Ian Lance Taylor
@ 2011-12-17 17:11                   ` H.J. Lu
       [not found]                     ` <CAKOQZ8zjAStMvF0Di2V0tmbXSaJYgOx9uE3tYCW_CDS2n5-AkA@mail.gmail.com>
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2011-12-17 17:11 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

On Fri, Dec 16, 2011 at 10:32 PM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
>> Given that it is very unlikely I can remove all dependencies on the ELF
>> class from Output_data_got, I will prepare a patch to add a new
>> parameter to class templates for GOT entry size.
>
> OK, I did it for you.  This patch changes Output_data_got to use a
> template parameter of got_size rather than size.  I added virtual
> functions and adjusted as necessary.  Committed to mainline.
>
> Ian
>
>

It doesn't work.  target.h has

template<int size, bool big_endian>
class Sized_target : public Target
{
...
  virtual Output_data_got<size, big_endian>*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  init_got_plt_for_update(Symbol_table*,
                          Layout*,
                          unsigned int /* got_count */,
                          unsigned int /* plt_count */)
  { gold_unreachable(); }
...

Here ELF class size is used for GOT entry size.

-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
       [not found]                     ` <CAKOQZ8zjAStMvF0Di2V0tmbXSaJYgOx9uE3tYCW_CDS2n5-AkA@mail.gmail.com>
@ 2012-01-02 17:09                       ` H.J. Lu
  2012-01-02 18:27                         ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: H.J. Lu @ 2012-01-02 17:09 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: binutils

On Sat, Dec 17, 2011 at 2:06 PM, Ian Lance Taylor <iant@google.com> wrote:
>
> On Dec 17, 2011 9:11 AM, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>
>> On Fri, Dec 16, 2011 at 10:32 PM, Ian Lance Taylor <iant@google.com>
>> wrote:
>> > "H.J. Lu" <hjl.tools@gmail.com> writes:
>> >
>> >> Given that it is very unlikely I can remove all dependencies on the ELF
>> >> class from Output_data_got, I will prepare a patch to add a new
>> >> parameter to class templates for GOT entry size.
>> >
>> > OK, I did it for you.  This patch changes Output_data_got to use a
>> > template parameter of got_size rather than size.  I added virtual
>> > functions and adjusted as necessary.  Committed to mainline.
>> >
>> > Ian
>> >
>> >
>>
>> It doesn't work.  target.h has
>>
>> template<int size, bool big_endian>
>> class Sized_target : public Target
>> {
>> ...
>>  virtual Output_data_got<size, big_endian>*
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>  init_got_plt_for_update(Symbol_table*,
>>                          Layout*,
>>                          unsigned int /* got_count */,
>>                          unsigned int /* plt_count */)
>>  { gold_unreachable(); }
>> ...
>>
>> Here ELF class size is used for GOT entry size.
>
> The incremental linker is work in progress.
>

Do you have any suggestions how to address this?

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2012-01-02 17:09                       ` H.J. Lu
@ 2012-01-02 18:27                         ` Ian Lance Taylor
  2012-01-03 23:24                           ` Cary Coutant
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2012-01-02 18:27 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, ccoutant

"H.J. Lu" <hjl.tools@gmail.com> writes:

>>> It doesn't work.  target.h has
>>>
>>> template<int size, bool big_endian>
>>> class Sized_target : public Target
>>> {
>>> ...
>>>  virtual Output_data_got<size, big_endian>*
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>  init_got_plt_for_update(Symbol_table*,
>>>                          Layout*,
>>>                          unsigned int /* got_count */,
>>>                          unsigned int /* plt_count */)
>>>  { gold_unreachable(); }
>>> ...
>>>
>>> Here ELF class size is used for GOT entry size.
>>
>> The incremental linker is work in progress.
>>
>
> Do you have any suggestions how to address this?

Cary, CC'ed, has been working on the incremental linker.

Fundamentally the generic incremental linker code in incremental.cc is
going to have to ask the target for the size of a GOT entry.  That is
true under any possible scheme.  This could be done by making
Output_data_got a virtual class, or via some other scheme.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2012-01-02 18:27                         ` Ian Lance Taylor
@ 2012-01-03 23:24                           ` Cary Coutant
  2012-01-04  0:01                             ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: Cary Coutant @ 2012-01-03 23:24 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: H.J. Lu, binutils

[-- Attachment #1: Type: text/plain, Size: 988 bytes --]

> Fundamentally the generic incremental linker code in incremental.cc is
> going to have to ask the target for the size of a GOT entry.  That is
> true under any possible scheme.  This could be done by making
> Output_data_got a virtual class, or via some other scheme.

This patch adds an abstract base class so that do_process_got_plt()
doesn't need to know the size of the GOT entries. OK to commit?

-cary


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.

[-- Attachment #2: gold-got-size-patch.txt --]
[-- Type: text/plain, Size: 5875 bytes --]

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.


commit 5a692679e63392dc2d7dbeb74d666578d633cdd6
Author: Cary Coutant <ccoutant@google.com>
Date:   Tue Jan 3 15:17:40 2012 -0800

    Make size of GOT entry independent of ELF size.

diff --git a/gold/incremental.cc b/gold/incremental.cc
index 75e44c5..39bad37 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -632,7 +632,7 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
   // Tell the target how big the GOT and PLT sections are.
   unsigned int got_count = got_plt_reader.get_got_entry_count();
   unsigned int plt_count = got_plt_reader.get_plt_entry_count();
-  Output_data_got<size, big_endian>* got =
+  Output_data_got_base* got =
       target->init_got_plt_for_update(symtab, layout, got_count, plt_count);
 
   // Read the GOT entries from the base file and build the outgoing GOT.
diff --git a/gold/output.cc b/gold/output.cc
index 6e46fd5..ca19039 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1582,7 +1582,7 @@ Output_data_got<size, big_endian>::reserve_local(
     unsigned int sym_index,
     unsigned int got_type)
 {
-  this->reserve_slot(i);
+  this->do_reserve_slot(i);
   object->set_local_got_offset(sym_index, got_type, this->got_offset(i));
 }
 
@@ -1595,7 +1595,7 @@ Output_data_got<size, big_endian>::reserve_global(
     Symbol* gsym,
     unsigned int got_type)
 {
-  this->reserve_slot(i);
+  this->do_reserve_slot(i);
   gsym->set_got_offset(got_type, this->got_offset(i));
 }
 
diff --git a/gold/output.h b/gold/output.h
index db38236..fa21b64 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -2151,20 +2151,42 @@ class Output_data_group : public Output_section_data
 // needed.  The GOT_SIZE template parameter is the size in bits of a
 // GOT entry, typically 32 or 64.
 
+class Output_data_got_base : public Output_section_data_build
+{
+ public:
+  Output_data_got_base(uint64_t align)
+    : Output_section_data_build(align)
+  { }
+
+  Output_data_got_base(off_t data_size, uint64_t align)
+    : Output_section_data_build(data_size, align)
+  { }
+
+  // Reserve a slot in the GOT.
+  void
+  reserve_slot(unsigned int i)
+  { this->do_reserve_slot(i); }
+
+ protected:
+  // Reserve a slot in the GOT.
+  virtual void
+  do_reserve_slot(unsigned int i) = 0;
+};
+
 template<int got_size, bool big_endian>
-class Output_data_got : public Output_section_data_build
+class Output_data_got : public Output_data_got_base
 {
  public:
   typedef typename elfcpp::Elf_types<got_size>::Elf_Addr Valtype;
 
   Output_data_got()
-    : Output_section_data_build(Output_data::default_alignment_for_size(got_size)),
+    : Output_data_got_base(Output_data::default_alignment_for_size(got_size)),
       entries_(), free_list_()
   { }
 
   Output_data_got(off_t data_size)
-    : Output_section_data_build(data_size,
-				Output_data::default_alignment_for_size(got_size)),
+    : Output_data_got_base(data_size,
+			   Output_data::default_alignment_for_size(got_size)),
       entries_(), free_list_()
   {
     // For an incremental update, we have an existing GOT section.
@@ -2231,11 +2253,6 @@ class Output_data_got : public Output_section_data_build
     return got_offset;
   }
 
-  // Reserve a slot in the GOT.
-  void
-  reserve_slot(unsigned int i)
-  { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
-
   // Reserve a slot in the GOT for a local symbol.
   void
   reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
@@ -2255,6 +2272,11 @@ class Output_data_got : public Output_section_data_build
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** GOT")); }
 
+  // Reserve a slot in the GOT.
+  virtual void
+  do_reserve_slot(unsigned int i)
+  { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
+
  private:
   // This POD class holds a single GOT entry.
   class Got_entry
diff --git a/gold/target.h b/gold/target.h
index a378120..1035427 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -56,8 +56,7 @@ template<int size>
 class Sized_symbol;
 class Symbol_table;
 class Output_data;
-template<int size, bool big_endian>
-class Output_data_got;
+class Output_data_got_base;
 class Output_section;
 class Input_objects;
 class Task;
@@ -845,7 +844,7 @@ class Sized_target : public Target
   // Create the GOT and PLT sections for an incremental update.
   // A target needs to implement this to support incremental linking.
 
-  virtual Output_data_got<size, big_endian>*
+  virtual Output_data_got_base*
   init_got_plt_for_update(Symbol_table*,
 			  Layout*,
 			  unsigned int /* got_count */,
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 552e9d1..eeb532b 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -425,7 +425,7 @@ class Target_x86_64 : public Sized_target<64, false>
   plt_entry_size() const;
 
   // Create the GOT section for an incremental update.
-  Output_data_got<64, false>*
+  Output_data_got_base*
   init_got_plt_for_update(Symbol_table* symtab,
 			  Layout* layout,
 			  unsigned int got_count,
@@ -1463,7 +1463,7 @@ Target_x86_64::plt_entry_size() const
 
 // Create the GOT and PLT sections for an incremental update.
 
-Output_data_got<64, false>*
+Output_data_got_base*
 Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
 				       Layout* layout,
 				       unsigned int got_count,

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2012-01-03 23:24                           ` Cary Coutant
@ 2012-01-04  0:01                             ` Ian Lance Taylor
  2012-01-04  0:25                               ` Cary Coutant
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2012-01-04  0:01 UTC (permalink / raw)
  To: Cary Coutant; +Cc: H.J. Lu, binutils

Cary Coutant <ccoutant@google.com> writes:

> 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.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size
  2012-01-04  0:01                             ` Ian Lance Taylor
@ 2012-01-04  0:25                               ` Cary Coutant
  0 siblings, 0 replies; 17+ messages in thread
From: Cary Coutant @ 2012-01-04  0:25 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: H.J. Lu, binutils

>> 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.

-cary

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2012-01-04  0:25 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-15 23:09 PATCH: PR gold/13507: Gold assumes GOT entry size is the same as ELF class size H.J. Lu
2011-12-16  2:38 ` Ian Lance Taylor
2011-12-16  2:58   ` H.J. Lu
2011-12-16  5:53     ` Ian Lance Taylor
2011-12-16 15:39       ` H.J. Lu
2011-12-16 16:43         ` Ian Lance Taylor
2011-12-16 17:08           ` H.J. Lu
2011-12-16 19:00             ` Ian Lance Taylor
2011-12-16 22:10               ` H.J. Lu
2011-12-17  6:33                 ` Ian Lance Taylor
2011-12-17 17:11                   ` H.J. Lu
     [not found]                     ` <CAKOQZ8zjAStMvF0Di2V0tmbXSaJYgOx9uE3tYCW_CDS2n5-AkA@mail.gmail.com>
2012-01-02 17:09                       ` H.J. Lu
2012-01-02 18:27                         ` Ian Lance Taylor
2012-01-03 23:24                           ` Cary Coutant
2012-01-04  0:01                             ` Ian Lance Taylor
2012-01-04  0:25                               ` Cary Coutant
2011-12-16  3:19 ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).