From e86fc4a5bc3747a6b811d93648a2afa4c1c74217 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Cl=C3=A9ment=20Chigot?= Date: Fri, 15 Oct 2021 16:12:39 +0200 Subject: [PATCH] PR 28447: implement multiple parameters for .file on XCOFF 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. --- bfd/coff-rs6000.c | 14 +-- bfd/coff64-rs6000.c | 14 +-- bfd/coffcode.h | 10 +- bfd/coffgen.c | 134 ++++++++++++++++++++------ bfd/cofflink.c | 14 +-- bfd/coffswap.h | 14 +-- bfd/libcoff.h | 4 + bfd/peXXigen.c | 12 +-- bfd/xcofflink.c | 12 +-- gas/config/tc-ppc.c | 63 ++++++++++++ gas/config/tc-ppc.h | 2 +- gas/testsuite/gas/ppc/aix.exp | 3 + gas/testsuite/gas/ppc/xcoff-file-32.d | 13 +++ gas/testsuite/gas/ppc/xcoff-file-64.d | 13 +++ gas/testsuite/gas/ppc/xcoff-file.s | 1 + include/coff/internal.h | 25 ++--- include/coff/rs6000.h | 1 + include/coff/xcoff.h | 6 ++ 18 files changed, 273 insertions(+), 82 deletions(-) create mode 100644 gas/testsuite/gas/ppc/xcoff-file-32.d create mode 100644 gas/testsuite/gas/ppc/xcoff-file-64.d create mode 100644 gas/testsuite/gas/ppc/xcoff-file.s diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 31d91190103..1cc2162e7d8 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -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 */ diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c index 8c206959fd3..95a31b606c8 100644 --- a/bfd/coff64-rs6000.c +++ b/bfd/coff64-rs6000.c @@ -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; diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 7967cedf918..f0b73a98881 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -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; diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 6627a9af4b6..40f1ac718e4 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -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) _(""); 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) _(""); + 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: diff --git a/bfd/cofflink.c b/bfd/cofflink.c index b8a370933be..67d9c62b0b4 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -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 = _(""); 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) diff --git a/bfd/coffswap.h b/bfd/coffswap.h index e0dbd04f399..a8bd932daf7 100644 --- a/bfd/coffswap.h +++ b/bfd/coffswap.h @@ -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; diff --git a/bfd/libcoff.h b/bfd/libcoff.h index 6dc68d1a398..1b4f988bb0b 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -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; diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index c41c3299277..e2a9cbb65c1 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -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; diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c index 3ca74ce0277..e87ed0e683b 100644 --- a/bfd/xcofflink.c +++ b/bfd/xcofflink.c @@ -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 = _(""); 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) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index af025af32ff..8750e379158 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -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 diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index fb18730db3c..2d0a8865d98 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -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 diff --git a/gas/testsuite/gas/ppc/aix.exp b/gas/testsuite/gas/ppc/aix.exp index aef295bc3b9..c6d10d5fb84 100644 --- a/gas/testsuite/gas/ppc/aix.exp +++ b/gas/testsuite/gas/ppc/aix.exp @@ -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 index 00000000000..a831b3b4587 --- /dev/null +++ b/gas/testsuite/gas/ppc/xcoff-file-32.d @@ -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 index 00000000000..12bb6efc93b --- /dev/null +++ b/gas/testsuite/gas/ppc/xcoff-file-64.d @@ -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 index 00000000000..229ab889f49 --- /dev/null +++ b/gas/testsuite/gas/ppc/xcoff-file.s @@ -0,0 +1 @@ +.file "file.s", "A long string", "short", "Another long string inside the strign table." diff --git a/include/coff/internal.h b/include/coff/internal.h index 8d757acb333..d01af7380c8 100644 --- a/include/coff/internal.h +++ b/include/coff/internal.h @@ -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 diff --git a/include/coff/rs6000.h b/include/coff/rs6000.h index e60efff23b6..fd3f01dccbc 100644 --- a/include/coff/rs6000.h +++ b/include/coff/rs6000.h @@ -176,6 +176,7 @@ union external_auxent { } x_n; } x_n; char x_ftype[1]; + char x_resv[3]; } x_file; struct { diff --git a/include/coff/xcoff.h b/include/coff/xcoff.h index 2b61545d611..1cff7dc30d5 100644 --- a/include/coff/xcoff.h +++ b/include/coff/xcoff.h @@ -190,6 +190,12 @@ #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. */ -- 2.30.2