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.
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 */
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.
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;
.
. {* 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;
.
.
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:
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;
}
}
+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,
bfd_size_type *debug_string_size_p)
{
unsigned int name_length;
- union internal_auxent *auxent;
char *name = (char *) (symbol->name);
if (name == NULL)
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 =
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
{
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,
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
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)
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
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)
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
{
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
{
{
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:
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
{
/* 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)
{
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)
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
{
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;
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;
/* 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;
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:
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;
/* 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)
{
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)
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);
{ "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 },
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
#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
run_dump_test "xcoff-stsym-32"
run_dump_test "xcoff-stsym-64"
+
+ run_dump_test "xcoff-file-32"
+ run_dump_test "xcoff-file-64"
}
--- /dev/null
+#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."
--- /dev/null
+#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."
--- /dev/null
+.file "file.s", "A long string", "short", "Another long string inside the strign table."
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
} x_n;
} x_n;
char x_ftype[1];
+ char x_resv[3];
} x_file;
struct {
#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. */