Merges from Intel.
[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
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 steve@cygnus.com
39
40 */
41
42
43 #include "sysdep.h"
44 #include "bfd.h"
45
46 #include "ldlang.h"
47 #include "ld.h"
48 #include "ldwrite.h"
49 #include "ldmisc.h"
50 #include "ldsym.h"
51 #include "ldgram.tab.h"
52
53
54
55 char *ldmalloc();
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
77 extern size_t largest_section;
78 ld_config_type config;
79
80 extern unsigned int global_symbol_count;
81
82 boolean trace_files;
83
84 static void perform_relocation(input_bfd,
85                                input_section,
86                                data,
87                                symbols)
88 bfd *input_bfd;
89 asection *input_section;
90 PTR data;
91 asymbol **symbols;
92 {
93   static asymbol *error_symbol = (asymbol *)NULL;
94   static unsigned int error_count = 0;
95 #define MAX_ERRORS_IN_A_ROW 5
96   size_t reloc_size = get_reloc_upper_bound(input_bfd, input_section);
97
98   arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
99   arelent **parent;
100   bfd *ob = output_bfd;
101   asection *os = input_section->output_section;
102   if (config.relocateable_output == false) ob = (bfd *)NULL;
103
104   if (bfd_canonicalize_reloc(input_bfd, 
105                              input_section,
106                              reloc_vector,
107                              symbols) )
108     {
109       for (parent = reloc_vector; *parent; parent++) 
110         {
111
112           bfd_reloc_status_enum_type r=
113             bfd_perform_relocation(input_bfd,
114                                    *parent,
115                                    data,
116                                    input_section, 
117                                    ob);
118
119           if (r == bfd_reloc_ok) {
120             if (ob != (bfd *)NULL) {
121               /* A parital link, so keep the relocs */
122               os->orelocation[os->reloc_count] = *parent;
123               os->reloc_count++;
124             }
125           }
126           else
127             {
128               asymbol *s;
129               arelent *p = *parent;
130
131               if (ob != (bfd *)NULL) {
132                 /* A parital link, so keep the relocs */
133                 os->orelocation[os->reloc_count] = *parent;
134                 os->reloc_count++;
135               }
136
137               if (p->sym_ptr_ptr != (asymbol **)NULL) {
138                 s = *(p->sym_ptr_ptr);
139               }
140               else {
141                 s = (asymbol *)NULL;
142               }
143               switch (r)
144                 {
145                 case bfd_reloc_undefined:
146                   /* We remember the symbol, and never print more than
147                      a reasonable number of them in a row */
148                   if (s == error_symbol) {
149                     error_count++;
150                   }
151                   else {
152                     error_count = 0;
153                     error_symbol = s;
154                   }
155                   if (error_count < MAX_ERRORS_IN_A_ROW) {
156                     info("%C: undefined reference to `%T'\n",
157                          input_bfd,
158                          input_section,
159                          symbols,
160                          (*parent)->address,
161                          s);
162                     config.make_executable = false;
163                   }
164                   else if (error_count == MAX_ERRORS_IN_A_ROW) {
165                     info("%C: more undefined references to `%T' follow\n",
166                          input_bfd,
167                          input_section,
168                          symbols,
169                          (*parent)->address,
170                          s);
171                   }                 
172                   else {
173                     /* Don't print any more */
174                   }
175                   break;
176                 case bfd_reloc_dangerous: 
177                   info("%B: relocation may be wrong `%T'\n",
178                        input_bfd,
179                        s);
180                   break;
181                 case bfd_reloc_outofrange:
182                   info("%B:%s relocation address out of range %T (%x)\n",
183                        input_bfd,
184                        input_section->name,
185                        s,
186                        p->address); 
187                   break;
188                 case bfd_reloc_overflow:
189                   info("%B:%s relocation overflow in %T reloc type %d\n",
190                        input_bfd,
191                        input_section->name,
192                        s,
193                        p->howto->type);
194                   break;
195                 default:
196                   info("%F%B: relocation error, symbol `%T'\n",
197                        input_bfd,
198                        s);
199                   break;
200                 }
201             }
202         }
203     }
204   free((char *)reloc_vector);
205 }
206
207
208
209
210
211
212 PTR data_area;
213
214 static void
215 copy_and_relocate(statement)
216 lang_statement_union_type *statement;
217 {
218   switch (statement->header.type) {
219   case lang_fill_statement_enum: 
220       {
221 #if 0
222       bfd_byte play_area[SHORT_SIZE];
223       unsigned int i;
224       bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
225       /* Write out all entire shorts */
226       for (i = 0;
227            i < statement->fill_statement.size - SHORT_SIZE + 1;
228            i+= SHORT_SIZE)
229         {
230           bfd_set_section_contents(output_bfd,
231                                    statement->fill_statement.output_section,
232                                    play_area,
233                                    statement->data_statement.output_offset +i,
234                                    SHORT_SIZE);
235
236         }
237
238       /* Now write any remaining byte */
239       if (i < statement->fill_statement.size) 
240         {
241           bfd_set_section_contents(output_bfd,
242                                    statement->fill_statement.output_section,
243                                    play_area,
244                                    statement->data_statement.output_offset +i,
245                                    1);
246
247         }
248 #endif
249     }
250     break;
251   case lang_data_statement_enum:
252     {
253       bfd_vma value = statement->data_statement.value;
254       bfd_byte play_area[LONG_SIZE];
255       unsigned int size;
256       switch (statement->data_statement.type) {
257       case LONG:
258         bfd_putlong(output_bfd, value,  play_area);
259         size = LONG_SIZE;
260         break;
261       case SHORT:
262         bfd_putshort(output_bfd, value,  play_area);
263         size = SHORT_SIZE;
264         break;
265       case BYTE:
266         bfd_putchar(output_bfd, value,  play_area);
267         size = BYTE_SIZE;
268         break;
269       }
270       
271       bfd_set_section_contents(output_bfd,
272                                statement->data_statement.output_section,
273                                play_area,
274                                statement->data_statement.output_vma,
275                                size);
276                                
277                                
278
279
280     }
281     break;
282   case lang_input_section_enum:
283       {
284
285         asection *i  = statement->input_section.section;
286         asection *output_section = i->output_section;
287         lang_input_statement_type *ifile =
288           statement->input_section.ifile;
289         if (ifile->just_syms_flag == false) {
290           bfd *inbfd = ifile->the_bfd;
291
292           if (output_section->flags & SEC_LOAD && i->size != 0) 
293               {
294                 if(bfd_get_section_contents(inbfd,
295                                             i,
296                                             data_area,
297                                             0L,
298                                             i->size) == false) 
299                     {
300                       info("%F%B error reading section contents %E\n",
301                            inbfd);
302                     }
303                 perform_relocation (inbfd,  i,  data_area, ifile->asymbols);
304
305
306                 if(bfd_set_section_contents(output_bfd,
307                                             output_section,
308                                             data_area,
309                                             (file_ptr)i->output_offset,
310                                             i->size) == false) 
311                     {
312                       info("%F%B error writing section contents of %E\n",
313                            output_bfd);
314                     }
315
316               }
317         }
318
319       }
320     break;
321
322   default:
323     /* All the other ones fall through */
324     ;
325
326   }
327 }
328
329 void
330 write_norel()
331 {
332   /* Output the text and data segments, relocating as we go.  */
333   lang_for_each_statement(copy_and_relocate);
334 }
335
336
337 static void read_relocs(abfd, section, symbols)
338 bfd *abfd;
339 asection *section;
340 asymbol **symbols;
341 {
342   /* Work out the output section ascociated with this input section */
343   asection *output_section = section->output_section;
344
345   size_t reloc_size = get_reloc_upper_bound(abfd, section);
346   arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
347
348   if (bfd_canonicalize_reloc(abfd, 
349                              section,
350                              reloc_vector,
351                              symbols)) {
352     output_section->reloc_count   += section->reloc_count;
353   }
354 }
355
356
357 static void
358 write_rel()
359 {
360   /*
361      Run through each section of each file and work work out the total
362      number of relocation records which will finally be in each output
363      section 
364      */
365
366   LANG_FOR_EACH_INPUT_SECTION
367     (statement, abfd, section,
368      (read_relocs(abfd, section, statement->asymbols)));
369
370
371
372   /*
373      Now run though all the output sections and allocate the space for
374      all the relocations
375      */
376   LANG_FOR_EACH_OUTPUT_SECTION
377     (section, 
378      (section->orelocation =
379       (arelent **)ldmalloc((size_t)(sizeof(arelent **)*
380                                     section->reloc_count)),
381       section->reloc_count = 0,
382      section->flags |= SEC_HAS_CONTENTS));
383
384
385   /*
386      Copy the data, relocating as we go
387      */
388   lang_for_each_statement(copy_and_relocate);
389 }
390
391 void
392 ldwrite ()
393 {
394   data_area = (PTR) ldmalloc(largest_section);
395   if (config.relocateable_output == true)
396     {
397       write_rel();
398     }
399   else 
400     {
401     write_norel();
402   }
403   free(data_area);
404   /* Output the symbol table (both globals and locals).  */
405   ldsym_write ();
406
407 }
408