This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] x86: Add -z print-local-ifuncs to ELF linker
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: binutils at sourceware dot org
- Date: Wed, 7 Jun 2017 06:05:55 -0700
- Subject: [PATCH] x86: Add -z print-local-ifuncs to ELF linker
- Authentication-results: sourceware.org; auth=none
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
Add -z print-local-ifuncs to x86 ELF linker to list local IFUNC functions
when generating executables and shared objects.
Any comments?
H.J.
----
bfd/
* elf32-i386.c (elf_i386_check_relocs): Set local IFUNC symbol
name.
(elf_i386_relocate_section): Print local IFUNC name when
generating R_386_IRELATIVE relocation for -z print-local-ifuncs.
(elf_i386_finish_dynamic_symbol): Likewise.
* elf_x86_64_check_relocs (elf_x86_64_check_relocs): Set local
IFUNC symbol name.
(elf_x86_64_relocate_section): Print local IFUNC name when
generating R_X86_64_IRELATIVE relocation for -z print-local-ifuncs.
(elf_x86_64_finish_dynamic_symbol): Likewise.
include/
* bfdlink.h (bfd_link_info): Add print_local_ifuncs.
ld/
* Makefile.am (ELF_X86_DEPS): Add
$(srcdir)/emulparams/print_local_ifuncs.sh.
* Makefile.in: Regenerated.
* NEWS: Mention -z print-local-ifuncs.
* emulparams/elf32_x86_64.sh: Source
${srcdir}/emulparams/print_local_ifuncs.sh.
* emulparams/elf_i386.sh: Likewise.
* emulparams/elf_x86_64.sh: Likewise.
* ld/emulparams/print_local_ifuncs.sh: New file.
* ld.texinfo: Document -z print-local-ifuncs and
-z noprint-local-ifuncs.
* testsuite/ld-ifunc/ifunc-1-local-x86.d: Pass
-z print-local-ifuncs to ld and expect local IFUNC listing.
* ld-ifunc/ifunc-1-x86.d: Likewise.
---
bfd/elf32-i386.c | 20 ++++++++++++++++++++
bfd/elf64-x86-64.c | 20 ++++++++++++++++++++
include/bfdlink.h | 3 +++
ld/Makefile.am | 3 ++-
ld/Makefile.in | 3 ++-
ld/NEWS | 3 +++
ld/emulparams/elf32_x86_64.sh | 1 +
ld/emulparams/elf_i386.sh | 1 +
ld/emulparams/elf_x86_64.sh | 1 +
ld/emulparams/print_local_ifuncs.sh | 14 ++++++++++++++
ld/ld.texinfo | 6 ++++++
ld/testsuite/ld-ifunc/ifunc-1-local-x86.d | 3 ++-
ld/testsuite/ld-ifunc/ifunc-1-x86.d | 3 ++-
ld/testsuite/ld-ifunc/ifunc.exp | 14 --------------
14 files changed, 77 insertions(+), 18 deletions(-)
create mode 100644 ld/emulparams/print_local_ifuncs.sh
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 1fdc06c..1b25f5f 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1945,6 +1945,8 @@ elf_i386_check_relocs (bfd *abfd,
goto error_return;
/* Fake a STT_GNU_IFUNC symbol. */
+ h->root.root.string = bfd_elf_sym_name (abfd, symtab_hdr,
+ isym, NULL);
h->type = STT_GNU_IFUNC;
h->def_regular = 1;
h->ref_regular = 1;
@@ -4081,6 +4083,12 @@ do_ifunc_pointer:
|| h->forced_local
|| bfd_link_executable (info))
{
+ if (info->print_local_ifuncs)
+ info->callbacks->einfo (_("%B: local IFUNC function `%s' in `%B'\n"),
+ output_bfd,
+ h->root.root.string,
+ h->root.u.def.section->owner);
+
/* This symbol is resolved locally. */
outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
bfd_put_32 (output_bfd,
@@ -5413,6 +5421,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
&& h->def_regular
&& h->type == STT_GNU_IFUNC))
{
+ if (info->print_local_ifuncs)
+ info->callbacks->einfo (_("%B: local IFUNC function `%s' in `%B'\n"),
+ output_bfd,
+ h->root.root.string,
+ h->root.u.def.section->owner);
+
/* If an STT_GNU_IFUNC symbol is locally defined, generate
R_386_IRELATIVE instead of R_386_JUMP_SLOT. Store addend
in the .got.plt section. */
@@ -5548,6 +5562,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
}
if (SYMBOL_REFERENCES_LOCAL (info, h))
{
+ if (info->print_local_ifuncs)
+ info->callbacks->einfo (_("%B: local IFUNC function `%s' in `%B'\n"),
+ output_bfd,
+ h->root.root.string,
+ h->root.u.def.section->owner);
+
bfd_put_32 (output_bfd,
(h->root.u.def.value
+ h->root.u.def.section->output_section->vma
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 7beb78e..8a8558c 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2281,6 +2281,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
goto error_return;
/* Fake a STT_GNU_IFUNC symbol. */
+ h->root.root.string = bfd_elf_sym_name (abfd, symtab_hdr,
+ isym, NULL);
h->type = STT_GNU_IFUNC;
h->def_regular = 1;
h->ref_regular = 1;
@@ -4422,6 +4424,12 @@ do_ifunc_pointer:
|| h->forced_local
|| bfd_link_executable (info))
{
+ if (info->print_local_ifuncs)
+ info->callbacks->einfo (_("%B: local IFUNC function `%s' in `%B'\n"),
+ output_bfd,
+ h->root.root.string,
+ h->root.u.def.section->owner);
+
/* This symbol is resolved locally. */
outrel.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
outrel.r_addend = (h->root.u.def.value
@@ -5791,6 +5799,12 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
&& h->def_regular
&& h->type == STT_GNU_IFUNC))
{
+ if (info->print_local_ifuncs)
+ info->callbacks->einfo (_("%B: local IFUNC function `%s' in `%B'\n"),
+ output_bfd,
+ h->root.root.string,
+ h->root.u.def.section->owner);
+
/* If an STT_GNU_IFUNC symbol is locally defined, generate
R_X86_64_IRELATIVE instead of R_X86_64_JUMP_SLOT. */
rela.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
@@ -5941,6 +5955,12 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
}
if (SYMBOL_REFERENCES_LOCAL (info, h))
{
+ if (info->print_local_ifuncs)
+ info->callbacks->einfo (_("%B: local IFUNC function `%s' in `%B'\n"),
+ output_bfd,
+ h->root.root.string,
+ h->root.u.def.section->owner);
+
rela.r_info = htab->r_info (0,
R_X86_64_IRELATIVE);
rela.r_addend = (h->root.u.def.value
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 2e3f0b1..4973d76 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -461,6 +461,9 @@ struct bfd_link_info
/* TRUE if user should be informed of removed unreferenced sections. */
unsigned int print_gc_sections: 1;
+ /* TRUE if user should be informed of local IFUNC functions. */
+ unsigned int print_local_ifuncs: 1;
+
/* TRUE if we should warn alternate ELF machine code. */
unsigned int warn_alternate_em: 1;
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 3aa7e80..09074e0 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -677,7 +677,8 @@ ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \
$(srcdir)/emulparams/extern_protected_data.sh \
$(srcdir)/emulparams/dynamic_undefined_weak.sh \
$(srcdir)/emulparams/reloc_overflow.sh \
- $(srcdir)/emulparams/call_nop.sh
+ $(srcdir)/emulparams/call_nop.sh \
+ $(srcdir)/emulparams/print_local_ifuncs.sh
@TDIRS@
diff --git a/ld/Makefile.in b/ld/Makefile.in
index f485f4f..7b8346f 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -932,7 +932,8 @@ ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \
$(srcdir)/emulparams/extern_protected_data.sh \
$(srcdir)/emulparams/dynamic_undefined_weak.sh \
$(srcdir)/emulparams/reloc_overflow.sh \
- $(srcdir)/emulparams/call_nop.sh
+ $(srcdir)/emulparams/call_nop.sh \
+ $(srcdir)/emulparams/print_local_ifuncs.sh
# We need this for automake to use YLWRAP.
diff --git a/ld/NEWS b/ld/NEWS
index 98055b5..b15cc47 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Support for -z print-local-ifuncs in the x86 ELF linker to list all
+ local IFUNC functions.
+
* Add support for ELF SHF_GNU_MBIND and PT_GNU_MBIND_XXX.
* Add support for ELF GNU program properties.
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 9b85239..66a6d8e 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -3,6 +3,7 @@
. ${srcdir}/emulparams/dynamic_undefined_weak.sh
. ${srcdir}/emulparams/reloc_overflow.sh
. ${srcdir}/emulparams/call_nop.sh
+. ${srcdir}/emulparams/print_local_ifuncs.sh
SCRIPT_NAME=elf
ELFSIZE=32
OUTPUT_FORMAT="elf32-x86-64"
diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
index b08e661..a760a01 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -2,6 +2,7 @@
. ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/dynamic_undefined_weak.sh
. ${srcdir}/emulparams/call_nop.sh
+. ${srcdir}/emulparams/print_local_ifuncs.sh
SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-i386"
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index ca6d06c..121e1d7 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -3,6 +3,7 @@
. ${srcdir}/emulparams/dynamic_undefined_weak.sh
. ${srcdir}/emulparams/reloc_overflow.sh
. ${srcdir}/emulparams/call_nop.sh
+. ${srcdir}/emulparams/print_local_ifuncs.sh
SCRIPT_NAME=elf
ELFSIZE=64
OUTPUT_FORMAT="elf64-x86-64"
diff --git a/ld/emulparams/print_local_ifuncs.sh b/ld/emulparams/print_local_ifuncs.sh
new file mode 100644
index 0000000..30ed9a2
--- /dev/null
+++ b/ld/emulparams/print_local_ifuncs.sh
@@ -0,0 +1,14 @@
+PARSE_AND_LIST_OPTIONS_PRINT_LOCAL_IFUNCS='
+ fprintf (file, _("\
+ -z print-local-ifuncs List local IFUNC functions\n\
+ -z noprint-local-ifuncs Do not list local IFUNC functions\n"));
+'
+PARSE_AND_LIST_ARGS_CASE_Z_PRINT_LOCAL_IFUNCS='
+ else if (strcmp (optarg, "print-local-ifuncs") == 0)
+ link_info.print_local_ifuncs = TRUE;
+ else if (strcmp (optarg, "noprint-local-ifuncs") == 0)
+ link_info.print_local_ifuncs = FALSE;
+'
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_PRINT_LOCAL_IFUNCS"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_PRINT_LOCAL_IFUNCS"
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 790b52f..e93f5be 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1261,6 +1261,12 @@ to a locally defined function, foo, via its GOT slot.
@option{call-nop=suffix-@var{byte}} generates @code{call foo @var{byte}}.
Supported for i386 and x86_64.
+@item print-local-ifuncs
+List all local IFUNC functions. Supported for i386 and x86_64.
+
+@item noprint-local-ifuncs
+Don't list local IFUNC functions. Supported for i386 and x86_64.
+
@end table
Other keywords are ignored for Solaris compatibility.
diff --git a/ld/testsuite/ld-ifunc/ifunc-1-local-x86.d b/ld/testsuite/ld-ifunc/ifunc-1-local-x86.d
index 00bc474..cf3b6f2 100644
--- a/ld/testsuite/ld-ifunc/ifunc-1-local-x86.d
+++ b/ld/testsuite/ld-ifunc/ifunc-1-local-x86.d
@@ -1,6 +1,7 @@
-#ld: -shared
+#ld: -shared -z print-local-ifuncs
#objdump: -dw
#target: x86_64-*-* i?86-*-*
+#warning: .*: local IFUNC function `__GI_foo' in `tmpdir/ifunc-1-local-x86.o'
#...
[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-fq]+<\*ABS\*(\+0x160|\+0x170|\+0x1e0|)@plt>
diff --git a/ld/testsuite/ld-ifunc/ifunc-1-x86.d b/ld/testsuite/ld-ifunc/ifunc-1-x86.d
index f9dee1b..70f83d4 100644
--- a/ld/testsuite/ld-ifunc/ifunc-1-x86.d
+++ b/ld/testsuite/ld-ifunc/ifunc-1-x86.d
@@ -1,6 +1,7 @@
-#ld: -shared
+#ld: -shared -z print-local-ifuncs
#objdump: -dw
#target: x86_64-*-* i?86-*-*
+#warning: .*: local IFUNC function `__GI_foo' in `tmpdir/ifunc-1-x86.o'
#...
[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-fq]+<\*ABS\*(\+0x170|\+0x190|\+0x210|)@plt>
diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp
index 9445f9f..75d053a 100644
--- a/ld/testsuite/ld-ifunc/ifunc.exp
+++ b/ld/testsuite/ld-ifunc/ifunc.exp
@@ -43,10 +43,6 @@ if {!(([istarget "i?86-*-*"]
# Skip targets where -shared is not supported
-if ![check_shared_lib_support] {
- return
-}
-
# We need a working compiler. (Strictly speaking this is
# not true, we could use target specific assembler files).
if { [which $CC] == 0 } {
@@ -206,10 +202,6 @@ if ![ar_simple_create $ar "" "tmpdir/libifunc.a" "tmpdir/static_ifunc.o"] {
set fails [expr $fails + 1]
}
-if { $fails != 0 } {
- return
-}
-
if ![ld_link $CC "tmpdir/dynamic_prog" "-Wl,--no-as-needed,-rpath=./tmpdir,-Bdynamic -Ltmpdir tmpdir/shared_prog.o -lshared_ifunc"] {
fail "Could not link a dynamic executable"
set fails [expr $fails + 1]
@@ -242,8 +234,6 @@ if ![ld_link $ld "tmpdir/libtest-2-now.so" "-shared -z now tmpdir/test-2.o"] {
if { $fails == 0 } {
pass "Building ifunc binaries"
set fails 0
-} else {
- return
}
# Check the executables and shared libraries
@@ -427,10 +417,6 @@ foreach t $test_list {
}
# Run-time tests which require working IFUNC support.
-if { ![check_ifunc_available] } {
- return
-}
-
run_cc_link_tests [list \
[list \
"Build ifunc-lib.so" \
--
2.9.4