-y support
[platform/upstream/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 This program 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 2 of the License, or
8 (at your option) any later version.
9
10 This program 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 this program; if not, write to the Free Software
17 Foundation, Inc., 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 "bfd.h"
44 #include "sysdep.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.h"
52
53
54
55
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 bfd_size_type largest_section;
78 ld_config_type config;
79
80 extern unsigned int global_symbol_count;
81
82 boolean trace_files;
83
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)
93 {
94   static asymbol *error_symbol = (asymbol *)NULL;
95   static unsigned int error_count = 0;
96 #define MAX_ERRORS_IN_A_ROW 5
97   bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section);
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
105   input_section->_cooked_size = input_section->_raw_size;
106   input_section->reloc_done = 1;
107   
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
116           bfd_reloc_status_type r=
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 */
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
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) {
165                     einfo("%C: undefined reference to `%T'\n",
166                           input_bfd, input_section, symbols,
167                           (*parent)->address, s);
168                     config.make_executable = false;
169                   }
170                   else if (error_count == MAX_ERRORS_IN_A_ROW) {
171                     einfo("%C: more undefined references to `%T' follow\n",
172                           input_bfd, input_section,
173                           symbols, (*parent)->address, s);
174                   }                 
175                   else {
176                     /* Don't print any more */
177                   }
178                   break;
179                 case bfd_reloc_dangerous: 
180                   einfo("%B: relocation may be wrong `%T'\n",
181                         input_bfd, s);
182                   break;
183                 case bfd_reloc_outofrange:
184                   einfo("%B:%s relocation address out of range %T (%V)\n",
185                         input_bfd, input_section->name, s, p->address); 
186                   break;
187                 case bfd_reloc_overflow:
188                   einfo("%B:%s relocation overflow in %T reloc type %d\n",
189                         input_bfd, input_section->name, s, p->howto->type);
190                   break;
191                 default:
192                   einfo("%F%B: relocation error, symbol `%T'\n",
193                         input_bfd, s);
194                   break;
195                 }
196             }
197         }
198     }
199   free((char *)reloc_vector);
200 }
201
202
203
204
205
206
207 PTR data_area;
208
209 static void
210 DEFUN(copy_and_relocate,(statement),
211       lang_statement_union_type *statement)
212 {
213   switch (statement->header.type) {
214   case lang_fill_statement_enum: 
215       {
216 #if 0
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);
230
231         }
232
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);
241
242         }
243 #endif
244     }
245     break;
246   case lang_data_statement_enum:
247     {
248       bfd_vma value = statement->data_statement.value;
249       bfd_byte play_area[LONG_SIZE];
250       unsigned int size = 0;
251       switch (statement->data_statement.type) {
252       case LONG:
253         bfd_put_32(output_bfd, value,  play_area);
254         size = LONG_SIZE;
255         break;
256       case SHORT:
257         bfd_put_16(output_bfd, value,  play_area);
258         size = SHORT_SIZE;
259         break;
260       case BYTE:
261         bfd_put_8(output_bfd, value,  play_area);
262         size = BYTE_SIZE;
263         break;
264       }
265       
266       bfd_set_section_contents(output_bfd,
267                                statement->data_statement.output_section,
268                                play_area,
269                                statement->data_statement.output_vma,
270                                size);
271                                
272                                
273
274
275     }
276     break;
277   case lang_input_section_enum:
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
287           if (output_section->flags & SEC_LOAD &&
288               output_section->flags & SEC_ALLOC
289               && bfd_get_section_size_before_reloc(i) != 0) 
290               {
291                 if(bfd_get_section_contents(inbfd,
292                                             i,
293                                             data_area,
294                                             (file_ptr)0,
295                                             bfd_get_section_size_before_reloc(i)) == false) 
296                     {
297                       einfo("%F%B error reading section contents %E\n", inbfd);
298                     }
299                 /* Set the reloc bit */
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,
307                                             bfd_get_section_size_after_reloc(i)) == false) 
308                     {
309                       einfo("%F%B error writing section contents of %E\n",
310                             output_bfd);
311                     }
312
313               }
314         }
315
316       }
317     break;
318
319   default:
320     /* All the other ones fall through */
321     ;
322
323   }
324 }
325
326 void
327 DEFUN_VOID(write_norel)
328 {
329   /* Output the text and data segments, relocating as we go.  */
330   lang_for_each_statement(copy_and_relocate);
331 }
332
333
334 static void 
335 DEFUN(read_relocs,(abfd, section, symbols),
336       bfd *abfd AND
337       asection *section AND
338       asymbol **symbols)
339 {
340   /* Work out the output section ascociated with this input section */
341   asection *output_section = section->output_section;
342
343   bfd_size_type reloc_size = bfd_get_reloc_upper_bound(abfd, section);
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
355 static  void
356 DEFUN_VOID(write_rel)
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 =
377       (arelent **)ldmalloc((bfd_size_type)(sizeof(arelent **)*
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
390 DEFUN_VOID(ldwrite)
391 {
392   data_area = (PTR) ldmalloc(largest_section);
393   if (config.relocateable_output == true)
394       {
395         write_rel();
396       }
397   else 
398       {
399         write_relaxnorel(output_bfd);
400       }
401   free(data_area);
402   /* Output the symbol table (both globals and locals).  */
403
404   /* Print a map, if requested.  */
405
406   if (config.map_file) {
407     ldsym_print_symbol_table ();
408     lang_map();
409   }
410
411   ldsym_write ();
412
413 }
414