[PATCH] riscv: Build SPL with -fno-pic

Nathaniel Hourt i at nathaniel.land
Fri Jan 2 02:41:42 CET 2026


On 2025-12-15 11:22, Yao Zi wrote:
> For RISC-V ports, both SPL and proper U-Boot are unconditionally built
> with -fpic, i.e. position-independent code, which means symbols may be
> addressed through GOT. This is useful for proper U-Boot, where we have
> relocate_code in arch/riscv/cpu/start.S and could relocate the GOT
> entries and other .data members to run at any address.
> 
> But for SPL, there's no self-relocating mechanism, all we could do is
> relying on the linker to fill correct addresses into the binary at link
> time, forming a position-dependent image. This effectively makes the
> GOT, which is generated by usage of -fpic and couldn't be optimized out
> at link time, an unnecessary size burden.
> 
> Moreover, our current linkscript for SPL doesn't take .got section into
> account, allowing the linker to put the GOT at unexpected positions,
> like after _end/_image_binary_end symbols. This has caused real-world
> boot failures[1] when SPL is linked by LLD.
> 
> These two reasons make building SPL with -fno-pic good choice,
> eliminating the usage of GOT at the first place. This patch replaces
> -fpic with -fno-pic in PLATFORM_CPPFLAGS when building SPL.
> 
> We also need to force medany code model for SPL to allow putting the
> executable at any contiguous 4GiB memory range, instead of only the
> lowest and highest 2GiB when using medlow. This wans't an issue
> previously, since GCC ignores -mcmodel=medlow when -fpic is specified,
> but is problematic with Clang, or without -fpic.
> 
> Building position-dependent code also produces bss/data/rodata section
> variants with "s" prefix on RISC-V, i.e. sbss/sdata/srodata. These are
> "small" sections which compilers expect to be put together, addressable
> through a single instruction relative to $gp register and thus saving
> code size. This is called GP-relaxation[2]. However, U-Boot takes $gp
> for global data pointer, making it impossible, so these sections are
> merged into their "larger" variants in linkscript.
> 
> Reported-by: Nathaniel Hourt <i at nathaniel.land>
> Closes: 
> https://lore.kernel.org/all/932979cb47c4fded7ac19216ca172504@nathaniel.land/
> Link: 
> https://lore.kernel.org/all/9c0038ed1494e9f293bf4faaf5e66ed8@nathaniel.land/ 
> # [1]
> Signed-off-by: Yao Zi <me at ziyao.cc>
> [Patch elided]

Happy New Year, at least for those of us in the west =)

Thank you, Yao Zi, for making this! I have done some initial testing, 
based on v2026.01-rc4, on my Mars board, and my results are mixed.

Right now, it seems to be a coin toss whether any given configuration 
yields a spl/u-boot-spl-nodtb.bin which is a multiple of 8 bytes, or 4 
bytes (but not 8). In the latter case, it doesn't work, even though _end 
points accurately to that 4-byte-aligned end-of-the-image position. In 
the former case, however, where the -nodtb.bin ends on an 8-byte 
boundary, it works great.

I have made some attempts to modify u-boot-spl.lds to add an ALIGN(8) 
directive before the _end symbol, and this makes the _end point to the 
next 8-byte boundary rather than a 4-byte (and not 8) boundary, but it 
doesn't cause the -nodtb.bin to be padded with those last 4 bytes. My 
attempts to pad it manually, concatenate the dtb, and run that through 
mkimage to get the final u-boot-spl.bin.normal.out image, have yielded 
no success. This failure surprises me; I was expecting that to work... I 
haven't had further inspiration on things to try. :-]

In conclusion, it seems to me that your patch is working fine, but I'm 
still having woes with DTB alignment. For now, I can get working builds 
by tweaking the config until it happens to give an 8-byte aligned _end 
pointer.

Oh, and sizes of u-boot-spl.bin.normal.out:
Without no-fpic patch: 152537
With no-fpic patch: 151749

—
Nathaniel


More information about the U-Boot mailing list