PR 28447: implement multiple parameters for .file on XCOFF
authorClément Chigot <clement.chigot@atos.net>
Fri, 15 Oct 2021 14:12:39 +0000 (16:12 +0200)
committerAlan Modra <amodra@gmail.com>
Wed, 10 Nov 2021 04:13:24 +0000 (14:43 +1030)
On XCOFF, ".file" pseudo-op allows 3 extras parameters to provide
additional information to AIX linker, or its debugger. These are
stored in auxiliary entries of the C_FILE symbol.

bfd/
PR 28447
* coffcode.h (combined_entry_type): Add extrap field.
(coff_bigobj_swap_aux_in): Adjust names of x_file fields.
(coff_bigobj_swap_aux_out): Likewise.
* coffgen.c (coff_write_auxent_fname): New function.
(coff_fix_symbol_name): Write x_file using
 coff_write_auxent_fname.
(coff_write_symbol): Likewise.
(coff_write_symbols): Add C_FILE auxiliary entries to
string table if needed.
(coff_get_normalized_symtab): Adjust names of x_file fields.
Normalize C_FILE auxiliary entries.
(coff_print_symbol): Print C_FILE auxiliary entries.
* coff-rs6000.c (_bfd_xcoff_swap_aux_in): Adjust names of
x_file fields.
(_bfd_xcoff_swap_aux_out): Likewise.
* coff64-rs6000.c (_bfd_xcoff64_swap_aux_in): Likewise.
(_bfd_xcoff64_swap_aux_out): Likewise.
* cofflink.c (_bfd_coff_final_link): Likewise.
(_bfd_coff_link_input_bfd): Likewise.
* coffswap.h (coff_swap_aux_in): Likewise.
* peXXigen.c (_bfd_XXi_swap_aux_in): Likewise.
(_bfd_XXi_swap_aux_out): Likewise.
* xcofflink.c (xcoff_link_input_bfd): Likewise.
* libcoff.h: Regenerate.
gas/
* config/tc-ppc.c (ppc_file): New function.
* config/tc-ppc.h (OBJ_COFF_MAX_AUXENTRIES): Change to 4.
* testsuite/gas/ppc/aix.exp: Add tests.
* testsuite/gas/ppc/xcoff-file-32.d: New test.
* testsuite/gas/ppc/xcoff-file-64.d: New test.
* testsuite/gas/ppc/xcoff-file.s: New test.
include/
* coff/internal.h (union internal_auxent): Change x_file to be a
  struct instead of a union. Add x_ftype field.
* coff/rs6000.h (union external_auxent): Add x_resv field.
* coff/xcoff.h (XFT_FN): New define.
(XFT_CT): Likewise.
(XFT_CV): Likewise.
(XFT_CD): Likewise.

18 files changed:
bfd/coff-rs6000.c
bfd/coff64-rs6000.c
bfd/coffcode.h
bfd/coffgen.c
bfd/cofflink.c
bfd/coffswap.h
bfd/libcoff.h
bfd/peXXigen.c
bfd/xcofflink.c
gas/config/tc-ppc.c
gas/config/tc-ppc.h
gas/testsuite/gas/ppc/aix.exp
gas/testsuite/gas/ppc/xcoff-file-32.d [new file with mode: 0644]
gas/testsuite/gas/ppc/xcoff-file-64.d [new file with mode: 0644]
gas/testsuite/gas/ppc/xcoff-file.s [new file with mode: 0644]
include/coff/internal.h
include/coff/rs6000.h
include/coff/xcoff.h

