aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-ppc.c
diff options
context:
space:
mode:
authorClément Chigot <clement.chigot@atos.net>2021-11-16 14:02:16 +0100
committerClément Chigot <clement.chigot@atos.net>2022-01-12 09:08:11 +0100
commitadd588a8ef53a5f77f2abda08a5de643923c4cce (patch)
treef5b85c033c265d175ec30c4de2d7568ac9751f8e /gas/config/tc-ppc.c
parentc4f5871457222f2c4a99e662dfa16b7c662f750a (diff)
downloadfsf-binutils-gdb-add588a8ef53a5f77f2abda08a5de643923c4cce.zip
fsf-binutils-gdb-add588a8ef53a5f77f2abda08a5de643923c4cce.tar.gz
fsf-binutils-gdb-add588a8ef53a5f77f2abda08a5de643923c4cce.tar.bz2
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.
Diffstat (limited to 'gas/config/tc-ppc.c')
-rw-r--r--gas/config/tc-ppc.c156
1 files changed, 152 insertions, 4 deletions
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 159d315..4a1d394 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -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 ();
}