This is the mail archive of the binutils@sources.redhat.com 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]

multiple powerpc .got2 sections


This adds linker support for multiple powerpc-linux .got2 sections, a
solution to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17828.  I won't
apply this immediately, since it isn't much use if the gcc patch isn't
approved.

bfd/
	* elf32-ppc.c (find_got2_section): New function.
	(ppc_elf_check_relocs, ppc_elf_gc_sweep_hook): Use it.
	(ppc_elf_relax_section, ppc_elf_relocate_section): Likewise.
ld/
	* emulparams/elf32ppc.sh (OTHER_RELRO_SECTIONS): Handle .got2.*.
	* emulparams/elf32ppclinux.sh: Likewise.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.174
diff -u -p -r1.174 elf32-ppc.c
--- bfd/elf32-ppc.c	16 Jul 2005 03:30:23 -0000	1.174
+++ bfd/elf32-ppc.c	26 Jul 2005 10:58:46 -0000
@@ -2242,7 +2242,8 @@ struct plt_entry
 {
   struct plt_entry *next;
 
-  /* -fPIC uses multiple GOT sections, one per file, called ".got2".
+  /* -fPIC uses multiple GOT sections, called ".got2", ".got2.*", or
+     ".gnu.linkonce.got2.*".
      This field stores the offset into .got2 used to initialise the
      GOT pointer reg.  It will always be at least 32768 (and for
      current gcc this is the only offset used).  */
@@ -2889,6 +2890,55 @@ update_local_sym_info (bfd *abfd,
   return TRUE;
 }
 
+/* Returns the .got2 section in ABFD associated with a given SEC.
+   Given a section named ".text.foo", this function will first look for
+   ".got2.foo" then fall back to ".got2".  Similarly, a section named
+   ".gnu.linkonce.got2.foo" will be returned for ".gnu.linkonce.t.foo".  */
+
+static asection *
+find_got2_section (bfd *abfd, asection *sec)
+{
+  const char *name = sec->name;
+  const char *suffix;
+  bfd_boolean is_linkonce = FALSE;
+
+  if ((sec->flags & SEC_LINK_ONCE) != 0
+      && strncmp (name, ".gnu.linkonce.", sizeof (".gnu.linkonce.") - 1) == 0)
+    {
+      is_linkonce = TRUE;
+      name += sizeof (".gnu.linkonce") - 1;
+    }
+  suffix = strchr (name + 1, '.');
+  if (suffix != NULL)
+    {
+      size_t len = strlen (suffix);
+      char *gotname, *p;
+
+      gotname = bfd_malloc (len + (is_linkonce
+				   ? sizeof (".gnu.linkonce.got2.") - 1
+				   : sizeof (".got2.") - 1));
+      if (gotname == NULL)
+	return NULL;
+      p = gotname;
+      if (is_linkonce)
+	{
+	  memcpy (p, ".gnu.linkonce.got2.", sizeof (".gnu.linkonce.got2.") - 1);
+	  p += sizeof (".gnu.linkonce.got2.") - 1;
+	}
+      else
+	{
+	  memcpy (p, ".got2.", sizeof (".got2.") - 1);
+	  p += sizeof (".got2.") - 1;
+	}
+      memcpy (p, suffix + 1, len);
+      sec = bfd_get_section_by_name (abfd, gotname);
+      free (gotname);
+      if (sec != NULL)
+	return sec;
+    }
+  return bfd_get_section_by_name (abfd, ".got2");
+}
+
 static bfd_boolean
 update_plt_info (bfd *abfd, struct elf_link_hash_entry *h,
 		 asection *sec, bfd_vma addend)
@@ -2980,7 +3030,7 @@ ppc_elf_check_relocs (bfd *abfd,
   htab = ppc_elf_hash_table (info);
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
-  got2 = bfd_get_section_by_name (abfd, ".got2");
+  got2 = find_got2_section (abfd, sec);
   sreloc = NULL;
 
   rel_end = relocs + sec->reloc_count;
@@ -3640,7 +3690,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
   local_got_refcounts = elf_local_got_refcounts (abfd);
-  got2 = bfd_get_section_by_name (abfd, ".got2");
+  got2 = find_got2_section (abfd, sec);
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
@@ -4892,7 +4946,7 @@ ppc_elf_relax_section (bfd *abfd,
     goto error_return;
 
   htab = ppc_elf_hash_table (link_info);
-  got2 = bfd_get_section_by_name (abfd, ".got2");
+  got2 = find_got2_section (abfd, isec);
 
   irelend = internal_relocs + isec->reloc_count;
   for (irel = internal_relocs; irel < irelend; irel++)
@@ -5419,7 +5473,7 @@ ppc_elf_relocate_section (bfd *output_bf
 		      (info->relocatable) ? " (relocatable)" : "");
 #endif
 
-  got2 = bfd_get_section_by_name (input_bfd, ".got2");
+  got2 = find_got2_section (input_bfd, input_section);
 
   if (info->relocatable)
     {
Index: ld/emulparams/elf32ppc.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf32ppc.sh,v
retrieving revision 1.16
diff -u -p -r1.16 elf32ppc.sh
--- ld/emulparams/elf32ppc.sh	5 Jul 2005 13:25:56 -0000	1.16
+++ ld/emulparams/elf32ppc.sh	26 Jul 2005 10:59:08 -0000
@@ -27,7 +27,7 @@ OTHER_BSS_END_SYMBOLS='__end = .;'
 OTHER_RELRO_SECTIONS="
   .fixup        ${RELOCATING-0} : { *(.fixup) }
   .got1         ${RELOCATING-0} : { *(.got1) }
-  .got2         ${RELOCATING-0} : { *(.got2) }
+  .got2         ${RELOCATING-0} : { *(.got2${RELOCATING+ .got2.* .gnu.linkonce.got2.*}) }
 "
 OTHER_GOT_RELOC_SECTIONS="
   .rela.got1         ${RELOCATING-0} : { *(.rela.got1) }
Index: ld/emulparams/elf32ppclinux.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf32ppclinux.sh,v
retrieving revision 1.7
diff -u -p -r1.7 elf32ppclinux.sh
--- ld/emulparams/elf32ppclinux.sh	16 Mar 2005 02:41:26 -0000	1.7
+++ ld/emulparams/elf32ppclinux.sh	26 Jul 2005 10:59:08 -0000
@@ -5,4 +5,5 @@ unset OTHER_BSS_END_SYMBOLS
 test -z "${RELOCATING}" || OTHER_SECTIONS="/DISCARD/	: { *(.fixup) }"
 OTHER_RELRO_SECTIONS="
   .got1         ${RELOCATING-0} : { *(.got1) }
-  .got2         ${RELOCATING-0} : { *(.got2) }"
+  .got2         ${RELOCATING-0} : { *(.got2${RELOCATING+ .got2.* .gnu.linkonce.got2.*}) }
+"

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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