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 287

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 166 khays
        link_order->u.data.size = link_order->size;
187 145 khays
      }
188
      break;
189
 
190
    case lang_reloc_statement_enum:
191
      {
192
        lang_reloc_statement_type *rs;
193
        asection *output_section;
194
        struct bfd_link_order *link_order;
195
 
196
        rs = &statement->reloc_statement;
197
 
198
        output_section = rs->output_section;
199
        ASSERT (output_section->owner == link_info.output_bfd);
200
 
201
        if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
202
              || ((output_section->flags & SEC_LOAD) != 0
203
                  && (output_section->flags & SEC_THREAD_LOCAL))))
204
          break;
205
 
206
        link_order = bfd_new_link_order (link_info.output_bfd, output_section);
207
        if (link_order == NULL)
208
          einfo (_("%P%F: bfd_new_link_order failed\n"));
209
 
210
        link_order->offset = rs->output_offset;
211
        link_order->size = bfd_get_reloc_size (rs->howto);
212
 
213
        link_order->u.reloc.p = (struct bfd_link_order_reloc *)
214
            xmalloc (sizeof (struct bfd_link_order_reloc));
215
 
216
        link_order->u.reloc.p->reloc = rs->reloc;
217
        link_order->u.reloc.p->addend = rs->addend_value;
218
 
219
        if (rs->name == NULL)
220
          {
221
            link_order->type = bfd_section_reloc_link_order;
222
            if (rs->section->owner == link_info.output_bfd)
223
              link_order->u.reloc.p->u.section = rs->section;
224
            else
225
              {
226
                link_order->u.reloc.p->u.section = rs->section->output_section;
227
                link_order->u.reloc.p->addend += rs->section->output_offset;
228
              }
229
          }
230
        else
231
          {
232
            link_order->type = bfd_symbol_reloc_link_order;
233
            link_order->u.reloc.p->u.name = rs->name;
234
          }
235
      }
236
      break;
237
 
238
    case lang_input_section_enum:
239
      {
240
        /* Create a new link_order in the output section with this
241
           attached */
242
        asection *i = statement->input_section.section;
243
 
244
        if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
245
            && (i->flags & SEC_EXCLUDE) == 0)
246
          {
247
            asection *output_section = i->output_section;
248
            struct bfd_link_order *link_order;
249
 
250
            ASSERT (output_section->owner == link_info.output_bfd);
251
 
252
            if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
253
                  || ((output_section->flags & SEC_LOAD) != 0
254
                      && (output_section->flags & SEC_THREAD_LOCAL))))
255
              break;
256
 
257
            link_order = bfd_new_link_order (link_info.output_bfd,
258
                                             output_section);
259
 
260
            if ((i->flags & SEC_NEVER_LOAD) != 0
261
                && (i->flags & SEC_DEBUGGING) == 0)
262
              {
263
                /* We've got a never load section inside one which is
264
                   going to be output, we'll change it into a fill.  */
265
                link_order->type = bfd_data_link_order;
266
                link_order->u.data.contents = (unsigned char *) "";
267
                link_order->u.data.size = 1;
268
              }
269
            else
270
              {
271
                link_order->type = bfd_indirect_link_order;
272
                link_order->u.indirect.section = i;
273
                ASSERT (i->output_section == output_section);
274
              }
275
            link_order->size = i->size;
276
            link_order->offset = i->output_offset;
277
          }
278
      }
279
      break;
280
 
281
    case lang_padding_statement_enum:
282
      /* Make a new link_order with the right filler */
283
      {
284
        asection *output_section;
285
        struct bfd_link_order *link_order;
286
 
287
        output_section = statement->padding_statement.output_section;
288
        ASSERT (statement->padding_statement.output_section->owner
289
                == link_info.output_bfd);
290
 
291
        if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
292
              || ((output_section->flags & SEC_LOAD) != 0
293
                  && (output_section->flags & SEC_THREAD_LOCAL))))
294
          break;
295
 
296
        link_order = bfd_new_link_order (link_info.output_bfd,
297
                                         output_section);
298
        link_order->type = bfd_data_link_order;
299
        link_order->size = statement->padding_statement.size;
300
        link_order->offset = statement->padding_statement.output_offset;
301
        link_order->u.data.contents = statement->padding_statement.fill->data;
302
        link_order->u.data.size = statement->padding_statement.fill->size;
303
      }
304
      break;
305
 
306
    default:
307
      /* All the other ones fall through */
308
      break;
309
    }
310
}
311
 
312
/* Return true if NAME is the name of an unsplittable section. These
313
   are the stabs strings, dwarf strings.  */
314
 
