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


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

[GOLD] PowerPC64 tocsave


This adds support to gold for the tocsave relocs already supported by
ld.bfd.  R_PPC64_TOCSAVE relocs are part of a scheme to move r2 saves
to the prologue of a function rather than in each plt call stub.  We
don't want a compiler to always emit the r2 save, as this would be
wasted if the calls turned out to be local.  See the testcase just
committed to ld/testsuite/ld-powerpc/.

	* powerpc.cc (Target_powerpc::tocsave_loc_): New var.
	(Target_powerpc::mark_pltcall, add_tocsave, tocsave_loc): New functions.
	(Target_powerpc::Branch_info::tocsave_): New var.
	(Target_powerpc::Branch_info::mark_pltcall): New function.
	(Target_powerpc::Branch_info::make_stub): Pass tocsave_ to
	add_plt_call_entry.
	(Stub_table::Plt_stub_ent): Make public.  Add r2save_.
	(Stub_table::add_plt_call_entry): Add bool tocsave_ param.  Set
	r2save_.
	(Stub_table::find_plt_call_entry): Return Plt_stub_ent*.  Adjust
	use throughout.
	(Stub_table::do_write): Conditionally output r2 save in plt stubs.
	(Target_powerpc::Scan::local): Handle R_PPC64_TOCSAVE.
	(Target_powerpc::Scan::global): Likewise.
	(Target_powerpc::Relocate::relocate): Use reloc_count.  Skip
	r2 save in plt call stub with tocsave reloc.  Replace header
	tocsave nop with r2 save.
	* symtab.h (struct Symbol_location_hash): Make public.

diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 95b8cc0..e102538 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -593,6 +593,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
     Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Reloc_section;
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   typedef typename elfcpp::Elf_types<size>::Elf_Swxword Signed_address;
+  typedef Unordered_set<Symbol_location, Symbol_location_hash> Tocsave_loc;
   static const Address invalid_address = static_cast<Address>(0) - 1;
   // Offset of tp and dtp pointers from start of TLS block.
   static const Address tp_offset = 0x7000;
@@ -603,7 +604,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
       got_(NULL), plt_(NULL), iplt_(NULL), brlt_section_(NULL),
       glink_(NULL), rela_dyn_(NULL), copy_relocs_(),
       tlsld_got_offset_(-1U),
-      stub_tables_(), branch_lookup_table_(), branch_info_(),
+      stub_tables_(), branch_lookup_table_(), branch_info_(), tocsave_loc_(),
       plt_thread_safe_(false), relax_failed_(false), relax_fail_count_(0),
       stub_group_size_(0), savres_section_(0)
   {
@@ -680,6 +681,39 @@ class Target_powerpc : public Sized_target<size, big_endian>
       ppc_object->set_has_14bit_branch(data_shndx);
   }
 
+  // Return whether the last branch is a plt call, and if so, mark the
+  // branch as having an R_PPC64_TOCSAVE.
+  bool
+  mark_pltcall(Powerpc_relobj<size, big_endian>* ppc_object,
+	       unsigned int data_shndx, Address r_offset, Symbol_table* symtab)
+  {
+    return (size == 64
+	    && !this->branch_info_.empty()
+	    && this->branch_info_.back().mark_pltcall(ppc_object, data_shndx,
+						      r_offset, this, symtab));
+  }
+
+  // Say the given location, that of a nop in a function prologue with
+  // an R_PPC64_TOCSAVE reloc, will be used to save r2.
+  // R_PPC64_TOCSAVE relocs on nops following calls point at this nop.
+  void
+  add_tocsave(Powerpc_relobj<size, big_endian>* ppc_object,
+	      unsigned int shndx, Address offset)
+  {
+    Symbol_location loc;
+    loc.object = ppc_object;
+    loc.shndx = shndx;
+    loc.offset = offset;
+    this->tocsave_loc_.insert(loc);
+  }
+
+  // Accessor
+  const Tocsave_loc
+  tocsave_loc() const
+  {
+    return this->tocsave_loc_;
+  }
+
   void
   do_define_standard_symbols(Symbol_table*, Layout*);
 
