[PATCH] ld: Disable separate code by default for Linux/x86

H.J. Lu hjl.tools@gmail.com
Tue Mar 17 02:15:16 GMT 2026


On Mon, Mar 16, 2026 at 7:11 PM hev <r@hev.cc> wrote:
>
> On Tue, Mar 17, 2026 at 9:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, Mar 16, 2026 at 5:27 PM hev <r@hev.cc> wrote:
> > >
> > > On Tue, Mar 17, 2026 at 5:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > >
> > > > > One benefit of -z noseparate-code is that the executable PT_LOAD ends
> > > > > up at virtual address 0 with file offset 0. For huge page mappings,
> > > > > both the virtual address and the file offset need to be aligned to the
> > > > > huge page size, e.g.
> > > > >
> > > > > ((p_vaddr | p_offset) & (HUGE_PAGE_SIZE - 1)) == 0
> > > > >
> > > > > Are you suggesting that, with the -z separate-code layout, ld.so would
> > > > > ignore the non-executable flag of the first PT_LOAD and merge it with
> > > > > the second PT_LOAD, mapping them together as read-only executable?
> > > > > That might help with existing binaries, but wouldn't it blur the
> > > > > permission boundaries between segments?
> > > > >
> > > >
> > > > That is correct.  It should have the similar effect as -z noseparate-code.
> > > > The difference is link-time vs run-time.  Of course, ld.so should do it only
> > > > when huge page is in use.
> > >
> > > Having ld.so transparently merge the mappings doesn't always seem
> > > workable. For example, in chromium the RE segment has different
> > > virtual addresses and file offsets, so we can't construct a correct
> > > mapping when attempting to merge them.
> > >
> > >   LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
> > >                  0x00000000014d2b2c 0x00000000014d2b2c  R      0x1000
> > >   LOAD           0x00000000014d3000 0x00000000014d4000 0x00000000014d4000
> > >                  0x000000000fb7a420 0x000000000fb7a420  R E    0x1000
> > >   LOAD           0x000000001104d420 0x000000001104f420 0x000000001104f420
> > >                  0x0000000000ac0f58 0x0000000000ac1be0  RW     0x1000
> > >   LOAD           0x0000000011b0f000 0x0000000011b12000 0x0000000011b12000
> > >                  0x0000000000146001 0x0000000000428d34  RW     0x1000
> > >
> >
> > This layout won't work.   It can be an option for compatible layouts.  For
> > ld on Linux/x86, we can default to --rosegment.
>
> With -z separate-code + --rosegment, the layout appears as RE, R, and
> RW, which also looks reasonable.

I think ld.so can map RE + R to RE when huge page is enabled if it
is shown to improve performance.

> With -z noseparate-code + --no-rosegment, the RE and R segments are
> merged, resulting in RE and RW.
>
> One advantage of the latter is that read-only data can also benefit
> from huge page mappings. In addition, the merged segment has a better
> chance of being mapped with huge pages. Since a PMD-sized huge page is
> 2 MB, a segment shorter than that cannot use it. Merging segments
> increases the total size, making PMD usage more likely.
>
> Thanks,
> Rui



-- 
H.J.


More information about the Libc-alpha mailing list