reed kotler <rkot...@mips.com> writes: > Consider the following function: > void floatvf(float x) { > } > > The compiled with: > mips-linux-gnu-gcc -mips16 mips16_fpcall.c -S -fPIC -EL > > > The stub looks like this: > > __fn_stub_floatvf: > .set noreorder > .cpload $25 > .set reorder > .reloc 0,R_MIPS_NONE,floatvf > la $25,__fn_local_floatvf > mfc1 $4,$f12 > jr $25 > .end __fn_stub_floatvf > __fn_local_floatvf = floatvf > > > What is the purpose of this .reloc and this __fn_local_floatvf = floatvf ?
__fn_local_floatvf = floatvf creates a local symbol alias for a locally-defined global function. The idea is that: la $25, __fn_local_floatvf then uses a page GOT access, ensuring the stub does not force the creation of stub-specific GOT entries. The difficulty with: la $25, floatvf is that it would appear to the assembler and linker as a global GOT reference (because floatvf is global). However, the relocation actually resolves to the MIPS16 function, whereas other non-stub instances of: la $25, floatvf should resolve to the stub. So we would have the strange (and currently unsupported) situation that the same symbol could need two GOT entries, one local entry pointing to the MIPS16 address and one global entry containing the canonical function address (i.e. the stub). Or, if floatvf is hidden, we could end up with two different local GOT entries for the same symbol. The .reloc ensures that the first relocation in the stub section points to the stubbed function (rather than its alias). That's how the linker works out which function is being stubbed. Thanks, Richard