]>
Commit | Line | Data |
---|---|---|
2fa0b342 DHW |
1 | /* Copyright (C) 1991 Free Software Foundation, Inc. |
2 | ||
3 | This file is part of GLD, the Gnu Linker. | |
4 | ||
2e2bf962 | 5 | This program is free software; you can redistribute it and/or modify |
2fa0b342 | 6 | it under the terms of the GNU General Public License as published by |
2e2bf962 SC |
7 | the Free Software Foundation; either version 2 of the License, or |
8 | (at your option) any later version. | |
2fa0b342 | 9 | |
2e2bf962 | 10 | This program is distributed in the hope that it will be useful, |
2fa0b342 DHW |
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 | |
2e2bf962 SC |
16 | along with this program; if not, write to the Free Software |
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
2fa0b342 DHW |
18 | |
19 | /* | |
20 | * $Id$ | |
2fa0b342 DHW |
21 | */ |
22 | ||
23 | /* | |
24 | This module writes out the final image by reading sections from the | |
25 | input files, relocating them and writing them out | |
26 | ||
27 | There are two main paths through this module, one for normal | |
28 | operation and one for partial linking. | |
29 | ||
30 | During normal operation, raw section data is read along with the | |
31 | associated relocation information, the relocation info applied and | |
32 | the section data written out on a section by section basis. | |
33 | ||
34 | When partially linking, all the relocation records are read to work | |
35 | out how big the output relocation vector will be. Then raw data is | |
36 | read, relocated and written section by section. | |
37 | ||
38 | Written by Steve Chamberlain [email protected] | |
39 | ||
40 | */ | |
41 | ||
42 | ||
2fa0b342 | 43 | #include "bfd.h" |
2e2bf962 | 44 | #include "sysdep.h" |
2fa0b342 DHW |
45 | |
46 | #include "ldlang.h" | |
47 | #include "ld.h" | |
48 | #include "ldwrite.h" | |
49 | #include "ldmisc.h" | |
50 | #include "ldsym.h" | |
2e2bf962 SC |
51 | #include "ldgram.h" |
52 | ||
2fa0b342 DHW |
53 | |
54 | ||
55 | ||
2fa0b342 DHW |
56 | /* Static vars for do_warnings and subroutines of it */ |
57 | int list_unresolved_refs; /* List unresolved refs */ | |
58 | int list_warning_symbols; /* List warning syms */ | |
59 | int list_multiple_defs; /* List multiple definitions */ | |
60 | extern int errno; | |
61 | extern char *sys_errlist[]; | |
62 | ||
63 | extern unsigned int undefined_global_sym_count; | |
64 | ||
65 | extern bfd *output_bfd; | |
66 | ||
67 | extern struct lang_output_section_statement_struct * create_object_symbols; | |
68 | ||
69 | extern char lprefix; | |
70 | ||
71 | #ifdef __STDC__ | |
72 | void lang_for_each_statement(void (*func)()); | |
73 | #else /* __STDC__ */ | |
74 | void lang_for_each_statement(); | |
75 | #endif /* __STDC__ */ | |
76 | ||
2e2bf962 | 77 | extern bfd_size_type largest_section; |
2fa0b342 DHW |
78 | ld_config_type config; |
79 | ||
80 | extern unsigned int global_symbol_count; | |
81 | ||
82 | boolean trace_files; | |
83 | ||
2e2bf962 SC |
84 | static void |
85 | DEFUN(perform_relocation,(input_bfd, | |
86 | input_section, | |
87 | data, | |
88 | symbols), | |
89 | bfd *input_bfd AND | |
90 | asection *input_section AND | |
91 | PTR data AND | |
92 | asymbol **symbols) | |
2fa0b342 DHW |
93 | { |
94 | static asymbol *error_symbol = (asymbol *)NULL; | |
95 | static unsigned int error_count = 0; | |
96 | #define MAX_ERRORS_IN_A_ROW 5 | |
2e2bf962 | 97 | bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section); |
2fa0b342 DHW |
98 | |
99 | arelent **reloc_vector = (arelent **)ldmalloc(reloc_size); | |
100 | arelent **parent; | |
101 | bfd *ob = output_bfd; | |
102 | asection *os = input_section->output_section; | |
103 | if (config.relocateable_output == false) ob = (bfd *)NULL; | |
104 | ||
2e2bf962 SC |
105 | input_section->_cooked_size = input_section->_raw_size; |
106 | input_section->reloc_done = 1; | |
107 | ||
2fa0b342 DHW |
108 | if (bfd_canonicalize_reloc(input_bfd, |
109 | input_section, | |
110 | reloc_vector, | |
111 | symbols) ) | |
112 | { | |
113 | for (parent = reloc_vector; *parent; parent++) | |
114 | { | |
115 | ||
2e2bf962 | 116 | bfd_reloc_status_type r= |
2fa0b342 DHW |
117 | bfd_perform_relocation(input_bfd, |
118 | *parent, | |
119 | data, | |
120 | input_section, | |
121 | ob); | |
122 | ||
123 | if (r == bfd_reloc_ok) { | |
124 | if (ob != (bfd *)NULL) { | |
125 | /* A parital link, so keep the relocs */ | |
2e2bf962 SC |
126 | |
127 | /* Add to each relocation the offset of where it lives | |
128 | in the output section */ | |
129 | /* (*parent)->address += input_section->output_offset;*/ | |
130 | ||
2fa0b342 DHW |
131 | os->orelocation[os->reloc_count] = *parent; |
132 | os->reloc_count++; | |
133 | } | |
134 | } | |
135 | else | |
136 | { | |
137 | asymbol *s; | |
138 | arelent *p = *parent; | |
139 | ||
140 | if (ob != (bfd *)NULL) { | |
141 | /* A parital link, so keep the relocs */ | |
142 | os->orelocation[os->reloc_count] = *parent; | |
143 | os->reloc_count++; | |
144 | } | |
145 | ||
146 | if (p->sym_ptr_ptr != (asymbol **)NULL) { | |
147 | s = *(p->sym_ptr_ptr); | |
148 | } | |
149 | else { | |
150 | s = (asymbol *)NULL; | |
151 | } | |
152 | switch (r) | |
153 | { | |
154 | case bfd_reloc_undefined: | |
155 | /* We remember the symbol, and never print more than | |
156 | a reasonable number of them in a row */ | |
157 | if (s == error_symbol) { | |
158 | error_count++; | |
159 | } | |
160 | else { | |
161 | error_count = 0; | |
162 | error_symbol = s; | |
163 | } | |
164 | if (error_count < MAX_ERRORS_IN_A_ROW) { | |
2e2bf962 SC |
165 | einfo("%C: undefined reference to `%T'\n", |
166 | input_bfd, input_section, symbols, | |
167 | (*parent)->address, s); | |
2fa0b342 DHW |
168 | config.make_executable = false; |
169 | } | |
170 | else if (error_count == MAX_ERRORS_IN_A_ROW) { | |
2e2bf962 SC |
171 | einfo("%C: more undefined references to `%T' follow\n", |
172 | input_bfd, input_section, | |
173 | symbols, (*parent)->address, s); | |
2fa0b342 DHW |
174 | } |
175 | else { | |
176 | /* Don't print any more */ | |
177 | } | |
178 | break; | |
179 | case bfd_reloc_dangerous: | |
2e2bf962 SC |
180 | einfo("%B: relocation may be wrong `%T'\n", |
181 | input_bfd, s); | |
2fa0b342 DHW |
182 | break; |
183 | case bfd_reloc_outofrange: | |
2e2bf962 SC |
184 | einfo("%B:%s relocation address out of range %T (%V)\n", |
185 | input_bfd, input_section->name, s, p->address); | |
2fa0b342 DHW |
186 | break; |
187 | case bfd_reloc_overflow: | |
2e2bf962 SC |
188 | einfo("%B:%s relocation overflow in %T reloc type %d\n", |
189 | input_bfd, input_section->name, s, p->howto->type); | |
2fa0b342 DHW |
190 | break; |
191 | default: | |
2e2bf962 SC |
192 | einfo("%F%B: relocation error, symbol `%T'\n", |
193 | input_bfd, s); | |
2fa0b342 DHW |
194 | break; |
195 | } | |
196 | } | |
197 | } | |
198 | } | |
199 | free((char *)reloc_vector); | |
200 | } | |
201 | ||
202 | ||
203 | ||
204 | ||
205 | ||
206 | ||
99fe4553 | 207 | PTR data_area; |
2fa0b342 DHW |
208 | |
209 | static void | |
2e2bf962 SC |
210 | DEFUN(copy_and_relocate,(statement), |
211 | lang_statement_union_type *statement) | |
2fa0b342 DHW |
212 | { |
213 | switch (statement->header.type) { | |
214 | case lang_fill_statement_enum: | |
1418c83b | 215 | { |
2fa0b342 | 216 | #if 0 |
99fe4553 SC |
217 | bfd_byte play_area[SHORT_SIZE]; |
218 | unsigned int i; | |
219 | bfd_putshort(output_bfd, statement->fill_statement.fill, play_area); | |
220 | /* Write out all entire shorts */ | |
221 | for (i = 0; | |
222 | i < statement->fill_statement.size - SHORT_SIZE + 1; | |
223 | i+= SHORT_SIZE) | |
224 | { | |
225 | bfd_set_section_contents(output_bfd, | |
226 | statement->fill_statement.output_section, | |
227 | play_area, | |
228 | statement->data_statement.output_offset +i, | |
229 | SHORT_SIZE); | |
2fa0b342 | 230 | |
99fe4553 | 231 | } |
2fa0b342 | 232 | |
99fe4553 SC |
233 | /* Now write any remaining byte */ |
234 | if (i < statement->fill_statement.size) | |
235 | { | |
236 | bfd_set_section_contents(output_bfd, | |
237 | statement->fill_statement.output_section, | |
238 | play_area, | |
239 | statement->data_statement.output_offset +i, | |
240 | 1); | |
2fa0b342 | 241 | |
99fe4553 | 242 | } |
2fa0b342 | 243 | #endif |
99fe4553 | 244 | } |
2fa0b342 DHW |
245 | break; |
246 | case lang_data_statement_enum: | |
99fe4553 SC |
247 | { |
248 | bfd_vma value = statement->data_statement.value; | |
249 | bfd_byte play_area[LONG_SIZE]; | |
2e2bf962 | 250 | unsigned int size = 0; |
99fe4553 SC |
251 | switch (statement->data_statement.type) { |
252 | case LONG: | |
2e2bf962 | 253 | bfd_put_32(output_bfd, value, play_area); |
99fe4553 SC |
254 | size = LONG_SIZE; |
255 | break; | |
256 | case SHORT: | |
2e2bf962 | 257 | bfd_put_16(output_bfd, value, play_area); |
99fe4553 SC |
258 | size = SHORT_SIZE; |
259 | break; | |
260 | case BYTE: | |
2e2bf962 | 261 | bfd_put_8(output_bfd, value, play_area); |
99fe4553 SC |
262 | size = BYTE_SIZE; |
263 | break; | |
264 | } | |
2fa0b342 | 265 | |
99fe4553 SC |
266 | bfd_set_section_contents(output_bfd, |
267 | statement->data_statement.output_section, | |
268 | play_area, | |
269 | statement->data_statement.output_vma, | |
270 | size); | |
2fa0b342 DHW |
271 | |
272 | ||
273 | ||
274 | ||
99fe4553 | 275 | } |
2fa0b342 DHW |
276 | break; |
277 | case lang_input_section_enum: | |
1418c83b SC |
278 | { |
279 | ||
280 | asection *i = statement->input_section.section; | |
281 | asection *output_section = i->output_section; | |
282 | lang_input_statement_type *ifile = | |
283 | statement->input_section.ifile; | |
284 | if (ifile->just_syms_flag == false) { | |
285 | bfd *inbfd = ifile->the_bfd; | |
286 | ||
2e2bf962 SC |
287 | if (output_section->flags & SEC_LOAD && |
288 | output_section->flags & SEC_ALLOC | |
289 | && bfd_get_section_size_before_reloc(i) != 0) | |
1418c83b SC |
290 | { |
291 | if(bfd_get_section_contents(inbfd, | |
292 | i, | |
293 | data_area, | |
2e2bf962 SC |
294 | (file_ptr)0, |
295 | bfd_get_section_size_before_reloc(i)) == false) | |
1418c83b | 296 | { |
2e2bf962 | 297 | einfo("%F%B error reading section contents %E\n", inbfd); |
1418c83b | 298 | } |
2e2bf962 | 299 | /* Set the reloc bit */ |
1418c83b SC |
300 | perform_relocation (inbfd, i, data_area, ifile->asymbols); |
301 | ||
302 | ||
303 | if(bfd_set_section_contents(output_bfd, | |
304 | output_section, | |
305 | data_area, | |
306 | (file_ptr)i->output_offset, | |
2e2bf962 | 307 | bfd_get_section_size_after_reloc(i)) == false) |
1418c83b | 308 | { |
2e2bf962 SC |
309 | einfo("%F%B error writing section contents of %E\n", |
310 | output_bfd); | |
1418c83b | 311 | } |
2fa0b342 | 312 | |
1418c83b | 313 | } |
2fa0b342 | 314 | } |
1418c83b SC |
315 | |
316 | } | |
2fa0b342 DHW |
317 | break; |
318 | ||
1418c83b | 319 | default: |
2fa0b342 DHW |
320 | /* All the other ones fall through */ |
321 | ; | |
322 | ||
323 | } | |
324 | } | |
325 | ||
326 | void | |
2e2bf962 | 327 | DEFUN_VOID(write_norel) |
2fa0b342 DHW |
328 | { |
329 | /* Output the text and data segments, relocating as we go. */ | |
330 | lang_for_each_statement(copy_and_relocate); | |
331 | } | |
332 | ||
333 | ||
2e2bf962 SC |
334 | static void |
335 | DEFUN(read_relocs,(abfd, section, symbols), | |
336 | bfd *abfd AND | |
337 | asection *section AND | |
338 | asymbol **symbols) | |
2fa0b342 DHW |
339 | { |
340 | /* Work out the output section ascociated with this input section */ | |
341 | asection *output_section = section->output_section; | |
342 | ||
2e2bf962 | 343 | bfd_size_type reloc_size = bfd_get_reloc_upper_bound(abfd, section); |
2fa0b342 DHW |
344 | arelent **reloc_vector = (arelent **)ldmalloc(reloc_size); |
345 | ||
346 | if (bfd_canonicalize_reloc(abfd, | |
347 | section, | |
348 | reloc_vector, | |
349 | symbols)) { | |
350 | output_section->reloc_count += section->reloc_count; | |
351 | } | |
352 | } | |
353 | ||
354 | ||
2e2bf962 SC |
355 | static void |
356 | DEFUN_VOID(write_rel) | |
2fa0b342 DHW |
357 | { |
358 | /* | |
359 | Run through each section of each file and work work out the total | |
360 | number of relocation records which will finally be in each output | |
361 | section | |
362 | */ | |
363 | ||
364 | LANG_FOR_EACH_INPUT_SECTION | |
365 | (statement, abfd, section, | |
366 | (read_relocs(abfd, section, statement->asymbols))); | |
367 | ||
368 | ||
369 | ||
370 | /* | |
371 | Now run though all the output sections and allocate the space for | |
372 | all the relocations | |
373 | */ | |
374 | LANG_FOR_EACH_OUTPUT_SECTION | |
375 | (section, | |
376 | (section->orelocation = | |
2e2bf962 | 377 | (arelent **)ldmalloc((bfd_size_type)(sizeof(arelent **)* |
2fa0b342 DHW |
378 | section->reloc_count)), |
379 | section->reloc_count = 0, | |
380 | section->flags |= SEC_HAS_CONTENTS)); | |
381 | ||
382 | ||
383 | /* | |
384 | Copy the data, relocating as we go | |
385 | */ | |
386 | lang_for_each_statement(copy_and_relocate); | |
387 | } | |
388 | ||
389 | void | |
ac593907 | 390 | DEFUN_VOID(ldwrite) |
2fa0b342 | 391 | { |
99fe4553 | 392 | data_area = (PTR) ldmalloc(largest_section); |
2fa0b342 | 393 | if (config.relocateable_output == true) |
2e2bf962 SC |
394 | { |
395 | write_rel(); | |
396 | } | |
2fa0b342 | 397 | else |
2e2bf962 SC |
398 | { |
399 | write_relaxnorel(output_bfd); | |
400 | } | |
2fa0b342 DHW |
401 | free(data_area); |
402 | /* Output the symbol table (both globals and locals). */ | |
2e2bf962 SC |
403 | |
404 | /* Print a map, if requested. */ | |
405 | ||
ac593907 | 406 | if (config.map_file) { |
2e2bf962 | 407 | ldsym_print_symbol_table (); |
ac593907 | 408 | lang_map(); |
2e2bf962 SC |
409 | } |
410 | ||
2fa0b342 DHW |
411 | ldsym_write (); |
412 | ||
413 | } | |
414 |