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