[PATCH] Support %r_disp{8,16,32,64} and %r_plt{32,64} on SPARC

Jakub Jelinek jakub@redhat.com
Fri Dec 21 07:21:00 GMT 2001


Hi!

The following patch adds support for the weird Solaris as pc relative
notation, ie.
	.word	%r_disp32(foo)
instead of
	.word	foo - .
Actually, Solaris as doesn't support %r_disp8 and %r_disp16, but this seems
like a logical extension to me.
Also, which is far worse,
	.align 4
	.byte 1
	.uaword	%r_disp32(foo)
in Solaris as results in ld error if linking shared library, while the
following patch figures things properly (similarly for %r_plt32, which if
aligned becomes a R_SPARC_RELATIVE reloc (on sparc32) and if not aligned,
R_SPARC_UA32 against .plt).

Richard, do you agree?

In gcc, I'm afraid we'll need to:
1) add configure check for working unaligned %r_disp32() (ie. not Solaris as)
2) if assembler has working unaligned %r_disp32(), use DW_EH_PE_pcrel|DW_EH_PE_sdata4
   as preferred format for shared libs, otherwise on Solaris use DW_EH_PE_aligned
   due to ld.so bugs and elsewhere DW_EH_PE_absptr.

2001-12-21  Jakub Jelinek  <jakub@redhat.com>

	* elf32-sparc.c (_bfd_sparc_elf_howto_table): Fix dst_mask for
	R_SPARC_DISP32.  Support R_SPARC_PLT32.
	(sparc_reloc_map): Add BFD_RELOC_16_PCREL and BFD_RELOC_SPARC_PLT32.
	(elf32_sparc_check_relocs): Handle R_SPARC_PLT32.
	(elf32_sparc_relocate_section): Likewise.
	* elf64-sparc.c (sparc64_elf_howto_table): Fix dst_mask for
	R_SPARC_DISP32.  Support R_SPARC_PLT32 and R_SPARC_PLT64.
	(sparc_reloc_map): Add BFD_RELOC_16_PCREL, BFD_RELOC_64_PCREL
	and BFD_RELOC_SPARC_PLT32.
	(sparc64_elf_check_relocs): Handle R_SPARC_PLT32 and R_SPARC_PLT64.
	(sparc64_elf_relocate_section): Likewise.
	* reloc.c (bfd_reloc_code_type): Add BFD_RELOC_SPARC_PLT32.
	* bfd-in2.h, libbfd.h: Rebuilt.

	* config/tc-sparc.h (TC_PARSE_CONS_EXPRESSION): Define.
	(sparc_cons): Provide prototype.
	* config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_*_PCREL and
	BFD_RELOC_SPARC_PLT{32,64}.  Enumerate for which relocs
	reloc->addend = fixp->fx_addnumber shouldn't be done instead of
	enumarating for which pc relative ones it should be done.
	(sparc_cons_special_reloc): New variable.
	(sparc_cons): New function.
	(cons_fix_new_sparc): Use sparc_cons_special_reloc.
	* testsuite/gas/sparc/pcrel.s: New test.
	* testsuite/gas/sparc/pcrel.d: Expected output.
	* testsuite/gas/sparc/pcrel64.s: New test.
	* testsuite/gas/sparc/pcrel64.d: Expected output.
	* testsuite/gas/sparc/plt.s: New test.
	* testsuite/gas/sparc/plt.d: Expected output.
	* testsuite/gas/sparc/plt64.s: New test.
	* testsuite/gas/sparc/plt64.d: Expected output.
	* testsuite/gas/sparc/sparc.exp: Add pcrel, pcrel64, plt and plt64
	tests.

