diff mbox series

RFC: Add DT_FLAGS_2 and DF_2_GNU_IFUNC

Message ID 20180525174725.GA8012@intel.com
State New
Headers show
Series RFC: Add DT_FLAGS_2 and DF_2_GNU_IFUNC | expand

Commit Message

H.J. Lu May 25, 2018, 5:47 p.m. UTC
As shown in

https://sourceware.org/bugzilla/show_bug.cgi?id=20019

it is possible to create a shared object which references an IFUNC
function defined in another shared object.  With non-lazy binding at
run-time, usage of such a shared object can lead to segfault.  The
issue is the shared object, which provides the IFUNC function, isn't
in DT_NEEDED and dynamic linker tries to resolve the reference to the
IFUNC function defined in the unrelocated shared object with non-lazy
binding.  Currently, the glibc dynamic linker issues a warning:

[hjl@gnu-cfl-1 pr20019]$ ./main-dynamic
./main-dynamic: Relink `./libbar.so' with `/export/build/gnu/glibc/build-x86_64-linux/libc.so.6' for IFUNC symbol `memmove'
Segmentation fault
[hjl@gnu-cfl-1 pr20019]$

But it doesn't prevent segfault.

This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
that a shared object or executable has IFUNC symbols so that dynamic
linker can relocate it early.

bfd/

	* elflink.c (bfd_elf_size_dynamic_sections): Set DF_2_GNU_IFUNC
	if there are GNU IFUNC symbols in shared objects or executables
	with interpreter.

binutils/

	* readelf.c (get_dynamic_type): Handle DT_FLAGS_2.
	(process_dynamic_section): Handle DT_FLAGS_2 and DF_2_GNU_IFUNC.

include/

	* bfdlink.h (bfd_link_info): Add flags_2.
	* elf/common.h (DT_FLAGS_2): New.
	(DF_2_GNU_IFUNC): Likewise.

ld/

	* testsuite/ld-ifunc/ifunc-2-i386-now.d: Updated.
	* testsuite/ld-ifunc/ifunc-2-local-i386-now.d: Likewise.
	* testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d: Likewise.
	* testsuite/ld-ifunc/ifunc-2-x86-64-now.d: Likewise.
	* testsuite/ld-ifunc/pr17154-x86-64-now.d: Likewise.
	* testsuite/ld-ifunc/pr17154-x86-64.d: Likewise.
	* testsuite/ld-x86-64/bnd-ifunc-1-now.d: Likewise.
	* testsuite/ld-x86-64/bnd-ifunc-2-now.d: Likewise.
	* testsuite/ld-x86-64/bnd-ifunc-2.d: Likewise.
	* ld-x86-64/pr20253-1d.d: Likewise.
	* ld-x86-64/pr20253-1f.d: Likewise.
	* ld-x86-64/pr20253-1j.d: Likewise.
	* ld-x86-64/pr20253-1l.d: Likewise.
	* testsuite/ld-ifunc/ifunc-26.d: Pass -d to readelf.  Check
	for DF_2_GNU_IFUNC.
---
 bfd/elflink.c                                 | 12 +++++
 binutils/readelf.c                            | 23 ++++++++
 include/bfdlink.h                             |  3 ++
 include/elf/common.h                          |  5 ++
 ld/testsuite/ld-ifunc/ifunc-2-i386-now.d      |  4 +-
 .../ld-ifunc/ifunc-2-local-i386-now.d         |  4 +-
 .../ld-ifunc/ifunc-2-local-x86-64-now.d       |  6 +--
 ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d    |  6 +--
 ld/testsuite/ld-ifunc/ifunc-26.d              |  4 +-
 ld/testsuite/ld-ifunc/pr17154-x86-64-now.d    | 12 ++---
 ld/testsuite/ld-ifunc/pr17154-x86-64.d        | 12 ++---
 ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d      | 22 ++++----
 ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d      | 54 +++++++++----------
 ld/testsuite/ld-x86-64/bnd-ifunc-2.d          | 20 +++----
 ld/testsuite/ld-x86-64/pr20253-1d.d           | 12 ++---
 ld/testsuite/ld-x86-64/pr20253-1f.d           | 12 ++---
 ld/testsuite/ld-x86-64/pr20253-1j.d           | 12 ++---
 ld/testsuite/ld-x86-64/pr20253-1l.d           | 12 ++---
 18 files changed, 140 insertions(+), 95 deletions(-)

Comments

Florian Weimer May 25, 2018, 8:35 p.m. UTC | #1
On 05/25/2018 07:47 PM, H.J. Lu wrote:
> This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
> that a shared object or executable has IFUNC symbols so that dynamic
> linker can relocate it early.

I don't think this will solve any of the thorny cases.  It may help with 
missing DT_NEEDED entries, but that's only a small subset of the issues, 
and as far as linking against glibc is concerned, such binaries are 
invalid anyway.

Thanks,
Florian
H.J. Lu May 25, 2018, 8:58 p.m. UTC | #2
On Fri, May 25, 2018 at 1:35 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 05/25/2018 07:47 PM, H.J. Lu wrote:
>>
>> This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
>> that a shared object or executable has IFUNC symbols so that dynamic
>> linker can relocate it early.
>
>
> I don't think this will solve any of the thorny cases.  It may help with
> missing DT_NEEDED entries, but that's only a small subset of the issues, and
> as far as linking against glibc is concerned, such binaries are invalid
> anyway.

In my case, LD_PRELOADed shared library is linked against libc.so.  But there
is no dependency on it by definition.
Florian Weimer May 25, 2018, 9:09 p.m. UTC | #3
On 05/25/2018 10:58 PM, H.J. Lu wrote:
> On Fri, May 25, 2018 at 1:35 PM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 05/25/2018 07:47 PM, H.J. Lu wrote:
>>>
>>> This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
>>> that a shared object or executable has IFUNC symbols so that dynamic
>>> linker can relocate it early.
>>
>>
>> I don't think this will solve any of the thorny cases.  It may help with
>> missing DT_NEEDED entries, but that's only a small subset of the issues, and
>> as far as linking against glibc is concerned, such binaries are invalid
>> anyway.
> 
> In my case, LD_PRELOADed shared library is linked against libc.so.  But there
> is no dependency on it by definition.

Still I don't see what this buys you if the LD_PRELOAD object has 
IFUNCs, too.

Thanks,
Florian
H.J. Lu May 25, 2018, 9:18 p.m. UTC | #4
On Fri, May 25, 2018 at 2:09 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 05/25/2018 10:58 PM, H.J. Lu wrote:
>>
>> On Fri, May 25, 2018 at 1:35 PM, Florian Weimer <fweimer@redhat.com>
>> wrote:
>>>
>>> On 05/25/2018 07:47 PM, H.J. Lu wrote:
>>>>
>>>>
>>>> This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
>>>> that a shared object or executable has IFUNC symbols so that dynamic
>>>> linker can relocate it early.
>>>
>>>
>>>
>>> I don't think this will solve any of the thorny cases.  It may help with
>>> missing DT_NEEDED entries, but that's only a small subset of the issues,
>>> and
>>> as far as linking against glibc is concerned, such binaries are invalid
>>> anyway.
>>
>>
>> In my case, LD_PRELOADed shared library is linked against libc.so.  But
>> there
>> is no dependency on it by definition.
>
>
> Still I don't see what this buys you if the LD_PRELOAD object has IFUNCs,
> too.

