mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-29 16:38:05 +08:00
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.
This commit is contained in:
@ -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>
|
2020-04-20 Sudakshina Das <sudi.das@arm.com>
|
||||||
|
|
||||||
* config/tc-aarch64.c (parse_barrier_psb): Update error messages
|
* config/tc-aarch64.c (parse_barrier_psb): Update error messages
|
||||||
|
3
gas/NEWS
3
gas/NEWS
@ -1,5 +1,8 @@
|
|||||||
-*- text -*-
|
-*- 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 support for Intel SERIALIZE and TSXLDTRK instructions.
|
||||||
|
|
||||||
* Add -mlfence-after-load=, -mlfence-before-indirect-branch= and
|
* Add -mlfence-after-load=, -mlfence-before-indirect-branch= and
|
||||||
|
@ -1515,6 +1515,70 @@ obj_elf_line (int ignore ATTRIBUTE_UNUSED)
|
|||||||
demand_empty_rest_of_line ();
|
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
|
/* This handles the .symver pseudo-op, which is used to specify a
|
||||||
symbol version. The syntax is ``.symver NAME,SYMVERNAME''.
|
symbol version. The syntax is ``.symver NAME,SYMVERNAME''.
|
||||||
SYMVERNAME may contain ELF_VER_CHR ('@') characters. This
|
SYMVERNAME may contain ELF_VER_CHR ('@') characters. This
|
||||||
@ -1525,9 +1589,12 @@ static void
|
|||||||
obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
|
obj_elf_symver (int ignore ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
const char *sym_name;
|
||||||
char c;
|
char c;
|
||||||
char old_lexat;
|
char old_lexat;
|
||||||
symbolS *sym;
|
symbolS *sym;
|
||||||
|
struct elf_obj_sy *sy_obj;
|
||||||
|
char *p;
|
||||||
|
|
||||||
sym = get_sym_from_input_line_and_check ();
|
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;
|
lex_type[(unsigned char) '@'] |= LEX_NAME;
|
||||||
c = get_symbol_name (& name);
|
c = get_symbol_name (& name);
|
||||||
lex_type[(unsigned char) '@'] = old_lexat;
|
lex_type[(unsigned char) '@'] = old_lexat;
|
||||||
|
sym_name = S_GET_NAME (sym);
|
||||||
|
|
||||||
if (S_IS_COMMON (sym))
|
if (S_IS_COMMON (sym))
|
||||||
{
|
{
|
||||||
as_bad (_("`%s' can't be versioned to common symbol '%s'"),
|
as_bad (_("`%s' can't be versioned to common symbol '%s'"),
|
||||||
name, S_GET_NAME (sym));
|
name, sym_name);
|
||||||
ignore_rest_of_line ();
|
ignore_rest_of_line ();
|
||||||
return;
|
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);
|
||||||
(void) restore_line_pointer (c);
|
ignore_rest_of_line ();
|
||||||
|
return;
|
||||||
if (strchr (symbol_get_obj (sym)->versioned_name,
|
|
||||||
ELF_VER_CHR) == NULL)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (strcmp (symbol_get_obj (sym)->versioned_name, name))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) restore_line_pointer (c);
|
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);
|
||||||
|
|
||||||
|
if (*input_line_pointer == ',')
|
||||||
|
{
|
||||||
|
char *save = input_line_pointer;
|
||||||
|
|
||||||
|
++input_line_pointer;
|
||||||
|
SKIP_WHITESPACE ();
|
||||||
|
if (strncmp (input_line_pointer, "local", 5) == 0)
|
||||||
|
{
|
||||||
|
input_line_pointer += 5;
|
||||||
|
sy_obj->visibility = visibility_local;
|
||||||
|
}
|
||||||
|
else if (strncmp (input_line_pointer, "hidden", 6) == 0)
|
||||||
|
{
|
||||||
|
input_line_pointer += 6;
|
||||||
|
sy_obj->visibility = visibility_hidden;
|
||||||
|
}
|
||||||
|
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 ();
|
demand_empty_rest_of_line ();
|
||||||
@ -2382,6 +2465,7 @@ elf_frob_symbol (symbolS *symp, int *puntp)
|
|||||||
{
|
{
|
||||||
struct elf_obj_sy *sy_obj;
|
struct elf_obj_sy *sy_obj;
|
||||||
expressionS *size;
|
expressionS *size;
|
||||||
|
struct elf_versioned_name_list *versioned_name;
|
||||||
|
|
||||||
#ifdef NEED_ECOFF_DEBUG
|
#ifdef NEED_ECOFF_DEBUG
|
||||||
if (ECOFF_DEBUGGING)
|
if (ECOFF_DEBUGGING)
|
||||||
@ -2409,73 +2493,47 @@ elf_frob_symbol (symbolS *symp, int *puntp)
|
|||||||
sy_obj->size = NULL;
|
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.
|
/* This symbol was given a new name with the .symver directive.
|
||||||
|
|
||||||
If this is an external reference, just rename the symbol to
|
If this is an external reference, just rename the symbol to
|
||||||
include the version string. This will make the relocs be
|
include the version string. This will make the relocs be
|
||||||
against the correct versioned symbol.
|
against the correct versioned symbol. */
|
||||||
|
|
||||||
If this is a definition, add an alias. FIXME: Using an alias
|
/* We will have already reported an version error. */
|
||||||
will permit the debugging information to refer to the right
|
if (sy_obj->bad_version)
|
||||||
symbol. However, it's not clear whether it is the best
|
*puntp = TRUE;
|
||||||
approach. */
|
/* elf_frob_file_before_adjust only allows one version symbol for
|
||||||
|
renamed symbol. */
|
||||||
else if (! S_IS_DEFINED (symp))
|
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
|
as_bad (_("`%s' can't be versioned to common symbol '%s'"),
|
||||||
reserved for definitions of the default version to link
|
versioned_name->name, S_GET_NAME (symp));
|
||||||
against. */
|
*puntp = TRUE;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
|
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)
|
||||||
{
|
{
|
||||||
size_t l;
|
symbolS *symp2 = symbol_find_or_make (versioned_name->name);
|
||||||
|
|
||||||
/* 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
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
|
S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
|
||||||
|
|
||||||
@ -2498,6 +2556,27 @@ elf_frob_symbol (symbolS *symp, int *puntp)
|
|||||||
if (S_IS_EXTERNAL (symp))
|
if (S_IS_EXTERNAL (symp))
|
||||||
S_SET_EXTERNAL (symp2);
|
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;
|
symbolS *symp;
|
||||||
|
|
||||||
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
|
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
|
||||||
if (!S_IS_DEFINED (symp))
|
{
|
||||||
{
|
struct elf_obj_sy *sy_obj = symbol_get_obj (symp);
|
||||||
if (symbol_get_obj (symp)->versioned_name)
|
int is_defined = !!S_IS_DEFINED (symp);
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
/* The @@@ syntax is a special case. If the symbol is
|
if (sy_obj->versioned_name)
|
||||||
not defined, 2 `@'s will be removed from the
|
{
|
||||||
versioned_name. */
|
char *p = strchr (sy_obj->versioned_name->name,
|
||||||
|
ELF_VER_CHR);
|
||||||
|
|
||||||
p = strchr (symbol_get_obj (symp)->versioned_name,
|
if (sy_obj->rename)
|
||||||
ELF_VER_CHR);
|
{
|
||||||
if (p != NULL && p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
|
/* The @@@ syntax is a special case. If the symbol is
|
||||||
{
|
not defined, 2 `@'s will be removed from the
|
||||||
size_t l = strlen (&p[3]) + 1;
|
versioned_name. Otherwise, 1 `@' will be removed. */
|
||||||
memmove (&p[1], &p[3], l);
|
size_t l = strlen (&p[3]) + 1;
|
||||||
}
|
memmove (&p[1 + is_defined], &p[3], l);
|
||||||
if (symbol_used_p (symp) == 0
|
}
|
||||||
&& symbol_used_in_reloc_p (symp) == 0)
|
|
||||||
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there was .weak foo, but foo was neither defined nor
|
if (!is_defined)
|
||||||
used anywhere, remove it. */
|
{
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
else if (S_IS_WEAK (symp)
|
/* Only one version symbol is allowed for undefined
|
||||||
&& symbol_used_p (symp) == 0
|
symbol. */
|
||||||
&& symbol_used_in_reloc_p (symp) == 0)
|
if (sy_obj->versioned_name->next)
|
||||||
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
|
{
|
||||||
}
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,18 +55,41 @@ extern int mips_flag_mdebug;
|
|||||||
#endif
|
#endif
|
||||||
#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. */
|
/* Additional information we keep for each symbol. */
|
||||||
struct elf_obj_sy
|
struct elf_obj_sy
|
||||||
{
|
{
|
||||||
/* Whether the symbol has been marked as local. */
|
/* 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
|
/* Use this to keep track of .size expressions that involve
|
||||||
differences that we can't compute yet. */
|
differences that we can't compute yet. */
|
||||||
expressionS *size;
|
expressionS *size;
|
||||||
|
|
||||||
/* The name specified by the .symver directive. */
|
/* The list of names specified by the .symver directive. */
|
||||||
char *versioned_name;
|
struct elf_versioned_name_list *versioned_name;
|
||||||
|
|
||||||
#ifdef ECOFF_DEBUGGING
|
#ifdef ECOFF_DEBUGGING
|
||||||
/* If we are generating ECOFF debugging information, we need some
|
/* If we are generating ECOFF debugging information, we need some
|
||||||
|
@ -4509,7 +4509,7 @@ Some machine configurations provide additional directives.
|
|||||||
* Struct:: @code{.struct @var{expression}}
|
* Struct:: @code{.struct @var{expression}}
|
||||||
@ifset ELF
|
@ifset ELF
|
||||||
* SubSection:: @code{.subsection}
|
* SubSection:: @code{.subsection}
|
||||||
* Symver:: @code{.symver @var{name},@var{name2@@nodename}}
|
* Symver:: @code{.symver @var{name},@var{name2@@nodename}[,@var{visibility}]}
|
||||||
@end ifset
|
@end ifset
|
||||||
|
|
||||||
@ifset COFF
|
@ifset COFF
|
||||||
@ -7112,9 +7112,9 @@ shared library.
|
|||||||
|
|
||||||
For ELF targets, the @code{.symver} directive can be used like this:
|
For ELF targets, the @code{.symver} directive can be used like this:
|
||||||
@smallexample
|
@smallexample
|
||||||
.symver @var{name}, @var{name2@@nodename}
|
.symver @var{name}, @var{name2@@nodename}[ ,@var{visibility}]
|
||||||
@end smallexample
|
@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
|
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
|
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
|
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
|
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
|
building a shared library. If you are attempting to override a versioned
|
||||||
symbol from a shared library, then @var{nodename} should correspond to the
|
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
|
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
|
references to @var{name} will be changed to @var{name2@@nodename}. If no
|
||||||
|
@ -46,8 +46,13 @@ if { [is_elf_format] } then {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
run_dump_test "symver0"
|
set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
|
||||||
run_dump_test "symver1"
|
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 "symver2" ""
|
||||||
run_error_test "symver3" ""
|
run_error_test "symver3" ""
|
||||||
# We have to comment out symver4 and symver5, which check the
|
# We have to comment out symver4 and symver5, which check the
|
||||||
@ -56,5 +61,6 @@ if { [is_elf_format] } then {
|
|||||||
# version name.
|
# version name.
|
||||||
# run_error_test "symver4" ""
|
# run_error_test "symver4" ""
|
||||||
# run_error_test "symver5" ""
|
# run_error_test "symver5" ""
|
||||||
run_error_test "symver6" ""
|
run_error_test "symver14" ""
|
||||||
|
run_error_test "symver15" ""
|
||||||
}
|
}
|
||||||
|
8
gas/testsuite/gas/symver/symver10.s
Normal file
8
gas/testsuite/gas/symver/symver10.s
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver10a.d
Normal file
8
gas/testsuite/gas/symver/symver10a.d
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver10b.d
Normal file
8
gas/testsuite/gas/symver/symver10b.d
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#source: symver10.s
|
||||||
|
#readelf: -sW
|
||||||
|
#name: symver symver10b
|
||||||
|
|
||||||
|
#failif
|
||||||
|
#...
|
||||||
|
+[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo
|
||||||
|
#pass
|
8
gas/testsuite/gas/symver/symver11.d
Normal file
8
gas/testsuite/gas/symver/symver11.d
Normal file
@ -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
|
9
gas/testsuite/gas/symver/symver11.s
Normal file
9
gas/testsuite/gas/symver/symver11.s
Normal file
@ -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
|
9
gas/testsuite/gas/symver/symver12.d
Normal file
9
gas/testsuite/gas/symver/symver12.d
Normal file
@ -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
|
10
gas/testsuite/gas/symver/symver12.s
Normal file
10
gas/testsuite/gas/symver/symver12.s
Normal file
@ -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
|
9
gas/testsuite/gas/symver/symver13.d
Normal file
9
gas/testsuite/gas/symver/symver13.d
Normal file
@ -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
|
11
gas/testsuite/gas/symver/symver13.s
Normal file
11
gas/testsuite/gas/symver/symver13.s
Normal file
@ -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
|
2
gas/testsuite/gas/symver/symver14.l
Normal file
2
gas/testsuite/gas/symver/symver14.l
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.*: Assembler messages:
|
||||||
|
.*: Error: only one version name with `@@@' is allowed for symbol `foo'
|
6
gas/testsuite/gas/symver/symver14.s
Normal file
6
gas/testsuite/gas/symver/symver14.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.data
|
||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
.byte 1
|
||||||
|
.symver foo,foo@@@version1
|
||||||
|
.symver foo,foo@@@version2
|
2
gas/testsuite/gas/symver/symver15.l
Normal file
2
gas/testsuite/gas/symver/symver15.l
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.*: Assembler messages:
|
||||||
|
.*: Error: multiple versions \[`foo@version2'|`foo@version1'\] for symbol `foo'
|
3
gas/testsuite/gas/symver/symver15.s
Normal file
3
gas/testsuite/gas/symver/symver15.s
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.data
|
||||||
|
.symver foo,foo@version1
|
||||||
|
.symver foo,foo@version2
|
11
gas/testsuite/gas/symver/symver6.d
Normal file
11
gas/testsuite/gas/symver/symver6.d
Normal file
@ -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
|
@ -1,3 +0,0 @@
|
|||||||
.*: Assembler messages:
|
|
||||||
.*:7: Error: multiple versions \[`foo@version1'|`foo@@version1'\] for symbol `foo'
|
|
||||||
#pass
|
|
@ -3,7 +3,7 @@
|
|||||||
.type foo1,object
|
.type foo1,object
|
||||||
foo1:
|
foo1:
|
||||||
.long foo
|
.long foo
|
||||||
.symver foo,foo@@version1
|
.symver foo1,foo@@version1
|
||||||
.symver foo,foo@version1
|
.symver foo1,foo@version1
|
||||||
L_foo1:
|
L_foo1:
|
||||||
.size foo1,L_foo1-foo1
|
.size foo1,L_foo1-foo1
|
||||||
|
8
gas/testsuite/gas/symver/symver7.d
Normal file
8
gas/testsuite/gas/symver/symver7.d
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver7.s
Normal file
8
gas/testsuite/gas/symver/symver7.s
Normal file
@ -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
|
9
gas/testsuite/gas/symver/symver8.d
Normal file
9
gas/testsuite/gas/symver/symver8.d
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver8.s
Normal file
8
gas/testsuite/gas/symver/symver8.s
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver9.s
Normal file
8
gas/testsuite/gas/symver/symver9.s
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver9a.d
Normal file
8
gas/testsuite/gas/symver/symver9a.d
Normal file
@ -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
|
8
gas/testsuite/gas/symver/symver9b.d
Normal file
8
gas/testsuite/gas/symver/symver9b.d
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#source: symver9.s
|
||||||
|
#readelf: -sW
|
||||||
|
#name: symver symver9b
|
||||||
|
|
||||||
|
#failif
|
||||||
|
#...
|
||||||
|
+[0-9]+: +0+ +1 +OBJECT +GLOBAL +DEFAULT +[0-9]+ +foo
|
||||||
|
#pass
|
Reference in New Issue
Block a user