Tweak powerpc64 support for old (dot-sym) object vs. as-needed libs

Alan Modra amodra@bigpond.net.au
Tue Feb 1 03:40:00 GMT 2005


Found when running glibc testsuite with latest binutils.  glibc
references .__tls_get_addr, which didn't trigger DT_NEEDED for ld64.so.1.

bfd/
	* elf64-ppc.c (func_desc_adjust): Move code creating func desc sym to..
	(make_fdh): ..here.  New function.  Don't set BSF_OBJECT for
	undefined syms.
	(struct add_symbol_adjust_data): New.
	(add_symbol_adjust): Make an undefweak func desc for old ABI
	objects to link with --as-needed shared libs.  Return fail status.
	Don't adjust old ABI func entry sym to weak if func desc syms
	isn't defined.
	(ppc64_elf_check_directives): Adjust call to add_symbol_adjust,
	and return status.
ld/testsuite/
	* ld-powerpc/tlsso.r: Update.
	* ld-powerpc/tlstocso.r: Update.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.186
diff -u -p -r1.186 elf64-ppc.c
--- bfd/elf64-ppc.c	1 Feb 2005 01:11:13 -0000	1.186
+++ bfd/elf64-ppc.c	1 Feb 2005 02:19:50 -0000
@@ -3937,6 +3937,37 @@ get_fdh (struct ppc_link_hash_entry *fh,
   return fdh;
 }
 
+/* Make a fake function descriptor sym for the code sym FH.  */
+
+static struct ppc_link_hash_entry *
+make_fdh (struct bfd_link_info *info,
+	  struct ppc_link_hash_entry *fh,
+	  flagword flags)
+{
+  bfd *abfd;
+  asymbol *newsym;
+  struct bfd_link_hash_entry *bh;
+  struct ppc_link_hash_entry *fdh;
+
+  abfd = fh->elf.root.u.undef.abfd;
+  newsym = bfd_make_empty_symbol (abfd);
+  newsym->name = fh->elf.root.root.string + 1;
+  newsym->section = bfd_und_section_ptr;
+  newsym->value = 0;
+  newsym->flags = flags;
+
+  bh = NULL;
+  if (!_bfd_generic_link_add_one_symbol (info, abfd, newsym->name,
+					 newsym->flags, newsym->section,
+					 newsym->value, NULL, FALSE, FALSE,
+					 &bh))
+    return NULL;
+
+  fdh = (struct ppc_link_hash_entry *) bh;
+  fdh->elf.non_elf = 0;
+  return fdh;
+}
+
 /* Hacks to support old ABI code.
    When making function calls, old ABI code references function entry
    points (dot symbols), while new ABI code references the function
@@ -4009,10 +4040,16 @@ ppc64_elf_archive_symbol_lookup (bfd *ab
    most restrictive visibility of the function descriptor and the
    function entry symbol is used.  */
 
