aboutsummaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2005-10-24 17:51:42 +0000
committerAlexandre Oliva <aoliva@redhat.com>2005-10-24 17:51:42 +0000
commit06e77878ef2b6a57ef92c1691b3aeb668dc248ba (patch)
tree5bb8d868d5530589690a1e248422257110dea2b3 /gas/read.c
parent9ba4c445137e7c387090441e2837e09479f14457 (diff)
downloadfsf-binutils-gdb-06e77878ef2b6a57ef92c1691b3aeb668dc248ba.zip
fsf-binutils-gdb-06e77878ef2b6a57ef92c1691b3aeb668dc248ba.tar.gz
fsf-binutils-gdb-06e77878ef2b6a57ef92c1691b3aeb668dc248ba.tar.bz2
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.
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/gas/read.c b/gas/read.c
index 00f676f..9381735 100644
--- a/gas/read.c
+++ b/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