This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc 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]

GNU C Library master sources branch, master, updated. glibc-2.10-399-g31c759b


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  31c759bf37a7a41faf8b13800deb769e8a5f3871 (commit)
       via  51a71cf063505d689337cf998670691a0a4b2410 (commit)
       via  77799d9d9b3f9c937bd6de035b724b9b272c9227 (commit)
      from  9fd76770c304ac30a344150d6a56bd6f873b2be0 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=31c759bf37a7a41faf8b13800deb769e8a5f3871

commit 31c759bf37a7a41faf8b13800deb769e8a5f3871
Author: Alan Modra <amodra@bigpond.net.au>
Date:   Fri Oct 30 00:48:54 2009 -0700

    Uglify IFUNC tests for PPC.

diff --git a/ChangeLog b/ChangeLog
index 3359bc2..ebae859 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2009-10-28  Alan Modra  <amodra@bigpond.net.au>
+
+	* elf/ifuncdep2.c: Include ifunc-sel.h.
+	(global): Delete.
+	(foo1_ifunc, foo2_ifunc, foo3_ifunc): Use ifunc_sel.
+	* elf/ifuncmain1.c (global): Delete.
+	* elf/ifuncmain1vis.c: Likewise.
+	* elf/ifuncmain2.c: Likewise.
+	* elf/ifuncmain5.c: Likewise.
+	* elf/ifuncmod3.c: Likewise.
+	* elf/ifuncmain6pie.c: Include ifunc-sel.h.
+	(foo_ifunc): Use ifunc_one.
+	* elf/ifuncmain7.c: Likewise.
+	* elf/ifuncmod1.c: Include ifunc-sel.h.
+	(global): Define protected var.
+	(foo_ifunc, foo_hidden_ifunc, foo_protected_ifunc): Use ifunc_sel.
+	* elf/ifuncmod5.c: Likewise.
+	* sysdeps/generic/elf/ifunc-sel.h: New file.
+	* sysdeps/powerpc/elf/ifunc-sel.h: New file.
+
 2009-07-30  Alan Modra  <amodra@bigpond.net.au>
 
 	* elf/elf.h (R_PPC_NUM, R_PPC64_NUM): Delete unused and incorrect.
diff --git a/elf/ifuncdep2.c b/elf/ifuncdep2.c
index fb21eef..758bae1 100644
--- a/elf/ifuncdep2.c
+++ b/elf/ifuncdep2.c
@@ -1,6 +1,8 @@
 /* Test 3 STT_GNU_IFUNC symbols.  */
 
-extern int global;
+#include "ifunc-sel.h"
+
+int global __attribute__ ((visibility ("protected"))) = -1;
 
 static int
 one (void)
@@ -26,15 +28,7 @@ __asm__(".type foo1, %gnu_indirect_function");
 void * 
 foo1_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return one;
-    case -1:
-      return minus_one;
-    default:
-      return zero;
-    }
+  return ifunc_sel (one, minus_one, zero);
 }
 
 void * foo2_ifunc (void) __asm__ ("foo2");
@@ -43,15 +37,7 @@ __asm__(".type foo2, %gnu_indirect_function");
 void * 
 foo2_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return minus_one;
-    case -1:
-      return one;
-    default:
-      return zero;
-    }
+  return ifunc_sel (minus_one, one, zero);
 }
 
 void * foo3_ifunc (void) __asm__ ("foo3");
@@ -60,13 +46,5 @@ __asm__(".type foo3, %gnu_indirect_function");
 void * 
 foo3_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return one;
-    case -1:
-      return zero;
-    default:
-      return minus_one;
-    }
+  return ifunc_sel (one, zero, minus_one);
 }
diff --git a/elf/ifuncmain1.c b/elf/ifuncmain1.c
index de7ffe8..cc1e5ec 100644
--- a/elf/ifuncmain1.c
+++ b/elf/ifuncmain1.c
@@ -7,8 +7,6 @@
 
 #include <stdlib.h>
 
