1 /* Copyright (C) 1991 Free Software Foundation, Inc.
3 This file is part of GLD, the Gnu Linker.
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)
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.
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. */
23 * Revision 1.5 1991/04/14 03:22:42 steve
24 * checkpoint before a merge
26 * Revision 1.4 1991/03/22 23:02:40 steve
27 * Brought up to sync with Intel again.
29 * Revision 1.2 1991/03/15 18:45:55 rich
32 * Revision 1.1 1991/03/13 00:48:37 chrisb
35 * Revision 1.7 1991/03/10 19:15:03 sac
36 * Took out the abort() which had been put in the wrong place
37 * Updated the version #.
39 * Revision 1.6 1991/03/10 09:31:41 rich
41 * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
42 * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
43 * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
44 * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
45 * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
47 * As of this round of changes, ld now builds on all hosts of (Intel960)
48 * interest and copy passes my copy test on big endian hosts again.
50 * Revision 1.5 1991/03/09 03:25:08 sac
51 * Added support for LONG, SHORT and BYTE keywords in scripts
53 * Revision 1.4 1991/03/06 21:59:34 sac
54 * Completed G++ support
56 * Revision 1.3 1991/03/06 02:29:52 sac
57 * Added support for partial linking.
59 * Revision 1.2 1991/02/22 17:15:11 sac
60 * Added RCS keywords and copyrights
65 This module writes out the final image by reading sections from the
66 input files, relocating them and writing them out
68 There are two main paths through this module, one for normal
69 operation and one for partial linking.
71 During normal operation, raw section data is read along with the
72 associated relocation information, the relocation info applied and
73 the section data written out on a section by section basis.
75 When partially linking, all the relocation records are read to work
76 out how big the output relocation vector will be. Then raw data is
77 read, relocated and written section by section.
79 Written by Steve Chamberlain steve@cygnus.com
92 #include "ldgram.tab.h"
97 /* Static vars for do_warnings and subroutines of it */
98 int list_unresolved_refs; /* List unresolved refs */
99 int list_warning_symbols; /* List warning syms */
100 int list_multiple_defs; /* List multiple definitions */
102 extern char *sys_errlist[];
104 extern unsigned int undefined_global_sym_count;
106 extern bfd *output_bfd;
108 extern struct lang_output_section_statement_struct * create_object_symbols;
113 void lang_for_each_statement(void (*func)());
115 void lang_for_each_statement();
116 #endif /* __STDC__ */
118 extern size_t largest_section;
119 ld_config_type config;
121 extern unsigned int global_symbol_count;
125 static void perform_relocation(input_bfd,
130 asection *input_section;
134 static asymbol *error_symbol = (asymbol *)NULL;
135 static unsigned int error_count = 0;
136 #define MAX_ERRORS_IN_A_ROW 5
137 size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
139 arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
141 bfd *ob = output_bfd;
142 asection *os = input_section->output_section;
143 if (config.relocateable_output == false) ob = (bfd *)NULL;
145 if (bfd_canonicalize_reloc(input_bfd,
150 for (parent = reloc_vector; *parent; parent++)
153 bfd_reloc_status_enum_type r=
154 bfd_perform_relocation(input_bfd,
160 if (r == bfd_reloc_ok) {
161 if (ob != (bfd *)NULL) {
162 /* A parital link, so keep the relocs */
163 os->orelocation[os->reloc_count] = *parent;
170 arelent *p = *parent;
172 if (ob != (bfd *)NULL) {
173 /* A parital link, so keep the relocs */
174 os->orelocation[os->reloc_count] = *parent;
178 if (p->sym_ptr_ptr != (asymbol **)NULL) {
179 s = *(p->sym_ptr_ptr);
186 case bfd_reloc_undefined:
187 /* We remember the symbol, and never print more than
188 a reasonable number of them in a row */
189 if (s == error_symbol) {
196 if (error_count < MAX_ERRORS_IN_A_ROW) {
197 info("%C: undefined reference to `%T'\n",
203 config.make_executable = false;
205 else if (error_count == MAX_ERRORS_IN_A_ROW) {
206 info("%C: more undefined references to `%T' follow\n",
214 /* Don't print any more */
217 case bfd_reloc_dangerous:
218 info("%B: relocation may be wrong `%T'\n",
222 case bfd_reloc_outofrange:
223 info("%B:%s relocation address out of range %T (%x)\n",
229 case bfd_reloc_overflow:
230 info("%B:%s relocation overflow in %T reloc type %d\n",
237 info("%F%B: relocation error, symbol `%T'\n",
245 free((char *)reloc_vector);
256 copy_and_relocate(statement)
257 lang_statement_union_type *statement;
259 switch (statement->header.type) {
260 case lang_fill_statement_enum:
263 bfd_byte play_area[SHORT_SIZE];
265 bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
266 /* Write out all entire shorts */
268 i < statement->fill_statement.size - SHORT_SIZE + 1;
271 bfd_set_section_contents(output_bfd,
272 statement->fill_statement.output_section,
274 statement->data_statement.output_offset +i,
279 /* Now write any remaining byte */
280 if (i < statement->fill_statement.size)
282 bfd_set_section_contents(output_bfd,
283 statement->fill_statement.output_section,
285 statement->data_statement.output_offset +i,
292 case lang_data_statement_enum:
294 bfd_vma value = statement->data_statement.value;
295 bfd_byte play_area[LONG_SIZE];
297 switch (statement->data_statement.type) {
299 bfd_putlong(output_bfd, value, play_area);
303 bfd_putshort(output_bfd, value, play_area);
307 bfd_putchar(output_bfd, value, play_area);
312 bfd_set_section_contents(output_bfd,
313 statement->data_statement.output_section,
315 statement->data_statement.output_vma,
323 case lang_input_section_enum:
326 asection *i = statement->input_section.section;
327 asection *output_section = i->output_section;
328 lang_input_statement_type *ifile =
329 statement->input_section.ifile;
330 if (ifile->just_syms_flag == false) {
331 bfd *inbfd = ifile->the_bfd;
333 if (output_section->flags & SEC_LOAD && i->size != 0)
335 if(bfd_get_section_contents(inbfd,
341 info("%F%B error reading section contents %E\n",
344 perform_relocation (inbfd, i, data_area, ifile->asymbols);
347 if(bfd_set_section_contents(output_bfd,
350 (file_ptr)i->output_offset,
353 info("%F%B error writing section contents of %E\n",
364 /* All the other ones fall through */
373 /* Output the text and data segments, relocating as we go. */
374 lang_for_each_statement(copy_and_relocate);
378 static void read_relocs(abfd, section, symbols)
383 /* Work out the output section ascociated with this input section */
384 asection *output_section = section->output_section;
386 size_t reloc_size = get_reloc_upper_bound(abfd, section);
387 arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
389 if (bfd_canonicalize_reloc(abfd,
393 output_section->reloc_count += section->reloc_count;
402 Run through each section of each file and work work out the total
403 number of relocation records which will finally be in each output
407 LANG_FOR_EACH_INPUT_SECTION
408 (statement, abfd, section,
409 (read_relocs(abfd, section, statement->asymbols)));
414 Now run though all the output sections and allocate the space for
417 LANG_FOR_EACH_OUTPUT_SECTION
419 (section->orelocation =
420 (arelent **)ldmalloc((size_t)(sizeof(arelent **)*
421 section->reloc_count)),
422 section->reloc_count = 0,
423 section->flags |= SEC_HAS_CONTENTS));
427 Copy the data, relocating as we go
429 lang_for_each_statement(copy_and_relocate);
435 data_area = (void*) ldmalloc(largest_section);
436 if (config.relocateable_output == true)
445 /* Output the symbol table (both globals and locals). */