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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [ld/] [emultempl/] [ppc64elf.em] - Blame information for rev 853

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

Line No. Rev Author Line
1 205 julius
# This shell script emits a C file. -*- C -*-
2
# Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3
# Free Software Foundation, Inc.
4
#
5
# This file is part of the GNU Binutils.
6
#
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
# MA 02110-1301, USA.
21
#
22
 
23
# This file is sourced from elf32.em, and defines extra powerpc64-elf
24
# specific routines.
25
#
26
fragment <
27
 
28
#include "ldctor.h"
29
#include "libbfd.h"
30
#include "elf-bfd.h"
31
#include "elf64-ppc.h"
32
 
33
/* Fake input file for stubs.  */
34
static lang_input_statement_type *stub_file;
35
static int stub_added = 0;
36
 
37
/* Whether we need to call ppc_layout_sections_again.  */
38
static int need_laying_out = 0;
39
 
40
/* Maximum size of a group of input sections that can be handled by
41
   one stub section.  A value of +/-1 indicates the bfd back-end
42
   should use a suitable default size.  */
43
static bfd_signed_vma group_size = 1;
44
 
45
/* Whether to add ".foo" entries for each "foo" in a version script.  */
46
static int dotsyms = 1;
47
 
48
/* Whether to run tls optimization.  */
49
static int no_tls_opt = 0;
50
static int no_tls_get_addr_opt = 0;
51
 
52
/* Whether to run opd optimization.  */
53
static int no_opd_opt = 0;
54
 
55
/* Whether to run toc optimization.  */
56
static int no_toc_opt = 0;
57
 
58
/* Whether to allow multiple toc sections.  */
59
static int no_multi_toc = 0;
60
 
61
/* Whether to emit symbols for stubs.  */
62
static int emit_stub_syms = -1;
63
 
64
static asection *toc_section = 0;
65
 
66
/* Whether to canonicalize .opd so that there are no overlapping
67
   .opd entries.  */
68
static int non_overlapping_opd = 0;
69
 
70
/* This is called before the input files are opened.  We create a new
71
   fake input file to hold the stub sections.  */
72
 
73
static void
74
ppc_create_output_section_statements (void)
75
{
76
  if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
77
        && elf_object_id (link_info.output_bfd) == PPC64_ELF_TDATA))
78
    return;
79
 
80
  link_info.wrap_char = '.';
81
 
82
  stub_file = lang_add_input_file ("linker stubs",
83
                                   lang_input_file_is_fake_enum,
84
                                   NULL);
85
  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
86
  if (stub_file->the_bfd == NULL
87
      || !bfd_set_arch_mach (stub_file->the_bfd,
88
                             bfd_get_arch (link_info.output_bfd),
89
                             bfd_get_mach (link_info.output_bfd)))
90
    {
91
      einfo ("%F%P: can not create BFD %E\n");
92
      return;
93
    }
94
 
95
  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
96
  ldlang_add_file (stub_file);
97
  ppc64_elf_init_stub_bfd (stub_file->the_bfd, &link_info);
98
}
99
 
100
static void
101
ppc_before_allocation (void)
102
{
103
  if (stub_file != NULL)
104
    {
105
      if (!no_opd_opt
106
          && !ppc64_elf_edit_opd (link_info.output_bfd, &link_info,
107
                                  non_overlapping_opd))
108
        einfo ("%X%P: can not edit %s %E\n", "opd");
109
 
110
      if (ppc64_elf_tls_setup (link_info.output_bfd, &link_info,
111
                               no_tls_get_addr_opt)
112
          && !no_tls_opt)
113
        {
114
          /* Size the sections.  This is premature, but we want to know the
115
             TLS segment layout so that certain optimizations can be done.  */
116
          expld.phase = lang_mark_phase_enum;
117
          expld.dataseg.phase = exp_dataseg_none;
118
          one_lang_size_sections_pass (NULL, TRUE);
119
 
120
          if (!ppc64_elf_tls_optimize (link_info.output_bfd, &link_info))
121
            einfo ("%X%P: TLS problem %E\n");
122
 
123
          /* We must not cache anything from the preliminary sizing.  */
124
          lang_reset_memory_regions ();
125
        }
126
 
127
      if (!no_toc_opt
128
          && !link_info.relocatable
129
          && !ppc64_elf_edit_toc (link_info.output_bfd, &link_info))
130
        einfo ("%X%P: can not edit %s %E\n", "toc");
131
    }
132
 
133
  gld${EMULATION_NAME}_before_allocation ();
134
}
135
 