-int global = -1;
-
 int ret_foo;
 int ret_foo_hidden;
 int ret_foo_protected;
diff --git a/elf/ifuncmain1vis.c b/elf/ifuncmain1vis.c
index a239d2d..81cd122 100644
--- a/elf/ifuncmain1vis.c
+++ b/elf/ifuncmain1vis.c
@@ -7,8 +7,6 @@
 
 #include <stdlib.h>
 
-int global = -1;
-
 int ret_foo;
 int ret_foo_hidden;
 int ret_foo_protected;
diff --git a/elf/ifuncmain2.c b/elf/ifuncmain2.c
index cd9b2c8..db3ba56 100644
--- a/elf/ifuncmain2.c
+++ b/elf/ifuncmain2.c
@@ -3,8 +3,6 @@
 
 #include <stdlib.h>
 
-int global = -1;
-
 extern int foo1 (void);
 
 int
diff --git a/elf/ifuncmain5.c b/elf/ifuncmain5.c
index 7f128d0..f398085 100644
--- a/elf/ifuncmain5.c
+++ b/elf/ifuncmain5.c
@@ -2,8 +2,6 @@
 
 #include <stdlib.h>
 
-int global = -1;
-
 extern int foo (void);
 extern int foo_protected (void);
 
diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c
index 06f179b..8478d4c 100644
--- a/elf/ifuncmain6pie.c
+++ b/elf/ifuncmain6pie.c
@@ -6,6 +6,7 @@
  */
 
 #include <stdlib.h>
+#include "ifunc-sel.h"
 
 typedef int (*foo_p) (void);
 extern foo_p foo_ptr;
@@ -22,7 +23,7 @@ __asm__(".type foo, %gnu_indirect_function");
 void *
 foo_ifunc (void)
 {
-  return one;
+  return ifunc_one (one);
 }
 
 extern int foo (void);
diff --git a/elf/ifuncmain7.c b/elf/ifuncmain7.c
index 099e929..617a596 100644
--- a/elf/ifuncmain7.c
+++ b/elf/ifuncmain7.c
@@ -5,6 +5,7 @@
  */
 
 #include <stdlib.h>
+#include "ifunc-sel.h"
 
 extern int foo (void);
 
@@ -21,7 +22,7 @@ static void *
 __attribute__ ((used))
 foo_ifunc (void)
 {
-  return one;
+  return ifunc_one (one);
 }
 
 typedef int (*foo_p) (void);
diff --git a/elf/ifuncmod1.c b/elf/ifuncmod1.c
index a1697b5..2b8195c 100644
--- a/elf/ifuncmod1.c
+++ b/elf/ifuncmod1.c
@@ -4,8 +4,9 @@
    2. Function pointer.
    3. Visibility.
  */
+#include "ifunc-sel.h"
 
-extern int global;
+int global __attribute__ ((visibility ("protected"))) = -1;
 
 static int
 one (void)
@@ -20,7 +21,7 @@ minus_one (void)
 }
 
 static int
-zero (void) 
+zero (void)
 {
   return 0;
 }
@@ -28,52 +29,28 @@ zero (void)
 void * foo_ifunc (void) __asm__ ("foo");
 __asm__(".type foo, %gnu_indirect_function");
 
-void * 
+void *
 foo_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return one;
-    case -1:
-      return minus_one;
-    default:
-      return zero;
-    }
+  return ifunc_sel (one, minus_one, zero);
 }
 
 void * foo_hidden_ifunc (void) __asm__ ("foo_hidden");
 __asm__(".type foo_hidden, %gnu_indirect_function");
 
-void * 
+void *
 foo_hidden_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return minus_one;
-    case -1:
-      return one;
-    default:
-      return zero;
-    }
+  return ifunc_sel (minus_one, one, zero);
 }
 
 void * foo_protected_ifunc (void) __asm__ ("foo_protected");
 __asm__(".type foo_protected, %gnu_indirect_function");
 
