PowerPC64 changes for xlc
authorAlan Modra <amodra@gmail.com>
Tue, 27 Jan 2015 13:10:05 +0000 (23:40 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 28 Jan 2015 08:00:54 +0000 (18:30 +1030)
The changes to reorder sections for better relro protection on powerpc64,
3e2b0f3123283c1b, 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.

13 files changed:
bfd/ChangeLog
bfd/elf64-ppc.c
bfd/elf64-ppc.h
ld/ChangeLog
ld/emulparams/elf64ppc.sh
ld/emultempl/ppc64elf.em
ld/ldlang.c
ld/testsuite/ChangeLog
ld/testsuite/ld-powerpc/powerpc.exp
ld/testsuite/ld-powerpc/tocnovar.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tocnovar.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/tocvar.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/tocvar.s [new file with mode: 0644]

index 581b312b3155c193f325cf9eeb265983a0fc7528..f5a50fa2385d6cba7a726722d0df42d78abc9265 100644 (file)
@@ -1,3 +1,9 @@
+2015-01-28  Alan Modra  <amodra@gmail.com>
+
+       * 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  <james.bowman@ftdichip.com>
 
        * Makefile.am: Add FT32 files.
index 8c7c3b77adac4f98f0f91d30f4c2ab1b9985c284..da37465feeb50b2f0d721156a847335c3d8f418d 100644 (file)
@@ -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)
     {
index 8c627a4edee9589d737a1b30852c79d1efeb3129..19f72b5fbf14d1ff2956c0d5246719bb4397fe9d 100644 (file)
@@ -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
index 4a16b50db15d8648862c3a5a82a57a7ccf5764e0..9cab995187df05dcef97fb5d937507ff735b973e 100644 (file)
@@ -1,3 +1,11 @@
+2015-01-28  Alan Modra  <amodra@gmail.com>
+
+       * 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  <james.bowman@ftdichip.com>
 
        * Makefile.am: Add FT32 files.
index b805dbed93c41d5c8d3bf3ecfcdd54b24b18fec8..d6b09bf6ffd0e824cbeec5dee06fd37f89ceff36 100644 (file)
@@ -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
index a803c5caa95cf0d4532beb50bc3caae7777984d0..5a784fdfe707fa3d7b9fd725df068686a38b1943 100644 (file)
@@ -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
index 5344e5e401433818c75832b733d8a6a8f4886ced..3a4257cc59d608d0ccef81e2a62725148462cd2a 100644 (file)
@@ -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.  */
index 4746f14a4aa851f44e89a286aaff37f4e2c573c4..e249d69f3b921d30d56fe83779a122f225a0181b 100644 (file)
@@ -1,3 +1,9 @@
+2015-01-28  Alan Modra  <amodra@gmail.com>
+
+       * 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  <senthil_kumar.selvaraj@atmel.com>
 
        * ld-scripts/memory.t: Define new symbol tred.
index 11f1e4fbd71e18c6be98a97891f9ffa82d8e0b20..81cc310ad8fbed71bc08920fd9b6b7fdb1a38a20 100644 (file)
@@ -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 (file)
index 0000000..d1fd258
--- /dev/null
@@ -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 (file)
index 0000000..8045d14
--- /dev/null
@@ -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 (file)
index 0000000..62bc998
--- /dev/null
@@ -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 (file)
index 0000000..d4ebbbe
--- /dev/null
@@ -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