136
struct hook_stub_info
137
{
138
  lang_statement_list_type add;
139
  asection *input_section;
140
};
141
 
142
/* Traverse the linker tree to find the spot where the stub goes.  */
143
 
144
static bfd_boolean
145
hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
146
{
147
  lang_statement_union_type *l;
148
  bfd_boolean ret;
149
 
150
  for (; (l = *lp) != NULL; lp = &l->header.next)
151
    {
152
      switch (l->header.type)
153
        {
154
        case lang_constructors_statement_enum:
155
          ret = hook_in_stub (info, &constructor_list.head);
156
          if (ret)
157
            return ret;
158
          break;
159
 
160
        case lang_output_section_statement_enum:
161
          ret = hook_in_stub (info,
162
                              &l->output_section_statement.children.head);
163
          if (ret)
164
            return ret;
165
          break;
166
 
167
        case lang_wild_statement_enum:
168
          ret = hook_in_stub (info, &l->wild_statement.children.head);
169
          if (ret)
170
            return ret;
171
          break;
172
 
173
        case lang_group_statement_enum:
174
          ret = hook_in_stub (info, &l->group_statement.children.head);
175
          if (ret)
176
            return ret;
177
          break;
178
 
179
        case lang_input_section_enum:
180
          if (l->input_section.section == info->input_section)
181
            {
182
              /* We've found our section.  Insert the stub immediately
183
                 before its associated input section.  */
184
              *lp = info->add.head;
185
              *(info->add.tail) = l;
186
              return TRUE;
187
            }
188
          break;
189
 
190
        case lang_data_statement_enum:
191
        case lang_reloc_statement_enum:
192
        case lang_object_symbols_statement_enum:
193
        case lang_output_statement_enum:
194
        case lang_target_statement_enum:
195
        case lang_input_statement_enum:
196
        case lang_assignment_statement_enum:
197
        case lang_padding_statement_enum:
198
        case lang_address_statement_enum:
199
        case lang_fill_statement_enum:
200
          break;
201
 
202
        default:
203
          FAIL ();
204
          break;
205
        }
206
    }
207
  return FALSE;
208
}
209
 
210
 
211
/* Call-back for ppc64_elf_size_stubs.  */
212
 
213
/* Create a new stub section, and arrange for it to be linked
214
   immediately before INPUT_SECTION.  */
215
 
216
static asection *
217
ppc_add_stub_section (const char *stub_sec_name, asection *input_section)
218
{
219
  asection *stub_sec;
220
  flagword flags;
221
  asection *output_section;
222
  const char *secname;
223
  lang_output_section_statement_type *os;
224
  struct hook_stub_info info;
225
 
226
  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
227
           | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
228
  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
229
                                                 stub_sec_name, flags);
230
  if (stub_sec == NULL)
231
    goto err_ret;
232
 
233
  output_section = input_section->output_section;
234
  secname = bfd_get_section_name (output_section->owner, output_section);
235
  os = lang_output_section_find (secname);
236
 
237
  info.input_section = input_section;
238
  lang_list_init (&info.add);
239
  lang_add_section (&info.add, stub_sec, os);
240
 
241
  if (info.add.head == NULL)
242
    goto err_ret;
243
 
244
  stub_added = 1;
245
  if (hook_in_stub (&info, &os->children.head))
246
    return stub_sec;
247
 
248
 err_ret:
249
  einfo ("%X%P: can not make stub section: %E\n");
250
  return NULL;
251
}
252
 
253
 
254
/* Another call-back for ppc64_elf_size_stubs.  */
255
 
256
static void
257
ppc_layout_sections_again (void)
258
{
259
  /* If we have changed sizes of the stub sections, then we need
260
     to recalculate all the section offsets.  This may mean we need to
261
     add even more stubs.  */
262
  gld${EMULATION_NAME}_map_segments (TRUE);
263
 
264
  if (!link_info.relocatable)
265
    _bfd_set_gp_value (link_info.output_bfd,
266
                       ppc64_elf_toc (link_info.output_bfd));
267
 
268
  need_laying_out = -1;
269
}
270
 
271
 