-void * 
+void *
 foo_protected_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return one;
-    case -1:
-      return zero;
-    default:
-      return minus_one;
-    }
+  return ifunc_sel (one, zero, minus_one);
 }
 
 /* Test hidden indirect function.  */
diff --git a/elf/ifuncmod3.c b/elf/ifuncmod3.c
index 379d2c8..ca2d962 100644
--- a/elf/ifuncmod3.c
+++ b/elf/ifuncmod3.c
@@ -5,4 +5,3 @@
 int ret_foo;
 int ret_foo_hidden;
 int ret_foo_protected;
-int global = -1;
diff --git a/elf/ifuncmod5.c b/elf/ifuncmod5.c
index 2ca1c71..9a08e8c 100644
--- a/elf/ifuncmod5.c
+++ b/elf/ifuncmod5.c
@@ -1,6 +1,7 @@
 /* Test STT_GNU_IFUNC symbols without direct function call.  */
+#include "ifunc-sel.h"
 
-extern int global;
+int global __attribute__ ((visibility ("protected"))) = -1;
 
 static int
 one (void)
@@ -26,15 +27,7 @@ __asm__(".type foo, %gnu_indirect_function");
 void *
 foo_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return one;
-    case -1:
-      return minus_one;
-    default:
-      return zero;
-    }
+  return ifunc_sel (one, minus_one, zero);
 }
 
 void * foo_hidden_ifunc (void) __asm__ ("foo_hidden");
@@ -43,15 +36,7 @@ __asm__(".type foo_hidden, %gnu_indirect_function");
 void *
 foo_hidden_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return minus_one;
-    case -1:
-      return one;
-    default:
-      return zero;
-    }
+  return ifunc_sel (minus_one, one, zero);
 }
 
 void * foo_protected_ifunc (void) __asm__ ("foo_protected");
@@ -60,15 +45,7 @@ __asm__(".type foo_protected, %gnu_indirect_function");
 void *
 foo_protected_ifunc (void)
 {
-  switch (global)
-    {
-    case 1:
-      return one;
-    case -1:
-      return zero;
-    default:
-      return minus_one;
-    }
+  return ifunc_sel (one, zero, minus_one);
 }
 
 /* Test hidden indirect function.  */
diff --git a/sysdeps/generic/elf/ifunc-sel.h b/sysdeps/generic/elf/ifunc-sel.h
new file mode 100644
index 0000000..6a27b69
--- /dev/null
+++ b/sysdeps/generic/elf/ifunc-sel.h
@@ -0,0 +1,26 @@
+/* Used by the elf ifunc tests.  */
+#ifndef ELF_IFUNC_SEL_H
+#define ELF_IFUNC_SEL_H 1
+
+extern int global;
+
+static inline void *
+ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
+{
+ switch (global)
+   {
+   case 1:
+     return f1;
+   case -1:
+     return f2;
+   default:
+     return f3;
+   }
+}
+
+static inline void *
+ifunc_one (int (*f1) (void))
+{
+  return f1;
+}
+#endif
diff --git a/sysdeps/powerpc/elf/ifunc-sel.h b/sysdeps/powerpc/elf/ifunc-sel.h
new file mode 100644
index 0000000..526d8ed
--- /dev/null
+++ b/sysdeps/powerpc/elf/ifunc-sel.h
@@ -0,0 +1,46 @@
+/* Used by the elf ifunc tests.  */
+#ifndef ELF_IFUNC_SEL_H
+#define ELF_IFUNC_SEL_H 1
+
+extern int global;
+
+static inline void *
+ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
+{
+  register void *ret __asm__ ("r3");
+  __asm__ ("mflr 12\n\t"
+	   "bcl 20,31,1f\n"
+	   "1:\tmflr 11\n\t"
+	   "mtlr 12\n\t"
+	   "addis 12,11,global-1b@ha\n\t"
+	   "lwz 12,global-1b@l(12)\n\t"
+	   "addis %0,11,%2-1b@ha\n\t"
+	   "addi %0,%0,%2-1b@l\n\t"
+	   "cmpwi 12,1\n\t"
+	   "beqlr\n\t"
+	   "addis %0,11,%3-1b@ha\n\t"
+	   "addi %0,%0,%3-1b@l\n\t"
+	   "cmpwi 12,-1\n\t"
+	   "beqlr\n\t"
+	   "addis %0,11,%4-1b@ha\n\t"
+	   "addi %0,%0,%4-1b@l"
+	   : "=r" (ret)
+	   : "X" (&global), "X" (f1), "X" (f2), "X" (f3));
+  return ret;
+}
+
+static inline void *
+ifunc_one (int (*f1) (void))
+{
+  register void *ret __asm__ ("r3");
+  __asm__ ("mflr 12\n\t"
+	   "bcl 20,31,1f\n"
+	   "1:\tmflr %0\n\t"
+	   "mtlr 12\n\t"
+	   "addis %0,%0,%1-1b@ha\n\t"
+	   "addi %0,%0,%1-1b@l"
+	   : "=r" (ret)
+	   : "X" (f1));
+  return ret;
+}
+#endif

