[PATCH] Linux/x86: Enable --rosegment by default
hev
r@hev.cc
Thu Mar 19 04:10:18 GMT 2026
On Thu, Mar 19, 2026 at 11:15 AM Fangrui Song <i@maskray.me> wrote:
>
> On Wed, Mar 18, 2026 at 7:56 PM hev <r@hev.cc> wrote:
> >
> > On Thu, Mar 19, 2026 at 10:06 AM Fangrui Song <i@maskray.me> wrote:
> > > For x86, --no-rosegment -z noseparate-code -z max-page-size=2097152 is
> > > the most compact layout that works with transparent hugepages.
> > > Google and ChromeOS have been using such a layout for a long time.
> >
> > --no-rosegment -z noseparate-code -z max-page-size=2097152 is somewhat
> > more compact than --no-rosegment -z separate-code -z
> > max-page-size=2097152. However, due to alignment, there is still a
> > sizable gap between the RE and RW segments, which significantly
> > increases the file size (e.g. hello world: 6K -> 2.1M). This is almost
> > impractical with 32M huge pages.
> >
> > LOAD 0x0000000000000000 0x0000000000000000
> > 0x0000000000000000
> > 0x0000000000000738 0x0000000000000738 R E
> > 0x200000
> > LOAD 0x00000000001ffe10 0x00000000003ffe10 0x00000000003ffe10
> > 0x0000000000000200 0x0000000000000208 RW 0x200000
>
> This is due to the suboptimal PT_GNU_RELRO layout in GNU ld. See
> https://sourceware.org/bugzilla/show_bug.cgi?id=30612
> mold and ld.lld avoid this issue by introducing the .relro_padding
> section. lld's implementation also emulates
> DATA_SEGMENT_ALIGN/DATA_RELRO_END.
>
> https://maskray.me/blog/2020-11-15-explain-gnu-linker-options#z-relro
>
> """
> GNU ld uses one RW PT_LOAD program header with padding at the start.
> The first half of the PT_LOAD overlaps with PT_GNU_RELRO. The padding
> is added so that the end of PT_GNU_RELRO is aligned by max-page-size.
> (See ld.bfd --verbose output.) Prior to GNU ld 2.39, the end was
> aligned by common-page-size. GNU ld's one RW PT_LOAD layout makes the
> alignment increase the file size. max-page-size can be large, such as
> 65536 for many systems, causing wasted space.
>
> lld utilitizes two RW PT_LOAD program headers: one for RELRO sections
> and the other for non-RELRO sections. Although this might appear
> unusual initially, it eliminates the need for alignment padding as
> seen in GNU ld's layout. Key changes:
>
> https://reviews.llvm.org/D58892 switched from
> PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) .data .bss) to
> PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro)) PT_LOAD(.data. .bss).
> The end of the PT_GNU_RELRO segment and the associated RW PT_LOAD
> segment is padded to a common-page-size boundary. The padding section
> .relro_padding is like mold. Before LLD 18, there is an issue that
> runtime_page_size < common-page-size does not work.
>
> The layout used by mold is similar to that of lld. In mold's case, the
> end of PT_GNU_RELRO is padded to max-page-size by appending a
> SHT_NOBITS .relro_padding section. This approach ensures that the last
> page of PT_GNU_RELRO is protected, regardless of the system page size.
> However, when the system page size is less than max-page-size, the map
> from the first RW PT_LOAD is larger than needed.
> """
Thanks for the explanation.
With -z separate-code --rosegment, the segments are page-aligned, so
there’s no overlap when mapped.
With the default -z noseparate-code --rosegment, read-only data ends
up in a non-executable segment, but since the layout is packed, the RO
and RX segments aren’t fully separated. From a THP-friendly
perspective, I’m curious what you think about LLD defaulting to
--no-rosegment?
Thanks,
Rui
More information about the Binutils
mailing list