272
static void
273
build_toc_list (lang_statement_union_type *statement)
274
{
275
  if (statement->header.type == lang_input_section_enum)
276
    {
277
      asection *i = statement->input_section.section;
278
 
279
      if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
280
          && (i->flags & SEC_EXCLUDE) == 0
281
          && i->output_section == toc_section)
282
        ppc64_elf_next_toc_section (&link_info, i);
283
    }
284
}
285
 
286
 
287
static void
288
build_section_lists (lang_statement_union_type *statement)
289
{
290
  if (statement->header.type == lang_input_section_enum)
291
    {
292
      asection *i = statement->input_section.section;
293
 
294
      if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
295
          && (i->flags & SEC_EXCLUDE) == 0
296
          && i->output_section != NULL
297
          && i->output_section->owner == link_info.output_bfd)
298
        {
299
          if (!ppc64_elf_next_input_section (&link_info, i))
300
            einfo ("%X%P: can not size stub section: %E\n");
301
        }
302
    }
303
}
304
 
305
 
306
/* Call the back-end function to set TOC base after we have placed all
307
   the sections.  */
308
static void
309
gld${EMULATION_NAME}_after_allocation (void)
310
{
311
  /* bfd_elf_discard_info just plays with data and debugging sections,
312
     ie. doesn't affect code size, so we can delay resizing the
313
     sections.  It's likely we'll resize everything in the process of
314
     adding stubs.  */
315
  if (bfd_elf_discard_info (link_info.output_bfd, &link_info))
316
    need_laying_out = 1;
317
 
318
  /* If generating a relocatable output file, then we don't have any
319
     stubs.  */
320
  if (stub_file != NULL && !link_info.relocatable)
321
    {
322
      int ret = ppc64_elf_setup_section_lists (link_info.output_bfd,
323
                                               &link_info,
324
                                               no_multi_toc);
325
      if (ret < 0)
326
        einfo ("%X%P: can not size stub section: %E\n");
327
      else if (ret > 0)
328
        {
329
          toc_section = bfd_get_section_by_name (link_info.output_bfd, ".got");
330
          if (toc_section != NULL)
331
            lang_for_each_statement (build_toc_list);
332
 
333
          ppc64_elf_reinit_toc (link_info.output_bfd, &link_info);
334
 
335
          lang_for_each_statement (build_section_lists);
336
 
337
          /* Call into the BFD backend to do the real work.  */
338
          if (!ppc64_elf_size_stubs (link_info.output_bfd,
339
                                     &link_info,
340
                                     group_size,
341
                                     &ppc_add_stub_section,
342
                                     &ppc_layout_sections_again))
343
            einfo ("%X%P: can not size stub section: %E\n");
344
        }
345
    }
346
 
347
  if (need_laying_out != -1)
348
    {
349
      gld${EMULATION_NAME}_map_segments (need_laying_out);
350
 
351
      if (!link_info.relocatable)
352
        _bfd_set_gp_value (link_info.output_bfd,
353
                           ppc64_elf_toc (link_info.output_bfd));
354
    }
355
}
356
 
357
 
358
/* Final emulation specific call.  */
359
 
360
static void
361
gld${EMULATION_NAME}_finish (void)
362
{
363
  /* e_entry on PowerPC64 points to the function descriptor for
364
     _start.  If _start is missing, default to the first function
365
     descriptor in the .opd section.  */
366
  entry_section = ".opd";
367
 
368
  if (link_info.relocatable)
369
    {
370
      asection *toc = bfd_get_section_by_name (link_info.output_bfd, ".toc");
371
      if (toc != NULL
372
          && bfd_section_size (link_info.output_bfd, toc) > 0x10000)
373
        einfo ("%X%P: TOC section size exceeds 64k\n");
374
    }
375
 
376
  if (stub_added)
377
    {
378
      char *msg = NULL;
379
      char *line, *endline;
380
 
381
      if (emit_stub_syms < 0)
382
        emit_stub_syms = 1;
383
      if (!ppc64_elf_build_stubs (emit_stub_syms, &link_info,
384
                                  config.stats ? &msg : NULL))
385
        einfo ("%X%P: can not build stubs: %E\n");
386
 
387
      for (line = msg; line != NULL; line = endline)
388
        {
389
          endline = strchr (line, '\n');
390
          if (endline != NULL)
391
            *endline++ = '\0';
392
          fprintf (stderr, "%s: %s\n", program_name, line);
393
        }
394
      if (msg != NULL)
395
        free (msg);
396
    }
397
 
398
  ppc64_elf_restore_symbols (&link_info);
399
  finish_default ();
400
}
401
 
