gas/ChangeLog:
* read.c (potable): Add weakref. (s_weakref): New. * read.h (s_weakref): Declare. * struc-symbol.h (struct symbol): Add sy_weakrefr and sy_weakrefd. * symbols.c (colon): Clear weakrefr. (symbol_find_exact): Rename to, and reimplement in terms of... (symbol_find_exact_noref): ... new function. (symbol_find): Likewise... (symbol_find_noref): ... ditto. (resolve_symbol_value): Resolve weakrefr without setting their values. (S_SET_WEAK): Call hook. (S_GET_VALUE): Follow weakref link. (S_SET_VALUE): Clear weakrefr. (S_IS_WEAK): Follow weakref link. (S_IS_WEAKREFR, S_SET_WEAKREFR, S_CLEAR_WEAKREFR): New. (S_IS_WEAKREFD, S_SET_WEAKREFD, S_CLEAR_WEAKREFD): New. (symbol_set_value_expression, symbol_set_frag): Clear weakrefr. (symbol_mark_used): Follow weakref link. (print_symbol_value_1): Print weak, weakrefr and weakrefd. * symbols.h (symbol_find_noref, symbol_find_exact_noref): Declare. (S_IS_WEAKREFR, S_SET_WEAKREFR, S_CLEAR_WEAKREFR): Declare. (S_IS_WEAKREFD, S_SET_WEAKREFD, S_CLEAR_WEAKREFD): Declare. * write.c (adust_reloc_syms): Follow weakref link. Do not complain if target is undefined. (write_object_file): Likewise. Remove weakrefr symbols. Drop unreferenced weakrefd symbols. * config/obj-coff.c (obj_frob_symbol): Do not force WEAKREFD symbols EXTERNAL. (pecoff_obj_set_weak_hook, pecoff_obj_clear_weak_hook): New. * config/obj-coff.h (obj_set_weak_hook, obj_clear_weak_hook): Define. * doc/as.texinfo: Document weakref. * doc/internals.texi: Document new struct members, internal functions and hooks. gas/testsuite/ChangeLog: * gas/all/weakref1.s, gas/all/weakref1.d: New test. * gas/all/weakref1g.d, gas/all/weakref1l.d: New tests. * gas/all/weakref1u.d, gas/all/weakref1w.d: New tests. * gas/all/weakref2.s, gas/all/weakref3.s: New tests. * gas/all/gas.exp: Run new tests.
This commit is contained in:
parent
9ba4c44513
commit
06e77878ef
@ -1,3 +1,40 @@
|
||||
2005-10-24 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* read.c (potable): Add weakref.
|
||||
(s_weakref): New.
|
||||
* read.h (s_weakref): Declare.
|
||||
* struc-symbol.h (struct symbol): Add sy_weakrefr and sy_weakrefd.
|
||||
* symbols.c (colon): Clear weakrefr.
|
||||
(symbol_find_exact): Rename to, and reimplement in terms of...
|
||||
(symbol_find_exact_noref): ... new function.
|
||||
(symbol_find): Likewise...
|
||||
(symbol_find_noref): ... ditto.
|
||||
(resolve_symbol_value): Resolve weakrefr without setting their
|
||||
values.
|
||||
(S_SET_WEAK): Call hook.
|
||||
(S_GET_VALUE): Follow weakref link.
|
||||
(S_SET_VALUE): Clear weakrefr.
|
||||
(S_IS_WEAK): Follow weakref link.
|
||||
(S_IS_WEAKREFR, S_SET_WEAKREFR, S_CLEAR_WEAKREFR): New.
|
||||
(S_IS_WEAKREFD, S_SET_WEAKREFD, S_CLEAR_WEAKREFD): New.
|
||||
(symbol_set_value_expression, symbol_set_frag): Clear weakrefr.
|
||||
(symbol_mark_used): Follow weakref link.
|
||||
(print_symbol_value_1): Print weak, weakrefr and weakrefd.
|
||||
* symbols.h (symbol_find_noref, symbol_find_exact_noref): Declare.
|
||||
(S_IS_WEAKREFR, S_SET_WEAKREFR, S_CLEAR_WEAKREFR): Declare.
|
||||
(S_IS_WEAKREFD, S_SET_WEAKREFD, S_CLEAR_WEAKREFD): Declare.
|
||||
* write.c (adust_reloc_syms): Follow weakref link. Do not
|
||||
complain if target is undefined.
|
||||
(write_object_file): Likewise. Remove weakrefr symbols. Drop
|
||||
unreferenced weakrefd symbols.
|
||||
* config/obj-coff.c (obj_frob_symbol): Do not force WEAKREFD
|
||||
symbols EXTERNAL.
|
||||
(pecoff_obj_set_weak_hook, pecoff_obj_clear_weak_hook): New.
|
||||
* config/obj-coff.h (obj_set_weak_hook, obj_clear_weak_hook): Define.
|
||||
* doc/as.texinfo: Document weakref.
|
||||
* doc/internals.texi: Document new struct members, internal
|
||||
functions and hooks.
|
||||
|
||||
2005-10-24 Jie Zhang <jie.zhang@analog.com>
|
||||
|
||||
* Makefile.am (bfin-parse.h): Renamed from bfin-parse.tab.h.
|
||||
|
@ -1055,6 +1055,39 @@ weak_uniquify (const char * name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
pecoff_obj_set_weak_hook (symbolS *symbolP)
|
||||
{
|
||||
symbolS *alternateP;
|
||||
|
||||
/* See _Microsoft Portable Executable and Common Object
|
||||
File Format Specification_, section 5.5.3.
|
||||
Create a symbol representing the alternate value.
|
||||
coff_frob_symbol will set the value of this symbol from
|
||||
the value of the weak symbol itself. */
|
||||
S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
|
||||
S_SET_NUMBER_AUXILIARY (symbolP, 1);
|
||||
SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
|
||||
|
||||
alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP)));
|
||||
S_SET_EXTERNAL (alternateP);
|
||||
S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
|
||||
|
||||
SA_SET_SYM_TAGNDX (symbolP, alternateP);
|
||||
}
|
||||
|
||||
void
|
||||
pecoff_obj_clear_weak_hook (symbolS *symbolP)
|
||||
{
|
||||
symbolS *alternateP;
|
||||
|
||||
S_SET_STORAGE_CLASS (symbolP, 0);
|
||||
SA_SET_SYM_FSIZE (symbolP, 0);
|
||||
|
||||
alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP)));
|
||||
S_CLEAR_EXTERNAL (alternateP);
|
||||
}
|
||||
|
||||
#endif /* TE_PE */
|
||||
|
||||
/* Handle .weak. This is a GNU extension in formats other than PE. */
|
||||
@ -1065,9 +1098,6 @@ obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
|
||||
char *name;
|
||||
int c;
|
||||
symbolS *symbolP;
|
||||
#ifdef TE_PE
|
||||
symbolS *alternateP;
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
@ -1085,23 +1115,6 @@ obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
|
||||
SKIP_WHITESPACE ();
|
||||
S_SET_WEAK (symbolP);
|
||||
|
||||
#ifdef TE_PE
|
||||
/* See _Microsoft Portable Executable and Common Object
|
||||
File Format Specification_, section 5.5.3.
|
||||
Create a symbol representing the alternate value.
|
||||
coff_frob_symbol will set the value of this symbol from
|
||||
the value of the weak symbol itself. */
|
||||
S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
|
||||
S_SET_NUMBER_AUXILIARY (symbolP, 1);
|
||||
SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
|
||||
|
||||
alternateP = symbol_find_or_make (weak_name2altname (name));
|
||||
S_SET_EXTERNAL (alternateP);
|
||||
S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
|
||||
|
||||
SA_SET_SYM_TAGNDX (symbolP, alternateP);
|
||||
#endif
|
||||
|
||||
if (c == ',')
|
||||
{
|
||||
input_line_pointer++;
|
||||
@ -1157,12 +1170,19 @@ coff_frob_symbol (symbolS *symp, int *punt)
|
||||
{
|
||||
/* This is a weak alternate symbol. All processing of
|
||||
PECOFFweak symbols is done here, through the alternate. */
|
||||
symbolS *weakp = symbol_find (weak_altname2name (S_GET_NAME (symp)));
|
||||
symbolS *weakp = symbol_find_noref (weak_altname2name
|
||||
(S_GET_NAME (symp)), 1);
|
||||
|
||||
assert (weakp);
|
||||
assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
|
||||
|
||||
if (symbol_equated_p (weakp))
|
||||
if (! S_IS_WEAK (weakp))
|
||||
{
|
||||
/* The symbol was turned from weak to strong. Discard altname. */
|
||||
*punt = 1;
|
||||
return;
|
||||
}
|
||||
else if (symbol_equated_p (weakp))
|
||||
{
|
||||
/* The weak symbol has an alternate specified; symp is unneeded. */
|
||||
S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
|
||||
@ -1225,7 +1245,7 @@ coff_frob_symbol (symbolS *symp, int *punt)
|
||||
&& !SF_GET_STATICS (symp)
|
||||
&& S_GET_STORAGE_CLASS (symp) != C_LABEL
|
||||
&& symbol_constant_p (symp)
|
||||
&& (real = symbol_find (S_GET_NAME (symp)))
|
||||
&& (real = symbol_find_noref (S_GET_NAME (symp), 1))
|
||||
&& S_GET_STORAGE_CLASS (real) == C_NULL
|
||||
&& real != symp)
|
||||
{
|
||||
@ -1237,7 +1257,10 @@ coff_frob_symbol (symbolS *symp, int *punt)
|
||||
if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
|
||||
{
|
||||
assert (S_GET_VALUE (symp) == 0);
|
||||
S_SET_EXTERNAL (symp);
|
||||
if (S_IS_WEAKREFD (symp))
|
||||
*punt = 1;
|
||||
else
|
||||
S_SET_EXTERNAL (symp);
|
||||
}
|
||||
else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
|
||||
{
|
||||
|
@ -157,6 +157,9 @@
|
||||
#ifdef TE_PE
|
||||
/* PE weak symbols need USE_UNIQUE. */
|
||||
#define USE_UNIQUE 1
|
||||
|
||||
#define obj_set_weak_hook pecoff_obj_set_weak_hook
|
||||
#define obj_clear_weak_hook pecoff_obj_clear_weak_hook
|
||||
#endif
|
||||
|
||||
#ifndef OBJ_COFF_MAX_AUXENTRIES
|
||||
@ -384,6 +387,10 @@ extern void coff_adjust_section_syms (bfd *, asection *, void *);
|
||||
extern void coff_frob_file_after_relocs (void);
|
||||
extern void coff_obj_symbol_new_hook (symbolS *);
|
||||
extern void coff_obj_read_begin_hook (void);
|
||||
#ifdef TE_PE
|
||||
extern void pecoff_obj_set_weak_hook (symbolS *);
|
||||
extern void pecoff_obj_clear_weak_hook (symbolS *);
|
||||
#endif
|
||||
extern void obj_coff_section (int);
|
||||
extern segT obj_coff_add_segment (const char *);
|
||||
extern void obj_coff_section (int);
|
||||
|
@ -3842,6 +3842,7 @@ Some machine configurations provide additional directives.
|
||||
|
||||
* Warning:: @code{.warning @var{string}}
|
||||
* Weak:: @code{.weak @var{names}}
|
||||
* Weakref:: @code{.weakref @var{alias}, @var{symbol}}
|
||||
* Word:: @code{.word @var{expressions}}
|
||||
* Deprecated:: Deprecated Directives
|
||||
@end menu
|
||||
@ -5989,6 +5990,25 @@ On the PE target, weak symbols are supported natively as weak aliases.
|
||||
When a weak symbol is created that is not an alias, GAS creates an
|
||||
alternate symbol to hold the default value.
|
||||
|
||||
@node Weakref
|
||||
@section @code{.weakref @var{alias}, @var{target}}
|
||||
|
||||
@cindex @code{weakref} directive
|
||||
This directive creates an alias to the target symbol that enables the symbol to
|
||||
be referenced with weak-symbol semantics, but without actually making it weak.
|
||||
If direct references or definitions of the symbol are present, then the symbol
|
||||
will not be weak, but if all references to it are through weak references, the
|
||||
symbol will be marked as weak in the symbol table.
|
||||
|
||||
The effect is equivalent to moving all references to the alias to a separate
|
||||
assembly source file, renaming the alias to the symbol in it, declaring the
|
||||
symbol as weak there, and running a reloadable link to merge the object files
|
||||
resulting from the assembly of the new source file and the old source file that
|
||||
had the references to the alias removed.
|
||||
|
||||
The alias itself never makes to the symbol table, and is entirely handled
|
||||
within the assembler.
|
||||
|
||||
@node Word
|
||||
@section @code{.word @var{expressions}}
|
||||
|
||||
|
@ -93,6 +93,13 @@ responsible for setting it when a symbol is used in backend routines.
|
||||
Whether the symbol is an MRI common symbol created by the @code{COMMON}
|
||||
pseudo-op when assembling in MRI mode.
|
||||
|
||||
@item sy_weakrefr
|
||||
Whether the symbol is a @code{weakref} alias to another symbol.
|
||||
|
||||
@item sy_weakrefd
|
||||
Whether the symbol is or was referenced by one or more @code{weakref} aliases,
|
||||
and has not had any direct references.
|
||||
|
||||
@item bsym
|
||||
This points to the BFD @code{asymbol} that
|
||||
will be used in writing the object file.
|
||||
@ -146,7 +153,17 @@ A synonym for @code{S_IS_EXTERNAL}. Don't use it.
|
||||
|
||||
@item S_IS_WEAK
|
||||
@cindex S_IS_WEAK
|
||||
Return non-zero if the symbol is weak.
|
||||
Return non-zero if the symbol is weak, or if it is a @code{weakref} alias or
|
||||
symbol that has not been strongly referenced.
|
||||
|
||||
@item S_IS_WEAKREFR
|
||||
@cindex S_IS_WEAKREFR
|
||||
Return non-zero if the symbol is a @code{weakref} alias.
|
||||
|
||||
@item S_IS_WEAKREFD
|
||||
@cindex S_IS_WEAKREFD
|
||||
Return non-zero if the symbol was aliased by a @code{weakref} alias and has not
|
||||
had any strong references.
|
||||
|
||||
@item S_IS_COMMON
|
||||
@cindex S_IS_COMMON
|
||||
@ -182,6 +199,29 @@ Mark the symbol as not externally visible.
|
||||
@cindex S_SET_WEAK
|
||||
Mark the symbol as weak.
|
||||
|
||||
@item S_SET_WEAKREFR
|
||||
@cindex S_SET_WEAKREFR
|
||||
Mark the symbol as the referrer in a @code{weakref} directive. The symbol it
|
||||
aliases must have been set to the value expression before this point. If the
|
||||
alias has already been used, the symbol is marked as used too.
|
||||
|
||||
@item S_CLEAR_WEAKREFR
|
||||
@cindex S_CLEAR_WEAKREFR
|
||||
Clear the @code{weakref} alias status of a symbol. This is implicitly called
|
||||
whenever a symbol is defined or set to a new expression.
|
||||
|
||||
@item S_SET_WEAKREFD
|
||||
@cindex S_SET_WEAKREFD
|
||||
Mark the symbol as the referred symbol in a @code{weakref} directive.
|
||||
Implicitly marks the symbol as weak, but see below. It should only be called
|
||||
if the referenced symbol has just been added to the symbol table.
|
||||
|
||||
@item S_SET_WEAKREFD
|
||||
@cindex S_SET_WEAKREFD
|
||||
Clear the @code{weakref} aliased status of a symbol. This is implicitly called
|
||||
whenever the symbol is looked up, as part of a direct reference or a
|
||||
definition, but not as part of a @code{weakref} directive.
|
||||
|
||||
@item S_GET_TYPE
|
||||
@item S_GET_DESC
|
||||
@item S_GET_OTHER
|
||||
@ -1533,6 +1573,16 @@ If you define this macro, GAS will call it for each symbol. You can indicate
|
||||
that the symbol should not be included in the object file by defining this
|
||||
macro to set its second argument to a non-zero value.
|
||||
|
||||
@item obj_set_weak_hook
|
||||
@cindex obj_set_weak_hook
|
||||
If you define this macro, @code{S_SET_WEAK} will call it before modifying the
|
||||
symbol's flags.
|
||||
|
||||
@item obj_clear_weak_hook
|
||||
@cindex obj_clear_weak_hook
|
||||
If you define this macro, @code{S_CLEAR_WEAKREFD} will call it after clearning
|
||||
the @code{weakrefd} flag, but before modifying any other flags.
|
||||
|
||||
@item obj_frob_file
|
||||
@cindex obj_frob_file
|
||||
If you define this macro, GAS will call it after the symbol table has been
|
||||
|
119
gas/read.c
119
gas/read.c
@ -434,6 +434,7 @@ static const pseudo_typeS potable[] = {
|
||||
{"xref", s_ignore, 0},
|
||||
{"xstabs", s_xstab, 's'},
|
||||
{"warning", s_errwarn, 0},
|
||||
{"weakref", s_weakref, 0},
|
||||
{"word", cons, 2},
|
||||
{"zero", s_space, 0},
|
||||
{NULL, NULL, 0} /* End sentinel. */
|
||||
@ -3150,6 +3151,124 @@ s_text (int ignore ATTRIBUTE_UNUSED)
|
||||
const_flag &= ~IN_DEFAULT_SECTION;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* .weakref x, y sets x as an alias to y that, as long as y is not
|
||||
referenced directly, will cause y to become a weak symbol. */
|
||||
void
|
||||
s_weakref (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
char *name;
|
||||
char delim;
|
||||
char *end_name;
|
||||
symbolS *symbolP;
|
||||
symbolS *symbolP2;
|
||||
expressionS exp;
|
||||
|
||||
name = input_line_pointer;
|
||||
delim = get_symbol_end ();
|
||||
end_name = input_line_pointer;
|
||||
|
||||
if (name == end_name)
|
||||
{
|
||||
as_bad (_("expected symbol name"));
|
||||
*end_name = delim;
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
symbolP = symbol_find_or_make (name);
|
||||
|
||||
*end_name = delim;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
*end_name = 0;
|
||||
as_bad (_("expected comma after \"%s\""), name);
|
||||
*end_name = delim;
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
input_line_pointer++;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
name = input_line_pointer;
|
||||
delim = get_symbol_end ();
|
||||
end_name = input_line_pointer;
|
||||
|
||||
if (name == end_name)
|
||||
{
|
||||
as_bad (_("expected symbol name"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((symbolP2 = symbol_find_noref (name, 1)) == NULL
|
||||
&& (symbolP2 = md_undefined_symbol (name)) == NULL)
|
||||
{
|
||||
symbolP2 = symbol_find_or_make (name);
|
||||
S_SET_WEAKREFD (symbolP2);
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolS *symp = symbolP2;
|
||||
|
||||
while (S_IS_WEAKREFR (symp) && symp != symbolP)
|
||||
{
|
||||
expressionS *expP = symbol_get_value_expression (symp);
|
||||
|
||||
assert (expP->X_op == O_symbol
|
||||
&& expP->X_add_number == 0);
|
||||
symp = expP->X_add_symbol;
|
||||
}
|
||||
if (symp == symbolP)
|
||||
{
|
||||
char *loop;
|
||||
|
||||
loop = concat (S_GET_NAME (symbolP),
|
||||
" => ", S_GET_NAME (symbolP2), NULL);
|
||||
|
||||
symp = symbolP2;
|
||||
while (symp != symbolP)
|
||||
{
|
||||
char *old_loop = loop;
|
||||
symp = symbol_get_value_expression (symp)->X_add_symbol;
|
||||
loop = concat (loop, " => ", S_GET_NAME (symp), NULL);
|
||||
free (old_loop);
|
||||
}
|
||||
|
||||
as_bad (_("%s: would close weakref loop: %s"),
|
||||
S_GET_NAME (symbolP), loop);
|
||||
|
||||
free (loop);
|
||||
|
||||
*end_name = delim;
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Short-circuiting instead of just checking here might speed
|
||||
things up a tiny little bit, but loop error messages would
|
||||
miss intermediate links. */
|
||||
/* symbolP2 = symp; */
|
||||
}
|
||||
|
||||
*end_name = delim;
|
||||
|
||||
memset (&exp, 0, sizeof (exp));
|
||||
exp.X_op = O_symbol;
|
||||
exp.X_add_symbol = symbolP2;
|
||||
|
||||
S_SET_SEGMENT (symbolP, undefined_section);
|
||||
symbol_set_value_expression (symbolP, &exp);
|
||||
symbol_set_frag (symbolP, &zero_address_frag);
|
||||
S_SET_WEAKREFR (symbolP);
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
|
||||
/* Verify that we are at the end of a line. If not, issue an error and
|
||||
|
@ -185,3 +185,4 @@ extern void stringer (int append_zero);
|
||||
extern void s_xstab (int what);
|
||||
extern void s_rva (int);
|
||||
extern void s_incbin (int);
|
||||
extern void s_weakref (int);
|
||||
|
@ -72,6 +72,15 @@ struct symbol
|
||||
routines. */
|
||||
unsigned int sy_mri_common : 1;
|
||||
|
||||
/* This is set if the symbol is set with a .weakref directive. */
|
||||
unsigned int sy_weakrefr : 1;
|
||||
|
||||
/* This is set when the symbol is referenced as part of a .weakref
|
||||
directive, but only if the symbol was not in the symbol table
|
||||
before. It is cleared as soon as any direct reference to the
|
||||
symbol is present. */
|
||||
unsigned int sy_weakrefd : 1;
|
||||
|
||||
#ifdef OBJ_SYMFIELD_TYPE
|
||||
OBJ_SYMFIELD_TYPE sy_obj;
|
||||
#endif
|
||||
|
139
gas/symbols.c
139
gas/symbols.c
@ -309,6 +309,7 @@ colon (/* Just seen "x:" - rattle symbols & frags. */
|
||||
|
||||
if ((symbolP = symbol_find (sym_name)) != 0)
|
||||
{
|
||||
S_CLEAR_WEAKREFR (symbolP);
|
||||
#ifdef RESOLVE_SYMBOL_REDEFINITION
|
||||
if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
|
||||
return symbolP;
|
||||
@ -650,18 +651,41 @@ symbol_temp_make (void)
|
||||
|
||||
symbolS *
|
||||
symbol_find_exact (const char *name)
|
||||
{
|
||||
return symbol_find_exact_noref (name, 0);
|
||||
}
|
||||
|
||||
symbolS *
|
||||
symbol_find_exact_noref (const char *name, int noref)
|
||||
{
|
||||
struct local_symbol *locsym;
|
||||
symbolS* sym;
|
||||
|
||||
locsym = (struct local_symbol *) hash_find (local_hash, name);
|
||||
if (locsym != NULL)
|
||||
return (symbolS *) locsym;
|
||||
|
||||
return ((symbolS *) hash_find (sy_hash, name));
|
||||
sym = ((symbolS *) hash_find (sy_hash, name));
|
||||
|
||||
/* Any references to the symbol, except for the reference in
|
||||
.weakref, must clear this flag, such that the symbol does not
|
||||
turn into a weak symbol. Note that we don't have to handle the
|
||||
local_symbol case, since a weakrefd is always promoted out of the
|
||||
local_symbol table when it is turned into a weak symbol. */
|
||||
if (sym && ! noref)
|
||||
S_CLEAR_WEAKREFD (sym);
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
symbolS *
|
||||
symbol_find (const char *name)
|
||||
{
|
||||
return symbol_find_noref (name, 0);
|
||||
}
|
||||
|
||||
symbolS *
|
||||
symbol_find_noref (const char *name, int noref)
|
||||
{
|
||||
#ifdef tc_canonicalize_symbol_name
|
||||
{
|
||||
@ -690,7 +714,7 @@ symbol_find (const char *name)
|
||||
*copy = '\0';
|
||||
}
|
||||
|
||||
return symbol_find_exact (name);
|
||||
return symbol_find_exact_noref (name, noref);
|
||||
}
|
||||
|
||||
/* Once upon a time, symbols were kept in a singly linked list. At
|
||||
@ -970,6 +994,19 @@ resolve_symbol_value (symbolS *symp)
|
||||
symp->sy_value.X_op_symbol = NULL;
|
||||
|
||||
do_symbol:
|
||||
if (S_IS_WEAKREFR (symp))
|
||||
{
|
||||
assert (final_val == 0);
|
||||
if (S_IS_WEAKREFR (add_symbol))
|
||||
{
|
||||
assert (add_symbol->sy_value.X_op == O_symbol
|
||||
&& add_symbol->sy_value.X_add_number == 0);
|
||||
add_symbol = add_symbol->sy_value.X_add_symbol;
|
||||
assert (! S_IS_WEAKREFR (add_symbol));
|
||||
symp->sy_value.X_add_symbol = add_symbol;
|
||||
}
|
||||
}
|
||||
|
||||
if (symp->sy_mri_common)
|
||||
{
|
||||
/* This is a symbol inside an MRI common section. The
|
||||
@ -1039,6 +1076,8 @@ resolve_symbol_value (symbolS *symp)
|
||||
}
|
||||
|
||||
resolved = symbol_resolved_p (add_symbol);
|
||||
if (S_IS_WEAKREFR (symp))
|
||||
goto exit_dont_set_value;
|
||||
break;
|
||||
|
||||
case O_uminus:
|
||||
@ -1717,6 +1756,9 @@ S_GET_VALUE (symbolS *s)
|
||||
if (!finalize_syms)
|
||||
return val;
|
||||
}
|
||||
if (S_IS_WEAKREFR (s))
|
||||
return S_GET_VALUE (s->sy_value.X_add_symbol);
|
||||
|
||||
if (s->sy_value.X_op != O_constant)
|
||||
{
|
||||
static symbolS *recur;
|
||||
@ -1751,6 +1793,7 @@ S_SET_VALUE (symbolS *s, valueT val)
|
||||
s->sy_value.X_op = O_constant;
|
||||
s->sy_value.X_add_number = (offsetT) val;
|
||||
s->sy_value.X_unsigned = 0;
|
||||
S_CLEAR_WEAKREFR (s);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1806,9 +1849,31 @@ S_IS_WEAK (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
return 0;
|
||||
/* Conceptually, a weakrefr is weak if the referenced symbol is. We
|
||||
could probably handle a WEAKREFR as always weak though. E.g., if
|
||||
the referenced symbol has lost its weak status, there's no reason
|
||||
to keep handling the weakrefr as if it was weak. */
|
||||
if (S_IS_WEAKREFR (s))
|
||||
return S_IS_WEAK (s->sy_value.X_add_symbol);
|
||||
return (s->bsym->flags & BSF_WEAK) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
S_IS_WEAKREFR (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
return 0;
|
||||
return s->sy_weakrefr != 0;
|
||||
}
|
||||
|
||||
int
|
||||
S_IS_WEAKREFD (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
return 0;
|
||||
return s->sy_weakrefd != 0;
|
||||
}
|
||||
|
||||
int
|
||||
S_IS_COMMON (symbolS *s)
|
||||
{
|
||||
@ -2008,10 +2073,70 @@ S_SET_WEAK (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
s = local_symbol_convert ((struct local_symbol *) s);
|
||||
#ifdef obj_set_weak_hook
|
||||
obj_set_weak_hook (s);
|
||||
#endif
|
||||
s->bsym->flags |= BSF_WEAK;
|
||||
s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
|
||||
}
|
||||
|
||||
void
|
||||
S_SET_WEAKREFR (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
s = local_symbol_convert ((struct local_symbol *) s);
|
||||
s->sy_weakrefr = 1;
|
||||
/* If the alias was already used, make sure we mark the target as
|
||||
used as well, otherwise it might be dropped from the symbol
|
||||
table. This may have unintended side effects if the alias is
|
||||
later redirected to another symbol, such as keeping the unused
|
||||
previous target in the symbol table. Since it will be weak, it's
|
||||
not a big deal. */
|
||||
if (s->sy_used)
|
||||
symbol_mark_used (s->sy_value.X_add_symbol);
|
||||
}
|
||||
|
||||
void
|
||||
S_CLEAR_WEAKREFR (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
return;
|
||||
s->sy_weakrefr = 0;
|
||||
}
|
||||
|
||||
void
|
||||
S_SET_WEAKREFD (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
s = local_symbol_convert ((struct local_symbol *) s);
|
||||
s->sy_weakrefd = 1;
|
||||
S_SET_WEAK (s);
|
||||
}
|
||||
|
||||
void
|
||||
S_CLEAR_WEAKREFD (symbolS *s)
|
||||
{
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
return;
|
||||
if (s->sy_weakrefd)
|
||||
{
|
||||
s->sy_weakrefd = 0;
|
||||
/* If a weakref target symbol is weak, then it was never
|
||||
referenced directly before, not even in a .global directive,
|
||||
so decay it to local. If it remains undefined, it will be
|
||||
later turned into a global, like any other undefined
|
||||
symbol. */
|
||||
if (s->bsym->flags & BSF_WEAK)
|
||||
{
|
||||
#ifdef obj_clear_weak_hook
|
||||
obj_clear_weak_hook (s);
|
||||
#endif
|
||||
s->bsym->flags &= ~BSF_WEAK;
|
||||
s->bsym->flags |= BSF_LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
S_SET_THREAD_LOCAL (symbolS *s)
|
||||
{
|
||||
@ -2095,6 +2220,7 @@ symbol_set_value_expression (symbolS *s, const expressionS *exp)
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
s = local_symbol_convert ((struct local_symbol *) s);
|
||||
s->sy_value = *exp;
|
||||
S_CLEAR_WEAKREFR (s);
|
||||
}
|
||||
|
||||
/* Return a pointer to the X_add_number component of a symbol. */
|
||||
@ -2129,6 +2255,7 @@ symbol_set_frag (symbolS *s, fragS *f)
|
||||
return;
|
||||
}
|
||||
s->sy_frag = f;
|
||||
S_CLEAR_WEAKREFR (s);
|
||||
}
|
||||
|
||||
/* Return the frag of a symbol. */
|
||||
@ -2149,6 +2276,8 @@ symbol_mark_used (symbolS *s)
|
||||
if (LOCAL_SYMBOL_CHECK (s))
|
||||
return;
|
||||
s->sy_used = 1;
|
||||
if (S_IS_WEAKREFR (s))
|
||||
symbol_mark_used (s->sy_value.X_add_symbol);
|
||||
}
|
||||
|
||||
/* Clear the mark of whether a symbol has been used. */
|
||||
@ -2472,11 +2601,17 @@ print_symbol_value_1 (FILE *file, symbolS *sym)
|
||||
fprintf (file, " local");
|
||||
if (S_IS_EXTERNAL (sym))
|
||||
fprintf (file, " extern");
|
||||
if (S_IS_WEAK (sym))
|
||||
fprintf (file, " weak");
|
||||
if (S_IS_DEBUG (sym))
|
||||
fprintf (file, " debug");
|
||||
if (S_IS_DEFINED (sym))
|
||||
fprintf (file, " defined");
|
||||
}
|
||||
if (S_IS_WEAKREFR (sym))
|
||||
fprintf (file, " weakrefr");
|
||||
if (S_IS_WEAKREFD (sym))
|
||||
fprintf (file, " weakrefd");
|
||||
fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
|
||||
if (symbol_resolved_p (sym))
|
||||
{
|
||||
|
@ -37,7 +37,9 @@ extern int symbols_case_sensitive;
|
||||
|
||||
char *decode_local_label_name (char *s);
|
||||
symbolS *symbol_find (const char *name);
|
||||
symbolS *symbol_find_noref (const char *name, int noref);
|
||||
symbolS *symbol_find_exact (const char *name);
|
||||
symbolS *symbol_find_exact_noref (const char *name, int noref);
|
||||
symbolS *symbol_find_or_make (const char *name);
|
||||
symbolS *symbol_make (const char *name);
|
||||
symbolS *symbol_new (const char *name, segT segment, valueT value,
|
||||
@ -83,6 +85,8 @@ extern void S_SET_VALUE (symbolS *, valueT);
|
||||
extern int S_IS_FUNCTION (symbolS *);
|
||||
extern int S_IS_EXTERNAL (symbolS *);
|
||||
extern int S_IS_WEAK (symbolS *);
|
||||
extern int S_IS_WEAKREFR (symbolS *);
|
||||
extern int S_IS_WEAKREFD (symbolS *);
|
||||
extern int S_IS_COMMON (symbolS *);
|
||||
extern int S_IS_DEFINED (symbolS *);
|
||||
extern int S_FORCE_RELOC (symbolS *, int);
|
||||
@ -98,6 +102,10 @@ extern void S_SET_EXTERNAL (symbolS *);
|
||||
extern void S_SET_NAME (symbolS *, const char *);
|
||||
extern void S_CLEAR_EXTERNAL (symbolS *);
|
||||
extern void S_SET_WEAK (symbolS *);
|
||||
extern void S_SET_WEAKREFR (symbolS *);
|
||||
extern void S_CLEAR_WEAKREFR (symbolS *);
|
||||
extern void S_SET_WEAKREFD (symbolS *);
|
||||
extern void S_CLEAR_WEAKREFD (symbolS *);
|
||||
extern void S_SET_THREAD_LOCAL (symbolS *);
|
||||
extern void S_SET_VOLATILE (symbolS *);
|
||||
extern void S_SET_FORWARD_REF (symbolS *);
|
||||
|
@ -1,3 +1,11 @@
|
||||
2005-10-24 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* gas/all/weakref1.s, gas/all/weakref1.d: New test.
|
||||
* gas/all/weakref1g.d, gas/all/weakref1l.d: New tests.
|
||||
* gas/all/weakref1u.d, gas/all/weakref1w.d: New tests.
|
||||
* gas/all/weakref2.s, gas/all/weakref3.s: New tests.
|
||||
* gas/all/gas.exp: Run new tests.
|
||||
|
||||
2005-10-24 Jan Beulich <jbeulich@novell.com>
|
||||
|
||||
* gas/ia64/index.[sl]: New.
|
||||
|
@ -250,6 +250,14 @@ if { ![istarget "i960-*-*"] } {
|
||||
run_dump_test quad
|
||||
}
|
||||
|
||||
run_dump_test weakref1
|
||||
run_dump_test weakref1g
|
||||
run_dump_test weakref1l
|
||||
run_dump_test weakref1u
|
||||
run_dump_test weakref1w
|
||||
gas_test_error "weakref2.s" "" "e: would close weakref loop: e => a => b => c => d => e"
|
||||
gas_test_error "weakref3.s" "" "a: would close weakref loop: a => b => c => d => e => a"
|
||||
|
||||
load_lib gas-dg.exp
|
||||
dg-init
|
||||
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" ""
|
||||
|
112
gas/testsuite/gas/all/weakref1.d
Normal file
112
gas/testsuite/gas/all/weakref1.d
Normal file
@ -0,0 +1,112 @@
|
||||
#objdump: -r
|
||||
#name: weakref tests, relocations
|
||||
# ecoff (OSF/alpha) lacks .weak support
|
||||
# pdp11 lacks .long
|
||||
# the following must be present in all weakref1*.d
|
||||
#not-target: alpha*-*-osf* *-*-ecoff pdp11-*-aout
|
||||
|
||||
#...
|
||||
RELOCATION RECORDS FOR \[\.text\]:
|
||||
OFFSET +TYPE +VALUE *
|
||||
# the rest of this file is generated with the following script:
|
||||
# # script begin
|
||||
# echo \#...
|
||||
# sed -n 's:^\.weakref .*, \(\(u\|\(w\)\).*\)$:.*( \3 |\(sec 0\)).* \1:p' weakref1.s | uniq | while read line; do echo "$line"; echo "#..."; done
|
||||
|
||||
# sed -n 's:^\.long \(W\|\)\(.*[^a-z]\)[a-z]*\(\| - .*\)$:\2:p' weakref1.s | sed -e 's,^[lg].*,(&|\\.text)(\\+0x[0-9a-f]+)?,' | sed 's,^,[0-9a-f]+ [^ ]* +,'
|
||||
# # script output:
|
||||
#...
|
||||
[0-9a-f]+ [^ ]* +wa1
|
||||
[0-9a-f]+ [^ ]* +ua2
|
||||
[0-9a-f]+ [^ ]* +ua3
|
||||
[0-9a-f]+ [^ ]* +ua3
|
||||
[0-9a-f]+ [^ ]* +ua4
|
||||
[0-9a-f]+ [^ ]* +ua4
|
||||
[0-9a-f]+ [^ ]* +wb1
|
||||
[0-9a-f]+ [^ ]* +ub2
|
||||
[0-9a-f]+ [^ ]* +ub3
|
||||
[0-9a-f]+ [^ ]* +ub3
|
||||
[0-9a-f]+ [^ ]* +ub4
|
||||
[0-9a-f]+ [^ ]* +ub4
|
||||
[0-9a-f]+ [^ ]* +wc1
|
||||
[0-9a-f]+ [^ ]* +wc1
|
||||
[0-9a-f]+ [^ ]* +uc2
|
||||
[0-9a-f]+ [^ ]* +uc2
|
||||
[0-9a-f]+ [^ ]* +uc3
|
||||
[0-9a-f]+ [^ ]* +uc3
|
||||
[0-9a-f]+ [^ ]* +uc3
|
||||
[0-9a-f]+ [^ ]* +uc3
|
||||
[0-9a-f]+ [^ ]* +uc4
|
||||
[0-9a-f]+ [^ ]* +uc4
|
||||
[0-9a-f]+ [^ ]* +uc4
|
||||
[0-9a-f]+ [^ ]* +uc4
|
||||
[0-9a-f]+ [^ ]* +uc5
|
||||
[0-9a-f]+ [^ ]* +uc5
|
||||
[0-9a-f]+ [^ ]* +uc5
|
||||
[0-9a-f]+ [^ ]* +uc5
|
||||
[0-9a-f]+ [^ ]* +uc6
|
||||
[0-9a-f]+ [^ ]* +uc6
|
||||
[0-9a-f]+ [^ ]* +uc6
|
||||
[0-9a-f]+ [^ ]* +uc6
|
||||
[0-9a-f]+ [^ ]* +uc7
|
||||
[0-9a-f]+ [^ ]* +uc7
|
||||
[0-9a-f]+ [^ ]* +uc8
|
||||
[0-9a-f]+ [^ ]* +uc8
|
||||
[0-9a-f]+ [^ ]* +uc9
|
||||
[0-9a-f]+ [^ ]* +uc9
|
||||
[0-9a-f]+ [^ ]* +uc9
|
||||
[0-9a-f]+ [^ ]* +ww1
|
||||
[0-9a-f]+ [^ ]* +ww2
|
||||
[0-9a-f]+ [^ ]* +ww3
|
||||
[0-9a-f]+ [^ ]* +ww3
|
||||
[0-9a-f]+ [^ ]* +ww4
|
||||
[0-9a-f]+ [^ ]* +ww4
|
||||
[0-9a-f]+ [^ ]* +ww5
|
||||
[0-9a-f]+ [^ ]* +ww5
|
||||
[0-9a-f]+ [^ ]* +ww6
|
||||
[0-9a-f]+ [^ ]* +ww7
|
||||
[0-9a-f]+ [^ ]* +ww8
|
||||
[0-9a-f]+ [^ ]* +ww8
|
||||
[0-9a-f]+ [^ ]* +ww9
|
||||
[0-9a-f]+ [^ ]* +ww9
|
||||
[0-9a-f]+ [^ ]* +ww10
|
||||
[0-9a-f]+ [^ ]* +ww10
|
||||
[0-9a-f]+ [^ ]* +um2
|
||||
[0-9a-f]+ [^ ]* +wm3
|
||||
[0-9a-f]+ [^ ]* +um5
|
||||
[0-9a-f]+ [^ ]* +wm6
|
||||
[0-9a-f]+ [^ ]* +wm7
|
||||
[0-9a-f]+ [^ ]* +wm8
|
||||
[0-9a-f]+ [^ ]* +wh2
|
||||
[0-9a-f]+ [^ ]* +wh3
|
||||
[0-9a-f]+ [^ ]* +wh4
|
||||
[0-9a-f]+ [^ ]* +wh5
|
||||
[0-9a-f]+ [^ ]* +wh6
|
||||
[0-9a-f]+ [^ ]* +wh7
|
||||
[0-9a-f]+ [^ ]* +uh8
|
||||
[0-9a-f]+ [^ ]* +uh8
|
||||
[0-9a-f]+ [^ ]* +uh9
|
||||
[0-9a-f]+ [^ ]* +uh9
|
||||
[0-9a-f]+ [^ ]* +(lr1|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(lr1|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(lr2|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(lr2|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +wr3
|
||||
[0-9a-f]+ [^ ]* +wr3
|
||||
[0-9a-f]+ [^ ]* +wr4
|
||||
[0-9a-f]+ [^ ]* +wr5
|
||||
[0-9a-f]+ [^ ]* +(lr6|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +ur6
|
||||
[0-9a-f]+ [^ ]* +(lr7|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(lr7|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld1|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld2|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld3|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld4|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +ud5
|
||||
[0-9a-f]+ [^ ]* +(gd6|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(gd7|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld8|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld8|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld9|\.text)(\+0x[0-9a-f]+)?
|
||||
[0-9a-f]+ [^ ]* +(ld9|\.text)(\+0x[0-9a-f]+)?
|
277
gas/testsuite/gas/all/weakref1.s
Normal file
277
gas/testsuite/gas/all/weakref1.s
Normal file
@ -0,0 +1,277 @@
|
||||
.text
|
||||
l:
|
||||
/* a# test references after weakref. */
|
||||
.weakref Wwa1, wa1
|
||||
.long Wwa1
|
||||
|
||||
.weakref Wua2, ua2
|
||||
.long ua2
|
||||
|
||||
.weakref Wua3, ua3
|
||||
.long Wua3
|
||||
.long ua3
|
||||
|
||||
.weakref Wua4, ua4
|
||||
.long ua4
|
||||
.long Wua4
|
||||
|
||||
.weakref Wna5, na5
|
||||
|
||||
/* b# test references before weakref. */
|
||||
.long Wwb1
|
||||
.weakref Wwb1, wb1
|
||||
|
||||
.long ub2
|
||||
.weakref Wub2, ub2
|
||||
|
||||
.long Wub3
|
||||
.long ub3
|
||||
.weakref Wub3, ub3
|
||||
|
||||
.long ub4
|
||||
.long Wub4
|
||||
.weakref Wub4, ub4
|
||||
|
||||
/* c# test combinations of references before and after weakref. */
|
||||
.long Wwc1
|
||||
.weakref Wwc1, wc1
|
||||
.long Wwc1
|
||||
|
||||
.long uc2
|
||||
.weakref Wuc2, uc2
|
||||
.long uc2
|
||||
|
||||
.long Wuc3
|
||||
.long uc3
|
||||
.weakref Wuc3, uc3
|
||||
.long Wuc3
|
||||
.long uc3
|
||||
|
||||
.long uc4
|
||||
.long Wuc4
|
||||
.weakref Wuc4, uc4
|
||||
.long uc4
|
||||
.long Wuc4
|
||||
|
||||
.long Wuc5
|
||||
.long uc5
|
||||
.weakref Wuc5, uc5
|
||||
.long uc5
|
||||
.long Wuc5
|
||||
|
||||
.long uc6
|
||||
.long Wuc6
|
||||
.weakref Wuc6, uc6
|
||||
.long uc6
|
||||
.long Wuc6
|
||||
|
||||
.long uc7
|
||||
.weakref Wuc7, uc7
|
||||
.long Wuc7
|
||||
|
||||
.long Wuc8
|
||||
.weakref Wuc8, uc8
|
||||
.long uc8
|
||||
|
||||
.long Wuc9
|
||||
.weakref Wuc9, uc9
|
||||
.long Wuc9
|
||||
.long uc9
|
||||
|
||||
/* w# test that explicitly weak target don't lose the weak status */
|
||||
.weakref Www1, ww1
|
||||
.weak ww1
|
||||
.long ww1
|
||||
|
||||
.weak ww2
|
||||
.weakref Www2, ww2
|
||||
.long ww2
|
||||
|
||||
.weak ww3
|
||||
.long ww3
|
||||
.weakref Www3, ww3
|
||||
.long ww3
|
||||
|
||||
.long ww4
|
||||
.weakref Www4, ww4
|
||||
.weak ww4
|
||||
.long ww4
|
||||
|
||||
.long ww5
|
||||
.weakref Www5, ww5
|
||||
.long ww5
|
||||
.weak ww5
|
||||
|
||||
.weakref Www6, ww6
|
||||
.weak ww6
|
||||
.long Www6
|
||||
|
||||
.weak ww7
|
||||
.weakref Www7, ww7
|
||||
.long Www7
|
||||
|
||||
.weak ww8
|
||||
.long Www8
|
||||
.weakref Www8, ww8
|
||||
.long Www8
|
||||
|
||||
.long Www9
|
||||
.weakref Www9, ww9
|
||||
.weak ww9
|
||||
.long Www9
|
||||
|
||||
.long Www10
|
||||
.weakref Www10, ww10
|
||||
.long Www10
|
||||
.weak ww10
|
||||
|
||||
/* m# test multiple weakrefs */
|
||||
.weakref Wnm1, nm1
|
||||
.weakref Wnm1, nm1
|
||||
|
||||
.weakref Wum2, um2
|
||||
.weakref Wum2, um2
|
||||
.long um2
|
||||
|
||||
.weakref Wwm3, wm3
|
||||
.weakref Wwm3, wm3
|
||||
.long Wwm3
|
||||
|
||||
.weakref Wnm4a, nm4
|
||||
.weakref Wnm4b, nm4
|
||||
|
||||
.weakref Wum5a, um5
|
||||
.weakref Wum5b, um5
|
||||
.long um5
|
||||
|
||||
.weakref Wwm6a, wm6
|
||||
.weakref Wwm6b, wm6
|
||||
.long Wwm6a
|
||||
|
||||
.weakref Wwm7a, wm7
|
||||
.weakref Wwm7b, wm7
|
||||
.long Wwm7b
|
||||
|
||||
.weakref Wwm8a, wm8
|
||||
.long Wwm8b
|
||||
.weakref Wwm8b, wm8
|
||||
|
||||
/* h# test weakref chain */
|
||||
.weakref Wnh1a, nh1
|
||||
.weakref Wnh1b, Wnh1a
|
||||
.weakref Wnh1c, Wnh1b
|
||||
|
||||
.weakref Wwh2a, wh2
|
||||
.weakref Wwh2b, Wwh2a
|
||||
.long Wwh2b
|
||||
|
||||
.weakref Wwh3a, wh3
|
||||
.weakref Wwh3b, Wwh3a
|
||||
.long Wwh3a
|
||||
|
||||
.weakref Wwh4b, Wwh4a
|
||||
.weakref Wwh4a, wh4
|
||||
.long Wwh4b
|
||||
|
||||
.long Wwh5b
|
||||
.weakref Wwh5a, wh5
|
||||
.weakref Wwh5b, Wwh5a
|
||||
|
||||
.long Wwh6b
|
||||
.weakref Wwh6b, Wwh6a
|
||||
.weakref Wwh6a, wh6
|
||||
|
||||
.weakref Wwh7b, Wwh7a
|
||||
.long Wwh7b
|
||||
.weakref Wwh7a, wh7
|
||||
|
||||
.long Wuh8c
|
||||
.weakref Wuh8a, uh8
|
||||
.weakref Wuh8b, Wuh8a
|
||||
.weakref Wuh8c, Wuh8b
|
||||
.long uh8
|
||||
|
||||
.long Wuh9c
|
||||
.weakref Wuh9c, Wuh9b
|
||||
.weakref Wuh9b, Wuh9a
|
||||
.weakref Wuh9a, uh9
|
||||
.long uh9
|
||||
|
||||
/* r# weakref redefinitions, to and from */
|
||||
.weakref lr1, nr1
|
||||
.long lr1
|
||||
.set lr1, l
|
||||
.long lr1
|
||||
|
||||
.long lr2
|
||||
.weakref lr2, nr2
|
||||
.set lr2, l
|
||||
.long lr2
|
||||
|
||||
.set Wwr3, l
|
||||
.long Wwr3
|
||||
.weakref Wwr3, wr3
|
||||
.long Wwr3
|
||||
|
||||
.set Wwr4, l
|
||||
.weakref Wwr4, wr4
|
||||
.long Wwr4
|
||||
|
||||
.set Wwr5, l
|
||||
.long Wwr5
|
||||
.weakref Wwr5, wr5
|
||||
|
||||
.weakref lr6, ur6
|
||||
.long lr6
|
||||
.set lr6, l
|
||||
.long ur6
|
||||
|
||||
.weakref lr7, nr7
|
||||
.long lr7
|
||||
lr7:
|
||||
.long lr7
|
||||
|
||||
/* d# target symbol definitions */
|
||||
.weakref Wld1, ld1
|
||||
.long Wld1
|
||||
.set ld1, l
|
||||
|
||||
.weakref Wld2, ld2
|
||||
.long Wld2
|
||||
ld2:
|
||||
|
||||
ld3:
|
||||
.weakref Wld3, ld3
|
||||
.long Wld3
|
||||
|
||||
ld4:
|
||||
.long Wld4
|
||||
.weakref Wld4, ld4
|
||||
|
||||
.global ud5
|
||||
.weakref Wud5, ud5
|
||||
.long Wud5
|
||||
|
||||
.global gd6
|
||||
.weakref Wgd6, gd6
|
||||
.long Wgd6
|
||||
gd6:
|
||||
|
||||
.weakref Wgd7, gd7
|
||||
.long Wgd7
|
||||
.global gd7
|
||||
gd7:
|
||||
|
||||
.long Wld8c
|
||||
.weakref Wld8a, ld8
|
||||
.weakref Wld8b, Wld8a
|
||||
.weakref Wld8c, Wld8b
|
||||
.long ld8
|
||||
ld8:
|
||||
|
||||
.long Wld9c
|
||||
.weakref Wld9c, Wld9b
|
||||
.weakref Wld9b, Wld9a
|
||||
.weakref Wld9a, ld9
|
||||
.long ld9
|
||||
ld9:
|
18
gas/testsuite/gas/all/weakref1g.d
Normal file
18
gas/testsuite/gas/all/weakref1g.d
Normal file
@ -0,0 +1,18 @@
|
||||
#nm: --defined-only --extern-only --no-sort
|
||||
#name: weakref tests, global syms
|
||||
#source: weakref1.s
|
||||
# see weakref1.d for comments on the not-targets
|
||||
# ecoff (OSF/alpha) lacks .weak support
|
||||
# pdp11 lacks .long
|
||||
#not-target: alpha*-*-osf* *-*-ecoff pdp11-*-aout
|
||||
|
||||
# the rest of this file is generated with the following script:
|
||||
# # script begin
|
||||
# echo \#...
|
||||
# sed -n 's,^[ ]*\.global \(g.*\),.* T \1,p' weakref1.s | uniq
|
||||
# echo \#pass
|
||||
# # script output:
|
||||
#...
|
||||
.* T gd6
|
||||
.* T gd7
|
||||
#pass
|
35
gas/testsuite/gas/all/weakref1l.d
Normal file
35
gas/testsuite/gas/all/weakref1l.d
Normal file
@ -0,0 +1,35 @@
|
||||
#nm: --defined-only --no-sort
|
||||
#name: weakref tests, local syms
|
||||
#source: weakref1.s
|
||||
# aix drops local symbols
|
||||
# see weakref1.d for comments on the other not-targets
|
||||
#not-target: *-*-aix* alpha*-*-osf* *-*-ecoff pdp11-*-aout
|
||||
|
||||
# the rest of this file is generated with the following script:
|
||||
# # script begin
|
||||
# sed -n 's,^\(l[^ ]*\)[ ]*:.*,.* t \1,p;s:^[ ]*\.set[ ][ ]*\(l[^ ]*\)[ ]*,.*:.* t \1:p' weakref1.s | uniq | while read line; do echo "#..."; echo "$line"; done
|
||||
# echo \#pass
|
||||
# # script output:
|
||||
#...
|
||||
.* t l
|
||||
#...
|
||||
.* t lr1
|
||||
#...
|
||||
.* t lr2
|
||||
#...
|
||||
.* t lr6
|
||||
#...
|
||||
.* t lr7
|
||||
#...
|
||||
.* t ld1
|
||||
#...
|
||||
.* t ld2
|
||||
#...
|
||||
.* t ld3
|
||||
#...
|
||||
.* t ld4
|
||||
#...
|
||||
.* t ld8
|
||||
#...
|
||||
.* t ld9
|
||||
#pass
|
53
gas/testsuite/gas/all/weakref1u.d
Normal file
53
gas/testsuite/gas/all/weakref1u.d
Normal file
@ -0,0 +1,53 @@
|
||||
#nm: --undefined-only --no-sort
|
||||
#name: weakref tests, strong undefined syms
|
||||
#source: weakref1.s
|
||||
# aout turns undefined into *ABS* symbols.
|
||||
# see weakref1.d for comments on the other not-targets
|
||||
#not-target: *-*-aout ns32k-*-netbsd alpha*-*-osf* *-*-ecoff pdp11-*-aout
|
||||
|
||||
# the rest of this file is generated with the following script:
|
||||
# # script begin
|
||||
# sed -n 's:^[ ]*\.weakref .*, \(u.*\)$:.* U \1:p' weakref1.s | uniq | while read line; do echo "#..."; echo "$line"; done
|
||||
# echo \#pass
|
||||
# # script output:
|
||||
#...
|
||||
.* U ua2
|
||||
#...
|
||||
.* U ua3
|
||||
#...
|
||||
.* U ua4
|
||||
#...
|
||||
.* U ub2
|
||||
#...
|
||||
.* U ub3
|
||||
#...
|
||||
.* U ub4
|
||||
#...
|
||||
.* U uc2
|
||||
#...
|
||||
.* U uc3
|
||||
#...
|
||||
.* U uc4
|
||||
#...
|
||||
.* U uc5
|
||||
#...
|
||||
.* U uc6
|
||||
#...
|
||||
.* U uc7
|
||||
#...
|
||||
.* U uc8
|
||||
#...
|
||||
.* U uc9
|
||||
#...
|
||||
.* U um2
|
||||
#...
|
||||
.* U um5
|
||||
#...
|
||||
.* U uh8
|
||||
#...
|
||||
.* U uh9
|
||||
#...
|
||||
.* U ur6
|
||||
#...
|
||||
.* U ud5
|
||||
#pass
|
64
gas/testsuite/gas/all/weakref1w.d
Normal file
64
gas/testsuite/gas/all/weakref1w.d
Normal file
@ -0,0 +1,64 @@
|
||||
#nm: --undefined-only --no-sort
|
||||
#name: weakref tests, weak undefined syms
|
||||
#source: weakref1.s
|
||||
# see weakref1.d for comments on the not-targets
|
||||
#not-target: alpha*-*-osf* *-*-ecoff pdp11-*-aout
|
||||
|
||||
# the rest of this file is generated with the following script:
|
||||
# # script begin
|
||||
# sed -n 's:^[ ]*\.weakref .*, \(w.*\)$:.* w \1:p' weakref1.s | uniq | while read line; do echo "#..."; echo "$line"; done
|
||||
# echo \#pass
|
||||
# # script output:
|
||||
#...
|
||||
.* w wa1
|
||||
#...
|
||||
.* w wb1
|
||||
#...
|
||||
.* w wc1
|
||||
#...
|
||||
.* w ww1
|
||||
#...
|
||||
.* w ww2
|
||||
#...
|
||||
.* w ww3
|
||||
#...
|
||||
.* w ww4
|
||||
#...
|
||||
.* w ww5
|
||||
#...
|
||||
.* w ww6
|
||||
#...
|
||||
.* w ww7
|
||||
#...
|
||||
.* w ww8
|
||||
#...
|
||||
.* w ww9
|
||||
#...
|
||||
.* w ww10
|
||||
#...
|
||||
.* w wm3
|
||||
#...
|
||||
.* w wm6
|
||||
#...
|
||||
.* w wm7
|
||||
#...
|
||||
.* w wm8
|
||||
#...
|
||||
.* w wh2
|
||||
#...
|
||||
.* w wh3
|
||||
#...
|
||||
.* w wh4
|
||||
#...
|
||||
.* w wh5
|
||||
#...
|
||||
.* w wh6
|
||||
#...
|
||||
.* w wh7
|
||||
#...
|
||||
.* w wr3
|
||||
#...
|
||||
.* w wr4
|
||||
#...
|
||||
.* w wr5
|
||||
#pass
|
5
gas/testsuite/gas/all/weakref2.s
Normal file
5
gas/testsuite/gas/all/weakref2.s
Normal file
@ -0,0 +1,5 @@
|
||||
.weakref a,b
|
||||
.weakref b,c
|
||||
.weakref c,d
|
||||
.weakref d,e
|
||||
.weakref e,a
|
5
gas/testsuite/gas/all/weakref3.s
Normal file
5
gas/testsuite/gas/all/weakref3.s
Normal file
@ -0,0 +1,5 @@
|
||||
.weakref e,a
|
||||
.weakref d,e
|
||||
.weakref c,d
|
||||
.weakref b,c
|
||||
.weakref a,b
|
10
gas/write.c
10
gas/write.c
@ -678,13 +678,15 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
|
||||
/* If this symbol is equated to an undefined or common symbol,
|
||||
convert the fixup to being against that symbol. */
|
||||
if (symbol_equated_reloc_p (sym))
|
||||
if (symbol_equated_reloc_p (sym)
|
||||
|| S_IS_WEAKREFR (sym))
|
||||
{
|
||||
symbolS *new_sym
|
||||
= symbol_get_value_expression (sym)->X_add_symbol;
|
||||
const char *name = S_GET_NAME (sym);
|
||||
if (!S_IS_COMMON (new_sym)
|
||||
&& !TC_FAKE_LABEL (name)
|
||||
&& !S_IS_WEAKREFR (sym)
|
||||
&& (!S_IS_EXTERNAL (sym) || S_IS_LOCAL (sym)))
|
||||
as_bad (_("Local symbol `%s' can't be equated to undefined symbol `%s'"),
|
||||
name, S_GET_NAME (new_sym));
|
||||
@ -1483,11 +1485,13 @@ write_object_file (void)
|
||||
|
||||
/* Skip symbols which were equated to undefined or common
|
||||
symbols. */
|
||||
if (symbol_equated_reloc_p (symp))
|
||||
if (symbol_equated_reloc_p (symp)
|
||||
|| S_IS_WEAKREFR (symp))
|
||||
{
|
||||
const char *name = S_GET_NAME (symp);
|
||||
if (S_IS_COMMON (symp)
|
||||
&& !TC_FAKE_LABEL (name)
|
||||
&& !S_IS_WEAKREFR (symp)
|
||||
&& (!S_IS_EXTERNAL (symp) || S_IS_LOCAL (symp)))
|
||||
{
|
||||
expressionS *e = symbol_get_value_expression (symp);
|
||||
@ -1524,7 +1528,7 @@ write_object_file (void)
|
||||
opposites. Sometimes the former checks flags and the
|
||||
latter examines the name... */
|
||||
|| (!S_IS_EXTERNAL (symp)
|
||||
&& (punt || S_IS_LOCAL (symp))
|
||||
&& (punt || S_IS_LOCAL (symp) || S_IS_WEAKREFD (symp))
|
||||
&& ! symbol_used_in_reloc_p (symp)))
|
||||
{
|
||||
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
|
||||
|
Loading…
x
Reference in New Issue
Block a user