aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog21
-rw-r--r--ld/ldsym.c111
-rw-r--r--ld/ldsym.h5
3 files changed, 134 insertions, 3 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index c9cc7f4..b81016d 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,24 @@
+Fri Sep 25 13:49:52 1992 Ken Raeburn (raeburn@kyriath.cygnus.com)
+
+ * Makefile.in (ldexp.o, ldctor.o, ldlang.o, ldmain.o, ldwrite.o,
+ lexsup.o, mri.o, relax.o): Indicate dependence on ldgram.h.
+
+ * ld.h (strip_symbols_type): Add value STRIP_SOME.
+ * ldgram.y (OPTION_RETAIN_SYMBOLS_FILE): New terminal token.
+ (lang_add_keepsyms_file): New function.
+ * ldlex.l: Handle "-retain-symbols-file".
+ * ldsym.c (keepsyms_file, kept_syms): New vars.
+ (process_keepsyms): New functihon; reads file, marks symbols for
+ saving.
+ (write_file_locals): File symbols should always be kept.
+ (ldsym_write): Warn about "-retain-symbols-file" overriding "-S"
+ and "-s". Process retain-symbols file before setting symtab.
+ * ldsym.h (SYM_KEEP): New flag for ldsym_type flags.
+ (keepsyms_file, kept_syms): Declare them.
+
+ * ldmain.c (main): Non-fatal errors should still cause non-zero
+ exit status even with -r.
+
Fri Sep 25 11:08:01 1992 Steve Chamberlain (sac@thepub.cygnus.com)
Added initial support for the z8k
diff --git a/ld/ldsym.c b/ld/ldsym.c
index 22a24d9..587c92e 100644
--- a/ld/ldsym.c
+++ b/ld/ldsym.c
@@ -65,6 +65,8 @@ extern discard_locals_type discard_locals;
ldsym_type *symbol_head = (ldsym_type *)NULL;
ldsym_type **symbol_tail_ptr = &symbol_head;
+CONST char *keepsyms_file;
+int kept_syms;
extern ld_config_type config;
@@ -185,9 +187,103 @@ DEFUN(ldsym_get_soft,(key),
return search(key, hashval);
}
+static asymbol **
+process_keepsyms (table, size)
+ asymbol ** table;
+ int size;
+{
+ struct obstack obstack;
+ char *start_of_obstack;
+ FILE *ks_file = 0;
+ asymbol **out = table;
+ asymbol **end = table + size;
+ asymbol **sym;
+
+ if (!keepsyms_file || size == 0)
+ return end;
+ obstack_init (&obstack);
+ obstack_alloc (&obstack, 1);
+ obstack_finish (&obstack);
+ start_of_obstack = obstack_alloc (&obstack, 1);
+ ks_file = fopen (keepsyms_file, "r");
+ if (!ks_file)
+ {
+ info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file);
+ goto egress;
+ }
+ errno = 0;
+#define KEEP(S) \
+ do { asymbol **p=(S), *tmp=*out; *out=*p; *p=tmp; out++; } while (0)
+ while (!feof (ks_file) && !ferror (ks_file))
+ {
+ int c;
+ char *ptr;
+ int found = 0;
+ obstack_free (&obstack, start_of_obstack);
+ do
+ {
+ c = getc (ks_file);
+ if (c == '\n')
+ c = 0;
+ obstack_1grow (&obstack, c);
+ }
+ while (c > 0);
+ if (c == EOF)
+ {
+ if (!feof (ks_file))
+ /* error occurred */
+ {
+ info ("%X%P: error reading keep-symbols file `%s': %E\n",
+ keepsyms_file);
+ out = end;
+ goto egress;
+ }
+ if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
+ /* eof in middle of symbol */
+ {
+ info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
+ keepsyms_file);
+ out = end;
+ goto egress;
+ }
+ /* All okay -- no incomplete lines, EOF reached. */
+ break;
+ }
+ ptr = obstack_next_free (&obstack) - 2;
+ /* discard trailing trash */
+ while (*ptr == ' '
+ || *ptr == '\t')
+ *ptr-- = 0;
+ ptr = obstack_base (&obstack);
+ for (sym = out; sym < end; sym++)
+ if (!strcmp ((*sym)->name, ptr))
+ {
+ KEEP (sym);
+ found = 1;
+ }
+ if (!found)
+ info ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
+ }
+ /* It'd be slightly faster to move this pass above the previous one,
+ but that'd mean any symbols preserved in this pass would generate
+ warnings if they were also listed in the keepsyms file. */
+ for (sym = out; sym < end; sym++)
+ {
+ asymbol *s = *sym;
+ if (s->section == &bfd_und_section
+ || s->section == &bfd_com_section
+ || s->flags & BSF_KEEP_G)
+ KEEP (sym);
+ }
+ egress:
+ obstack_free (&obstack, start_of_obstack);
+ if (ks_file)
+ fclose (ks_file);
+ return out;
+}
static void
list_file_locals (entry)
@@ -348,7 +444,11 @@ asymbol **output_buffer;
/* The value is the start of this section in the output file*/
newsym->value = 0;
- newsym->flags = BSF_LOCAL;
+ /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as
+ "used by the linker" and I can't find any other code that
+ uses it. Should be a cleaner way of doing this (like an
+ "application flags" field in the symbol structure?). */
+ newsym->flags = BSF_LOCAL | BSF_KEEP_G;
newsym->section = s;
*output_buffer++ = newsym;
break;
@@ -462,11 +562,15 @@ asymbol **symbol_table;
return symbol_table;
}
-
-
void
ldsym_write()
{
+ if (keepsyms_file != 0
+ && strip_symbols != STRIP_SOME)
+ {
+ info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n");
+ strip_symbols = STRIP_SOME;
+ }
if (strip_symbols != STRIP_ALL) {
/* We know the maximum size of the symbol table -
it's the size of all the global symbols ever seen +
@@ -484,6 +588,7 @@ ldsym_write()
asymbol ** tablep = write_file_locals(symbol_table);
tablep = write_file_globals(tablep);
+ tablep = process_keepsyms (symbol_table, tablep - symbol_table);
*tablep = (asymbol *)NULL;
bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
diff --git a/ld/ldsym.h b/ld/ldsym.h
index 90ba007..fdd24da 100644
--- a/ld/ldsym.h
+++ b/ld/ldsym.h
@@ -53,9 +53,14 @@ typedef struct user_symbol_struct
#define SYM_WARNING 2
/* IF this is an alias for another symbol */
#define SYM_INDIRECT 4
+ /* If this symbol explicitly should be kept, despite discarding
+ most others. */
+#define SYM_KEEP 8
int flags;
} ldsym_type;
+extern CONST char *keepsyms_file;
+extern int kept_syms;
PROTO(ldsym_type *, ldsym_get, (CONST char *));
PROTO(ldsym_type *, ldsym_get_soft, (CONST char *));