@@ -1347,12 +1381,19 @@ class Target_powerpc : public Sized_target<size, big_endian>
 		unsigned int r_sym,
 		Address addend)
       : object_(ppc_object), shndx_(data_shndx), offset_(r_offset),
-	r_type_(r_type), r_sym_(r_sym), addend_(addend)
+	r_type_(r_type), tocsave_ (0), r_sym_(r_sym), addend_(addend)
     { }
 
     ~Branch_info()
     { }
 
+    // Return whether this branch is going via a plt call stub, and if
+    // so, mark it as having an R_PPC64_TOCSAVE.
+    bool
+    mark_pltcall(Powerpc_relobj<size, big_endian>* ppc_object,
+		 unsigned int shndx, Address offset,
+		 Target_powerpc* target, Symbol_table* symtab);
+
     // If this branch needs a plt call stub, or a long branch stub, make one.
     bool
     make_stub(Stub_table<size, big_endian>*,
@@ -1365,7 +1406,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
     unsigned int shndx_;
     Address offset_;
     // ..and the branch type and destination.
-    unsigned int r_type_;
+    unsigned int r_type_ : 31;
+    unsigned int tocsave_ : 1;
     unsigned int r_sym_;
     Address addend_;
   };
@@ -1430,6 +1472,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
 
   typedef std::vector<Branch_info> Branches;
   Branches branch_info_;
+  Tocsave_loc tocsave_loc_;
 
   bool plt_thread_safe_;
 
@@ -2890,6 +2933,36 @@ max_branch_delta (unsigned int r_type)
   return 0;
 }
 
+// Return whether this branch is going via a plt call stub.
+
+template<int size, bool big_endian>
+bool
+Target_powerpc<size, big_endian>::Branch_info::mark_pltcall(
+    Powerpc_relobj<size, big_endian>* ppc_object,
+    unsigned int shndx,
+    Address offset,
+    Target_powerpc* target,
+    Symbol_table* symtab)
+{
+  if (this->object_ != ppc_object
+      || this->shndx_ != shndx
+      || this->offset_ != offset)
+    return false;
+
+  Symbol* sym = this->object_->global_symbol(this->r_sym_);
+  if (sym != NULL && sym->is_forwarder())
+    sym = symtab->resolve_forwards(sym);
+  const Sized_symbol<size>* gsym = static_cast<const Sized_symbol<size>*>(sym);
+  if (gsym != NULL
+      ? gsym->use_plt_offset(Scan::get_reference_flags(this->r_type_, target))
+      : this->object_->local_has_plt_offset(this->r_sym_))
+    {
+      this->tocsave_ = 1;
+      return true;
+    }
+  return false;
+}
+
 // If this branch needs a plt call stub, or a long branch stub, make one.
 
 template<int size, bool big_endian>
@@ -2935,11 +3008,13 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
 	  if (gsym != NULL)
 	    ok = stub_table->add_plt_call_entry(from,
 						this->object_, gsym,
-						this->r_type_, this->addend_);
+						this->r_type_, this->addend_,
+						this->tocsave_);
 	  else
 	    ok = stub_table->add_plt_call_entry(from,
 						this->object_, this->r_sym_,
-						this->r_type_, this->addend_);
+						this->r_type_, this->addend_,
+						this->tocsave_);
 	}
     }
   else
@@ -3911,6 +3986,16 @@ template<int size, bool big_endian>
 class Stub_table : public Output_relaxed_input_section
 {
  public:
+  struct Plt_stub_ent
+  {
+    Plt_stub_ent(unsigned int off, unsigned int indx)
+      : off_(off), indx_(indx), r2save_(0)
+    { }
+
+    unsigned int off_;
+    unsigned int indx_ : 31;
+    unsigned int r2save_ : 1;
+  };
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   static const Address invalid_address = static_cast<Address>(0) - 1;
 
@@ -3940,30 +4025,32 @@ class Stub_table : public Output_relaxed_input_section
 		     const Sized_relobj_file<size, big_endian>*,
 		     const Symbol*,
 		     unsigned int,
-		     Address);
+		     Address,
+		     bool);
 
   bool
   add_plt_call_entry(Address,
 		     const Sized_relobj_file<size, big_endian>*,
 		     unsigned int,
 		     unsigned int,
-		     Address);
+		     Address,
+		     bool);
 
   // Find a given plt call stub.