--- bfd/elf32-sparc.c.jj	Mon Dec 17 12:29:15 2001
+++ bfd/elf32-sparc.c	Fri Dec 21 16:15:37 2001
@@ -76,7 +76,7 @@ reloc_howto_type _bfd_sparc_elf_howto_ta
   HOWTO(R_SPARC_32,        0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_32",      false,0,0xffffffff,true),
   HOWTO(R_SPARC_DISP8,     0,0, 8,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP8",   false,0,0x000000ff,true),
   HOWTO(R_SPARC_DISP16,    0,1,16,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP16",  false,0,0x0000ffff,true),
-  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0x00ffffff,true),
+  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0xffffffff,true),
   HOWTO(R_SPARC_WDISP30,   2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP30", false,0,0x3fffffff,true),
   HOWTO(R_SPARC_WDISP22,   2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP22", false,0,0x003fffff,true),
   HOWTO(R_SPARC_HI22,     10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HI22",    false,0,0x003fffff,true),
@@ -94,7 +94,7 @@ reloc_howto_type _bfd_sparc_elf_howto_ta
   HOWTO(R_SPARC_JMP_SLOT,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_JMP_SLOT",false,0,0x00000000,true),
   HOWTO(R_SPARC_RELATIVE,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_RELATIVE",false,0,0x00000000,true),
   HOWTO(R_SPARC_UA32,      0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0xffffffff,true),
-  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PLT32",    false,0,0x00000000,true),
+  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT32",   false,0,0xffffffff,true),
   HOWTO(R_SPARC_HIPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HIPLT22",  false,0,0x00000000,true),
   HOWTO(R_SPARC_LOPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_LOPLT10",  false,0,0x00000000,true),
   HOWTO(R_SPARC_PCPLT32,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT32",  false,0,0x00000000,true),
@@ -146,6 +146,7 @@ static const struct elf_reloc_map sparc_
 {
   { BFD_RELOC_NONE, R_SPARC_NONE, },
   { BFD_RELOC_16, R_SPARC_16, },
+  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
   { BFD_RELOC_8, R_SPARC_8 },
   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
   { BFD_RELOC_CTOR, R_SPARC_32 },
@@ -154,6 +155,7 @@ static const struct elf_reloc_map sparc_
   { BFD_RELOC_HI22, R_SPARC_HI22 },
   { BFD_RELOC_LO10, R_SPARC_LO10, },
   { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
   { BFD_RELOC_SPARC22, R_SPARC_22 },
   { BFD_RELOC_SPARC13, R_SPARC_13 },
   { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
@@ -494,6 +496,7 @@ elf32_sparc_check_relocs (abfd, info, se
 
 	  break;
 
+	case R_SPARC_PLT32:
 	case R_SPARC_WPLT30:
 	  /* This symbol requires a procedure linkage table entry.  We
              actually build the entry in adjust_dynamic_symbol,
@@ -507,6 +510,8 @@ elf32_sparc_check_relocs (abfd, info, se
                  reloc for a local symbol if you assemble a call from
                  one section to another when using -K pic.  We treat
                  it as WDISP30.  */
+	      if (ELF32_R_TYPE (rel->r_info) != R_SPARC_WPLT30)
+		goto r_sparc_plt32;
 	      break;
 	    }
 
@@ -519,6 +524,8 @@ elf32_sparc_check_relocs (abfd, info, se
 
 	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
 
+	  if (ELF32_R_TYPE (rel->r_info) != R_SPARC_WPLT30)
+	    goto r_sparc_plt32;
 	  break;
 
 	case R_SPARC_PC10:
@@ -566,6 +573,7 @@ elf32_sparc_check_relocs (abfd, info, se
 	  if (h != NULL)
 	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
 
+	r_sparc_plt32:
 	  if (info->shared && (sec->flags & SEC_ALLOC))
 	    {
 	      /* When creating a shared object, we must copy these
@@ -1127,6 +1135,7 @@ elf32_sparc_relocate_section (output_bfd
       asection *sec;
       bfd_vma relocation;
       bfd_reloc_status_type r;
+      boolean is_plt = false;
 
       r_type = ELF32_R_TYPE (rel->r_info);
 
@@ -1182,7 +1191,8 @@ elf32_sparc_relocate_section (output_bfd
 	      || h->root.type == bfd_link_hash_defweak)
 	    {
 	      sec = h->root.u.def.section;
-	      if ((r_type == R_SPARC_WPLT30
+	      if (((r_type == R_SPARC_WPLT30
+		    || r_type == R_SPARC_PLT32)
 		   && h->plt.offset != (bfd_vma) -1)
 		  || ((r_type == R_SPARC_GOT10
 		       || r_type == R_SPARC_GOT13
@@ -1351,6 +1361,13 @@ elf32_sparc_relocate_section (output_bfd
 
 	  break;
 
+	case R_SPARC_PLT32:
+	  if (h == NULL || h->plt.offset == (bfd_vma) -1)
+	    {
+	      r_type = R_SPARC_32;
+	      goto r_sparc_plt32;
+	    }
+	  /* Fall through.  */
 	case R_SPARC_WPLT30:
 	  /* Relocation is to the entry for this symbol in the
              procedure linkage table.  */
@@ -1379,6 +1396,12 @@ elf32_sparc_relocate_section (output_bfd
 	  relocation = (splt->output_section->vma
 			+ splt->output_offset
 			+ h->plt.offset);
+	  if (r_type == R_SPARC_PLT32)
+	    {
+	      r_type = R_SPARC_32;
+	      is_plt = true;
+	      goto r_sparc_plt32;
+	    }
 	  break;
 
 	case R_SPARC_PC10:
@@ -1409,6 +1432,7 @@ elf32_sparc_relocate_section (output_bfd
 	case R_SPARC_LO10:
 	case R_SPARC_UA16:
 	case R_SPARC_UA32:
+	r_sparc_plt32:
 	  if (info->shared
 	      && r_symndx != 0
 	      && (input_section->flags & SEC_ALLOC))
@@ -1476,7 +1500,7 @@ elf32_sparc_relocate_section (output_bfd
 		memset (&outrel, 0, sizeof outrel);
 	      /* h->dynindx may be -1 if the symbol was marked to
                  become local.  */
-	      else if (h != NULL
+	      else if (h != NULL && ! is_plt
 		       && ((! info->symbolic && h->dynindx != -1)
 			   || (h->elf_link_hash_flags
 			       & ELF_LINK_HASH_DEF_REGULAR) == 0))
@@ -1496,7 +1520,9 @@ elf32_sparc_relocate_section (output_bfd
 		    {
 		      long indx;
 
-		      if (h == NULL)
+		      if (is_plt)
+			sec = splt;
+		      else if (h == NULL)
 			sec = local_sections[r_symndx];
 		      else
 			{
--- bfd/elf64-sparc.c.jj	Fri Dec  7 13:22:19 2001
+++ bfd/elf64-sparc.c	Fri Dec 21 16:21:20 2001
@@ -118,7 +118,7 @@ static reloc_howto_type sparc64_elf_howt
   HOWTO(R_SPARC_32,        0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_32",      false,0,0xffffffff,true),
   HOWTO(R_SPARC_DISP8,     0,0, 8,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP8",   false,0,0x000000ff,true),
   HOWTO(R_SPARC_DISP16,    0,1,16,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP16",  false,0,0x0000ffff,true),
-  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0x00ffffff,true),
+  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0xffffffff,true),
   HOWTO(R_SPARC_WDISP30,   2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP30", false,0,0x3fffffff,true),
   HOWTO(R_SPARC_WDISP22,   2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP22", false,0,0x003fffff,true),
   HOWTO(R_SPARC_HI22,     10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HI22",    false,0,0x003fffff,true),
@@ -137,8 +137,8 @@ static reloc_howto_type sparc64_elf_howt
   HOWTO(R_SPARC_RELATIVE,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_RELATIVE",false,0,0x00000000,true),
   HOWTO(R_SPARC_UA32,      0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0xffffffff,true),
 #ifndef SPARC64_OLD_RELOCS
+  HOWTO(R_SPARC_PLT32,     0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT32",   false,0,0xffffffff,true),
   /* These aren't implemented yet.  */
-  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PLT32",    false,0,0x00000000,true),
   HOWTO(R_SPARC_HIPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_HIPLT22",  false,0,0x00000000,true),
   HOWTO(R_SPARC_LOPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_LOPLT10",  false,0,0x00000000,true),
   HOWTO(R_SPARC_PCPLT32,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PCPLT32",  false,0,0x00000000,true),
@@ -162,7 +162,7 @@ static reloc_howto_type sparc64_elf_howt
   HOWTO(R_SPARC_5,         0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_5",       false,0,0x0000001f,true),
   HOWTO(R_SPARC_6,         0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_6",       false,0,0x0000003f,true),
   HOWTO(R_SPARC_DISP64,    0,4,64,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP64",  false,0,MINUS_ONE, true),
-  HOWTO(R_SPARC_PLT64,     0,4,64,false,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_PLT64",   false,0,MINUS_ONE, false),
+  HOWTO(R_SPARC_PLT64,     0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT64",   false,0,MINUS_ONE, true),
   HOWTO(R_SPARC_HIX22,     0,4, 0,false,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,  "R_SPARC_HIX22",   false,0,MINUS_ONE, false),
   HOWTO(R_SPARC_LOX10,     0,4, 0,false,0,complain_overflow_dont,    sparc_elf_lox10_reloc,  "R_SPARC_LOX10",   false,0,MINUS_ONE, false),
   HOWTO(R_SPARC_H44,      22,2,22,false,0,complain_overflow_unsigned,bfd_elf_generic_reloc,  "R_SPARC_H44",     false,0,0x003fffff,false),
@@ -182,6 +182,7 @@ static const struct elf_reloc_map sparc_
 {
   { BFD_RELOC_NONE, R_SPARC_NONE, },
   { BFD_RELOC_16, R_SPARC_16, },
+  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
   { BFD_RELOC_8, R_SPARC_8 },
   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
   { BFD_RELOC_CTOR, R_SPARC_64 },
@@ -190,6 +191,7 @@ static const struct elf_reloc_map sparc_
   { BFD_RELOC_HI22, R_SPARC_HI22 },
   { BFD_RELOC_LO10, R_SPARC_LO10, },
   { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+  { BFD_RELOC_64_PCREL, R_SPARC_DISP64 },
   { BFD_RELOC_SPARC22, R_SPARC_22 },
   { BFD_RELOC_SPARC13, R_SPARC_13 },
   { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
@@ -222,6 +224,9 @@ static const struct elf_reloc_map sparc_
   { BFD_RELOC_SPARC_5, R_SPARC_5 },
   { BFD_RELOC_SPARC_6, R_SPARC_6 },
   { BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 },
+#ifndef SPARC64_OLD_RELOCS
+  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
+#endif
   { BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
   { BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
   { BFD_RELOC_SPARC_LOX10, R_SPARC_LOX10 },
@@ -1169,8 +1174,10 @@ sparc64_elf_check_relocs (abfd, info, se
 	    }
 
 	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
-	  break;
-
+	  if (ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT32
+	      && ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT64)
+	    break;
+	  /* Fall through.  */
 	case R_SPARC_PC10:
 	case R_SPARC_PC22:
 	case R_SPARC_PC_HH22:
@@ -1931,6 +1938,7 @@ sparc64_elf_relocate_section (output_bfd
       asection *sec;
       bfd_vma relocation;
       bfd_reloc_status_type r;
+      boolean is_plt = false;
 
       r_type = ELF64_R_TYPE_ID (rel->r_info);
       if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
@@ -2107,6 +2115,7 @@ sparc64_elf_relocate_section (output_bfd
 	    }
 	}
 
+do_dynreloc:
       /* When generating a shared object, these relocations are copied
 	 into the output file to be resolved at run time.  */
       if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
@@ -2221,7 +2230,7 @@ sparc64_elf_relocate_section (output_bfd
 		  memset (&outrel, 0, sizeof outrel);
 		/* h->dynindx may be -1 if the symbol was marked to
 		   become local.  */
-		else if (h != NULL
+		else if (h != NULL && ! is_plt
 			 && ((! info->symbolic && h->dynindx != -1)
 			     || (h->elf_link_hash_flags
 				 & ELF_LINK_HASH_DEF_REGULAR) == 0))
@@ -2245,7 +2254,9 @@ sparc64_elf_relocate_section (output_bfd
 		      {
 			long indx;
 
-			if (h == NULL)
+			if (is_plt)
+			  sec = splt;
+			else if (h == NULL)
 			  sec = local_sections[r_symndx];
 			else
 			  {
@@ -2435,6 +2446,12 @@ sparc64_elf_relocate_section (output_bfd
 			+ sparc64_elf_plt_entry_offset (h->plt.offset));
 	  if (r_type == R_SPARC_WPLT30)
 	    goto do_wplt30;
+	  if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
+	    {
+	      r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64;
+	      is_plt = true;
+	      goto do_dynreloc;
+	    }
 	  goto do_default;
 
 	case R_SPARC_OLO10:
--- bfd/bfd-in2.h.jj	Mon Dec 17 12:29:01 2001
+++ bfd/bfd-in2.h	Fri Dec 21 15:56:15 2001
@@ -2022,6 +2022,7 @@ relocation types already defined. */
   BFD_RELOC_SPARC_6,
   BFD_RELOC_SPARC_5,
 #define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+  BFD_RELOC_SPARC_PLT32,
   BFD_RELOC_SPARC_PLT64,
   BFD_RELOC_SPARC_HIX22,
   BFD_RELOC_SPARC_LOX10,
--- bfd/libbfd.h.jj	Mon Dec 17 12:29:48 2001
+++ bfd/libbfd.h	Fri Dec 21 15:56:48 2001
@@ -702,6 +702,7 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_SPARC_7",
   "BFD_RELOC_SPARC_6",
   "BFD_RELOC_SPARC_5",
+  "BFD_RELOC_SPARC_PLT32",
   "BFD_RELOC_SPARC_PLT64",
   "BFD_RELOC_SPARC_HIX22",
   "BFD_RELOC_SPARC_LOX10",
--- bfd/reloc.c.jj	Thu Dec 13 13:09:45 2001
+++ bfd/reloc.c	Fri Dec 21 15:57:38 2001
@@ -1857,6 +1857,8 @@ ENUMEQX
   BFD_RELOC_SPARC_DISP64
   BFD_RELOC_64_PCREL
 ENUMX
+  BFD_RELOC_SPARC_PLT32
+ENUMX
   BFD_RELOC_SPARC_PLT64
 ENUMX
   BFD_RELOC_SPARC_HIX22
--- gas/config/tc-sparc.h.jj	Fri Nov 16 21:50:12 2001
+++ gas/config/tc-sparc.h	Thu Dec 20 18:35:04 2001
@@ -166,6 +166,11 @@ extern void sparc_md_end PARAMS ((void))
 
 #endif
 
+#ifdef OBJ_ELF
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) sparc_cons (EXP, NBYTES)
+extern void sparc_cons PARAMS ((expressionS *, int));
+#endif
+
 #define TC_CONS_FIX_NEW cons_fix_new_sparc
 extern void cons_fix_new_sparc
   PARAMS ((struct frag *, int, unsigned int, struct expressionS *));
--- gas/config/tc-sparc.c.jj	Wed Nov 28 21:24:59 2001
+++ gas/config/tc-sparc.c	Fri Dec 21 16:23:52 2001
@@ -3313,6 +3313,12 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_SPARC_UA16:
     case BFD_RELOC_SPARC_UA32:
     case BFD_RELOC_SPARC_UA64:
+    case BFD_RELOC_8_PCREL:
+    case BFD_RELOC_16_PCREL:
+    case BFD_RELOC_32_PCREL:
+    case BFD_RELOC_64_PCREL:
+    case BFD_RELOC_SPARC_PLT32:
+    case BFD_RELOC_SPARC_PLT64:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
       code = fixp->fx_r_type;
@@ -3402,9 +3408,11 @@ tc_gen_reloc (section, fixp)
 
 #else /* elf or coff  */
 
-  if (reloc->howto->pc_relative == 0
-      || code == BFD_RELOC_SPARC_PC10
-      || code == BFD_RELOC_SPARC_PC22)
+  if (code != BFD_RELOC_32_PCREL_S2
+      && code != BFD_RELOC_SPARC_WDISP22
+      && code != BFD_RELOC_SPARC_WDISP16
+      && code != BFD_RELOC_SPARC_WDISP19
+      && code != BFD_RELOC_SPARC_WPLT30)
     reloc->addend = fixp->fx_addnumber;
   else if (symbol_section_p (fixp->fx_addsy))
     reloc->addend = (section->vma
@@ -3900,6 +3908,11 @@ s_proc (ignore)
 
 static int sparc_no_align_cons = 0;
 
+/* This static variable is set by sparc_cons to emit requested types
+   of relocations in cons_fix_new_sparc.  */
+
+static const char *sparc_cons_special_reloc;
+
 /* This handles the unaligned space allocation pseudo-ops, such as
    .uaword.  .uaword is just like .word, but the value does not need
    to be aligned.  */
@@ -4172,6 +4185,134 @@ sparc_elf_final_processing ()
   else if (current_architecture == SPARC_OPCODE_ARCH_V9B)
     elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1|EF_SPARC_SUN_US3;
 }
+
+void
+sparc_cons (exp, size)
+     expressionS *exp;
+     int size;
+{
+  char *save;
+
+  SKIP_WHITESPACE ();
+  sparc_cons_special_reloc = NULL;
+  save = input_line_pointer;
+  if (input_line_pointer[0] == '%'
+      && input_line_pointer[1] == 'r'
+      && input_line_pointer[2] == '_')
+    {
+      if (strncmp (input_line_pointer + 3, "disp", 4) == 0)
+	{
+	  input_line_pointer += 7;
+	  sparc_cons_special_reloc = "disp";
+	}
+      else if (strncmp (input_line_pointer + 3, "plt", 3) == 0)
+	{
+	  if (size != 4 && size != 8)
+	    as_bad (_("Illegal operands: %%r_plt in %d-byte data field"), size);
+	  else
+	    {
+	      input_line_pointer += 6;
+	      sparc_cons_special_reloc = "plt";
+	    }
+	}
+      if (sparc_cons_special_reloc)
+	{
+	  int bad = 0;
+
+	  switch (size)
+	    {
+	    case 1:
+	      if (*input_line_pointer != '8')
+		bad = 1;
+	      input_line_pointer--;
+	      break;
+	    case 2:
+	      if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
+		bad = 1;
+	      break;
+	    case 4:
+	      if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
+		bad = 1;
+	      break;
+	    case 8:
+	      if (input_line_pointer[0] != '6' || input_line_pointer[1] != '4')
+		bad = 1;
+	      break;
+	    default:
+	      bad = 1;
+	      break;
+	    }
+
+	  if (bad)
+	    {
+	      as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
+		      sparc_cons_special_reloc, size * 8, size);
+	    }
+	  else
+	    {
+	      input_line_pointer += 2;
+	      if (*input_line_pointer != '(')
+		{
+		  as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+			  sparc_cons_special_reloc, size * 8);
+		  bad = 1;
+		}
+	    }
+
+	  if (bad)
+	    {
+	      input_line_pointer = save;
+	      sparc_cons_special_reloc = NULL;
+	    }
+	  else
+	    {
+	      int c;
+	      char *end = ++input_line_pointer;
+	      int npar = 0;
+
+	      while (! is_end_of_line[(c = *end)])
+		{
+		  if (c == '(')
+	  	    npar++;
+		  else if (c == ')')
+	  	    {
+		      if (!npar)
+	      		break;
+		      npar--;
+		    }
+	    	  end++;
+		}
+
+	      if (c != ')')
+		as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+			sparc_cons_special_reloc, size * 8);
+	      else
+		{
+		  *end = '\0';
+		  expression (exp);
+		  *end = c;
+		  if (input_line_pointer != end)
+		    {
+		      as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+			      sparc_cons_special_reloc, size * 8);
+		    }
+		  else
+		    {
+		      input_line_pointer++;
+		      SKIP_WHITESPACE ();
+		      c = *input_line_pointer;
+		      if (! is_end_of_line[c] && c != ',')
+			as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
+			        sparc_cons_special_reloc, size * 8);
+		    }
+		}
+	    }
+	}
+    }
+  if (sparc_cons_special_reloc == NULL)
+    expression (exp);
+}
+
 #endif
 
 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
@@ -4196,7 +4337,25 @@ cons_fix_new_sparc (frag, where, nbytes,
       && now_seg->flags & SEC_ALLOC)
     r = BFD_RELOC_SPARC_REV32;
 
-  if (sparc_no_align_cons)
+  if (sparc_cons_special_reloc)
+    {
+      if (*sparc_cons_special_reloc == 'd')
+	switch (nbytes)
+	  {
+	  case 1: r = BFD_RELOC_8_PCREL; break;
+	  case 2: r = BFD_RELOC_16_PCREL; break;
+	  case 4: r = BFD_RELOC_32_PCREL; break;
+	  case 8: r = BFD_RELOC_64_PCREL; break;
+	  default: abort ();
+	  }
+      else
+	switch (nbytes)
+	  {
+	  case 4: r = BFD_RELOC_SPARC_PLT32; break;
+	  case 8: r = BFD_RELOC_SPARC_PLT64; break;
+	  }
+    }
+  else if (sparc_no_align_cons)
     {
       switch (nbytes)
 	{
--- gas/testsuite/gas/sparc/pcrel.s.jj	Fri Dec 21 14:34:12 2001
+++ gas/testsuite/gas/sparc/pcrel.s	Fri Dec 21 14:41:44 2001
@@ -0,0 +1,26 @@
+	.text
+	.align 4
+1:	nop
+2:	nop
+	.globl foo
+foo:	nop
+
+	.data
+	.align 32
+	.word 0
+	.word 1
+	.word 1b + 16
+	.word %r_disp32(1b + 16)
+	.word 1b + 16
+	.word %r_disp32(1b + 16)
+3:	.word foo
+	.word %r_disp32(foo)
+	.word foo + 16
+	.word %r_disp32(foo + 16)
+	.byte %r_disp8(3b)
+	.byte %r_disp8(4f)
+	.half %r_disp16(3b)
+	.half %r_disp16(4f)
+	.uaword 2
+	.half 0
+4:
--- gas/testsuite/gas/sparc/pcrel.d.jj	Fri Dec 21 14:40:36 2001
+++ gas/testsuite/gas/sparc/pcrel.d	Fri Dec 21 15:05:18 2001
@@ -0,0 +1,34 @@
+#as: 
+#objdump: -Dr
+#name: pc relative relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <foo-0x8>:
+   0:	01 00 00 00 	nop 
+   4:	01 00 00 00 	nop 
+
+0+8 <foo>:
+   8:	01 00 00 00 	nop 
+Disassembly of section .data:
+
+0+ <.data>:
+   0:	00 00 00 00 	(unimp|illtrap)  0
+   4:	00 00 00 01 	(unimp|illtrap)  0x1
+	...
+			8: R_SPARC_32	.text\+0x10
+			c: R_SPARC_DISP32	.text\+0x10
+			10: R_SPARC_32	.text\+0x10
+			14: R_SPARC_DISP32	.text\+0x10
+			18: R_SPARC_32	foo
+			1c: R_SPARC_DISP32	foo
+			20: R_SPARC_32	foo\+0x10
+			24: R_SPARC_DISP32	foo\+0x10
+			28: R_SPARC_DISP8	.data\+0x18
+			29: R_SPARC_DISP8	.data\+0x34
+			2a: R_SPARC_DISP16	.data\+0x18
+			2c: R_SPARC_DISP16	.data\+0x34
+  30:	00 02 00 00 	(unimp|illtrap)  0x20000
+	...
--- gas/testsuite/gas/sparc/pcrel64.s.jj	Fri Dec 21 14:47:04 2001
+++ gas/testsuite/gas/sparc/pcrel64.s	Fri Dec 21 14:48:40 2001
@@ -0,0 +1,32 @@
+	.text
+	.align 4
+1:	nop
+2:	nop
+	.globl foo
+foo:	nop
+
+	.data
+	.align 32
+	.word 0
+	.word 1
+	.word 1b + 16
+	.word %r_disp32(1b + 16)
+	.word 1b + 16
+	.word %r_disp32(1b + 16)
+3:	.word foo
+	.word %r_disp32(foo)
+	.word foo + 16
+	.word %r_disp32(foo + 16)
+	.xword 2b + 4
+	.xword %r_disp64(2b + 4)
+	.xword foo
+	.xword %r_disp64(foo)
+	.xword foo + 16
+	.xword %r_disp64(foo + 16)
+	.byte %r_disp8(3b)
+	.byte %r_disp8(4f)
+	.half %r_disp16(3b)
+	.half %r_disp16(4f)
+	.uaword 2
+	.half 0
+4:
--- gas/testsuite/gas/sparc/pcrel64.d.jj	Fri Dec 21 14:48:52 2001
+++ gas/testsuite/gas/sparc/pcrel64.d	Fri Dec 21 15:05:51 2001
@@ -0,0 +1,40 @@
+#as: -64 -K PIC
+#objdump: -Dr
+#name: pc relative 64-bit relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <foo-0x8>:
+   0:	01 00 00 00 	nop 
+   4:	01 00 00 00 	nop 
+
+0+8 <foo>:
+   8:	01 00 00 00 	nop 
+Disassembly of section .data:
+
+0+ <.data>:
+   0:	00 00 00 00 	illtrap  0
+   4:	00 00 00 01 	illtrap  0x1
+	...
+			8: R_SPARC_32	.text\+0x10
+			c: R_SPARC_DISP32	.text\+0x10
+			10: R_SPARC_32	.text\+0x10
+			14: R_SPARC_DISP32	.text\+0x10
+			18: R_SPARC_32	foo
+			1c: R_SPARC_DISP32	foo
+			20: R_SPARC_32	foo\+0x10
+			24: R_SPARC_DISP32	foo\+0x10
+			28: R_SPARC_64	.text\+0x8
+			30: R_SPARC_DISP64	.text\+0x8
+			38: R_SPARC_64	foo
+			40: R_SPARC_DISP64	foo
+			48: R_SPARC_64	foo\+0x10
+			50: R_SPARC_DISP64	foo\+0x10
+			58: R_SPARC_DISP8	.data\+0x18
+			59: R_SPARC_DISP8	.data\+0x64
+			5a: R_SPARC_DISP16	.data\+0x18
+			5c: R_SPARC_DISP16	.data\+0x64
+  60:	00 02 00 00 	illtrap  0x20000
+	...
--- gas/testsuite/gas/sparc/sparc.exp.jj	Wed Jul 11 15:48:52 2001
+++ gas/testsuite/gas/sparc/sparc.exp	Fri Dec 21 16:38:11 2001
@@ -19,6 +19,8 @@ proc gas_64_check { } {
 if [istarget sparc*-*-*] {
     run_dump_test "synth"
     run_dump_test "unalign"
+    run_dump_test "pcrel"
+    run_dump_test "plt"
     if [gas_64_check] {
 	run_dump_test "asi"
 	run_dump_test "membar"
@@ -28,6 +30,8 @@ if [istarget sparc*-*-*] {
 	run_dump_test "rdpr"
 	run_dump_test "wrpr"
 	run_dump_test "reloc64"
+	run_dump_test "pcrel64"
+	run_dump_test "plt64"
     }
 }
 
--- gas/testsuite/gas/sparc/plt.s.jj	Fri Dec 21 16:28:35 2001
+++ gas/testsuite/gas/sparc/plt.s	Fri Dec 21 16:22:54 2001
@@ -0,0 +1,12 @@
+	.text
+	.align 4
+	call	foo
+	 nop
+	call	bar + 4
+	.data
+	.align 4
+	.word	%r_plt32(foo)
+	.word	%r_plt32(bar + 4)
+	.byte	1
+	.uaword	%r_plt32(foo)
+	.byte	2, 3, 4
--- gas/testsuite/gas/sparc/plt.d.jj	Fri Dec 21 16:28:39 2001
+++ gas/testsuite/gas/sparc/plt.d	Fri Dec 21 16:42:39 2001
@@ -0,0 +1,23 @@
+#as: -K PIC
+#objdump: -Dr
+#name: plt relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:	40 00 00 00 	call  0x0
+			0: R_SPARC_WPLT30	foo
+   4:	01 00 00 00 	nop 
+   8:	40 00 00 00 	call  0x8
+			8: R_SPARC_WPLT30	bar\+0x4
+Disassembly of section .data:
+
+0+ <.data>:
+	...
+			0: R_SPARC_PLT32	foo
+			4: R_SPARC_PLT32	bar\+0x4
+   8:	01 00 00 00 	nop 
+			9: R_SPARC_PLT32	foo
+   c:	00 02 03 04 	(unimp|illtrap)  0x20304
--- gas/testsuite/gas/sparc/plt64.s.jj	Fri Dec 21 16:28:52 2001
+++ gas/testsuite/gas/sparc/plt64.s	Fri Dec 21 16:32:28 2001
@@ -0,0 +1,13 @@
+	.text
+	.align 4
+	call	foo
+	 nop
+	call	bar + 4
+	.data
+	.align 8
+	.xword	%r_plt64(foo)
+	.xword	%r_plt64(bar + 4)
+        .byte   1
+	.uaxword %r_plt64(foo)
+	.byte	2, 3, 4
+	.word	%r_plt32(bar + 4)
--- gas/testsuite/gas/sparc/plt64.d.jj	Fri Dec 21 16:30:11 2001
+++ gas/testsuite/gas/sparc/plt64.d	Fri Dec 21 16:42:50 2001
@@ -0,0 +1,26 @@
+#as: -K PIC -64
+#objdump: -Dr
+#name: plt 64-bit relocs
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:	40 00 00 00 	call  0x0
+			0: R_SPARC_WPLT30	foo
+   4:	01 00 00 00 	nop 
+   8:	40 00 00 00 	call  0x8
+			8: R_SPARC_WPLT30	bar\+0x4
+Disassembly of section .data:
+
+0+ <.data>:
+	...
+			0: R_SPARC_PLT64	foo
+			8: R_SPARC_PLT64	bar\+0x4
+  10:	01 00 00 00 	nop 
+			11: R_SPARC_PLT64	foo
+  14:	00 00 00 00 	illtrap  0
+  18:	00 02 03 04 	illtrap  0x20304
+  1c:	00 00 00 00 	illtrap  0
+			1c: R_SPARC_PLT32	bar\+0x4

	Jakub



More information about the Binutils mailing list