[hjl@gnu-cfl-1 ifunc-2]$ cat bar.c
void
bar (char *dst, const char *src, unsigned int size)
{
  __builtin_memmove (dst, src, size);
}
[hjl@gnu-cfl-1 ifunc-2]$ cat main.c
extern void bar (char *, const char *, unsigned int);

int
main ()
{
  char dst[50];
  const char src[] =
    {
      "This is a test"
    };
  bar (dst, src, sizeof (src));
  if (__builtin_memcmp (dst, src, sizeof (src)) != 0)
    __builtin_abort ();
  return 0;
}
[hjl@gnu-cfl-1 ifunc-2]$ make
gcc -O2 -g   -c -o main.o main.c
gcc -O2 -g -fPIC   -c -o bar.o bar.c
gcc -shared -z now -o libbar.so bar.o
gcc -z now -o x main.o libbar.so -Wl,-R,.
./x
[hjl@gnu-cfl-1 ifunc-2]$ LD_PRELOAD=./libmemmove.so ./x
./x: Relink `./libbar.so' with `./libmemmove.so' for IFUNC symbol `memmove'
[hjl@gnu-cfl-1 ifunc-2]$
Florian Weimer May 25, 2018, 9:26 p.m. UTC | #5
On 05/25/2018 11:18 PM, H.J. Lu wrote:

>> Still I don't see what this buys you if the LD_PRELOAD object has IFUNCs,
>> too.
> 
> [hjl@gnu-cfl-1 ifunc-2]$ cat bar.c
> void
> bar (char *dst, const char *src, unsigned int size)
> {
>    __builtin_memmove (dst, src, size);
> }
> [hjl@gnu-cfl-1 ifunc-2]$ cat main.c
> extern void bar (char *, const char *, unsigned int);
> 
> int
> main ()
> {
>    char dst[50];
>    const char src[] =
>      {
>        "This is a test"
>      };
>    bar (dst, src, sizeof (src));
>    if (__builtin_memcmp (dst, src, sizeof (src)) != 0)
>      __builtin_abort ();
>    return 0;
> }
> [hjl@gnu-cfl-1 ifunc-2]$ make
> gcc -O2 -g   -c -o main.o main.c
> gcc -O2 -g -fPIC   -c -o bar.o bar.c
> gcc -shared -z now -o libbar.so bar.o
> gcc -z now -o x main.o libbar.so -Wl,-R,.
> ./x
> [hjl@gnu-cfl-1 ifunc-2]$ LD_PRELOAD=./libmemmove.so ./x
> ./x: Relink `./libbar.so' with `./libmemmove.so' for IFUNC symbol `memmove'
> [hjl@gnu-cfl-1 ifunc-2]$

