[PATCH] ld: Disable separate code by default for Linux/x86
H.J. Lu
hjl.tools@gmail.com
Tue Mar 17 16:21:13 GMT 2026
On Mon, Mar 16, 2026 at 7:35 PM hev <r@hev.cc> wrote:
>
> 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.
ld.so should check if merging of RE and R segments is possible and
beneficial. Also merging should be tunable.
>
> 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.
>
True.
--
H.J.
More information about the Binutils
mailing list