Skip to content

Fix MIPS __start linker error with default relocation model#171

Open
walruscraft wants to merge 1 commit intosunfishcode:mainfrom
walruscraft:fix-mips-call16
Open

Fix MIPS __start linker error with default relocation model#171
walruscraft wants to merge 1 commit intosunfishcode:mainfrom
walruscraft:fix-mips-call16

Conversation

@walruscraft
Copy link
Contributor

Embarrassing follow-up to #170 - I introduced a bug in the MIPS startup code.

The la $t9, {entry} instruction in __start generates a CALL16 relocation when compiled with PIC (which is the default relocation model for mipsel-unknown-linux-gnu). CALL16 requires the target to be a global symbol, but entry is pub(super) so the linker rejects it:

mipsel-linux-gnu-ld: CALL16 reloc at 0x18 not against global symbol

I missed this because my test setup happened to use -C relocation-model=static, which avoids PIC entirely. So it linked fine on my end and I never saw the issue. Anyone using the default relocation model would hit this on their first MIPS build.

The fix is to use lui/addiu instead of la. These generate HI16/LO16 relocations which work with local symbols. Still loads the address into $t9 for PIC convention, just without going through the GOT.

Tested by building a real application (kv) for mipsel-unknown-linux-gnu without the relocation-model workaround. Links and runs correctly under QEMU.

Sorry about the mess.

Turns out `la $t9, {entry}` generates a CALL16 relocation in PIC
mode, and CALL16 needs the target to be a global symbol. Since
`entry` is pub(super), the linker rightfully complains. Swapped
to lui/addiu which use HI16/LO16 and don't care about visibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant