1# This shell script emits a C file. -*- C -*-
2#   Copyright (C) 2013-2016 Free Software Foundation, Inc.
3#
4# This file is part of GNU Binutils.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19# MA 02110-1301, USA.
20#
21
22# This file is sourced from elf32.em, and defines extra metagelf
23# specific routines. Taken from hppaelf.em.
24#
25fragment <<EOF
26
27#include "ldctor.h"
28#include "elf32-metag.h"
29
30
31/* Fake input file for stubs.  */
32static lang_input_statement_type *stub_file;
33
34/* Whether we need to call metag_layout_sections_again.  */
35static int need_laying_out = 0;
36
37/* Maximum size of a group of input sections that can be handled by
38   one stub section.  A value of +/-1 indicates the bfd back-end
39   should use a suitable default size.  */
40static bfd_signed_vma group_size = 1;
41
42/* This is called before the input files are opened.  We create a new
43   fake input file to hold the stub sections.  */
44
45static void
46metagelf_create_output_section_statements (void)
47{
48  extern const bfd_target metag_elf32_vec;
49
50  if (link_info.output_bfd->xvec != &metag_elf32_vec)
51    return;
52
53  stub_file = lang_add_input_file ("linker stubs",
54				   lang_input_file_is_fake_enum,
55				   NULL);
56  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
57  if (stub_file->the_bfd == NULL
58      || ! bfd_set_arch_mach (stub_file->the_bfd,
59			      bfd_get_arch (link_info.output_bfd),
60			      bfd_get_mach (link_info.output_bfd)))
61    {
62      einfo ("%X%P: can not create BFD %E\n");
63      return;
64    }
65
66  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
67  ldlang_add_file (stub_file);
68}
69
70
71struct hook_stub_info
72{
73  lang_statement_list_type add;
74  asection *input_section;
75};
76
77/* Traverse the linker tree to find the spot where the stub goes.  */
78
79static bfd_boolean
80hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
81{
82  lang_statement_union_type *l;
83  bfd_boolean ret;
84
85  for (; (l = *lp) != NULL; lp = &l->header.next)
86    {
87      switch (l->header.type)
88	{
89	case lang_constructors_statement_enum:
90	  ret = hook_in_stub (info, &constructor_list.head);
91	  if (ret)
92	    return ret;
93	  break;
94
95	case lang_output_section_statement_enum:
96	  ret = hook_in_stub (info,
97			      &l->output_section_statement.children.head);
98	  if (ret)
99	    return ret;
100	  break;
101
102	case lang_wild_statement_enum:
103	  ret = hook_in_stub (info, &l->wild_statement.children.head);
104	  if (ret)
105	    return ret;
106	  break;
107
108	case lang_group_statement_enum:
109	  ret = hook_in_stub (info, &l->group_statement.children.head);
110	  if (ret)
111	    return ret;
112	  break;
113
114	case lang_input_section_enum:
115	  if (l->input_section.section == info->input_section)
116	    {
117	      /* We've found our section.  Insert the stub immediately
118		 before its associated input section.  */
119	      *lp = info->add.head;
120	      *(info->add.tail) = l;
121	      return TRUE;
122	    }
123	  break;
124
125	case lang_data_statement_enum:
126	case lang_reloc_statement_enum:
127	case lang_object_symbols_statement_enum:
128	case lang_output_statement_enum:
129	case lang_target_statement_enum:
130	case lang_input_statement_enum:
131	case lang_assignment_statement_enum:
132	case lang_padding_statement_enum:
133	case lang_address_statement_enum:
134	case lang_fill_statement_enum:
135	  break;
136
137	default:
138	  FAIL ();
139	  break;
140	}
141    }
142  return FALSE;
143}
144
145
146/* Call-back for elf_metag_size_stubs.  */
147
148/* Create a new stub section, and arrange for it to be linked
149   immediately before INPUT_SECTION.  */
150
151static asection *
152metagelf_add_stub_section (const char *stub_sec_name, asection *input_section)
153{
154  asection *stub_sec;
155  flagword flags;
156  asection *output_section;
157  lang_output_section_statement_type *os;
158  struct hook_stub_info info;
159
160  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
161	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
162  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
163						 stub_sec_name, flags);
164  if (stub_sec == NULL)
165    goto err_ret;
166
167  output_section = input_section->output_section;
168  os = lang_output_section_get (output_section);
169
170  info.input_section = input_section;
171  lang_list_init (&info.add);
172  lang_add_section (&info.add, stub_sec, NULL, os);
173
174  if (info.add.head == NULL)
175    goto err_ret;
176
177  if (hook_in_stub (&info, &os->children.head))
178    return stub_sec;
179
180 err_ret:
181  einfo ("%X%P: can not make stub section: %E\n");
182  return NULL;
183}
184
185
186/* Another call-back for elf_metag_size_stubs.  */
187
188static void
189metagelf_layout_sections_again (void)
190{
191  /* If we have changed sizes of the stub sections, then we need
192     to recalculate all the section offsets.  This may mean we need to
193     add even more stubs.  */
194  gld${EMULATION_NAME}_map_segments (TRUE);
195  need_laying_out = -1;
196}
197
198
199static void
200build_section_lists (lang_statement_union_type *statement)
201{
202  if (statement->header.type == lang_input_section_enum)
203    {
204      asection *i = statement->input_section.section;
205
206      if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
207	  && (i->flags & SEC_EXCLUDE) == 0
208	  && i->output_section != NULL
209	  && i->output_section->owner == link_info.output_bfd)
210	{
211	  elf_metag_next_input_section (&link_info, i);
212	}
213    }
214}
215
216
217/* For Meta we use this opportunity to build linker stubs.  */
218
219static void
220gld${EMULATION_NAME}_after_allocation (void)
221{
222  int ret;
223
224  /* bfd_elf_discard_info just plays with data and debugging sections,
225     ie. doesn't affect code size, so we can delay resizing the
226     sections.  It's likely we'll resize everything in the process of
227     adding stubs.  */
228  ret = bfd_elf_discard_info (link_info.output_bfd, &link_info);
229  if (ret < 0)
230    {
231      einfo ("%X%P: .eh_frame/.stab edit: %E\n");
232      return;
233    }
234  else if (ret > 0)
235    need_laying_out = 1;
236
237  /* If generating a relocatable output file, then we don't
238     have to examine the relocs.  */
239  if (stub_file != NULL && !bfd_link_relocatable (&link_info))
240    {
241      ret = elf_metag_setup_section_lists (link_info.output_bfd, &link_info);
242      if (ret != 0)
243	{
244	  if (ret < 0)
245	    {
246	      einfo ("%X%P: can not size stub section: %E\n");
247	      return;
248	    }
249
250	  lang_for_each_statement (build_section_lists);
251
252	  /* Call into the BFD backend to do the real work.  */
253	  if (! elf_metag_size_stubs (link_info.output_bfd,
254				      stub_file->the_bfd,
255				      &link_info,
256				      group_size,
257				      &metagelf_add_stub_section,
258				      &metagelf_layout_sections_again))
259	    {
260	      einfo ("%X%P: can not size stub section: %E\n");
261	      return;
262	    }
263	}
264    }
265
266  if (need_laying_out != -1)
267    gld${EMULATION_NAME}_map_segments (need_laying_out);
268
269  if (!bfd_link_relocatable (&link_info))
270    {
271      /* Now build the linker stubs.  */
272      if (stub_file != NULL && stub_file->the_bfd->sections != NULL)
273	{
274	  if (! elf_metag_build_stubs (&link_info))
275	    einfo ("%X%P: can not build stubs: %E\n");
276	}
277    }
278}
279
280
281/* Avoid processing the fake stub_file in vercheck, stat_needed and
282   check_needed routines.  */
283
284static void (*real_func) (lang_input_statement_type *);
285
286static void metag_for_each_input_file_wrapper (lang_input_statement_type *l)
287{
288  if (l != stub_file)
289    (*real_func) (l);
290}
291
292static void
293metag_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
294{
295  real_func = func;
296  lang_for_each_input_file (&metag_for_each_input_file_wrapper);
297}
298
299#define lang_for_each_input_file metag_lang_for_each_input_file
300
301EOF
302
303# Define some shell vars to insert bits of code into the standard elf
304# parse_args and list_options functions.
305#
306PARSE_AND_LIST_PROLOGUE='
307#define OPTION_STUBGROUP_SIZE		301
308'
309
310PARSE_AND_LIST_LONGOPTS='
311  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
312'
313
314PARSE_AND_LIST_OPTIONS='
315  fprintf (file, _("\
316  --stub-group-size=N         Maximum size of a group of input sections that\n\
317                                can be handled by one stub section.  A negative\n\
318                                value locates all stubs before their branches\n\
319                                (with a group size of -N), while a positive\n\
320                                value allows two groups of input sections, one\n\
321                                before, and one after each stub section.\n\
322                                Values of +/-1 indicate the linker should\n\
323                                choose suitable defaults.\n"
324		   ));
325'
326
327PARSE_AND_LIST_ARGS_CASES='
328    case OPTION_STUBGROUP_SIZE:
329      {
330	const char *end;
331        group_size = bfd_scan_vma (optarg, &end, 0);
332        if (*end)
333	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
334      }
335      break;
336'
337
338# Put these extra metagelf routines in ld_${EMULATION_NAME}_emulation
339#
340LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
341LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=metagelf_create_output_section_statements
342