PATCH: Support R_*_IRELATIVE in static executables

H.J. Lu hjl.tools@gmail.com
Fri May 29 14:51:00 GMT 2009


On Thu, May 28, 2009 at 1:09 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> Hi,
>
> Here is the total rewrite of STT_GNU_IFUNC support
> with R_*_IRELATIVE for i386 and x86-64 on shared
> library and static/dynamic executables together with
> a modified glibc.  OK for trunk?
>


Here the glibc patch to support  R_*_IRELATIVE in
static executables. Need the above linker patch to
build.


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

	* csu/elf-init.c: Include <link.h> and <dl-irel.h> if
	LIBC_NONSHARED is not defined.
	(__rela_iplt_start): New.
	(__rela_iplt_end): Likewise.
	(__rel_iplt_start): Likewise.
	(__rel_iplt_end): Likewise.
	(__libc_csu_init): Process __rela_iplt_start and
	__rel_iplt_start.

	* sysdeps/generic/dl-irel.h: New.
	* sysdeps/i386/dl-irel.h: Likewise.
	* sysdeps/x86_64/dl-irel.h: Likewise.
-------------- next part --------------
2009-05-28  H.J. Lu  <hongjiu.lu@intel.com>

	* csu/elf-init.c: Include <link.h> and <dl-irel.h> if
	LIBC_NONSHARED is not defined.
	(__rela_iplt_start): New.
	(__rela_iplt_end): Likewise.
	(__rel_iplt_start): Likewise.
	(__rel_iplt_end): Likewise.
	(__libc_csu_init): Process __rela_iplt_start and
	__rel_iplt_start.

	* sysdeps/generic/dl-irel.h: New.
	* sysdeps/i386/dl-irel.h: Likewise.
	* sysdeps/x86_64/dl-irel.h: Likewise.

diff --git a/csu/elf-init.c b/csu/elf-init.c
index 27eae15..b1c4a05 100644
--- a/csu/elf-init.c
+++ b/csu/elf-init.c
@@ -35,7 +35,21 @@
    02111-1307 USA.  */
 
 #include <stddef.h>
+#ifndef LIBC_NONSHARED
+#include <link.h>
+#include <dl-irel.h>
+
+#ifdef ELF_MACHINE_IRELA
+extern const ElfW(Rela) __rela_iplt_start [];
+extern const ElfW(Rela) __rela_iplt_end [];
+#endif
+
+#ifdef ELF_MACHINE_IREL
+extern const ElfW(Rel) __rel_iplt_start [];
+extern const ElfW(Rel) __rel_iplt_end [];
+#endif
 
+#endif	/* LIBC_NONSHARED */
 
 /* These magic symbols are provided by the linker.  */
 extern void (*__preinit_array_start []) (int, char **, char **)
@@ -67,6 +81,24 @@ __libc_csu_init (int argc, char **argv, char **envp)
      the dynamic linker (before initializing any shared object.  */
 
 #ifndef LIBC_NONSHARED
+#ifdef ELF_MACHINE_IRELA
+  {
+    const size_t size = __rela_iplt_end - __rela_iplt_start;
+    size_t i;
+    for (i = 0; i < size; i++)
+      elf_irela (&__rela_iplt_start [i]);
+  }
+#endif
+
+#ifdef ELF_MACHINE_IREL
+  {
+    const size_t size = __rel_iplt_end - __rel_iplt_start;
+    size_t i;
+    for (i = 0; i < size; i++)
+      elf_irel (&__rel_iplt_start [i]);
+  }
+#endif
+
   /* For static executables, preinit happens rights before init.  */
   {
     const size_t size = __preinit_array_end - __preinit_array_start;
diff --git a/sysdeps/generic/dl-irel.h b/sysdeps/generic/dl-irel.h
new file mode 100644
index 0000000..c7d8adb
--- /dev/null
+++ b/sysdeps/generic/dl-irel.h
@@ -0,0 +1,23 @@
+/* Machine-dependent ELF indirect relocation inline functions.
+   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
+
+#endif /* !dl_irel_h */
diff --git a/sysdeps/i386/dl-irel.h b/sysdeps/i386/dl-irel.h
new file mode 100644
index 0000000..8dff42f
--- /dev/null
+++ b/sysdeps/i386/dl-irel.h
@@ -0,0 +1,49 @@
+/* Machine-dependent ELF indirect relocation inline functions.
+   i386 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 <unistd.h>
+
+#define ELF_MACHINE_IREL	1
+
+#if 0
+static inline void
+__attribute ((always_inline))
+#else
+static void
+__attribute ((noinline))
+#endif
+elf_irel (const Elf32_Rel *reloc)
+{
+  Elf32_Addr *const reloc_addr = (void *) reloc->r_offset;
+  const unsigned long int r_type = ELF32_R_TYPE (reloc->r_info);
+
+  if (__builtin_expect (r_type == R_386_IRELATIVE, 1))
+    {
+      Elf64_Addr value = ((Elf32_Addr (*) (void)) (*reloc_addr)) ();
+      *reloc_addr = value;
+    }
+  else
+    _exit (-1);
+}
+
+#endif /* !dl_irel_h */
diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h
new file mode 100644
index 0000000..d0e5d47
--- /dev/null
+++ b/sysdeps/x86_64/dl-irel.h
@@ -0,0 +1,44 @@
+/* Machine-dependent ELF indirect relocation inline functions.
+   x86-64 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 <unistd.h>
+
+#define ELF_MACHINE_IRELA	1
+
+static inline void
+__attribute ((always_inline))
+elf_irela (const Elf64_Rela *reloc)
+{
+  Elf64_Addr *const reloc_addr = (void *) reloc->r_offset;
+  const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
+
+  if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 1))
+    {
+      Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) ();
+      *reloc_addr = value;
+    }
+  else
+    _exit (-1);
+}
+
+#endif /* !dl_irel_h */


More information about the Libc-alpha mailing list