http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=51a71cf063505d689337cf998670691a0a4b2410

commit 51a71cf063505d689337cf998670691a0a4b2410
Author: Ulrich Drepper <drepper@redhat.com>
Date:   Fri Oct 30 00:41:33 2009 -0700

    Mention IFUNC for PPC.

diff --git a/NEWS b/NEWS
index 04a6b8c..30af08d 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,8 @@ Version 2.11
 * STT_GNU_IFUNC is now supported in static executables.
   Implemented by H.J. Lu.
 
+* STT_GNU_IFUNC implemented for PPC by Alan Modra.
+
 * New optimized string functions for x86-64: strstr, strcasestr, memcmp,
   strcspn, strpbrk, strspn, strcpy, stpcpy, strncpy, strcmp (SSE2, SSE4.2),
   strncmp (SSE2, SSE4.2), strchr (SSE4.2), strrchr (SSE4.2).

http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=77799d9d9b3f9c937bd6de035b724b9b272c9227

commit 77799d9d9b3f9c937bd6de035b724b9b272c9227
Author: Alan Modra <amodra@bigpond.net.au>
Date:   Fri Oct 30 00:39:38 2009 -0700

    Implement IFUNC for PPC.

diff --git a/ChangeLog b/ChangeLog
index 5fd0861..3359bc2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,24 @@
-2009-10-30  Ulrich Drepper  <drepper@redhat.com>
+2009-07-30  Alan Modra  <amodra@bigpond.net.au>
+
+	* elf/elf.h (R_PPC_NUM, R_PPC64_NUM): Delete unused and incorrect.
+	(R_PPC_REL16*): Correct comments.
+	(R_PPC_IRELATIVE, R_PPC64_IRELATIVE, R_PPC64_JMP_IREL): Define.
+	(R_PPC64_REL16, R_PPC64_REL16_LO, R_PPC64_REL16_HI,
+	 R_PPC64_REL16_HA): Define.
+	* sysdeps/powerpc/powerpc32/dl-irel.h: New file.
+	* sysdeps/powerpc/powerpc64/dl-irel.h: New file.
+	* sysdeps/powerpc/powerpc32/dl-machine.c (__elf_machine_fixup_plt):
+	Delete unused "reloc" param.
+	(__process_machine_rela): Handle R_PPC_IRELATIVE.
+	* sysdeps/powerpc/powerpc32/dl-machine.h (__elf_machine_fixup_plt):
+	Delete "reloc" param.
+	(elf_machine_rela): Handle STT_GNU_IFUNC functions and
+	R_PPC_IRELATIVE.
+	* sysdeps/powerpc/powerpc64/dl-machine.h (resolve_ifunc): New function.
+	(elf_machine_rela): Handle STT_GNU_IFUNC functions and new ifunc
+	relocations.
+
+d2009-10-30  Ulrich Drepper  <drepper@redhat.com>
 
 	[BZ #10315]
 	* sysdeps/gnu/netinet/udp.h: Define UDP_CORK, UDP_ENCAP,
diff --git a/elf/elf.h b/elf/elf.h
index ce6de07..c772ff4 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2041,9 +2041,6 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC_GOT_DTPREL16_HI	93 /* half16*	(sym+add)@got@dtprel@h */
 #define R_PPC_GOT_DTPREL16_HA	94 /* half16*	(sym+add)@got@dtprel@ha */
 
-/* Keep this the last entry.  */
-#define R_PPC_NUM		95
-
 /* The remaining relocs are from the Embedded ELF ABI, and are not
    in the SVR4 ELF ABI.  */
 #define R_PPC_EMB_NADDR32	101
@@ -2071,11 +2068,14 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC_DIAB_RELSDA_HI	184	/* like EMB_RELSDA, but high 16 bit */
 #define R_PPC_DIAB_RELSDA_HA	185	/* like EMB_RELSDA, adjusted high 16 */
 
+/* GNU extension to support local ifunc.  */
+#define R_PPC_IRELATIVE		248
+
 /* GNU relocs used in PIC code sequences.  */
-#define R_PPC_REL16		249	/* word32   (sym-.) */
-#define R_PPC_REL16_LO		250	/* half16   (sym-.)@l */
-#define R_PPC_REL16_HI		251	/* half16   (sym-.)@h */
-#define R_PPC_REL16_HA		252	/* half16   (sym-.)@ha */
+#define R_PPC_REL16		249	/* half16   (sym+add-.) */
+#define R_PPC_REL16_LO		250	/* half16   (sym+add-.)@l */
+#define R_PPC_REL16_HI		251	/* half16   (sym+add-.)@h */
+#define R_PPC_REL16_HA		252	/* half16   (sym+add-.)@ha */
 
 /* This is a phony reloc to handle any old fashioned TOC16 references
    that may still be in object files.  */
@@ -2197,8 +2197,13 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC64_DTPREL16_HIGHEST 105 /* half16	(sym+add)@dtprel@highest */
 #define R_PPC64_DTPREL16_HIGHESTA 106 /* half16	(sym+add)@dtprel@highesta */
 
-/* Keep this the last entry.  */
-#define R_PPC64_NUM		107
+/* GNU extension to support local ifunc.  */
+#define R_PPC64_JMP_IREL	247
+#define R_PPC64_IRELATIVE	248
+#define R_PPC64_REL16		249	/* half16   (sym+add-.) */
+#define R_PPC64_REL16_LO	250	/* half16   (sym+add-.)@l */
+#define R_PPC64_REL16_HI	251	/* half16   (sym+add-.)@h */
+#define R_PPC64_REL16_HA	252	/* half16   (sym+add-.)@ha */
 
 /* PowerPC64 specific values for the Dyn d_tag field.  */
 #define DT_PPC64_GLINK  (DT_LOPROC + 0)
diff --git a/sysdeps/powerpc/powerpc32/dl-irel.h b/sysdeps/powerpc/powerpc32/dl-irel.h
new file mode 100644
index 0000000..3f204cd
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/dl-irel.h
@@ -0,0 +1,45 @@
+/* Machine-dependent ELF indirect relocation inline functions.
+   PowerPC version.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _DL_IREL_H
+#define _DL_IREL_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define ELF_MACHINE_IRELA	1
+
+static inline void
+__attribute ((always_inline))
+elf_irela (const Elf32_Rela *reloc)
+{
+  unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+
+  if (__builtin_expect (r_type == R_PPC_IRELATIVE, 1))
+    {
+      Elf32_Addr *const reloc_addr = (void *) reloc->r_offset;
+      Elf32_Addr value = ((Elf32_Addr (*) (void)) reloc->r_addend) ();
+      *reloc_addr = value;
+    }
+  else
+    __libc_fatal ("unexpected reloc type in static binary");
+}
+
+#endif /* dl-irel.h */
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c
index 71540bd..ee4c3e0 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.c
+++ b/sysdeps/powerpc/powerpc32/dl-machine.c
@@ -337,7 +337,7 @@ __elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 }
 
 Elf32_Addr
