svn commit: r275873 - head/contrib/binutils/gas/config

Justin Hibbits jhibbits at FreeBSD.org
Thu Dec 18 03:12:47 UTC 2014


Author: jhibbits
Date: Thu Dec 18 03:12:46 2014
New Revision: 275873
URL: https://svnweb.freebsd.org/changeset/base/275873

Log:
  Make gas parse '__tls_get_addr(foo at tlsgd)'.
  
  Corresponds to 727fc41e077139570ea8b8ddfd6c546b2a55627c.
  
  This allows us to use -no-integrated-as with clang, if we prefer.
  
  Obtained from:	binutils-gdb (Relicensed from Alan Modra as GPLv2)
  MFC after:	2 weeks
  X-MFC-with:	r275718

Modified:
  head/contrib/binutils/gas/config/tc-ppc.c

Modified: head/contrib/binutils/gas/config/tc-ppc.c
==============================================================================
--- head/contrib/binutils/gas/config/tc-ppc.c	Wed Dec 17 21:36:45 2014	(r275872)
+++ head/contrib/binutils/gas/config/tc-ppc.c	Thu Dec 18 03:12:46 2014	(r275873)
@@ -2509,121 +2509,168 @@ md_assemble (char *str)
 				     (char *) NULL, 0);
 	}
 #ifdef OBJ_ELF
-      else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
+      else
 	{
-	  /* Some TLS tweaks.  */
-	  switch (reloc)
+	  if (ex.X_op == O_symbol && str[0] == '(')
 	    {
-	    default:
-	      break;
-	    case BFD_RELOC_PPC_TLS:
-	      insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
-					 (char *) NULL, 0);
-	      break;
-	  /* We'll only use the 32 (or 64) bit form of these relocations
-	     in constants.  Instructions get the 16 bit form.  */
-	    case BFD_RELOC_PPC_DTPREL:
-	      reloc = BFD_RELOC_PPC_DTPREL16;
-	      break;
-	    case BFD_RELOC_PPC_TPREL:
-	      reloc = BFD_RELOC_PPC_TPREL16;
-	      break;
-	    }
+	      const char *sym_name = S_GET_NAME (ex.X_add_symbol);
+	      if (sym_name[0] == '.')
+		++sym_name;
 
-	  /* For the absolute forms of branches, convert the PC
-	     relative form back into the absolute.  */
-	  if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
-	    {
-	      switch (reloc)
+	      if (strcasecmp (sym_name, "__tls_get_addr") == 0)
 		{
-		case BFD_RELOC_PPC_B26:
-		  reloc = BFD_RELOC_PPC_BA26;
-		  break;
-		case BFD_RELOC_PPC_B16:
-		  reloc = BFD_RELOC_PPC_BA16;
-		  break;
-		case BFD_RELOC_PPC_B16_BRTAKEN:
-		  reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
-		  break;
-		case BFD_RELOC_PPC_B16_BRNTAKEN:
-		  reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
-		  break;
-		default:
-		  break;
+		  expressionS tls_exp;
+
+		  hold = input_line_pointer;
+		  input_line_pointer = str + 1;
+		  expression (&tls_exp);
+		  if (tls_exp.X_op == O_symbol)
+		    {
+		      reloc = BFD_RELOC_UNUSED;
+		      if (strncasecmp (input_line_pointer, "@tlsgd)", 7) == 0)
+			{
+			  reloc = BFD_RELOC_PPC_TLSGD;
+			  input_line_pointer += 7;
+			}
+		      else if (strncasecmp (input_line_pointer, "@tlsld)", 7) == 0)
+			{
+			  reloc = BFD_RELOC_PPC_TLSLD;
+			  input_line_pointer += 7;
+			}
+		      if (reloc != BFD_RELOC_UNUSED)
+			{
+			  SKIP_WHITESPACE ();
+			  str = input_line_pointer;
+
+			  if (fc >= MAX_INSN_FIXUPS)
+			    as_fatal (_("too many fixups"));
+			  fixups[fc].exp = tls_exp;
+			  fixups[fc].opindex = *opindex_ptr;
+			  fixups[fc].reloc = reloc;
+			  ++fc;
+			}
+		    }
+		  input_line_pointer = hold;
 		}
 	    }
 
