This is the mail archive of the binutils@sources.redhat.com 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]

Add lituse_jsrdirect relocation for alpha


In the secureplt format, we clobber more registers than in the old
format, which means that we can not allow the special integer division
routines to be vectored through the plt.

For the most part this can be solved in libc, by not marking the division
routines STT_FUNC.  That works except in the case that the user builds a
shared library but does not link it against libc.  In that case, the linker
would have no information that __divq is special and would vector the call
through the plt anyway, leading to corruption.  While not linking against
all of the required libraries is A Highly Questionable Practice, it did
work before.

This adds a LITUSE form that requests relaxation as for a call, but does
not allow the linker to fall back to a plt entry.  This is backward 
compatible with old linkers, in that LITUSE is, and has always been, a
hint, and we ignore forms that we don't recognize.  Indeed, we ignore 
them to the extent that we won't process them for plt entries either,
which has the desired correctness effect as well.


r~


bfd/
        * elf64-alpha.c (ALPHA_ELF_LINK_HASH_LU_JSRDIRECT): New.
        (ALPHA_ELF_LINK_HASH_TLS_IE): Renumber to 0x80.
        (ALPHA_ELF_LINK_HASH_LU_PLT): Rename from ALPHA_ELF_LINK_HASH_LU_FUNC.
        (elf64_alpha_want_plt): Update to match.
        (elf64_alpha_check_relocs): Collect JSRDIRECT in gotent_flags.
        (elf64_alpha_relax_with_lituse): Likewise.  Handle JSRDIRECT.

binutils/
        * readelf.c (dump_relocations): Special case R_ALPHA_LITUSE.

gas/
	* config/tc-alpha.c (O_lituse_jsrdirect): New.
	(alpha_reloc_op): Add it.
	(debug_exp): Handle it.
	(DUMMY_RELOC_LITUSE_JSRDIRECT): New.
	(emit_insn): Handle it.
	* doc/c-alpha.texi (Alpha-Relocs): Document lituse_jsrdirect.

include/elf/
	* alpha.h (LITUSE_ALPHA_JSRDIRECT): New.


Index: bfd/elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.140
diff -u -p -d -r1.140 elf64-alpha.c
--- bfd/elf64-alpha.c	30 May 2005 21:22:40 -0000	1.140
+++ bfd/elf64-alpha.c	31 May 2005 22:37:03 -0000
@@ -112,14 +112,15 @@ struct alpha_elf_link_hash_entry
   int flags;
 
   /* Contexts in which a literal was referenced.  */
-#define ALPHA_ELF_LINK_HASH_LU_ADDR	0x01
-#define ALPHA_ELF_LINK_HASH_LU_MEM	0x02
-#define ALPHA_ELF_LINK_HASH_LU_BYTE	0x04
-#define ALPHA_ELF_LINK_HASH_LU_JSR	0x08
-#define ALPHA_ELF_LINK_HASH_LU_TLSGD	0x10
-#define ALPHA_ELF_LINK_HASH_LU_TLSLDM	0x20
-#define ALPHA_ELF_LINK_HASH_LU_FUNC	0x38
-#define ALPHA_ELF_LINK_HASH_TLS_IE	0x40
+#define ALPHA_ELF_LINK_HASH_LU_ADDR	 0x01
+#define ALPHA_ELF_LINK_HASH_LU_MEM	 0x02
+#define ALPHA_ELF_LINK_HASH_LU_BYTE	 0x04
+#define ALPHA_ELF_LINK_HASH_LU_JSR	 0x08
+#define ALPHA_ELF_LINK_HASH_LU_TLSGD	 0x10
+#define ALPHA_ELF_LINK_HASH_LU_TLSLDM	 0x20
+#define ALPHA_ELF_LINK_HASH_LU_JSRDIRECT 0x40
+#define ALPHA_ELF_LINK_HASH_LU_PLT	 0x38
+#define ALPHA_ELF_LINK_HASH_TLS_IE	 0x80
 
   /* Used to implement multiple .got subsections.  */
   struct alpha_elf_got_entry