-__elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
+__elf_machine_fixup_plt (struct link_map *map,
 			 Elf32_Addr *reloc_addr, Elf32_Addr finaladdr)
 {
   Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr;
@@ -430,6 +430,10 @@ __process_machine_rela (struct link_map *map,
       *reloc_addr = finaladdr;
       return;
 
+    case R_PPC_IRELATIVE:
+      *reloc_addr = ((Elf32_Addr (*) (void)) finaladdr) ();
+      return;
+
     case R_PPC_UADDR32:
       ((char *) reloc_addr)[0] = finaladdr >> 24;
       ((char *) reloc_addr)[1] = finaladdr >> 16;
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index a50ffdd..6f8d0f5 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -226,7 +226,6 @@ elf_machine_runtime_setup (struct link_map *map,
 
 /* Change the PLT entry whose reloc is 'reloc' to call the actual routine.  */
 extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map,
-					   const Elf32_Rela *reloc,
 					   Elf32_Addr *reloc_addr,
 					   Elf32_Addr finaladdr);
 
@@ -237,7 +236,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t,
 {
   if (map->l_info[DT_PPC(GOT)] == 0)
     /* Handle old style PLT.  */
-    return __elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr);
+    return __elf_machine_fixup_plt (map, reloc_addr, finaladdr);
 
   *reloc_addr = finaladdr;
   return finaladdr;
@@ -317,6 +316,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   value = reloc->r_addend;
 #endif
 
+  if (sym != NULL
+      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
+      && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+    value = ((Elf32_Addr (*) (void)) value) ();
+
   /* A small amount of code is duplicated here for speed.  In libc,
      more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
      libraries, 60% are R_PPC_RELATIVE, 24% are R_PPC_GLOB_DAT or
diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h
new file mode 100644
index 0000000..6cded50
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/dl-irel.h
@@ -0,0 +1,58 @@
+/* Machine-dependent ELF indirect relocation inline functions.
+   PowerPC64 version.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _DL_IREL_H
+#define _DL_IREL_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define ELF_MACHINE_IRELA	1
+
+typedef struct
+{
+  Elf64_Addr fd_func;
+  Elf64_Addr fd_toc;
+  Elf64_Addr fd_aux;
+} Elf64_FuncDesc;
+
+static inline void
+__attribute ((always_inline))
+elf_irela (const Elf64_Rela *reloc)
+{
+  unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
+
+  if (__builtin_expect (r_type == R_PPC64_IRELATIVE, 1))
+    {
+      Elf64_Addr *const reloc_addr = (void *) reloc->r_offset;
+      Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) ();
+      *reloc_addr = value;
+    }
+  else if (__builtin_expect (r_type == R_PPC64_JMP_IREL, 1))
+    {
+      Elf64_Addr *const reloc_addr = (void *) reloc->r_offset;
+      Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) ();
+      *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value;
+    }
+  else
+    __libc_fatal ("unexpected reloc type in static binary");
+}
+
+#endif /* dl-irel.h */
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index b674dbe..8a720ae 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -526,6 +526,29 @@ elf_machine_tprel (struct link_map *map,
 }
 #endif
 
+/* Call function at address VALUE (an OPD entry) to resolve ifunc relocs.  */
+auto inline Elf64_Addr __attribute__ ((always_inline))
+resolve_ifunc (Elf64_Addr value,
+	       const struct link_map *map, const struct link_map *sym_map)
+{
+  /* The function we are calling may not yet have its opd entry relocated.  */
+  Elf64_FuncDesc opd;
+  if (map != sym_map
+#if !defined RTLD_BOOTSTRAP && defined SHARED
+      /* Bootstrap map doesn't have l_relocated set for it.  */
+      && sym_map != &GL(dl_rtld_map)
+#endif
+      && !sym_map->l_relocated)
+    {
+      Elf64_FuncDesc *func = (Elf64_FuncDesc *) value;
+      opd.fd_func = func->fd_func + sym_map->l_addr;
+      opd.fd_toc = func->fd_toc + sym_map->l_addr;
+      opd.fd_aux = func->fd_aux;
+      value = (Elf64_Addr) &opd;
+    }
+  return ((Elf64_Addr (*) (void)) value) ();
+}
+
 /* Perform the relocation specified by RELOC and SYM (which is fully
    resolved).  MAP is the object containing the reloc.  */
 auto inline void __attribute__ ((always_inline))
@@ -550,11 +573,17 @@ elf_machine_rela (struct link_map *map,
   if (__builtin_expect (r_type == R_PPC64_NONE, 0))
     return;
 
-  /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt.  */
+  /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
+     and STT_GNU_IFUNC.  */
   struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
   Elf64_Addr value = ((sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value)
 		      + reloc->r_addend);
 
+  if (sym != NULL
+      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
+      && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+    value = resolve_ifunc (value, map, sym_map);
+
   /* For relocs that don't edit code, return.
      For relocs that might edit instructions, break from the switch.  */
   switch (r_type)
@@ -564,6 +593,14 @@ elf_machine_rela (struct link_map *map,
       *reloc_addr = value;
       return;
 
+    case R_PPC64_IRELATIVE:
+      value = resolve_ifunc (value, map, sym_map);
+      *reloc_addr = value;
+      return;
+
+    case R_PPC64_JMP_IREL:
+      value = resolve_ifunc (value, map, sym_map);
+      /* Fall thru */
     case R_PPC64_JMP_SLOT:
 #ifdef RESOLVE_CONFLICT_FIND_MAP
       elf_machine_plt_conflict (reloc_addr, value);

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                              |   42 ++++++++++++++++++++++-
 NEWS                                   |    2 +
 elf/elf.h                              |   23 ++++++++-----
 elf/ifuncdep2.c                        |   34 +++---------------
 elf/ifuncmain1.c                       |    2 -
 elf/ifuncmain1vis.c                    |    2 -
 elf/ifuncmain2.c                       |    2 -
 elf/ifuncmain5.c                       |    2 -
 elf/ifuncmain6pie.c                    |    3 +-
 elf/ifuncmain7.c                       |    3 +-
 elf/ifuncmod1.c                        |   41 +++++-----------------
 elf/ifuncmod3.c                        |    1 -
 elf/ifuncmod5.c                        |   33 +++---------------
 sysdeps/generic/elf/ifunc-sel.h        |   26 ++++++++++++++
 sysdeps/powerpc/elf/ifunc-sel.h        |   46 +++++++++++++++++++++++++
 sysdeps/powerpc/powerpc32/dl-irel.h    |   45 ++++++++++++++++++++++++
 sysdeps/powerpc/powerpc32/dl-machine.c |    6 +++-
 sysdeps/powerpc/powerpc32/dl-machine.h |    8 +++-
 sysdeps/powerpc/powerpc64/dl-irel.h    |   58 ++++++++++++++++++++++++++++++++
 sysdeps/powerpc/powerpc64/dl-machine.h |   39 +++++++++++++++++++++-
 20 files changed, 305 insertions(+), 113 deletions(-)
 create mode 100644 sysdeps/generic/elf/ifunc-sel.h
 create mode 100644 sysdeps/powerpc/elf/ifunc-sel.h
 create mode 100644 sysdeps/powerpc/powerpc32/dl-irel.h
 create mode 100644 sysdeps/powerpc/powerpc64/dl-irel.h


hooks/post-receive
-- 
GNU C Library master sources


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