+struct add_symbol_adjust_data
+{
+  struct bfd_link_info *info;
+  bfd_boolean ok;
+};
+
 static bfd_boolean
 add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
 {
-  struct bfd_link_info *info;
+  struct add_symbol_adjust_data *data;
   struct ppc_link_hash_table *htab;
   struct ppc_link_hash_entry *eh;
   struct ppc_link_hash_entry *fdh;
@@ -4026,11 +4063,25 @@ add_symbol_adjust (struct elf_link_hash_
   if (h->root.root.string[0] != '.')
     return TRUE;
 
-  info = inf;
-  htab = ppc_hash_table (info);
+  data = inf;
+  htab = ppc_hash_table (data->info);
   eh = (struct ppc_link_hash_entry *) h;
   fdh = get_fdh (eh, htab);
-  if (fdh != NULL)
+  if (fdh == NULL
+      && (eh->elf.root.type == bfd_link_hash_undefined
+	  || eh->elf.root.type == bfd_link_hash_undefweak)
+      && eh->elf.ref_regular)
+    {
+      /* Make an undefweak function descriptor sym, which is enough to
+	 pull in an --as-needed shared lib, but won't cause link
+	 errors.  Archives are handled elsewhere.  */
+      fdh = make_fdh (data->info, eh, BSF_WEAK);
+      if (fdh == NULL)
+	data->ok = FALSE;
+      else
+	fdh->elf.ref_regular = 1;
+    }
+  else if (fdh != NULL)
     {
       unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1;
       unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1;
@@ -4039,7 +4090,9 @@ add_symbol_adjust (struct elf_link_hash_
       else if (entry_vis > descr_vis)
 	eh->elf.other += descr_vis - entry_vis;
 
-      if (eh->elf.root.type == bfd_link_hash_undefined)
+      if (eh->elf.root.type == bfd_link_hash_undefined
+	  && (fdh->elf.root.type == bfd_link_hash_defined
+	      || fdh->elf.root.type == bfd_link_hash_defweak))
 	{
 	  eh->elf.root.type = bfd_link_hash_undefweak;
 	  eh->was_undefined = 1;
@@ -4055,12 +4108,15 @@ ppc64_elf_check_directives (bfd *abfd AT
 			    struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
+  struct add_symbol_adjust_data data;
 
   htab = ppc_hash_table (info);
   if (!is_ppc64_elf_target (htab->elf.root.creator))
     return TRUE;
 
-  elf_link_hash_traverse (&htab->elf, add_symbol_adjust, info);
+  data.info = info;
+  data.ok = TRUE;
+  elf_link_hash_traverse (&htab->elf, add_symbol_adjust, &data);
 
   /* We need to fix the undefs list for any syms we have twiddled to
      undef_weak.  */
@@ -4069,7 +4125,7 @@ ppc64_elf_check_directives (bfd *abfd AT
       bfd_link_repair_undef_list (&htab->elf.root);
       htab->twiddled_syms = 0;
     }
-  return TRUE;
+  return data.ok;
 }
 
 static bfd_boolean
@@ -5358,30 +5414,12 @@ func_desc_adjust (struct elf_link_hash_e
       && (fh->elf.root.type == bfd_link_hash_undefined
 	  || fh->elf.root.type == bfd_link_hash_undefweak))
     {
-      bfd *abfd;
-      asymbol *newsym;
-      struct bfd_link_hash_entry *bh;
-
-      abfd = fh->elf.root.u.undef.abfd;
-      newsym = bfd_make_empty_symbol (abfd);
-      newsym->name = fh->elf.root.root.string + 1;
-      newsym->section = bfd_und_section_ptr;
-      newsym->value = 0;
-      newsym->flags = BSF_OBJECT;
+      flagword flags = 0;
       if (fh->elf.root.type == bfd_link_hash_undefweak)
-	newsym->flags |= BSF_WEAK;
-
-      bh = &fdh->elf.root;
-      if ( !(_bfd_generic_link_add_one_symbol
-	     (info, abfd, newsym->name, newsym->flags,
-	      newsym->section, newsym->value, NULL, FALSE, FALSE, &bh)))
-	{
-	  return FALSE;
-	}
-      fdh = (struct ppc_link_hash_entry *) bh;
-      fdh->elf.non_elf = 0;
-      fdh->elf.size = 24;
-      fdh->elf.type = STT_OBJECT;
+	flags = BSF_WEAK;
+      fdh = make_fdh (info, fh, flags);
+      if (fdh == NULL)
+	return FALSE;
     }
 
   if (fdh != NULL
Index: ld/testsuite/ld-powerpc/tlsso.r
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/tlsso.r,v
retrieving revision 1.9
diff -u -p -r1.9 tlsso.r
--- ld/testsuite/ld-powerpc/tlsso.r	1 Oct 2004 02:19:04 -0000	1.9
+++ ld/testsuite/ld-powerpc/tlsso.r	1 Feb 2005 02:05:06 -0000
@@ -82,7 +82,7 @@ Symbol table '\.dynsym' contains 22 entr
  +[0-9]+: 0+10700 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
  +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 le0
- +[0-9]+: 0+ +24 OBJECT +GLOBAL DEFAULT +UND __tls_get_addr
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
  +[0-9]+: 0+40 +0 TLS +GLOBAL DEFAULT +8 ld0
  +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 le1
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
@@ -127,7 +127,7 @@ Symbol table '\.symtab' contains 42 entr
  +[0-9]+: 0+10700 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
  +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 le0
- +[0-9]+: 0+ +24 OBJECT +GLOBAL DEFAULT +UND __tls_get_addr
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
  +[0-9]+: 0+40 +0 TLS +GLOBAL DEFAULT +8 ld0
  +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 le1
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
Index: ld/testsuite/ld-powerpc/tlstocso.r
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/tlstocso.r,v
retrieving revision 1.10
diff -u -p -r1.10 tlstocso.r
--- ld/testsuite/ld-powerpc/tlstocso.r	1 Oct 2004 02:19:04 -0000	1.10
+++ ld/testsuite/ld-powerpc/tlstocso.r	1 Feb 2005 02:05:06 -0000
@@ -77,7 +77,7 @@ Symbol table '\.dynsym' contains 22 entr
  +[0-9]+: 0+10648 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
  +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 le0
- +[0-9]+: 0+ +24 OBJECT +GLOBAL DEFAULT +UND __tls_get_addr
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
  +[0-9]+: 0+40 +0 TLS +GLOBAL DEFAULT +8 ld0
  +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 le1
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
@@ -123,7 +123,7 @@ Symbol table '\.symtab' contains 43 entr
  +[0-9]+: 0+10648 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
  +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 le0
- +[0-9]+: 0+ +24 OBJECT +GLOBAL DEFAULT +UND __tls_get_addr
+ +[0-9]+: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
  +[0-9]+: 0+40 +0 TLS +GLOBAL DEFAULT +8 ld0
  +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 le1
  +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +UND ld

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list