@@ -1729,8 +1730,8 @@ elf64_alpha_want_plt (struct alpha_elf_l
   return ((ah->root.type == STT_FUNC
 	  || ah->root.root.type == bfd_link_hash_undefweak
 	  || ah->root.root.type == bfd_link_hash_undefined)
-	  && (ah->flags & ALPHA_ELF_LINK_HASH_LU_FUNC) != 0
-	  && (ah->flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC) == 0);
+	  && (ah->flags & ALPHA_ELF_LINK_HASH_LU_PLT) != 0
+	  && (ah->flags & ~ALPHA_ELF_LINK_HASH_LU_PLT) == 0);
 }
 
 /* Handle dynamic relocations when doing an Alpha ELF link.  */
@@ -1826,7 +1827,7 @@ elf64_alpha_check_relocs (bfd *abfd, str
 	     This will be important when it comes to decide if we can
 	     create a .plt entry for a function symbol.  */
 	  while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_ALPHA_LITUSE)
-	    if (rel->r_addend >= 1 && rel->r_addend <= 5)
+	    if (rel->r_addend >= 1 && rel->r_addend <= 6)
 	      gotent_flags |= 1 << rel->r_addend;
 	  --rel;
 
@@ -3137,7 +3138,7 @@ elf64_alpha_relax_with_lituse (struct al
     {
       if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
 	break;
-      if (urel->r_addend <= 3)
+      if (urel->r_addend <= 6)
 	flags |= 1 << urel->r_addend;
     }
 
@@ -3232,6 +3233,7 @@ elf64_alpha_relax_with_lituse (struct al
 	case LITUSE_ALPHA_JSR:
 	case LITUSE_ALPHA_TLSGD:
 	case LITUSE_ALPHA_TLSLDM:
+	case LITUSE_ALPHA_JSRDIRECT:
 	  {
 	    bfd_vma optdest, org;
 	    bfd_signed_vma odisp;
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.298
diff -u -p -d -r1.298 readelf.c
--- binutils/readelf.c	29 May 2005 23:18:51 -0000	1.298
+++ binutils/readelf.c	31 May 2005 22:37:07 -0000
@@ -1243,7 +1243,31 @@ dump_relocations (FILE *file,
       else
 	printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
 
-      if (symtab_index)
+      if (elf_header.e_machine == EM_ALPHA
+	  && streq (rtype, "R_ALPHA_LITUSE")
+	  && is_rela)
+	{
+	  switch (rels[i].r_addend)
+	    {
+	    case LITUSE_ALPHA_ADDR:   rtype = "ADDR";   break;
+	    case LITUSE_ALPHA_BASE:   rtype = "BASE";   break;
+	    case LITUSE_ALPHA_BYTOFF: rtype = "BYTOFF"; break;
+	    case LITUSE_ALPHA_JSR:    rtype = "JSR";    break;
+	    case LITUSE_ALPHA_TLSGD:  rtype = "TLSGD";  break;
+	    case LITUSE_ALPHA_TLSLDM: rtype = "TLSLDM"; break;
+	    case LITUSE_ALPHA_JSRDIRECT: rtype = "JSRDIRECT"; break;
+	    default: rtype = NULL;
+	    }
+	  if (rtype)
+	    printf (" (%s)", rtype);
+	  else
+	    {
+	      putchar (' ');
+	      printf (_("<unknown addend: %lx>"),
+		      (unsigned long) rels[i].r_addend);
+	    }
+	}
+      else if (symtab_index)
 	{
 	  if (symtab == NULL || symtab_index >= nsyms)
 	    printf (" bad symbol index: %08lx", (unsigned long) symtab_index);
@@ -1309,8 +1333,7 @@ dump_relocations (FILE *file,
 	  print_vma (rels[i].r_addend, LONG_HEX);
 	}
 
-      if (elf_header.e_machine == EM_SPARCV9
-	  && streq (rtype, "R_SPARC_OLO10"))
+      if (elf_header.e_machine == EM_SPARCV9 && streq (rtype, "R_SPARC_OLO10"))
 	printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
 
       putchar ('\n');
Index: gas/config/tc-alpha.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.c,v
retrieving revision 1.67
diff -u -p -d -r1.67 tc-alpha.c
--- gas/config/tc-alpha.c	5 May 2005 09:12:53 -0000	1.67
+++ gas/config/tc-alpha.c	31 May 2005 22:37:08 -0000
@@ -109,28 +109,29 @@ struct alpha_macro
 #define O_cpregister	O_md2	/* + a leading comma.  */
 
 /* The alpha_reloc_op table below depends on the ordering of these.  */
-#define O_literal	O_md3	/* !literal relocation.  */
-#define O_lituse_addr	O_md4	/* !lituse_addr relocation.  */
-#define O_lituse_base	O_md5	/* !lituse_base relocation.  */
-#define O_lituse_bytoff	O_md6	/* !lituse_bytoff relocation.  */
-#define O_lituse_jsr	O_md7	/* !lituse_jsr relocation.  */
-#define O_lituse_tlsgd	O_md8	/* !lituse_tlsgd relocation.  */
-#define O_lituse_tlsldm	O_md9	/* !lituse_tlsldm relocation.  */
-#define O_gpdisp	O_md10	/* !gpdisp relocation.  */
-#define O_gprelhigh	O_md11	/* !gprelhigh relocation.  */
-#define O_gprellow	O_md12	/* !gprellow relocation.  */
-#define O_gprel		O_md13	/* !gprel relocation.  */
-#define O_samegp	O_md14	/* !samegp relocation.  */
-#define O_tlsgd		O_md15	/* !tlsgd relocation.  */
-#define O_tlsldm	O_md16	/* !tlsldm relocation.  */
-#define O_gotdtprel	O_md17	/* !gotdtprel relocation.  */
-#define O_dtprelhi	O_md18	/* !dtprelhi relocation.  */
-#define O_dtprello	O_md19	/* !dtprello relocation.  */
-#define O_dtprel	O_md20	/* !dtprel relocation.  */
-#define O_gottprel	O_md21	/* !gottprel relocation.  */
-#define O_tprelhi	O_md22	/* !tprelhi relocation.  */
-#define O_tprello	O_md23	/* !tprello relocation.  */
-#define O_tprel		O_md24	/* !tprel relocation.  */
+#define O_literal	O_md3		/* !literal relocation.  */
+#define O_lituse_addr	O_md4		/* !lituse_addr relocation.  */
+#define O_lituse_base	O_md5		/* !lituse_base relocation.  */
+#define O_lituse_bytoff	O_md6		/* !lituse_bytoff relocation.  */
+#define O_lituse_jsr	O_md7		/* !lituse_jsr relocation.  */
+#define O_lituse_tlsgd	O_md8		/* !lituse_tlsgd relocation.  */
+#define O_lituse_tlsldm	O_md9		/* !lituse_tlsldm relocation.  */
+#define O_lituse_jsrdirect O_md10	/* !lituse_jsrdirect relocation.  */
+#define O_gpdisp	O_md11		/* !gpdisp relocation.  */
+#define O_gprelhigh	O_md12		/* !gprelhigh relocation.  */
+#define O_gprellow	O_md13		/* !gprellow relocation.  */
+#define O_gprel		O_md14		/* !gprel relocation.  */
+#define O_samegp	O_md15		/* !samegp relocation.  */
+#define O_tlsgd		O_md16		/* !tlsgd relocation.  */
+#define O_tlsldm	O_md17		/* !tlsldm relocation.  */
+#define O_gotdtprel	O_md18		/* !gotdtprel relocation.  */
+#define O_dtprelhi	O_md19		/* !dtprelhi relocation.  */
+#define O_dtprello	O_md20		/* !dtprello relocation.  */
+#define O_dtprel	O_md21		/* !dtprel relocation.  */
+#define O_gottprel	O_md22		/* !gottprel relocation.  */
+#define O_tprelhi	O_md23		/* !tprelhi relocation.  */
+#define O_tprello	O_md24		/* !tprello relocation.  */
+#define O_tprel		O_md25		/* !tprel relocation.  */
 
 #define DUMMY_RELOC_LITUSE_ADDR		(BFD_RELOC_UNUSED + 1)
 #define DUMMY_RELOC_LITUSE_BASE		(BFD_RELOC_UNUSED + 2)
@@ -138,6 +139,7 @@ struct alpha_macro
 #define DUMMY_RELOC_LITUSE_JSR		(BFD_RELOC_UNUSED + 4)
 #define DUMMY_RELOC_LITUSE_TLSGD	(BFD_RELOC_UNUSED + 5)
 #define DUMMY_RELOC_LITUSE_TLSLDM	(BFD_RELOC_UNUSED + 6)
+#define DUMMY_RELOC_LITUSE_JSRDIRECT	(BFD_RELOC_UNUSED + 7)
 
 #define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_tprel)
 
@@ -418,6 +420,7 @@ alpha_reloc_op[] =
   DEF (lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1),
   DEF (lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1),
   DEF (lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1),
+  DEF (lituse_jsrdirect, DUMMY_RELOC_LITUSE_JSRDIRECT, 1, 1),
   DEF (gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
   DEF (gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
   DEF (gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
@@ -770,6 +773,7 @@ debug_exp (expressionS tok[], int ntok)
 	case O_lituse_jsr:		name = "O_lituse_jsr";		break;
 	case O_lituse_tlsgd:		name = "O_lituse_tlsgd";	break;
 	case O_lituse_tlsldm:		name = "O_lituse_tlsldm";	break;
+	case O_lituse_jsrdirect:	name = "O_lituse_jsrdirect";	break;
 	case O_gpdisp:			name = "O_gpdisp";		break;
 	case O_gprelhigh:		name = "O_gprelhigh";		break;
 	case O_gprellow:		name = "O_gprellow";		break;
@@ -1720,6 +1724,9 @@ emit_insn (struct alpha_insn *insn)
 	case DUMMY_RELOC_LITUSE_TLSLDM:
 	  fixP->fx_offset = LITUSE_ALPHA_TLSLDM;
 	  goto do_lituse;
+	case DUMMY_RELOC_LITUSE_JSRDIRECT:
+	  fixP->fx_offset = LITUSE_ALPHA_JSRDIRECT;
+	  goto do_lituse;
 	do_lituse:
 	  fixP->fx_addsy = section_symbol (now_seg);
 	  fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
Index: include/elf/alpha.h
===================================================================
RCS file: /cvs/src/src/include/elf/alpha.h,v
retrieving revision 1.11
diff -u -p -d -r1.11 alpha.h
--- include/elf/alpha.h	29 May 2005 23:18:26 -0000	1.11
+++ include/elf/alpha.h	31 May 2005 22:37:09 -0000
@@ -125,5 +125,6 @@ END_RELOC_NUMBERS (R_ALPHA_max)
 #define LITUSE_ALPHA_JSR	3
 #define LITUSE_ALPHA_TLSGD	4
 #define LITUSE_ALPHA_TLSLDM	5
+#define LITUSE_ALPHA_JSRDIRECT	6
 
 #endif /* _ELF_ALPHA_H */
? gas/doc/as.info
Index: gas/doc/c-alpha.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-alpha.texi,v
retrieving revision 1.7
diff -u -p -d -r1.7 c-alpha.texi
--- gas/doc/c-alpha.texi	3 Mar 2005 01:29:53 -0000	1.7
+++ gas/doc/c-alpha.texi	31 May 2005 22:50:57 -0000
@@ -203,6 +203,12 @@ Used with a register branch format instr
 indicate that the literal is used for a call.  During relaxation, the
 code may be altered to use a direct branch (e.g.@: @code{bsr}).
 
+@item !lituse_jsrdirect!@var{N}
+Similar to @code{lituse_jsr}, but also that this call cannot be vectored
+through a PLT entry.  This is useful for functions with special calling
+conventions which do not allow the normal call-clobbered registers to be
+clobbered.
+
 @item !lituse_bytoff!@var{N}
 Used with a byte mask instruction (e.g.@: @code{extbl}) to indicate
 that only the low 3 bits of the address are relevant.  During relaxation,


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