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]

[PATCH] s390 brasl TLS code morphing.


Hi,
if a 32 bit libc is compiled with the option -march=z990 gcc will
use a "brasl" instruction instead of a "bas" for the function call
to __tls_get_offset in the general dynamic and local dynamic TLS
model. The 32 bit elf bfd can only optimize the "bas" instruction
and generates broken code if a "brasl" instruction is used.
This patch adds the code morphing for the "brasl" instruction to
the 32 bit elf bfd and sets an error in invalid_tls_insn for the
32 and 64 bit bfds if an unknown instruction has been found in the
tls code morphing. 

blue skies,
  Martin.

2006-05-05  Martin Schwidefsky  <schwidefsky@de.ibm.com>

	* elf32-s390.c (invalid_tls_insn): Call bfd_set_error.
	(elf_s390_relocate_section): Add code to do the GD->LE and
	LD->LE TLS linker optimizations if a brasl instruction is used
	for the __tls_get_offset function call.
	* elf64-s390.c (invalid_tls_insn): Call bfd_set_error.

diff -urpN src/bfd/elf32-s390.c src-s390/bfd/elf32-s390.c
--- src/bfd/elf32-s390.c	2006-03-23 11:36:06.000000000 +0100
+++ src-s390/bfd/elf32-s390.c	2006-05-05 14:13:39.000000000 +0200
@@ -2268,6 +2268,7 @@ invalid_tls_insn (input_bfd, input_secti
      input_section,
      (long) rel->r_offset,
      howto->name);
+  bfd_set_error (bfd_error_bad_value);
 }
 
 /* Relocate a 390 ELF section.  */
@@ -2982,16 +2983,44 @@ elf_s390_relocate_section (output_bfd, i
 	      unsigned int insn;
 
 	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-	      if ((insn & 0xff000fff) != 0x4d000000)
+	      if ((insn & 0xff000fff) != 0x4d000000 &&
+		  (insn & 0xffff0000) != 0xc0e50000)
 		invalid_tls_insn (input_bfd, input_section, rel);
 	      if (!info->shared && (h == NULL || h->dynindx == -1))
-		/* GD->LE transition.
-		   bas %r14,0(%rx,%r13) -> bc 0,0  */
-		insn = 0x47000000;
+		{
+		  if ((insn & 0xff000000) == 0x4d000000)
+		    {
+		      /* GD->LE transition.
+			 bas %r14,0(%rx,%r13) -> bc 0,0  */
+		      insn = 0x47000000;
+		    }
+		  else
+		    {
+		      /* GD->LE transition.
+			 brasl %r14,_tls_get_addr@plt -> brcl 0,.  */
+		      insn = 0xc0040000;
+		      bfd_put_16 (output_bfd, 0x0000,
+				  contents + rel->r_offset + 4);
+		    }
+		}
 	      else
-		/* GD->IE transition.
-		   bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12)  */
-		insn = 0x5822c000;
+		{
+		  if ((insn & 0xff000000) == 0x4d000000)
+		    {
+		      /* GD->IE transition.
+			 bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12)  */
+		      insn = 0x5822c000;
+		    }
+		  else
+		    {
+		      /* GD->IE transition.
+			 brasl %r14,__tls_get_addr@plt ->
+			 	l %r2,0(%r2,%r12) ; bcr 0,0 */
+		      insn = 0x5822c000;
+		      bfd_put_16 (output_bfd, 0x0700,
+				  contents + rel->r_offset + 4);
+		    }
+		}
 	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
 	    }
 	  else if (r_type == R_390_TLS_LDCALL)
@@ -3001,11 +3030,23 @@ elf_s390_relocate_section (output_bfd, i
 		  unsigned int insn;
 
 		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-		  if ((insn & 0xff000fff) != 0x4d000000)
+		  if ((insn & 0xff000fff) != 0x4d000000 &&
+		      (insn & 0xffff0000) != 0xc0e50000)
 		    invalid_tls_insn (input_bfd, input_section, rel);
-		  /* LD->LE transition.
-		     bas %r14,0(%rx,%r13) -> bc 0,0  */
-		  insn = 0x47000000;
+		  if ((insn & 0xff000000) == 0x4d000000)
+		    {
+		      /* LD->LE transition.
+			 bas %r14,0(%rx,%r13) -> bc 0,0  */
+		      insn = 0x47000000;
+		    }
+		  else
+		    {
+		      /* LD->LE transition.
+			 brasl %r14,__tls_get_addr@plt -> brcl 0,. */
+		      insn = 0xc0040000;
+		      bfd_put_16 (output_bfd, 0x0000,
+				  contents + rel->r_offset + 4);
+		    }
 		  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
 		}
 	    }
diff -urpN src/bfd/elf64-s390.c src-s390/bfd/elf64-s390.c
--- src/bfd/elf64-s390.c	2006-05-05 14:14:58.000000000 +0200
+++ src-s390/bfd/elf64-s390.c	2006-05-05 14:13:08.000000000 +0200
@@ -2240,6 +2240,7 @@ invalid_tls_insn (input_bfd, input_secti
      input_section,
      (long) rel->r_offset,
      howto->name);
+  bfd_set_error (bfd_error_bad_value);
 }
 
 /* Relocate a 390 ELF section.  */


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