315
static bfd_boolean
316
unsplittable_name (const char *name)
317
{
318
  if (CONST_STRNEQ (name, ".stab"))
319
    {
320
      /* There are several stab like string sections. We pattern match on
321
         ".stab...str"  */
322
      unsigned len = strlen (name);
323
      if (strcmp (&name[len-3], "str") == 0)
324
        return TRUE;
325
    }
326
  else if (strcmp (name, "$GDB_STRINGS$") == 0)
327
    return TRUE;
328
  return FALSE;
329
}
330
 
331
/* Wander around the input sections, make sure that
332
   we'll never try and create an output section with more relocs
333
   than will fit.. Do this by always assuming the worst case, and
334
   creating new output sections with all the right bits.  */
335
#define TESTIT 1
336
static asection *
337
clone_section (bfd *abfd, asection *s, const char *name, int *count)
338
{
339
  char *tname;
340
  char *sname;
341
  unsigned int len;
342
  asection *n;
343
  struct bfd_link_hash_entry *h;
344
 
345
  /* Invent a section name from the section name and a dotted numeric
346
     suffix.   */
347
  len = strlen (name);
348
  tname = (char *) xmalloc (len + 1);
349
  memcpy (tname, name, len + 1);
350
  /* Remove a dotted number suffix, from a previous split link. */
351
  while (len && ISDIGIT (tname[len-1]))
352
    len--;
353
  if (len > 1 && tname[len-1] == '.')
354
    /* It was a dotted number. */
355
    tname[len-1] = 0;
356
 
357
  /* We want to use the whole of the original section name for the
358
     split name, but coff can be restricted to 8 character names.  */
359
  if (bfd_family_coff (abfd) && strlen (tname) > 5)
360
    {
361
      /* Some section names cannot be truncated, as the name is
362
         used to locate some other section.  */
363
      if (CONST_STRNEQ (name, ".stab")
364
          || strcmp (name, "$GDB_SYMBOLS$") == 0)
365
        {
366
          einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
367
          /* Silence gcc warnings.  einfo exits, so we never reach here.  */
368
          return NULL;
369
        }
370
      tname[5] = 0;
371
    }
372
 
373
  if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
374
      || (n = bfd_make_section_anyway (abfd, sname)) == NULL
375
      || (h = bfd_link_hash_lookup (link_info.hash,
376
                                    sname, TRUE, TRUE, FALSE)) == NULL)
377
    {
378
      einfo (_("%F%P: clone section failed: %E\n"));
379
      /* Silence gcc warnings.  einfo exits, so we never reach here.  */
380
      return NULL;
381
    }
382
  free (tname);
383
 
384
  /* Set up section symbol.  */
385
  h->type = bfd_link_hash_defined;
386
  h->u.def.value = 0;
387
  h->u.def.section = n;
388
 
389
  n->flags = s->flags;
390
  n->vma = s->vma;
391
  n->user_set_vma = s->user_set_vma;
392
  n->lma = s->lma;
393
  n->size = 0;
394
  n->output_offset = s->output_offset;
395
  n->output_section = n;
396
  n->orelocation = 0;
397
  n->reloc_count = 0;
398
  n->alignment_power = s->alignment_power;
399
 
400
  bfd_copy_private_section_data (abfd, s, abfd, n);
401
 
402
  return n;
403
}
404
 
405
#if TESTING
406
static void
407
ds (asection *s)
408
{
409
  struct bfd_link_order *l = s->map_head.link_order;
410
  printf ("vma %x size %x\n", s->vma, s->size);
411
  while (l)
412
    {
413
      if (l->type == bfd_indirect_link_order)
414
        {
415
          printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
416
        }
417
      else
418
        {
419
          printf (_("%8x something else\n"), l->offset);
420
        }
421
      l = l->next;
422
    }
423
  printf ("\n");
424
}
425
 
426
dump (char *s, asection *a1, asection *a2)
427
{
428
  printf ("%s\n", s);
429
  ds (a1);
430
  ds (a2);
431
}
432
 
433
static void
434
sanity_check (bfd *abfd)
435
{
436
  asection *s;
437
  for (s = abfd->sections; s; s = s->next)
438
    {
439
      struct bfd_link_order *p;
440
      bfd_vma prev = 0;
441
      for (p = s->map_head.link_order; p; p = p->next)
442
        {
443
          if (p->offset > 100000)
444
            abort ();
445
          if (p->offset < prev)
446
            abort ();
447
          prev = p->offset;
448
        }
449
    }
450
}
451
#else
452
#define sanity_check(a)
453
#define dump(a, b, c)
454
#endif
455
 
