Skip to content

Link failure with GCC -O2/-O3: "relocation truncated to fit: R_X86_64_TPOFF32 against xoshiro_s" (4.17.0) #600

Description

@Schuemi

Linking the 4.17.0 amalgamation into an executable fails on x86_64 Linux
with GCC at -O2/-O3 (GCC 13.3, binutils 2.42, Ubuntu 24.04):

sqlite3.c:(.text+0x294eb): relocation truncated to fit: R_X86_64_TPOFF32 against `xoshiro_s'

-O0 links fine. LTO is not required — openSUSE hit the same symbol with LTO
and disabled LTO as a workaround
(https://www.mail-archive.com/commit@lists.opensuse.org/msg143397.html),
but plain -O2 already triggers it.

Reproduce:

./configure && make sqlite3.c
gcc -O2 -c sqlite3.c -DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLITE_THREADSAFE=1 \
  -DSQLITE_EXTRA_INIT=sqlcipher_extra_init -DSQLITE_EXTRA_SHUTDOWN=sqlcipher_extra_shutdown
echo 'extern unsigned long xoshiro_next(void); int main(void){return (int)xoshiro_next();}' > main.c
gcc -O2 main.c sqlite3.o -lcrypto -lpthread -ldl -lm   # link fails

Root cause: the thread-local xoshiro state is seeded from its own address
(splitmix64(&xoshiro_s)). GCC constant-folds the seeding and merges the
64-bit golden-ratio constants (k * 0x9e3779b97f4a7c15) into the addend of
the TLS relocation, which cannot be encoded in the signed 32-bit
R_X86_64_TPOFF32 field:

$ readelf -r sqlite3.o | grep xoshiro_s
... R_X86_64_TPOFF32  xoshiro_s + 3c6ef372fe94f82a    (= 2 * 0x9e3779b97f4a7c15 mod 2^64)

Workaround: compile the amalgamation with -fPIC -ftls-model=initial-exec
(GOT-based TLS; -ftls-model alone is not enough — without -fPIC GCC
downgrades back to local-exec). A possible upstream fix is laundering the
seed address so the optimizer cannot fold arithmetic into the symbol
reference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions