On Fri, Feb 13, 2026 at 08:05:02PM -0500, Nicholas Vinson wrote:
> The i386-pc kernel image fails to build because of changes made to
> address ld.lld-21 and newer linking issues. Specifically, with
> ld.lld-21, if you try to set the text section address below image base
> address when linking a non-relocatable binary, ld.lld wil fail to link.
>
> Switching to using a customized linker script solves the issue and is a
> more robost solution to supporting multiple linkers than attempting to
> find a set of command-line flags that satisified all supported linkers
> and links the kernel properly. In the worst case, continued use of
> command-line flags could result in having to create code branches to
> support various linkers.
>
> For example, when dealing with just ld.bfd and ld.lld, the behavioral
> differences between the two made finding a proper subset of flags that
> worked impossible. The previous attempt dropped -Ttext for --image-base,
> which has been proven not to work. The simplest correction,
> -Wl,--image-base=0 -Wl,-Ttext, did not work because that option resulted
> in a GRUB kernel that entered into a tight infinite refresh loop.
>
> Moreover, ld.lld does not order the sections the same way ld.bfd does,
> and that results in object files with gaps or holes when sections are
> stripped. I suspect, but did not investigate, that this plays a role in
> the infinite refresh loop I mentioned earlier.
>
> The easiest way to resolve all this is to use customized linker scripts.
> These scripts, by default, override any default configuration the linker
> would otherwise impose, allow for complete control in aligning sections,
> and allows GRUB to specify where in the load segment each section goes.
>
> This change does require linkers to support the --defsym flag, which
> requires its argument to be of the form 'sym=address' as 'sym address'
> is not supported.
>
> Signed-off-by: Nicholas Vinson <[email protected]>
> ---
>  conf/Makefile.extra-dist    |  1 +
>  conf/i386-pc-kernel.lds     | 51 +++++++++++++++++++++++++++++++++++++
>  grub-core/Makefile.core.def | 31 +++++++++++-----------
>  3 files changed, 68 insertions(+), 15 deletions(-)
>  create mode 100644 conf/i386-pc-kernel.lds
>
> diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
> index d22b6c862..892df8208 100644
> --- a/conf/Makefile.extra-dist
> +++ b/conf/Makefile.extra-dist
> @@ -17,6 +17,7 @@ EXTRA_DIST += docs/grub.cfg
>  EXTRA_DIST += docs/osdetect.cfg
>
>  EXTRA_DIST += conf/i386-cygwin-img-ld.sc
> +EXTRA_DIST += conf/i386-pc-kernel.lds
>
>  EXTRA_DIST += grub-core/Makefile.core.def
>  EXTRA_DIST += grub-core/Makefile.gcry.def
> diff --git a/conf/i386-pc-kernel.lds b/conf/i386-pc-kernel.lds
> new file mode 100644
> index 000000000..d40c7736c
> --- /dev/null
> +++ b/conf/i386-pc-kernel.lds
> @@ -0,0 +1,51 @@
> +ENTRY(_start)
> +
> +/*
> + * Align sections to a 16-byte boundary. This guarantees ABI compatibility 
> with
> + * C generated code
> + */
> +SECTION_ALIGN = 0x10;
> +
> +PHDRS {
> +    text PT_LOAD FLAGS(7) /* PF_R | PF_W | PF_X */;
> +}
> +
> +SECTIONS
> +{
> +    /*
> +     * Set section alignment to 1. This allows sections to be aligned without
> +     * creating holes in the VMA space or gaps in the file.
> +     */
> +    . = _grub_text_base;
> +    .text ALIGN(0x1) : {
> +        _start = .;
> +        *(.text .text.*)
> +        . = ALIGN(SECTION_ALIGN);
> +    } :text
> +    .rodata ALIGN(0x1) : {
> +        *(.rodata .rodata.*)
> +        . = ALIGN(SECTION_ALIGN);
> +    } :text
> +    .module_license ALIGN(0x1) : {
> +        *(.module_license)
> +        . = ALIGN(SECTION_ALIGN);
> +    } :text
> +    .data ALIGN(0x1) : {
> +        *(.data .data.*)
> +        . = ALIGN(SECTION_ALIGN);
> +        _edata = .;
> +    } :text
> +    .bss ALIGN(0x1) : {
> +        __bss_start = .;
> +        *(.bss .bss.*)
> +        *(COMMON)
> +        . = ALIGN(SECTION_ALIGN);
> +        _end = .;
> +    } :text
> +    /DISCARD/ : {
> +        *(.interp)
> +        *(.note*)
> +        *(.comment)
> +        *(.build-id)
> +    }
> +}
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 0cf155128..1a91e53d6 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -10,6 +10,7 @@ transform_data = {
>    installdir = noinst;
>    name = genmod.sh;
>    common = genmod.sh.in;
> +  i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';

I think everything below belongs to patch #7.

>  };
>
>  transform_data = {
> @@ -82,21 +83,21 @@ kernel = {
>    riscv64_efi_stripflags   = '--strip-unneeded -K start -R .note -R .comment 
> -R .note.gnu.gold-version -R .eh_frame';
>
>    i386_pc_ldflags          = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags          = '$(TARGET_IMG_BASE_LDOPT),0x9000';
> +  i386_pc_ldflags          = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x9000';
>    i386_qemu_ldflags        = '$(TARGET_IMG_LDFLAGS)';
> -  i386_qemu_ldflags        = '$(TARGET_IMG_BASE_LDOPT),0x9000';
> +  i386_qemu_ldflags        = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x9000';
>    i386_coreboot_ldflags    = '$(TARGET_IMG_LDFLAGS)';
> -  i386_coreboot_ldflags    = '$(TARGET_IMG_BASE_LDOPT),0x9000';
> +  i386_coreboot_ldflags    = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x9000';
>    i386_multiboot_ldflags   = '$(TARGET_IMG_LDFLAGS)';
> -  i386_multiboot_ldflags   = '$(TARGET_IMG_BASE_LDOPT),0x9000';
> +  i386_multiboot_ldflags   = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x9000';
>    i386_ieee1275_ldflags    = '$(TARGET_IMG_LDFLAGS)';
> -  i386_ieee1275_ldflags    = '$(TARGET_IMG_BASE_LDOPT),0x10000';
> +  i386_ieee1275_ldflags    = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x10000';
>    i386_xen_ldflags         = '$(TARGET_IMG_LDFLAGS)';
> -  i386_xen_ldflags         = '$(TARGET_IMG_BASE_LDOPT),0';
> +  i386_xen_ldflags         = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0';
>    x86_64_xen_ldflags       = '$(TARGET_IMG_LDFLAGS)';
>    x86_64_xen_ldflags       = '$(TARGET_IMG_BASE_LDOPT),0';
>    i386_xen_pvh_ldflags     = '$(TARGET_IMG_LDFLAGS)';
> -  i386_xen_pvh_ldflags     = '$(TARGET_IMG_BASE_LDOPT),0x100000';
> +  i386_xen_pvh_ldflags     = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x100000';
>
>    mips_loongson_ldflags    = '-Wl,-Ttext,0x80200000';
>    powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000';
> @@ -450,10 +451,10 @@ image = {
>    sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S;
>
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
> +  i386_pc_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x7C00';
>
>    i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_qemu_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT),$(GRUB_BOOT_MACHINE_LINK_ADDR)';
> +  i386_qemu_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)$(GRUB_BOOT_MACHINE_LINK_ADDR)';
>    i386_qemu_ccasflags = 
> '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
>
>    /* The entry point for a.out binaries on sparc64 starts
> @@ -478,7 +479,7 @@ image = {
>    cppflags = '-DHYBRID_BOOT=1';
>
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
> +  i386_pc_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x7C00';
>
>    objcopyflags = '-O binary';
>    enable = i386_pc;
> @@ -489,7 +490,7 @@ image = {
>
>    i386_pc = boot/i386/pc/cdboot.S;
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
> +  i386_pc_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x7C00';
>
>    sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S;
>
> @@ -509,7 +510,7 @@ image = {
>    i386_pc = boot/i386/pc/pxeboot.S;
>
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
> +  i386_pc_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x7C00';
>
>    objcopyflags = '-O binary';
>    enable = i386_pc;
> @@ -520,7 +521,7 @@ image = {
>    i386_pc = boot/i386/pc/diskboot.S;
>
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8000';
> +  i386_pc_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x8000';
>
>    sparc64_ieee1275 = boot/sparc64/ieee1275/diskboot.S;
>    sparc64_ieee1275_ldflags = '-Wl,-Ttext=0x4200';
> @@ -536,7 +537,7 @@ image = {
>    i386_pc = boot/i386/pc/lnxboot.S;
>
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
> -  i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x6000';
> +  i386_pc_ldflags = 
> '$(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x6000';
>
>    objcopyflags = '-O binary';
>    enable = i386_pc;
> @@ -578,7 +579,7 @@ image = {
>    i386_pc_nodist = rs_decoder.h;
>
>    objcopyflags = '-O binary';
> -  ldflags = '$(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x8200';
> +  ldflags = '$(TARGET_IMG_LDFLAGS) 
> $(TARGET_IMG_BASE_LDOPT)$(TARGET_IMG_BASE_LDOPT_ARG_SEP)0x8200';
>    enable = i386_pc;
>  };

Daniel

_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to