-  Address
+  const Plt_stub_ent*
   find_plt_call_entry(const Symbol*) const;
 
-  Address
+  const Plt_stub_ent*
   find_plt_call_entry(const Sized_relobj_file<size, big_endian>*,
 		      unsigned int) const;
 
-  Address
+  const Plt_stub_ent*
   find_plt_call_entry(const Sized_relobj_file<size, big_endian>*,
 		      const Symbol*,
 		      unsigned int,
 		      Address) const;
 
-  Address
+  const Plt_stub_ent*
   find_plt_call_entry(const Sized_relobj_file<size, big_endian>*,
 		      unsigned int,
 		      unsigned int,
@@ -4120,15 +4207,6 @@ class Stub_table : public Output_relaxed_input_section
  private:
   class Plt_stub_key;
   class Plt_stub_key_hash;
-  struct Plt_stub_ent
-  {
-    Plt_stub_ent(unsigned int off, unsigned int indx)
-      : off_(off), indx_(indx)
-    { }
-
-    unsigned int off_;
-    unsigned int indx_;
-  };
   typedef Unordered_map<Plt_stub_key, Plt_stub_ent,
 			Plt_stub_key_hash> Plt_stub_entries;
   class Branch_stub_ent;
@@ -4353,7 +4431,8 @@ Stub_table<size, big_endian>::add_plt_call_entry(
     const Sized_relobj_file<size, big_endian>* object,
     const Symbol* gsym,
     unsigned int r_type,
-    Address addend)
+    Address addend,
+    bool tocsave)
 {
   Plt_stub_key key(object, gsym, r_type, addend);
   Plt_stub_ent ent(this->plt_size_, this->plt_call_stubs_.size());
@@ -4361,6 +4440,8 @@ Stub_table<size, big_endian>::add_plt_call_entry(
     = this->plt_call_stubs_.insert(std::make_pair(key, ent));
   if (p.second)
     this->plt_size_ = ent.off_ + this->plt_call_size(p.first);
+  if (size == 64 && !tocsave)
+    p.first->second.r2save_ = 1;
   return this->can_reach_stub(from, ent.off_, r_type);
 }
 
@@ -4371,7 +4452,8 @@ Stub_table<size, big_endian>::add_plt_call_entry(
     const Sized_relobj_file<size, big_endian>* object,
     unsigned int locsym_index,
     unsigned int r_type,
-    Address addend)
+    Address addend,
+    bool tocsave)
 {
   Plt_stub_key key(object, locsym_index, r_type, addend);
   Plt_stub_ent ent(this->plt_size_, this->plt_call_stubs_.size());
@@ -4379,13 +4461,15 @@ Stub_table<size, big_endian>::add_plt_call_entry(
     = this->plt_call_stubs_.insert(std::make_pair(key, ent));
   if (p.second)
     this->plt_size_ = ent.off_ + this->plt_call_size(p.first);
+  if (size == 64 && !tocsave)
+    p.first->second.r2save_ = 1;
   return this->can_reach_stub(from, ent.off_, r_type);
 }
 
 // Find a plt call stub.
 
 template<int size, bool big_endian>
-typename Stub_table<size, big_endian>::Address
+const typename Stub_table<size, big_endian>::Plt_stub_ent*
 Stub_table<size, big_endian>::find_plt_call_entry(
     const Sized_relobj_file<size, big_endian>* object,
     const Symbol* gsym,
@@ -4395,21 +4479,23 @@ Stub_table<size, big_endian>::find_plt_call_entry(
   Plt_stub_key key(object, gsym, r_type, addend);
   typename Plt_stub_entries::const_iterator p = this->plt_call_stubs_.find(key);
   if (p == this->plt_call_stubs_.end())
-    return invalid_address;
-  return p->second.off_;
+    return NULL;
+  return &p->second;
 }
 
 template<int size, bool big_endian>
-typename Stub_table<size, big_endian>::Address
+const typename Stub_table<size, big_endian>::Plt_stub_ent*
 Stub_table<size, big_endian>::find_plt_call_entry(const Symbol* gsym) const
 {
   Plt_stub_key key(gsym);
   typename Plt_stub_entries::const_iterator p = this->plt_call_stubs_.find(key);
-  return p == this->plt_call_stubs_.end() ? invalid_address : p->second.off_;
+  if (p == this->plt_call_stubs_.end())
+    return NULL;
+  return &p->second;
 }
 
 template<int size, bool big_endian>
-typename Stub_table<size, big_endian>::Address
+const typename Stub_table<size, big_endian>::Plt_stub_ent*
 Stub_table<size, big_endian>::find_plt_call_entry(
     const Sized_relobj_file<size, big_endian>* object,
     unsigned int locsym_index,
@@ -4419,19 +4505,21 @@ Stub_table<size, big_endian>::find_plt_call_entry(
   Plt_stub_key key(object, locsym_index, r_type, addend);
   typename Plt_stub_entries::const_iterator p = this->plt_call_stubs_.find(key);
   if (p == this->plt_call_stubs_.end())
-    return invalid_address;
-  return p->second.off_;
+    return NULL;
+  return &p->second;
 }
 
 template<int size, bool big_endian>
-typename Stub_table<size, big_endian>::Address
+const typename Stub_table<size, big_endian>::Plt_stub_ent*
 Stub_table<size, big_endian>::find_plt_call_entry(
     const Sized_relobj_file<size, big_endian>* object,
     unsigned int locsym_index) const
 {
   Plt_stub_key key(object, locsym_index);
   typename Plt_stub_entries::const_iterator p = this->plt_call_stubs_.find(key);
-  return p == this->plt_call_stubs_.end() ? invalid_address : p->second.off_;
+  if (p == this->plt_call_stubs_.end())
+    return NULL;
+  return &p->second;
 }
 
 // Add a long branch stub if we don't already have one to given
@@ -4787,7 +4875,8 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
 		  Address to
 		    = this->targ_->glink_section()->address() + glinkoff;
 		  Address from
-		    = (this->stub_address() + cs->second.off_ + 24
+		    = (this->stub_address() + cs->second.off_ + 20
+		       + 4 * cs->second.r2save_
 		       + 4 * (ha(off) != 0)
 		       + 4 * (ha(off + 8 + 8 * static_chain) != ha(off))
 		       + 4 * static_chain);
@@ -4798,8 +4887,12 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
 	      p = oview + cs->second.off_;
 	      if (ha(off) != 0)
 		{
-		  write_insn<big_endian>(p, std_2_1 + this->targ_->stk_toc());
-		  p += 4;
+		  if (cs->second.r2save_)
+		    {
+		      write_insn<big_endian>(p,
+					     std_2_1 + this->targ_->stk_toc());
+		      p += 4;
+		    }
 		  if (plt_load_toc)
 		    {
 		      write_insn<big_endian>(p, addis_11_2 + ha(off));
@@ -4843,8 +4936,12 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
 		}
 	      else
 		{
-		  write_insn<big_endian>(p, std_2_1 + this->targ_->stk_toc());
-		  p += 4;
+		  if (cs->second.r2save_)
+		    {
+		      write_insn<big_endian>(p,
+					     std_2_1 + this->targ_->stk_toc());
+		      p += 4;
+		    }
 		  write_insn<big_endian>(p, ld_12_2 + l(off));
 		  p += 4;
 		  if (plt_load_toc
@@ -6047,7 +6144,6 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_POWERPC_NONE:
     case elfcpp::R_POWERPC_GNU_VTINHERIT:
     case elfcpp::R_POWERPC_GNU_VTENTRY:
-    case elfcpp::R_PPC64_TOCSAVE:
     case elfcpp::R_POWERPC_TLS:
     case elfcpp::R_PPC64_ENTRY:
       break;
@@ -6155,6 +6251,27 @@ Target_powerpc<size, big_endian>::Scan::local(
 	}
       break;
 
+    case elfcpp::R_PPC64_TOCSAVE:
+      // R_PPC64_TOCSAVE follows a call instruction to indicate the
+      // caller has already saved r2 and thus a plt call stub need not
+      // save r2.
+      if (size == 64
+	  && target->mark_pltcall(ppc_object, data_shndx,
+				  reloc.get_r_offset() - 4, symtab))
+	{
+	  unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+	  unsigned int shndx = lsym.get_st_shndx();
+	  bool is_ordinary;
+	  shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
+	  if (!is_ordinary)
+	    object->error(_("tocsave symbol %u has bad shndx %u"),
+			  r_sym, shndx);
+	  else
+	    target->add_tocsave(ppc_object, shndx,
+				lsym.get_st_value() + reloc.get_r_addend());
+	}
+      break;
+
     case elfcpp::R_PPC64_REL64:
     case elfcpp::R_POWERPC_REL32:
     case elfcpp::R_POWERPC_REL16:
@@ -6758,6 +6875,29 @@ Target_powerpc<size, big_endian>::Scan::global(
 	}
       break;
 
+    case elfcpp::R_PPC64_TOCSAVE:
+      // R_PPC64_TOCSAVE follows a call instruction to indicate the
+      // caller has already saved r2 and thus a plt call stub need not
+      // save r2.
+      if (size == 64
+	  && target->mark_pltcall(ppc_object, data_shndx,
+				  reloc.get_r_offset() - 4, symtab))
+	{
+	  unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+	  bool is_ordinary;
+	  unsigned int shndx = gsym->shndx(&is_ordinary);
+	  if (!is_ordinary)
+	    object->error(_("tocsave symbol %u has bad shndx %u"),
+			  r_sym, shndx);
+	  else
+	    {
+	      Sized_symbol<size>* sym = symtab->get_sized_symbol<size>(gsym);
+	      target->add_tocsave(ppc_object, shndx,
+				  sym->value() + reloc.get_r_addend());
+	    }
+	}
+      break;
+
     case elfcpp::R_POWERPC_REL16:
     case elfcpp::R_POWERPC_REL16_LO:
     case elfcpp::R_POWERPC_REL16_HI:
@@ -7738,7 +7878,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     Target_powerpc* target,
     Output_section* os,
     size_t relnum,
-    size_t,
+    size_t reloc_count,
     const unsigned char* preloc,
     const Sized_symbol<size>* gsym,
     const Symbol_value<size>* psymval,
@@ -7808,16 +7948,27 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 	    }
 	  if (stub_table != NULL)
 	    {
-	      Address off;
+	      const typename Stub_table<size, big_endian>::Plt_stub_ent* ent;
 	      if (gsym != NULL)
-		off = stub_table->find_plt_call_entry(object, gsym, r_type,
+		ent = stub_table->find_plt_call_entry(object, gsym, r_type,
 						      rela.get_r_addend());
 	      else
-		off = stub_table->find_plt_call_entry(object, r_sym, r_type,
+		ent = stub_table->find_plt_call_entry(object, r_sym, r_type,
 						      rela.get_r_addend());
-	      if (off != invalid_address)
+	      if (ent != NULL)
 		{
-		  value = stub_table->stub_address() + off;
+		  value = stub_table->stub_address() + ent->off_;
+		  if (size == 64
+		      && ent->r2save_
+		      && relnum + 1 < reloc_count)
+		    {
+		      const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+		      Reltype next_rela(preloc + reloc_size);
+		      if (elfcpp::elf_r_type<size>(next_rela.get_r_info())
+			  == elfcpp::R_PPC64_TOCSAVE
+			  && next_rela.get_r_offset() == rela.get_r_offset() + 4)
+			value += 4;
+		    }
 		  has_stub_value = true;
 		}
 	    }
@@ -8846,12 +8997,26 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 			     r_type);
       break;
 
-    case elfcpp::R_PPC_EMB_SDA21:
+    case elfcpp::R_PPC64_TOCSAVE:
       if (size == 32)
+	// R_PPC_EMB_SDA21
 	goto unsupp;
       else
 	{
-	  // R_PPC64_TOCSAVE.  For the time being this can be ignored.
+	  Symbol_location loc;
+	  loc.object = relinfo->object;
+	  loc.shndx = relinfo->data_shndx;
+	  loc.offset = rela.get_r_offset();
+	  Tocsave_loc::const_iterator p = target->tocsave_loc().find(loc);
+	  if (p != target->tocsave_loc().end())
+	    {
+	      // If we've generated plt calls using this tocsave, then
+	      // the nop needs to be changed to save r2.
+	      Insn* iview = reinterpret_cast<Insn*>(view);
+	      if (elfcpp::Swap<32, big_endian>::readval(iview) == nop)
+		elfcpp::Swap<32, big_endian>::
+		  writeval(iview, std_2_1 + target->stk_toc());
+	    }
 	}
       break;
 
@@ -9409,9 +9574,10 @@ Target_powerpc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const
 	   p != this->stub_tables_.end();
 	   ++p)
 	{
-	  Address off = (*p)->find_plt_call_entry(gsym);
-	  if (off != invalid_address)
-	    return (*p)->stub_address() + off;
+	  const typename Stub_table<size, big_endian>::Plt_stub_ent* ent
+	    = (*p)->find_plt_call_entry(gsym);
+	  if (ent != NULL)
+	    return (*p)->stub_address() + ent->off_;
 	}
     }
   else if (this->abiversion() >= 2)
@@ -9438,10 +9604,10 @@ Target_powerpc<size, big_endian>::do_plt_address_for_local(
 	   p != this->stub_tables_.end();
 	   ++p)
 	{
-	  Address off = (*p)->find_plt_call_entry(relobj->sized_relobj(),
-						  symndx);
-	  if (off != invalid_address)
-	    return (*p)->stub_address() + off;
+	  const typename Stub_table<size, big_endian>::Plt_stub_ent* ent
+	    = (*p)->find_plt_call_entry(relobj->sized_relobj(), symndx);
+	  if (ent != NULL)
+	    return (*p)->stub_address() + ent->off_;
 	}
     }
   gold_unreachable();
@@ -9459,9 +9625,10 @@ Target_powerpc<size, big_endian>::do_plt_address_for_global(
 	   p != this->stub_tables_.end();
 	   ++p)
 	{
-	  Address off = (*p)->find_plt_call_entry(gsym);
-	  if (off != invalid_address)
-	    return (*p)->stub_address() + off;
+	  const typename Stub_table<size, big_endian>::Plt_stub_ent* ent
+	    = (*p)->find_plt_call_entry(gsym);
+	  if (ent != NULL)
+	    return (*p)->stub_address() + ent->off_;
 	}
     }
   else if (this->abiversion() >= 2)
diff --git a/gold/symtab.h b/gold/symtab.h
index 46c7fce..77552ae 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -1273,6 +1273,16 @@ struct Symbol_location
   }
 };
 
+// A map from symbol name (as a pointer into the namepool) to all
+// the locations the symbols is (weakly) defined (and certain other
+// conditions are met).  This map will be used later to detect
+// possible One Definition Rule (ODR) violations.
+struct Symbol_location_hash
+{
+  size_t operator()(const Symbol_location& loc) const
+  { return reinterpret_cast<uintptr_t>(loc.object) ^ loc.offset ^ loc.shndx; }
+};
+
 // This class manages warnings.  Warnings are a GNU extension.  When
 // we see a section named .gnu.warning.SYM in an object file, and if
 // we wind using the definition of SYM from that object file, then we
@@ -1695,16 +1705,6 @@ class Symbol_table
   typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash,
 			Symbol_table_eq> Symbol_table_type;
 
-  // A map from symbol name (as a pointer into the namepool) to all
-  // the locations the symbols is (weakly) defined (and certain other
-  // conditions are met).  This map will be used later to detect
-  // possible One Definition Rule (ODR) violations.
-  struct Symbol_location_hash
-  {
-    size_t operator()(const Symbol_location& loc) const
-    { return reinterpret_cast<uintptr_t>(loc.object) ^ loc.offset ^ loc.shndx; }
-  };
-
   typedef Unordered_map<const char*,
                         Unordered_set<Symbol_location, Symbol_location_hash> >
   Odr_map;

-- 
Alan Modra
Australia Development Lab, IBM


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