aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog24
-rw-r--r--gas/config/obj-aout.c1
-rw-r--r--gas/config/obj-coff.c1
-rw-r--r--gas/config/obj-ecoff.c1
-rw-r--r--gas/config/obj-elf.c59
-rw-r--r--gas/config/obj-elf.h5
-rw-r--r--gas/config/obj-multi.h5
-rw-r--r--gas/doc/as.texinfo9
-rw-r--r--gas/obj.h1
9 files changed, 89 insertions, 17 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index fd576ca..a3ca474 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,27 @@
+2000-11-07 H.J. Lu <hjl@gnu.org>
+
+ * doc/as.texinfo (.symver): Updated for versioned symbol
+ reference.
+
+ * obj.h (format_ops): Add the frob_file_before_adjust field.
+
+ * config/obj-aout.c (aout_format_ops): Set the
+ frob_file_before_adjust field to 0.
+ * config/obj-coff.c (coff_format_ops): Likewise.
+ * config/obj-ecoff.c (ecoff_format_ops): Likewise.
+
+ * config/obj-elf.c (obj_elf_symver): Allow duplicated version
+ name.
+ (elf_frob_file_before_adjust): New function to remove unneeded
+ versioned symbols from the symbol table.
+ (elf_format_ops): Set the frob_file_before_adjust field to
+ elf_frob_file_before_adjust.
+
+ * config/obj-elf.h (obj_frob_file_before_adjust): Defined if
+ not defined.
+
+ * config/obj-multi.h (obj_frob_file_before_adjust): Defined.
+
2000-11-07 Peter Targett <peter.targett@arccores.com>
* gas/config/tc-arc.h: Avoid warnings for LITTLE_ENDIAN and
diff --git a/gas/config/obj-aout.c b/gas/config/obj-aout.c
index f24af61..67bb18e 100644
--- a/gas/config/obj-aout.c
+++ b/gas/config/obj-aout.c
@@ -732,6 +732,7 @@ const struct format_ops aout_format_ops =
0, /* app_file */
obj_aout_frob_symbol,
obj_aout_frob_file,
+ 0, /* frob_file_before_adjust */
0, /* frob_file_after_relocs */
0, /* s_get_size */
0, /* s_set_size */
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index 54c968f..e66f17b 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -4653,6 +4653,7 @@ const struct format_ops coff_format_ops =
c_dot_file_symbol,
coff_frob_symbol,
0, /* frob_file */
+ 0, /* frob_file_before_adjust */
coff_frob_file_after_relocs,
0, /* s_get_size */
0, /* s_set_size */
diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c
index 42eaf59..3f80e7d 100644
--- a/gas/config/obj-ecoff.c
+++ b/gas/config/obj-ecoff.c
@@ -309,6 +309,7 @@ const struct format_ops ecoff_format_ops =
ecoff_new_file,
obj_ecoff_frob_symbol,
ecoff_frob_file,
+ 0, /* frob_file_before_adjust */
0, /* frob_file_after_relocs */
0, /* s_get_size */
0, /* s_set_size */
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 4e7f3a36..bad6259 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -1107,14 +1107,6 @@ obj_elf_symver (ignore)
*input_line_pointer = c;
- if (symbol_get_obj (sym)->versioned_name != NULL)
- {
- as_bad (_("multiple .symver directives for symbol `%s'"),
- S_GET_NAME (sym));
- ignore_rest_of_line ();
- return;
- }
-
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
@@ -1133,16 +1125,34 @@ obj_elf_symver (ignore)
*input_line_pointer++ = c;
}
- symbol_get_obj (sym)->versioned_name = xstrdup (name);
+ if (symbol_get_obj (sym)->versioned_name == NULL)
+ {
+ symbol_get_obj (sym)->versioned_name = xstrdup (name);
- *input_line_pointer = c;
+ *input_line_pointer = c;
- if (strchr (symbol_get_obj (sym)->versioned_name, ELF_VER_CHR) == NULL)
+ if (strchr (symbol_get_obj (sym)->versioned_name,
+ ELF_VER_CHR) == NULL)
+ {
+ as_bad (_("missing version name in `%s' for symbol `%s'"),
+ symbol_get_obj (sym)->versioned_name,
+ S_GET_NAME (sym));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
{
- as_bad (_("missing version name in `%s' for symbol `%s'"),
- symbol_get_obj (sym)->versioned_name, S_GET_NAME (sym));
- ignore_rest_of_line ();
- return;
+ if (strcmp (symbol_get_obj (sym)->versioned_name, name))
+ {
+ as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"),
+ name, symbol_get_obj (sym)->versioned_name,
+ S_GET_NAME (sym));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ *input_line_pointer = c;
}
demand_empty_rest_of_line ();
@@ -1754,6 +1764,24 @@ elf_frob_file ()
#endif
}
+/* It removes any unneeded versioned symbols from the symbol table. */
+
+void
+elf_frob_file_before_adjust ()
+{
+ if (symbol_rootP)
+ {
+ symbolS *symp;
+
+ for (symp = symbol_rootP; symp; symp = symbol_next (symp))
+ if (symbol_get_obj (symp)->versioned_name
+ && !S_IS_DEFINED (symp)
+ && symbol_used_p (symp) == 0
+ && symbol_used_in_reloc_p (symp) == 0)
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ }
+}
+
/* It is required that we let write_relocs have the opportunity to
optimize away fixups before output has begun, since it is possible
to eliminate all fixups for a section and thus we never should
@@ -1958,6 +1986,7 @@ const struct format_ops elf_format_ops =
elf_file_symbol,
elf_frob_symbol,
elf_frob_file,
+ elf_frob_file_before_adjust,
elf_frob_file_after_relocs,
elf_s_get_size, elf_s_set_size,
elf_s_get_align, elf_s_set_align,
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index 70ee61a..37004d7 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -132,6 +132,11 @@ extern asection *gdb_section;
#endif
extern void elf_frob_file PARAMS ((void));
+#ifndef obj_frob_file_before_adjust
+#define obj_frob_file_before_adjust elf_frob_file_before_adjust
+#endif
+extern void elf_frob_file_before_adjust PARAMS ((void));
+
#ifndef obj_frob_file_after_relocs
#define obj_frob_file_after_relocs elf_frob_file_after_relocs
#endif
diff --git a/gas/config/obj-multi.h b/gas/config/obj-multi.h
index 3b80f38..1d68a0c 100644
--- a/gas/config/obj-multi.h
+++ b/gas/config/obj-multi.h
@@ -50,6 +50,11 @@
? (*this_format->frob_file) () \
: (void) 0)
+#define obj_frob_file_before_adjust() \
+ (this_format->frob_file_before_adjust \
+ ? (*this_format->frob_file_before_adjust) () \
+ : (void) 0)
+
#define obj_frob_file_after_relocs() \
(this_format->frob_file_after_relocs \
? (*this_format->frob_file_after_relocs) () \
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index c0d3276..2b73d3d 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -4937,8 +4937,8 @@ For ELF targets, the @code{.symver} directive is used like this:
@smallexample
.symver @var{name}, @var{name2@@nodename}
@end smallexample
-In this case, the symbol @var{name} must exist and be defined within the file
-being assembled. The @code{.versym} directive effectively creates a symbol
+If the symbol @var{name} is defined within the file
+being assembled, the @code{.versym} directive effectively creates a symbol
alias with the name @var{name2@@nodename}, and in fact the main reason that we
just don't try and create a regular alias is that the @var{@@} character isn't
permitted in symbol names. The @var{name2} part of the name is the actual name
@@ -4951,6 +4951,11 @@ the name of a node specified in the version script supplied to the linker when
building a shared library. If you are attempting to override a versioned
symbol from a shared library, then @var{nodename} should correspond to the
nodename of the symbol you are trying to override.
+
+If the symbol @var{name} is not defined within the file being assembled, all
+references to @var{name} will be changed to @var{name2@@nodename}. If no
+reference to @var{name} is made, @var{name2@@nodename} will be removed from the
+symbol table.
@end ifset
@ifset COFF
diff --git a/gas/obj.h b/gas/obj.h
index 71f35e8..4c9759f 100644
--- a/gas/obj.h
+++ b/gas/obj.h
@@ -54,6 +54,7 @@ struct format_ops {
void (*app_file) PARAMS ((const char *));
void (*frob_symbol) PARAMS ((symbolS *, int *));
void (*frob_file) PARAMS ((void));
+ void (*frob_file_before_adjust) PARAMS ((void));
void (*frob_file_after_relocs) PARAMS ((void));
bfd_vma (*s_get_size) PARAMS ((symbolS *));
void (*s_set_size) PARAMS ((symbolS *, bfd_vma));