Convert to C90
[external/binutils.git] / ld / ldwrite.c
1 /* ldwrite.c -- write out the linked file
2    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003
3    Free Software Foundation, Inc.
4    Written by Steve Chamberlain sac@cygnus.com
5
6 This file is part of GLD, the Gnu Linker.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "bfdlink.h"
25 #include "libiberty.h"
26
27 #include "ld.h"
28 #include "ldexp.h"
29 #include "ldlang.h"
30 #include "ldwrite.h"
31 #include "ldmisc.h"
32 #include <ldgram.h>
33 #include "ldmain.h"
34
35 /* Build link_order structures for the BFD linker.  */
36
37 static void
38 build_link_order (lang_statement_union_type *statement)
39 {
40   switch (statement->header.type)
41     {
42     case lang_data_statement_enum:
43       {
44         asection *output_section;
45         struct bfd_link_order *link_order;
46         bfd_vma value;
47         bfd_boolean big_endian = FALSE;
48
49         output_section = statement->data_statement.output_section;
50         ASSERT (output_section->owner == output_bfd);
51
52         link_order = bfd_new_link_order (output_bfd, output_section);
53         if (link_order == NULL)
54           einfo (_("%P%F: bfd_new_link_order failed\n"));
55
56         link_order->type = bfd_data_link_order;
57         link_order->offset = statement->data_statement.output_vma;
58         link_order->u.data.contents = xmalloc (QUAD_SIZE);
59
60         value = statement->data_statement.value;
61
62         /* If the endianness of the output BFD is not known, then we
63            base the endianness of the data on the first input file.
64            By convention, the bfd_put routines for an unknown
65            endianness are big endian, so we must swap here if the
66            input file is little endian.  */
67         if (bfd_big_endian (output_bfd))
68           big_endian = TRUE;
69         else if (bfd_little_endian (output_bfd))
70           big_endian = FALSE;
71         else
72           {
73             bfd_boolean swap;
74
75             swap = FALSE;
76             if (command_line.endian == ENDIAN_BIG)
77               big_endian = TRUE;
78             else if (command_line.endian == ENDIAN_LITTLE)
79               {
80                 big_endian = FALSE;
81                 swap = TRUE;
82               }
83             else if (command_line.endian == ENDIAN_UNSET)
84               {
85                 big_endian = TRUE;
86                 {
87                   LANG_FOR_EACH_INPUT_STATEMENT (s)
88                     {
89                       if (s->the_bfd != NULL)
90                         {
91                           if (bfd_little_endian (s->the_bfd))
92                             {
93                               big_endian = FALSE;
94                               swap = TRUE;
95                             }
96                           break;
97                         }
98                     }
99                 }
100               }
101
102             if (swap)
103               {
104                 bfd_byte buffer[8];
105
106                 switch (statement->data_statement.type)
107                   {
108                   case QUAD:
109                   case SQUAD:
110                     if (sizeof (bfd_vma) >= QUAD_SIZE)
111                       {
112                         bfd_putl64 (value, buffer);
113                         value = bfd_getb64 (buffer);
114                         break;
115                       }
116                     /* Fall through.  */
117                   case LONG:
118                     bfd_putl32 (value, buffer);
119                     value = bfd_getb32 (buffer);
120                     break;
121                   case SHORT:
122                     bfd_putl16 (value, buffer);
123                     value = bfd_getb16 (buffer);
124                     break;
125                   case BYTE:
126                     break;
127                   default:
128                     abort ();
129                   }
130               }
131           }
132
133         ASSERT (output_section->owner == output_bfd);
134         switch (statement->data_statement.type)
135           {
136           case QUAD:
137           case SQUAD:
138             if (sizeof (bfd_vma) >= QUAD_SIZE)
139               bfd_put_64 (output_bfd, value, link_order->u.data.contents);
140             else
141               {
142                 bfd_vma high;
143
144                 if (statement->data_statement.type == QUAD)
145                   high = 0;
146                 else if ((value & 0x80000000) == 0)
147                   high = 0;
148                 else
149                   high = (bfd_vma) -1;
150                 bfd_put_32 (output_bfd, high,
151                             (link_order->u.data.contents
152                              + (big_endian ? 0 : 4)));
153                 bfd_put_32 (output_bfd, value,
154                             (link_order->u.data.contents
155                              + (big_endian ? 4 : 0)));
156               }
157             link_order->size = QUAD_SIZE;
158             break;
159           case LONG:
160             bfd_put_32 (output_bfd, value, link_order->u.data.contents);
161             link_order->size = LONG_SIZE;
162             break;
163           case SHORT:
164             bfd_put_16 (output_bfd, value, link_order->u.data.contents);
165             link_order->size = SHORT_SIZE;
166             break;
167           case BYTE:
168             bfd_put_8 (output_bfd, value, link_order->u.data.contents);
169             link_order->size = BYTE_SIZE;
170             break;
171           default:
172             abort ();
173           }
174       }
175       break;
176
177     case lang_reloc_statement_enum:
178       {
179         lang_reloc_statement_type *rs;
180         asection *output_section;
181         struct bfd_link_order *link_order;
182
183         rs = &statement->reloc_statement;
184
185         output_section = rs->output_section;
186         ASSERT (output_section->owner == output_bfd);
187
188         link_order = bfd_new_link_order (output_bfd, output_section);
189         if (link_order == NULL)
190           einfo (_("%P%F: bfd_new_link_order failed\n"));
191
192         link_order->offset = rs->output_vma;
193         link_order->size = bfd_get_reloc_size (rs->howto);
194
195         link_order->u.reloc.p = xmalloc (sizeof (struct bfd_link_order_reloc));
196
197         link_order->u.reloc.p->reloc = rs->reloc;
198         link_order->u.reloc.p->addend = rs->addend_value;
199
200         if (rs->name == NULL)
201           {
202             link_order->type = bfd_section_reloc_link_order;
203             if (rs->section->owner == output_bfd)
204               link_order->u.reloc.p->u.section = rs->section;
205             else
206               {
207                 link_order->u.reloc.p->u.section = rs->section->output_section;
208                 link_order->u.reloc.p->addend += rs->section->output_offset;
209               }
210           }
211         else
212           {
213             link_order->type = bfd_symbol_reloc_link_order;
214             link_order->u.reloc.p->u.name = rs->name;
215           }
216       }
217       break;
218
219     case lang_input_section_enum:
220       /* Create a new link_order in the output section with this
221          attached */
222       if (!statement->input_section.ifile->just_syms_flag)
223         {
224           asection *i = statement->input_section.section;
225           asection *output_section = i->output_section;
226
227           ASSERT (output_section->owner == output_bfd);
228
229           if ((output_section->flags & SEC_HAS_CONTENTS) != 0
230               || ((output_section->flags & SEC_LOAD) != 0
231                   && (output_section->flags & SEC_THREAD_LOCAL)))
232             {
233               struct bfd_link_order *link_order;
234
235               link_order = bfd_new_link_order (output_bfd, output_section);
236
237               if (i->flags & SEC_NEVER_LOAD)
238                 {
239                   /* We've got a never load section inside one which
240                      is going to be output, we'll change it into a
241                      fill.  */
242                   link_order->type = bfd_data_link_order;
243                   link_order->u.data.contents = "";
244                   link_order->u.data.size = 1;
245                 }
246               else
247                 {
248                   link_order->type = bfd_indirect_link_order;
249                   link_order->u.indirect.section = i;
250                   ASSERT (i->output_section == output_section);
251                 }
252               if (i->_cooked_size)
253                 link_order->size = i->_cooked_size;
254               else
255                 link_order->size = bfd_get_section_size_before_reloc (i);
256               link_order->offset = i->output_offset;
257             }
258         }
259       break;
260
261     case lang_padding_statement_enum:
262       /* Make a new link_order with the right filler */
263       {
264         asection *output_section;
265         struct bfd_link_order *link_order;
266
267         output_section = statement->padding_statement.output_section;
268         ASSERT (statement->padding_statement.output_section->owner
269                 == output_bfd);
270         if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
271           {
272             link_order = bfd_new_link_order (output_bfd, output_section);
273             link_order->type = bfd_data_link_order;
274             link_order->size = statement->padding_statement.size;
275             link_order->offset = statement->padding_statement.output_offset;
276             link_order->u.data.contents = statement->padding_statement.fill->data;
277             link_order->u.data.size = statement->padding_statement.fill->size;
278           }
279       }
280       break;
281
282     default:
283       /* All the other ones fall through */
284       break;
285     }
286 }
287
288 /* Wander around the input sections, make sure that
289    we'll never try and create an output section with more relocs
290    than will fit.. Do this by always assuming the worst case, and
291    creating new output sections with all the right bits.  */
292 #define TESTIT 1
293 static asection *
294 clone_section (bfd *abfd, asection *s, const char *name, int *count)
295 {
296   char templ[6];
297   char *sname;
298   asection *n;
299   struct bfd_link_hash_entry *h;
300
301   /* Invent a section name from the first five chars of the base
302      section name and a digit suffix.  */
303   strncpy (templ, name, sizeof (templ) - 1);
304   templ[sizeof (templ) - 1] = '\0';
305   if ((sname = bfd_get_unique_section_name (abfd, templ, count)) == NULL
306       || (n = bfd_make_section_anyway (abfd, sname)) == NULL
307       || (h = bfd_link_hash_lookup (link_info.hash,
308                                     sname, TRUE, TRUE, FALSE)) == NULL)
309     {
310       einfo (_("%F%P: clone section failed: %E\n"));
311       /* Silence gcc warnings.  einfo exits, so we never reach here.  */
312       return NULL;
313     }
314
315   /* Set up section symbol.  */
316   h->type = bfd_link_hash_defined;
317   h->u.def.value = 0;
318   h->u.def.section = n;
319
320   n->flags = s->flags;
321   n->vma = s->vma;
322   n->user_set_vma = s->user_set_vma;
323   n->lma = s->lma;
324   n->_cooked_size = 0;
325   n->_raw_size = 0;
326   n->output_offset = s->output_offset;
327   n->output_section = n;
328   n->orelocation = 0;
329   n->reloc_count = 0;
330   n->alignment_power = s->alignment_power;
331   return n;
332 }
333
334 #if TESTING
335 static void
336 ds (asection *s)
337 {
338   struct bfd_link_order *l = s->link_order_head;
339   printf ("vma %x size %x\n", s->vma, s->_raw_size);
340   while (l)
341     {
342       if (l->type == bfd_indirect_link_order)
343         {
344           printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
345         }
346       else
347         {
348           printf (_("%8x something else\n"), l->offset);
349         }
350       l = l->next;
351     }
352   printf ("\n");
353 }
354
355 dump (char *s, asection *a1, asection *a2)
356 {
357   printf ("%s\n", s);
358   ds (a1);
359   ds (a2);
360 }
361
362 static void
363 sanity_check (bfd *abfd)
364 {
365   asection *s;
366   for (s = abfd->sections; s; s = s->next)
367     {
368       struct bfd_link_order *p;
369       bfd_vma prev = 0;
370       for (p = s->link_order_head; p; p = p->next)
371         {
372           if (p->offset > 100000)
373             abort ();
374           if (p->offset < prev)
375             abort ();
376           prev = p->offset;
377         }
378     }
379 }
380 #else
381 #define sanity_check(a)
382 #define dump(a, b, c)
383 #endif
384
385 static void
386 split_sections (bfd *abfd, struct bfd_link_info *info)
387 {
388   asection *original_sec;
389   int nsecs = abfd->section_count;
390   sanity_check (abfd);
391   /* Look through all the original sections.  */
392   for (original_sec = abfd->sections;
393        original_sec && nsecs;
394        original_sec = original_sec->next, nsecs--)
395     {
396       int count = 0;
397       unsigned int lines = 0;
398       unsigned int relocs = 0;
399       bfd_size_type sec_size = 0;
400       struct bfd_link_order *l;
401       struct bfd_link_order *p;
402       bfd_vma vma = original_sec->vma;
403       asection *cursor = original_sec;
404
405       /* Count up the relocations and line entries to see if anything
406          would be too big to fit.  Accumulate section size too.  */
407       for (l = NULL, p = cursor->link_order_head; p != NULL; p = l->next)
408         {
409           unsigned int thislines = 0;
410           unsigned int thisrelocs = 0;
411           bfd_size_type thissize = 0;
412           if (p->type == bfd_indirect_link_order)
413             {
414               asection *sec;
415
416               sec = p->u.indirect.section;
417
418               if (info->strip == strip_none
419                   || info->strip == strip_some)
420                 thislines = sec->lineno_count;
421
422               if (info->relocatable)
423                 thisrelocs = sec->reloc_count;
424
425               if (sec->_cooked_size != 0)
426                 thissize = sec->_cooked_size;
427               else
428                 thissize = sec->_raw_size;
429
430             }
431           else if (info->relocatable
432                    && (p->type == bfd_section_reloc_link_order
433                        || p->type == bfd_symbol_reloc_link_order))
434             thisrelocs++;
435
436           if (l != NULL
437               && (thisrelocs + relocs >= config.split_by_reloc
438                   || thislines + lines >= config.split_by_reloc
439                   || thissize + sec_size >= config.split_by_file))
440             {
441               /* Create a new section and put this link order and the
442                  following link orders into it.  */
443               bfd_vma shift_offset;
444               asection *n;
445
446               n = clone_section (abfd, cursor, original_sec->name, &count);
447
448               /* Attach the link orders to the new section and snip
449                  them off from the old section.  */
450               n->link_order_head = p;
451               n->link_order_tail = cursor->link_order_tail;
452               cursor->link_order_tail = l;
453               l->next = NULL;
454               l = p;
455
456               /* Change the size of the original section and
457                  update the vma of the new one.  */
458
459               dump ("before snip", cursor, n);
460
461               shift_offset = p->offset;
462               if (cursor->_cooked_size != 0)
463                 {
464                   n->_cooked_size = cursor->_cooked_size - shift_offset;
465                   cursor->_cooked_size = shift_offset;
466                 }
467               n->_raw_size = cursor->_raw_size - shift_offset;
468               cursor->_raw_size = shift_offset;
469
470               vma += shift_offset;
471               n->lma = n->vma = vma;
472
473               /* Run down the chain and change the output section to
474                  the right one, update the offsets too.  */
475               do
476                 {
477                   p->offset -= shift_offset;
478                   if (p->type == bfd_indirect_link_order)
479                     {
480                       p->u.indirect.section->output_section = n;
481                       p->u.indirect.section->output_offset = p->offset;
482                     }
483                   p = p->next;
484                 }
485               while (p);
486
487               dump ("after snip", cursor, n);
488               cursor = n;
489               relocs = thisrelocs;
490               lines = thislines;
491               sec_size = thissize;
492             }
493           else
494             {
495               l = p;
496               relocs += thisrelocs;
497               lines += thislines;
498               sec_size += thissize;
499             }
500         }
501     }
502   sanity_check (abfd);
503 }
504
505 /* Call BFD to write out the linked file.  */
506
507 void
508 ldwrite (void)
509 {
510   /* Reset error indicator, which can typically something like invalid
511      format from opening up the .o files.  */
512   bfd_set_error (bfd_error_no_error);
513   lang_for_each_statement (build_link_order);
514
515   if (config.split_by_reloc != (unsigned) -1
516       || config.split_by_file != (bfd_size_type) -1)
517     split_sections (output_bfd, &link_info);
518   if (!bfd_final_link (output_bfd, &link_info))
519     {
520       /* If there was an error recorded, print it out.  Otherwise assume
521          an appropriate error message like unknown symbol was printed
522          out.  */
523
524       if (bfd_get_error () != bfd_error_no_error)
525         einfo (_("%F%P: final link failed: %E\n"));
526       else
527         xexit (1);
528     }
529 }