-	  if (ppc_obj64
-	      && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
+	  if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
 	    {
+	      /* Some TLS tweaks.  */
 	      switch (reloc)
 		{
-		case BFD_RELOC_16:
-		  reloc = BFD_RELOC_PPC64_ADDR16_DS;
-		  break;
-		case BFD_RELOC_LO16:
-		  reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
-		  break;
-		case BFD_RELOC_16_GOTOFF:
-		  reloc = BFD_RELOC_PPC64_GOT16_DS;
-		  break;
-		case BFD_RELOC_LO16_GOTOFF:
-		  reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
-		  break;
-		case BFD_RELOC_LO16_PLTOFF:
-		  reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
-		  break;
-		case BFD_RELOC_16_BASEREL:
-		  reloc = BFD_RELOC_PPC64_SECTOFF_DS;
-		  break;
-		case BFD_RELOC_LO16_BASEREL:
-		  reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
-		  break;
-		case BFD_RELOC_PPC_TOC16:
-		  reloc = BFD_RELOC_PPC64_TOC16_DS;
-		  break;
-		case BFD_RELOC_PPC64_TOC16_LO:
-		  reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
-		  break;
-		case BFD_RELOC_PPC64_PLTGOT16:
-		  reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
-		  break;
-		case BFD_RELOC_PPC64_PLTGOT16_LO:
-		  reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
-		  break;
-		case BFD_RELOC_PPC_DTPREL16:
-		  reloc = BFD_RELOC_PPC64_DTPREL16_DS;
-		  break;
-		case BFD_RELOC_PPC_DTPREL16_LO:
-		  reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
-		  break;
-		case BFD_RELOC_PPC_TPREL16:
-		  reloc = BFD_RELOC_PPC64_TPREL16_DS;
+		default:
 		  break;
-		case BFD_RELOC_PPC_TPREL16_LO:
-		  reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
+
+		case BFD_RELOC_PPC_TLS:
+		  insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
+					     (char *) NULL, 0);
 		  break;
-		case BFD_RELOC_PPC_GOT_DTPREL16:
-		case BFD_RELOC_PPC_GOT_DTPREL16_LO:
-		case BFD_RELOC_PPC_GOT_TPREL16:
-		case BFD_RELOC_PPC_GOT_TPREL16_LO:
+
+		  /* We'll only use the 32 (or 64) bit form of these relocations
+		     in constants.  Instructions get the 16 bit form.  */
+		case BFD_RELOC_PPC_DTPREL:
+		  reloc = BFD_RELOC_PPC_DTPREL16;
 		  break;
-		default:
-		  as_bad (_("unsupported relocation for DS offset field"));
+		case BFD_RELOC_PPC_TPREL:
+		  reloc = BFD_RELOC_PPC_TPREL16;
 		  break;
 		}
+
+	      /* For the absolute forms of branches, convert the PC
+		 relative form back into the absolute.  */
+	      if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+		{
+		  switch (reloc)
+		    {
+		    case BFD_RELOC_PPC_B26:
+		      reloc = BFD_RELOC_PPC_BA26;
+		      break;
+		    case BFD_RELOC_PPC_B16:
+		      reloc = BFD_RELOC_PPC_BA16;
+		      break;
+		    case BFD_RELOC_PPC_B16_BRTAKEN:
+		      reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
+		      break;
+		    case BFD_RELOC_PPC_B16_BRNTAKEN:
+		      reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
+		      break;
+		    default:
+		      break;
+		    }
+		}
+
+	      if (ppc_obj64
+		  && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
+		{
+		  switch (reloc)
+		    {
+		    case BFD_RELOC_16:
+		      reloc = BFD_RELOC_PPC64_ADDR16_DS;
+		      break;
+		    case BFD_RELOC_LO16:
+		      reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
+		      break;
+		    case BFD_RELOC_16_GOTOFF:
+		      reloc = BFD_RELOC_PPC64_GOT16_DS;
+		      break;
+		    case BFD_RELOC_LO16_GOTOFF:
+		      reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
+		      break;
+		    case BFD_RELOC_LO16_PLTOFF:
+		      reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
+		      break;
+		    case BFD_RELOC_16_BASEREL:
+		      reloc = BFD_RELOC_PPC64_SECTOFF_DS;
+		      break;
+		    case BFD_RELOC_LO16_BASEREL:
+		      reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
+		      break;
+		    case BFD_RELOC_PPC_TOC16:
+		      reloc = BFD_RELOC_PPC64_TOC16_DS;
+		      break;
+		    case BFD_RELOC_PPC64_TOC16_LO:
+		      reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
+		      break;
+		    case BFD_RELOC_PPC64_PLTGOT16:
+		      reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
+		      break;
+		    case BFD_RELOC_PPC64_PLTGOT16_LO:
+		      reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
+		      break;
+		    case BFD_RELOC_PPC_DTPREL16:
+		      reloc = BFD_RELOC_PPC64_DTPREL16_DS;
+		      break;
+		    case BFD_RELOC_PPC_DTPREL16_LO:
+		      reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
+		      break;
+		    case BFD_RELOC_PPC_TPREL16:
+		      reloc = BFD_RELOC_PPC64_TPREL16_DS;
+		      break;
+		    case BFD_RELOC_PPC_TPREL16_LO:
+		      reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
+		      break;
+		    case BFD_RELOC_PPC_GOT_DTPREL16:
+		    case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+		    case BFD_RELOC_PPC_GOT_TPREL16:
+		    case BFD_RELOC_PPC_GOT_TPREL16_LO:
+		      break;
+		    default:
+		      as_bad (_("unsupported relocation for DS offset field"));
+		      break;
+		    }
+		}
 	    }
 
 	  /* We need to generate a fixup for this expression.  */
 	  if (fc >= MAX_INSN_FIXUPS)
 	    as_fatal (_("too many fixups"));
 	  fixups[fc].exp = ex;
-	  fixups[fc].opindex = 0;
+	  fixups[fc].opindex = *opindex_ptr;
 	  fixups[fc].reloc = reloc;
 	  ++fc;
 	}
-#endif /* OBJ_ELF */
-
+#else /* OBJ_ELF */
       else
 	{
 	  /* We need to generate a fixup for this expression.  */
@@ -2634,6 +2681,7 @@ md_assemble (char *str)
 	  fixups[fc].reloc = BFD_RELOC_UNUSED;
 	  ++fc;
 	}
+#endif /* OBJ_ELF */
 
       if (need_paren)
 	{
@@ -5908,6 +5956,8 @@ md_apply_fix (fixS *fixP, valueT *valP, 
 	  break;
 
 	case BFD_RELOC_PPC_TLS:
+	case BFD_RELOC_PPC_TLSLD:
+	case BFD_RELOC_PPC_TLSGD:
 	  break;
 
 	case BFD_RELOC_PPC_DTPMOD:


More information about the svn-src-head mailing list