diff options
-rw-r--r-- | ld/ldindr.c | 58 | ||||
-rw-r--r-- | ld/ldindr.h | 4 | ||||
-rw-r--r-- | ld/ldwarn.c | 72 |
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); + } +} |