]>
Commit | Line | Data |
---|---|---|
fcf276c4 ILT |
1 | /* Copyright (C) 1991 Free Software Foundation, Inc. |
2 | ||
3 | This file is part of GLD, the Gnu Linker. | |
4 | ||
5 | GLD is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 1, or (at your option) | |
8 | any later version. | |
9 | ||
10 | GLD is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with GLD; see the file COPYING. If not, write to | |
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
18 | ||
19 | /* | |
20 | * By steve chamberlain | |
21 | * [email protected] | |
22 | */ | |
23 | ||
24 | #include "bfd.h" | |
25 | #include "sysdep.h" | |
26 | #include "ld.h" | |
27 | #include "ldexp.h" | |
28 | #include "ldlang.h" | |
29 | #include "ldsym.h" | |
30 | #include "ldmisc.h" | |
31 | #include "ldgram.h" | |
32 | ||
33 | /* exported list of statements needed to handle constructors */ | |
34 | lang_statement_list_type constructor_list; | |
35 | ||
36 | ||
37 | ||
38 | typedef struct constructor_list | |
39 | { | |
40 | CONST char *name; | |
41 | struct constructor_list *next; | |
42 | } constructor_list_type; | |
43 | ||
44 | static constructor_list_type *constructor_name_list; | |
45 | ||
46 | static void | |
47 | add_constructor_name (name) | |
48 | CONST char *name; | |
49 | { | |
50 | register constructor_list_type *ptr = constructor_name_list; | |
51 | for (; ptr != (constructor_list_type *)NULL; ptr = ptr->next) { | |
52 | if (strcmp (ptr->name, name) == 0) | |
53 | return; | |
54 | } | |
55 | ||
56 | /* There isn't an entry, so add one */ | |
57 | ptr = (constructor_list_type *) ldmalloc (sizeof(constructor_list_type)); | |
58 | ptr->next = constructor_name_list; | |
59 | ptr->name = name; | |
60 | constructor_name_list = ptr; | |
61 | } | |
62 | ||
63 | void | |
64 | ldlang_add_constructor (name) | |
65 | ldsym_type *name; | |
66 | { | |
67 | if (name->flags & SYM_CONSTRUCTOR) return; | |
68 | add_constructor_name (name->name); | |
69 | name->flags |= SYM_CONSTRUCTOR; | |
70 | } | |
71 | ||
72 | ||
73 | /* this function looks through the sections attached to the supplied | |
74 | bfd to see if any of them are magical constructor sections. If so | |
75 | their names are remembered and added to the list of constructors */ | |
76 | ||
77 | void | |
78 | ldlang_check_for_constructors (entry) | |
79 | struct lang_input_statement_struct *entry; | |
80 | { | |
81 | asection *section; | |
82 | ||
83 | for (section = entry->the_bfd->sections; | |
84 | section != (asection *)NULL; | |
85 | section = section->next) | |
86 | { | |
87 | if (section->flags & SEC_CONSTRUCTOR) | |
88 | add_constructor_name (section->name); | |
89 | } | |
90 | } | |
91 | ||
92 | ||
93 | /* run through the symbol table, find all the symbols which are | |
94 | constructors and for each one, create statements to do something | |
95 | like.. | |
96 | ||
97 | for something like "__CTOR_LIST__, foo" in the assembler | |
98 | ||
99 | __CTOR_LIST__ = . ; | |
100 | LONG(__CTOR_LIST_END - . / 4 - 2) | |
101 | *(foo) | |
102 | __CTOR_LIST_END= . | |
103 | ||
104 | Put these statements onto a special list. | |
105 | ||
106 | */ | |
107 | ||
108 | ||
109 | void | |
110 | find_constructors () | |
111 | { | |
112 | lang_statement_list_type *old = stat_ptr; | |
113 | constructor_list_type *p = constructor_name_list; | |
114 | stat_ptr = & constructor_list; | |
115 | lang_list_init(stat_ptr); | |
116 | while (p != (constructor_list_type *)NULL) | |
117 | { | |
118 | /* Have we already done this one ? */ | |
119 | CONST char *name = p->name; | |
120 | ldsym_type *lookup = ldsym_get_soft(name); | |
121 | ||
122 | /* If ld is invoked from collect, then the constructor list | |
123 | will already have been defined, so don't do it again. */ | |
124 | ||
125 | if (lookup->sdefs_chain == (asymbol **)NULL) | |
126 | { | |
127 | size_t len = strlen(name); | |
128 | char *end = ldmalloc(len+3); | |
129 | strcpy(end, name); | |
130 | strcat(end,"$e"); | |
131 | ||
132 | lang_add_assignment | |
133 | ( exp_assop('=',name, exp_nameop(NAME,"."))); | |
134 | ||
135 | lang_add_data | |
136 | (LONG, exp_binop('-', | |
137 | exp_binop ( '/', | |
138 | exp_binop ( '-', | |
139 | exp_nameop(NAME, end), | |
140 | exp_nameop(NAME,".")), | |
141 | exp_intop(4)), | |
142 | ||
143 | exp_intop(2))); | |
144 | ||
145 | ||
146 | lang_add_wild(name, (char *)NULL); | |
147 | lang_add_data(LONG, exp_intop(0)); | |
148 | lang_add_assignment | |
149 | (exp_assop('=', end, exp_nameop(NAME,"."))); | |
150 | } | |
151 | p = p->next; | |
152 | } | |
153 | stat_ptr = old; | |
154 | } | |
155 |