This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Handling of libgcc symbols in SH shared libraries


I recently had the dubious pleasure of back-porting the symbol
version scripts for SH5 linux to a gcc 3.2 variant.
The symbol version scripts can prevent symbols from being exported by
libgcc which shouldn't be exported.  However, that may not be enough to
make sure that shared libraries work properly.  The SH5 Linux resolver
potentially clobbers all call-clobbered registers that are not used
to pass integer arguments.  Hence, for SH5, no SFUNCs may use lazy linking.
Also, as others have found out before, there are some SH4 SFUNCs that
preserve r0 and/or r1, and therefore can't be called via a PLT.
However, reventing such symbols from being exported from libgcc
solves only part of the issue.  If these functions are used internally
in any shared library, they still get a GOT and PLT entry, and internal
calls might go through the PLT and thus clobber r0 and r1.
Moreover, these symbols are exported from any user-built library that
is made without mechanisms to fully control the set of exported symbols.

On the other hand, there are some library functions in libgcc that
are large enough that it might be useful to export them, even though
lazy linking is not possible.

So I did an audit of the lib1funcs.asm sfuncs.  These are the functions
where I came up with different settings than the 3.5 script:

  # __mulsi3 ! this is an SH1-only symbol.

  __sdivsi3     # must not use lazy linking
  __div_table   # data
  __GCC_shcompact_call_trampoline # must not use lazy linking
  __GCC_shcompact_incoming_args # must not use lazy linking
  __GCC_push_shmedia_regs       # must not use lazy linking
  __GCC_push_shmedia_regs_nofpu # must not use lazy linking
  __GCC_pop_shmedia_regs        # must not use lazy linking
  __GCC_pop_shmedia_regs_nofpu  # must not use lazy linking
 # The following symbols are for functions that are to small to warrant
 #  putting them in a shared library.
 # __sdvisi3_2
 # __sdivsi3_i4
 # __udivsi3
 # __udivsi3_i4
 # __set_fpscr
 # __GCC_shcompact_return_trampoline
 # __init_trampoline
 # __ic_invalidate # FIXME: for SH4, should we put this into libicache*_s.so,
 #      so that other shared libraries are cache-layout independent?
 # __GCC_nested_trampoline

FWIW __div_table is a new symbol for inlined integer division on SH5.

What do you think about the above changes?  I am assuming that the
SHcompact support functions are not used very often, so that it makes
sense to save on the size of the function body.

I am using a three-pronged approach to keep the sfunc symbols in check:

First is the version script, with changes as detailed above.

Second, I've defined in sh-protos.h:

enum sh_function_kind {
  /* A function with normal C ABI  */
  FUNCTION_ORDINARY,
  /* A special function that guarantees that some otherwise call-clobbered
     registers are not clobbered.  These can't go through the SH5 resolver,
     because it only saves argument passing registers.  */
  SFUNC_GOT,
  /* A special function that should be linked statically.  These are typically
     smaller or not much larger than a PLT entry.  */
  SFUNC_STATIC
};

And changed the parameters to function_symbol:

rtx
function_symbol (rtx target, const char *name, enum sh_function_kind kind)

So when TARGET is given, it computes the address into TARGET; otherwise,
it might allocate a register to place the address into when needed.

Third, in order to avoid leaking symbols that should never be exported
from user libraries, in lib1funcs.asm, I've defined a new macro HIDDEN_FUNC,
and used it for the functions in question.


For now, for SFUNC_GOT, I always make function_symbol generate
@GOT addressing, although for most functions that is not strictly
necessary: they could use @PLT addressing, as long as it is guaranteed
that the symbol is resolved at load time (or earlier with pre-linking).
Is there any good way to do this?  As I understand, the presence of a single
@GOT relocation would guarantee the timely resolution of the symbol,
but we don't want to put extra crap in the program so we have a place where
to put our relocation.
I think best would be some kind of assembler directive that I can place
in lib1funcs.asm that will force the symbol to be resolved at load time.

There are also some issues with the software floating point functions
that I am writing.  A number of these are drop-in replacements of
the fp-bit and newlib functions, except that they use less registers
(and are faster, obviously).  Leaving more registers unclobbered is
quite useful on the SH architecture, so the sfunc patterns give an
exact list of the registers that are clobbered.  That means
the new functions can be linked with old programs and lobraries, but
not vice versa.
For static libraries, we can just make up another name so that we are sure
that we will get the new functionality.
For shared libraries, the symbol versioning is the preferred method;
using a new name needlessly just pollutes the GOT.

However, these two approaches don't seem to mix very well.  Should I
rely on someone using a new compiler to compile the programs to link
against the new libgcc for static linking?

Or should I make the compiler generate new names without -fpic and the old
(implicitly versioned) names for -fpic, and use a special static library
when linking non-pic programs against a shared libgcc which equates the
value of the new symbols to the value of the old ones?
dynamically and statically, and for linking of sattically-


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]