gas: add visibility support for XCOFF

XCOFF assembly defines the visibility using an additional argument
on several pseudo-ops: .globl, .weak, .extern and .comm.
This implies that .globl and .weak syntax is different than the
usual GNU syntax. But we want to provide compatibility with AIX
assembler, especially because GCC is generating the visibility
using this XCOFF syntax.

PR 22085

bfd/ChangeLog:

        * coffcode.h (coff_write_object_contents): Change XCOFF header
        vstamp field to 2.
        * coffgen.c (coff_print_symbol): Increase the size for n_type.

gas/ChangeLog:

        * config/tc-ppc.c (ppc_xcoff_get_visibility): New function.
        (ppc_globl): New function.
        (ppc_weak): New function.
        (ppc_comm): Add visibility field support.
        (ppc_extern): Likewise.
        * testsuite/gas/all/cofftag.d: Adjust to new n_type size
        providing by objdump.
        * testsuite/gas/ppc/test1xcoff32.d: Likewise.
        * testsuite/gas/ppc/aix.exp: Add new tests.
        * testsuite/gas/ppc/xcoff-visibility-1-32.d: New test.
        * testsuite/gas/ppc/xcoff-visibility-1-64.d: New test.
        * testsuite/gas/ppc/xcoff-visibility-1.s: New test.

include/ChangeLog:

        * coff/internal.h (SYM_V_INTERNAL, SYM_V_HIDDEN,
        SYM_V_PROTECTED, SYM_V_EXPORTED, SYM_V_MASK): New defines.
        * coff/xcoff.h (struct xcoff_link_hash_entry): Add visibility
        field.

ld/ChangeLog:

        * testsuite/ld-pe/pr19803.d: Adjust to new n_type size
        providing by objdump.
This commit is contained in:
Clément Chigot
2021-11-16 14:02:16 +01:00
parent c4f5871457
commit add588a8ef
12 changed files with 423 additions and 39 deletions

View File

@ -3994,8 +3994,13 @@ coff_write_object_contents (bfd * abfd)
#endif
}
#ifdef RS6000COFF_C
/* XCOFF 32bit needs this to have new behaviour for n_type field. */
internal_a.vstamp = 2;
#else
/* FIXME: Does anybody ever set this to another value? */
internal_a.vstamp = 0;
#endif
/* Now should write relocs, strings, syms. */
obj_sym_filepos (abfd) = sym_base;
@ -4070,7 +4075,7 @@ coff_write_object_contents (bfd * abfd)
bfd_vma toc;
asection *loader_sec;
internal_a.vstamp = 1;
internal_a.vstamp = 2;
internal_a.o_snentry = xcoff_data (abfd)->snentry;
if (internal_a.o_snentry == 0)

View File

