[PATCH] ld: Avoid moving desired relro end below relro section
H.J. Lu
hjl.tools@gmail.com
Mon Feb 17 07:58:40 GMT 2025
On Mon, Feb 17, 2025 at 3:20 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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)
Here I got
(gdb) call debug_vma ()
section vma size vma + size alignment
.got (0x6f91130) 0x2c2118 0x0 0x2c2118 8
.dynamic (0x6f91008) 0x2c20e8 0x0 0x2c20e8 8
.data.rel.ro (0x6f90ee0) 0x298020 0x0 0x298020 32
.fini_array (0x6f90db8) 0x298008 0x0 0x298008 8
.init_array (0x6f80a60) 0x298000 0x0 0x298000 8
(gdb)
The input dynamic .data.rel.ro (dynbss) is changed to 128:
Hardware watchpoint 6: *(unsigned int *) 0x743674
Old value = 0
New value = 7
bfd_set_section_alignment (sec=0x7435f8, val=7) at ./bfd.h:918
918 return true;
(gdb) bt
#0 bfd_set_section_alignment (sec=0x7435f8, val=7) at ./bfd.h:918
#1 0x00000000004adef3 in _bfd_elf_adjust_dynamic_copy (
info=0x6ed380 <link_info>, h=0x1f1d820, dynbss=0x7435f8)
at /export/gnu/import/git/gitlab/x86-binutils/bfd/elflink.c:3390
#2 0x000000000047d11b in _bfd_x86_elf_adjust_dynamic_symbol (
info=0x6ed380 <link_info>, h=0x1f1d820)
at /export/gnu/import/git/gitlab/x86-binutils/bfd/elfxx-x86.c:3611
#3 0x00000000004ade47 in _bfd_elf_adjust_dynamic_symbol (h=0x1f1d820,
data=0x7fffffffb270)
at /export/gnu/import/git/gitlab/x86-binutils/bfd/elflink.c:3353
#4 0x00000000004552a0 in bfd_link_hash_traverse (htab=0x71bbe0,
func=0x4adb54 <_bfd_elf_adjust_dynamic_symbol>, info=0x7fffffffb270)
at /export/gnu/import/git/gitlab/x86-binutils/bfd/linker.c:692
#5 0x00000000004a7d68 in elf_link_hash_traverse (table=0x71bbe0,
f=0x4adb54 <_bfd_elf_adjust_dynamic_symbol>, info=0x7fffffffb270)
at /export/gnu/import/git/gitlab/x86-binutils/bfd/elf-bfd.h:800
#6 0x00000000004b72b0 in bfd_elf_size_dynamic_sections (output_bfd=0x704230,
soname=0x0, rpath=0x701c40 "/tmp/foo", filter_shlib=0x0, audit=0x0,
depaudit=0x0, auxiliary_filters=0x0, info=0x6ed380 <link_info>,
sinterpptr=0x7fffffffb4f8)
at /export/gnu/import/git/gitlab/x86-binutils/bfd/elflink.c:7586
#7 0x0000000000440fb5 in ldelf_before_allocation (audit=0x6ed8c0 <audit>,
depaudit=0x6ed8c8 <depaudit>, default_interpreter_name=0x0)
at /export/gnu/import/git/gitlab/x86-binutils/ld/ldelf.c:1840
#8 0x0000000000436057 in gldelf_x86_64_before_allocation ()
at eelf_x86_64.c:172
#9 0x0000000000435efb in elf_x86_64_before_allocation () at eelf_x86_64.c:115
#10 0x0000000000429535 in ldemul_before_allocation ()
at /export/gnu/import/git/gitlab/x86-binutils/ld/ldemul.c:96
#11 0x000000000041c3bf in lang_process ()
at /export/gnu/import/git/gitlab/x86-binutils/ld/ldlang.c:8628
#12 0x00000000004227ea in main (argc=382, argv=0x7fffffffb858)
at /export/gnu/import/git/gitlab/x86-binutils/ld/ldmain.c:533
(gdb)
.data.rel.ro in libbfd.so is aligned to 128 bytes. We guess
the symbol, tic6x_elf32_c6000_be_vec, alignment
bool
_bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
struct elf_link_hash_entry *h,
asection *dynbss)
{
unsigned int power_of_two;
bfd_vma mask;
asection *sec = h->root.u.def.section;
/* The section alignment of the definition is the maximum alignment
requirement of symbols defined in the section. Since we don't
know the symbol alignment requirement, we start with the
maximum alignment and check low bits of the symbol address
for the minimum alignment. */
power_of_two = bfd_section_alignment (sec);
mask = ((bfd_vma) 1 << power_of_two) - 1;
while ((h->root.u.def.value & mask) != 0)
We got a non-zero value since sec->vma != 0 after my patch.
{
mask >>= 1;
--power_of_two;
}
if (power_of_two > bfd_section_alignment (dynbss))
{
/* Adjust the section alignment if needed. */
if (!bfd_set_section_alignment (dynbss, power_of_two))
return false;
}
> 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.
--
H.J.
More information about the Binutils
mailing list