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