@ -2185,7 +2185,7 @@ coff_print_symbol (bfd *abfd,
- (bfd_hostptr_t) root)
/ sizeof (combined_entry_type));
fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x",
fprintf (file, "(sec %2d)(fl 0x%02x)(ty %4x)(scl %3d) (nx %d) 0x",
combined->u.syment.n_scnum,
combined->u.syment.n_flags,
combined->u.syment.n_type,

View File

@ -110,6 +110,7 @@ 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_globl (int);
static void ppc_lglobl (int);
static void ppc_ref (int);
static void ppc_section (int);
@ -119,6 +120,7 @@ static void ppc_rename (int);
static void ppc_toc (int);
static void ppc_xcoff_cons (int);
static void ppc_vbyte (int);
static void ppc_weak (int);
#endif
#ifdef OBJ_ELF
@ -230,6 +232,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "extern", ppc_extern, 0 },
{ "file", ppc_file, 0 },
{ "function", ppc_function, 0 },
{ "globl", ppc_globl, 0 },
{ "lglobl", ppc_lglobl, 0 },
{ "ref", ppc_ref, 0 },
{ "rename", ppc_rename, 0 },
@ -242,6 +245,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "word", ppc_xcoff_cons, 1 },
{ "short", ppc_xcoff_cons, 1 },
{ "vbyte", ppc_vbyte, 0 },
{ "weak", ppc_weak, 0 },
#endif
#ifdef OBJ_ELF
@ -4285,6 +4289,39 @@ ppc_byte (int ignore ATTRIBUTE_UNUSED)
to handle symbol suffixes for such symbols. */
static bool ppc_stab_symbol;
/* Retrieve the visiblity input for pseudo-ops having ones. */
static unsigned short
ppc_xcoff_get_visibility (void) {
SKIP_WHITESPACE();
if (startswith (input_line_pointer, "exported"))
{
input_line_pointer += 8;
return SYM_V_EXPORTED;
}
if (startswith (input_line_pointer, "hidden"))
{
input_line_pointer += 6;
return SYM_V_HIDDEN;
}
if (startswith (input_line_pointer, "internal"))
{
input_line_pointer += 8;
return SYM_V_INTERNAL;
}
if (startswith (input_line_pointer, "protected"))
{
input_line_pointer += 9;
return SYM_V_PROTECTED;
}
return 0;
}
/* The .comm and .lcomm pseudo-ops for XCOFF. XCOFF puts common
symbols in the .bss segment as though they were local common
symbols, and uses a different smclas. The native Aix 4.3.3 assembler
@ -4305,6 +4342,7 @@ ppc_comm (int lcomm)
symbolS *lcomm_sym = NULL;
symbolS *sym;
char *pfrag;
unsigned short visibility;
struct ppc_xcoff_section *section;
endc = get_symbol_name (&name);
@ -4341,6 +4379,19 @@ ppc_comm (int lcomm)
as_warn (_("ignoring bad alignment"));
align = 2;
}
/* The fourth argument to .comm is the visibility. */
if (*input_line_pointer == ',')
{
input_line_pointer++;
visibility = ppc_xcoff_get_visibility ();
if (!visibility)
{
as_bad (_("Unknown visibility field in .comm"));
ignore_rest_of_line ();
return;
}
}
}
}
else
@ -4463,6 +4514,14 @@ ppc_comm (int lcomm)
symbol_get_frag (lcomm_sym)->fr_offset += size;
}
if (!lcomm && visibility)
{
/* Add visibility to .comm symbol. */
coff_symbol_type *coffsym = coffsymbol (symbol_get_bfdsym (sym));
coffsym->native->u.syment.n_type &= ~SYM_V_MASK;
coffsym->native->u.syment.n_type |= visibility;
}
subseg_set (current_seg, current_subseg);
demand_empty_rest_of_line ();
@ -4842,13 +4901,102 @@ static void
ppc_extern (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
symbolS *sym;
endc = get_symbol_name (&name);
if ((name = read_symbol_name ()) == NULL)
return;
(void) symbol_find_or_make (name);
sym = symbol_find_or_make (name);
(void) restore_line_pointer (endc);
if (*input_line_pointer == ',')
{
unsigned short visibility;
coff_symbol_type *coffsym = coffsymbol (symbol_get_bfdsym (sym));
input_line_pointer++;
visibility = ppc_xcoff_get_visibility ();
if (!visibility)
{
as_bad (_("Unknown visibility field in .extern"));
ignore_rest_of_line ();
return;
}
coffsym->native->u.syment.n_type &= ~SYM_V_MASK;
coffsym->native->u.syment.n_type |= visibility;
}
demand_empty_rest_of_line ();
}
/* XCOFF semantic for .globl says that the second parameter is
the symbol visibility. */
static void
ppc_globl (int ignore ATTRIBUTE_UNUSED)
{
char *name;
symbolS *sym;
if ((name = read_symbol_name ()) == NULL)
return;
sym = symbol_find_or_make (name);
S_SET_EXTERNAL (sym);
if (*input_line_pointer == ',')
{
unsigned short visibility;
coff_symbol_type *coffsym = coffsymbol (symbol_get_bfdsym (sym));
input_line_pointer++;
visibility = ppc_xcoff_get_visibility ();
if (!visibility)
{
as_bad (_("Unknown visibility field in .globl"));
ignore_rest_of_line ();
return;
}
coffsym->native->u.syment.n_type &= ~SYM_V_MASK;
coffsym->native->u.syment.n_type |= visibility;
}
demand_empty_rest_of_line ();
}
/* XCOFF semantic for .weak says that the second parameter is
the symbol visibility. */
static void
ppc_weak (int ignore ATTRIBUTE_UNUSED)
{
char *name;
symbolS *sym;
if ((name = read_symbol_name ()) == NULL)
return;
sym = symbol_find_or_make (name);
S_SET_WEAK (sym);
if (*input_line_pointer == ',')
{
unsigned short visibility;
coff_symbol_type *coffsym = coffsymbol (symbol_get_bfdsym (sym));
input_line_pointer++;
visibility = ppc_xcoff_get_visibility ();
if (!visibility)
{
as_bad (_("Unknown visibility field in .weak"));
ignore_rest_of_line ();
return;
}
coffsym->native->u.syment.n_type &= ~SYM_V_MASK;
coffsym->native->u.syment.n_type |= visibility;
}
demand_empty_rest_of_line ();
}

