elf: Remove the 1-page gap before the RELRO segment

Message ID 20220111021241.1937265-1-hjl.tools@gmail.com
State New
Headers show
Series
  • elf: Remove the 1-page gap before the RELRO segment
Related show

Commit Message

H.J. Lu via Binutils Jan. 11, 2022, 2:12 a.m.
The existing RELRO scheme may leave a 1-page gap before the RELRO segment
and align the end of the RELRO segment to the page size:

  [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8
  [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8
  [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8
  [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8
  [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8
  [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8

Instead, we can remove the 1-page gap if the maximum page size >= the
maximum section alignment:

  [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8
  [19] .init_array  INIT_ARRAY  40fde0 00fde0 000008 08  WA  0   0  8
  [20] .fini_array  FINI_ARRAY  40fde8 00fde8 000008 08  WA  0   0  8
  [21] .dynamic     DYNAMIC     40fdf0 00fdf0 000200 10  WA  7   0  8
  [22] .got         PROGBITS    40fff0 00fff0 000010 08  WA  0   0  8
  [23] .got.plt     PROGBITS    410000 010000 000048 08  WA  0   0  8

Because the end of the RELRO segment is always aligned to the page size
and may not be moved, the RELRO segment size may be increased:

  [ 3] .dynstr      STRTAB      000148 000148 000001 00   A  0   0  1
  [ 4] .eh_frame    PROGBITS    000150 000150 000000 00   A  0   0  8
  [ 5] .init_array  INIT_ARRAY  200150 000150 000010 08  WA  0   0  1
  [ 6] .fini_array  FINI_ARRAY  200160 000160 000010 08  WA  0   0  1
  [ 7] .jcr         PROGBITS    200170 000170 000008 00  WA  0   0  1
  [ 8] .data.rel.ro PROGBITS    200180 000180 000020 00  WA  0   0 16
  [ 9] .dynamic     DYNAMIC     2001a0 0001a0 0001c0 10  WA  3   0  8
  [10] .got         PROGBITS    200360 000360 0002a8 00  WA  0   0  8
  [11] .bss         NOBITS      201000 000608 000840 00  WA  0   0  1

vs the old section layout:

  [ 3] .dynstr      STRTAB      000148 000148 000001 00   A  0   0  1
  [ 4] .eh_frame    PROGBITS    000150 000150 000000 00   A  0   0  8
  [ 5] .init_array  INIT_ARRAY  200b48 000b48 000010 08  WA  0   0  1
  [ 6] .fini_array  FINI_ARRAY  200b58 000b58 000010 08  WA  0   0  1
  [ 7] .jcr         PROGBITS    200b68 000b68 000008 00  WA  0   0  1
  [ 8] .data.rel.ro PROGBITS    200b70 000b70 000020 00  WA  0   0 16
  [ 9] .dynamic     DYNAMIC     200b90 000b90 0001c0 10  WA  3   0  8
  [10] .got         PROGBITS    200d50 000d50 0002a8 00  WA  0   0  8
  [11] .bss         NOBITS      201000 000ff8 000840 00  WA  0   0  1

But there is no 1-page gap.

	PR ld/28743
	* ldlang.c (lang_size_relro_segment_1): Remove the 1-page gap
	before the RELRO segment if the maximum page size >= the maximum
	section alignment.
	* testsuite/ld-i386/pr20830.d: Adjusted.
	* testsuite/ld-s390/gotreloc_64-relro-1.dd: Likewise.
	* testsuite/ld-x86-64/pr14207.d: Likewise.
	* testsuite/ld-x86-64/pr18176.d: Likewise.
	* testsuite/ld-x86-64/pr20830a-now.d: Likewise.
	* testsuite/ld-x86-64/pr20830a.d: Likewise.
	* testsuite/ld-x86-64/pr20830b-now.d: Likewise.
	* testsuite/ld-x86-64/pr20830b.d: Likewise.
	* testsuite/ld-x86-64/pr21038a-now.d: Likewise.
	* testsuite/ld-x86-64/pr21038a.d: Likewise.
	* testsuite/ld-x86-64/pr21038b-now.d: Likewise.
	* testsuite/ld-x86-64/pr21038c-now.d: Likewise.
	* testsuite/ld-x86-64/pr21038c.d: Likewise.
---
 ld/ldlang.c                                 | 89 ++++++++++++++++-----
 ld/testsuite/ld-i386/pr20830.d              |  4 +-
 ld/testsuite/ld-s390/gotreloc_64-relro-1.dd |  6 +-
 ld/testsuite/ld-x86-64/pr14207.d            |  6 +-
 ld/testsuite/ld-x86-64/pr18176.d            |  2 +-
 ld/testsuite/ld-x86-64/pr20830a-now.d       |  8 +-
 ld/testsuite/ld-x86-64/pr20830a.d           |  4 +-
 ld/testsuite/ld-x86-64/pr20830b-now.d       | 10 +--
 ld/testsuite/ld-x86-64/pr20830b.d           |  6 +-
 ld/testsuite/ld-x86-64/pr21038a-now.d       |  8 +-
 ld/testsuite/ld-x86-64/pr21038a.d           |  4 +-
 ld/testsuite/ld-x86-64/pr21038b-now.d       |  6 +-
 ld/testsuite/ld-x86-64/pr21038c-now.d       | 10 +--
 ld/testsuite/ld-x86-64/pr21038c.d           |  4 +-
 14 files changed, 110 insertions(+), 57 deletions(-)

-- 
2.34.1

Comments

Fangrui Song Jan. 11, 2022, 5:26 a.m. | #1
On 2022-01-10, H.J. Lu via Binutils wrote:
>The existing RELRO scheme may leave a 1-page gap before the RELRO segment

>and align the end of the RELRO segment to the page size:

>

>  [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

>  [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8

>  [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8

>  [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8

>  [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8

>  [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8

>

>Instead, we can remove the 1-page gap if the maximum page size >= the

>maximum section alignment:

>

>  [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

>  [19] .init_array  INIT_ARRAY  40fde0 00fde0 000008 08  WA  0   0  8

>  [20] .fini_array  FINI_ARRAY  40fde8 00fde8 000008 08  WA  0   0  8

>  [21] .dynamic     DYNAMIC     40fdf0 00fdf0 000200 10  WA  7   0  8

>  [22] .got         PROGBITS    40fff0 00fff0 000010 08  WA  0   0  8

>  [23] .got.plt     PROGBITS    410000 010000 000048 08  WA  0   0  8

>

>Because the end of the RELRO segment is always aligned to the page size

>and may not be moved, the RELRO segment size may be increased:

>

>  [ 3] .dynstr      STRTAB      000148 000148 000001 00   A  0   0  1

>  [ 4] .eh_frame    PROGBITS    000150 000150 000000 00   A  0   0  8

>  [ 5] .init_array  INIT_ARRAY  200150 000150 000010 08  WA  0   0  1

>  [ 6] .fini_array  FINI_ARRAY  200160 000160 000010 08  WA  0   0  1

>  [ 7] .jcr         PROGBITS    200170 000170 000008 00  WA  0   0  1

>  [ 8] .data.rel.ro PROGBITS    200180 000180 000020 00  WA  0   0 16

>  [ 9] .dynamic     DYNAMIC     2001a0 0001a0 0001c0 10  WA  3   0  8

>  [10] .got         PROGBITS    200360 000360 0002a8 00  WA  0   0  8

>  [11] .bss         NOBITS      201000 000608 000840 00  WA  0   0  1

>

>vs the old section layout:

>

>  [ 3] .dynstr      STRTAB      000148 000148 000001 00   A  0   0  1

>  [ 4] .eh_frame    PROGBITS    000150 000150 000000 00   A  0   0  8

>  [ 5] .init_array  INIT_ARRAY  200b48 000b48 000010 08  WA  0   0  1

>  [ 6] .fini_array  FINI_ARRAY  200b58 000b58 000010 08  WA  0   0  1

>  [ 7] .jcr         PROGBITS    200b68 000b68 000008 00  WA  0   0  1

>  [ 8] .data.rel.ro PROGBITS    200b70 000b70 000020 00  WA  0   0 16

>  [ 9] .dynamic     DYNAMIC     200b90 000b90 0001c0 10  WA  3   0  8

>  [10] .got         PROGBITS    200d50 000d50 0002a8 00  WA  0   0  8

>  [11] .bss         NOBITS      201000 000ff8 000840 00  WA  0   0  1

>

>But there is no 1-page gap.

> [...}


If you want to avoid a max-page-size alignment (at the end of PT_GNU_RELRO), you may adopt ld.lld's design
I implemented:

   LOAD           0x000000 0x0000000000200000 0x0000000000200000 0xcaac4c 0xcaac4c R   0x1000
   LOAD           0xcaac50 0x0000000000eabc50 0x0000000000eabc50 0x208a0c0 0x208a0c0 R E 0x1000
   LOAD           0x2d34d10 0x0000000002f36d10 0x0000000002f36d10 0x1777e8 0x1777e8 RW  0x1000     match
   LOAD           0x2eac500 0x00000000030af500 0x00000000030af500 0x008038 0x064664 RW  0x1000
   TLS            0x2d34d10 0x0000000002f35d10 0x0000000002f35d10 0x000000 0x000018 R   0x8
   DYNAMIC        0x2ea5570 0x00000000030a7570 0x00000000030a7570 0x000240 0x000240 RW  0x8
   GNU_RELRO      0x2d34d10 0x0000000002f36d10 0x0000000002f36d10 0x1777e8 0x1782f0 R   0x1        match
   GNU_EH_FRAME   0x89ce34 0x0000000000a9ce34 0x0000000000a9ce34 0x08586c 0x08586c R   0x4
   GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0
   NOTE           0x0002fc 0x00000000002002fc 0x00000000002002fc 0x000020 0x000020 R   0x4

The idea is to have 2 RW PT_LOAD with one exactly matching PT_GNU_RELRO.
H.J. Lu via Binutils Jan. 13, 2022, 12:44 p.m. | #2
Hi H.J.

> 	PR ld/28743

> 	* ldlang.c (lang_size_relro_segment_1): Remove the 1-page gap

> 	before the RELRO segment if the maximum page size >= the maximum

> 	section alignment.

> 	* testsuite/ld-i386/pr20830.d: Adjusted.

> 	* testsuite/ld-s390/gotreloc_64-relro-1.dd: Likewise.

> 	* testsuite/ld-x86-64/pr14207.d: Likewise.

> 	* testsuite/ld-x86-64/pr18176.d: Likewise.

> 	* testsuite/ld-x86-64/pr20830a-now.d: Likewise.

> 	* testsuite/ld-x86-64/pr20830a.d: Likewise.

> 	* testsuite/ld-x86-64/pr20830b-now.d: Likewise.

> 	* testsuite/ld-x86-64/pr20830b.d: Likewise.

> 	* testsuite/ld-x86-64/pr21038a-now.d: Likewise.

> 	* testsuite/ld-x86-64/pr21038a.d: Likewise.

> 	* testsuite/ld-x86-64/pr21038b-now.d: Likewise.

> 	* testsuite/ld-x86-64/pr21038c-now.d: Likewise.

> 	* testsuite/ld-x86-64/pr21038c.d: Likewise.


Approved - please apply.

Cheers
   Nick
H.J. Lu via Binutils Jan. 13, 2022, 12:52 p.m. | #3
On Mon, Jan 10, 2022 at 06:12:41PM -0800, H.J. Lu via Binutils wrote:
> The existing RELRO scheme may leave a 1-page gap before the RELRO segment

> and align the end of the RELRO segment to the page size:

> 

>   [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

>   [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8

>   [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8

>   [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8

>   [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8

>   [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8


Do you know what is going wrong with the relro section layout for this
to occur?

In this particular case, the end of the read-only segment is at
0x408fa0 + 0x5e80 = 0x40ee20.  My guess is that layout of the
following rw sections starts on the next page plus current offset
within page, the standard choice to minimise disk pages.  ie. We start
at 0x40fe20.  Then discover that this puts .got.plt at 0x40fe20 + 8 +
8 + 0x200 + 0x10 = 0x40f040.  However, we want this to be on a page
boundary so that the relro segment ends on a page boundary.  So we
bump 0x40f040 up to 0x411000 and calculate backwards from there to
arrive at .init_array with a vma of 0x410de0.  Resulting in the
0x40f000 page being unused.

If instead we start relro layout on the next page, we'd start laying
out at 0x40f000 rather than 0x40fe20.  I think that would be the
correct thing to do rather than fixing up afterwards as your patch
does.

-- 
Alan Modra
Australia Development Lab, IBM
H.J. Lu via Binutils Jan. 13, 2022, 1:19 p.m. | #4
On Thu, Jan 13, 2022 at 4:52 AM Alan Modra <amodra@gmail.com> wrote:
>

> On Mon, Jan 10, 2022 at 06:12:41PM -0800, H.J. Lu via Binutils wrote:

> > The existing RELRO scheme may leave a 1-page gap before the RELRO segment

> > and align the end of the RELRO segment to the page size:

> >

> >   [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

> >   [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8

> >   [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8

> >   [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8

> >   [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8

> >   [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8

>

> Do you know what is going wrong with the relro section layout for this

> to occur?

>

> In this particular case, the end of the read-only segment is at

> 0x408fa0 + 0x5e80 = 0x40ee20.  My guess is that layout of the

> following rw sections starts on the next page plus current offset

> within page, the standard choice to minimise disk pages.  ie. We start

> at 0x40fe20.  Then discover that this puts .got.plt at 0x40fe20 + 8 +

> 8 + 0x200 + 0x10 = 0x40f040.  However, we want this to be on a page

> boundary so that the relro segment ends on a page boundary.  So we

> bump 0x40f040 up to 0x411000 and calculate backwards from there to

> arrive at .init_array with a vma of 0x410de0.  Resulting in the

> 0x40f000 page being unused.

>

> If instead we start relro layout on the next page, we'd start laying

> out at 0x40f000 rather than 0x40fe20.  I think that would be the


But if the prior ro section size is greater than one page, we want
to subtract 1 page:

+  /* If the preceding section size is greater than the maximum
+      page size, subtract the maximum page size.  Otherwise,
+      align the RELRO segment to the maximum page size.  */
+   if (prev_sec->size > seg->maxpagesize)
+     {
+       desired_end -= seg->maxpagesize;
+       relro_end -= seg->maxpagesize;
+     }
+   else
+     {
+       desired_end &= ~(seg->maxpagesize - 1);
+       relro_end &= ~(seg->maxpagesize - 1);
+     }
+   }

> correct thing to do rather than fixing up afterwards as your patch

> does.

>


I am checking in my patch as Nick has approved it. There is a
possibility that one 1-page gap may be needed to maintain
the section alignment.  My patch checks it and includes many
testcase adjustments to remove one 1-page gap.   Can you
update the RELRO segment algorithm to make my fixup
unnecessary?

Thanks.

-- 
H.J.
H.J. Lu via Binutils Jan. 14, 2022, 8:12 a.m. | #5
On Thu, Jan 13, 2022 at 05:19:22AM -0800, H.J. Lu wrote:
> On Thu, Jan 13, 2022 at 4:52 AM Alan Modra <amodra@gmail.com> wrote:

> >

> > On Mon, Jan 10, 2022 at 06:12:41PM -0800, H.J. Lu via Binutils wrote:

> > > The existing RELRO scheme may leave a 1-page gap before the RELRO segment

> > > and align the end of the RELRO segment to the page size:

> > >

> > >   [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

> > >   [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8

> > >   [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8

> > >   [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8

> > >   [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8

> > >   [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8

> >

> > Do you know what is going wrong with the relro section layout for this

> > to occur?

> >

> > In this particular case, the end of the read-only segment is at

> > 0x408fa0 + 0x5e80 = 0x40ee20.  My guess is that layout of the

> > following rw sections starts on the next page plus current offset

> > within page, the standard choice to minimise disk pages.  ie. We start

> > at 0x40fe20.  Then discover that this puts .got.plt at 0x40fe20 + 8 +

> > 8 + 0x200 + 0x10 = 0x40f040.  However, we want this to be on a page

> > boundary so that the relro segment ends on a page boundary.  So we

> > bump 0x40f040 up to 0x411000 and calculate backwards from there to

> > arrive at .init_array with a vma of 0x410de0.  Resulting in the

> > 0x40f000 page being unused.

> >

> > If instead we start relro layout on the next page, we'd start laying

> > out at 0x40f000 rather than 0x40fe20.  I think that would be the

> 

> But if the prior ro section size is greater than one page, we want

> to subtract 1 page:

> 

> +  /* If the preceding section size is greater than the maximum

> +      page size, subtract the maximum page size.  Otherwise,

> +      align the RELRO segment to the maximum page size.  */

> +   if (prev_sec->size > seg->maxpagesize)

> +     {

> +       desired_end -= seg->maxpagesize;

> +       relro_end -= seg->maxpagesize;

> +     }

> +   else

> +     {

> +       desired_end &= ~(seg->maxpagesize - 1);

> +       relro_end &= ~(seg->maxpagesize - 1);

> +     }

> +   }


The above code is the major reason why I took a dislike to your
patch.  I fully expected you would have rev 2 posted.  Why does
anything depend on the size of a previous section??  That just doesn't
make sense.  And please don't write comments that just say what the
code is doing.  Any half competent programmer can see what the code is
doing.  Write comments that say *why*.

> > correct thing to do rather than fixing up afterwards as your patch

> > does.

> >

> 

> I am checking in my patch as Nick has approved it. There is a

> possibility that one 1-page gap may be needed to maintain

> the section alignment.  My patch checks it and includes many

> testcase adjustments to remove one 1-page gap.   Can you

> update the RELRO segment algorithm to make my fixup

> unnecessary?


Yes, I do think that is possible and desirable.  My thinking last
night was that it ought to be easy too.  A one-liner even.  Silly me,
a little experimentation soon showed up a fail of the pr18176
testcase, demonstrating that there are cases we can save disk space
without causing gaps.

-- 
Alan Modra
Australia Development Lab, IBM
Fangrui Song Jan. 14, 2022, 9:37 a.m. | #6
On 2022-01-14, Alan Modra via Binutils wrote:
>On Thu, Jan 13, 2022 at 05:19:22AM -0800, H.J. Lu wrote:

>> On Thu, Jan 13, 2022 at 4:52 AM Alan Modra <amodra@gmail.com> wrote:

>> >

>> > On Mon, Jan 10, 2022 at 06:12:41PM -0800, H.J. Lu via Binutils wrote:

>> > > The existing RELRO scheme may leave a 1-page gap before the RELRO segment

>> > > and align the end of the RELRO segment to the page size:

>> > >

>> > >   [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

>> > >   [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8

>> > >   [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8

>> > >   [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8

>> > >   [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8

>> > >   [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8

>> >

>> > Do you know what is going wrong with the relro section layout for this

>> > to occur?

>> >

>> > In this particular case, the end of the read-only segment is at

>> > 0x408fa0 + 0x5e80 = 0x40ee20.  My guess is that layout of the

>> > following rw sections starts on the next page plus current offset

>> > within page, the standard choice to minimise disk pages.  ie. We start

>> > at 0x40fe20.  Then discover that this puts .got.plt at 0x40fe20 + 8 +

>> > 8 + 0x200 + 0x10 = 0x40f040.  However, we want this to be on a page

>> > boundary so that the relro segment ends on a page boundary.  So we

>> > bump 0x40f040 up to 0x411000 and calculate backwards from there to

>> > arrive at .init_array with a vma of 0x410de0.  Resulting in the

>> > 0x40f000 page being unused.

>> >

>> > If instead we start relro layout on the next page, we'd start laying

>> > out at 0x40f000 rather than 0x40fe20.  I think that would be the

>>

>> But if the prior ro section size is greater than one page, we want

>> to subtract 1 page:

>>

>> +  /* If the preceding section size is greater than the maximum

>> +      page size, subtract the maximum page size.  Otherwise,

>> +      align the RELRO segment to the maximum page size.  */

>> +   if (prev_sec->size > seg->maxpagesize)

>> +     {

>> +       desired_end -= seg->maxpagesize;

>> +       relro_end -= seg->maxpagesize;

>> +     }

>> +   else

>> +     {

>> +       desired_end &= ~(seg->maxpagesize - 1);

>> +       relro_end &= ~(seg->maxpagesize - 1);

>> +     }

>> +   }

>

>The above code is the major reason why I took a dislike to your

>patch.  I fully expected you would have rev 2 posted.  Why does

>anything depend on the size of a previous section??  That just doesn't

>make sense.  And please don't write comments that just say what the

>code is doing.  Any half competent programmer can see what the code is

>doing.  Write comments that say *why*.

>

>> > correct thing to do rather than fixing up afterwards as your patch

>> > does.

>> >

>>

>> I am checking in my patch as Nick has approved it. There is a

>> possibility that one 1-page gap may be needed to maintain

>> the section alignment.  My patch checks it and includes many

>> testcase adjustments to remove one 1-page gap.   Can you

>> update the RELRO segment algorithm to make my fixup

>> unnecessary?

>

>Yes, I do think that is possible and desirable.  My thinking last

>night was that it ought to be easy too.  A one-liner even.  Silly me,

>a little experimentation soon showed up a fail of the pr18176

>testcase, demonstrating that there are cases we can save disk space

>without causing gaps.


How about the 2-RW design?  |RW(RELRO)  |RW(non-RELRO)
The bar | indicates an alignment. Only alignment the start of a
segment, never the end of a segment.

It may avoid the unusual "otherwise DATA_SEGMENT_ALIGN is padded so that
exp + offset is aligned to the commonpagesize argument given to
DATA_SEGMENT_ALIGN" semantics on
https://sourceware.org/binutils/docs/ld/Builtin-Functions.html

I thought about the layout in the past and did not find cases where it
used more pages than the single-RW layout, but I did not think very
hard. (I haven't thought about max-page-size > common-page-size cases.)
H.J. Lu via Binutils Jan. 14, 2022, 2:58 p.m. | #7
On Fri, Jan 14, 2022 at 12:12 AM Alan Modra <amodra@gmail.com> wrote:
>

> On Thu, Jan 13, 2022 at 05:19:22AM -0800, H.J. Lu wrote:

> > On Thu, Jan 13, 2022 at 4:52 AM Alan Modra <amodra@gmail.com> wrote:

> > >

> > > On Mon, Jan 10, 2022 at 06:12:41PM -0800, H.J. Lu via Binutils wrote:

> > > > The existing RELRO scheme may leave a 1-page gap before the RELRO segment

> > > > and align the end of the RELRO segment to the page size:

> > > >

> > > >   [18] .eh_frame    PROGBITS    408fa0 008fa0 005e80 00   A  0   0  8

> > > >   [19] .init_array  INIT_ARRAY  410de0 00fde0 000008 08  WA  0   0  8

> > > >   [20] .fini_array  FINI_ARRAY  410de8 00fde8 000008 08  WA  0   0  8

> > > >   [21] .dynamic     DYNAMIC     410df0 00fdf0 000200 10  WA  7   0  8

> > > >   [22] .got         PROGBITS    410ff0 00fff0 000010 08  WA  0   0  8

> > > >   [23] .got.plt     PROGBITS    411000 010000 000048 08  WA  0   0  8

> > >

> > > Do you know what is going wrong with the relro section layout for this

> > > to occur?

> > >

> > > In this particular case, the end of the read-only segment is at

> > > 0x408fa0 + 0x5e80 = 0x40ee20.  My guess is that layout of the

> > > following rw sections starts on the next page plus current offset

> > > within page, the standard choice to minimise disk pages.  ie. We start

> > > at 0x40fe20.  Then discover that this puts .got.plt at 0x40fe20 + 8 +

> > > 8 + 0x200 + 0x10 = 0x40f040.  However, we want this to be on a page

> > > boundary so that the relro segment ends on a page boundary.  So we

> > > bump 0x40f040 up to 0x411000 and calculate backwards from there to

> > > arrive at .init_array with a vma of 0x410de0.  Resulting in the

> > > 0x40f000 page being unused.

> > >

> > > If instead we start relro layout on the next page, we'd start laying

> > > out at 0x40f000 rather than 0x40fe20.  I think that would be the

> >

> > But if the prior ro section size is greater than one page, we want

> > to subtract 1 page:

> >

> > +  /* If the preceding section size is greater than the maximum

> > +      page size, subtract the maximum page size.  Otherwise,

> > +      align the RELRO segment to the maximum page size.  */

> > +   if (prev_sec->size > seg->maxpagesize)

> > +     {

> > +       desired_end -= seg->maxpagesize;

> > +       relro_end -= seg->maxpagesize;

> > +     }

> > +   else

> > +     {

> > +       desired_end &= ~(seg->maxpagesize - 1);

> > +       relro_end &= ~(seg->maxpagesize - 1);

> > +     }

> > +   }

>

> The above code is the major reason why I took a dislike to your

> patch.  I fully expected you would have rev 2 posted.  Why does

> anything depend on the size of a previous section??  That just doesn't


If the size of the preceding section is less than one page, we need
to align the RELRO segment.  If we subtract one page, we still
have a 1-page gap.   I ran out of time before I could dig into the
complex logic.

> make sense.  And please don't write comments that just say what the

> code is doing.  Any half competent programmer can see what the code is

> doing.  Write comments that say *why*.

>

> > > correct thing to do rather than fixing up afterwards as your patch

> > > does.

> > >

> >

> > I am checking in my patch as Nick has approved it. There is a

> > possibility that one 1-page gap may be needed to maintain

> > the section alignment.  My patch checks it and includes many

> > testcase adjustments to remove one 1-page gap.   Can you

> > update the RELRO segment algorithm to make my fixup

> > unnecessary?

>

> Yes, I do think that is possible and desirable.  My thinking last

> night was that it ought to be easy too.  A one-liner even.  Silly me,

> a little experimentation soon showed up a fail of the pr18176

> testcase, demonstrating that there are cases we can save disk space

> without causing gaps.

>

> --

> Alan Modra

> Australia Development Lab, IBM




-- 
H.J.

Patch

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 9dbc8752f87..4a1dc19e100 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -6361,7 +6361,9 @@  static bfd_vma
 lang_size_relro_segment_1 (seg_align_type *seg)
 {
   bfd_vma relro_end, desired_end;
-  asection *sec;
+  asection *sec, *prev_sec = NULL;
+  bool remove_page_gap = false;
+  unsigned int max_alignment_power = 0;
 
   /* Compute the expected PT_GNU_RELRO/PT_LOAD segment end.  */
   relro_end = ((seg->relro_end + seg->pagesize - 1)
@@ -6372,28 +6374,79 @@  lang_size_relro_segment_1 (seg_align_type *seg)
 
   /* For sections in the relro segment..  */
   for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
-    if ((sec->flags & SEC_ALLOC) != 0
-	&& sec->vma >= seg->base
-	&& sec->vma < seg->relro_end - seg->relro_offset)
+    if ((sec->flags & SEC_ALLOC) != 0)
       {
-	/* Where do we want to put this section so that it ends as
-	   desired?  */
-	bfd_vma start, end, bump;
-
-	end = start = sec->vma;
-	if (!IS_TBSS (sec))
-	  end += TO_ADDR (sec->size);
-	bump = desired_end - end;
-	/* We'd like to increase START by BUMP, but we must heed
-	   alignment so the increase might be less than optimum.  */
-	start += bump;
-	start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
-	/* This is now the desired end for the previous section.  */
-	desired_end = start;
+	if (sec->alignment_power > max_alignment_power)
+	  max_alignment_power = sec->alignment_power;
+
+	if (sec->vma >= seg->base
+	    && sec->vma < seg->relro_end - seg->relro_offset)
+	  {
+	    /* Where do we want to put this section so that it ends as
+	       desired?  */
+	    bfd_vma start, end, bump;
+
+	    end = start = sec->vma;
+	    if (!IS_TBSS (sec))
+	      end += TO_ADDR (sec->size);
+	    bump = desired_end - end;
+	    /* We'd like to increase START by BUMP, but we must heed
+	       alignment so the increase might be less than optimum.  */
+	    start += bump;
+	    start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
+	    /* This is now the desired end for the previous section.  */
+	    desired_end = start;
+	    prev_sec = sec->prev;
+	  }
       }
 
   seg->phase = exp_seg_relro_adjust;
   ASSERT (desired_end >= seg->base);
+
+  for (; prev_sec; prev_sec = prev_sec->prev)
+    if ((prev_sec->flags & SEC_ALLOC) != 0)
+      {
+	if (prev_sec->alignment_power > max_alignment_power)
+	  max_alignment_power = prev_sec->alignment_power;
+
+	if (prev_sec->size != 0)
+	  {
+	    /* The 1-page gap before the RELRO segment may be removed.  */
+	    remove_page_gap = ((prev_sec->vma + prev_sec->size
+				+ seg->maxpagesize) < desired_end);
+
+	    break;
+	  }
+      }
+
+  if (remove_page_gap)
+    {
+      /* Find the maximum section alignment.  */
+      for (sec = prev_sec; sec; sec = sec->prev)
+	if ((sec->flags & SEC_ALLOC) != 0
+	    && sec->alignment_power > max_alignment_power)
+	  max_alignment_power = sec->alignment_power;
+
+      /* Remove the 1-page gap before the RELRO segment only if the
+	 maximum page size >= the maximum section alignment.  */
+      if (seg->maxpagesize >= (1U << max_alignment_power))
+	{
+	  /* If the preceding section size is greater than the maximum
+	     page size, subtract the maximum page size.  Otherwise,
+	     align the RELRO segment to the maximum page size.  */
+	  if (prev_sec->size > seg->maxpagesize)
+	    {
+	      desired_end -= seg->maxpagesize;
+	      relro_end -= seg->maxpagesize;
+	    }
+	  else
+	    {
+	      desired_end &= ~(seg->maxpagesize - 1);
+	      relro_end &= ~(seg->maxpagesize - 1);
+	    }
+	  }
+      }
+
   seg->base = desired_end;
   return relro_end;
 }
diff --git a/ld/testsuite/ld-i386/pr20830.d b/ld/testsuite/ld-i386/pr20830.d
index 8a14a6087a1..f1e37336733 100644
--- a/ld/testsuite/ld-i386/pr20830.d
+++ b/ld/testsuite/ld-i386/pr20830.d
@@ -49,12 +49,12 @@  Disassembly of section .plt:
 Disassembly of section .plt.got:
 
 0+120 <func@plt>:
- +[a-f0-9]+:	ff a3 fc ff ff ff    	jmp    \*-0x4\(%ebx\)
+ +[a-f0-9]+:	ff a3 78 f0 ff ff    	jmp    \*-0xf88\(%ebx\)
  +[a-f0-9]+:	66 90                	xchg   %ax,%ax
 
 Disassembly of section .text:
 
 0+128 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   120 <func@plt>
- +[a-f0-9]+:	8b 83 fc ff ff ff    	mov    -0x4\(%ebx\),%eax
+ +[a-f0-9]+:	8b 83 78 f0 ff ff    	mov    -0xf88\(%ebx\),%eax
 #pass
diff --git a/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd b/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd
index 64151d10a7c..5a107465be2 100644
--- a/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd
+++ b/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd
@@ -5,8 +5,8 @@  Disassembly of section .text:
 .* <foo>:
 .*:	c0 10 00 00 0f 0c [	 ]*larl	%r1,2000 <bar>
 .*:	c0 10 00 00 0f 09 [	 ]*larl	%r1,2000 <bar>
-.*:	c4 1d 00 00 0f 02 [	 ]*lrl	%r1,1ff8 <_GLOBAL_OFFSET_TABLE_\+0x28>
+.*:	c4 1d 00 00 07 8a [	 ]*lrl	%r1,1108 <_GLOBAL_OFFSET_TABLE_\+0x28>
 .*:	58 10 c0 28 [	 ]*l	%r1,40\(%r12\)
 .*:	e3 10 c0 28 00 58 [	 ]*ly	%r1,40\(%r12\)
-.*:	c4 18 00 00 0e f6 [	 ]*lgrl	%r1,1ff0 <_GLOBAL_OFFSET_TABLE_\+0x20>
-.*:	c4 18 00 00 0e ef [	 ]*lgrl	%r1,1fe8 <_GLOBAL_OFFSET_TABLE_\+0x18>
+.*:	c4 18 00 00 07 7e [	 ]*lgrl	%r1,1100 <_GLOBAL_OFFSET_TABLE_\+0x20>
+.*:	c4 18 00 00 07 77 [	 ]*lgrl	%r1,10f8 <_GLOBAL_OFFSET_TABLE_\+0x18>
diff --git a/ld/testsuite/ld-x86-64/pr14207.d b/ld/testsuite/ld-x86-64/pr14207.d
index f330600b916..c06755f96d9 100644
--- a/ld/testsuite/ld-x86-64/pr14207.d
+++ b/ld/testsuite/ld-x86-64/pr14207.d
@@ -11,9 +11,9 @@  There are 4 program headers, starting at offset 64
 Program Headers:
   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
   LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000150 0x000150 R   0x200000
-  LOAD           0x000b.8 0x0000000000200b.8 0x0000000000200b.8 0x0004.0 0x000c.8 RW  0x200000
-  DYNAMIC        0x000b.0 0x0000000000200b.0 0x0000000000200b.0 0x0001.0 0x0001.0 RW  0x8
-  GNU_RELRO      0x000b.8 0x0000000000200b.8 0x0000000000200b.8 0x0004.0 0x0004.8 R   0x1
+  LOAD           0x000150 0x0000000000200150 0x0000000000200150 0x0004b8 0x0016f0 RW  0x200000
+  DYNAMIC        0x0001a0 0x00000000002001a0 0x00000000002001a0 0x0001c0 0x0001c0 RW  0x8
+  GNU_RELRO      0x000150 0x0000000000200150 0x0000000000200150 0x0004b8 0x000eb0 R   0x1
 
  Section to Segment mapping:
   Segment Sections...
diff --git a/ld/testsuite/ld-x86-64/pr18176.d b/ld/testsuite/ld-x86-64/pr18176.d
index 4e3ad9ff08d..3ff34fad6cb 100644
--- a/ld/testsuite/ld-x86-64/pr18176.d
+++ b/ld/testsuite/ld-x86-64/pr18176.d
@@ -5,5 +5,5 @@ 
 #target: x86_64-*-linux*
 
 #...
-  GNU_RELRO      0x04bd17 0x000000000024bd17 0x000000000024bd17 0x0022e9 0x0022e9 R   0x1
+  GNU_RELRO      0x04bcc7 0x000000000024bcc7 0x000000000024bcc7 0x002339 0x002339 R   0x1
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20830a-now.d b/ld/testsuite/ld-x86-64/pr20830a-now.d
index 4f284c44a40..b8fa6acd1d4 100644
--- a/ld/testsuite/ld-x86-64/pr20830a-now.d
+++ b/ld/testsuite/ld-x86-64/pr20830a-now.d
@@ -50,19 +50,19 @@  Contents of the .eh_frame section:
 Disassembly of section .plt:
 
 0+1b0 <.plt>:
- +[a-f0-9]+:	ff 35 32 0e 20 00    	push   0x200e32\(%rip\)        # 200fe8 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	ff 25 34 0e 20 00    	jmp    \*0x200e34\(%rip\)        # 200ff0 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 aa 01 20 00    	push   0x2001aa\(%rip\)        # 200360 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 ac 01 20 00    	jmp    \*0x2001ac\(%rip\)        # 200368 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
 
 Disassembly of section .plt.got:
 
 0+1c0 <func@plt>:
- +[a-f0-9]+:	ff 25 32 0e 20 00    	jmp    \*0x200e32\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	ff 25 aa 01 20 00    	jmp    \*0x2001aa\(%rip\)        # 200370 <func>
  +[a-f0-9]+:	66 90                	xchg   %ax,%ax
 
 Disassembly of section .text:
 
 0+1c8 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   1c0 <func@plt>
- +[a-f0-9]+:	48 8b 05 24 0e 20 00 	mov    0x200e24\(%rip\),%rax        # 200ff8 <func>
+ +[a-f0-9]+:	48 8b 05 9c 01 20 00 	mov    0x20019c\(%rip\),%rax        # 200370 <func>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20830a.d b/ld/testsuite/ld-x86-64/pr20830a.d
index 615b59fd5de..5c16652c4a8 100644
--- a/ld/testsuite/ld-x86-64/pr20830a.d
+++ b/ld/testsuite/ld-x86-64/pr20830a.d
@@ -57,12 +57,12 @@  Disassembly of section .plt:
 Disassembly of section .plt.got:
 
 0+1c0 <func@plt>:
- +[a-f0-9]+:	ff 25 32 0e 20 00    	jmp    \*0x200e32\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	ff 25 72 01 20 00    	jmp    \*0x200172\(%rip\)        # 200338 <func>
  +[a-f0-9]+:	66 90                	xchg   %ax,%ax
 
 Disassembly of section .text:
 
 0+1c8 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   1c0 <func@plt>
- +[a-f0-9]+:	48 8b 05 24 0e 20 00 	mov    0x200e24\(%rip\),%rax        # 200ff8 <func>
+ +[a-f0-9]+:	48 8b 05 64 01 20 00 	mov    0x200164\(%rip\),%rax        # 200338 <func>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20830b-now.d b/ld/testsuite/ld-x86-64/pr20830b-now.d
index 7c7f2f928ac..0c4f2ada3dd 100644
--- a/ld/testsuite/ld-x86-64/pr20830b-now.d
+++ b/ld/testsuite/ld-x86-64/pr20830b-now.d
@@ -1,4 +1,4 @@ 
-#name: PR ld/20830 (.plt.got, -z now)
+#name: PR ld/20830 x32 (.plt.got, -z now)
 #source: pr20830.s
 #as: --x32
 #ld: -z now -melf32_x86_64 -shared -z relro --ld-generated-unwind-info --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
@@ -42,19 +42,19 @@  Contents of the .eh_frame section:
 Disassembly of section .plt:
 
 0+120 <.plt>:
- +[a-f0-9]+:	ff 35 c2 0e 20 00    	push   0x200ec2\(%rip\)        # 200fe8 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	ff 25 c4 0e 20 00    	jmp    \*0x200ec4\(%rip\)        # 200ff0 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 12 01 20 00    	push   0x200112\(%rip\)        # 200238 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	ff 25 14 01 20 00    	jmp    \*0x200114\(%rip\)        # 200240 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 40 00          	nopl   0x0\(%rax\)
 
 Disassembly of section .plt.got:
 
 0+130 <func@plt>:
- +[a-f0-9]+:	ff 25 c2 0e 20 00    	jmp    \*0x200ec2\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	ff 25 12 01 20 00    	jmp    \*0x200112\(%rip\)        # 200248 <func>
  +[a-f0-9]+:	66 90                	xchg   %ax,%ax
 
 Disassembly of section .text:
 
 0+138 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   130 <func@plt>
- +[a-f0-9]+:	48 8b 05 b4 0e 20 00 	mov    0x200eb4\(%rip\),%rax        # 200ff8 <func>
+ +[a-f0-9]+:	48 8b 05 04 01 20 00 	mov    0x200104\(%rip\),%rax        # 200248 <func>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr20830b.d b/ld/testsuite/ld-x86-64/pr20830b.d
index 3c5d42b9c43..6f4f22ca960 100644
--- a/ld/testsuite/ld-x86-64/pr20830b.d
+++ b/ld/testsuite/ld-x86-64/pr20830b.d
@@ -1,4 +1,4 @@ 
-#name: PR ld/20830 (.plt.got)
+#name: PR ld/20830 x32 (.plt.got)
 #source: pr20830.s
 #as: --x32
 #ld: -melf32_x86_64 -shared -z relro --ld-generated-unwind-info --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code
@@ -49,12 +49,12 @@  Disassembly of section .plt:
 Disassembly of section .plt.got:
 
 0+130 <func@plt>:
- +[a-f0-9]+:	ff 25 c2 0e 20 00    	jmp    \*0x200ec2\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	ff 25 ea 00 20 00    	jmp    \*0x2000ea\(%rip\)        # 200220 <func>
  +[a-f0-9]+:	66 90                	xchg   %ax,%ax
 
 Disassembly of section .text:
 
 0+138 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   130 <func@plt>
- +[a-f0-9]+:	48 8b 05 b4 0e 20 00 	mov    0x200eb4\(%rip\),%rax        # 200ff8 <func>
+ +[a-f0-9]+:	48 8b 05 dc 00 20 00 	mov    0x2000dc\(%rip\),%rax        # 200220 <func>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr21038a-now.d b/ld/testsuite/ld-x86-64/pr21038a-now.d
index 1653a68ff8a..c05800962be 100644
--- a/ld/testsuite/ld-x86-64/pr21038a-now.d
+++ b/ld/testsuite/ld-x86-64/pr21038a-now.d
@@ -50,19 +50,19 @@  Contents of the .eh_frame section:
 Disassembly of section .plt:
 
 0+1b0 <.plt>:
- +[a-f0-9]+:	ff 35 32 0e 20 00    	push   0x200e32\(%rip\)        # 200fe8 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	f2 ff 25 33 0e 20 00 	bnd jmp \*0x200e33\(%rip\)        # 200ff0 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 aa 01 20 00    	push   0x2001aa\(%rip\)        # 200360 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	f2 ff 25 ab 01 20 00 	bnd jmp \*0x2001ab\(%rip\)        # 200368 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
 
 Disassembly of section .plt.got:
 
 0+1c0 <func@plt>:
- +[a-f0-9]+:	f2 ff 25 31 0e 20 00 	bnd jmp \*0x200e31\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	f2 ff 25 a9 01 20 00 	bnd jmp \*0x2001a9\(%rip\)        # 200370 <func>
  +[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
 
 0+1c8 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   1c0 <func@plt>
- +[a-f0-9]+:	48 8b 05 24 0e 20 00 	mov    0x200e24\(%rip\),%rax        # 200ff8 <func>
+ +[a-f0-9]+:	48 8b 05 9c 01 20 00 	mov    0x20019c\(%rip\),%rax        # 200370 <func>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr21038a.d b/ld/testsuite/ld-x86-64/pr21038a.d
index 6ef8db254e9..e0c3c7cf63f 100644
--- a/ld/testsuite/ld-x86-64/pr21038a.d
+++ b/ld/testsuite/ld-x86-64/pr21038a.d
@@ -56,12 +56,12 @@  Disassembly of section .plt:
 Disassembly of section .plt.got:
 
 0+1c0 <func@plt>:
- +[a-f0-9]+:	f2 ff 25 31 0e 20 00 	bnd jmp \*0x200e31\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	f2 ff 25 71 01 20 00 	bnd jmp \*0x200171\(%rip\)        # 200338 <func>
  +[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
 
 0+1c8 <foo>:
  +[a-f0-9]+:	e8 f3 ff ff ff       	call   1c0 <func@plt>
- +[a-f0-9]+:	48 8b 05 24 0e 20 00 	mov    0x200e24\(%rip\),%rax        # 200ff8 <func>
+ +[a-f0-9]+:	48 8b 05 64 01 20 00 	mov    0x200164\(%rip\),%rax        # 200338 <func>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr21038b-now.d b/ld/testsuite/ld-x86-64/pr21038b-now.d
index c042b6cf702..519c5a3e957 100644
--- a/ld/testsuite/ld-x86-64/pr21038b-now.d
+++ b/ld/testsuite/ld-x86-64/pr21038b-now.d
@@ -50,8 +50,8 @@  Contents of the .eh_frame section:
 Disassembly of section .plt:
 
 0+1b0 <.plt>:
- +[a-f0-9]+:	ff 35 32 0e 20 00    	push   0x200e32\(%rip\)        # 200fe8 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	f2 ff 25 33 0e 20 00 	bnd jmp \*0x200e33\(%rip\)        # 200ff0 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 b2 01 20 00    	push   0x2001b2\(%rip\)        # 200368 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	f2 ff 25 b3 01 20 00 	bnd jmp \*0x2001b3\(%rip\)        # 200370 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
  +[a-f0-9]+:	68 00 00 00 00       	push   \$0x0
  +[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmp 1b0 <func@plt-0x20>
@@ -60,7 +60,7 @@  Disassembly of section .plt:
 Disassembly of section .plt.sec:
 
 0+1d0 <func@plt>:
- +[a-f0-9]+:	f2 ff 25 21 0e 20 00 	bnd jmp \*0x200e21\(%rip\)        # 200ff8 <func>
+ +[a-f0-9]+:	f2 ff 25 a1 01 20 00 	bnd jmp \*0x2001a1\(%rip\)        # 200378 <func>
  +[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
diff --git a/ld/testsuite/ld-x86-64/pr21038c-now.d b/ld/testsuite/ld-x86-64/pr21038c-now.d
index 2058512b74e..6c947ea4c13 100644
--- a/ld/testsuite/ld-x86-64/pr21038c-now.d
+++ b/ld/testsuite/ld-x86-64/pr21038c-now.d
@@ -59,8 +59,8 @@  Contents of the .eh_frame section:
 Disassembly of section .plt:
 
 0+1f0 <.plt>:
- +[a-f0-9]+:	ff 35 ea 0d 20 00    	push   0x200dea\(%rip\)        # 200fe0 <_GLOBAL_OFFSET_TABLE_\+0x8>
- +[a-f0-9]+:	f2 ff 25 eb 0d 20 00 	bnd jmp \*0x200deb\(%rip\)        # 200fe8 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ +[a-f0-9]+:	ff 35 12 02 20 00    	push   0x200212\(%rip\)        # 200408 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ +[a-f0-9]+:	f2 ff 25 13 02 20 00 	bnd jmp \*0x200213\(%rip\)        # 200410 <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
  +[a-f0-9]+:	68 00 00 00 00       	push   \$0x0
  +[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmp 1f0 <func1@plt-0x20>
@@ -69,13 +69,13 @@  Disassembly of section .plt:
 Disassembly of section .plt.got:
 
 0+210 <func1@plt>:
- +[a-f0-9]+:	f2 ff 25 e1 0d 20 00 	bnd jmp \*0x200de1\(%rip\)        # 200ff8 <func1>
+ +[a-f0-9]+:	f2 ff 25 09 02 20 00 	bnd jmp \*0x200209\(%rip\)        # 200420 <func1>
  +[a-f0-9]+:	90                   	nop
 
 Disassembly of section .plt.sec:
 
 0+218 <func2@plt>:
- +[a-f0-9]+:	f2 ff 25 d1 0d 20 00 	bnd jmp \*0x200dd1\(%rip\)        # 200ff0 <func2>
+ +[a-f0-9]+:	f2 ff 25 f9 01 20 00 	bnd jmp \*0x2001f9\(%rip\)        # 200418 <func2>
  +[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
@@ -83,5 +83,5 @@  Disassembly of section .text:
 0+220 <foo>:
  +[a-f0-9]+:	e8 eb ff ff ff       	call   210 <func1@plt>
  +[a-f0-9]+:	e8 ee ff ff ff       	call   218 <func2@plt>
- +[a-f0-9]+:	48 8b 05 c7 0d 20 00 	mov    0x200dc7\(%rip\),%rax        # 200ff8 <func1>
+ +[a-f0-9]+:	48 8b 05 ef 01 20 00 	mov    0x2001ef\(%rip\),%rax        # 200420 <func1>
 #pass
diff --git a/ld/testsuite/ld-x86-64/pr21038c.d b/ld/testsuite/ld-x86-64/pr21038c.d
index a62d43a7bc0..40ecc97e517 100644
--- a/ld/testsuite/ld-x86-64/pr21038c.d
+++ b/ld/testsuite/ld-x86-64/pr21038c.d
@@ -68,7 +68,7 @@  Disassembly of section .plt:
 Disassembly of section .plt.got:
 
 0+210 <func1@plt>:
- +[a-f0-9]+:	f2 ff 25 e1 0d 20 00 	bnd jmp \*0x200de1\(%rip\)        # 200ff8 <func1>
+ +[a-f0-9]+:	f2 ff 25 c9 01 20 00 	bnd jmp \*0x2001c9\(%rip\)        # 2003e0 <func1>
  +[a-f0-9]+:	90                   	nop
 
 Disassembly of section .plt.sec:
@@ -82,5 +82,5 @@  Disassembly of section .text:
 0+220 <foo>:
  +[a-f0-9]+:	e8 eb ff ff ff       	call   210 <func1@plt>
  +[a-f0-9]+:	e8 ee ff ff ff       	call   218 <func2@plt>
- +[a-f0-9]+:	48 8b 05 c7 0d 20 00 	mov    0x200dc7\(%rip\),%rax        # 200ff8 <func1>
+ +[a-f0-9]+:	48 8b 05 af 01 20 00 	mov    0x2001af\(%rip\),%rax        # 2003e0 <func1>
 #pass