1# This shell script emits a C file. -*- C -*- 2# Copyright (C) 2003-2018 Free Software Foundation, Inc. 3# 4# This file is part of the 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 powerpc32-elf 23# specific routines. 24# 25fragment <<EOF 26 27#include "elf32-ppc.h" 28#include "ldlex.h" 29#include "ldlang.h" 30 31#define is_ppc_elf(bfd) \ 32 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ 33 && elf_object_id (bfd) == PPC32_ELF_DATA) 34 35/* Whether to run tls optimization. */ 36static int notlsopt = 0; 37 38/* Whether to convert inline PLT calls to direct. */ 39static int no_inline_opt = 0; 40 41/* Choose the correct place for .got. */ 42static int old_got = 0; 43 44static struct ppc_elf_params params = { PLT_UNSET, 0, -1, 45 0, 0, 0, 0, 0, 0, 0 }; 46 47static void 48ppc_after_open_output (void) 49{ 50 if (params.emit_stub_syms < 0) 51 params.emit_stub_syms = (link_info.emitrelocations 52 || bfd_link_pic (&link_info)); 53 if (params.pagesize == 0) 54 params.pagesize = config.commonpagesize; 55 ppc_elf_link_params (&link_info, ¶ms); 56} 57 58EOF 59 60# No --secure-plt, --bss-plt, or --sdata-got for vxworks. 61if test -z "$VXWORKS_BASE_EM_FILE" ; then 62 fragment <<EOF 63static void 64ppc_after_check_relocs (void) 65{ 66 if (is_ppc_elf (link_info.output_bfd)) 67 { 68 int new_plt; 69 int keep_new; 70 unsigned int num_plt; 71 unsigned int num_got; 72 lang_output_section_statement_type *os; 73 lang_output_section_statement_type *plt_os[2]; 74 lang_output_section_statement_type *got_os[2]; 75 76 new_plt = ppc_elf_select_plt_layout (link_info.output_bfd, &link_info); 77 if (new_plt < 0) 78 einfo (_("%X%P: select_plt_layout problem %E\n")); 79 80 num_got = 0; 81 num_plt = 0; 82 for (os = &lang_output_section_statement.head->output_section_statement; 83 os != NULL; 84 os = os->next) 85 { 86 if (os->constraint == SPECIAL && strcmp (os->name, ".plt") == 0) 87 { 88 if (num_plt < 2) 89 plt_os[num_plt] = os; 90 ++num_plt; 91 } 92 if (os->constraint == SPECIAL && strcmp (os->name, ".got") == 0) 93 { 94 if (num_got < 2) 95 got_os[num_got] = os; 96 ++num_got; 97 } 98 } 99 100 keep_new = new_plt == 1 ? 0 : -1; 101 if (num_plt == 2) 102 { 103 plt_os[0]->constraint = keep_new; 104 plt_os[1]->constraint = ~keep_new; 105 } 106 if (num_got == 2) 107 { 108 if (old_got) 109 keep_new = -1; 110 got_os[0]->constraint = keep_new; 111 got_os[1]->constraint = ~keep_new; 112 } 113 } 114 115 after_check_relocs_default (); 116} 117 118EOF 119fi 120fragment <<EOF 121static void 122prelim_size_sections (void) 123{ 124 if (expld.phase != lang_mark_phase_enum) 125 { 126 expld.phase = lang_mark_phase_enum; 127 expld.dataseg.phase = exp_seg_none; 128 one_lang_size_sections_pass (NULL, FALSE); 129 /* We must not cache anything from the preliminary sizing. */ 130 lang_reset_memory_regions (); 131 } 132} 133 134static void 135ppc_before_allocation (void) 136{ 137 if (is_ppc_elf (link_info.output_bfd)) 138 { 139 if (!no_inline_opt 140 && !bfd_link_relocatable (&link_info)) 141 { 142 prelim_size_sections (); 143 144 if (!ppc_elf_inline_plt (&link_info)) 145 einfo (_("%X%P: inline PLT: %E\n")); 146 } 147 148 if (ppc_elf_tls_setup (link_info.output_bfd, &link_info) 149 && !notlsopt) 150 { 151 if (!ppc_elf_tls_optimize (link_info.output_bfd, &link_info)) 152 { 153 einfo (_("%X%P: TLS problem %E\n")); 154 return; 155 } 156 } 157 } 158 159 gld${EMULATION_NAME}_before_allocation (); 160 161 ppc_elf_maybe_strip_sdata_syms (&link_info); 162 163 if (RELAXATION_ENABLED) 164 params.branch_trampolines = 1; 165 166 /* Turn on relaxation if executable sections have addresses that 167 might make branches overflow. */ 168 else if (!RELAXATION_DISABLED_BY_USER) 169 { 170 bfd_vma low = (bfd_vma) -1; 171 bfd_vma high = 0; 172 asection *o; 173 174 /* Run lang_size_sections (if not already done). */ 175 prelim_size_sections (); 176 177 for (o = link_info.output_bfd->sections; o != NULL; o = o->next) 178 { 179 if ((o->flags & (SEC_ALLOC | SEC_CODE)) != (SEC_ALLOC | SEC_CODE)) 180 continue; 181 if (o->rawsize == 0) 182 continue; 183 if (low > o->vma) 184 low = o->vma; 185 if (high < o->vma + o->rawsize - 1) 186 high = o->vma + o->rawsize - 1; 187 } 188 if (high > low && high - low > (1 << 25) - 1) 189 params.branch_trampolines = 1; 190 } 191 192 if (params.branch_trampolines 193 || params.ppc476_workaround 194 || params.pic_fixup > 0) 195 ENABLE_RELAXATION; 196} 197 198/* Replaces default zero fill padding in executable sections with 199 "ba 0" instructions. This works around the ppc476 icache bug if we 200 have a function pointer tail call near the end of a page, some 201 small amount of padding, then the function called at the beginning 202 of the next page. If the "ba 0" is ever executed we should hit a 203 segv, so it's almost as good as an illegal instruction (zero). */ 204 205static void 206no_zero_padding (lang_statement_union_type *l) 207{ 208 if (l->header.type == lang_padding_statement_enum 209 && l->padding_statement.size != 0 210 && l->padding_statement.output_section != NULL 211 && (l->padding_statement.output_section->flags & SEC_CODE) != 0 212 && l->padding_statement.fill->size == 0) 213 { 214 struct _ppc_fill_type 215 { 216 size_t size; 217 unsigned char data[4]; 218 }; 219 static struct _ppc_fill_type fill_be = { 4, {0x48, 0, 0, 2} }; 220 static struct _ppc_fill_type fill_le = { 4, {2, 0, 0, 0x48} }; 221 222 if (bfd_big_endian (link_info.output_bfd)) 223 l->padding_statement.fill = (struct _fill_type *) &fill_be; 224 else 225 l->padding_statement.fill = (struct _fill_type *) &fill_le; 226 } 227} 228 229static void 230ppc_finish (void) 231{ 232 if (params.ppc476_workaround) 233 lang_for_each_statement (no_zero_padding); 234 if (!ppc_finish_symbols (&link_info)) 235 einfo (_("%X%P: ppc_finish_symbols problem %E\n")); 236 finish_default (); 237} 238 239EOF 240 241if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then 242 fragment <<EOF 243/* Special handling for embedded SPU executables. */ 244extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *); 245static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *); 246 247static bfd_boolean 248ppc_recognized_file (lang_input_statement_type *entry) 249{ 250 if (embedded_spu_file (entry, "-m32")) 251 return TRUE; 252 253 return gld${EMULATION_NAME}_load_symbols (entry); 254} 255 256EOF 257LDEMUL_RECOGNIZED_FILE=ppc_recognized_file 258fi 259 260# Define some shell vars to insert bits of code into the standard elf 261# parse_args and list_options functions. 262# 263PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}' 264enum ppc32_opt 265{ 266 OPTION_NO_TLS_OPT = 321, 267 OPTION_NO_TLS_GET_ADDR_OPT, 268 OPTION_NEW_PLT, 269 OPTION_OLD_PLT, 270 OPTION_PLT_ALIGN, 271 OPTION_NO_PLT_ALIGN, 272 OPTION_NO_INLINE_OPT, 273 OPTION_OLD_GOT, 274 OPTION_STUBSYMS, 275 OPTION_NO_STUBSYMS, 276 OPTION_PPC476_WORKAROUND, 277 OPTION_NO_PPC476_WORKAROUND, 278 OPTION_NO_PICFIXUP, 279 OPTION_VLE_RELOC_FIXUP 280}; 281' 282 283PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' 284 { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS }, 285 { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS }, 286 { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT }, 287 { "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },' 288if test -z "$VXWORKS_BASE_EM_FILE" ; then 289 PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' 290 { "secure-plt", no_argument, NULL, OPTION_NEW_PLT }, 291 { "bss-plt", no_argument, NULL, OPTION_OLD_PLT }, 292 { "plt-align", optional_argument, NULL, OPTION_PLT_ALIGN }, 293 { "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN }, 294 { "no-inline-optimize", no_argument, NULL, OPTION_NO_INLINE_OPT }, 295 { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },' 296fi 297PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' 298 { "ppc476-workaround", optional_argument, NULL, OPTION_PPC476_WORKAROUND }, 299 { "no-ppc476-workaround", no_argument, NULL, OPTION_NO_PPC476_WORKAROUND }, 300 { "no-pic-fixup", no_argument, NULL, OPTION_NO_PICFIXUP }, 301 { "vle-reloc-fixup", no_argument, NULL, OPTION_VLE_RELOC_FIXUP }, 302' 303 304PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' 305 fprintf (file, _("\ 306 --emit-stub-syms Label linker stubs with a symbol\n" 307 )); 308 fprintf (file, _("\ 309 --no-emit-stub-syms Don'\''t label linker stubs with a symbol\n" 310 )); 311 fprintf (file, _("\ 312 --no-tls-optimize Don'\''t try to optimize TLS accesses\n" 313 )); 314 fprintf (file, _("\ 315 --no-tls-get-addr-optimize Don'\''t use a special __tls_get_addr call\n" 316 ));' 317if test -z "$VXWORKS_BASE_EM_FILE" ; then 318 PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'\ 319 fprintf (file, _("\ 320 --secure-plt Use new-style PLT if possible\n" 321 )); 322 fprintf (file, _("\ 323 --bss-plt Force old-style BSS PLT\n" 324 )); 325 fprintf (file, _("\ 326 --plt-align Align PLT call stubs to fit cache lines\n" 327 )); 328 fprintf (file, _("\ 329 --no-plt-align Dont'\''t align individual PLT call stubs\n" 330 )); 331 fprintf (file, _("\ 332 --no-inline-optimize Don'\''t convert inline PLT to direct calls\n" 333 )); 334 fprintf (file, _("\ 335 --sdata-got Force GOT location just before .sdata\n" 336 ));' 337fi 338PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'\ 339 fprintf (file, _("\ 340 --ppc476-workaround [=pagesize]\n\ 341 Avoid a cache bug on ppc476\n" 342 )); 343 fprintf (file, _("\ 344 --no-ppc476-workaround Disable workaround\n" 345 )); 346 fprintf (file, _("\ 347 --no-pic-fixup Don'\''t edit non-pic to pic\n" 348 )); 349 fprintf (file, _("\ 350 --vle-reloc-fixup Correct old object file 16A/16D relocation\n" 351 )); 352' 353 354PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' 355 case OPTION_STUBSYMS: 356 params.emit_stub_syms = 1; 357 break; 358 359 case OPTION_NO_STUBSYMS: 360 params.emit_stub_syms = 0; 361 break; 362 363 case OPTION_NO_TLS_OPT: 364 notlsopt = 1; 365 break; 366 367 case OPTION_NO_TLS_GET_ADDR_OPT: 368 params.no_tls_get_addr_opt = 1; 369 break; 370 371 case OPTION_NEW_PLT: 372 params.plt_style = PLT_NEW; 373 break; 374 375 case OPTION_OLD_PLT: 376 params.plt_style = PLT_OLD; 377 break; 378 379 case OPTION_PLT_ALIGN: 380 if (optarg != NULL) 381 { 382 char *end; 383 unsigned long val = strtoul (optarg, &end, 0); 384 if (*end || val > 5) 385 einfo (_("%F%P: invalid --plt-align `%s'\''\n"), optarg); 386 params.plt_stub_align = val; 387 } 388 else 389 params.plt_stub_align = 5; 390 break; 391 392 case OPTION_NO_PLT_ALIGN: 393 params.plt_stub_align = 0; 394 break; 395 396 case OPTION_NO_INLINE_OPT: 397 no_inline_opt = 1; 398 break; 399 400 case OPTION_OLD_GOT: 401 old_got = 1; 402 break; 403 404 case OPTION_TRADITIONAL_FORMAT: 405 notlsopt = 1; 406 params.no_tls_get_addr_opt = 1; 407 return FALSE; 408 409 case OPTION_PPC476_WORKAROUND: 410 params.ppc476_workaround = 1; 411 if (optarg != NULL) 412 { 413 char *end; 414 params.pagesize = strtoul (optarg, &end, 0); 415 if (*end 416 || (params.pagesize < 4096 && params.pagesize != 0) 417 || params.pagesize != (params.pagesize & -params.pagesize)) 418 einfo (_("%F%P: invalid pagesize `%s'\''\n"), optarg); 419 } 420 break; 421 422 case OPTION_NO_PPC476_WORKAROUND: 423 params.ppc476_workaround = 0; 424 break; 425 426 case OPTION_NO_PICFIXUP: 427 params.pic_fixup = -1; 428 break; 429 430 case OPTION_VLE_RELOC_FIXUP: 431 params.vle_reloc_fixup = 1; 432 break; 433' 434 435# Put these extra ppc32elf routines in ld_${EMULATION_NAME}_emulation 436# 437LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_after_open_output 438if test -z "$VXWORKS_BASE_EM_FILE" ; then 439 LDEMUL_AFTER_CHECK_RELOCS=ppc_after_check_relocs 440fi 441LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation 442LDEMUL_FINISH=ppc_finish 443