View File

@ -87,4 +87,7 @@ if { [istarget "powerpc*-*-aix*"] || [istarget "rs6000-*-aix*"] } then {
run_dump_test "xcoff-file-32"
run_dump_test "xcoff-file-64"
run_dump_test "xcoff-visibility-1-32"
run_dump_test "xcoff-visibility-1-64"
}

View File

@ -0,0 +1,70 @@
#as: -a32
#source: xcoff-visibility-1.s
#objdump: -t
#name: XCOFF Visibility 1 (32 bit)
.*
SYMBOL TABLE:
.*
.*
.*
.*
\[ 4\].*\(ty 0\).*l_novisibility
.*
\[ 6\].*\(ty 1000\).*l_internal
.*
\[ 8\].*\(ty 2000\).*l_hidden
.*
\[ 10\].*\(ty 3000\).*l_protected
.*
\[ 12\].*\(ty 4000\).*l_exported
.*
\[ 14\].*\(ty 1000\).*l_dual
.*
\[ 16\].*\(ty 0\).*globl_novisibility
.*
\[ 18\].*\(ty 1000\).*globl_internal
.*
\[ 20\].*\(ty 2000\).*globl_hidden
.*
\[ 22\].*\(ty 3000\).*globl_protected
.*
\[ 24\].*\(ty 4000\).*globl_exported
.*
\[ 26\].*\(ty 1000\).*globl_dual
.*
\[ 28\].*\(ty 0\).*weak_novisibility
.*
\[ 30\].*\(ty 1000\).*weak_internal
.*
\[ 32\].*\(ty 2000\).*weak_hidden
.*
\[ 34\].*\(ty 3000\).*weak_protected
.*
\[ 36\].*\(ty 4000\).*weak_exported
.*
\[ 38\].*\(ty 1000\).*weak_dual
.*
\[ 40\].*\(ty 0\).*comm_novisibility
.*
\[ 42\].*\(ty 1000\).*comm_internal
.*
\[ 44\].*\(ty 2000\).*comm_hidden
.*
\[ 46\].*\(ty 3000\).*comm_protected
.*
\[ 48\].*\(ty 4000\).*comm_exported
.*
\[ 50\].*\(ty 0\).*extern_novisibility
.*
\[ 52\].*\(ty 1000\).*extern_internal
.*
\[ 54\].*\(ty 2000\).*extern_hidden
.*
\[ 56\].*\(ty 3000\).*extern_protected
.*
\[ 58\].*\(ty 4000\).*extern_exported
.*
\[ 60\].*\(ty 1000\).*extern_dual
.*

View File