402
 
403
/* Add a pattern matching ".foo" for every "foo" in a version script.
404
 
405
   The reason for doing this is that many shared library version
406
   scripts export a selected set of functions or data symbols, forcing
407
   others local.  eg.
408
 
409
   . VERS_1 {
410
   .       global:
411
   .               this; that; some; thing;
412
   .       local:
413
   .               *;
414
   .   };
415
 
416
   To make the above work for PowerPC64, we need to export ".this",
417
   ".that" and so on, otherwise only the function descriptor syms are
418
   exported.  Lack of an exported function code sym may cause a
419
   definition to be pulled in from a static library.  */
420
 
421
static struct bfd_elf_version_expr *
422
gld${EMULATION_NAME}_new_vers_pattern (struct bfd_elf_version_expr *entry)
423
{
424
  struct bfd_elf_version_expr *dot_entry;
425
  unsigned int len;
426
  char *dot_pat;
427
 
428
  if (!dotsyms
429
      || entry->pattern[0] == '.'
430
      || (!entry->literal && entry->pattern[0] == '*'))
431
    return entry;
432
 
433
  dot_entry = xmalloc (sizeof *dot_entry);
434
  *dot_entry = *entry;
435
  dot_entry->next = entry;
436
  len = strlen (entry->pattern) + 2;
437
  dot_pat = xmalloc (len);
438
  dot_pat[0] = '.';
439
  memcpy (dot_pat + 1, entry->pattern, len - 1);
440
  dot_entry->pattern = dot_pat;
441
  return dot_entry;
442
}
443
 
444
 
445
/* Avoid processing the fake stub_file in vercheck, stat_needed and
446
   check_needed routines.  */
447
 
448
static void (*real_func) (lang_input_statement_type *);
449
 
450
static void ppc_for_each_input_file_wrapper (lang_input_statement_type *l)
451
{
452
  if (l != stub_file)
453
    (*real_func) (l);
454
}
455
 
456
static void
457
ppc_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
458
{
459
  real_func = func;
460
  lang_for_each_input_file (&ppc_for_each_input_file_wrapper);
461
}
462
 
463
#define lang_for_each_input_file ppc_lang_for_each_input_file
464
 
465
EOF
466
 
467
if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
468
  fragment <
469
/* Special handling for embedded SPU executables.  */
470
extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
471
static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *);
472
 
473
static bfd_boolean
474
ppc64_recognized_file (lang_input_statement_type *entry)
475
{
476
  if (embedded_spu_file (entry, "-m64"))
477
    return TRUE;
478
 
479
  return gld${EMULATION_NAME}_load_symbols (entry);
480
}
481
EOF
482
LDEMUL_RECOGNIZED_FILE=ppc64_recognized_file
483
fi
484
 
485
# Define some shell vars to insert bits of code into the standard elf
486
# parse_args and list_options functions.
487
#
488
PARSE_AND_LIST_PROLOGUE='
489
#define OPTION_STUBGROUP_SIZE           301
490
#define OPTION_STUBSYMS                 (OPTION_STUBGROUP_SIZE + 1)
491
#define OPTION_NO_STUBSYMS              (OPTION_STUBSYMS + 1)
492
#define OPTION_DOTSYMS                  (OPTION_NO_STUBSYMS + 1)
493
#define OPTION_NO_DOTSYMS               (OPTION_DOTSYMS + 1)
494
#define OPTION_NO_TLS_OPT               (OPTION_NO_DOTSYMS + 1)
495
#define OPTION_NO_TLS_GET_ADDR_OPT      (OPTION_NO_TLS_OPT + 1)
496
#define OPTION_NO_OPD_OPT               (OPTION_NO_TLS_GET_ADDR_OPT + 1)
497
#define OPTION_NO_TOC_OPT               (OPTION_NO_OPD_OPT + 1)
498
#define OPTION_NO_MULTI_TOC             (OPTION_NO_TOC_OPT + 1)
499
#define OPTION_NON_OVERLAPPING_OPD      (OPTION_NO_MULTI_TOC + 1)
500
'
501
 
502
PARSE_AND_LIST_LONGOPTS='
503
  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