This doesn't reproduce for me.  The commands above do not produce 
libmemmove.so.  “LD_PRELOAD=./libbar.so ./x” does not crash here (with a 
glibc 2.26-derived library that hasn't got my IFUNC scheduler).

Thanks,
Florian
H.J. Lu May 25, 2018, 9:58 p.m. UTC | #6
On Fri, May 25, 2018 at 2:26 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 05/25/2018 11:18 PM, H.J. Lu wrote:
>
>>> Still I don't see what this buys you if the LD_PRELOAD object has IFUNCs,
>>> too.
>>
>>
>> [hjl@gnu-cfl-1 ifunc-2]$ cat bar.c
>> void
>> bar (char *dst, const char *src, unsigned int size)
>> {
>>    __builtin_memmove (dst, src, size);
>> }
>> [hjl@gnu-cfl-1 ifunc-2]$ cat main.c
>> extern void bar (char *, const char *, unsigned int);
>>
>> int
>> main ()
>> {
>>    char dst[50];
>>    const char src[] =
>>      {
>>        "This is a test"
>>      };
>>    bar (dst, src, sizeof (src));
>>    if (__builtin_memcmp (dst, src, sizeof (src)) != 0)
>>      __builtin_abort ();
>>    return 0;
>> }
>> [hjl@gnu-cfl-1 ifunc-2]$ make
>> gcc -O2 -g   -c -o main.o main.c
>> gcc -O2 -g -fPIC   -c -o bar.o bar.c
>> gcc -shared -z now -o libbar.so bar.o
>> gcc -z now -o x main.o libbar.so -Wl,-R,.
>> ./x
>> [hjl@gnu-cfl-1 ifunc-2]$ LD_PRELOAD=./libmemmove.so ./x
>> ./x: Relink `./libbar.so' with `./libmemmove.so' for IFUNC symbol
>> `memmove'
>> [hjl@gnu-cfl-1 ifunc-2]$
>
>
> This doesn't reproduce for me.  The commands above do not produce
> libmemmove.so.  “LD_PRELOAD=./libbar.so ./x” does not crash here (with a
> glibc 2.26-derived library that hasn't got my IFUNC scheduler).
>

https://sourceware.org/bugzilla/show_bug.cgi?id=23240
Florian Weimer May 25, 2018, 10:05 p.m. UTC | #7
On 05/25/2018 11:58 PM, H.J. Lu wrote:
> On Fri, May 25, 2018 at 2:26 PM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 05/25/2018 11:18 PM, H.J. Lu wrote:
>>
>>>> Still I don't see what this buys you if the LD_PRELOAD object has IFUNCs,
>>>> too.
>>>
>>>
>>> [hjl@gnu-cfl-1 ifunc-2]$ cat bar.c
>>> void
>>> bar (char *dst, const char *src, unsigned int size)
>>> {
>>>     __builtin_memmove (dst, src, size);
>>> }
>>> [hjl@gnu-cfl-1 ifunc-2]$ cat main.c
>>> extern void bar (char *, const char *, unsigned int);
>>>
>>> int
>>> main ()
>>> {
>>>     char dst[50];
>>>     const char src[] =
>>>       {
>>>         "This is a test"
>>>       };
>>>     bar (dst, src, sizeof (src));
>>>     if (__builtin_memcmp (dst, src, sizeof (src)) != 0)
>>>       __builtin_abort ();
>>>     return 0;
>>> }
>>> [hjl@gnu-cfl-1 ifunc-2]$ make
>>> gcc -O2 -g   -c -o main.o main.c
>>> gcc -O2 -g -fPIC   -c -o bar.o bar.c
>>> gcc -shared -z now -o libbar.so bar.o
>>> gcc -z now -o x main.o libbar.so -Wl,-R,.
>>> ./x
>>> [hjl@gnu-cfl-1 ifunc-2]$ LD_PRELOAD=./libmemmove.so ./x
>>> ./x: Relink `./libbar.so' with `./libmemmove.so' for IFUNC symbol
>>> `memmove'
>>> [hjl@gnu-cfl-1 ifunc-2]$
>>
>>
>> This doesn't reproduce for me.  The commands above do not produce
>> libmemmove.so.  “LD_PRELOAD=./libbar.so ./x” does not crash here (with a
>> glibc 2.26-derived library that hasn't got my IFUNC scheduler).

(some commands are missing from the reproduction steps)

> https://sourceware.org/bugzilla/show_bug.cgi?id=23240

This is just the old known issue related to symbol interposition and 
IFUNC resolvers, where even complete DT_NEEDED information is not 
sufficient to perform the relocations in the correct order.

A single bit will not solve this.  In your reproducer, add an IFUNC 
resolver to libbar.so, and I'm sure the bug will resurface again.

Thanks,
Florian
H.J. Lu May 25, 2018, 10:09 p.m. UTC | #8
On Fri, May 25, 2018 at 3:05 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 05/25/2018 11:58 PM, H.J. Lu wrote:
>>
>> On Fri, May 25, 2018 at 2:26 PM, Florian Weimer <fweimer@redhat.com>
>> wrote:
>>>
>>> On 05/25/2018 11:18 PM, H.J. Lu wrote:
>>>
>>>>> Still I don't see what this buys you if the LD_PRELOAD object has
>>>>> IFUNCs,
>>>>> too.
>>>>
>>>>
>>>>
>>>> [hjl@gnu-cfl-1 ifunc-2]$ cat bar.c
>>>> void
>>>> bar (char *dst, const char *src, unsigned int size)
>>>> {
>>>>     __builtin_memmove (dst, src, size);
>>>> }
>>>> [hjl@gnu-cfl-1 ifunc-2]$ cat main.c
>>>> extern void bar (char *, const char *, unsigned int);
>>>>
>>>> int
>>>> main ()
>>>> {
>>>>     char dst[50];
>>>>     const char src[] =
>>>>       {
>>>>         "This is a test"
>>>>       };
>>>>     bar (dst, src, sizeof (src));
>>>>     if (__builtin_memcmp (dst, src, sizeof (src)) != 0)
>>>>       __builtin_abort ();
>>>>     return 0;
>>>> }
>>>> [hjl@gnu-cfl-1 ifunc-2]$ make
>>>> gcc -O2 -g   -c -o main.o main.c
>>>> gcc -O2 -g -fPIC   -c -o bar.o bar.c
>>>> gcc -shared -z now -o libbar.so bar.o
>>>> gcc -z now -o x main.o libbar.so -Wl,-R,.
>>>> ./x
>>>> [hjl@gnu-cfl-1 ifunc-2]$ LD_PRELOAD=./libmemmove.so ./x
>>>> ./x: Relink `./libbar.so' with `./libmemmove.so' for IFUNC symbol
>>>> `memmove'
>>>> [hjl@gnu-cfl-1 ifunc-2]$
>>>
>>>
>>>
>>> This doesn't reproduce for me.  The commands above do not produce
>>> libmemmove.so.  “LD_PRELOAD=./libbar.so ./x” does not crash here (with a
>>> glibc 2.26-derived library that hasn't got my IFUNC scheduler).
>
>
> (some commands are missing from the reproduction steps)
>
>> https://sourceware.org/bugzilla/show_bug.cgi?id=23240
>
>
> This is just the old known issue related to symbol interposition and IFUNC
> resolvers, where even complete DT_NEEDED information is not sufficient to
> perform the relocations in the correct order.
>
> A single bit will not solve this.  In your reproducer, add an IFUNC resolver
> to libbar.so, and I'm sure the bug will resurface again.

Can you add a complete testcase to

https://sourceware.org/bugzilla/show_bug.cgi?id=23240
Florian Weimer May 25, 2018, 10:16 p.m. UTC | #9
On 05/26/2018 12:09 AM, H.J. Lu wrote:

>> This is just the old known issue related to symbol interposition and IFUNC
>> resolvers, where even complete DT_NEEDED information is not sufficient to
>> perform the relocations in the correct order.
>>
>> A single bit will not solve this.  In your reproducer, add an IFUNC resolver
>> to libbar.so, and I'm sure the bug will resurface again.
> 
> Can you add a complete testcase to
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=23240

Let's not clutter Bugzilla unnecessarily.

Try this with your patched toolchain:


void
bar (char *dst, const char *src, unsigned int size)
{
   __builtin_memmove (dst, src, size);
}

void unused_func (void) __attribute__ ((ifunc ("resolve_unused_func")));

static void *
resolve_unused_func (void)
{
   return 0;
}


It should result in libbar.so having the DF_2_GNU_IFUNC flag (please 
verify with readelf).  I expect that with your ld.so patch, we again 
relocate libbar.so first, leading to exactly the same crash.

I hope this makes it clearer what I'm worried about.

Thanks,
Florian
Carlos O'Donell May 28, 2018, 4:52 p.m. UTC | #10
On 05/25/2018 01:47 PM, H.J. Lu wrote:
> As shown in
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=20019
> 
> it is possible to create a shared object which references an IFUNC
> function defined in another shared object.  

Which is not allowed in the present documentation:
https://sourceware.org/glibc/wiki/GNU_IFUNC

The GCC documentation says that resolver and implementation should be
in the same translation unit.

My opinion is that we need a *clearer* description of GNU IFUNC before
we move forward with further kludges like this to make singular use
cases work.

At present your CPU dispatching library with LD_PRELOAD is treading
on undocumented or poorly documented behaviour.

> With non-lazy binding at
> run-time, usage of such a shared object can lead to segfault.  The
> issue is the shared object, which provides the IFUNC function, isn't
> in DT_NEEDED and dynamic linker tries to resolve the reference to the
> IFUNC function defined in the unrelocated shared object with non-lazy
> binding.  Currently, the glibc dynamic linker issues a warning:

The usage of GNU IFUNC is a runtime transformation by the dyanmic loader
in much the same way as the static linker.

If the usage of GNU IFUNC creates, at runtime, an additional startup ordering
requirement on a specific shared object, then you have one of a few choices:

* ... the shared object must list the superset of additional requirements
  for all possible resolutions of GNU IFUNC.
  - Burden on the user.

* ... the dynamic loader must have enough information to compute the ordering,
  possibly from relocations.
  - Burden on the dynamic loader.

* ... the dynamic linker can relax the IFUNC resolution until later.
  - Already pointed out that relaxing BIND_NOW is unacceptable, unless it's
    scheduled until later (like Florian's scheduling patch) without deferral.

> [hjl@gnu-cfl-1 pr20019]$ ./main-dynamic
> ./main-dynamic: Relink `./libbar.so' with `/export/build/gnu/glibc/build-x86_64-linux/libc.so.6' for IFUNC symbol `memmove'
> Segmentation fault
> [hjl@gnu-cfl-1 pr20019]$
> 
> But it doesn't prevent segfault.

Correct.

> This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
> that a shared object or executable has IFUNC symbols so that dynamic
> linker can relocate it early.

I would like to see a very clear description of how this impacts GNU IFUNC's
as feature design, and why it's the right solution.

Cheers,
Carlos.
H.J. Lu May 28, 2018, 7:52 p.m. UTC | #11
On Mon, May 28, 2018 at 9:52 AM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 05/25/2018 01:47 PM, H.J. Lu wrote:
>> As shown in
>>
>> https://sourceware.org/bugzilla/show_bug.cgi?id=20019
>>
>> it is possible to create a shared object which references an IFUNC
>> function defined in another shared object.
>
> Which is not allowed in the present documentation:
> https://sourceware.org/glibc/wiki/GNU_IFUNC
>
> The GCC documentation says that resolver and implementation should be
> in the same translation unit.
>
> My opinion is that we need a *clearer* description of GNU IFUNC before
> we move forward with further kludges like this to make singular use
> cases work.
>
> At present your CPU dispatching library with LD_PRELOAD is treading
> on undocumented or poorly documented behaviour.
>
>> With non-lazy binding at
>> run-time, usage of such a shared object can lead to segfault.  The
>> issue is the shared object, which provides the IFUNC function, isn't
>> in DT_NEEDED and dynamic linker tries to resolve the reference to the
>> IFUNC function defined in the unrelocated shared object with non-lazy
>> binding.  Currently, the glibc dynamic linker issues a warning:
>
> The usage of GNU IFUNC is a runtime transformation by the dyanmic loader
> in much the same way as the static linker.
>
> If the usage of GNU IFUNC creates, at runtime, an additional startup ordering
> requirement on a specific shared object, then you have one of a few choices:
>
> * ... the shared object must list the superset of additional requirements
>   for all possible resolutions of GNU IFUNC.
>   - Burden on the user.
>
> * ... the dynamic loader must have enough information to compute the ordering,
>   possibly from relocations.
>   - Burden on the dynamic loader.
>
> * ... the dynamic linker can relax the IFUNC resolution until later.
>   - Already pointed out that relaxing BIND_NOW is unacceptable, unless it's
>     scheduled until later (like Florian's scheduling patch) without deferral.
>
>> [hjl@gnu-cfl-1 pr20019]$ ./main-dynamic
>> ./main-dynamic: Relink `./libbar.so' with `/export/build/gnu/glibc/build-x86_64-linux/libc.so.6' for IFUNC symbol `memmove'
>> Segmentation fault
>> [hjl@gnu-cfl-1 pr20019]$
>>
>> But it doesn't prevent segfault.
>
> Correct.
>
>> This patch extends gABI with DT_FLAGS_2 and DF_2_GNU_IFUNC to indicate
>> that a shared object or executable has IFUNC symbols so that dynamic
>> linker can relocate it early.
>
> I would like to see a very clear description of how this impacts GNU IFUNC's
> as feature design, and why it's the right solution.

I withdrew this.
diff mbox series

Patch

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 05d0771a9a..5067bcc07a 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -6893,6 +6893,18 @@  bfd_elf_size_dynamic_sections (bfd *output_bfd,
 	    return FALSE;
 	}
 
+      /* Set DF_2_GNU_IFUNC if there are GNU IFUNC symbols in
+	 shared objects or executables with interpreter.  */
+      if ((bfd_link_dll (info) || !info->nointerp)
+	  && (elf_tdata (output_bfd)->has_gnu_symbols
+	      & elf_gnu_symbol_ifunc))
+	info->flags_2 |= DF_2_GNU_IFUNC;
+
+      if (info->flags_2
+	  && !_bfd_elf_add_dynamic_entry (info, DT_FLAGS_2,
+					  info->flags_2))
+	return FALSE;
+
       if (elf_tdata (output_bfd)->cverrefs)
 	{
 	  unsigned int crefs = elf_tdata (output_bfd)->cverrefs;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 8335538e03..11123cd48d 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2140,6 +2140,7 @@  get_dynamic_type (Filedata * filedata, unsigned long type)
     case DT_RELACOUNT:	return "RELACOUNT";
     case DT_RELCOUNT:	return "RELCOUNT";
     case DT_FLAGS_1:	return "FLAGS_1";
+    case DT_FLAGS_2:	return "FLAGS_2";
     case DT_VERDEF:	return "VERDEF";
     case DT_VERDEFNUM:	return "VERDEFNUM";
     case DT_VERNEED:	return "VERNEED";
@@ -10085,6 +10086,28 @@  process_dynamic_section (Filedata * filedata)
 	    }
 	  break;
 
+	case DT_FLAGS_2:
+	  if (do_dynamic)
+	    {
+	      printf (_("Flags:"));
+	      if (entry->d_un.d_val == 0)
+		printf (_(" None\n"));
+	      else
+		{
+		  unsigned long int val = entry->d_un.d_val;
+
+		  if (val & DF_2_GNU_IFUNC)
+		    {
+		      printf (" IFUNC");
+		      val ^= DF_2_GNU_IFUNC;
+		    }
+		  if (val != 0)
+		    printf (" %lx", val);
+		  puts ("");
+		}
+	    }
+	  break;
+
 	case DT_PLTREL:
 	  dynamic_info[entry->d_tag] = entry->d_un.d_val;
 	  if (do_dynamic)
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 773407f861..619143899b 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -630,6 +630,9 @@  struct bfd_link_info
   /* May be used to set DT_FLAGS_1 for ELF. */
   bfd_vma flags_1;
 
+  /* May be used to set DT_FLAGS_2 for ELF. */
+  bfd_vma flags_2;
+
   /* Start and end of RELRO region.  */
   bfd_vma relro_start, relro_end;
 
diff --git a/include/elf/common.h b/include/elf/common.h
index 773f378fde..6144c9e46a 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -957,6 +957,8 @@ 
 /* This tag is a GNU extension to the Solaris version scheme.  */
 #define DT_VERSYM	0x6ffffff0
 
+#define DT_FLAGS_2	0x6ffffff1
+
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
 
@@ -1015,6 +1017,9 @@ 
 #define	DF_1_WEAKFILTER	0x20000000
 #define	DF_1_NOCOMMON	0x40000000
 
+/* Flag value in in the DT_FLAGS_2 .dynamic entry.  */
+#define DF_2_GNU_IFUNC	0x00000001
+
 /* Flag values for the DT_FLAGS entry.	*/
 #define DF_ORIGIN	(1 << 0)
 #define DF_SYMBOLIC	(1 << 1)
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
index 7157d5fc5a..28fa794d79 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d
@@ -29,8 +29,8 @@  Disassembly of section .text:
 0+171 <bar>:
  +[a-f0-9]+:	e8 00 00 00 00       	call   176 <bar\+0x5>
  +[a-f0-9]+:	5b                   	pop    %ebx
- +[a-f0-9]+:	81 c3 9e 10 00 00    	add    \$0x109e,%ebx
+ +[a-f0-9]+:	81 c3 a6 10 00 00    	add    \$0x10a6,%ebx
  +[a-f0-9]+:	e8 de ff ff ff       	call   160 <\*ABS\*@plt>
- +[a-f0-9]+:	8d 83 4c ef ff ff    	lea    -0x10b4\(%ebx\),%eax
+ +[a-f0-9]+:	8d 83 44 ef ff ff    	lea    -0x10bc\(%ebx\),%eax
  +[a-f0-9]+:	c3                   	ret    
 #pass
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
index d5400a2754..52ce6aaa3e 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d
@@ -29,8 +29,8 @@  Disassembly of section .text:
 0+161 <bar>:
  +[a-f0-9]+:	e8 00 00 00 00       	call   166 <bar\+0x5>
  +[a-f0-9]+:	5b                   	pop    %ebx
- +[a-f0-9]+:	81 c3 9e 10 00 00    	add    \$0x109e,%ebx
+ +[a-f0-9]+:	81 c3 a6 10 00 00    	add    \$0x10a6,%ebx
  +[a-f0-9]+:	e8 de ff ff ff       	call   150 <\*ABS\*@plt>
- +[a-f0-9]+:	8d 83 4c ef ff ff    	lea    -0x10b4\(%ebx\),%eax
+ +[a-f0-9]+:	8d 83 44 ef ff ff    	lea    -0x10bc\(%ebx\),%eax
  +[a-f0-9]+:	c3                   	ret    
 #pass
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
index e466ef6e13..607ae65301 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-x86-64-now.d
@@ -11,12 +11,12 @@ 
 Disassembly of section .plt:
 
 0+1f0 <.plt>:
- +[a-f0-9]+:	ff 35 42 01 20 00    	pushq  0x200142\(%rip\)        # 200338 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	ff 25 44 01 20 00    	jmpq   \*0x200144\(%rip\)        # 200340 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 52 01 20 00    	pushq  0x200152\(%rip\)        # 200348 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 54 01 20 00    	jmpq   \*0x200154\(%rip\)        # 200350 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
 
 0+200 <\*ABS\*\+0x210@plt>:
- +[a-f0-9]+:	ff 25 42 01 20 00    	jmpq   \*0x200142\(%rip\)        # 200348 <_GLOBAL_OFFSET_TABLE_\+0x18>
+ +[a-f0-9]+:	ff 25 52 01 20 00    	jmpq   \*0x200152\(%rip\)        # 200358 <_GLOBAL_OFFSET_TABLE_\+0x18>
  +[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
  +[a-f0-9]+:	e9 e0 ff ff ff       	jmpq   1f0 <.plt>
 
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
index 261f0566b7..0faf1b1776 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
+++ b/ld/testsuite/ld-ifunc/ifunc-2-x86-64-now.d
@@ -11,12 +11,12 @@ 
 Disassembly of section .plt:
 
 0+1f0 <.plt>:
- +[a-f0-9]+:	ff 35 42 01 20 00    	pushq  0x200142\(%rip\)        # 200338 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	ff 25 44 01 20 00    	jmpq   \*0x200144\(%rip\)        # 200340 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 52 01 20 00    	pushq  0x200152\(%rip\)        # 200348 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 54 01 20 00    	jmpq   \*0x200154\(%rip\)        # 200350 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
 
 0+200 <\*ABS\*\+0x210@plt>:
- +[a-f0-9]+:	ff 25 42 01 20 00    	jmpq   \*0x200142\(%rip\)        # 200348 <_GLOBAL_OFFSET_TABLE_\+0x18>
+ +[a-f0-9]+:	ff 25 52 01 20 00    	jmpq   \*0x200152\(%rip\)        # 200358 <_GLOBAL_OFFSET_TABLE_\+0x18>
  +[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
  +[a-f0-9]+:	e9 e0 ff ff ff       	jmpq   1f0 <.plt>
 
diff --git a/ld/testsuite/ld-ifunc/ifunc-26.d b/ld/testsuite/ld-ifunc/ifunc-26.d
index 3b1e9f167a..0940bd49a6 100644
--- a/ld/testsuite/ld-ifunc/ifunc-26.d
+++ b/ld/testsuite/ld-ifunc/ifunc-26.d
@@ -1,7 +1,9 @@ 
 #ld: -shared
-#readelf: -h
+#readelf: -h -d
 
 ELF Header:
 #...
   OS/ABI:                            UNIX - GNU
+#...
+ +0x[0-9a-f]+ +\(FLAGS_2\) +Flags:.* +IFUNC.*
 #pass
diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
index da5d7ce72d..9734fbcf33 100644
--- a/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64-now.d
@@ -11,27 +11,27 @@ 
 Disassembly of section .plt:
 
 0+2b0 <.plt>:
- +[a-f0-9]+:	ff 35 7a 01 20 00    	pushq  0x20017a\(%rip\)        # 200430 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	ff 25 7c 01 20 00    	jmpq   \*0x20017c\(%rip\)        # 200438 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 8a 01 20 00    	pushq  0x20018a\(%rip\)        # 200440 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 8c 01 20 00    	jmpq   \*0x20018c\(%rip\)        # 200448 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
 
 0+2c0 <\*ABS\*\+0x30a@plt>:
- +[a-f0-9]+:	ff 25 7a 01 20 00    	jmpq   \*0x20017a\(%rip\)        # 200440 <_GLOBAL_OFFSET_TABLE_\+0x18>
+ +[a-f0-9]+:	ff 25 8a 01 20 00    	jmpq   \*0x20018a\(%rip\)        # 200450 <_GLOBAL_OFFSET_TABLE_\+0x18>
  +[a-f0-9]+:	68 03 00 00 00       	pushq  \$0x3
  +[a-f0-9]+:	e9 e0 ff ff ff       	jmpq   2b0 <.plt>
 
 0+2d0 <func1@plt>:
- +[a-f0-9]+:	ff 25 72 01 20 00    	jmpq   \*0x200172\(%rip\)        # 200448 <func1>
+ +[a-f0-9]+:	ff 25 82 01 20 00    	jmpq   \*0x200182\(%rip\)        # 200458 <func1>
  +[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
  +[a-f0-9]+:	e9 d0 ff ff ff       	jmpq   2b0 <.plt>
 
 0+2e0 <func2@plt>:
- +[a-f0-9]+:	ff 25 6a 01 20 00    	jmpq   \*0x20016a\(%rip\)        # 200450 <func2>
+ +[a-f0-9]+:	ff 25 7a 01 20 00    	jmpq   \*0x20017a\(%rip\)        # 200460 <func2>
  +[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
  +[a-f0-9]+:	e9 c0 ff ff ff       	jmpq   2b0 <.plt>
 
 0+2f0 <\*ABS\*\+0x300@plt>:
- +[a-f0-9]+:	ff 25 62 01 20 00    	jmpq   \*0x200162\(%rip\)        # 200458 <_GLOBAL_OFFSET_TABLE_\+0x30>
+ +[a-f0-9]+:	ff 25 72 01 20 00    	jmpq   \*0x200172\(%rip\)        # 200468 <_GLOBAL_OFFSET_TABLE_\+0x30>
  +[a-f0-9]+:	68 02 00 00 00       	pushq  \$0x2
  +[a-f0-9]+:	e9 b0 ff ff ff       	jmpq   2b0 <.plt>
 
diff --git a/ld/testsuite/ld-ifunc/pr17154-x86-64.d b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
index 737fb258db..72f1cb9dac 100644
--- a/ld/testsuite/ld-ifunc/pr17154-x86-64.d
+++ b/ld/testsuite/ld-ifunc/pr17154-x86-64.d
@@ -6,27 +6,27 @@ 
 
 #...
 0+2b0 <.*>:
-[ 	]*[a-f0-9]+:	ff 35 5a 01 20 00    	pushq  0x20015a\(%rip\)        # 200410 <.*>
-[ 	]*[a-f0-9]+:	ff 25 5c 01 20 00    	jmpq   \*0x20015c\(%rip\)        # 200418 <.*>
+[ 	]*[a-f0-9]+:	ff 35 6a 01 20 00    	pushq  0x20016a\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	ff 25 6c 01 20 00    	jmpq   \*0x20016c\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
 
 0+2c0 <\*ABS\*\+0x30a@plt>:
-[ 	]*[a-f0-9]+:	ff 25 5a 01 20 00    	jmpq   \*0x20015a\(%rip\)        # 200420 <.*>
+[ 	]*[a-f0-9]+:	ff 25 6a 01 20 00    	jmpq   \*0x20016a\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	68 03 00 00 00       	pushq  \$0x3
 [ 	]*[a-f0-9]+:	e9 e0 ff ff ff       	jmpq   2b0 <.*>
 
 0+2d0 <func1@plt>:
-[ 	]*[a-f0-9]+:	ff 25 52 01 20 00    	jmpq   \*0x200152\(%rip\)        # 200428 <.*>
+[ 	]*[a-f0-9]+:	ff 25 62 01 20 00    	jmpq   \*0x200162\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
 [ 	]*[a-f0-9]+:	e9 d0 ff ff ff       	jmpq   2b0 <.*>
 
 0+2e0 <func2@plt>:
-[ 	]*[a-f0-9]+:	ff 25 4a 01 20 00    	jmpq   \*0x20014a\(%rip\)        # 200430 <.*>
+[ 	]*[a-f0-9]+:	ff 25 5a 01 20 00    	jmpq   \*0x20015a\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
 [ 	]*[a-f0-9]+:	e9 c0 ff ff ff       	jmpq   2b0 <.*>
 
 0+2f0 <\*ABS\*\+0x300@plt>:
-[ 	]*[a-f0-9]+:	ff 25 42 01 20 00    	jmpq   \*0x200142\(%rip\)        # 200438 <.*>
+[ 	]*[a-f0-9]+:	ff 25 52 01 20 00    	jmpq   \*0x200152\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	68 02 00 00 00       	pushq  \$0x2
 [ 	]*[a-f0-9]+:	e9 b0 ff ff ff       	jmpq   2b0 <.*>
 
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
index a32eaccd5c..99bb0f7211 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-1-now.d
@@ -9,25 +9,25 @@ 
 Disassembly of section .plt:
 
 0+1f0 <.plt>:
- +[a-f0-9]+:	ff 35 4a 01 20 00    	pushq  0x20014a\(%rip\)        # 200340 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	f2 ff 25 4b 01 20 00 	bnd jmpq \*0x20014b\(%rip\)        # 200348 <_GLOBAL_OFFSET_TABLE_\+0x10>
- +[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
- +[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
- +[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 1f0 <.plt>
- +[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+[ 	]*[a-f0-9]+:	ff 35 5a 01 20 00    	pushq  0x20015a\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	f2 ff 25 5b 01 20 00 	bnd jmpq \*0x20015b\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
+[ 	]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
+[ 	]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 1f0 <.plt>
+[ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 
 Disassembly of section .plt.sec:
 
 0+210 <\*ABS\*\+0x218@plt>:
- +[a-f0-9]+:	f2 ff 25 39 01 20 00 	bnd jmpq \*0x200139\(%rip\)        # 200350 <_GLOBAL_OFFSET_TABLE_\+0x18>
- +[a-f0-9]+:	90                   	nop
+[ 	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
 
 0+218 <foo>:
- +[a-f0-9]+:	f2 c3                	bnd retq 
+[ 	]*[a-f0-9]+:	f2 c3                	bnd retq 
 
 0+21a <bar>:
- +[a-f0-9]+:	f2 e8 f0 ff ff ff    	bnd callq 210 <\*ABS\*\+0x218@plt>
- +[a-f0-9]+:	f2 c3                	bnd retq 
+[ 	]*[a-f0-9]+:	f2 e8 f0 ff ff ff    	bnd callq 210 <\*ABS\*\+0x218@plt>
+[ 	]*[a-f0-9]+:	f2 c3                	bnd retq 
 #pass
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
index 8bd144ed21..2342be6ac2 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2-now.d
@@ -9,51 +9,51 @@ 
 Disassembly of section .plt:
 
 0+2b0 <.plt>:
- +[a-f0-9]+:	ff 35 9a 01 20 00    	pushq  0x20019a\(%rip\)        # 200450 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	f2 ff 25 9b 01 20 00 	bnd jmpq \*0x20019b\(%rip\)        # 200458 <_GLOBAL_OFFSET_TABLE_\+0x10>
- +[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
- +[a-f0-9]+:	68 03 00 00 00       	pushq  \$0x3
- +[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 2b0 <.plt>
- +[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
- +[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
- +[a-f0-9]+:	f2 e9 d5 ff ff ff    	bnd jmpq 2b0 <.plt>
- +[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
- +[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
- +[a-f0-9]+:	f2 e9 c5 ff ff ff    	bnd jmpq 2b0 <.plt>
- +[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
- +[a-f0-9]+:	68 02 00 00 00       	pushq  \$0x2
- +[a-f0-9]+:	f2 e9 b5 ff ff ff    	bnd jmpq 2b0 <.plt>
- +[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+[ 	]*[a-f0-9]+:	ff 35 aa 01 20 00    	pushq  0x2001aa\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	f2 ff 25 ab 01 20 00 	bnd jmpq \*0x2001ab\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
+[ 	]*[a-f0-9]+:	68 03 00 00 00       	pushq  \$0x3
+[ 	]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 2b0 <.plt>
+[ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+[ 	]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
+[ 	]*[a-f0-9]+:	f2 e9 d5 ff ff ff    	bnd jmpq 2b0 <.plt>
+[ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+[ 	]*[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
+[ 	]*[a-f0-9]+:	f2 e9 c5 ff ff ff    	bnd jmpq 2b0 <.plt>
+[ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+[ 	]*[a-f0-9]+:	68 02 00 00 00       	pushq  \$0x2
+[ 	]*[a-f0-9]+:	f2 e9 b5 ff ff ff    	bnd jmpq 2b0 <.plt>
+[ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 
 Disassembly of section .plt.sec:
 
 0+300 <\*ABS\*\+0x32c@plt>:
- +[a-f0-9]+:	f2 ff 25 59 01 20 00 	bnd jmpq \*0x200159\(%rip\)        # 200460 <_GLOBAL_OFFSET_TABLE_\+0x18>
- +[a-f0-9]+:	90                   	nop
+[ 	]*[a-f0-9]+:	f2 ff 25 69 01 20 00 	bnd jmpq \*0x200169\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	90                   	nop
 
 0+308 <func1@plt>:
- +[a-f0-9]+:	f2 ff 25 59 01 20 00 	bnd jmpq \*0x200159\(%rip\)        # 200468 <func1>
- +[a-f0-9]+:	90                   	nop
+[ 	]*[a-f0-9]+:	f2 ff 25 69 01 20 00 	bnd jmpq \*0x200169\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	90                   	nop
 
 0+310 <func2@plt>:
- +[a-f0-9]+:	f2 ff 25 59 01 20 00 	bnd jmpq \*0x200159\(%rip\)        # 200470 <func2>
- +[a-f0-9]+:	90                   	nop
+[ 	]*[a-f0-9]+:	f2 ff 25 69 01 20 00 	bnd jmpq \*0x200169\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	90                   	nop
 
 0+318 <\*ABS\*\+0x320@plt>:
- +[a-f0-9]+:	f2 ff 25 59 01 20 00 	bnd jmpq \*0x200159\(%rip\)        # 200478 <_GLOBAL_OFFSET_TABLE_\+0x30>
- +[a-f0-9]+:	90                   	nop
+[ 	]*[a-f0-9]+:	f2 ff 25 69 01 20 00 	bnd jmpq \*0x200169\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
 
 0+320 <resolve1>:
- +[a-f0-9]+:	f2 e8 e2 ff ff ff    	bnd callq 308 <func1@plt>
+[ 	]*[a-f0-9]+:	f2 e8 e2 ff ff ff    	bnd callq 308 <func1@plt>
 
 0+326 <g1>:
- +[a-f0-9]+:	f2 e9 ec ff ff ff    	bnd jmpq 318 <\*ABS\*\+0x320@plt>
+[ 	]*[a-f0-9]+:	f2 e9 ec ff ff ff    	bnd jmpq 318 <\*ABS\*\+0x320@plt>
 
 0+32c <resolve2>:
- +[a-f0-9]+:	f2 e8 de ff ff ff    	bnd callq 310 <func2@plt>
+[ 	]*[a-f0-9]+:	f2 e8 de ff ff ff    	bnd callq 310 <func2@plt>
 
 0+332 <g2>:
- +[a-f0-9]+:	f2 e9 c8 ff ff ff    	bnd jmpq 300 <\*ABS\*\+0x32c@plt>
+[ 	]*[a-f0-9]+:	f2 e9 c8 ff ff ff    	bnd jmpq 300 <\*ABS\*\+0x32c@plt>
 #pass
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
index bee3bb299f..ea249bdeb5 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
@@ -4,38 +4,38 @@ 
 
 #...
 0+2b0 <.plt>:
-[ 	]*[a-f0-9]+:	ff 35 7a 01 20 00    	pushq  0x20017a\(%rip\)        # 200430 <_GLOBAL_OFFSET_TABLE_\+0x8>
-[ 	]*[a-f0-9]+:	f2 ff 25 7b 01 20 00 	bnd jmpq \*0x20017b\(%rip\)        # 200438 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[ 	]*[a-f0-9]+:	ff 35 8a 01 20 00    	pushq  0x20018a\(%rip\)[ 	]*(#.*)?
+[ 	]*[a-f0-9]+:	f2 ff 25 8b 01 20 00 	bnd jmpq \*0x20018b\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
 [ 	]*[a-f0-9]+:	68 03 00 00 00       	pushq  \$0x3
-[ 	]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 2b0 <.*>
+[ 	]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 2b0 <.plt>
 [ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 [ 	]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
-[ 	]*[a-f0-9]+:	f2 e9 d5 ff ff ff    	bnd jmpq 2b0 <.*>
+[ 	]*[a-f0-9]+:	f2 e9 d5 ff ff ff    	bnd jmpq 2b0 <.plt>
 [ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 [ 	]*[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
-[ 	]*[a-f0-9]+:	f2 e9 c5 ff ff ff    	bnd jmpq 2b0 <.*>
+[ 	]*[a-f0-9]+:	f2 e9 c5 ff ff ff    	bnd jmpq 2b0 <.plt>
 [ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 [ 	]*[a-f0-9]+:	68 02 00 00 00       	pushq  \$0x2
-[ 	]*[a-f0-9]+:	f2 e9 b5 ff ff ff    	bnd jmpq 2b0 <.*>
+[ 	]*[a-f0-9]+:	f2 e9 b5 ff ff ff    	bnd jmpq 2b0 <.plt>
 [ 	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 
 Disassembly of section .plt.sec:
 
 0+300 <\*ABS\*\+0x32c@plt>:
-[ 	]*[a-f0-9]+:	f2 ff 25 39 01 20 00 	bnd jmpq \*0x200139\(%rip\)        # 200440 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[ 	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	90                   	nop
 
 0+308 <func1@plt>:
-[ 	]*[a-f0-9]+:	f2 ff 25 39 01 20 00 	bnd jmpq \*0x200139\(%rip\)        # 200448 <func1>
+[ 	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	90                   	nop
 
 0+310 <func2@plt>:
-[ 	]*[a-f0-9]+:	f2 ff 25 39 01 20 00 	bnd jmpq \*0x200139\(%rip\)        # 200450 <func2>
+[ 	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	90                   	nop
 
 0+318 <\*ABS\*\+0x320@plt>:
-[ 	]*[a-f0-9]+:	f2 ff 25 39 01 20 00 	bnd jmpq \*0x200139\(%rip\)        # 200458 <_GLOBAL_OFFSET_TABLE_\+0x30>
+[ 	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)[ 	]*(#.*)?
 [ 	]*[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
diff --git a/ld/testsuite/ld-x86-64/pr20253-1d.d b/ld/testsuite/ld-x86-64/pr20253-1d.d
index 34bd4e7594..83b9828ebe 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1d.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1d.d
@@ -16,10 +16,10 @@  Disassembly of section .text:
  +[a-f0-9]+:	c3                   	retq   
 
 0+1ca <_start>:
- +[a-f0-9]+:	ff 15 28 01 20 00    	callq  \*0x200128\(%rip\)        # 2002f8 <.got>
- +[a-f0-9]+:	ff 25 2a 01 20 00    	jmpq   \*0x20012a\(%rip\)        # 200300 <.got\+0x8>
- +[a-f0-9]+:	48 c7 05 1f 01 20 00 00 00 00 00 	movq   \$0x0,0x20011f\(%rip\)        # 200300 <.got\+0x8>
- +[a-f0-9]+:	48 83 3d 0f 01 20 00 00 	cmpq   \$0x0,0x20010f\(%rip\)        # 2002f8 <.got>
- +[a-f0-9]+:	48 3b 0d 08 01 20 00 	cmp    0x200108\(%rip\),%rcx        # 2002f8 <.got>
- +[a-f0-9]+:	48 3b 0d 09 01 20 00 	cmp    0x200109\(%rip\),%rcx        # 200300 <.got\+0x8>
+ +[a-f0-9]+:	ff 15 38 01 20 00    	callq  \*0x200138\(%rip\)        # 200308 <.got>
+ +[a-f0-9]+:	ff 25 3a 01 20 00    	jmpq   \*0x20013a\(%rip\)        # 200310 <.got\+0x8>
+ +[a-f0-9]+:	48 c7 05 2f 01 20 00 00 00 00 00 	movq   \$0x0,0x20012f\(%rip\)        # 200310 <.got\+0x8>
+ +[a-f0-9]+:	48 83 3d 1f 01 20 00 00 	cmpq   \$0x0,0x20011f\(%rip\)        # 200308 <.got>
+ +[a-f0-9]+:	48 3b 0d 18 01 20 00 	cmp    0x200118\(%rip\),%rcx        # 200308 <.got>
+ +[a-f0-9]+:	48 3b 0d 19 01 20 00 	cmp    0x200119\(%rip\),%rcx        # 200310 <.got\+0x8>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1f.d b/ld/testsuite/ld-x86-64/pr20253-1f.d
index 9b0fc72898..1b33560034 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1f.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1f.d
@@ -16,10 +16,10 @@  Disassembly of section .text:
  +[a-f0-9]+:	c3                   	retq   
 
 0+1fa <_start>:
- +[a-f0-9]+:	ff 15 08 01 20 00    	callq  \*0x200108\(%rip\)        # 200308 <.*>
- +[a-f0-9]+:	ff 25 0a 01 20 00    	jmpq   \*0x20010a\(%rip\)        # 200310 <.*>
- +[a-f0-9]+:	48 c7 05 ff 00 20 00 00 00 00 00 	movq   \$0x0,0x2000ff\(%rip\)        # 200310 <.*>
- +[a-f0-9]+:	48 83 3d ef 00 20 00 00 	cmpq   \$0x0,0x2000ef\(%rip\)        # 200308 <.*>
- +[a-f0-9]+:	48 3b 0d e8 00 20 00 	cmp    0x2000e8\(%rip\),%rcx        # 200308 <.*>
- +[a-f0-9]+:	48 3b 0d e9 00 20 00 	cmp    0x2000e9\(%rip\),%rcx        # 200310 <.*>
+ +[a-f0-9]+:	ff 15 18 01 20 00    	callq  \*0x200118\(%rip\)        # 200318 <foo\+0x200120>
+ +[a-f0-9]+:	ff 25 1a 01 20 00    	jmpq   \*0x20011a\(%rip\)        # 200320 <.got\+0x8>
+ +[a-f0-9]+:	48 c7 05 0f 01 20 00 00 00 00 00 	movq   \$0x0,0x20010f\(%rip\)        # 200320 <.got\+0x8>
+ +[a-f0-9]+:	48 83 3d ff 00 20 00 00 	cmpq   \$0x0,0x2000ff\(%rip\)        # 200318 <foo\+0x200120>
+ +[a-f0-9]+:	48 3b 0d f8 00 20 00 	cmp    0x2000f8\(%rip\),%rcx        # 200318 <foo\+0x200120>
+ +[a-f0-9]+:	48 3b 0d f9 00 20 00 	cmp    0x2000f9\(%rip\),%rcx        # 200320 <.got\+0x8>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1j.d b/ld/testsuite/ld-x86-64/pr20253-1j.d
index db4895268a..6db9f52a92 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1j.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1j.d
@@ -16,10 +16,10 @@  Disassembly of section .text:
  +[a-f0-9]+:	c3                   	retq   
 
 0+122 <_start>:
- +[a-f0-9]+:	ff 15 a8 00 20 00    	callq  \*0x2000a8\(%rip\)        # 2001d0 <.*>
- +[a-f0-9]+:	ff 25 aa 00 20 00    	jmpq   \*0x2000aa\(%rip\)        # 2001d8 <.*>
- +[a-f0-9]+:	48 c7 05 9f 00 20 00 00 00 00 00 	movq   \$0x0,0x20009f\(%rip\)        # 2001d8 <.*>
- +[a-f0-9]+:	48 83 3d 8f 00 20 00 00 	cmpq   \$0x0,0x20008f\(%rip\)        # 2001d0 <.*>
- +[a-f0-9]+:	48 3b 0d 88 00 20 00 	cmp    0x200088\(%rip\),%rcx        # 2001d0 <.*>
- +[a-f0-9]+:	48 3b 0d 89 00 20 00 	cmp    0x200089\(%rip\),%rcx        # 2001d8 <.*>
+ +[a-f0-9]+:	ff 15 b0 00 20 00    	callq  \*0x2000b0\(%rip\)        # 2001d8 <.got>
+ +[a-f0-9]+:	ff 25 b2 00 20 00    	jmpq   \*0x2000b2\(%rip\)        # 2001e0 <.got\+0x8>
+ +[a-f0-9]+:	48 c7 05 a7 00 20 00 00 00 00 00 	movq   \$0x0,0x2000a7\(%rip\)        # 2001e0 <.got\+0x8>
+ +[a-f0-9]+:	48 83 3d 97 00 20 00 00 	cmpq   \$0x0,0x200097\(%rip\)        # 2001d8 <.got>
+ +[a-f0-9]+:	48 3b 0d 90 00 20 00 	cmp    0x200090\(%rip\),%rcx        # 2001d8 <.got>
+ +[a-f0-9]+:	48 3b 0d 91 00 20 00 	cmp    0x200091\(%rip\),%rcx        # 2001e0 <.got\+0x8>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20253-1l.d b/ld/testsuite/ld-x86-64/pr20253-1l.d
index 5b04442723..176491a7cf 100644
--- a/ld/testsuite/ld-x86-64/pr20253-1l.d
+++ b/ld/testsuite/ld-x86-64/pr20253-1l.d
@@ -16,10 +16,10 @@  Disassembly of section .text:
  +[a-f0-9]+:	c3                   	retq   
 
 0+15a <_start>:
- +[a-f0-9]+:	ff 15 98 00 20 00    	callq  \*0x200098\(%rip\)        # 2001f8 <.*>
- +[a-f0-9]+:	ff 25 9a 00 20 00    	jmpq   \*0x20009a\(%rip\)        # 200200 <.*>
- +[a-f0-9]+:	48 c7 05 8f 00 20 00 00 00 00 00 	movq   \$0x0,0x20008f\(%rip\)        # 200200 <.*>
- +[a-f0-9]+:	48 83 3d 7f 00 20 00 00 	cmpq   \$0x0,0x20007f\(%rip\)        # 2001f8 <.*>
- +[a-f0-9]+:	48 3b 0d 78 00 20 00 	cmp    0x200078\(%rip\),%rcx        # 2001f8 <.*>
- +[a-f0-9]+:	48 3b 0d 79 00 20 00 	cmp    0x200079\(%rip\),%rcx        # 200200 <.*>
+ +[a-f0-9]+:	ff 15 a0 00 20 00    	callq  \*0x2000a0\(%rip\)        # 200200 <foo\+0x2000a8>
+ +[a-f0-9]+:	ff 25 a2 00 20 00    	jmpq   \*0x2000a2\(%rip\)        # 200208 <.got\+0x8>
+ +[a-f0-9]+:	48 c7 05 97 00 20 00 00 00 00 00 	movq   \$0x0,0x200097\(%rip\)        # 200208 <.got\+0x8>
+ +[a-f0-9]+:	48 83 3d 87 00 20 00 00 	cmpq   \$0x0,0x200087\(%rip\)        # 200200 <foo\+0x2000a8>
+ +[a-f0-9]+:	48 3b 0d 80 00 20 00 	cmp    0x200080\(%rip\),%rcx        # 200200 <foo\+0x2000a8>
+ +[a-f0-9]+:	48 3b 0d 81 00 20 00 	cmp    0x200081\(%rip\),%rcx        # 200208 <.got\+0x8>
 #pass