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:
Alexandre Oliva 2005-10-24 17:51:42 +00:00
parent 9ba4c44513
commit 06e77878ef
21 changed files with 1028 additions and 30 deletions

View File

@ -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.

View File

@ -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)
{

View File

@ -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);

View File

@ -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}}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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))
{

View File

@ -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 *);

View File

@ -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.

View File

@ -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]] "" ""

View 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]+)?

View 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:

View 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

View 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

View 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

View 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

View File

@ -0,0 +1,5 @@
.weakref a,b
.weakref b,c
.weakref c,d
.weakref d,e
.weakref e,a

View File

@ -0,0 +1,5 @@
.weakref e,a
.weakref d,e
.weakref c,d
.weakref b,c
.weakref a,b

View File

@ -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);