xref: /netbsd-src/external/gpl3/binutils/dist/ld/emultempl/aarch64elf.em (revision c64d4171c6f912972428361000d29636c687d68b)
1# This shell script emits a C file. -*- C -*-
2#   Copyright (C) 2009-2022 Free Software Foundation, Inc.
3#   Contributed by ARM Ltd.
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; see the file COPYING3. If not,
19# see <http://www.gnu.org/licenses/>.
20#
21
22# This file is sourced from elf.em, and defines extra aarch64-elf
23# specific routines.
24#
25fragment <<EOF
26
27#include "ldctor.h"
28#include "elf/aarch64.h"
29#include "elfxx-aarch64.h"
30
31static int no_enum_size_warning = 0;
32static int no_wchar_size_warning = 0;
33static int pic_veneer = 0;
34static int fix_erratum_835769 = 0;
35static erratum_84319_opts fix_erratum_843419 = ERRAT_NONE;
36static int no_apply_dynamic_relocs = 0;
37static aarch64_plt_type plt_type = PLT_NORMAL;
38static aarch64_enable_bti_type bti_type = BTI_NONE;
39
40static void
41gld${EMULATION_NAME}_before_parse (void)
42{
43#ifndef TARGET_			/* I.e., if not generic.  */
44  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
45#endif /* not TARGET_ */
46  input_flags.dynamic = ${DYNAMIC_LINK-true};
47  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
48  config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo true ; else echo false ; fi`;
49  link_info.check_relocs_after_open_input = true;
50EOF
51if test -n "$COMMONPAGESIZE"; then
52fragment <<EOF
53  link_info.relro = DEFAULT_LD_Z_RELRO;
54EOF
55fi
56fragment <<EOF
57  link_info.separate_code = DEFAULT_LD_Z_SEPARATE_CODE;
58  link_info.warn_execstack = DEFAULT_LD_WARN_EXECSTACK;
59  link_info.no_warn_rwx_segments = ! DEFAULT_LD_WARN_RWX_SEGMENTS;
60  link_info.default_execstack = DEFAULT_LD_EXECSTACK;
61}
62
63static void
64aarch64_elf_before_allocation (void)
65{
66  /* We should be able to set the size of the interworking stub section.  We
67     can't do it until later if we have dynamic sections, though.  */
68  if (! elf_hash_table (&link_info)->dynamic_sections_created)
69    {
70      /* Here we rummage through the found bfds to collect information.  */
71      LANG_FOR_EACH_INPUT_STATEMENT (is)
72      {
73	/* Initialise mapping tables for code/data.  */
74	bfd_elf${ELFSIZE}_aarch64_init_maps (is->the_bfd);
75      }
76    }
77
78  /* Call the standard elf routine.  */
79  gld${EMULATION_NAME}_before_allocation ();
80}
81
82/* Fake input file for stubs.  */
83static lang_input_statement_type *stub_file;
84
85/* Whether we need to call gldarm_layout_sections_again.  */
86static int need_laying_out = 0;
87
88/* Maximum size of a group of input sections that can be handled by
89   one stub section.  A value of +/-1 indicates the bfd back-end
90   should use a suitable default size.  */
91static bfd_signed_vma group_size = 1;
92
93struct hook_stub_info
94{
95  lang_statement_list_type add;
96  asection *input_section;
97};
98
99/* Traverse the linker tree to find the spot where the stub goes.  */
100
101static bool
102hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
103{
104  lang_statement_union_type *l;
105  bool ret;
106
107  for (; (l = *lp) != NULL; lp = &l->header.next)
108    {
109      switch (l->header.type)
110	{
111	case lang_constructors_statement_enum:
112	  ret = hook_in_stub (info, &constructor_list.head);
113	  if (ret)
114	    return ret;
115	  break;
116
117	case lang_output_section_statement_enum:
118	  ret = hook_in_stub (info,
119			      &l->output_section_statement.children.head);
120	  if (ret)
121	    return ret;
122	  break;
123
124	case lang_wild_statement_enum:
125	  ret = hook_in_stub (info, &l->wild_statement.children.head);
126	  if (ret)
127	    return ret;
128	  break;
129
130	case lang_group_statement_enum:
131	  ret = hook_in_stub (info, &l->group_statement.children.head);
132	  if (ret)
133	    return ret;
134	  break;
135
136	case lang_input_section_enum:
137	  if (l->input_section.section == info->input_section)
138	    {
139	      /* We've found our section.  Insert the stub immediately
140		 after its associated input section.  */
141	      *(info->add.tail) = l->header.next;
142	      l->header.next = info->add.head;
143	      return true;
144	    }
145	  break;
146
147	case lang_data_statement_enum:
148	case lang_reloc_statement_enum:
149	case lang_object_symbols_statement_enum:
150	case lang_output_statement_enum:
151	case lang_target_statement_enum:
152	case lang_input_statement_enum:
153	case lang_assignment_statement_enum:
154	case lang_padding_statement_enum:
155	case lang_address_statement_enum:
156	case lang_fill_statement_enum:
157	  break;
158
159	default:
160	  FAIL ();
161	  break;
162	}
163    }
164  return false;
165}
166
167
168/* Call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
169
170/* Create a new stub section, and arrange for it to be linked
171   immediately after INPUT_SECTION.  */
172
173static asection *
174elf${ELFSIZE}_aarch64_add_stub_section (const char *stub_sec_name,
175					asection *input_section)
176{
177  asection *stub_sec;
178  flagword flags;
179  asection *output_section;
180  lang_output_section_statement_type *os;
181  struct hook_stub_info info;
182
183  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
184	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
185  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
186						 stub_sec_name, flags);
187  if (stub_sec == NULL)
188    goto err_ret;
189
190  /* Long branch stubs contain a 64-bit address, so the section requires
191     8 byte alignment.  */
192  bfd_set_section_alignment (stub_sec, 3);
193
194  output_section = input_section->output_section;
195  os = lang_output_section_get (output_section);
196
197  info.input_section = input_section;
198  lang_list_init (&info.add);
199  lang_add_section (&info.add, stub_sec, NULL, NULL, os);
200
201  if (info.add.head == NULL)
202    goto err_ret;
203
204  if (hook_in_stub (&info, &os->children.head))
205    return stub_sec;
206
207 err_ret:
208  einfo (_("%X%P: can not make stub section: %E\n"));
209  return NULL;
210}
211
212/* Another call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
213
214static void
215gldaarch64_layout_sections_again (void)
216{
217  /* If we have changed sizes of the stub sections, then we need
218     to recalculate all the section offsets.  This may mean we need to
219     add even more stubs.  */
220  ldelf_map_segments (true);
221  need_laying_out = -1;
222}
223
224static void
225build_section_lists (lang_statement_union_type *statement)
226{
227  if (statement->header.type == lang_input_section_enum)
228    {
229      asection *i = statement->input_section.section;
230
231      if (!bfd_input_just_syms (i->owner)
232	  && (i->flags & SEC_EXCLUDE) == 0
233	  && i->output_section != NULL
234	  && i->output_section->owner == link_info.output_bfd)
235	elf${ELFSIZE}_aarch64_next_input_section (& link_info, i);
236    }
237}
238
239static void
240gld${EMULATION_NAME}_after_allocation (void)
241{
242  int ret;
243
244  /* bfd_elf32_discard_info just plays with debugging sections,
245     ie. doesn't affect any code, so we can delay resizing the
246     sections.  It's likely we'll resize everything in the process of
247     adding stubs.  */
248  ret = bfd_elf_discard_info (link_info.output_bfd, & link_info);
249  if (ret < 0)
250    {
251      einfo (_("%X%P: .eh_frame/.stab edit: %E\n"));
252      return;
253    }
254  else if (ret > 0)
255    need_laying_out = 1;
256
257  /* If generating a relocatable output file, then we don't
258     have to examine the relocs.  */
259  if (stub_file != NULL && !bfd_link_relocatable (&link_info))
260    {
261      ret = elf${ELFSIZE}_aarch64_setup_section_lists (link_info.output_bfd,
262						       &link_info);
263      if (ret != 0)
264	{
265	  if (ret < 0)
266	    {
267	      einfo (_("%X%P: could not compute sections lists "
268		       "for stub generation: %E\n"));
269	      return;
270	    }
271
272	  lang_for_each_statement (build_section_lists);
273
274	  /* Call into the BFD backend to do the real work.  */
275	  if (! elf${ELFSIZE}_aarch64_size_stubs (link_info.output_bfd,
276					  stub_file->the_bfd,
277					  & link_info,
278					  group_size,
279					  & elf${ELFSIZE}_aarch64_add_stub_section,
280					  & gldaarch64_layout_sections_again))
281	    {
282	      einfo (_("%X%P: can not size stub section: %E\n"));
283	      return;
284	    }
285	}
286    }
287
288  if (need_laying_out != -1)
289    ldelf_map_segments (need_laying_out);
290}
291
292static void
293gld${EMULATION_NAME}_finish (void)
294{
295  if (!bfd_link_relocatable (&link_info))
296    {
297      /* Now build the linker stubs.  */
298      if (stub_file->the_bfd->sections != NULL)
299	{
300	  if (! elf${ELFSIZE}_aarch64_build_stubs (& link_info))
301	    einfo (_("%X%P: can not build stubs: %E\n"));
302	}
303    }
304
305  finish_default ();
306}
307
308/* This is a convenient point to tell BFD about target specific flags.
309   After the output has been created, but before inputs are read.  */
310static void
311aarch64_elf_create_output_section_statements (void)
312{
313  if (strstr (bfd_get_target (link_info.output_bfd), "aarch64") == NULL)
314    {
315      /* The arm backend needs special fields in the output hash structure.
316	 These will only be created if the output format is an arm format,
317	 hence we do not support linking and changing output formats at the
318	 same time.  Use a link followed by objcopy to change output formats.  */
319      einfo (_("%F%P: error: cannot change output format "
320	       "whilst linking %s binaries\n"), "AArch64");
321      return;
322    }
323
324  aarch64_bti_pac_info bp_info;
325  bp_info.plt_type = plt_type;
326  bp_info.bti_type = bti_type;
327
328  bfd_elf${ELFSIZE}_aarch64_set_options (link_info.output_bfd, &link_info,
329				 no_enum_size_warning,
330				 no_wchar_size_warning,
331				 pic_veneer,
332				 fix_erratum_835769, fix_erratum_843419,
333				 no_apply_dynamic_relocs,
334				 bp_info);
335
336  stub_file = lang_add_input_file ("linker stubs",
337				   lang_input_file_is_fake_enum,
338				   NULL);
339  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
340  if (stub_file->the_bfd == NULL
341      || ! bfd_set_arch_mach (stub_file->the_bfd,
342			      bfd_get_arch (link_info.output_bfd),
343			      bfd_get_mach (link_info.output_bfd)))
344    {
345      einfo (_("%F%P: can not create BFD: %E\n"));
346      return;
347    }
348
349  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
350  ldlang_add_file (stub_file);
351}
352
353EOF
354
355# Define some shell vars to insert bits of code into the standard elf
356# parse_args and list_options functions.
357#
358PARSE_AND_LIST_PROLOGUE='
359#define OPTION_NO_ENUM_SIZE_WARNING	309
360#define OPTION_PIC_VENEER		310
361#define OPTION_STUBGROUP_SIZE		311
362#define OPTION_NO_WCHAR_SIZE_WARNING	312
363#define OPTION_FIX_ERRATUM_835769	313
364#define OPTION_FIX_ERRATUM_843419	314
365#define OPTION_NO_APPLY_DYNAMIC_RELOCS	315
366'
367
368PARSE_AND_LIST_SHORTOPTS=p
369
370PARSE_AND_LIST_LONGOPTS='
371  { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
372  { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
373  { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
374  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
375  { "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
376  { "fix-cortex-a53-835769", no_argument, NULL, OPTION_FIX_ERRATUM_835769},
377  { "fix-cortex-a53-843419", optional_argument, NULL, OPTION_FIX_ERRATUM_843419},
378  { "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS},
379'
380
381PARSE_AND_LIST_OPTIONS='
382  fprintf (file, _("  --no-enum-size-warning      Don'\''t warn about objects with incompatible\n"
383		   "                                enum sizes\n"));
384  fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible\n"
385		   "                                wchar_t sizes\n"));
386  fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
387  fprintf (file, _("\
388  --stub-group-size=N         Maximum size of a group of input sections that\n\
389                                can be handled by one stub section.  A negative\n\
390                                value locates all stubs after their branches\n\
391                                (with a group size of -N), while a positive\n\
392                                value allows two groups of input sections, one\n\
393                                before, and one after each stub section.\n\
394                                Values of +/-1 indicate the linker should\n\
395                                choose suitable defaults.\n"));
396  fprintf (file, _("  --fix-cortex-a53-835769      Fix erratum 835769\n"));
397  fprintf (file, _("\
398  --fix-cortex-a53-843419[=full|adr|adrp]      Fix erratum 843419 and optionally specify which workaround to use.\n\
399                                               full (default): Use both ADRP and ADR workaround, this will \n\
400                                                 increase the size of your binaries.\n\
401                                               adr: Only use the ADR workaround, this will not cause any increase\n\
402                                                 in binary size but linking will fail if the referenced address is\n\
403                                                 out of range of an ADR instruction.  This will remove the need of using\n\
404                                                 a veneer and results in both performance and size benefits.\n\
405                                               adrp: Use only the ADRP workaround, this will never rewrite your ADRP\n\
406                                                 instruction into an ADR.  As such the workaround will always use a\n\
407                                                 veneer and this will give you both a performance and size overhead.\n"));
408  fprintf (file, _("  --no-apply-dynamic-relocs    Do not apply link-time values for dynamic relocations\n"));
409  fprintf (file, _("  -z force-bti                  Turn on Branch Target Identification mechanism and generate PLTs with BTI. Generate warnings for missing BTI on inputs\n"));
410  fprintf (file, _("  -z pac-plt                    Protect PLTs with Pointer Authentication.\n"));
411'
412
413PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
414      else if (strcmp (optarg, "force-bti") == 0)
415	{
416	  plt_type |= PLT_BTI;
417	  bti_type = BTI_WARN;
418	}
419      else if (strcmp (optarg, "pac-plt") == 0)
420	plt_type |= PLT_PAC;
421'
422PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_AARCH64"
423
424PARSE_AND_LIST_ARGS_CASES='
425    case '\'p\'':
426      /* Only here for backwards compatibility.  */
427      break;
428
429    case OPTION_NO_ENUM_SIZE_WARNING:
430      no_enum_size_warning = 1;
431      break;
432
433    case OPTION_NO_WCHAR_SIZE_WARNING:
434      no_wchar_size_warning = 1;
435      break;
436
437    case OPTION_PIC_VENEER:
438      pic_veneer = 1;
439      break;
440
441    case OPTION_FIX_ERRATUM_835769:
442      fix_erratum_835769 = 1;
443      break;
444
445    case OPTION_FIX_ERRATUM_843419:
446      fix_erratum_843419 = ERRAT_ADR | ERRAT_ADRP;
447      if (optarg && *optarg)
448	{
449	  if (strcmp ("full", optarg) == 0)
450	    fix_erratum_843419 = ERRAT_ADR | ERRAT_ADRP;
451	  else if (strcmp ("adrp", optarg) == 0)
452	    fix_erratum_843419 = ERRAT_ADRP;
453	  else if (strcmp ("adr", optarg) == 0)
454	    fix_erratum_843419 = ERRAT_ADR;
455	  else
456	    einfo (_("%P: error: unrecognized option for "
457		     "--fix-cortex-a53-843419: %s\n"), optarg);
458	}
459      break;
460
461    case OPTION_NO_APPLY_DYNAMIC_RELOCS:
462      no_apply_dynamic_relocs = 1;
463      break;
464
465    case OPTION_STUBGROUP_SIZE:
466      {
467	const char *end;
468
469	group_size = bfd_scan_vma (optarg, &end, 0);
470	if (*end)
471	  einfo (_("%F%P: invalid number `%s'\''\n"), optarg);
472      }
473      break;
474'
475
476# We have our own before_allocation etc. functions, but they call
477# the standard routines, so give them a different name.
478LDEMUL_BEFORE_ALLOCATION=aarch64_elf_before_allocation
479LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
480LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=aarch64_elf_create_output_section_statements
481
482# Replace the elf before_parse function with our own.
483LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
484
485# Call the extra arm-elf function
486LDEMUL_FINISH=gld${EMULATION_NAME}_finish
487