aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ldindr.c58
-rw-r--r--ld/ldindr.h4
-rw-r--r--ld/ldwarn.c72
3 files changed, 134 insertions, 0 deletions
diff --git a/ld/ldindr.c b/ld/ldindr.c
new file mode 100644
index 0000000..8e19842
--- /dev/null
+++ b/ld/ldindr.c
@@ -0,0 +1,58 @@
+/* ldindr.c
+ Handle indirect symbols.
+
+ BFD supplies symbols to be indirected with the BFD_INDIRECT bit
+ set. Whenever the linker gets one of these, it calls add_indirect
+ with the symbol. We create an entry into the ldsym hash table as if it
+ were a normal symbol, but with the SYM_INDIRECT bit set in the
+ flags.
+
+ When it comes time to tie up the symbols at a later date, the flag
+ will be seen and a call made to do the right thing (tm)
+
+*/
+
+
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "ld.h"
+#include "ldsym.h"
+
+extern ld_config_type config;
+void
+DEFUN(add_indirect,(ptr),
+asymbol **ptr)
+{
+ if (config.relocateable_output == false) {
+ ldsym_type *sp = ldsym_get((*ptr)->name);
+ sp->flags |= SYM_INDIRECT;
+ sp->sdefs_chain = ptr;
+ }
+}
+
+
+
+void
+DEFUN(do_indirect,(ptr),
+ldsym_type *ptr)
+{
+if (config.relocateable_output == false) {
+ /* Dig out the symbol were indirecting to. It's held in the value
+ field.
+ */
+
+
+ CONST char *name = ((asymbol *)(*(ptr->sdefs_chain))->value)->name;
+
+ ldsym_type *new = ldsym_get(name);
+
+ /* We have to make a copy of the sdefs_chain item name, since
+ symbols will be clobbered on writing, and we want to write the
+ same string twice */
+
+
+ ptr->sdefs_chain[0][0] = new->sdefs_chain[0][0];
+ ptr->sdefs_chain[0][0].name = name;
+}
+}
diff --git a/ld/ldindr.h b/ld/ldindr.h
new file mode 100644
index 0000000..209c8cf
--- /dev/null
+++ b/ld/ldindr.h
@@ -0,0 +1,4 @@
+
+
+void EXFUN(do_indirect, (ldsym_type *));
+void EXFUN(add_indirect,(asymbol *));
diff --git a/ld/ldwarn.c b/ld/ldwarn.c
new file mode 100644
index 0000000..c22f36b
--- /dev/null
+++ b/ld/ldwarn.c
@@ -0,0 +1,72 @@
+#include "sysdep.h"
+#include "bfd.h"
+#include "ldsym.h"
+
+
+/* we keep all the warning symbols in a list, if we ever get a
+ warning, we'll search it the hard way. This won't be to bad since
+ warnings are infrequent, and never that many (true or false ?).
+
+*/
+
+typedef struct warning_list_struct {
+ struct warning_list_struct *next;
+ asymbol *sym;
+} warning_list_type;
+
+
+static warning_list_type *warning_list;
+
+
+
+/* This is a warning symbol, add the error text to a list we keep, and mark
+ the symbol referenced as requiring a warning */
+
+
+void
+DEFUN(add_warning,(sym),
+ asymbol *sym)
+{
+ CONST char *name = ((asymbol *)(sym->value))->name;
+ warning_list_type *new;
+
+ ldsym_type *lookup = ldsym_get(name);
+
+ lookup->flags |= SYM_WARNING;
+
+ new = (warning_list_type *)ldmalloc(sizeof(warning_list_type));
+ new->next = warning_list;
+ new->sym = sym;
+ warning_list = new;
+}
+
+/* run through the list we kept, and find the warning associated with
+ this symbol */
+CONST char *
+DEFUN(fetch_warning,(sym),
+asymbol *sym)
+{
+ warning_list_type *ptr = warning_list;
+ while (ptr != (warning_list_type *)NULL) {
+ if (strcmp(((asymbol*)(ptr->sym->value))->name, sym->name) == 0) {
+ return ptr->sym->name;
+ }
+ ptr = ptr->next;
+ }
+ return "This is a warning without a message !";
+}
+
+
+void
+DEFUN(produce_warnings,(lgs,it),
+ ldsym_type *lgs AND
+ asymbol *it)
+{
+ asymbol **ptr;
+ ptr = lgs->srefs_chain;
+ while (ptr != (asymbol **)NULL) {
+ asymbol *ref = *ptr;
+ info("%B: %s\n", ref->the_bfd, fetch_warning(it));
+ ptr = (asymbol **)(ref->udata);
+ }
+}