GNU linker and Function stubs on mips.

Ian Lance Taylor ian@zembu.com
Sat Feb 26 18:42:00 GMT 2000


   Date: Sat, 26 Feb 2000 19:25:43 -0700
   From: Koundinya K <knk@dde.dk>

   I have been compiling a couple of things with the newly built gcc.
   Sometimes some programs fail citing "procedure referencing errors from
   the dynanic linker". But the programs work when the LD_BIND_NOW
   environment flag is turned on ( The LD_BIND_NOW environment variable can
   change the behavior of dynamic linking. When turned on, the dynamic
   linker evalutes all symbol table entries of the type STT_FUNC, replacing
   their stub address in the GOT with the actual addresses of the
   referenced function ).

This sounds like the linker is not initializing the GOT correctly.
When LD_BIND_NOW is defined, the dynamic linker will initialize all
the GOT entries when the program starts.  When LD_BIND_NOW is not
defined, the GOT entries must contain a stub address or a quickstart
value.

However, according to the MIPS ELF ABI, there is an exception.  If the
program takes the address of a function, then the GOT entry should
contain either 0 or a quickstart value.

Perhaps the linker is incorrectly using a stub address for a function
whose address is taken.

   Undefined symbols of the type STT_FUN, which have been referenced by
   R_MIPS_CALL16 and R_MIPS_26 relocations can contain on zero values in
   their st_value field, denoting the stub addresses used for lazy
   evaluation for this symbol. The run time linker uses this to reset the
   GOT entry for this external to its stub address when unlinking a shared
   object. All othe undefined symbols must contain zero in their st_value
   fields.

   I have takes several object files having all possible relocs and tried
   to link with the GNU linker. It sets the stubs for all symbols ,
   irrespective of the relocs. So it looks like the default behavior of the
   GNU linker is to set up stubs for lazy binding.

   I tried to figure out to see how the GNU linker checks if a particular
   symbol requires a stub or not. But looks like no where such checks are
   done. For all the symbols stubs are generated.  In particular I was
   looking through where the st_value for a symbol is assigned at first and
   is there any sort of test done before this is assigned. But got no clues
   anywhere.

So, you have come to the same conclusion.

The code which set an undefined dynamic symbol to hold a stub address
is in _bfd_mips_elf_adjust_dynamic_symbol.  That sets the value of the
symbol.  The stub code is created in
_bfd_mips_elf_finish_dynamic_symbol.

It is also _bfd_mips_elf_finish_dynamic_symbol which sets the final
value which is stored in the file.  Right now it appears to always set
the value of the symbol to the stub address.

An undefined dynamic symbol which is referenced by a non-call
relocation should not have a stub, and the value should be set to
zero.  The check_relocs function needs to check for this case and set
some sort of flag.  adjust_dynamic_symbol needs to check the flag, and
avoid allocating a stub in that case.  It also needs to set the symbol
value to something, but offhand I'm not sure what that something is.
finish_dynamic_symbol needs to check the flag, and set the value to
zero in that case.

Ian


More information about the Binutils mailing list