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