OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [ld/] [ldwrite.c] - Blame information for rev 146

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.