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