[PATCH] ld: Avoid moving desired relro end below relro section

H.J. Lu hjl.tools@gmail.com
Mon Feb 17 07:20:43 GMT 2025


On Mon, Feb 17, 2025 at 2:29 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Mon, Feb 17, 2025 at 04:56:57AM +0800, H.J. Lu wrote:
> > On Sun, Feb 16, 2025 at 12:38 PM Alan Modra <amodra@gmail.com> wrote:
> > >
> > > On Sun, Feb 16, 2025 at 06:19:07AM +0800, H.J. Lu wrote:
> > > > --- a/ld/ldlang.c
> > > > +++ b/ld/ldlang.c
> > > > @@ -6605,10 +6605,16 @@ lang_size_relro_segment_1 (void)
> > > >       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;
> > > > +     if (desired_end > end)
> > > > +       {
> > > > +         /* Avoid moving START backwards.  */
> > > > +         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;
> > > > +       }
> > > > +     else
> > > > +       start = end;
> > > >       start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
> > > >       /* This is now the desired end for the previous section.  */
> > > >       desired_end = start;
> > >
> > > This doesn't make any sense at all.  You're putting sections on top of
> > > each other!
> > >
> > > The assert failure can't be fixed by totally breaking this function.
> > >
> > > Look instead at why sections now don't fit.  Have they changed in size
> > > since the time seg->relro_end and seg->base were set?
> >
> > When setting seg->base to 0x2f3000, there are:
> >
> > section       vma           size      vma + size    alignment
> > .got   0x2c2118   0x0    0x2c2118   8
> > .dynamic   0x2c20e8   0x0    0x2c20e8   8
> > .data.rel.ro   0x298020   0x0    0x298020   32
> > .fini_array   0x298008   0x0    0x298008   8
> > .init_array   0x298000   0x0    0x298000   8
>
> Something doesn't add up here.  The change in vma indicates the size
> of .init_array is 8, .fini_array between 0 and 0x18, .data.rel.ro is
> 0x2a0c8, .dynamic is 0x30.
>
> >
> > When setting seg->relro_end to 0x320fe8 after that, there are
> >
> > section       vma           size      vma + size    alignment
> > .got   0x320268   0xd80    0x320fe8   8
> > .dynamic   0x31ffe8   0x280    0x320268   8
> > .data.rel.ro   0x2f3020   0x2cfc8    0x31ffe8   128
> > .fini_array   0x2f3008   0x8    0x2f3010   8
> > .init_array   0x2f3000   0x8    0x2f3008   8
>
> Lot's of things changed according to this, including .data.rel.ro
> alignment.  There can be multiple iterations of layout and sizing.
>
> For the iteration of lang_size_relro_segment_1 that failed the

lang_size_relro_segment_1 failed at the first interation.

> assertion, what were the most recent assignments to relro_end and
> base?  After those particular assignments, did any relro section size
> or alignment change?  If they did, you've found the real problem.

There were no changes in size nor alignment after he most recent
assignments to relro_end and base before lang_size_relro_segment_1
was called.

(gdb) run
...
Hardware watchpoint 2: expld.dataseg.base

Old value = 0
New value = 2719744
fold_segment_align (lhs=0x7fffffffb350)
    at /export/gnu/import/git/gitlab/x86-binutils/ld/ldexp.c:487
487       seg->commonpagesize = commonpage;
(gdb) c
Continuing.

Hardware watchpoint 3: expld.dataseg.relro_end

Old value = 0
New value = 2892056
fold_segment_relro_end (lhs=0x7fffffffb350)
    at /export/gnu/import/git/gitlab/x86-binutils/ld/ldexp.c:519
519       if (seg->phase == exp_seg_relro_adjust
(gdb)
Continuing.

Hardware watchpoint 2: expld.dataseg.base

Old value = 2719744
New value = 3092480
fold_segment_align (lhs=0x7fffffffb350)
    at /export/gnu/import/git/gitlab/x86-binutils/ld/ldexp.c:487
487       seg->commonpagesize = commonpage;
(gdb)
Continuing.

Hardware watchpoint 3: expld.dataseg.relro_end

Old value = 2892056
New value = 0
fold_segment_align (lhs=0x7fffffffb350)
    at /export/gnu/import/git/gitlab/x86-binutils/ld/ldexp.c:496
496 }
(gdb)
Continuing.

Hardware watchpoint 3: expld.dataseg.relro_end

Old value = 0
New value = 3280872
fold_segment_relro_end (lhs=0x7fffffffb350)
    at /export/gnu/import/git/gitlab/x86-binutils/ld/ldexp.c:519
519       if (seg->phase == exp_seg_relro_adjust
(gdb) call debug_vma ()
section       vma           size      vma + size    alignment
.got (0x6f91130)   0x320268   0xd80    0x320fe8   8
.dynamic (0x6f91008)   0x31ffe8   0x280    0x320268   8
.data.rel.ro (0x6f90ee0)   0x2f3020   0x2cfc8    0x31ffe8   128
.fini_array (0x6f90db8)   0x2f3008   0x8    0x2f3010   8
.init_array (0x6f80a60)   0x2f3000   0x8    0x2f3008   8
(gdb) c
Continuing.

Breakpoint 1, lang_size_relro_segment_1 ()
    at /export/gnu/import/git/gitlab/x86-binutils/ld/ldlang.c:6616
6616   seg_align_type *seg = &expld.dataseg;
(gdb) call debug_vma ()
section       vma           size      vma + size    alignment
.got (0x6f91130)   0x320268   0xd80    0x320fe8   8
.dynamic (0x6f91008)   0x31ffe8   0x280    0x320268   8
.data.rel.ro (0x6f90ee0)   0x2f3020   0x2cfc8    0x31ffe8   128
.fini_array (0x6f90db8)   0x2f3008   0x8    0x2f3010   8
.init_array (0x6f80a60)   0x2f3000   0x8    0x2f3008   8
(gdb)


H.J.


More information about the Binutils mailing list