3 /* Copyright (C) 1991 Free Software Foundation, Inc.
5 This file is part of GLD, the Gnu Linker.
7 GLD is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
12 GLD is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GLD; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 * Revision 1.2 1991/03/22 22:31:37 steve
26 * *** empty log message ***
28 * Revision 1.1.1.1 1991/03/21 21:29:05 gumby
29 * Back from Intel with Steve
31 * Revision 1.1 1991/03/21 21:29:04 gumby
34 * Revision 1.2 1991/03/15 18:45:55 rich
37 * Revision 1.1 1991/03/13 00:48:37 chrisb
40 * Revision 1.7 1991/03/10 19:15:03 sac
41 * Took out the abort() which had been put in the wrong place
42 * Updated the version #.
44 * Revision 1.6 1991/03/10 09:31:41 rich
46 * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
47 * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
48 * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
49 * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
50 * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
52 * As of this round of changes, ld now builds on all hosts of (Intel960)
53 * interest and copy passes my copy test on big endian hosts again.
55 * Revision 1.5 1991/03/09 03:25:08 sac
56 * Added support for LONG, SHORT and BYTE keywords in scripts
58 * Revision 1.4 1991/03/06 21:59:34 sac
59 * Completed G++ support
61 * Revision 1.3 1991/03/06 02:29:52 sac
62 * Added support for partial linking.
64 * Revision 1.2 1991/02/22 17:15:11 sac
65 * Added RCS keywords and copyrights
70 This module writes out the final image by reading sections from the
71 input files, relocating them and writing them out
73 There are two main paths through this module, one for normal
74 operation and one for partial linking.
76 During normal operation, raw section data is read along with the
77 associated relocation information, the relocation info applied and
78 the section data written out on a section by section basis.
80 When partially linking, all the relocation records are read to work
81 out how big the output relocation vector will be. Then raw data is
82 read, relocated and written section by section.
84 Written by Steve Chamberlain steve@cygnus.com
97 #include "ldgram.tab.h"
102 /* Static vars for do_warnings and subroutines of it */
103 int list_unresolved_refs; /* List unresolved refs */
104 int list_warning_symbols; /* List warning syms */
105 int list_multiple_defs; /* List multiple definitions */
107 extern char *sys_errlist[];
109 extern unsigned int undefined_global_sym_count;
111 extern bfd *output_bfd;
113 extern struct lang_output_section_statement_struct * create_object_symbols;
118 void lang_for_each_statement(void (*func)());
120 void lang_for_each_statement();
121 #endif /* __STDC__ */
123 extern size_t largest_section;
124 ld_config_type config;
126 extern unsigned int global_symbol_count;
130 static void perform_relocation(input_bfd,
135 asection *input_section;
139 static asymbol *error_symbol = (asymbol *)NULL;
140 static unsigned int error_count = 0;
141 #define MAX_ERRORS_IN_A_ROW 5
142 size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
144 arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
146 bfd *ob = output_bfd;
147 asection *os = input_section->output_section;
148 if (config.relocateable_output == false) ob = (bfd *)NULL;
150 if (bfd_canonicalize_reloc(input_bfd,
155 for (parent = reloc_vector; *parent; parent++)
158 bfd_reloc_status_enum_type r=
159 bfd_perform_relocation(input_bfd,
165 if (r == bfd_reloc_ok) {
166 if (ob != (bfd *)NULL) {
167 /* A parital link, so keep the relocs */
168 os->orelocation[os->reloc_count] = *parent;
175 arelent *p = *parent;
177 if (ob != (bfd *)NULL) {
178 /* A parital link, so keep the relocs */
179 os->orelocation[os->reloc_count] = *parent;
183 if (p->sym_ptr_ptr != (asymbol **)NULL) {
184 s = *(p->sym_ptr_ptr);
191 case bfd_reloc_undefined:
192 /* We remember the symbol, and never print more than
193 a reasonable number of them in a row */
194 if (s == error_symbol) {
201 if (error_count < MAX_ERRORS_IN_A_ROW) {
202 info("%C: undefined reference to `%T'\n",
208 config.make_executable = false;
210 else if (error_count == MAX_ERRORS_IN_A_ROW) {
211 info("%C: more undefined references to `%T' follow\n",
219 /* Don't print any more */
222 case bfd_reloc_dangerous:
223 info("%B: relocation may be wrong `%T'\n",
227 case bfd_reloc_outofrange:
228 info("%B:%s relocation address out of range %T (%x)\n",
234 case bfd_reloc_overflow:
235 info("%B:%s relocation overflow in %T reloc type %d\n",
242 info("%F%B: relocation error, symbol `%T'\n",
250 free((char *)reloc_vector);
261 copy_and_relocate(statement)
262 lang_statement_union_type *statement;
264 switch (statement->header.type) {
265 case lang_fill_statement_enum:
268 bfd_byte play_area[SHORT_SIZE];
270 bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
271 /* Write out all entire shorts */
273 i < statement->fill_statement.size - SHORT_SIZE + 1;
276 bfd_set_section_contents(output_bfd,
277 statement->fill_statement.output_section,
279 statement->data_statement.output_offset +i,
284 /* Now write any remaining byte */
285 if (i < statement->fill_statement.size)
287 bfd_set_section_contents(output_bfd,
288 statement->fill_statement.output_section,
290 statement->data_statement.output_offset +i,
297 case lang_data_statement_enum:
299 bfd_vma value = statement->data_statement.value;
300 bfd_byte play_area[LONG_SIZE];
302 switch (statement->data_statement.type) {
304 bfd_putlong(output_bfd, value, play_area);
308 bfd_putshort(output_bfd, value, play_area);
312 bfd_putchar(output_bfd, value, play_area);
317 bfd_set_section_contents(output_bfd,
318 statement->data_statement.output_section,
320 statement->data_statement.output_vma,
328 case lang_input_section_enum:
331 asection *i = statement->input_section.section;
332 asection *output_section = i->output_section;
333 lang_input_statement_type *ifile = statement->input_section.ifile;
334 bfd *inbfd = ifile->the_bfd;
335 if (output_section->flags & SEC_LOAD && i->size != 0)
337 if(bfd_get_section_contents(inbfd,
343 info("%F%B error reading section contents %E\n",
346 perform_relocation (inbfd, i, data_area, ifile->asymbols);
349 if(bfd_set_section_contents(output_bfd,
352 (file_ptr)i->output_offset,
355 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). */