changes for hp300hpux -- won't be enabled until bfd work is done
[external/binutils.git] / ld / ldindr.c
1
2 /* ldindr.c
3    Handle indirect symbols.
4
5    Copyright (C) 1991 Free Software Foundation, Inc.
6    Written by Steve Chamberlain steve@cygnus.com
7
8    This file is part of GLD, the Gnu Linker.
9
10    GLD is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2, or (at your option)
13    any later version.
14
15    GLD is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with GLD; see the file COPYING.  If not, write to
22    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
23
24 */
25
26 /*
27    An indirect symbol is where a global symbol in one file say's that
28    all refs like it should be turned into refs of the symbol pointed
29    at by the value of the indirect symbol.
30
31    BFD supplies symbols to be indirected with the BFD_INDIRECT bit
32    set. Whenever the linker gets one of these, it calls add_indirect
33    with the symbol. We look up the symbol which this one dereferneces,
34    and stop if they are the same. If they are not the same, copy all
35    the information from the current to the dereffed symbol. Set the
36    indirect bit in the flag. From now on the ldsym_get stuff will
37    perform the indirection for us, at no charge.
38 */
39
40
41
42 #include "bfd.h"
43 #include "sysdep.h"
44 #include "ld.h"
45 #include "ldsym.h"
46 #include "ldmisc.h"
47
48
49
50 static asymbol **
51 DEFUN(move_it,(a_list, b_list),
52 asymbol **a_list AND
53 asymbol **b_list)
54 {
55   asymbol **head = a_list;
56   asymbol **cursor = head;
57
58   if (a_list == 0) return b_list;
59   if (b_list == 0) return a_list;
60
61   while (1) {
62     asymbol *ptr = cursor[0];
63     asymbol **next = (asymbol **)(ptr->udata);
64     if (next == 0) {
65       ptr->udata = (PTR) b_list;
66       return head;
67     }
68     cursor = next;
69   }
70 }
71
72 #if 0
73 void 
74 DEFUN(copy_over,(ldsym, bfdsym),
75    ldsym_type *ldsym AND
76    asymbol **bfdsym)
77 {
78   while (list && *list)
79   {
80     refize(Q_enter_global_ref(list, name);
81     list = (asymbol **)((*list)->udata);
82   }
83 }
84 #endif
85
86 /* This call allows us to change the symbol table so that all future
87    refs to the symbol are patched to know the alias - but we still
88    have to fix all the old ones */
89 void 
90 DEFUN(add_indirect,(ptr),
91 asymbol **ptr)
92 {
93   asymbol **p;
94   ldsym_type *lgs = ldsym_get((*ptr)->name);
95   ldsym_type *new = ldsym_get(((asymbol *)((*ptr)->value))->name);
96
97   /* If the mapping has already been done, stop now */
98   if (lgs == new) return;
99
100   lgs->flags |= SYM_INDIRECT;
101
102   if (lgs->sdefs_chain && lgs->sdefs_chain[0]) 
103   {
104     einfo("indirect symbol already has definition %s",   lgs->sdefs_chain[0]);
105   }
106   new->scoms_chain = move_it(new->scoms_chain, lgs->scoms_chain);
107   lgs->scoms_chain = 0;
108   new->srefs_chain = move_it(new->srefs_chain, lgs->srefs_chain);
109   lgs->srefs_chain = 0;
110   new->sdefs_chain = move_it(new->sdefs_chain, lgs->sdefs_chain);
111   lgs->sdefs_chain = 0;
112
113   /* If the result has any commons they should be turned into refs */
114
115   if (new->sdefs_chain && new->scoms_chain) 
116   {
117     refize(new, new->scoms_chain);
118   }    
119   lgs->sdefs_chain = (asymbol **)new;
120   lgs->srefs_chain = ptr;
121 }
122
123
124