index 31d91190103a9be5434c6d900e9385638a155e25..1cc2162e7d819c7dddd81944e8e04214f09982a5 100644 (file)
@@ -489,12 +489,13 @@ _bfd_xcoff_swap_aux_in (bfd *abfd, void * ext1, int type ATTRIBUTE_UNUSED,
     case C_FILE:
       if (ext->x_file.x_n.x_fname[0] == 0)
        {
-         in->x_file.x_n.x_zeroes = 0;
-         in->x_file.x_n.x_offset =
+         in->x_file.x_n.x_n.x_zeroes = 0;
+         in->x_file.x_n.x_n.x_offset =
            H_GET_32 (abfd, ext->x_file.x_n.x_n.x_offset);
        }
       else
-       memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+       memcpy (in->x_file.x_n.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+      in->x_file.x_ftype = H_GET_8 (abfd, ext->x_file.x_ftype);
       break;
 
       /* RS/6000 "csect" auxents.
@@ -573,14 +574,15 @@ _bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type ATTRIBUTE_UNUSED,
       break;
 
     case C_FILE:
-      if (in->x_file.x_fname[0] == 0)
+      if (in->x_file.x_n.x_fname[0] == 0)
        {
          H_PUT_32 (abfd, 0, ext->x_file.x_n.x_n.x_zeroes);
-         H_PUT_32 (abfd, in->x_file.x_n.x_offset,
+         H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset,
                    ext->x_file.x_n.x_n.x_offset);
        }
       else
-       memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
+       memcpy (ext->x_file.x_n.x_fname, in->x_file.x_n.x_fname, FILNMLEN);
+      H_PUT_8 (abfd, in->x_file.x_ftype, ext->x_file.x_ftype);
       break;
 
       /* RS/6000 "csect" auxents */
index 8c206959fd344ac8587b4047f4d01f8a1d3b74b4..95a31b606c8440a7bfe8c2c9f70dd416a7d1c8d1 100644 (file)
@@ -386,12 +386,13 @@ _bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type ATTRIBUTE_UNUSED,
 
       if (ext->x_file.x_n.x_n.x_zeroes[0] == 0)
        {
-         in->x_file.x_n.x_zeroes = 0;
-         in->x_file.x_n.x_offset =
+         in->x_file.x_n.x_n.x_zeroes = 0;
+         in->x_file.x_n.x_n.x_offset =
            H_GET_32 (abfd, ext->x_file.x_n.x_n.x_offset);
        }
       else
-       memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+       memcpy (in->x_file.x_n.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+      in->x_file.x_ftype = H_GET_8 (abfd, ext->x_file.x_ftype);
       break;
 
       /* RS/6000 "csect" auxents.
@@ -499,14 +500,15 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type ATTRIBUTE_UNUSED,
       break;
 
     case C_FILE:
-      if (in->x_file.x_n.x_zeroes == 0)
+      if (in->x_file.x_n.x_n.x_zeroes == 0)
        {
          H_PUT_32 (abfd, 0, ext->x_file.x_n.x_n.x_zeroes);
-         H_PUT_32 (abfd, in->x_file.x_n.x_offset,
+         H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset,
                    ext->x_file.x_n.x_n.x_offset);
        }
       else
-       memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
+       memcpy (ext->x_file.x_n.x_fname, in->x_file.x_n.x_fname, FILNMLEN);
+      H_PUT_8 (abfd, in->x_file.x_ftype, ext->x_file.x_ftype);
       H_PUT_8 (abfd, _AUX_FILE, ext->x_file.x_auxtype);
       break;
 
index 7967cedf918b086a129c1c918af6520b29ab2034..f0b73a988810bd72bb49aef982ccdf9d7ccaa383 100644 (file)
@@ -326,6 +326,10 @@ CODE_FRAGMENT
 .
 . {* Selector for the union above.  *}
 . bool is_sym;
+.
+. {* An extra pointer which can used by format based on COFF (like XCOFF)
+.    to provide extra information to their backend.  *}
+. void *extrap;
 .} combined_entry_type;
 .
 .
@@ -5663,11 +5667,11 @@ coff_bigobj_swap_aux_in (bfd *abfd,
       if (numaux > 1)
        {
          if (indx == 0)
-           memcpy (in->x_file.x_fname, ext->File.Name,
+           memcpy (in->x_file.x_n.x_fname, ext->File.Name,
                    numaux * sizeof (AUXENT_BIGOBJ));
        }
       else
-       memcpy (in->x_file.x_fname, ext->File.Name, sizeof (ext->File.Name));
+       memcpy (in->x_file.x_n.x_fname, ext->File.Name, sizeof (ext->File.Name));
       break;
 
     case C_STAT:
@@ -5712,7 +5716,7 @@ coff_bigobj_swap_aux_out (bfd * abfd,
   switch (in_class)
     {
     case C_FILE:
-      memcpy (ext->File.Name, in->x_file.x_fname, sizeof (ext->File.Name));
+      memcpy (ext->File.Name, in->x_file.x_n.x_fname, sizeof (ext->File.Name));
 
       return AUXESZ;
 
index 6627a9af4b6607849432bca258971d8d7980f58d..40f1ac718e48c74f1a95576a6ed9aa2c8a79f2af 100644 (file)
@@ -847,6 +847,34 @@ coff_mangle_symbols (bfd *bfd_ptr)
     }
 }
 
+static void
+coff_write_auxent_fname (bfd *abfd,
+                        char *str,
+                        union internal_auxent *auxent,
+                        bfd_size_type *string_size_p)
+{
+  unsigned int str_length = strlen (str);
+  unsigned int filnmlen = bfd_coff_filnmlen (abfd);
+
+  if (bfd_coff_long_filenames (abfd))
+    {
+      if (str_length <= filnmlen)
+       strncpy (auxent->x_file.x_n.x_fname, str, filnmlen);
+      else
+       {
+         auxent->x_file.x_n.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
+         auxent->x_file.x_n.x_n.x_zeroes = 0;
+         *string_size_p += str_length + 1;
+       }
+    }
+  else
+    {
+      strncpy (auxent->x_file.x_n.x_fname, str, filnmlen);
+      if (str_length > filnmlen)
+       str[filnmlen] = '\0';
+    }
+}
+
 static void
 coff_fix_symbol_name (bfd *abfd,
                      asymbol *symbol,
@@ -856,7 +884,6 @@ coff_fix_symbol_name (bfd *abfd,
                      bfd_size_type *debug_string_size_p)
 {
   unsigned int name_length;
-  union internal_auxent *auxent;
   char *name = (char *) (symbol->name);
 
   if (name == NULL)
@@ -871,8 +898,6 @@ coff_fix_symbol_name (bfd *abfd,
   if (native->u.syment.n_sclass == C_FILE
       && native->u.syment.n_numaux > 0)
     {
-      unsigned int filnmlen;
-
       if (bfd_coff_force_symnames_in_strings (abfd))
        {
          native->u.syment._n._n_n._n_offset =
@@ -884,27 +909,8 @@ coff_fix_symbol_name (bfd *abfd,
        strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
 
       BFD_ASSERT (! (native + 1)->is_sym);
-      auxent = &(native + 1)->u.auxent;
-
-      filnmlen = bfd_coff_filnmlen (abfd);
-
-      if (bfd_coff_long_filenames (abfd))
-       {
-         if (name_length <= filnmlen)
-           strncpy (auxent->x_file.x_fname, name, filnmlen);
-         else
-           {
-             auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
-             auxent->x_file.x_n.x_zeroes = 0;
-             *string_size_p += name_length + 1;
-           }
-       }
-      else
-       {
-         strncpy (auxent->x_file.x_fname, name, filnmlen);
-         if (name_length > filnmlen)
-           name[filnmlen] = '\0';
-       }
+      coff_write_auxent_fname (abfd, name, &(native + 1)->u.auxent,
+                              string_size_p);
     }
   else
     {
@@ -1029,6 +1035,11 @@ coff_write_symbol (bfd *abfd,
       for (j = 0; j < native->u.syment.n_numaux; j++)
        {
          BFD_ASSERT (! (native + j + 1)->is_sym);
+
+         if (native->u.syment.n_sclass == C_FILE && j > 0)
+           coff_write_auxent_fname (abfd, (char *) (native + j + 1)->extrap,
+                                    &(native + j + 1)->u.auxent, string_size_p);
+
          bfd_coff_swap_aux_out (abfd,
                                 &((native + j + 1)->u.auxent),
                                 type, n_sclass, (int) j,
@@ -1358,6 +1369,7 @@ coff_write_symbols (bfd *abfd)
          size_t name_length = strlen (q->name);
          coff_symbol_type *c_symbol = coff_symbol_from (q);
          size_t maxlen;
+         bool is_c_file = false;
 
          /* Figure out whether the symbol name should go in the string
             table.  Symbol names that are short enough are stored
@@ -1384,6 +1396,7 @@ coff_write_symbols (bfd *abfd)
          else if (c_symbol->native->u.syment.n_sclass == C_FILE
                   && c_symbol->native->u.syment.n_numaux > 0)
            {
+             is_c_file=true;
              if (bfd_coff_force_symnames_in_strings (abfd))
                {
                  if (bfd_bwrite (".file", (bfd_size_type) 6, abfd) != 6)
@@ -1400,6 +1413,30 @@ coff_write_symbols (bfd *abfd)
                             abfd) != name_length + 1)
                return false;
            }
+
+         /* Add strings for C_FILE aux entries. */
+         if (is_c_file
+             && c_symbol->native->u.syment.n_numaux > 1)
+           {
+             for (int j = 1; j < c_symbol->native->u.syment.n_numaux; j++)
+               {
+                 char *str;
+                 size_t str_length;
+
+                 if (c_symbol->native[j + 1].u.auxent.x_file.x_n.x_fname[0] != 0)
+                   continue;
+
+                 str = (char *) c_symbol->native[j + 1].extrap;
+                 str_length = strlen (str);
+                 if (str_length > maxlen)
+                   {
+                     if (bfd_bwrite ((void *) (str), (bfd_size_type) str_length + 1,
+                                     abfd) != str_length + 1)
+                       return false;
+                   }
+
+               }
+           }
        }
     }
   else
@@ -1872,7 +1909,7 @@ coff_get_normalized_symtab (bfd *abfd)
             the text ".file" is redundant.  */
          BFD_ASSERT (! aux->is_sym);
 
-         if (aux->u.auxent.x_file.x_n.x_zeroes == 0)
+         if (aux->u.auxent.x_file.x_n.x_n.x_zeroes == 0)
            {
              /* The filename is a long one, point into the string table.  */
              if (string_table == NULL)
@@ -1882,12 +1919,12 @@ coff_get_normalized_symtab (bfd *abfd)
                    return NULL;
                }
 
-             if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_offset)
+             if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_n.x_offset)
                  >= obj_coff_strings_len (abfd))
                internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
              else
                internal_ptr->u.syment._n._n_n._n_offset =
