[PATCH] Linux/x86: Enable --rosegment by default

hev r@hev.cc
Tue Mar 17 17:13:11 GMT 2026


On Wed, Mar 18, 2026 at 12:18 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Mar 16, 2026 at 7:20 AM WANG Rui <r@hev.cc> wrote:
> >
> > Years ago, commit f6aec96dce1d ("ld: Add --enable-separate-code") introduced
> > -z separate-code, mainly to avoid mixing code and data in the same segment
> > for better cache performance, and enabled it by default for Linux/x86.
> >
> > Today, Linux already has working support for mapping executable code with THP,
> > which can noticeably reduce iTLB pressure and bring measurable performance
> > benefits.
> >
> > In practice, I observed that on AArch64 and LoongArch64 distros, ELF executables
> > typically place the code PT_LOAD segment first, so both the virtual address and
> > file offset are 0. That turns out to be an important prerequisite for THP-aware
> > PT_LOAD alignment optimizations [1][2][3], and the data shows clear performance
> > wins on both AArch64 and LoongArch64. [4][1]
> >
> > Linux/x86 is a bit of an outlier here: the default -z separate-code setting
> > happens to break this layout. So this patch changes the Linux/x86 default to
> > -z noseparate-code.
> >
> > Benchmark
> >
> > Machine: AMD Ryzen 9 7950X (x86_64)
> > Binutils: 2.46
> > GCC: 15.2.1 (built with -z,noseparate-code + --enable-host-pie)
> > Linux kernel: 6.19.6 with patch [1]
> >
> > Workload: building Linux v7.0-rc1 vmlinux with x86_64_defconfig.
> >
> >                 Without patch        With patch
> > instructions    8,246,133,611,932    8,246,025,137,750
> > cpu-cycles      8,001,028,142,928    7,565,925,107,502
> > itlb-misses     3,672,158,331        26,821,242
> > time elapsed    64.66 s              61.97 s
> >
> > Instructions are basically unchanged. iTLB misses drop from ~3.67B to
> > ~26M (~99.27% reduction), which results in about a ~5.44% reduction in
> > cycles and ~4.18% shorter wall time for this workload.
> >
> > [1] https://lore.kernel.org/linux-fsdevel/20260313005211.882831-1-r@hev.cc
> > [2] https://sourceware.org/pipermail/libc-alpha/2026-March/175776.html
> > [3] https://lore.kernel.org/linux-fsdevel/20260310145406.3073394-1-usama.arif@linux.dev
> > [4] https://lore.kernel.org/linux-fsdevel/20260314095022.217231-1-r@hev.cc
> >
>
> Please try this patch.
>
> Linux is working on mapping executable code with THP, transparent huge
> page, which can noticeably reduce iTLB pressure and bring measurable
> performance benefits.  Aligning both virtual address and file offset of
> code pages at the huge page size can help THP-aware PT_LOAD alignment
> optimizations.  When -z separate-code is used with PIE, we get
>
>  Type  Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
>  LOAD  0x000000 0x00000000 0x00000000 0x00404 0x00404 R   0x1000
>  LOAD  0x001000 0x00001000 0x00001000 0x00161 0x00161 R E 0x1000
>  LOAD  0x002000 0x00002000 0x00002000 0x00114 0x00114 R   0x1000
>  LOAD  0x002eac 0x00003eac 0x00003eac 0x00160 0x00164 RW  0x1000
>
> where virtual address and file offset of code pages aren't aligned at the
> huge page size which is greater than 4KB.  When --rosegment
>
> ‘--rosegment’
> ‘--no-rosegment’
>      Attempt to ensure that only a single read-only, non-code segment is
>      created.  Only useful when used in conjunction with the ‘-z
>      separate-code’ option.  The resulting binaries should be smaller
>      than if ‘-z separate-code’ is used on its own.  Without this
>      option, or if ‘--no-rosegment’ is specified, the ‘-z separate-code’
>      option will create two read-only segments, one before the code
>      segment and one after it.
>
> is also used, we got
>
>  Type  Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
>  LOAD  0x000000 0x00000000 0x00000000 0x00341 0x00341 R E 0x1000
>  LOAD  0x001000 0x00001000 0x00001000 0x00320 0x00320 R   0x1000
>  LOAD  0x001eac 0x00002eac 0x00002eac 0x00160 0x00164 RW  0x1000
>
> where virtual address and file offset of code pages are aligned at the
> huge page size.

This patch looks acceptable to me, and it’s good to see progress here.
That said, in some cases, -z noseparate-code can be more helpful for
THP. I explained the reasoning in another thread. [1][2]

Also, I’m a bit curious: GNU ld with --rosegment doesn’t seem to
arrange segments as R, RE, RW. From a security perspective, it would
make more sense to put R first so the ELF header is not executable.
LLVM lld with --rosegment does this by default (R, RE, RW).

I wonder whether relying on the current GNU ld --rosegment layout is
entirely stable, if it ever shifts towards a more security-driven
layout, it might not behave the way we expect here.

[1] https://sourceware.org/pipermail/binutils/2026-March/148605.html
[2] https://sourceware.org/pipermail/binutils/2026-March/148607.html

Thanks,
Rui


More information about the Binutils mailing list