This is the mail archive of the libc-alpha@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]

Re: PATCH: Support STT_GNU_IFUNC in executables


On Tue, May 26, 2009 at 02:11:20PM -0700, H.J. Lu wrote:
> Hi,
> 
> We have STT_GNU_IFUNC symbol definitions in executables, which leads
> to DT_TEXTREL. We need to turn on PROT_EXEC during relocation.
> 
> 

"loader" may be NULL when ld.so is run directly. Here is the
updated patch.


H.J.
2009-05-26  H.J. Lu  <hongjiu.lu@intel.com>

	* elf/dl-load.c (open_verify): Set the l_ifunc field.

	* elf/dl-reloc.c (_dl_relocate_object): Add PROT_EXEC for
	DT_TEXTREL if l_ifunc is TRUE.

	* include/link.h (link_map): Add l_ifunc.

	* sysdeps/unix/sysv/linux/ldsodefs.h (HAVE_STT_GNU_IFUNC): New.

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0b896d9..f0d593c 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1737,6 +1737,11 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
 	    }
 	}
 
+#ifdef HAVE_STT_GNU_IFUNC
+      if (__builtin_expect (loader, 1))
+	loader->l_ifunc = HAVE_STT_GNU_IFUNC (ehdr);
+#endif
+
       /* Check .note.ABI-tag if present.  */
       for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
 	if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 28f08de..8b7484f 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -200,6 +200,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
 	  {
 	    struct textrels *newp;
+	    int prot;
 
 	    newp = (struct textrels *) alloca (sizeof (*newp));
 	    newp->len = (((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
@@ -208,7 +209,13 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	    newp->start = ((ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))
 			   + (caddr_t) l->l_addr);
 
-	    if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
+	    /* We need PROT_EXEC for STT_GNU_IFUNC.  */
+	    if (__builtin_expect(l->l_ifunc, 0))
+	      prot = PROT_READ|PROT_WRITE|PROT_EXEC;
+	    else
+	      prot = PROT_READ|PROT_WRITE;
+
+	    if (__mprotect (newp->start, newp->len, prot) < 0)
 	      {
 		errstring = N_("cannot make segment writable for relocation");
 	      call_error:
diff --git a/include/link.h b/include/link.h
index 4b9978a..1281c12 100644
--- a/include/link.h
+++ b/include/link.h
@@ -189,6 +189,7 @@ struct link_map
     unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
 				    mprotected or if no holes are present at
 				    all.  */
+    unsigned int l_ifunc:1;	/* Nonzero if object has STT_GNU_IFUNC.  */
 
     /* Collected information about own RPATH directories.  */
     struct r_search_path_struct l_rpath_dirs;
diff --git a/sysdeps/unix/sysv/linux/ldsodefs.h b/sysdeps/unix/sysv/linux/ldsodefs.h
index 0965f14..c67a501 100644
--- a/sysdeps/unix/sysv/linux/ldsodefs.h
+++ b/sysdeps/unix/sysv/linux/ldsodefs.h
@@ -73,4 +73,7 @@ extern void _dl_non_dynamic_init (void) internal_function;
     [EI_ABIVERSION] = 0					\
   }
 
+#define HAVE_STT_GNU_IFUNC(ehdr) \
+  ((ehdr)->e_ident[EI_OSABI] == ELFOSABI_LINUX)
+
 #endif /* ldsodefs.h */


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