456
static void
457
split_sections (bfd *abfd, struct bfd_link_info *info)
458
{
459
  asection *original_sec;
460
  int nsecs = abfd->section_count;
461
  sanity_check (abfd);
462
  /* Look through all the original sections.  */
463
  for (original_sec = abfd->sections;
464
       original_sec && nsecs;
465
       original_sec = original_sec->next, nsecs--)
466
    {
467
      int count = 0;
468
      unsigned int lines = 0;
469
      unsigned int relocs = 0;
470
      bfd_size_type sec_size = 0;
471
      struct bfd_link_order *l;
472
      struct bfd_link_order *p;
473
      bfd_vma vma = original_sec->vma;
474
      asection *cursor = original_sec;
475
 
476
      /* Count up the relocations and line entries to see if anything
477
         would be too big to fit.  Accumulate section size too.  */
478
      for (l = NULL, p = cursor->map_head.link_order; p != NULL; p = l->next)
479
        {
480
          unsigned int thislines = 0;
481
          unsigned int thisrelocs = 0;
482
          bfd_size_type thissize = 0;
483
          if (p->type == bfd_indirect_link_order)
484
            {
485
              asection *sec;
486
 
487
              sec = p->u.indirect.section;
488
 
489
              if (info->strip == strip_none
490
                  || info->strip == strip_some)
491
                thislines = sec->lineno_count;
492
 
493
              if (info->relocatable)
494
                thisrelocs = sec->reloc_count;
495
 
496
              thissize = sec->size;
497
 
498
            }
499
          else if (info->relocatable
500
                   && (p->type == bfd_section_reloc_link_order
501
                       || p->type == bfd_symbol_reloc_link_order))
502
            thisrelocs++;
503
 
504
          if (l != NULL
505
              && (thisrelocs + relocs >= config.split_by_reloc
506
                  || thislines + lines >= config.split_by_reloc
507
                  || (thissize + sec_size >= config.split_by_file))
508
              && !unsplittable_name (cursor->name))
509
            {
510
              /* Create a new section and put this link order and the
511
                 following link orders into it.  */
512
              bfd_vma shift_offset;
513
              asection *n;
514
 
515
              n = clone_section (abfd, cursor, original_sec->name, &count);
516
 
517
              /* Attach the link orders to the new section and snip
518
                 them off from the old section.  */
519
              n->map_head.link_order = p;
520
              n->map_tail.link_order = cursor->map_tail.link_order;
521
              cursor->map_tail.link_order = l;
522
              l->next = NULL;
523
              l = p;
524
 
525
              /* Change the size of the original section and
526
                 update the vma of the new one.  */
527
 
528
              dump ("before snip", cursor, n);
529
 
530
              shift_offset = p->offset;
531
              n->size = cursor->size - shift_offset;
532
              cursor->size = shift_offset;
533
 
534
              vma += shift_offset;
535
              n->lma = n->vma = vma;
536
 
537
              /* Run down the chain and change the output section to
538
                 the right one, update the offsets too.  */
539
              do
540
                {
541
                  p->offset -= shift_offset;
542
                  if (p->type == bfd_indirect_link_order)
543
                    {
544
                      p->u.indirect.section->output_section = n;
545
                      p->u.indirect.section->output_offset = p->offset;
546
                    }
547
                  p = p->next;
548
                }
549
              while (p);
550
 
551
              dump ("after snip", cursor, n);
552
              cursor = n;
553
              relocs = thisrelocs;
554
              lines = thislines;
555
              sec_size = thissize;
556
            }
557
          else
558
            {
559
              l = p;
560
              relocs += thisrelocs;
561
              lines += thislines;
562
              sec_size += thissize;
563
            }
564
        }
565
    }
566
  sanity_check (abfd);
567
}
568
 
569
/* Call BFD to write out the linked file.  */
570
 
571
void
572
ldwrite (void)
573
{
574
  /* Reset error indicator, which can typically something like invalid
575
     format from opening up the .o files.  */
576
  bfd_set_error (bfd_error_no_error);
577
  lang_for_each_statement (build_link_order);
578
 
579
  if (config.split_by_reloc != (unsigned) -1
580
      || config.split_by_file != (bfd_size_type) -1)
581
    split_sections (link_info.output_bfd, &link_info);
582
  if (!bfd_final_link (link_info.output_bfd, &link_info))
583
    {
584
      /* If there was an error recorded, print it out.  Otherwise assume
585
         an appropriate error message like unknown symbol was printed
586
         out.  */
587
 
588
      if (bfd_get_error () != bfd_error_no_error)
589
        einfo (_("%F%P: final link failed: %E\n"));
590
      else
591
        xexit (1);
592
    }
593
}

powered by: WebSVN 2.1.0

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