-                 (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_offset));
+                 (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_n.x_offset));
            }
          else
            {
@@ -1899,15 +1936,48 @@ coff_get_normalized_symtab (bfd *abfd)
                internal_ptr->u.syment._n._n_n._n_offset =
                  (bfd_hostptr_t)
                  copy_name (abfd,
-                            aux->u.auxent.x_file.x_fname,
+                            aux->u.auxent.x_file.x_n.x_fname,
                             internal_ptr->u.syment.n_numaux * symesz);
              else
                internal_ptr->u.syment._n._n_n._n_offset =
                  ((bfd_hostptr_t)
                   copy_name (abfd,
-                             aux->u.auxent.x_file.x_fname,
+                             aux->u.auxent.x_file.x_n.x_fname,
                              (size_t) bfd_coff_filnmlen (abfd)));
            }
+
+         /* Normalize other strings available in C_FILE aux entries.  */
+         if (!coff_data (abfd)->pe)
+           for (int numaux = 1; numaux < internal_ptr->u.syment.n_numaux; numaux++)
+             {
+               aux = internal_ptr + numaux + 1;
+               BFD_ASSERT (! aux->is_sym);
+
+               if (aux->u.auxent.x_file.x_n.x_n.x_zeroes == 0)
+                 {
+                   /* The string information is a long one, point into the string table.  */
+                   if (string_table == NULL)
+                     {
+                       string_table = _bfd_coff_read_string_table (abfd);
+                       if (string_table == NULL)
+                         return NULL;
+                     }
+
+                   if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_n.x_offset)
+                       >= obj_coff_strings_len (abfd))
+                     aux->u.auxent.x_file.x_n.x_n.x_offset = (bfd_hostptr_t) _("<corrupt>");
+                   else
+                     aux->u.auxent.x_file.x_n.x_n.x_offset =
+                       (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_n.x_offset));
+                 }
+               else
+                 aux->u.auxent.x_file.x_n.x_n.x_offset =
+                   ((bfd_hostptr_t)
+                    copy_name (abfd,
+                               aux->u.auxent.x_file.x_n.x_fname,
+                               (size_t) bfd_coff_filnmlen (abfd)));
+             }
+
        }
       else
        {
@@ -2135,6 +2205,12 @@ coff_print_symbol (bfd *abfd,
                {
                case C_FILE:
                  fprintf (file, "File ");
+                 /* Add additional information if this isn't the filename
+                    auxiliary entry.  */
+                 if (aux)
+                   fprintf (file, "ftype %d fname \"%s\"",
+                            auxp->u.auxent.x_file.x_ftype,
+                            (char *) auxp->u.auxent.x_file.x_n.x_n.x_offset);
                  break;
 
                case C_DWARF:
index b8a370933be68c6419e5c61454073599c9424859..67d9c62b0b44fc2bb10c1ea3b11764b1f96faecc 100644 (file)
@@ -963,7 +963,7 @@ _bfd_coff_final_link (bfd *abfd,
                  else
                    {
                      BFD_ASSERT (isym.n_numaux == 1);
-                     iaux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+                     iaux.x_file.x_n.x_n.x_offset = STRING_SIZE_SIZE + indx;
                      bfd_coff_swap_aux_out (abfd, &iaux, isym.n_type, C_FILE,
                                             0, 1, flaginfo.outsyms + symesz);
                      if (bfd_seek (abfd, pos + symesz, SEEK_SET) != 0
@@ -2006,13 +2006,13 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
                {
                  /* If this is a long filename, we must put it in the
                     string table.  */
-                 if (auxp->x_file.x_n.x_zeroes == 0
-                     && auxp->x_file.x_n.x_offset != 0)
+                 if (auxp->x_file.x_n.x_n.x_zeroes == 0
+                     && auxp->x_file.x_n.x_n.x_offset != 0)
                    {
                      const char *filename;
                      bfd_size_type indx;
 
-                     BFD_ASSERT (auxp->x_file.x_n.x_offset
+                     BFD_ASSERT (auxp->x_file.x_n.x_n.x_offset
                                  >= STRING_SIZE_SIZE);
                      if (strings == NULL)
                        {
@@ -2020,15 +2020,15 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
                          if (strings == NULL)
                            return false;
                        }
-                     if ((bfd_size_type) auxp->x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd))
+                     if ((bfd_size_type) auxp->x_file.x_n.x_n.x_offset >= obj_coff_strings_len (input_bfd))
                        filename = _("<corrupt>");
                      else
-                       filename = strings + auxp->x_file.x_n.x_offset;
+                       filename = strings + auxp->x_file.x_n.x_n.x_offset;
                      indx = _bfd_stringtab_add (flaginfo->strtab, filename,
                                                 hash, copy);
                      if (indx == (bfd_size_type) -1)
                        return false;
-                     auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+                     auxp->x_file.x_n.x_n.x_offset = STRING_SIZE_SIZE + indx;
                    }
                }
              else if ((isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
index e0dbd04f399611997198bfde66c79d3b2a95f10d..a8bd932daf7e08e97dffd4bdb1611d74d96c26ee 100644 (file)
@@ -418,8 +418,8 @@ coff_swap_aux_in (bfd *abfd,
     case C_FILE:
       if (ext->x_file.x_fname[0] == 0)
        {
-         in->x_file.x_n.x_zeroes = 0;
-         in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
+         in->x_file.x_n.x_n.x_zeroes = 0;
+         in->x_file.x_n.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
        }
       else
        {
@@ -429,11 +429,11 @@ coff_swap_aux_in (bfd *abfd,
          if (numaux > 1 && coff_data (abfd)->pe)
            {
              if (indx == 0)
-               memcpy (in->x_file.x_fname, ext->x_file.x_fname,
+               memcpy (in->x_file.x_n.x_fname, ext->x_file.x_fname,
                        numaux * sizeof (AUXENT));
            }
          else
-           memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+           memcpy (in->x_file.x_n.x_fname, ext->x_file.x_fname, FILNMLEN);
 #endif
        }
       goto end;
@@ -522,17 +522,17 @@ coff_swap_aux_out (bfd * abfd,
   switch (in_class)
     {
     case C_FILE:
-      if (in->x_file.x_fname[0] == 0)
+      if (in->x_file.x_n.x_fname[0] == 0)
        {
          H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
-         H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
+         H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset, ext->x_file.x_n.x_offset);
        }
       else
        {
 #if FILNMLEN != E_FILNMLEN
 #error we need to cope with truncating or extending FILNMLEN
 #else
-         memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
+         memcpy (ext->x_file.x_fname, in->x_file.x_n.x_fname, FILNMLEN);
 #endif
        }
       goto end;
index 6dc68d1a39876be3003073c185e4523815e34446..1b4f988bb0be810cdfd5bcc4b7bed457a6f185ca 100644 (file)
@@ -658,6 +658,10 @@ typedef struct coff_ptr_struct
 
  /* Selector for the union above.  */
  bool is_sym;
+
+ /* An extra pointer which can used by format based on COFF (like XCOFF)
+    to provide extra information to their backend.  */
+ void *extrap;
 } combined_entry_type;
 
 
index c41c3299277846875ee7eca9ca00e530b2683d61..e2a9cbb65c1925451d932530d89ee880b1374eb4 100644 (file)
@@ -298,11 +298,11 @@ _bfd_XXi_swap_aux_in (bfd *       abfd,
     case C_FILE:
       if (ext->x_file.x_fname[0] == 0)
        {
-         in->x_file.x_n.x_zeroes = 0;
-         in->x_file.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
+         in->x_file.x_n.x_n.x_zeroes = 0;
+         in->x_file.x_n.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_offset);
        }
       else
-       memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+       memcpy (in->x_file.x_n.x_fname, ext->x_file.x_fname, FILNMLEN);
       return;
 
     case C_STAT:
@@ -370,13 +370,13 @@ _bfd_XXi_swap_aux_out (bfd *  abfd,
   switch (in_class)
     {
     case C_FILE:
-      if (in->x_file.x_fname[0] == 0)
+      if (in->x_file.x_n.x_fname[0] == 0)
        {
          H_PUT_32 (abfd, 0, ext->x_file.x_n.x_zeroes);
-         H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
+         H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset, ext->x_file.x_n.x_offset);
        }
       else
-       memcpy (ext->x_file.x_fname, in->x_file.x_fname, sizeof (ext->x_file.x_fname));
+       memcpy (ext->x_file.x_fname, in->x_file.x_n.x_fname, sizeof (ext->x_file.x_fname));
 
       return AUXESZ;
 
index 3ca74ce02774f336442f683c329630c2e042b161..e87ed0e683b5e4380d16c858fc24743f14e30e8e 100644 (file)
@@ -4550,13 +4550,13 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
                  /* This is the file name (or some comment put in by
                     the compiler).  If it is long, we must put it in
                     the string table.  */
-                 if (aux.x_file.x_n.x_zeroes == 0
-                     && aux.x_file.x_n.x_offset != 0)
+                 if (aux.x_file.x_n.x_n.x_zeroes == 0
+                     && aux.x_file.x_n.x_n.x_offset != 0)
                    {
                      const char *filename;
                      bfd_size_type indx;
 
-                     BFD_ASSERT (aux.x_file.x_n.x_offset
+                     BFD_ASSERT (aux.x_file.x_n.x_n.x_offset
                                  >= STRING_SIZE_SIZE);
                      if (strings == NULL)
                        {
@@ -4564,15 +4564,15 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
                          if (strings == NULL)
                            return false;
                        }
-                     if ((bfd_size_type) aux.x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd))
+                     if ((bfd_size_type) aux.x_file.x_n.x_n.x_offset >= obj_coff_strings_len (input_bfd))
                        filename = _("<corrupt>");
                      else
-                       filename = strings + aux.x_file.x_n.x_offset;
+                       filename = strings + aux.x_file.x_n.x_n.x_offset;
                      indx = _bfd_stringtab_add (flinfo->strtab, filename,
                                                 hash, copy);
                      if (indx == (bfd_size_type) -1)
                        return false;
-                     aux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+                     aux.x_file.x_n.x_n.x_offset = STRING_SIZE_SIZE + indx;
                    }
                }
              else if (CSECT_SYM_P (isymp->n_sclass)
index af025af32ffc97a125249f52ceacd1ce2d1fe8a0..8750e379158a4e26cdcb2161eaca2912948bcd97 100644 (file)
@@ -107,6 +107,7 @@ static void ppc_es (int);
 static void ppc_csect (int);
 static void ppc_dwsect (int);
 static void ppc_change_csect (symbolS *, offsetT);
+static void ppc_file (int);
 static void ppc_function (int);
 static void ppc_extern (int);
 static void ppc_lglobl (int);
@@ -227,6 +228,7 @@ const pseudo_typeS md_pseudo_table[] =
   { "ei",      ppc_biei,       1 },
   { "es",      ppc_es,         0 },
   { "extern",  ppc_extern,     0 },
+  { "file",    ppc_file,       0 },
   { "function",        ppc_function,   0 },
   { "lglobl",  ppc_lglobl,     0 },
   { "ref",     ppc_ref,        0 },
@@ -5073,6 +5075,67 @@ ppc_stabx (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* The .file pseudo-op. On XCOFF, .file can have several parameters
+   which are being added to the symbol table to provide additional
+   information.  */
+
+static void
+ppc_file (int ignore ATTRIBUTE_UNUSED)
+{
+  char *sfname, *s1 = NULL, *s2 = NULL, *s3 = NULL;
+  int length, auxnb = 1;
+
+  /* Some assemblers tolerate immediately following '"'.  */
+  if ((sfname = demand_copy_string (&length)) != 0)
+    {
+      coff_symbol_type *coffsym;
+      if (*input_line_pointer == ',')
+       {
+         ++input_line_pointer;
+         s1 = demand_copy_string (&length);
+         auxnb++;
+
+         if (*input_line_pointer == ',')
+           {
+             ++input_line_pointer;
+             s2 = demand_copy_string (&length);
+             auxnb++;
+
+             if (*input_line_pointer == ',')
+               {
+                 ++input_line_pointer;
+                 s3 = demand_copy_string (&length);
+                 auxnb++;
+               }
+           }
+       }
+
+      /* Use coff dot_file creation and adjust auxiliary entries.  */
+      c_dot_file_symbol (sfname, 0);
+      S_SET_NUMBER_AUXILIARY (symbol_rootP, auxnb);
+      coffsym = coffsymbol (symbol_get_bfdsym (symbol_rootP));
+      coffsym->native[1].u.auxent.x_file.x_ftype = XFT_FN;
+
+      if (s1)
+       {
+         coffsym->native[2].u.auxent.x_file.x_ftype = XFT_CT;
+         coffsym->native[2].extrap = s1;
+       }
+      if (s2)
+       {
+         coffsym->native[3].u.auxent.x_file.x_ftype = XFT_CV;
+         coffsym->native[3].extrap = s2;
+       }
+      if (s3)
+       {
+         coffsym->native[4].u.auxent.x_file.x_ftype = XFT_CD;
+         coffsym->native[4].extrap = s3;
+       }
+
+      demand_empty_rest_of_line ();
+    }
+}
+
 /* The .function pseudo-op.  This takes several arguments.  The first
    argument seems to be the external name of the symbol.  The second
    argument seems to be the label for the start of the function.  gcc
index fb18730db3c8110630d19e033c2bf86238beb21b..2d0a8865d98c895feaa31533258e1afd865ad0e3 100644 (file)
@@ -146,7 +146,7 @@ struct ppc_tc_sy
 #define TC_SYMFIELD_TYPE struct ppc_tc_sy
 
 /* We need an additional auxent for function symbols.  */
-#define OBJ_COFF_MAX_AUXENTRIES 2
+#define OBJ_COFF_MAX_AUXENTRIES 4
 
 /* Square and curly brackets are permitted in symbol names.  */
 #define LEX_BR 3
index aef295bc3b9098ad21ca63f72b1513e74e8d0490..c6d10d5fb84b76586e865b727a6f9dc29ed0b26e 100644 (file)
@@ -84,4 +84,7 @@ if { [istarget "powerpc*-*-aix*"] || [istarget "rs6000-*-aix*"] } then {
 
     run_dump_test "xcoff-stsym-32"
     run_dump_test "xcoff-stsym-64"
+
+    run_dump_test "xcoff-file-32"
+    run_dump_test "xcoff-file-64"
 }
diff --git a/gas/testsuite/gas/ppc/xcoff-file-32.d b/gas/testsuite/gas/ppc/xcoff-file-32.d
new file mode 100644 (file)
index 0000000..a831b3b
--- /dev/null
@@ -0,0 +1,13 @@
+#as: -a32
+#source: xcoff-file.s
+#objdump: -t
+#name: XCOFF file test (32-bit)
+
+.*
+
+SYMBOL TABLE:
+\[  0\].*\(scl 103\) \(nx 4\) .* file.s
+File 
+File ftype 1 fname "A long string"
+File ftype 2 fname "short"
+File ftype 128 fname "Another long string inside the strign table."
diff --git a/gas/testsuite/gas/ppc/xcoff-file-64.d b/gas/testsuite/gas/ppc/xcoff-file-64.d
new file mode 100644 (file)
index 0000000..12bb6ef
--- /dev/null
@@ -0,0 +1,13 @@
+#as: -a64
+#source: xcoff-file.s
+#objdump: -t
+#name: XCOFF file test (64-bit)
+
+.*
+
+SYMBOL TABLE:
+\[  0\].*\(scl 103\) \(nx 4\) .* file.s
+File 
+File ftype 1 fname "A long string"
+File ftype 2 fname "short"
+File ftype 128 fname "Another long string inside the strign table."
diff --git a/gas/testsuite/gas/ppc/xcoff-file.s b/gas/testsuite/gas/ppc/xcoff-file.s
new file mode 100644 (file)
index 0000000..229ab88
--- /dev/null
@@ -0,0 +1 @@
+.file "file.s", "A long string", "short", "Another long string inside the strign table."
index 8d757acb333ba6c1e36a0e9d7329412d62e37f0f..d01af7380c86a9d631038d3f50a432d8d869007b 100644 (file)
@@ -578,18 +578,21 @@ union internal_auxent
     unsigned short x_tvndx;    /* tv index */
   }      x_sym;
 
-  union
+  struct
   {
-    /* PR 17754: We use to FILNMLEN for the size of the x_fname
-       array, but that causes problems as PE targets use a larger
-       value.  We cannot use their definition of E_FILNMLEN as this
-       header can be used without including any PE headers.  */
-    char x_fname[20];
-    struct
-    {
-      long x_zeroes;
-      long x_offset;
-    }      x_n;
+    union {
+      /* PR 17754: We use to FILNMLEN for the size of the x_fname
+        array, but that causes problems as PE targets use a larger
+        value.  We cannot use their definition of E_FILNMLEN as this
+        header can be used without including any PE headers.  */
+      char x_fname[20];
+      struct
+      {
+       long x_zeroes;
+       long x_offset;
+      }      x_n;
+    } x_n;
+    unsigned char x_ftype;
   }     x_file;
 
   struct
index e60efff23b6d1b633ddfac668cd4bcf93babe307..fd3f01dccbc560f6f94ee9e333156fdbac8cee62 100644 (file)
@@ -176,6 +176,7 @@ union external_auxent {
       } x_n;
     } x_n;
     char x_ftype[1];
+    char x_resv[3];
   } x_file;
 
   struct {
index 2b61545d611760f0697d93b497417b9ac50daac2..1cff7dc30d5ec0c3443f00bb527f5433bfb2f630 100644 (file)
 #define XMC_UL     21          /* Read-write uninitialized TLS data */
 #define XMC_TE     22          /* Same as XMC_TC but mapped after it */
 
+/* x_ftype values:  */
+#define XFT_FN 0    /* Specifies the source-file name */
+#define XFT_CT 1    /* Specifies the compiler time stamp */
+#define XFT_CV 2    /* Specifies the compiler version number */
+#define XFT_CD 128  /*Specifies compiler-defined information */
+
 /* The ldhdr structure.  This appears at the start of the .loader
    section.  */