aboutsummaryrefslogtreecommitdiff
path: root/ld/ldindr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldindr.c')
-rw-r--r--ld/ldindr.c73
1 files changed, 41 insertions, 32 deletions
diff --git a/ld/ldindr.c b/ld/ldindr.c
index 8e19842..7770e8d 100644
--- a/ld/ldindr.c
+++ b/ld/ldindr.c
@@ -3,13 +3,11 @@
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)
-
+ with the symbol. We look up the symbol which this one dereferneces,
+ and stop if they are the same. If they are not the same, copy all
+ the information from the current to the dereffed symbol. Set the
+ indirect bit in the flag. From now on the ldsym_get stuff will
+ perform the indirection for us, at no charge.
*/
@@ -18,41 +16,52 @@
#include "bfd.h"
#include "ld.h"
#include "ldsym.h"
+#include "ldmisc.h"
-extern ld_config_type config;
-void
-DEFUN(add_indirect,(ptr),
-asymbol **ptr)
+
+
+static asymbol **
+DEFUN(move_it,(a_list, b_list),
+asymbol **a_list AND
+asymbol **b_list)
{
- if (config.relocateable_output == false) {
- ldsym_type *sp = ldsym_get((*ptr)->name);
- sp->flags |= SYM_INDIRECT;
- sp->sdefs_chain = ptr;
+ asymbol **head = a_list;
+ asymbol **cursor = head;
+
+ if (a_list == 0) return b_list;
+ if (b_list == 0) return a_list;
+
+ while (1) {
+ asymbol *ptr = cursor[0];
+ asymbol **next = (asymbol **)(ptr->udata);
+ if (next == 0) {
+ ptr->udata = (PTR) b_list;
+ return head;
+ }
+ cursor = next;
}
}
-
-
void
-DEFUN(do_indirect,(ptr),
-ldsym_type *ptr)
+DEFUN(add_indirect,(ptr),
+asymbol **ptr)
{
-if (config.relocateable_output == false) {
- /* Dig out the symbol were indirecting to. It's held in the value
- field.
- */
+ ldsym_type *lgs = ldsym_get((*ptr)->name);
+ ldsym_type *new = ldsym_get(((asymbol *)((*ptr)->value))->name);
+ /* If the mapping has already been done, stop now */
+ if (lgs == new) return;
+ lgs->flags |= SYM_INDIRECT;
- CONST char *name = ((asymbol *)(*(ptr->sdefs_chain))->value)->name;
+ new->scoms_chain = move_it(new->scoms_chain, lgs->scoms_chain);
+ lgs->scoms_chain = 0;
+ new->srefs_chain = move_it(new->srefs_chain, lgs->srefs_chain);
+ lgs->srefs_chain = 0;
+ new->sdefs_chain = move_it(new->sdefs_chain, lgs->sdefs_chain);
+ lgs->sdefs_chain = 0;
- ldsym_type *new = ldsym_get(name);
+ lgs->sdefs_chain = (asymbol **)new;
+}
- /* 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;
-}
-}