@ -0,0 +1,70 @@
#as: -a64
#source: xcoff-visibility-1.s
#objdump: -t
#name: XCOFF Visibility 1 (64 bit)
.*
SYMBOL TABLE:
.*
.*
.*
.*
\[ 4\].*\(ty 0\).*l_novisibility
.*
\[ 6\].*\(ty 1000\).*l_internal
.*
\[ 8\].*\(ty 2000\).*l_hidden
.*
\[ 10\].*\(ty 3000\).*l_protected
.*
\[ 12\].*\(ty 4000\).*l_exported
.*
\[ 14\].*\(ty 1000\).*l_dual
.*
\[ 16\].*\(ty 0\).*globl_novisibility
.*
\[ 18\].*\(ty 1000\).*globl_internal
.*
\[ 20\].*\(ty 2000\).*globl_hidden
.*
\[ 22\].*\(ty 3000\).*globl_protected
.*
\[ 24\].*\(ty 4000\).*globl_exported
.*
\[ 26\].*\(ty 1000\).*globl_dual
.*
\[ 28\].*\(ty 0\).*weak_novisibility
.*
\[ 30\].*\(ty 1000\).*weak_internal
.*
\[ 32\].*\(ty 2000\).*weak_hidden
.*
\[ 34\].*\(ty 3000\).*weak_protected
.*
\[ 36\].*\(ty 4000\).*weak_exported
.*
\[ 38\].*\(ty 1000\).*weak_dual
.*
\[ 40\].*\(ty 0\).*comm_novisibility
.*
\[ 42\].*\(ty 1000\).*comm_internal
.*
\[ 44\].*\(ty 2000\).*comm_hidden
.*
\[ 46\].*\(ty 3000\).*comm_protected
.*
\[ 48\].*\(ty 4000\).*comm_exported
.*
\[ 50\].*\(ty 0\).*extern_novisibility
.*
\[ 52\].*\(ty 1000\).*extern_internal
.*
\[ 54\].*\(ty 2000\).*extern_hidden
.*
\[ 56\].*\(ty 3000\).*extern_protected
.*
\[ 58\].*\(ty 4000\).*extern_exported
.*
\[ 60\].*\(ty 1000\).*extern_dual
.*

View File

@ -0,0 +1,78 @@
# Tests every possible visibility using XCOFF format.
# Ensure that the visibility field is left empty if no
# visibility is provided.
# Ensure that only the last visibility is taken into
# account when several are provided.
# Csect visibility
.globl globl_novisibility[RW]
.csect globl_novisibility[RW]
.globl globl_internal[RW], internal
.csect globl_internal[RW]
.globl globl_hidden[RW], hidden
.csect globl_hidden[RW]
.globl globl_protected[RW], protected
.csect globl_protected[RW]
.globl globl_exported[RW], exported
.csect globl_exported[RW]
.globl globl_dual[RW], exported
.globl globl_dual[RW], internal
.csect globl_dual[RW]
# Weak csect visibility
.weak weak_novisibility[RW]
.csect weak_novisibility[RW]
.weak weak_internal[RW], internal
.csect weak_internal[RW]
.weak weak_hidden[RW], hidden
.csect weak_hidden[RW]
.weak weak_protected[RW], protected
.csect weak_protected[RW]
.weak weak_exported[RW], exported
.csect weak_exported[RW]
.weak weak_dual[RW], exported
.weak weak_dual[RW], internal
.csect weak_dual[RW]
# Comm visibility
.comm comm_novisibility[RW], 8, 4
.comm comm_internal[RW], 8, 4, internal
.comm comm_hidden[RW], 8, 4, hidden
.comm comm_protected[RW], 8, 4, protected
.comm comm_exported[RW], 8, 4, exported
# Extern visibility
.extern extern_novisibility[RW]
.extern extern_internal[RW], internal
.extern extern_hidden[RW], hidden
.extern extern_protected[RW], protected
.extern extern_exported[RW], exported
.extern extern_dual[RW], exported
.extern extern_dual[RW], internal
# Label visibility
.csect .text[PR]
.globl l_novisibility
l_novisibility:
blr
.globl l_internal, internal
l_internal:
blr
.globl l_hidden, hidden
l_hidden:
blr
.globl l_protected, protected
l_protected:
blr
.globl l_exported, exported
l_exported:
blr
.globl l_dual, exported
.globl l_dual, internal
l_dual:
blr

View File

@ -536,6 +536,13 @@ struct internal_syment
#define DECREF(x) \
((((x) >> N_TSHIFT) & ~ N_BTMASK) | ((x) & N_BTMASK))
/* Visibility flag, in XCOFF n_type. */
#define SYM_V_INTERNAL 0x1000
#define SYM_V_HIDDEN 0x2000
#define SYM_V_PROTECTED 0x3000
#define SYM_V_EXPORTED 0x4000
#define SYM_V_MASK 0xF000
union internal_auxent
{
struct

View File

@ -349,6 +349,9 @@ struct xcoff_link_hash_entry
/* Some linker flags. */
unsigned long flags;
/* Symbol visibility, using the same define than n_type. */
unsigned short visibility;
/* The storage mapping class. */
unsigned char smclas;
};