* 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.
+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.
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. */
char *name;
int c;
symbolS *symbolP;
-#ifdef TE_PE
- symbolS *alternateP;
-#endif
do
{
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++;
{
/* 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);
&& !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)
{
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)
{
#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
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);
* 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
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}}
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.
@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
@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
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
{"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. */
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 ();
+}
\f
/* Verify that we are at the end of a line. If not, issue an error and
extern void s_xstab (int what);
extern void s_rva (int);
extern void s_incbin (int);
+extern void s_weakref (int);
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
if ((symbolP = symbol_find (sym_name)) != 0)
{
+ S_CLEAR_WEAKREFR (symbolP);
#ifdef RESOLVE_SYMBOL_REDEFINITION
if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
return symbolP;
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
{
*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
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
}
resolved = symbol_resolved_p (add_symbol);
+ if (S_IS_WEAKREFR (symp))
+ goto exit_dont_set_value;
break;
case O_uminus:
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;
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
{
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)
{
{
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)
{
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. */
return;
}
s->sy_frag = f;
+ S_CLEAR_WEAKREFR (s);
}
/* Return the frag of a symbol. */
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. */
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))
{
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,
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);
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 *);
+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.
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]] "" ""
--- /dev/null
+#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]+)?
--- /dev/null
+ .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:
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+.weakref a,b
+.weakref b,c
+.weakref c,d
+.weakref d,e
+.weakref e,a
--- /dev/null
+.weakref e,a
+.weakref d,e
+.weakref c,d
+.weakref b,c
+.weakref a,b
/* 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));
/* 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);
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);