[PATCH] ld: Disable separate code by default for Linux/x86
hev
r@hev.cc
Tue Mar 17 02:35:14 GMT 2026
On Tue, Mar 17, 2026 at 10:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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.
Yes, this works if the virtual addresses and file offsets line up.
When the segment p_align matches the base page size, merging them in
ld.so doesn't waste physical memory.
However, on systems that support multiple page sizes, such as AArch64
and LoongArch64, p_align is typically 64 KB. That means there is
padding between the RE and R segments. With normal page mappings those
pages aren't populated, but if they are merged into a huge-page
mapping, the entire huge page would end up being backed by physical
memory.
If ld.so goes down this path, it probably needs to work as a general
mechanism rather than something tailored for x86, which introduces
another trade-off.
Thanks,
Rui
More information about the Libc-alpha
mailing list