504
  { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
505
  { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS },
506
  { "dotsyms", no_argument, NULL, OPTION_DOTSYMS },
507
  { "no-dotsyms", no_argument, NULL, OPTION_NO_DOTSYMS },
508
  { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
509
  { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
510
  { "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
511
  { "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
512
  { "no-multi-toc", no_argument, NULL, OPTION_NO_MULTI_TOC },
513
  { "non-overlapping-opd", no_argument, NULL, OPTION_NON_OVERLAPPING_OPD },
514
'
515
 
516
PARSE_AND_LIST_OPTIONS='
517
  fprintf (file, _("\
518
  --stub-group-size=N         Maximum size of a group of input sections that\n\
519
                                can be handled by one stub section.  A negative\n\
520
                                value locates all stubs before their branches\n\
521
                                (with a group size of -N), while a positive\n\
522
                                value allows two groups of input sections, one\n\
523
                                before, and one after each stub section.\n\
524
                                Values of +/-1 indicate the linker should\n\
525
                                choose suitable defaults.\n"
526
                   ));
527
  fprintf (file, _("\
528
  --emit-stub-syms            Label linker stubs with a symbol.\n"
529
                   ));
530
  fprintf (file, _("\
531
  --no-emit-stub-syms         Don'\''t label linker stubs with a symbol.\n"
532
                   ));
533
  fprintf (file, _("\
534
  --dotsyms                   For every version pattern \"foo\" in a version\n\
535
                                script, add \".foo\" so that function code\n\
536
                                symbols are treated the same as function\n\
537
                                descriptor symbols.  Defaults to on.\n"
538
                   ));
539
  fprintf (file, _("\
540
  --no-dotsyms                Don'\''t do anything special in version scripts.\n"
541
                   ));
542
  fprintf (file, _("\
543
  --no-tls-optimize           Don'\''t try to optimize TLS accesses.\n"
544
                   ));
545
  fprintf (file, _("\
546
  --no-tls-get-addr-optimize  Don'\''t use a special __tls_get_addr call.\n"
547
                   ));
548
  fprintf (file, _("\
549
  --no-opd-optimize           Don'\''t optimize the OPD section.\n"
550
                   ));
551
  fprintf (file, _("\
552
  --no-toc-optimize           Don'\''t optimize the TOC section.\n"
553
                   ));
554
  fprintf (file, _("\
555
  --no-multi-toc              Disallow automatic multiple toc sections.\n"
556
                   ));
557
  fprintf (file, _("\
558
  --non-overlapping-opd       Canonicalize .opd, so that there are no\n\
559
                                overlapping .opd entries.\n"
560
                   ));
561
'
562
 
563
PARSE_AND_LIST_ARGS_CASES='
564
    case OPTION_STUBGROUP_SIZE:
565
      {
566
        const char *end;
567
        group_size = bfd_scan_vma (optarg, &end, 0);
568
        if (*end)
569
          einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
570
      }
571
      break;
572
 
573
    case OPTION_STUBSYMS:
574
      emit_stub_syms = 1;
575
      break;
576
 
577
    case OPTION_NO_STUBSYMS:
578
      emit_stub_syms = 0;
579
      break;
580
 
581
    case OPTION_DOTSYMS:
582
      dotsyms = 1;
583
      break;
584
 
585
    case OPTION_NO_DOTSYMS:
586
      dotsyms = 0;
587
      break;
588
 
589
    case OPTION_NO_TLS_OPT:
590
      no_tls_opt = 1;
591
      break;
592
 
593
    case OPTION_NO_TLS_GET_ADDR_OPT:
594
      no_tls_get_addr_opt = 1;
595
      break;
596
 
597
    case OPTION_NO_OPD_OPT:
598
      no_opd_opt = 1;
599
      break;
600
 
601
    case OPTION_NO_TOC_OPT:
602
      no_toc_opt = 1;
603
      break;
604
 
605
    case OPTION_NO_MULTI_TOC:
606
      no_multi_toc = 1;
607
      break;
608
 
609
    case OPTION_NON_OVERLAPPING_OPD:
610
      non_overlapping_opd = 1;
611
      break;
612
'
613
 
614
# Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
615
#
616
LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
617
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
618
LDEMUL_FINISH=gld${EMULATION_NAME}_finish
619
LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements
620
LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern

powered by: WebSVN 2.1.0

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