aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-04-21 05:33:04 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-04-21 05:33:17 -0700
commit6914be53bd662eefd979d0c82d2e20e108c4ee66 (patch)
tree1ae1bebd08fc216bb92d2deb38e21408776a1f87 /gas
parent6f6fd151cbf226bbaa66e44977f57b7c6dc33d89 (diff)
downloadfsf-binutils-gdb-6914be53bd662eefd979d0c82d2e20e108c4ee66.zip
fsf-binutils-gdb-6914be53bd662eefd979d0c82d2e20e108c4ee66.tar.gz
fsf-binutils-gdb-6914be53bd662eefd979d0c82d2e20e108c4ee66.tar.bz2
gas: Extend .symver directive
Extend .symver directive to update visibility of the original symbol and assign one original symbol to different versioned symbols: .symver foo, foo@VERS_1, local # Change foo to a local symbol. .symver foo, foo@VERS_2, hidden # Change foo to a hidden symbol. .symver foo, foo@@VERS_3, remove # Remove foo from symbol table. .symver foo, bar@V1 # Assign foo to bar@V1 and baz@V2. .symver foo, baz@V2 PR gas/23840 PR gas/25295 * NEWS: Mention .symver extension. * config/obj-elf.c (obj_elf_find_and_add_versioned_name): New function. (obj_elf_symver): Call obj_elf_find_and_add_versioned_name to add a version name. Add local, hidden and remove visibility support. (elf_frob_symbol): Handle the list of version names. Update the original symbol to local, hidden or remove it from the symbol table. (elf_frob_file_before_adjust): Handle the list of version names. * config/obj-elf.h (elf_visibility): New. (elf_versioned_name_list): Likewise. (elf_obj_sy): Change local to bitfield. Add rename, bad_version and visibility. Change versioned_name pointer to struct elf_versioned_name_list. * doc/as.texi: Update .symver directive. * testsuite/gas/symver/symver.exp: Run all *.d tests. Add more error checking tests. * testsuite/gas/symver/symver6.d: New file. * testsuite/gas/symver/symver7.d: Likewise. * testsuite/gas/symver/symver7.s: Likewise. * testsuite/gas/symver/symver8.d: Likewise. * testsuite/gas/symver/symver8.s: Likewise. * testsuite/gas/symver/symver9.s: Likewise. * testsuite/gas/symver/symver9a.d: Likewise. * testsuite/gas/symver/symver9b.d: Likewise. * testsuite/gas/symver/symver10.s: Likewise. * testsuite/gas/symver/symver10a.d: Likewise. * testsuite/gas/symver/symver10b.d: Likewise. * testsuite/gas/symver/symver11.d: Likewise. * testsuite/gas/symver/symver11.s: Likewise. * testsuite/gas/symver/symver12.d: Likewise. * testsuite/gas/symver/symver12.s: Likewise. * testsuite/gas/symver/symver13.d: Likewise. * testsuite/gas/symver/symver13.s: Likewise. * testsuite/gas/symver/symver14.d: Likewise. * testsuite/gas/symver/symver14.l: Likewise. * testsuite/gas/symver/symver15.d: Likewise. * testsuite/gas/symver/symver15.l: Likewise. * testsuite/gas/symver/symver6.l: Removed. * testsuite/gas/symver/symver6.s: Updated.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog46
-rw-r--r--gas/NEWS3
-rw-r--r--gas/config/obj-elf.c318
-rw-r--r--gas/config/obj-elf.h29
-rw-r--r--gas/doc/as.texi16
-rw-r--r--gas/testsuite/gas/symver/symver.exp12
-rw-r--r--gas/testsuite/gas/symver/symver10.s8
-rw-r--r--gas/testsuite/gas/symver/symver10a.d8
-rw-r--r--gas/testsuite/gas/symver/symver10b.d8
-rw-r--r--gas/testsuite/gas/symver/symver11.d8
-rw-r--r--gas/testsuite/gas/symver/symver11.s9
-rw-r--r--gas/testsuite/gas/symver/symver12.d9
-rw-r--r--gas/testsuite/gas/symver/symver12.s10
-rw-r--r--gas/testsuite/gas/symver/symver13.d9
-rw-r--r--gas/testsuite/gas/symver/symver13.s11
-rw-r--r--gas/testsuite/gas/symver/symver14.l2
-rw-r--r--gas/testsuite/gas/symver/symver14.s6
-rw-r--r--gas/testsuite/gas/symver/symver15.l2
-rw-r--r--gas/testsuite/gas/symver/symver15.s3
-rw-r--r--gas/testsuite/gas/symver/symver6.d11
-rw-r--r--gas/testsuite/gas/symver/symver6.l3
-rw-r--r--gas/testsuite/gas/symver/symver6.s4
-rw-r--r--gas/testsuite/gas/symver/symver7.d8
-rw-r--r--gas/testsuite/gas/symver/symver7.s8
-rw-r--r--gas/testsuite/gas/symver/symver8.d9
-rw-r--r--gas/testsuite/gas/symver/symver8.s8
-rw-r--r--gas/testsuite/gas/symver/symver9.s8
-rw-r--r--gas/testsuite/gas/symver/symver9a.d8
-rw-r--r--gas/testsuite/gas/symver/symver9b.d8
29 files changed, 470 insertions, 122 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index f821f3d..3185bdc 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,49 @@
+2020-04-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR gas/23840
+ PR gas/25295
+ * NEWS: Mention .symver extension.
+ * config/obj-elf.c (obj_elf_find_and_add_versioned_name): New
+ function.
+ (obj_elf_symver): Call obj_elf_find_and_add_versioned_name to
+ add a version name. Add local, hidden and remove visibility
+ support.
+ (elf_frob_symbol): Handle the list of version names. Update the
+ original symbol to local, hidden or remove it from the symbol
+ table.
+ (elf_frob_file_before_adjust): Handle the list of version names.
+ * config/obj-elf.h (elf_visibility): New.
+ (elf_versioned_name_list): Likewise.
+ (elf_obj_sy): Change local to bitfield. Add rename, bad_version
+ and visibility. Change versioned_name pointer to struct
+ elf_versioned_name_list.
+ * doc/as.texi: Update .symver directive.
+ * testsuite/gas/symver/symver.exp: Run all *.d tests. Add more
+ error checking tests.
+ * testsuite/gas/symver/symver6.d: New file.
+ * testsuite/gas/symver/symver7.d: Likewise.
+ * testsuite/gas/symver/symver7.s: Likewise.
+ * testsuite/gas/symver/symver8.d: Likewise.
+ * testsuite/gas/symver/symver8.s: Likewise.
+ * testsuite/gas/symver/symver9.s: Likewise.
+ * testsuite/gas/symver/symver9a.d: Likewise.
+ * testsuite/gas/symver/symver9b.d: Likewise.
+ * testsuite/gas/symver/symver10.s: Likewise.
+ * testsuite/gas/symver/symver10a.d: Likewise.
+ * testsuite/gas/symver/symver10b.d: Likewise.
+ * testsuite/gas/symver/symver11.d: Likewise.
+ * testsuite/gas/symver/symver11.s: Likewise.
+ * testsuite/gas/symver/symver12.d: Likewise.
+ * testsuite/gas/symver/symver12.s: Likewise.
+ * testsuite/gas/symver/symver13.d: Likewise.
+ * testsuite/gas/symver/symver13.s: Likewise.
+ * testsuite/gas/symver/symver14.d: Likewise.
+ * testsuite/gas/symver/symver14.l: Likewise.
+ * testsuite/gas/symver/symver15.d: Likewise.
+ * testsuite/gas/symver/symver15.l: Likewise.
+ * testsuite/gas/symver/symver6.l: Removed.
+ * testsuite/gas/symver/symver6.s: Updated.
+
2020-04-20 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_barrier_psb): Update error messages
diff --git a/gas/NEWS b/gas/NEWS
index 6748c17..58d79ca 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Extend .symver directive to update visibility of the original symbol
+ and assign one original symbol to different versioned symbols.
+
* Add support for Intel SERIALIZE and TSXLDTRK instructions.
* Add -mlfence-after-load=, -mlfence-before-indirect-branch= and
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 5e7e8f0..409ea4d 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -1515,6 +1515,70 @@ obj_elf_line (int ignore ATTRIBUTE_UNUSED)
demand_empty_rest_of_line ();
}
+static struct elf_versioned_name_list *
+obj_elf_find_and_add_versioned_name (const char *version_name,
+ const char *sym_name,
+ const char *ver,
+ struct elf_obj_sy *sy_obj)
+{
+ struct elf_versioned_name_list *versioned_name;
+ const char *p;
+
+ for (p = ver + 1; *p == ELF_VER_CHR; p++)
+ ;
+
+ /* NB: Since some tests in ld/testsuite/ld-elfvers have no version
+ names, we have to disable this. */
+ if (0 && *p == '\0')
+ {
+ as_bad (_("missing version name in `%s' for symbol `%s'"),
+ version_name, sym_name);
+ return NULL;
+ }
+
+ versioned_name = sy_obj->versioned_name;
+
+ switch (p - ver)
+ {
+ case 1:
+ case 2:
+ break;
+ case 3:
+ if (sy_obj->rename)
+ {
+ if (strcmp (versioned_name->name, version_name) == 0)
+ return versioned_name;
+ else
+ {
+ as_bad (_("only one version name with `@@@' is allowed "
+ "for symbol `%s'"), sym_name);
+ return NULL;
+ }
+ }
+ sy_obj->rename = TRUE;
+ break;
+ default:
+ as_bad (_("invalid version name '%s' for symbol `%s'"),
+ version_name, sym_name);
+ return NULL;
+ }
+
+ for (;
+ versioned_name != NULL;
+ versioned_name = versioned_name->next)
+ if (strcmp (versioned_name->name, version_name) == 0)
+ return versioned_name;
+
+ /* Add this versioned name to the head of the list, */
+ versioned_name = (struct elf_versioned_name_list *)
+ xmalloc (sizeof (*versioned_name));
+ versioned_name->name = xstrdup (version_name);
+ versioned_name->next = sy_obj->versioned_name;
+ sy_obj->versioned_name = versioned_name;
+
+ return versioned_name;
+}
+
/* This handles the .symver pseudo-op, which is used to specify a
symbol version. The syntax is ``.symver NAME,SYMVERNAME''.
SYMVERNAME may contain ELF_VER_CHR ('@') characters. This
@@ -1525,9 +1589,12 @@ static void
obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
{
char *name;
+ const char *sym_name;
char c;
char old_lexat;
symbolS *sym;
+ struct elf_obj_sy *sy_obj;
+ char *p;
sym = get_sym_from_input_line_and_check ();
@@ -1546,43 +1613,59 @@ obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
lex_type[(unsigned char) '@'] |= LEX_NAME;
c = get_symbol_name (& name);
lex_type[(unsigned char) '@'] = old_lexat;
+ sym_name = S_GET_NAME (sym);
if (S_IS_COMMON (sym))
{
as_bad (_("`%s' can't be versioned to common symbol '%s'"),
- name, S_GET_NAME (sym));
+ name, sym_name);
ignore_rest_of_line ();
return;
}
- if (symbol_get_obj (sym)->versioned_name == NULL)
+ p = strchr (name, ELF_VER_CHR);
+ if (p == NULL)
{
- symbol_get_obj (sym)->versioned_name = xstrdup (name);
+ as_bad (_("missing version name in `%s' for symbol `%s'"),
+ name, sym_name);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ sy_obj = symbol_get_obj (sym);
+ if (obj_elf_find_and_add_versioned_name (name, sym_name,
+ p, sy_obj) == NULL)
+ {
+ sy_obj->bad_version = TRUE;
+ ignore_rest_of_line ();
+ return;
+ }
- (void) restore_line_pointer (c);
+ (void) restore_line_pointer (c);
- if (strchr (symbol_get_obj (sym)->versioned_name,
- ELF_VER_CHR) == NULL)
+ if (*input_line_pointer == ',')
+ {
+ char *save = input_line_pointer;
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ if (strncmp (input_line_pointer, "local", 5) == 0)
{
- as_bad (_("missing version name in `%s' for symbol `%s'"),
- symbol_get_obj (sym)->versioned_name,
- S_GET_NAME (sym));
- ignore_rest_of_line ();
- return;
+ input_line_pointer += 5;
+ sy_obj->visibility = visibility_local;
}
- }
- else
- {
- if (strcmp (symbol_get_obj (sym)->versioned_name, name))
+ else if (strncmp (input_line_pointer, "hidden", 6) == 0)
{
- as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"),
- name, symbol_get_obj (sym)->versioned_name,
- S_GET_NAME (sym));
- ignore_rest_of_line ();
- return;
+ input_line_pointer += 6;
+ sy_obj->visibility = visibility_hidden;
}
-
- (void) restore_line_pointer (c);
+ else if (strncmp (input_line_pointer, "remove", 6) == 0)
+ {
+ input_line_pointer += 6;
+ sy_obj->visibility = visibility_remove;
+ }
+ else
+ input_line_pointer = save;
}
demand_empty_rest_of_line ();
@@ -2382,6 +2465,7 @@ elf_frob_symbol (symbolS *symp, int *puntp)
{
struct elf_obj_sy *sy_obj;
expressionS *size;
+ struct elf_versioned_name_list *versioned_name;
#ifdef NEED_ECOFF_DEBUG
if (ECOFF_DEBUGGING)
@@ -2409,73 +2493,47 @@ elf_frob_symbol (symbolS *symp, int *puntp)
sy_obj->size = NULL;
}
- if (sy_obj->versioned_name != NULL)
+ versioned_name = sy_obj->versioned_name;
+ if (versioned_name)
{
- char *p;
-
- p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
- if (p == NULL)
- /* We will have already reported an error about a missing version. */
- *puntp = TRUE;
-
/* This symbol was given a new name with the .symver directive.
-
If this is an external reference, just rename the symbol to
include the version string. This will make the relocs be
- against the correct versioned symbol.
-
- If this is a definition, add an alias. FIXME: Using an alias
- will permit the debugging information to refer to the right
- symbol. However, it's not clear whether it is the best
- approach. */
+ against the correct versioned symbol. */
- else if (! S_IS_DEFINED (symp))
+ /* We will have already reported an version error. */
+ if (sy_obj->bad_version)
+ *puntp = TRUE;
+ /* elf_frob_file_before_adjust only allows one version symbol for
+ renamed symbol. */
+ else if (sy_obj->rename)
+ S_SET_NAME (symp, versioned_name->name);
+ else if (S_IS_COMMON (symp))
{
- /* Verify that the name isn't using the @@ syntax--this is
- reserved for definitions of the default version to link
- against. */
- if (p[1] == ELF_VER_CHR)
- {
- as_bad (_("invalid attempt to declare external version name"
- " as default in symbol `%s'"),
- sy_obj->versioned_name);
- *puntp = TRUE;
- }
- S_SET_NAME (symp, sy_obj->versioned_name);
+ as_bad (_("`%s' can't be versioned to common symbol '%s'"),
+ versioned_name->name, S_GET_NAME (symp));
+ *puntp = TRUE;
}
else
{
- if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
- {
- size_t l;
-
- /* The @@@ syntax is a special case. It renames the
- symbol name to versioned_name with one `@' removed. */
- l = strlen (&p[3]) + 1;
- memmove (&p[2], &p[3], l);
- S_SET_NAME (symp, sy_obj->versioned_name);
- }
- else
+ asymbol *bfdsym;
+ elf_symbol_type *elfsym;
+
+ /* This is a definition. Add an alias for each version.
+ FIXME: Using an alias will permit the debugging information
+ to refer to the right symbol. However, it's not clear
+ whether it is the best approach. */
+
+ /* FIXME: Creating a new symbol here is risky. We're
+ in the final loop over the symbol table. We can
+ get away with it only because the symbol goes to
+ the end of the list, where the loop will still see
+ it. It would probably be better to do this in
+ obj_frob_file_before_adjust. */
+ for (; versioned_name != NULL;
+ versioned_name = versioned_name->next)
{
- symbolS *symp2;
-
- /* FIXME: Creating a new symbol here is risky. We're
- in the final loop over the symbol table. We can
- get away with it only because the symbol goes to
- the end of the list, where the loop will still see
- it. It would probably be better to do this in
- obj_frob_file_before_adjust. */
-
- symp2 = symbol_find_or_make (sy_obj->versioned_name);
-
- /* Now we act as though we saw symp2 = sym. */
- if (S_IS_COMMON (symp))
- {
- as_bad (_("`%s' can't be versioned to common symbol '%s'"),
- sy_obj->versioned_name, S_GET_NAME (symp));
- *puntp = TRUE;
- return;
- }
+ symbolS *symp2 = symbol_find_or_make (versioned_name->name);
S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
@@ -2498,6 +2556,27 @@ elf_frob_symbol (symbolS *symp, int *puntp)
if (S_IS_EXTERNAL (symp))
S_SET_EXTERNAL (symp2);
}
+
+ switch (symbol_get_obj (symp)->visibility)
+ {
+ case visibility_unchanged:
+ break;
+ case visibility_hidden:
+ bfdsym = symbol_get_bfdsym (symp);
+ elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym),
+ bfdsym);
+ elfsym->internal_elf_sym.st_other &= ~3;
+ elfsym->internal_elf_sym.st_other |= STV_HIDDEN;
+ break;
+ case visibility_remove:
+ /* Remove the symbol if it isn't used in relocation. */
+ if (!symbol_used_in_reloc_p (symp))
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ break;
+ case visibility_local:
+ S_CLEAR_EXTERNAL (symp);
+ break;
+ }
}
}
@@ -2676,36 +2755,61 @@ elf_frob_file_before_adjust (void)
symbolS *symp;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
- if (!S_IS_DEFINED (symp))
- {
- if (symbol_get_obj (symp)->versioned_name)
- {
- char *p;
-
- /* The @@@ syntax is a special case. If the symbol is
- not defined, 2 `@'s will be removed from the
- versioned_name. */
-
- p = strchr (symbol_get_obj (symp)->versioned_name,
- ELF_VER_CHR);
- if (p != NULL && p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
- {
- size_t l = strlen (&p[3]) + 1;
- memmove (&p[1], &p[3], l);
- }
- if (symbol_used_p (symp) == 0
- && symbol_used_in_reloc_p (symp) == 0)
- symbol_remove (symp, &symbol_rootP, &symbol_lastP);
- }
+ {
+ struct elf_obj_sy *sy_obj = symbol_get_obj (symp);
+ int is_defined = !!S_IS_DEFINED (symp);
- /* If there was .weak foo, but foo was neither defined nor
- used anywhere, remove it. */
+ if (sy_obj->versioned_name)
+ {
+ char *p = strchr (sy_obj->versioned_name->name,
+ ELF_VER_CHR);
- else if (S_IS_WEAK (symp)
- && symbol_used_p (symp) == 0
- && symbol_used_in_reloc_p (symp) == 0)
- symbol_remove (symp, &symbol_rootP, &symbol_lastP);
- }
+ if (sy_obj->rename)
+ {
+ /* The @@@ syntax is a special case. If the symbol is
+ not defined, 2 `@'s will be removed from the
+ versioned_name. Otherwise, 1 `@' will be removed. */
+ size_t l = strlen (&p[3]) + 1;
+ memmove (&p[1 + is_defined], &p[3], l);
+ }
+
+ if (!is_defined)
+ {
+ /* Verify that the name isn't using the @@ syntax--this
+ is reserved for definitions of the default version
+ to link against. */
+ if (!sy_obj->rename && p[1] == ELF_VER_CHR)
+ {
+ as_bad (_("invalid attempt to declare external "
+ "version name as default in symbol `%s'"),
+ sy_obj->versioned_name->name);
+ return;
+ }
+
+ /* Only one version symbol is allowed for undefined
+ symbol. */
+ if (sy_obj->versioned_name->next)
+ {
+ as_bad (_("multiple versions [`%s'|`%s'] for "
+ "symbol `%s'"),
+ sy_obj->versioned_name->name,
+ sy_obj->versioned_name->next->name,
+ S_GET_NAME (symp));
+ return;
+ }
+
+ sy_obj->rename = TRUE;
+ }
+ }
+
+ /* If there was .symver or .weak, but symbol was neither
+ defined nor used anywhere, remove it. */
+ if (!is_defined
+ && (sy_obj->versioned_name || S_IS_WEAK (symp))
+ && symbol_used_p (symp) == 0
+ && symbol_used_in_reloc_p (symp) == 0)
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ }
}
}
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index 54af9eb..b39a1a1 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -55,18 +55,41 @@ extern int mips_flag_mdebug;
#endif
#endif
+enum elf_visibility
+{
+ visibility_unchanged = 0,
+ visibility_local,
+ visibility_hidden,
+ visibility_remove
+};
+
+struct elf_versioned_name_list
+{
+ char *name;
+ struct elf_versioned_name_list *next;
+};
+
/* Additional information we keep for each symbol. */
struct elf_obj_sy
{
/* Whether the symbol has been marked as local. */
- int local;
+ unsigned int local : 1;
+
+ /* Whether the symbol has been marked for rename with @@@. */
+ unsigned int rename : 1;
+
+ /* Whether the symbol has a bad version name. */
+ unsigned int bad_version : 1;
+
+ /* Whether visibility of the symbol should be changed. */
+ ENUM_BITFIELD (elf_visibility) visibility : 2;
/* Use this to keep track of .size expressions that involve
differences that we can't compute yet. */
expressionS *size;
- /* The name specified by the .symver directive. */
- char *versioned_name;
+ /* The list of names specified by the .symver directive. */
+ struct elf_versioned_name_list *versioned_name;
#ifdef ECOFF_DEBUGGING
/* If we are generating ECOFF debugging information, we need some
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 0a6727e..8669879 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -4509,7 +4509,7 @@ Some machine configurations provide additional directives.
* Struct:: @code{.struct @var{expression}}
@ifset ELF
* SubSection:: @code{.subsection}
-* Symver:: @code{.symver @var{name},@var{name2@@nodename}}
+* Symver:: @code{.symver @var{name},@var{name2@@nodename}[,@var{visibility}]}
@end ifset
@ifset COFF
@@ -7112,9 +7112,9 @@ shared library.
For ELF targets, the @code{.symver} directive can be used like this:
@smallexample
-.symver @var{name}, @var{name2@@nodename}
+.symver @var{name}, @var{name2@@nodename}[ ,@var{visibility}]
@end smallexample
-If the symbol @var{name} is defined within the file
+If the original symbol @var{name} is defined within the file
being assembled, the @code{.symver} directive effectively creates a symbol
alias with the name @var{name2@@nodename}, and in fact the main reason that we
just don't try and create a regular alias is that the @var{@@} character isn't
@@ -7127,7 +7127,15 @@ function is being mentioned. The @var{nodename} portion of the alias should be
the name of a node specified in the version script supplied to the linker when
building a shared library. If you are attempting to override a versioned
symbol from a shared library, then @var{nodename} should correspond to the
-nodename of the symbol you are trying to override.
+nodename of the symbol you are trying to override. The optional argument
+@var{visibility} updates the visibility of the original symbol. The valid
+visibilities are @code{local}, @code {hidden}, and @code {remove}. The
+@code{local} visibility makes the original symbol a local symbol
+(@pxref{Local}). The @code{hidden} visibility sets the visibility of the
+original symbol to @code{hidden} (@pxref{Hidden}). The @code{remove}
+visibility removes the original symbol from the symbol table if it isn't
+used in relocation. If visibility isn't specified, the original symbol
+is unchanged.
If the symbol @var{name} is not defined within the file being assembled, all
references to @var{name} will be changed to @var{name2@@nodename}. If no
diff --git a/gas/testsuite/gas/symver/symver.exp b/gas/testsuite/gas/symver/symver.exp
index de122eb..6b29a12 100644
--- a/gas/testsuite/gas/symver/symver.exp
+++ b/gas/testsuite/gas/symver/symver.exp
@@ -46,8 +46,13 @@ if { [is_elf_format] } then {
return
}
- run_dump_test "symver0"
- run_dump_test "symver1"
+ set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+ foreach t $test_list {
+ # We need to strip the ".d", but can leave the dirname.
+ verbose [file rootname $t]
+ run_dump_test [file rootname $t]
+ }
+
run_error_test "symver2" ""
run_error_test "symver3" ""
# We have to comment out symver4 and symver5, which check the
@@ -56,5 +61,6 @@ if { [is_elf_format] } then {
# version name.
# run_error_test "symver4" ""
# run_error_test "symver5" ""
- run_error_test "symver6" ""
+ run_error_test "symver14" ""
+ run_error_test "symver15" ""
}
diff --git a/gas/testsuite/gas/symver/symver10.s b/gas/testsuite/gas/symver/symver10.s
new file mode 100644
index 0000000..967a692
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver10.s
@@ -0,0 +1,8 @@
+ .data
+ .globl foo
+ .type foo,%object
+foo:
+ .byte 0
+ .size foo,.-foo
+ .symver foo,foo@@version2,remove
+ .symver foo,foo@version1
diff --git a/gas/testsuite/gas/symver/symver10a.d b/gas/testsuite/gas/symver/symver10a.d
new file mode 100644
index 0000000..e9bd159
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver10a.d
@@ -0,0 +1,8 @@
+#source: symver10.s
+#readelf: -sW
+#name: symver symver10a
+
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@version1
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@@version2
+#pass
diff --git a/gas/testsuite/gas/symver/symver10b.d b/gas/testsuite/gas/symver/symver10b.d
new file mode 100644
index 0000000..17d0bfd
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver10b.d
@@ -0,0 +1,8 @@
+#source: symver10.s
+#readelf: -sW
+#name: symver symver10b
+
+#failif
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo
+#pass
diff --git a/gas/testsuite/gas/symver/symver11.d b/gas/testsuite/gas/symver/symver11.d
new file mode 100644
index 0000000..0e3e7f1
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver11.d
@@ -0,0 +1,8 @@
+#readelf: -rsW
+#name: symver symver11
+
+#...
+[0-9a-f]+ +[0-9a-f]+ +R_.* +[0-9a-f]+ +foo *.*
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo
+#pass
diff --git a/gas/testsuite/gas/symver/symver11.s b/gas/testsuite/gas/symver/symver11.s
new file mode 100644
index 0000000..547e812
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver11.s
@@ -0,0 +1,9 @@
+ .data
+ .globl foo
+ .type foo,%object
+foo:
+ .byte 0
+ .size foo,.-foo
+ .symver foo,foo@@version2,remove
+ .symver foo,foo@version1
+ .dc.a foo
diff --git a/gas/testsuite/gas/symver/symver12.d b/gas/testsuite/gas/symver/symver12.d
new file mode 100644
index 0000000..3878f4d
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver12.d
@@ -0,0 +1,9 @@
+#readelf: -sW
+#name: symver symver12
+
+#...
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +DEFAULT +[0-9]+ +foo
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +DEFAULT +[0-9]+ +foo@VERS_2
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +DEFAULT +[0-9]+ +foo@VERS_1
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +DEFAULT +[0-9]+ +foo@@VERS_2
+#pass
diff --git a/gas/testsuite/gas/symver/symver12.s b/gas/testsuite/gas/symver/symver12.s
new file mode 100644
index 0000000..724c3ef
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver12.s
@@ -0,0 +1,10 @@
+ .text
+ .space 13
+ .symver foo, foo@@VERS_2
+ .symver foo, foo@VERS_1
+ .symver foo, foo@VERS_2
+ .globl foo
+ .type foo, %function
+foo:
+ .byte 0
+ .size foo,.-foo
diff --git a/gas/testsuite/gas/symver/symver13.d b/gas/testsuite/gas/symver/symver13.d
new file mode 100644
index 0000000..dce8579
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver13.d
@@ -0,0 +1,9 @@
+#readelf: -sW
+#name: symver symver13
+
+#...
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +HIDDEN +[0-9]+ +foo
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +HIDDEN +[0-9]+ +foo@VERS_1
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +HIDDEN +[0-9]+ +foo@@VERS_2
+ +[0-9]+: +0+d +1 +FUNC +GLOBAL +HIDDEN +[0-9]+ +foo@VERS_2
+#pass
diff --git a/gas/testsuite/gas/symver/symver13.s b/gas/testsuite/gas/symver/symver13.s
new file mode 100644
index 0000000..5426d86
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver13.s
@@ -0,0 +1,11 @@
+ .text
+ .space 13
+ .globl foo
+ .type foo, %function
+foo:
+ .byte 0
+ .symver foo, foo@VERS_2
+ .symver foo, foo@@VERS_2
+ .symver foo, foo@VERS_1
+ .hidden foo
+ .size foo,.-foo
diff --git a/gas/testsuite/gas/symver/symver14.l b/gas/testsuite/gas/symver/symver14.l
new file mode 100644
index 0000000..53fb7f4
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver14.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*: Error: only one version name with `@@@' is allowed for symbol `foo'
diff --git a/gas/testsuite/gas/symver/symver14.s b/gas/testsuite/gas/symver/symver14.s
new file mode 100644
index 0000000..6693ff6
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver14.s
@@ -0,0 +1,6 @@
+ .data
+ .global foo
+foo:
+ .byte 1
+ .symver foo,foo@@@version1
+ .symver foo,foo@@@version2
diff --git a/gas/testsuite/gas/symver/symver15.l b/gas/testsuite/gas/symver/symver15.l
new file mode 100644
index 0000000..903a67c
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver15.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*: Error: multiple versions \[`foo@version2'|`foo@version1'\] for symbol `foo'
diff --git a/gas/testsuite/gas/symver/symver15.s b/gas/testsuite/gas/symver/symver15.s
new file mode 100644
index 0000000..abf1860
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver15.s
@@ -0,0 +1,3 @@
+ .data
+ .symver foo,foo@version1
+ .symver foo,foo@version2
diff --git a/gas/testsuite/gas/symver/symver6.d b/gas/testsuite/gas/symver/symver6.d
new file mode 100644
index 0000000..cddf7ec
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver6.d
@@ -0,0 +1,11 @@
+#nm: -n
+#name: symver symver6
+#
+
+#...
+[ ]+U foo
+#...
+0+00000.. D foo1
+0+0000000 D foo@@version1
+0+00000.. D foo@version1
+0+00000.. d L_foo1
diff --git a/gas/testsuite/gas/symver/symver6.l b/gas/testsuite/gas/symver/symver6.l
deleted file mode 100644
index c2d12ae..0000000
--- a/gas/testsuite/gas/symver/symver6.l
+++ /dev/null
@@ -1,3 +0,0 @@
-.*: Assembler messages:
-.*:7: Error: multiple versions \[`foo@version1'|`foo@@version1'\] for symbol `foo'
-#pass
diff --git a/gas/testsuite/gas/symver/symver6.s b/gas/testsuite/gas/symver/symver6.s
index 23d9fe2..b0bc0b8 100644
--- a/gas/testsuite/gas/symver/symver6.s
+++ b/gas/testsuite/gas/symver/symver6.s
@@ -3,7 +3,7 @@
.type foo1,object
foo1:
.long foo
- .symver foo,foo@@version1
- .symver foo,foo@version1
+ .symver foo1,foo@@version1
+ .symver foo1,foo@version1
L_foo1:
.size foo1,L_foo1-foo1
diff --git a/gas/testsuite/gas/symver/symver7.d b/gas/testsuite/gas/symver/symver7.d
new file mode 100644
index 0000000..5152678
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver7.d
@@ -0,0 +1,8 @@
+#readelf: -sW
+#name: symver symver7
+
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +HIDDEN +[0-9]+ +foo
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@version1
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@@version2
+#pass
diff --git a/gas/testsuite/gas/symver/symver7.s b/gas/testsuite/gas/symver/symver7.s
new file mode 100644
index 0000000..20c11b7
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver7.s
@@ -0,0 +1,8 @@
+ .data
+ .globl foo
+ .type foo,%object
+foo:
+ .byte 0
+ .size foo,.-foo
+ .symver foo,foo@@version2,local
+ .symver foo,foo@version1,hidden
diff --git a/gas/testsuite/gas/symver/symver8.d b/gas/testsuite/gas/symver/symver8.d
new file mode 100644
index 0000000..8938aec
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver8.d
@@ -0,0 +1,9 @@
+#readelf: -sW
+#name: symver symver8
+
+#...
+ +[0-9]+: +0+ +1 +OBJECT +LOCAL +DEFAULT +[0-9]+ +foo
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@version1
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@@version2
+#pass
diff --git a/gas/testsuite/gas/symver/symver8.s b/gas/testsuite/gas/symver/symver8.s
new file mode 100644
index 0000000..17ab037
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver8.s
@@ -0,0 +1,8 @@
+ .data
+ .globl foo
+ .type foo,%object
+foo:
+ .byte 0
+ .size foo,.-foo
+ .symver foo,foo@@version2,hidden
+ .symver foo,foo@version1,local
diff --git a/gas/testsuite/gas/symver/symver9.s b/gas/testsuite/gas/symver/symver9.s
new file mode 100644
index 0000000..2f60897
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver9.s
@@ -0,0 +1,8 @@
+ .data
+ .globl foo
+ .type foo,%object
+foo:
+ .byte 0
+ .size foo,.-foo
+ .symver foo,foo@@version2
+ .symver foo,foo@version1,remove
diff --git a/gas/testsuite/gas/symver/symver9a.d b/gas/testsuite/gas/symver/symver9a.d
new file mode 100644
index 0000000..1cdbce8
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver9a.d
@@ -0,0 +1,8 @@
+#source: symver9.s
+#readelf: -sW
+#name: symver symver9a
+
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@version1
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo@@version2
+#pass
diff --git a/gas/testsuite/gas/symver/symver9b.d b/gas/testsuite/gas/symver/symver9b.d
new file mode 100644
index 0000000..383d1bd
--- /dev/null
+++ b/gas/testsuite/gas/symver/symver9b.d
@@ -0,0 +1,8 @@
+#source: symver9.s
+#readelf: -sW
+#name: symver symver9b
+
+#failif
+#...
+ +[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo
+#pass