1# This shell script emits a C file. -*- C -*-
2#   Copyright (C) 2009-2016 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 elf32.em, and defines extra aarch64-elf
23# specific routines.
24#
25fragment <<EOF
26
27#include "ldctor.h"
28#include "elf/aarch64.h"
29
30static int no_enum_size_warning = 0;
31static int no_wchar_size_warning = 0;
32static int pic_veneer = 0;
33static int fix_erratum_835769 = 0;
34static int fix_erratum_843419 = 0;
35static int no_apply_dynamic_relocs = 0;
36
37static void
38gld${EMULATION_NAME}_before_parse (void)
39{
40#ifndef TARGET_			/* I.e., if not generic.  */
41  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
42#endif /* not TARGET_ */
43  input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
44  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
45  config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
46}
47
48static void
49aarch64_elf_before_allocation (void)
50{
51  /* We should be able to set the size of the interworking stub section.  We
52     can't do it until later if we have dynamic sections, though.  */
53  if (! elf_hash_table (&link_info)->dynamic_sections_created)
54    {
55      /* Here we rummage through the found bfds to collect information.  */
56      LANG_FOR_EACH_INPUT_STATEMENT (is)
57	{
58          /* Initialise mapping tables for code/data.  */
59          bfd_elf${ELFSIZE}_aarch64_init_maps (is->the_bfd);
60	}
61    }
62
63  /* Call the standard elf routine.  */
64  gld${EMULATION_NAME}_before_allocation ();
65}
66
67/* Fake input file for stubs.  */
68static lang_input_statement_type *stub_file;
69
70/* Whether we need to call gldarm_layout_sections_again.  */
71static int need_laying_out = 0;
72
73/* Maximum size of a group of input sections that can be handled by
74   one stub section.  A value of +/-1 indicates the bfd back-end
75   should use a suitable default size.  */
76static bfd_signed_vma group_size = 1;
77
78struct hook_stub_info
79{
80  lang_statement_list_type add;
81  asection *input_section;
82};
83
84/* Traverse the linker tree to find the spot where the stub goes.  */
85
86static bfd_boolean
87hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
88{
89  lang_statement_union_type *l;
90  bfd_boolean ret;
91
92  for (; (l = *lp) != NULL; lp = &l->header.next)
93    {
94      switch (l->header.type)
95	{
96	case lang_constructors_statement_enum:
97	  ret = hook_in_stub (info, &constructor_list.head);
98	  if (ret)
99	    return ret;
100	  break;
101
102	case lang_output_section_statement_enum:
103	  ret = hook_in_stub (info,
104			      &l->output_section_statement.children.head);
105	  if (ret)
106	    return ret;
107	  break;
108
109	case lang_wild_statement_enum:
110	  ret = hook_in_stub (info, &l->wild_statement.children.head);
111	  if (ret)
112	    return ret;
113	  break;
114
115	case lang_group_statement_enum:
116	  ret = hook_in_stub (info, &l->group_statement.children.head);
117	  if (ret)
118	    return ret;
119	  break;
120
121	case lang_input_section_enum:
122	  if (l->input_section.section == info->input_section)
123	    {
124	      /* We've found our section.  Insert the stub immediately
125		 after its associated input section.  */
126	      *(info->add.tail) = l->header.next;
127	      l->header.next = info->add.head;
128	      return TRUE;
129	    }
130	  break;
131
132	case lang_data_statement_enum:
133	case lang_reloc_statement_enum:
134	case lang_object_symbols_statement_enum:
135	case lang_output_statement_enum:
136	case lang_target_statement_enum:
137	case lang_input_statement_enum:
138	case lang_assignment_statement_enum:
139	case lang_padding_statement_enum:
140	case lang_address_statement_enum:
141	case lang_fill_statement_enum:
142	  break;
143
144	default:
145	  FAIL ();
146	  break;
147	}
148    }
149  return FALSE;
150}
151
152
153/* Call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
154
155/* Create a new stub section, and arrange for it to be linked
156   immediately after INPUT_SECTION.  */
157
158static asection *
159elf${ELFSIZE}_aarch64_add_stub_section (const char *stub_sec_name,
160					asection *input_section)
161{
162  asection *stub_sec;
163  flagword flags;
164  asection *output_section;
165  lang_output_section_statement_type *os;
166  struct hook_stub_info info;
167
168  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
169	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
170  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
171						 stub_sec_name, flags);
172  if (stub_sec == NULL)
173    goto err_ret;
174
175  bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 2);
176
177  output_section = input_section->output_section;
178  os = lang_output_section_get (output_section);
179
180  info.input_section = input_section;
181  lang_list_init (&info.add);
182  lang_add_section (&info.add, stub_sec, NULL, os);
183
184  if (info.add.head == NULL)
185    goto err_ret;
186
187  if (hook_in_stub (&info, &os->children.head))
188    return stub_sec;
189
190 err_ret:
191  einfo ("%X%P: can not make stub section: %E\n");
192  return NULL;
193}
194
195/* Another call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
196
197static void
198gldaarch64_layout_sections_again (void)
199{
200  /* If we have changed sizes of the stub sections, then we need
201     to recalculate all the section offsets.  This may mean we need to
202     add even more stubs.  */
203  gld${EMULATION_NAME}_map_segments (TRUE);
204  need_laying_out = -1;
205}
206
207static void
208build_section_lists (lang_statement_union_type *statement)
209{
210  if (statement->header.type == lang_input_section_enum)
211    {
212      asection *i = statement->input_section.section;
213
214      if (!((lang_input_statement_type *) i->owner->usrdata)->flags.just_syms
215	  && (i->flags & SEC_EXCLUDE) == 0
216	  && i->output_section != NULL
217	  && i->output_section->owner == link_info.output_bfd)
218	elf${ELFSIZE}_aarch64_next_input_section (& link_info, i);
219    }
220}
221
222static void
223gld${EMULATION_NAME}_after_allocation (void)
224{
225  int ret;
226
227  /* bfd_elf32_discard_info just plays with debugging sections,
228     ie. doesn't affect any code, so we can delay resizing the
229     sections.  It's likely we'll resize everything in the process of
230     adding stubs.  */
231  ret = bfd_elf_discard_info (link_info.output_bfd, & link_info);
232  if (ret < 0)
233    {
234      einfo ("%X%P: .eh_frame/.stab edit: %E\n");
235      return;
236    }
237  else if (ret > 0)
238    need_laying_out = 1;
239
240  /* If generating a relocatable output file, then we don't
241     have to examine the relocs.  */
242  if (stub_file != NULL && !bfd_link_relocatable (&link_info))
243    {
244      ret = elf${ELFSIZE}_aarch64_setup_section_lists (link_info.output_bfd,
245						       &link_info);
246      if (ret != 0)
247	{
248	  if (ret < 0)
249	    {
250	      einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
251	      return;
252	    }
253
254	  lang_for_each_statement (build_section_lists);
255
256	  /* Call into the BFD backend to do the real work.  */
257	  if (! elf${ELFSIZE}_aarch64_size_stubs (link_info.output_bfd,
258					  stub_file->the_bfd,
259					  & link_info,
260					  group_size,
261					  & elf${ELFSIZE}_aarch64_add_stub_section,
262					  & gldaarch64_layout_sections_again))
263	    {
264	      einfo ("%X%P: cannot size stub section: %E\n");
265	      return;
266	    }
267	}
268    }
269
270  if (need_laying_out != -1)
271    gld${EMULATION_NAME}_map_segments (need_laying_out);
272}
273
274static void
275gld${EMULATION_NAME}_finish (void)
276{
277  if (!bfd_link_relocatable (&link_info))
278    {
279      /* Now build the linker stubs.  */
280      if (stub_file->the_bfd->sections != NULL)
281	{
282	  if (! elf${ELFSIZE}_aarch64_build_stubs (& link_info))
283	    einfo ("%X%P: can not build stubs: %E\n");
284	}
285    }
286
287  finish_default ();
288}
289
290/* This is a convenient point to tell BFD about target specific flags.
291   After the output has been created, but before inputs are read.  */
292static void
293aarch64_elf_create_output_section_statements (void)
294{
295  if (strstr (bfd_get_target (link_info.output_bfd), "aarch64") == NULL)
296    {
297      /* The arm backend needs special fields in the output hash structure.
298	 These will only be created if the output format is an arm format,
299	 hence we do not support linking and changing output formats at the
300	 same time.  Use a link followed by objcopy to change output formats.  */
301      einfo ("%F%X%P: error: Cannot change output format whilst linking AArch64 binaries.\n");
302      return;
303    }
304
305  bfd_elf${ELFSIZE}_aarch64_set_options (link_info.output_bfd, &link_info,
306				 no_enum_size_warning,
307				 no_wchar_size_warning,
308				 pic_veneer,
309				 fix_erratum_835769, fix_erratum_843419,
310				 no_apply_dynamic_relocs);
311
312  stub_file = lang_add_input_file ("linker stubs",
313				   lang_input_file_is_fake_enum,
314				   NULL);
315  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
316  if (stub_file->the_bfd == NULL
317      || ! bfd_set_arch_mach (stub_file->the_bfd,
318			      bfd_get_arch (link_info.output_bfd),
319			      bfd_get_mach (link_info.output_bfd)))
320    {
321      einfo ("%X%P: can not create BFD %E\n");
322      return;
323    }
324
325  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
326  ldlang_add_file (stub_file);
327}
328
329/* Avoid processing the fake stub_file in vercheck, stat_needed and
330   check_needed routines.  */
331
332static void (*real_func) (lang_input_statement_type *);
333
334static void aarch64_for_each_input_file_wrapper (lang_input_statement_type *l)
335{
336  if (l != stub_file)
337    (*real_func) (l);
338}
339
340static void
341aarch64_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
342{
343  real_func = func;
344  lang_for_each_input_file (&aarch64_for_each_input_file_wrapper);
345}
346
347#define lang_for_each_input_file aarch64_lang_for_each_input_file
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", no_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"
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 can be\n\
385                           handled by one stub section.  A negative value\n\
386                           locates all stubs after their branches (with a\n\
387                           group size of -N), while a positive value allows\n\
388                           two groups of input sections, one before, and one\n\
389                           after each stub section.  Values of +/-1 indicate\n\
390                           the linker should choose suitable defaults.\n"
391		   ));
392  fprintf (file, _("  --fix-cortex-a53-835769      Fix erratum 835769\n"));
393  fprintf (file, _("  --fix-cortex-a53-843419      Fix erratum 843419\n"));
394  fprintf (file, _("  --no-apply-dynamic-relocs	   Do not apply link-time values for dynamic relocations\n"));
395'
396
397PARSE_AND_LIST_ARGS_CASES='
398    case '\'p\'':
399      /* Only here for backwards compatibility.  */
400      break;
401
402    case OPTION_NO_ENUM_SIZE_WARNING:
403      no_enum_size_warning = 1;
404      break;
405
406    case OPTION_NO_WCHAR_SIZE_WARNING:
407      no_wchar_size_warning = 1;
408      break;
409
410    case OPTION_PIC_VENEER:
411      pic_veneer = 1;
412      break;
413
414    case OPTION_FIX_ERRATUM_835769:
415      fix_erratum_835769 = 1;
416      break;
417
418    case OPTION_FIX_ERRATUM_843419:
419      fix_erratum_843419 = 1;
420      break;
421
422    case OPTION_NO_APPLY_DYNAMIC_RELOCS:
423      no_apply_dynamic_relocs = 1;
424      break;
425
426    case OPTION_STUBGROUP_SIZE:
427      {
428	const char *end;
429
430        group_size = bfd_scan_vma (optarg, &end, 0);
431        if (*end)
432	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
433      }
434      break;
435'
436
437# We have our own before_allocation etc. functions, but they call
438# the standard routines, so give them a different name.
439LDEMUL_BEFORE_ALLOCATION=aarch64_elf_before_allocation
440LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
441LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=aarch64_elf_create_output_section_statements
442
443# Replace the elf before_parse function with our own.
444LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
445
446# Call the extra arm-elf function
447LDEMUL_FINISH=gld${EMULATION_NAME}_finish
448