From: Alan Modra Date: Tue, 27 Jan 2015 13:10:05 +0000 (+1030) Subject: PowerPC64 changes for xlc X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dbd1e97e32057af2841e5150daa2e2d4cb046a3b;p=binutils-gdb.git PowerPC64 changes for xlc The changes to reorder sections for better relro protection on powerpc64, 3e2b0f31, 23283c1b, and 5ad18f16, run into a problem with xlc. xlc -qdatalocal puts global variables into .toc, which means that .toc must be writable. The simplest way to accomplish this is to edit the linker script to remove .toc sections from .got on detecting xlc object files. bfd/ * elf64-ppc.h (struct ppc64_elf_params): Add "object_in_toc". * elf64-ppc.c (ppc64_elf_add_symbol_hook): Assume that global symbols in .toc indicate xlc compiled code that might require a rw .toc. ld/ * emulparams/elf64ppc.sh (INITIAL_READWRITE_SECTIONS): Define. * emultempl/ppc64elf.em (params): Init new field. (ppc_after_open): New function. (LDEMUL_AFTER_OPEN): Define. * ldlang.c (lang_final): Whitespace fix. ld/testsuite/ * ld-powerpc/tocvar.d, * ld-powerpc/tocvar.s: New test. * ld-powerpc/tocnovar.d, * ld-powerpc/tocnovar.s: New test. * ld-powerpc/powerpc.exp: Run tocvar and tocnovar. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 581b312b315..f5a50fa2385 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2015-01-28 Alan Modra + + * elf64-ppc.h (struct ppc64_elf_params): Add "object_in_toc". + * elf64-ppc.c (ppc64_elf_add_symbol_hook): Assume that global symbols + in .toc indicate xlc compiled code that might require a rw .toc. + 2015-01-28 James Bowman * Makefile.am: Add FT32 files. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 8c7c3b77ada..da37465feeb 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -4836,6 +4836,14 @@ ppc64_elf_add_symbol_hook (bfd *ibfd, isym->st_shndx = SHN_UNDEF; } } + else if (*sec != NULL + && strcmp ((*sec)->name, ".toc") == 0 + && ELF_ST_TYPE (isym->st_info) == STT_OBJECT) + { + struct ppc_link_hash_table *htab = ppc_hash_table (info); + if (htab != NULL) + htab->params->object_in_toc = 1; + } if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0) { diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 8c627a4edee..19f72b5fbf1 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -57,6 +57,9 @@ struct ppc64_elf_params /* Whether to generate out-of-line register save/restore for gcc -Os code. */ int save_restore_funcs; + + /* Set when a potential variable is detected in .toc. */ + int object_in_toc; }; bfd_boolean ppc64_elf_init_stub_bfd diff --git a/ld/ChangeLog b/ld/ChangeLog index 4a16b50db15..9cab995187d 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2015-01-28 Alan Modra + + * emulparams/elf64ppc.sh (INITIAL_READWRITE_SECTIONS): Define. + * emultempl/ppc64elf.em (params): Init new field. + (ppc_after_open): New function. + (LDEMUL_AFTER_OPEN): Define. + * ldlang.c (lang_final): Whitespace fix. + 2015-01-28 James Bowman * Makefile.am: Add FT32 files. diff --git a/ld/emulparams/elf64ppc.sh b/ld/emulparams/elf64ppc.sh index b805dbed93c..d6b09bf6ffd 100644 --- a/ld/emulparams/elf64ppc.sh +++ b/ld/emulparams/elf64ppc.sh @@ -38,6 +38,8 @@ OTHER_RELRO_SECTIONS_2=" .opd ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { KEEP (*(.opd)) } .toc1 ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { *(.toc1) } .branch_lt ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { *(.branch_lt) }" +INITIAL_READWRITE_SECTIONS=" + .toc ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { *(.toc) }" # Put .got before .data DATA_GOT=" " # Always make .got read-only after relocation diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index a803c5caa95..5a784fdfe70 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -39,7 +39,7 @@ static struct ppc64_elf_params params = { NULL, &ppc_layout_sections_again, 1, 0, 0, ${DEFAULT_PLT_STATIC_CHAIN-0}, -1, 0, - 0, -1, -1}; + 0, -1, -1, 0}; /* Fake input file for stubs. */ static lang_input_statement_type *stub_file; @@ -98,6 +98,37 @@ ppc_create_output_section_statements (void) einfo ("%F%P: can not init BFD: %E\n"); } +/* Called after opening files but before mapping sections. */ + +static void +ppc_after_open (void) +{ + if (stub_file != NULL && link_info.relro && params.object_in_toc) + { + /* We have a .toc section that might be written to at run time. + Don't put .toc into the .got output section. */ + lang_output_section_statement_type *got; + + got = lang_output_section_find (".got"); + if (got != NULL) + { + lang_statement_union_type *s; + for (s = got->children.head; s != NULL; s = s->header.next) + if (s->header.type == lang_wild_statement_enum + && s->wild_statement.filename == NULL) + { + struct wildcard_list **i = &s->wild_statement.section_list; + while (*i != NULL) + if (strcmp ((*i)->spec.name, ".toc") == 0) + *i = (*i)->next; + else + i = &(*i)->next; + } + } + } + gld${EMULATION_NAME}_after_open (); +} + /* Move the input section statement at *U which happens to be on LIST to be just before *TO. */ @@ -874,8 +905,9 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' # Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation # +LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern +LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements +LDEMUL_AFTER_OPEN=ppc_after_open LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation LDEMUL_FINISH=gld${EMULATION_NAME}_finish -LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements -LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern diff --git a/ld/ldlang.c b/ld/ldlang.c index 5344e5e4014..3a4257cc59d 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -6295,7 +6295,6 @@ lang_final (void) new_stmt = new_stat (lang_output_statement, stat_ptr); new_stmt->name = output_filename; - } /* Reset the current counters in the regions. */ diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 4746f14a4aa..e249d69f3b9 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-01-28 Alan Modra + + * ld-powerpc/tocvar.d, * ld-powerpc/tocvar.s: New test. + * ld-powerpc/tocnovar.d, * ld-powerpc/tocnovar.s: New test. + * ld-powerpc/powerpc.exp: Run tocvar and tocnovar. + 2015-01-28 Senthil Kumar Selvaraj * ld-scripts/memory.t: Define new symbol tred. diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 11f1e4fbd71..81cc310ad8f 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -320,3 +320,5 @@ run_dump_test "attr-gnu-12-11" run_dump_test "attr-gnu-12-21" run_dump_test "vle-multiseg-6" +run_dump_test "tocvar" +run_dump_test "tocnovar" diff --git a/ld/testsuite/ld-powerpc/tocnovar.d b/ld/testsuite/ld-powerpc/tocnovar.d new file mode 100644 index 00000000000..d1fd258b4fe --- /dev/null +++ b/ld/testsuite/ld-powerpc/tocnovar.d @@ -0,0 +1,14 @@ +#source: tocnovar.s +#as: -a64 +#ld: -melf64ppc -z relro +#readelf: -l --wide +#target: powerpc64*-*-* + +#... + +LOAD .* + +LOAD .* + +GNU_RELRO .* +#... + +00 +\.text + +01 +\.opd \.got + +02 +\.opd \.got diff --git a/ld/testsuite/ld-powerpc/tocnovar.s b/ld/testsuite/ld-powerpc/tocnovar.s new file mode 100644 index 00000000000..8045d1488c0 --- /dev/null +++ b/ld/testsuite/ld-powerpc/tocnovar.s @@ -0,0 +1,16 @@ + .section .opd,"aw",@progbits + .global _start + .type _start,@function +_start: + .quad .L_start, .TOC.@tocbase, 0 + + .text +.L_start: + lwz 3,x@toc(2) + b _start + .size _start,.-.L_start + + .section .toc,"aw",@progbits + .type x,@object +x: .long 0 + .size x,.-x diff --git a/ld/testsuite/ld-powerpc/tocvar.d b/ld/testsuite/ld-powerpc/tocvar.d new file mode 100644 index 00000000000..62bc998e98c --- /dev/null +++ b/ld/testsuite/ld-powerpc/tocvar.d @@ -0,0 +1,14 @@ +#source: tocvar.s +#as: -a64 +#ld: -melf64ppc -z relro +#readelf: -l --wide +#target: powerpc64*-*-* + +#... + +LOAD .* + +LOAD .* + +GNU_RELRO .* +#... + +00 +\.text + +01 +\.opd \.toc + +02 +\.opd diff --git a/ld/testsuite/ld-powerpc/tocvar.s b/ld/testsuite/ld-powerpc/tocvar.s new file mode 100644 index 00000000000..d4ebbbe76e8 --- /dev/null +++ b/ld/testsuite/ld-powerpc/tocvar.s @@ -0,0 +1,17 @@ + .section .opd,"aw",@progbits + .global _start + .type _start,@function +_start: + .quad .L_start, .TOC.@tocbase, 0 + + .text +.L_start: + lwz 3,x@toc(2) + b _start + .size _start,.-.L_start + + .section .toc,"aw",@progbits + .global x + .type x,@object +x: .long 0 + .size x,.-x