This is the mail archive of the binutils-cvs@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]

[binutils-gdb] [GOLD] Edit PowerPC64 ELFv2 function entry code


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e3a7574e2e06f975a4933d3f7e77af1d9189d9de

commit e3a7574e2e06f975a4933d3f7e77af1d9189d9de
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Dec 9 10:18:44 2015 +1030

    [GOLD] Edit PowerPC64 ELFv2 function entry code
    
    In an fixed position executable, the entry code does not need to be
    PIC and can thus lose a dependency on r12.
    
    	* powerpc.cc (Target_powerpc::Relocate::relocate): Edit ELFv2
    	entry code.
    	(Target_powerpc::relocate_relocs): Edit relocs to suit.

Diff:
---
 gold/ChangeLog  |  6 +++++
 gold/powerpc.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index be004cd..824296b 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,11 @@
 2015-12-09  Alan Modra  <amodra@gmail.com>
 
+	* powerpc.cc (Target_powerpc::Relocate::relocate): Edit ELFv2
+	entry code.
+	(Target_powerpc::relocate_relocs): Edit relocs to suit.
+
+2015-12-09  Alan Modra  <amodra@gmail.com>
+
 	* object.h (struct Relocate_info): Add "rr".
 	* reloc.h (Relocatable_relocs::set_strategy): New accessor.
 	* reloc.cc (Sized_relobj_file::do_relocate_sections): Init
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index f16faf7..71507fe 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -7027,6 +7027,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 
   typedef Powerpc_relocate_functions<size, big_endian> Reloc;
   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insn;
+  typedef typename Reloc_types<elfcpp::SHT_RELA,
+			       size, big_endian>::Reloc Reltype;
   Powerpc_relobj<size, big_endian>* const object
     = static_cast<Powerpc_relobj<size, big_endian>*>(relinfo->object);
   Address value = 0;
@@ -7700,6 +7702,55 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 		}
 	    }
 	  break;
+
+	case elfcpp::R_POWERPC_REL16_LO:
+	  // If we are generating a non-PIC executable, edit
+	  // 	0:	addis 2,12,.TOC.-0b@ha
+	  //		addi 2,2,.TOC.-0b@l
+	  // used by ELFv2 global entry points to set up r2, to
+	  //		lis 2,.TOC.@ha
+	  //		addi 2,2,.TOC.@l
+	  // if .TOC. is in range.  */
+	  if (value + address - 4 + 0x80008000 <= 0xffffffff
+	      && relnum != 0
+	      && preloc != NULL
+	      && target->abiversion() >= 2
+	      && !parameters->options().output_is_position_independent()
+	      && gsym != NULL
+	      && strcmp(gsym->name(), ".TOC.") == 0)
+	    {
+	      const int reloc_size
+		= Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size;
+	      Reltype prev_rela(preloc - reloc_size);
+	      if ((prev_rela.get_r_info()
+		   == elfcpp::elf_r_info<size>(r_sym,
+					       elfcpp::R_POWERPC_REL16_HA))
+		  && prev_rela.get_r_offset() + 4 == rela.get_r_offset()
+		  && prev_rela.get_r_addend() + 4 == rela.get_r_addend())
+		{
+		  Insn* iview = reinterpret_cast<Insn*>(view - 2 * big_endian);
+		  Insn insn1 = elfcpp::Swap<32, big_endian>::readval(iview - 1);
+		  Insn insn2 = elfcpp::Swap<32, big_endian>::readval(iview);
+
+		  if ((insn1 & 0xffff0000) == addis_2_12
+		      && (insn2 & 0xffff0000) == addi_2_2)
+		    {
+		      insn1 = lis_2 + ha(value + address - 4);
+		      elfcpp::Swap<32, big_endian>::writeval(iview - 1, insn1);
+		      insn2 = addi_2_2 + l(value + address - 4);
+		      elfcpp::Swap<32, big_endian>::writeval(iview, insn2);
+		      if (relinfo->rr)
+			{
+			  relinfo->rr->set_strategy(relnum - 1,
+						    Relocatable_relocs::RELOC_SPECIAL);
+			  relinfo->rr->set_strategy(relnum,
+						    Relocatable_relocs::RELOC_SPECIAL);
+			}
+		      return true;
+		    }
+		}
+	    }
+	  break;
 	}
     }
 
@@ -8357,8 +8408,21 @@ Target_powerpc<size, big_endian>::relocate_relocs(
 	}
       else if (strategy == Relocatable_relocs::RELOC_SPECIAL)
 	{
-	  if (addend >= 32768)
-	    addend += got2_addend;
+	  if (size == 32)
+	    {
+	      if (addend >= 32768)
+		addend += got2_addend;
+	    }
+	  else if (r_type == elfcpp::R_POWERPC_REL16_HA)
+	    {
+	      r_type = elfcpp::R_POWERPC_ADDR16_HA;
+	      addend -= 2 * big_endian;
+	    }
+	  else if (r_type == elfcpp::R_POWERPC_REL16_LO)
+	    {
+	      r_type = elfcpp::R_POWERPC_ADDR16_LO;
+	      addend -= 2 * big_endian + 4;
+	    }
 	}
       else
 	gold_unreachable();


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