This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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/elf64-ppc.c b/bfd/elf64-ppc.c
index 8c7c3b7..da37465 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 8c627a4..19f72b5 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/emulparams/elf64ppc.sh b/ld/emulparams/elf64ppc.sh
index b805dbe..d6b09bf 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 a803c5c..5a784fd 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 5344e5e..3a4257c 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/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 11f1e4f..81cc310 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 0000000..d1fd258
--- /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 0000000..8045d14
--- /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 0000000..62bc998
--- /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 0000000..d4ebbbe
--- /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

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]