PATCH: Make STT_GNU_IFUNC symbol dynamic
H.J. Lu
hjl.tools@gmail.com
Mon May 25 22:55:00 GMT 2009
On Sun, May 24, 2009 at 8:50 AM, Ulrich Drepper <drepper@redhat.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> H.J. Lu wrote:
>> If you can check in your glibc patch, I can test my binutis change
>> before I submit it.
>
> Your patch seems fine. You can do testing with it. Once I have such a
> binutils version myself and can test it I'll check it in.
Here is the complete binutils patch for i386 and x86-64, tested wih
the enclosed glibc patch on Linux/ia32 and Linux/Intel64. I will check
it into binutlls trunk if I don't hear any objections within 12 hours.
BTW, I will post a summary to x86-64 and ia32 psABI mailing list after
my binutils patch is checked in.
Thanks.
--
H.J.
---
bfd/
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_howto_table): Add R_386_IRELATIVE.
(elf_i386_reloc_type_lookup): Likewise.
(R_386_tls): Removed.
(R_386_irelative): New.
(R_386_vt_offset): Updated.
(elf_i386_rtype_to_howto): Likewise.
(elf_i386_finish_dynamic_symbol): Generate R_386_IRELATIVE
relocation for local STT_GNU_IFUNC symbol.
* elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_IRELATIVE.
(x86_64_reloc_map): Likewise.
(R_X86_64_standard): Updated.
(elf64_x86_64_finish_dynamic_symbol): Generate R_X86_64_IRELATIVE
relocation for local STT_GNU_IFUNC symbol.
* elflink.c (_bfd_elf_symbol_refs_local_p): Return FALSE on
STT_GNU_IFUNC symbol.
(_bfd_elf_link_hash_hide_symbol): Don't clean plt on
STT_GNU_IFUNC symbol.
* reloc.c (BFD_RELOC_386_IRELATIVE): New.
(BFD_RELOC_X86_64_IRELATIVE): Likewise.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
include/elf/
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* i386.h (R_386_IRELATIVE): New.
* x86-64.h (R_X86_64_IRELATIVE): Likewise.
ld/testsuite/
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* ld-ifunc/ifunc.exp: Run *.d.
* ld-ifunc/ifunc-1-x86.d: New.
* ld-ifunc/ifunc-1-x86.s: Likewise.
-------------- next part --------------
bfd/
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_howto_table): Add R_386_IRELATIVE.
(elf_i386_reloc_type_lookup): Likewise.
(R_386_tls): Removed.
(R_386_irelative): New.
(R_386_vt_offset): Updated.
(elf_i386_rtype_to_howto): Likewise.
(elf_i386_finish_dynamic_symbol): Generate R_386_IRELATIVE
relocation for local STT_GNU_IFUNC symbol.
* elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_IRELATIVE.
(x86_64_reloc_map): Likewise.
(R_X86_64_standard): Updated.
(elf64_x86_64_finish_dynamic_symbol): Generate R_X86_64_IRELATIVE
relocation for local STT_GNU_IFUNC symbol.
* elflink.c (_bfd_elf_symbol_refs_local_p): Return FALSE on
STT_GNU_IFUNC symbol.
(_bfd_elf_link_hash_hide_symbol): Don't clean plt on
STT_GNU_IFUNC symbol.
* reloc.c (BFD_RELOC_386_IRELATIVE): New.
(BFD_RELOC_X86_64_IRELATIVE): Likewise.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
include/elf/
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* i386.h (R_386_IRELATIVE): New.
* x86-64.h (R_X86_64_IRELATIVE): Likewise.
ld/testsuite/
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* ld-ifunc/ifunc.exp: Run *.d.
* ld-ifunc/ifunc-1-x86.d: New.
* ld-ifunc/ifunc-1-x86.s: Likewise.
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc \
../binutils/src binutils
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/bfd/bfd-in2.h binutils/bfd/bfd-in2.h
--- ../binutils/src/bfd/bfd-in2.h 2009-05-22 11:13:32.000000000 -0700
+++ binutils/bfd/bfd-in2.h 2009-05-24 07:26:08.000000000 -0700
@@ -2837,6 +2837,7 @@ relaxation. */
BFD_RELOC_386_TLS_GOTDESC,
BFD_RELOC_386_TLS_DESC_CALL,
BFD_RELOC_386_TLS_DESC,
+ BFD_RELOC_386_IRELATIVE,
/* x86-64/elf relocations */
BFD_RELOC_X86_64_GOT32,
@@ -2865,6 +2866,7 @@ relaxation. */
BFD_RELOC_X86_64_GOTPC32_TLSDESC,
BFD_RELOC_X86_64_TLSDESC_CALL,
BFD_RELOC_X86_64_TLSDESC,
+ BFD_RELOC_X86_64_IRELATIVE,
/* ns32k relocations */
BFD_RELOC_NS32K_IMM_8,
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/bfd/elf32-i386.c binutils/bfd/elf32-i386.c
--- ../binutils/src/bfd/elf32-i386.c 2009-05-05 13:59:47.000000000 -0700
+++ binutils/bfd/elf32-i386.c 2009-05-24 19:00:11.000000000 -0700
@@ -138,10 +138,13 @@ static reloc_howto_type elf_howto_table[
HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_TLS_DESC",
TRUE, 0xffffffff, 0xffffffff, FALSE),
+ HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_generic_reloc, "R_386_IRELATIVE",
+ TRUE, 0xffffffff, 0xffffffff, FALSE),
/* Another gap. */
-#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset)
-#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls)
+#define R_386_irelative (R_386_IRELATIVE + 1 - R_386_tls_offset)
+#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_irelative)
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_386_GNU_VTINHERIT, /* type */
@@ -316,6 +319,10 @@ elf_i386_reloc_type_lookup (bfd *abfd AT
TRACE ("BFD_RELOC_386_TLS_DESC");
return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
+ case BFD_RELOC_386_IRELATIVE:
+ TRACE ("BFD_RELOC_386_IRELATIVE");
+ return &elf_howto_table[R_386_IRELATIVE];
+
case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT");
return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -355,9 +362,9 @@ elf_i386_rtype_to_howto (bfd *abfd, unsi
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
>= R_386_ext - R_386_standard)
&& ((indx = r_type - R_386_tls_offset) - R_386_ext
- >= R_386_tls - R_386_ext)
- && ((indx = r_type - R_386_vt_offset) - R_386_tls
- >= R_386_vt - R_386_tls))
+ >= R_386_irelative - R_386_ext)
+ && ((indx = r_type - R_386_vt_offset) - R_386_irelative
+ >= R_386_vt - R_386_irelative))
{
(*_bfd_error_handler) (_("%B: invalid relocation type %d"),
abfd, (int) r_type);
@@ -2606,7 +2613,7 @@ elf_i386_relocate_section (bfd *output_b
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
>= R_386_ext - R_386_standard)
&& ((indx = r_type - R_386_tls_offset) - R_386_ext
- >= R_386_tls - R_386_ext))
+ >= R_386_irelative - R_386_ext))
{
(*_bfd_error_handler)
(_("%B: unrecognized relocation (0x%x) in section `%A'"),
@@ -3684,7 +3691,10 @@ elf_i386_finish_dynamic_symbol (bfd *out
/* This symbol has an entry in the procedure linkage table. Set
it up. */
- if (h->dynindx == -1
+ if ((h->dynindx == -1
+ && !(h->forced_local
+ && h->def_regular
+ && ELF_ST_TYPE (h->type) == STT_GNU_IFUNC))
|| htab->splt == NULL
|| htab->sgotplt == NULL
|| htab->srelplt == NULL)
@@ -3773,7 +3783,18 @@ elf_i386_finish_dynamic_symbol (bfd *out
rel.r_offset = (htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset
+ got_offset);
- rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
+ if (h->dynindx != -1)
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
+ else
+ {
+ /* Store addend in the .got.plt section. */
+ bfd_put_32 (output_bfd,
+ (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset),
+ htab->sgotplt->contents + got_offset);
+ rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+ }
loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rel);
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/bfd/elf64-x86-64.c binutils/bfd/elf64-x86-64.c
--- ../binutils/src/bfd/elf64-x86-64.c 2009-05-22 12:49:50.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c 2009-05-24 07:21:45.000000000 -0700
@@ -143,12 +143,15 @@ static reloc_howto_type x86_64_elf_howto
complain_overflow_bitfield, bfd_elf_generic_reloc,
"R_X86_64_TLSDESC",
FALSE, MINUS_ONE, MINUS_ONE, FALSE),
+ HOWTO(R_X86_64_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_generic_reloc, "R_X86_64_IRELATIVE", FALSE, MINUS_ONE,
+ MINUS_ONE, FALSE),
/* We have a gap in the reloc numbers here.
R_X86_64_standard counts the number up to this point, and
R_X86_64_vt_offset is the value to subtract from a reloc type of
R_X86_64_GNU_VT* to form an index into this table. */
-#define R_X86_64_standard (R_X86_64_TLSDESC + 1)
+#define R_X86_64_standard (R_X86_64_IRELATIVE + 1)
#define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
/* GNU extension to record C++ vtable hierarchy. */
@@ -211,6 +214,7 @@ static const struct elf_reloc_map x86_64
{ BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
{ BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
{ BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, },
+ { BFD_RELOC_X86_64_IRELATIVE, R_X86_64_IRELATIVE, },
{ BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, },
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, },
};
@@ -3328,7 +3332,10 @@ elf64_x86_64_finish_dynamic_symbol (bfd
/* This symbol has an entry in the procedure linkage table. Set
it up. */
- if (h->dynindx == -1
+ if ((h->dynindx == -1
+ && !(h->forced_local
+ && h->def_regular
+ && ELF_ST_TYPE (h->type) == STT_GNU_IFUNC))
|| htab->splt == NULL
|| htab->sgotplt == NULL
|| htab->srelplt == NULL)
@@ -3381,8 +3388,18 @@ elf64_x86_64_finish_dynamic_symbol (bfd
rela.r_offset = (htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset
+ got_offset);
- rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT);
- rela.r_addend = 0;
+ if (h->dynindx != -1)
+ {
+ rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT);
+ rela.r_addend = 0;
+ }
+ else
+ {
+ rela.r_info = ELF64_R_INFO (0, R_X86_64_IRELATIVE);
+ rela.r_addend = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ }
loc = htab->srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/bfd/elflink.c binutils/bfd/elflink.c
--- ../binutils/src/bfd/elflink.c 2009-05-23 14:39:29.000000000 -0700
+++ binutils/bfd/elflink.c 2009-05-24 06:48:05.000000000 -0700
@@ -2845,6 +2845,10 @@ _bfd_elf_symbol_refs_local_p (struct elf
if (h == NULL)
return TRUE;
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (h->type == STT_GNU_IFUNC)
+ return FALSE;
+
/* STV_HIDDEN or STV_INTERNAL ones must be local. */
if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
@@ -6669,8 +6673,12 @@ _bfd_elf_link_hash_hide_symbol (struct b
struct elf_link_hash_entry *h,
bfd_boolean force_local)
{
- h->plt = elf_hash_table (info)->init_plt_offset;
- h->needs_plt = 0;
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (ELF_ST_TYPE (h->type) != STT_GNU_IFUNC)
+ {
+ h->plt = elf_hash_table (info)->init_plt_offset;
+ h->needs_plt = 0;
+ }
if (force_local)
{
h->forced_local = 1;
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/bfd/libbfd.h binutils/bfd/libbfd.h
--- ../binutils/src/bfd/libbfd.h 2009-05-05 10:56:24.000000000 -0700
+++ binutils/bfd/libbfd.h 2009-05-24 07:26:08.000000000 -0700
@@ -1104,6 +1104,7 @@ static const char *const bfd_reloc_code_
"BFD_RELOC_386_TLS_GOTDESC",
"BFD_RELOC_386_TLS_DESC_CALL",
"BFD_RELOC_386_TLS_DESC",
+ "BFD_RELOC_386_IRELATIVE",
"BFD_RELOC_X86_64_GOT32",
"BFD_RELOC_X86_64_PLT32",
"BFD_RELOC_X86_64_COPY",
@@ -1130,6 +1131,7 @@ static const char *const bfd_reloc_code_
"BFD_RELOC_X86_64_GOTPC32_TLSDESC",
"BFD_RELOC_X86_64_TLSDESC_CALL",
"BFD_RELOC_X86_64_TLSDESC",
+ "BFD_RELOC_X86_64_IRELATIVE",
"BFD_RELOC_NS32K_IMM_8",
"BFD_RELOC_NS32K_IMM_16",
"BFD_RELOC_NS32K_IMM_32",
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/bfd/reloc.c binutils/bfd/reloc.c
--- ../binutils/src/bfd/reloc.c 2009-05-05 10:56:24.000000000 -0700
+++ binutils/bfd/reloc.c 2009-05-24 07:26:01.000000000 -0700
@@ -2492,6 +2492,8 @@ ENUMX
BFD_RELOC_386_TLS_DESC_CALL
ENUMX
BFD_RELOC_386_TLS_DESC
+ENUMX
+ BFD_RELOC_386_IRELATIVE
ENUMDOC
i386/elf relocations
@@ -2547,6 +2549,8 @@ ENUMX
BFD_RELOC_X86_64_TLSDESC_CALL
ENUMX
BFD_RELOC_X86_64_TLSDESC
+ENUMX
+ BFD_RELOC_X86_64_IRELATIVE
ENUMDOC
x86-64/elf relocations
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/include/elf/i386.h binutils/include/elf/i386.h
--- ../binutils/src/include/elf/i386.h 2009-05-05 10:56:16.000000000 -0700
+++ binutils/include/elf/i386.h 2009-05-23 18:06:03.000000000 -0700
@@ -66,6 +66,7 @@ START_RELOC_NUMBERS (elf_i386_reloc_type
RELOC_NUMBER (R_386_TLS_GOTDESC, 39)
RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
RELOC_NUMBER (R_386_TLS_DESC, 41)
+ RELOC_NUMBER (R_386_IRELATIVE, 42) /* Adjust indirectly by program base */
/* Used by Intel. */
RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/include/elf/x86-64.h binutils/include/elf/x86-64.h
--- ../binutils/src/include/elf/x86-64.h 2009-05-05 10:56:16.000000000 -0700
+++ binutils/include/elf/x86-64.h 2009-05-23 18:05:08.000000000 -0700
@@ -71,6 +71,7 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 35) /* Relaxable call through TLS
descriptor. */
RELOC_NUMBER (R_X86_64_TLSDESC, 36) /* 2x64-bit TLS descriptor. */
+ RELOC_NUMBER (R_X86_64_IRELATIVE, 37) /* Adjust indirectly by program base */
RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */
RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */
END_RELOC_NUMBERS (R_X86_64_max)
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/ld/testsuite/ld-ifunc/ifunc-1-x86.d binutils/ld/testsuite/ld-ifunc/ifunc-1-x86.d
--- ../binutils/src/ld/testsuite/ld-ifunc/ifunc-1-x86.d 1969-12-31 16:00:00.000000000 -0800
+++ binutils/ld/testsuite/ld-ifunc/ifunc-1-x86.d 2009-05-24 19:12:28.000000000 -0700
@@ -0,0 +1,7 @@
+#ld: -shared
+#objdump: -dw
+#target: x86_64-*-* i?86-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-fq]+<\*ABS\*@plt>
+#pass
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/ld/testsuite/ld-ifunc/ifunc-1-x86.s binutils/ld/testsuite/ld-ifunc/ifunc-1-x86.s
--- ../binutils/src/ld/testsuite/ld-ifunc/ifunc-1-x86.s 1969-12-31 16:00:00.000000000 -0800
+++ binutils/ld/testsuite/ld-ifunc/ifunc-1-x86.s 2009-05-24 19:11:29.000000000 -0700
@@ -0,0 +1,16 @@
+ .type foo, %gnu_indirect_function
+ .global __GI_foo
+ .hidden __GI_foo
+ .set __GI_foo, foo
+ .text
+.globl foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+.globl bar
+ .type bar, @function
+bar:
+ call __GI_foo@PLT
+ ret
+ .size bar, .-bar
diff -x REVISION -x .svn -x CVS -uprN -x ChangeLog.ifunc ../binutils/src/ld/testsuite/ld-ifunc/ifunc.exp binutils/ld/testsuite/ld-ifunc/ifunc.exp
--- ../binutils/src/ld/testsuite/ld-ifunc/ifunc.exp 2009-05-23 14:39:29.000000000 -0700
+++ binutils/ld/testsuite/ld-ifunc/ifunc.exp 2009-05-24 19:11:29.000000000 -0700
@@ -252,3 +252,10 @@ if { $verbose < 1 } {
remote_file host delete "tmpdir/static_prog"
remote_file host delete "tmpdir/static_nonifunc_prog"
}
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach t $test_list {
+ # We need to strip the ".d", but can leave the dirname.
+ verbose [file rootname $t]
+ run_dump_test [file rootname $t]
+}
-------------- next part --------------
2009-05-24 H.J. Lu <hongjiu.lu@intel.com>
* elf/elf.h (R_386_IRELATIVE): New.
(R_X86_64_IRELATIVE): Likewise.
(R_386_NUM): Updated.
(R_X86_64_NUM): Likewise.
* sysdeps/i386/dl-machine.h (elf_machine_rel): Check SHN_UNDEF
for STT_GNU_IFUNC symbol. Handle R_386_IRELATIVE.
(elf_machine_rela): Likewise.
(elf_machine_lazy_rel): Handle R_386_IRELATIVE.
(elf_machine_lazy_rela): Likewise.
* sysdeps/x86_64/dl-machine.h (elf_machine_rela): Check SHN_UNDEF
for STT_GNU_IFUNC symbol. Handle R_X86_64_IRELATIVE.
(elf_machine_lazy_rel): Handle R_X86_64_IRELATIVE.
diff --git a/elf/elf.h b/elf/elf.h
index 062ef00..8fdf74b 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1177,8 +1177,9 @@ typedef struct
pointer to code and to
argument, returning the TLS
offset for the symbol. */
+#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */
/* Keep this the last entry. */
-#define R_386_NUM 42
+#define R_386_NUM 43
/* SUN SPARC specific definitions. */
@@ -2625,8 +2626,9 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS
descriptor. */
#define R_X86_64_TLSDESC 36 /* TLS descriptor. */
+#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */
-#define R_X86_64_NUM 37
+#define R_X86_64_NUM 38
/* AM33 relocations. */
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 0e15878..efa929e 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -345,6 +345,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
if (sym != NULL
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0))
value = ((Elf32_Addr (*) (void)) value) ();
@@ -471,6 +472,11 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
memcpy (reloc_addr_arg, (void *) value,
MIN (sym->st_size, refsym->st_size));
break;
+ case R_386_IRELATIVE:
+ value = map->l_addr + *reloc_addr;
+ value = ((Elf32_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ break;
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
@@ -500,6 +506,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
if (sym != NULL
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0))
value = ((Elf32_Addr (*) (void)) value) ();
@@ -609,6 +616,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
MIN (sym->st_size, refsym->st_size));
break;
# endif /* !RESOLVE_CONFLICT_FIND_MAP */
+ case R_386_IRELATIVE:
+ value = map->l_addr + reloc->r_addend;
+ value = ((Elf32_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ break;
default:
/* We add these checks in the version to relocate ld.so only
if we are still debugging. */
@@ -703,6 +715,12 @@ elf_machine_lazy_rel (struct link_map *map,
# endif
}
}
+ else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
+ {
+ Elf32_Addr value = map->l_addr + *reloc_addr;
+ value = ((Elf32_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ }
else
_dl_reloc_bad_type (map, r_type, 1);
}
@@ -726,6 +744,12 @@ elf_machine_lazy_rela (struct link_map *map,
td->arg = (void*)reloc;
td->entry = _dl_tlsdesc_resolve_rela;
}
+ else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
+ {
+ Elf32_Addr value = map->l_addr + reloc->r_addend;
+ value = ((Elf32_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ }
else
_dl_reloc_bad_type (map, r_type, 1);
}
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 4444ae0..1b5ce8e 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -297,6 +297,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
: (Elf64_Addr) sym_map->l_addr + sym->st_value);
if (sym != NULL
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0))
value = ((Elf64_Addr (*) (void)) value) ();
@@ -442,6 +443,11 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
}
break;
# endif
+ case R_X86_64_IRELATIVE:
+ value = map->l_addr + reloc->r_addend;
+ value = ((Elf64_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ break;
default:
_dl_reloc_bad_type (map, r_type, 0);
break;
@@ -488,6 +494,12 @@ elf_machine_lazy_rel (struct link_map *map,
td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
+ map->l_addr);
}
+ else if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 0))
+ {
+ Elf64_Addr value = map->l_addr + reloc->r_addend;
+ value = ((Elf64_Addr (*) (void)) value) ();
+ *reloc_addr = value;
+ }
else
_dl_reloc_bad_type (map, r_type, 1);
}
More information about the Libc-alpha
mailing list