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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [ld/] [emultempl/] [ppc64elf.em] - Blame information for rev 856

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

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