Initial revision
[external/binutils.git] / ld / ldwrite.c
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  * $Id$ 
21  *
22  *  $Log$
23  *  Revision 1.1  1991/03/21 21:29:04  gumby
24  *  Initial revision
25  *
26  * Revision 1.2  1991/03/15  18:45:55  rich
27  * foo
28  *
29  * Revision 1.1  1991/03/13  00:48:37  chrisb
30  * Initial revision
31  *
32  * Revision 1.7  1991/03/10  19:15:03  sac
33  * Took out the abort() which had been put in the wrong place
34  * Updated the version #.
35  *
36  * Revision 1.6  1991/03/10  09:31:41  rich
37  *  Modified Files:
38  *      Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
39  *      ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
40  *      ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
41  *      ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
42  *      ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
43  *
44  * As of this round of changes, ld now builds on all hosts of (Intel960)
45  * interest and copy passes my copy test on big endian hosts again.
46  *
47  * Revision 1.5  1991/03/09  03:25:08  sac
48  * Added support for LONG, SHORT and BYTE keywords in scripts
49  *
50  * Revision 1.4  1991/03/06  21:59:34  sac
51  * Completed G++ support
52  *
53  * Revision 1.3  1991/03/06  02:29:52  sac
54  * Added support for partial linking.
55  *
56  * Revision 1.2  1991/02/22  17:15:11  sac
57  * Added RCS keywords and copyrights
58  *
59 */
60
61 /* 
62    This module writes out the final image by reading sections from the
63    input files, relocating them and writing them out
64
65    There are two main paths through this module, one for normal
66    operation and one for partial linking. 
67
68    During  normal operation, raw section data is read along with the
69    associated relocation information, the relocation info applied and
70    the section data written out on a section by section basis.
71
72    When partially linking, all the relocation records are read to work
73    out how big the output relocation vector will be. Then raw data is
74    read, relocated and written section by section.
75
76    Written by Steve Chamberlain steve@cygnus.com
77
78 */
79
80
81 #include "sysdep.h"
82 #include "bfd.h"
83
84 #include "ldlang.h"
85 #include "ld.h"
86 #include "ldwrite.h"
87 #include "ldmisc.h"
88 #include "ldsym.h"
89 #include "ldgram.tab.h"
90
91
92
93 char *ldmalloc();
94 /* Static vars for do_warnings and subroutines of it */
95 int list_unresolved_refs;       /* List unresolved refs */
96 int list_warning_symbols;       /* List warning syms */
97 int list_multiple_defs;         /* List multiple definitions */
98 extern int errno;
99 extern char *sys_errlist[];
100
101 extern unsigned int undefined_global_sym_count;
102
103 extern bfd *output_bfd;
104
105 extern struct lang_output_section_statement_struct * create_object_symbols;
106
107 extern char lprefix;
108
109 #ifdef __STDC__
110 void lang_for_each_statement(void (*func)());
111 #else /* __STDC__ */
112 void lang_for_each_statement();
113 #endif /* __STDC__ */
114
115 extern size_t largest_section;
116 ld_config_type config;
117
118 extern unsigned int global_symbol_count;
119
120 boolean trace_files;
121
122 static void perform_relocation(input_bfd,
123                                input_section,
124                                data,
125                                symbols)
126 bfd *input_bfd;
127 asection *input_section;
128 void *data;
129 asymbol **symbols;
130 {
131   static asymbol *error_symbol = (asymbol *)NULL;
132   static unsigned int error_count = 0;
133 #define MAX_ERRORS_IN_A_ROW 5
134   size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
135
136   arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
137   arelent **parent;
138   bfd *ob = output_bfd;
139   asection *os = input_section->output_section;
140   if (config.relocateable_output == false) ob = (bfd *)NULL;
141
142   if (bfd_canonicalize_reloc(input_bfd, 
143                              input_section,
144                              reloc_vector,
145                              symbols) )
146     {
147       for (parent = reloc_vector; *parent; parent++) 
148         {
149
150           bfd_reloc_status_enum_type r=
151             bfd_perform_relocation(input_bfd,
152                                    *parent,
153                                    data,
154                                    input_section, 
155                                    ob);
156
157           if (r == bfd_reloc_ok) {
158             if (ob != (bfd *)NULL) {
159               /* A parital link, so keep the relocs */
160               os->orelocation[os->reloc_count] = *parent;
161               os->reloc_count++;
162             }
163           }
164           else
165             {
166               asymbol *s;
167               arelent *p = *parent;
168
169               if (ob != (bfd *)NULL) {
170                 /* A parital link, so keep the relocs */
171                 os->orelocation[os->reloc_count] = *parent;
172                 os->reloc_count++;
173               }
174
175               if (p->sym_ptr_ptr != (asymbol **)NULL) {
176                 s = *(p->sym_ptr_ptr);
177               }
178               else {
179                 s = (asymbol *)NULL;
180               }
181               switch (r)
182                 {
183                 case bfd_reloc_undefined:
184                   /* We remember the symbol, and never print more than
185                      a reasonable number of them in a row */
186                   if (s == error_symbol) {
187                     error_count++;
188                   }
189                   else {
190                     error_count = 0;
191                     error_symbol = s;
192                   }
193                   if (error_count < MAX_ERRORS_IN_A_ROW) {
194                     info("%C: undefined reference to `%T'\n",
195                          input_bfd,
196                          input_section,
197                          symbols,
198                          (*parent)->address,
199                          s);
200                     config.make_executable = false;
201                   }
202                   else if (error_count == MAX_ERRORS_IN_A_ROW) {
203                     info("%C: more undefined references to `%T' follow\n",
204                          input_bfd,
205                          input_section,
206                          symbols,
207                          (*parent)->address,
208                          s);
209                   }                 
210                   else {
211                     /* Don't print any more */
212                   }
213                   break;
214                 case bfd_reloc_dangerous: 
215                   info("%B: relocation may be wrong `%T'\n",
216                        input_bfd,
217                        s);
218                   break;
219                 case bfd_reloc_outofrange:
220                   info("%B:%s relocation address out of range %T (%x)\n",
221                        input_bfd,
222                        input_section->name,
223                        s,
224                        p->address); 
225                   break;
226                 case bfd_reloc_overflow:
227                   info("%B:%s relocation overflow in %T reloc type %d\n",
228                        input_bfd,
229                        input_section->name,
230                        s,
231                        p->howto->type);
232                   break;
233                 default:
234                   info("%F%B: relocation error, symbol `%T'\n",
235                        input_bfd,
236                        s);
237                   break;
238                 }
239             }
240         }
241     }
242   free((char *)reloc_vector);
243 }
244
245
246
247
248
249
250 void  *data_area;
251
252 static void
253 copy_and_relocate(statement)
254 lang_statement_union_type *statement;
255 {
256   switch (statement->header.type) {
257   case lang_fill_statement_enum: 
258     {
259 #if 0
260       bfd_byte play_area[SHORT_SIZE];
261       unsigned int i;
262       bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
263       /* Write out all entire shorts */
264       for (i = 0;
265            i < statement->fill_statement.size - SHORT_SIZE + 1;
266            i+= SHORT_SIZE)
267         {
268           bfd_set_section_contents(output_bfd,
269                                    statement->fill_statement.output_section,
270                                    play_area,
271                                    statement->data_statement.output_offset +i,
272                                    SHORT_SIZE);
273
274         }
275
276       /* Now write any remaining byte */
277       if (i < statement->fill_statement.size) 
278         {
279           bfd_set_section_contents(output_bfd,
280                                    statement->fill_statement.output_section,
281                                    play_area,
282                                    statement->data_statement.output_offset +i,
283                                    1);
284
285         }
286 #endif
287     }
288     break;
289   case lang_data_statement_enum:
290     {
291       bfd_vma value = statement->data_statement.value;
292       bfd_byte play_area[LONG_SIZE];
293       unsigned int size;
294       switch (statement->data_statement.type) {
295       case LONG:
296         bfd_putlong(output_bfd, value,  play_area);
297         size = LONG_SIZE;
298         break;
299       case SHORT:
300         bfd_putshort(output_bfd, value,  play_area);
301         size = SHORT_SIZE;
302         break;
303       case BYTE:
304         bfd_putchar(output_bfd, value,  play_area);
305         size = BYTE_SIZE;
306         break;
307       }
308       
309       bfd_set_section_contents(output_bfd,
310                                statement->data_statement.output_section,
311                                play_area,
312                                statement->data_statement.output_vma,
313                                size);
314                                
315                                
316
317
318     }
319     break;
320   case lang_input_section_enum:
321     {
322     
323       asection *i  = statement->input_section.section;
324       asection *output_section = i->output_section;
325       lang_input_statement_type *ifile = statement->input_section.ifile;
326       bfd *inbfd = ifile->the_bfd;
327       if (output_section->flags & SEC_LOAD && i->size != 0) 
328         {
329           if(bfd_get_section_contents(inbfd,
330                                       i,
331                                       data_area,
332                                       0L,
333                                       i->size) == false) 
334             {
335               info("%F%B error reading section contents %E\n",
336                    inbfd);
337             }
338           perform_relocation (inbfd,  i,  data_area, ifile->asymbols);
339
340
341           if(bfd_set_section_contents(output_bfd,
342                                       output_section,
343                                       data_area,
344                                       (file_ptr)i->output_offset,
345                                       i->size) == false) 
346             {
347               info("%F%B error writing section contents of %E\n",
348                    output_bfd);
349             }
350
351         }
352     }
353     break;
354
355  default:
356     /* All the other ones fall through */
357     ;
358
359   }
360 }
361
362 void
363 write_norel()
364 {
365   /* Output the text and data segments, relocating as we go.  */
366   lang_for_each_statement(copy_and_relocate);
367 }
368
369
370 static void read_relocs(abfd, section, symbols)
371 bfd *abfd;
372 asection *section;
373 asymbol **symbols;
374 {
375   /* Work out the output section ascociated with this input section */
376   asection *output_section = section->output_section;
377
378   size_t reloc_size = get_reloc_upper_bound(abfd, section);
379   arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
380
381   if (bfd_canonicalize_reloc(abfd, 
382                              section,
383                              reloc_vector,
384                              symbols)) {
385     output_section->reloc_count   += section->reloc_count;
386   }
387 }
388
389
390 static void
391 write_rel()
392 {
393   /*
394      Run through each section of each file and work work out the total
395      number of relocation records which will finally be in each output
396      section 
397      */
398
399   LANG_FOR_EACH_INPUT_SECTION
400     (statement, abfd, section,
401      (read_relocs(abfd, section, statement->asymbols)));
402
403
404
405   /*
406      Now run though all the output sections and allocate the space for
407      all the relocations
408      */
409   LANG_FOR_EACH_OUTPUT_SECTION
410     (section, 
411      (section->orelocation =
412       (arelent **)ldmalloc((size_t)(sizeof(arelent **)*
413                                     section->reloc_count)),
414       section->reloc_count = 0,
415      section->flags |= SEC_HAS_CONTENTS));
416
417
418   /*
419      Copy the data, relocating as we go
420      */
421   lang_for_each_statement(copy_and_relocate);
422 }
423
424 void
425 ldwrite ()
426 {
427   data_area = (void*) ldmalloc(largest_section);
428   if (config.relocateable_output == true)
429     {
430       write_rel();
431     }
432   else 
433     {
434     write_norel();
435   }
436   free(data_area);
437   /* Output the symbol table (both globals and locals).  */
438   ldsym_write ();
439
440 }
441