ldso dl-hash.c line 187

John Bowler jbowler at acm.org
Fri Sep 23 01:48:55 UTC 2005


It seems to me that a lot of this is very architecture dependent.  On ARM
(including thumb) I can see no reason for the dynamic loader to ever need to
'see' a PLT entry - i.e. so far as I can see if the dynamic symtab ever
contains a symbol corresponding to a PLT entry something is going wrong.
That is because on ARM the PLT is just a piece of code to call indirect via
a 32 bit (GOT) function pointer - if a PLT entry can be satisfied then any
other reference to the required function can also be satisfied in the same
way.  Consequently I don't see why ELF_RTYPE_CLASS_PLT needs any special
handling - so far as I can see there are no symtab entries for entries in
the PLT in an arm DLL.

The failure case on my system is as Joakim says.  To be exact libgcc_s.so.1
(from gcc 3.4.4 but I don't think that matters) implements a function
frame_dummy in crtstuff.c which is called from the libgcc .init.
frame_dummy itself calls a weak extern __register_frame_info and libgcc
provides a *strong* definition of this.

Everything is fine - my system boots, but dropbear and bash crash (boot uses
busybox ash, which works.)

The problem with bash is that it uses libncurses and libncurses.so.5.4 pulls
in frame_dummy in its own .init (I think) but does not provide a definition
of __register_frame_info.  Consequently libncurses.so.5.4 has a weak
SHN_UNDEF (undefined) symbol table entry for __register_frame_info within
it's dynamic symbol table.  With ld-uClibc-0.9.28.so this weak definition is
the first one encountered.

I've compiled the whole of everything (libgcc, libuClibc -
everything) -mthumb -mthumb-interwork.  The libncurses undefined symbol has
an st_value of 1 and is STT_FUNC.  The value returned by _dl_find_hash is
<load_base>+1, the libgcc .init crashes (eventually).

Three things have to go wrong - all three of them:

1) ld-uClibc doesn't implement weak symbols like glibc - even if glibc sees
the same (weak) symbol it will reject it in favour of the libgcc strong
version.
2) st_value==1, I think this is because of the binutils_2.16 change to
replace STT_ARM_TFUNC symbols with STT_FUNC (addr|1) (bottom bit set means a
thumb function target).  I guess it could also be because I damaged
something in all the patches I have...
3) I think the function has to be weak - because normally an *undefined*
function is not known to be thumb or arm...

I've actually fixed (1) as well as what I believe to be the basic problem (I
don't think _dl_find_hash should *ever* return the value from a *UND*
entry!)

From: Joakim Tjernlund [mailto:joakim.tjernlund at transmode.se]
>I think the above MAY produce different values for fun in symbol lookup.
>Can't recall the details, but I think it is arch dependant and/or possibly
>toolchain related.

Yep, that's the problem - I'm pretty sure what I have on ARM is correct,
but, well, MIPS... I just don't know.

>Maybe the st_value test should be:
>if (!(~1 & type_class) & ((sym->st_value == 0))

That's certainly more obscure ;-)  There are only two bits in there:

ELF_RTYPE_CLASS_PLT == 1
ELF_RTYPE_CLASS_COPY == 2 "the relocation should not be allowed to resolve
to one of the main executables symbols"

So that test is !ELF_RTYPE_CLASS_COPY && SHN_UNDEF...  That still doesn't
seem to make sense to me - I guess I don't see why _dl_find_hash need ever
return an entry from the symbol table which is marked "undefined".  Surely
those symbol table entries only exist as references from relocations to
record the name of a symbol which needs to be found?

John Bowler <jbowler at acm.org>





More information about the uClibc mailing list