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