OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [ld/] [ldwrite.c] - Blame information for rev 612

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

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

powered by: WebSVN 2.1.0

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