1# This shell script emits a C file. -*- C -*- 2# Copyright (C) 2009-2024 Free Software Foundation, Inc. 3# Contributed by Kalray Inc. 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 kvx-elf 23# specific routines. 24# 25fragment <<EOF 26 27#include "ldctor.h" 28#include "elf/kvx.h" 29#include "elfxx-kvx.h" 30 31 32static void 33elf${ELFSIZE}_kvx_before_allocation (void) 34{ 35EOF 36if test x"${EMULATION_NAME}" != x"elf64kvx_linux"; then 37fragment <<EOF 38 if (bfd_link_pie (&link_info)) { 39 einfo (_("%F:%P: -pie not supported\n")); 40 } 41EOF 42fi 43fragment <<EOF 44 45 /* Call the standard elf routine. */ 46 gld${EMULATION_NAME}_before_allocation (); 47} 48 49 50 51/* Fake input file for stubs. */ 52static lang_input_statement_type *stub_file; 53 54/* Whether we need to call gldarm_layout_sections_again. */ 55static int need_laying_out = 0; 56 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. */ 60static bfd_signed_vma group_size = -1; 61 62struct hook_stub_info 63{ 64 lang_statement_list_type add; 65 asection *input_section; 66}; 67 68/* Traverse the linker tree to find the spot where the stub goes. */ 69 70static bool 71hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp) 72{ 73 lang_statement_union_type *l; 74 bool ret; 75 76 for (; (l = *lp) != NULL; lp = &l->header.next) 77 { 78 switch (l->header.type) 79 { 80 case lang_constructors_statement_enum: 81 ret = hook_in_stub (info, &constructor_list.head); 82 if (ret) 83 return ret; 84 break; 85 86 case lang_output_section_statement_enum: 87 ret = hook_in_stub (info, 88 &l->output_section_statement.children.head); 89 90 if (ret) 91 return ret; 92 break; 93 94 case lang_wild_statement_enum: 95 ret = hook_in_stub (info, &l->wild_statement.children.head); 96 if (ret) 97 return ret; 98 break; 99 100 case lang_group_statement_enum: 101 ret = hook_in_stub (info, &l->group_statement.children.head); 102 if (ret) 103 return ret; 104 break; 105 106 case lang_input_section_enum: 107 if (l->input_section.section == info->input_section) 108 { 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; 113 return true; 114 } 115 116 break; 117 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: 128 break; 129 130 default: 131 FAIL (); 132 break; 133 } 134 } 135 return false; 136} 137 138 139/* Call-back for elf${ELFSIZE}_kvx_size_stubs. */ 140 141/* Create a new stub section, and arrange for it to be linked 142 immediately after INPUT_SECTION. */ 143 144static asection * 145elf${ELFSIZE}_kvx_add_stub_section (const char *stub_sec_name, 146 asection *input_section) 147{ 148 asection *stub_sec; 149 flagword flags; 150 asection *output_section; 151 lang_output_section_statement_type *os; 152 struct hook_stub_info info; 153 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) 159 goto err_ret; 160 161 bfd_set_section_alignment (stub_sec, 2); 162 163 output_section = input_section->output_section; 164 os = lang_output_section_get (output_section); 165 166 info.input_section = input_section; 167 lang_list_init (&info.add); 168 lang_add_section (&info.add, stub_sec, NULL, NULL, os); 169 170 if (info.add.head == NULL) 171 goto err_ret; 172 173 if (hook_in_stub (&info, &os->children.head)) 174 return stub_sec; 175 176 err_ret: 177 einfo ("%X%P: can not make stub section: %E\n"); 178 return NULL; 179} 180 181/* Another call-back for elf${ELFSIZE}_kvx_size_stubs. */ 182 183static void 184gldkvx_layout_sections_again (void) 185{ 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; 191} 192 193static void 194build_section_lists (lang_statement_union_type *statement) 195{ 196 if (statement->header.type == lang_input_section_enum) 197 { 198 asection *i = statement->input_section.section; 199 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); 205 } 206} 207 208static void 209gld${EMULATION_NAME}_after_allocation (void) 210{ 211 int ret; 212 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 216 adding stubs. */ 217 ret = bfd_elf_discard_info (link_info.output_bfd, & link_info); 218 if (ret < 0) 219 { 220 einfo ("%X%P: .eh_frame/.stab edit: %E\n"); 221 return; 222 } 223 else if (ret > 0) 224 need_laying_out = 1; 225 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)) 229 { 230 ret = elf${ELFSIZE}_kvx_setup_section_lists (link_info.output_bfd, 231 &link_info); 232 if (ret != 0) 233 { 234 if (ret < 0) 235 { 236 einfo ("%X%P: could not compute sections lists for stub generation: %E\n"); 237 return; 238 } 239 240 lang_for_each_statement (build_section_lists); 241 242 /* Call into the BFD backend to do the real work. */ 243 if (! elf${ELFSIZE}_kvx_size_stubs (link_info.output_bfd, 244 stub_file->the_bfd, 245 & link_info, 246 group_size, 247 & elf${ELFSIZE}_kvx_add_stub_section, 248 & gldkvx_layout_sections_again)) 249 { 250 einfo ("%X%P: cannot size stub section: %E\n"); 251 return; 252 } 253 } 254 } 255 256 if (need_laying_out != -1) 257 ldelf_map_segments (need_laying_out); 258} 259 260static void 261gld${EMULATION_NAME}_finish (void) 262{ 263 if (!bfd_link_relocatable (&link_info)) 264 { 265 /* Now build the linker stubs. */ 266 if (stub_file != NULL 267 && stub_file->the_bfd->sections != NULL) 268 { 269 if (! elf${ELFSIZE}_kvx_build_stubs (& link_info)) 270 einfo ("%X%P: can not build stubs: %E\n"); 271 } 272 } 273 274 finish_default (); 275} 276 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. */ 279static void 280kvx_elf_create_output_section_statements (void) 281{ 282 if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour 283 && elf_object_id (link_info.output_bfd) == KVX_ELF_DATA)) 284 return; 285 286 stub_file = lang_add_input_file ("linker stubs", 287 lang_input_file_is_fake_enum, 288 NULL); 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))) 294 { 295 einfo ("%X%P: can not create BFD %E\n"); 296 return; 297 } 298 299 stub_file->the_bfd->flags |= BFD_LINKER_CREATED; 300 ldlang_add_file (stub_file); 301 302 if (!kvx_elf${ELFSIZE}_init_stub_bfd (&link_info, stub_file->the_bfd)) 303 einfo ("%F%P: can not init BFD: %E\n"); 304} 305 306 307#define lang_for_each_input_file kvx_lang_for_each_input_file 308 309EOF 310 311LDEMUL_BEFORE_ALLOCATION=elf${ELFSIZE}_kvx_before_allocation 312LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation 313LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=kvx_elf_create_output_section_statements 314 315# Call the extra arm-elf function 316LDEMUL_FINISH=gld${EMULATION_NAME}_finish 317