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@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:
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to