xref: /netbsd-src/external/gpl3/binutils.old/dist/ld/emultempl/ppc32elf.em (revision 6db267571823ee3b0a1d61478df085a087f2e990)
1# This shell script emits a C file. -*- C -*-
2#   Copyright (C) 2003-2020 Free Software Foundation, Inc.
3#
4# This file is part of the GNU Binutils.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19# MA 02110-1301, USA.
20#
21
22# This file is sourced from elf.em, and defines extra powerpc32-elf
23# specific routines.
24#
25fragment <<EOF
26
27#include "elf32-ppc.h"
28#include "ldlex.h"
29#include "ldlang.h"
30
31#define is_ppc_elf(bfd) \
32  (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
33   && elf_object_id (bfd) == PPC32_ELF_DATA)
34
35/* Whether to run tls optimization.  */
36static int notlsopt = 0;
37
38/* Whether to convert inline PLT calls to direct.  */
39static int no_inline_opt = 0;
40
41/* Choose the correct place for .got.  */
42static int old_got = 0;
43
44static struct ppc_elf_params params = { PLT_UNSET, 0, -1,
45					0, 0, 0, 0, 0, 0, 0 };
46
47static void
48ppc_after_open_output (void)
49{
50  if (params.emit_stub_syms < 0)
51    params.emit_stub_syms = (link_info.emitrelocations
52			     || bfd_link_pic (&link_info));
53  if (params.pagesize == 0)
54    params.pagesize = config.commonpagesize;
55  ppc_elf_link_params (&link_info, &params);
56}
57
58EOF
59
60# No --secure-plt, --bss-plt, or --sdata-got for vxworks.
61if test -z "$VXWORKS_BASE_EM_FILE" ; then
62  fragment <<EOF
63static void
64ppc_after_check_relocs (void)
65{
66  if (is_ppc_elf (link_info.output_bfd))
67    {
68      int new_plt;
69      int keep_new;
70      unsigned int num_plt;
71      unsigned int num_got;
72      lang_output_section_statement_type *os;
73      lang_output_section_statement_type *plt_os[2];
74      lang_output_section_statement_type *got_os[2];
75
76      new_plt = ppc_elf_select_plt_layout (link_info.output_bfd, &link_info);
77      if (new_plt < 0)
78	einfo (_("%X%P: select_plt_layout problem %E\n"));
79
80      num_got = 0;
81      num_plt = 0;
82      for (os = (void *) lang_os_list.head;
83	   os != NULL;
84	   os = os->next)
85	{
86	  if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0)
87	    {
88	      if (num_plt < 2)
89		plt_os[num_plt] = os;
90	      ++num_plt;
91	    }
92	  if (os->constraint == SPECIAL && strcmp (os->name, ".got") == 0)
93	    {
94	      if (num_got < 2)
95		got_os[num_got] = os;
96	      ++num_got;
97	    }
98	}
99
100      keep_new = new_plt == 1 ? 0 : -1;
101      if (num_plt == 2)
102	{
103	  plt_os[0]->constraint = keep_new;
104	  plt_os[1]->constraint = ~keep_new;
105	}
106      if (num_got == 2)
107	{
108	  if (old_got)
109	    keep_new = -1;
110	  got_os[0]->constraint = keep_new;
111	  got_os[1]->constraint = ~keep_new;
112	}
113    }
114
115  after_check_relocs_default ();
116}
117
118EOF
119fi
120fragment <<EOF
121static void
122prelim_size_sections (void)
123{
124  if (expld.phase != lang_mark_phase_enum)
125    {
126      expld.phase = lang_mark_phase_enum;
127      expld.dataseg.phase = exp_seg_none;
128      one_lang_size_sections_pass (NULL, FALSE);
129      /* We must not cache anything from the preliminary sizing.  */
130      lang_reset_memory_regions ();
131    }
132}
133
134static void
135ppc_before_allocation (void)
136{
137  if (is_ppc_elf (link_info.output_bfd))
138    {
139      if (!no_inline_opt
140	  && !bfd_link_relocatable (&link_info))
141	{
142	  prelim_size_sections ();
143
144	  if (!ppc_elf_inline_plt (&link_info))
145	    einfo (_("%X%P: inline PLT: %E\n"));
146	}
147
148      if (ppc_elf_tls_setup (link_info.output_bfd, &link_info)
149	  && !notlsopt)
150	{
151	  if (!ppc_elf_tls_optimize (link_info.output_bfd, &link_info))
152	    {
153	      einfo (_("%X%P: TLS problem %E\n"));
154	      return;
155	    }
156	}
157    }
158
159  gld${EMULATION_NAME}_before_allocation ();
160
161  ppc_elf_maybe_strip_sdata_syms (&link_info);
162
163  if (RELAXATION_ENABLED)
164    params.branch_trampolines = 1;
165
166  /* Turn on relaxation if executable sections have addresses that
167     might make branches overflow.  */
168  else if (!RELAXATION_DISABLED_BY_USER)
169    {
170      bfd_vma low = (bfd_vma) -1;
171      bfd_vma high = 0;
172      asection *o;
173
174      /* Run lang_size_sections even if already done, so as to pick
175	 up gld${EMULATION_NAME}_before_allocation sizing.  This
176	 matters when we have an executable bss plt which will
177	 typically be laid out near the end of the image, ie. worst
178	 case for branches at the start of .text.  */
179      expld.phase = lang_first_phase_enum;
180      prelim_size_sections ();
181
182      for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
183	{
184	  if ((o->flags & (SEC_ALLOC | SEC_CODE)) != (SEC_ALLOC | SEC_CODE))
185	    continue;
186	  if (o->rawsize == 0)
187	    continue;
188	  if (low > o->vma)
189	    low = o->vma;
190	  if (high < o->vma + o->rawsize - 1)
191	    high = o->vma + o->rawsize - 1;
192	}
193      if (high > low && high - low > (1 << 25) - 1)
194	params.branch_trampolines = 1;
195    }
196
197  if (params.branch_trampolines
198      || params.ppc476_workaround
199      || params.pic_fixup > 0)
200    ENABLE_RELAXATION;
201}
202
203/* Replaces default zero fill padding in executable sections with
204   "ba 0" instructions.  This works around the ppc476 icache bug if we
205   have a function pointer tail call near the end of a page, some
206   small amount of padding, then the function called at the beginning
207   of the next page.  If the "ba 0" is ever executed we should hit a
208   segv, so it's almost as good as an illegal instruction (zero).  */
209
210static void
211no_zero_padding (lang_statement_union_type *l)
212{
213  if (l->header.type == lang_padding_statement_enum
214      && l->padding_statement.size != 0
215      && l->padding_statement.output_section != NULL
216      && (l->padding_statement.output_section->flags & SEC_CODE) != 0
217      && l->padding_statement.fill->size == 0)
218    {
219      struct _ppc_fill_type
220      {
221	size_t size;
222	unsigned char data[4];
223      };
224      static struct _ppc_fill_type fill_be = { 4, {0x48, 0, 0, 2} };
225      static struct _ppc_fill_type fill_le = { 4, {2, 0, 0, 0x48} };
226
227      if (bfd_big_endian (link_info.output_bfd))
228	l->padding_statement.fill = (struct _fill_type *) &fill_be;
229      else
230	l->padding_statement.fill = (struct _fill_type *) &fill_le;
231    }
232}
233
234static void
235ppc_finish (void)
236{
237  if (params.ppc476_workaround)
238    lang_for_each_statement (no_zero_padding);
239  if (!ppc_finish_symbols (&link_info))
240    einfo (_("%X%P: ppc_finish_symbols problem %E\n"));
241  finish_default ();
242}
243
244EOF
245
246if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
247  fragment <<EOF
248/* Special handling for embedded SPU executables.  */
249extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
250
251static bfd_boolean
252ppc_recognized_file (lang_input_statement_type *entry)
253{
254  if (embedded_spu_file (entry, "-m32"))
255    return TRUE;
256
257  return ldelf_load_symbols (entry);
258}
259
260EOF
261LDEMUL_RECOGNIZED_FILE=ppc_recognized_file
262fi
263
264# Define some shell vars to insert bits of code into the standard elf
265# parse_args and list_options functions.
266#
267PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}'
268enum ppc32_opt
269{
270  OPTION_NO_TLS_OPT = 321,
271  OPTION_NO_TLS_GET_ADDR_OPT,
272  OPTION_NEW_PLT,
273  OPTION_OLD_PLT,
274  OPTION_PLT_ALIGN,
275  OPTION_NO_PLT_ALIGN,
276  OPTION_NO_INLINE_OPT,
277  OPTION_OLD_GOT,
278  OPTION_STUBSYMS,
279  OPTION_NO_STUBSYMS,
280  OPTION_PPC476_WORKAROUND,
281  OPTION_NO_PPC476_WORKAROUND,
282  OPTION_NO_PICFIXUP,
283  OPTION_VLE_RELOC_FIXUP
284};
285'
286
287PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
288  { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
289  { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS },
290  { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
291  { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },'
292if test -z "$VXWORKS_BASE_EM_FILE" ; then
293  PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
294  { "secure-plt", no_argument, NULL, OPTION_NEW_PLT },
295  { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
296  { "plt-align", optional_argument, NULL, OPTION_PLT_ALIGN },
297  { "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN },
298  { "no-inline-optimize", no_argument, NULL, OPTION_NO_INLINE_OPT },
299  { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },'
300fi
301PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
302  { "ppc476-workaround", optional_argument, NULL, OPTION_PPC476_WORKAROUND },
303  { "no-ppc476-workaround", no_argument, NULL, OPTION_NO_PPC476_WORKAROUND },
304  { "no-pic-fixup", no_argument, NULL, OPTION_NO_PICFIXUP },
305  { "vle-reloc-fixup", no_argument, NULL, OPTION_VLE_RELOC_FIXUP },
306'
307
308PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
309  fprintf (file, _("\
310  --emit-stub-syms            Label linker stubs with a symbol\n"
311		   ));
312  fprintf (file, _("\
313  --no-emit-stub-syms         Don'\''t label linker stubs with a symbol\n"
314		   ));
315  fprintf (file, _("\
316  --no-tls-optimize           Don'\''t try to optimize TLS accesses\n"
317		   ));
318  fprintf (file, _("\
319  --no-tls-get-addr-optimize  Don'\''t use a special __tls_get_addr call\n"
320		   ));'
321if test -z "$VXWORKS_BASE_EM_FILE" ; then
322  PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'\
323  fprintf (file, _("\
324  --secure-plt                Use new-style PLT if possible\n"
325		   ));
326  fprintf (file, _("\
327  --bss-plt                   Force old-style BSS PLT\n"
328		   ));
329  fprintf (file, _("\
330  --plt-align                 Align PLT call stubs to fit cache lines\n"
331		   ));
332  fprintf (file, _("\
333  --no-plt-align              Dont'\''t align individual PLT call stubs\n"
334		   ));
335  fprintf (file, _("\
336  --no-inline-optimize        Don'\''t convert inline PLT to direct calls\n"
337		   ));
338  fprintf (file, _("\
339  --sdata-got                 Force GOT location just before .sdata\n"
340		   ));'
341fi
342PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'\
343  fprintf (file, _("\
344  --ppc476-workaround [=pagesize]\n\
345                              Avoid a cache bug on ppc476\n"
346		   ));
347  fprintf (file, _("\
348  --no-ppc476-workaround      Disable workaround\n"
349		   ));
350  fprintf (file, _("\
351  --no-pic-fixup              Don'\''t edit non-pic to pic\n"
352		   ));
353  fprintf (file, _("\
354  --vle-reloc-fixup           Correct old object file 16A/16D relocation\n"
355		   ));
356'
357
358PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
359    case OPTION_STUBSYMS:
360      params.emit_stub_syms = 1;
361      break;
362
363    case OPTION_NO_STUBSYMS:
364      params.emit_stub_syms = 0;
365      break;
366
367    case OPTION_NO_TLS_OPT:
368      notlsopt = 1;
369      break;
370
371    case OPTION_NO_TLS_GET_ADDR_OPT:
372      params.no_tls_get_addr_opt = 1;
373      break;
374
375    case OPTION_NEW_PLT:
376      params.plt_style = PLT_NEW;
377      break;
378
379    case OPTION_OLD_PLT:
380      params.plt_style = PLT_OLD;
381      break;
382
383    case OPTION_PLT_ALIGN:
384      if (optarg != NULL)
385	{
386	  char *end;
387	  unsigned long val = strtoul (optarg, &end, 0);
388	  if (*end || val > 5)
389	    einfo (_("%F%P: invalid --plt-align `%s'\''\n"), optarg);
390	  params.plt_stub_align = val;
391	}
392      else
393	params.plt_stub_align = 5;
394      break;
395
396    case OPTION_NO_PLT_ALIGN:
397      params.plt_stub_align = 0;
398      break;
399
400    case OPTION_NO_INLINE_OPT:
401      no_inline_opt = 1;
402      break;
403
404    case OPTION_OLD_GOT:
405      old_got = 1;
406      break;
407
408    case OPTION_TRADITIONAL_FORMAT:
409      notlsopt = 1;
410      params.no_tls_get_addr_opt = 1;
411      return FALSE;
412
413    case OPTION_PPC476_WORKAROUND:
414      params.ppc476_workaround = 1;
415      if (optarg != NULL)
416	{
417	  char *end;
418	  params.pagesize = strtoul (optarg, &end, 0);
419	  if (*end
420	      || (params.pagesize < 4096 && params.pagesize != 0)
421	      || params.pagesize != (params.pagesize & -params.pagesize))
422	    einfo (_("%F%P: invalid pagesize `%s'\''\n"), optarg);
423	}
424      break;
425
426    case OPTION_NO_PPC476_WORKAROUND:
427      params.ppc476_workaround = 0;
428      break;
429
430    case OPTION_NO_PICFIXUP:
431      params.pic_fixup = -1;
432      break;
433
434    case OPTION_VLE_RELOC_FIXUP:
435      params.vle_reloc_fixup = 1;
436      break;
437'
438
439# Put these extra ppc32elf routines in ld_${EMULATION_NAME}_emulation
440#
441LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_after_open_output
442if test -z "$VXWORKS_BASE_EM_FILE" ; then
443  LDEMUL_AFTER_CHECK_RELOCS=ppc_after_check_relocs
444fi
445LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
446LDEMUL_FINISH=ppc_finish
447