1 # This shell script emits a C file. -*- C -*-
2 # Copyright (C) 2009-2025 Free Software Foundation, Inc.
3 # Contributed by Kalray Inc.
5 # This file is part of the GNU Binutils.
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.
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.
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/>.
22 # This file is sourced from elf32.em, and defines extra kvx-elf
29 #include "elfxx-kvx.h"
33 elf${ELFSIZE}_kvx_before_allocation (void)
36 if test x"${EMULATION_NAME}" != x"elf64kvx_linux"; then
38 if (bfd_link_pie (&link_info)) {
39 einfo (_("%F:%P: -pie not supported\n"));
45 /* Call the standard elf routine. */
46 gld${EMULATION_NAME}_before_allocation ();
51 /* Fake input file for stubs. */
52 static lang_input_statement_type *stub_file;
54 /* Whether we need to call gldarm_layout_sections_again. */
55 static int need_laying_out = 0;
57 /* Maximum size of a group of input sections that can be handled by
58 one stub section. A value of +/-1 indicates the bfd back-end
59 should use a suitable default size. */
60 static bfd_signed_vma group_size = -1;
64 lang_statement_list_type add;
65 asection *input_section;
68 /* Traverse the linker tree to find the spot where the stub goes. */
71 hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
73 lang_statement_union_type *l;
76 for (; (l = *lp) != NULL; lp = &l->header.next)
78 switch (l->header.type)
80 case lang_constructors_statement_enum:
81 ret = hook_in_stub (info, &constructor_list.head);
86 case lang_output_section_statement_enum:
87 ret = hook_in_stub (info,
88 &l->output_section_statement.children.head);
94 case lang_wild_statement_enum:
95 ret = hook_in_stub (info, &l->wild_statement.children.head);
100 case lang_group_statement_enum:
101 ret = hook_in_stub (info, &l->group_statement.children.head);
106 case lang_input_section_enum:
107 if (l->input_section.section == info->input_section)
109 /* We've found our section. Insert the stub immediately
110 after its associated input section. */
111 *(info->add.tail) = l->header.next;
112 l->header.next = info->add.head;
118 case lang_data_statement_enum:
119 case lang_reloc_statement_enum:
120 case lang_object_symbols_statement_enum:
121 case lang_output_statement_enum:
122 case lang_target_statement_enum:
123 case lang_input_statement_enum:
124 case lang_assignment_statement_enum:
125 case lang_padding_statement_enum:
126 case lang_address_statement_enum:
127 case lang_fill_statement_enum:
139 /* Call-back for elf${ELFSIZE}_kvx_size_stubs. */
141 /* Create a new stub section, and arrange for it to be linked
142 immediately after INPUT_SECTION. */
145 elf${ELFSIZE}_kvx_add_stub_section (const char *stub_sec_name,
146 asection *input_section)
150 asection *output_section;
151 lang_output_section_statement_type *os;
152 struct hook_stub_info info;
154 flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
155 | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
156 stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
157 stub_sec_name, flags);
158 if (stub_sec == NULL)
161 bfd_set_section_alignment (stub_sec, 2);
163 output_section = input_section->output_section;
164 os = lang_output_section_get (output_section);
166 info.input_section = input_section;
167 lang_list_init (&info.add);
168 lang_add_section (&info.add, stub_sec, NULL, NULL, os);
170 if (info.add.head == NULL)
173 if (hook_in_stub (&info, &os->children.head))
177 einfo ("%X%P: can not make stub section: %E\n");
181 /* Another call-back for elf${ELFSIZE}_kvx_size_stubs. */
184 gldkvx_layout_sections_again (void)
186 /* If we have changed sizes of the stub sections, then we need
187 to recalculate all the section offsets. This may mean we need to
188 add even more stubs. */
189 ldelf_map_segments (true);
190 need_laying_out = -1;
194 build_section_lists (lang_statement_union_type *statement)
196 if (statement->header.type == lang_input_section_enum)
198 asection *i = statement->input_section.section;
200 if (!((lang_input_statement_type *) i->owner->usrdata)->flags.just_syms
201 && (i->flags & SEC_EXCLUDE) == 0
202 && i->output_section != NULL
203 && i->output_section->owner == link_info.output_bfd)
204 elf${ELFSIZE}_kvx_next_input_section (& link_info, i);
209 gld${EMULATION_NAME}_after_allocation (void)
213 /* bfd_elf32_discard_info just plays with debugging sections,
214 ie. doesn't affect any code, so we can delay resizing the
215 sections. It's likely we'll resize everything in the process of
217 ret = bfd_elf_discard_info (link_info.output_bfd, & link_info);
220 einfo ("%X%P: .eh_frame/.stab edit: %E\n");
226 /* If generating a relocatable output file, then we don't
227 have to examine the relocs. */
228 if (stub_file != NULL && !bfd_link_relocatable (&link_info))
230 ret = elf${ELFSIZE}_kvx_setup_section_lists (link_info.output_bfd,
236 einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
240 lang_for_each_statement (build_section_lists);
242 /* Call into the BFD backend to do the real work. */
243 if (! elf${ELFSIZE}_kvx_size_stubs (link_info.output_bfd,
247 & elf${ELFSIZE}_kvx_add_stub_section,
248 & gldkvx_layout_sections_again))
250 einfo ("%X%P: cannot size stub section: %E\n");
256 if (need_laying_out != -1)
257 ldelf_map_segments (need_laying_out);
261 gld${EMULATION_NAME}_finish (void)
263 if (!bfd_link_relocatable (&link_info))
265 /* Now build the linker stubs. */
266 if (stub_file != NULL
267 && stub_file->the_bfd->sections != NULL)
269 if (! elf${ELFSIZE}_kvx_build_stubs (& link_info))
270 einfo ("%X%P: can not build stubs: %E\n");
277 /* This is a convenient point to tell BFD about target specific flags.
278 After the output has been created, but before inputs are read. */
280 kvx_elf_create_output_section_statements (void)
282 if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
283 && elf_object_id (link_info.output_bfd) == KVX_ELF_DATA))
286 stub_file = lang_add_input_file ("linker stubs",
287 lang_input_file_is_fake_enum,
289 stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
290 if (stub_file->the_bfd == NULL
291 || ! bfd_set_arch_mach (stub_file->the_bfd,
292 bfd_get_arch (link_info.output_bfd),
293 bfd_get_mach (link_info.output_bfd)))
295 einfo ("%X%P: can not create BFD %E\n");
299 stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
300 ldlang_add_file (stub_file);
302 if (!kvx_elf${ELFSIZE}_init_stub_bfd (&link_info, stub_file->the_bfd))
303 einfo ("%F%P: can not init BFD: %E\n");
307 #define lang_for_each_input_file kvx_lang_for_each_input_file
311 LDEMUL_BEFORE_ALLOCATION=elf${ELFSIZE}_kvx_before_allocation
312 LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
313 LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=kvx_elf_create_output_section_statements
315 # Call the extra arm-elf function
316 LDEMUL_FINISH=gld${EMULATION_NAME}_finish