On 17-Sep-07, at 7:20 PM, Sven Panne wrote:

On Monday 17 September 2007 13:48, Simon Marlow wrote:
When you generate a non-PIC object file, references to external functions will go through the PLT (a table of jump instructions, or it might be more
complicated than that and support lazy resolution).  So when you use
dlsym() you're getting the real address of the function, but the static binding is pointing to an entry in the PLT. I guess the -fPIC version is
doing the indirection at the point of the symbol reference.  [...]

[...]
The above results in the same behaviour, even though we reference data now, so
I guess a PLT or something like that can't be the reason:

"Something like that" is the reason. For non-PIC, ELF tries to keep up the illusion that there is no such thing as dynamic linking. In the X86_64 small code model, all addresses in the main program are expected to lie in the 32-bit range (+-2GB), so the assembler will generate a 32-bit reloc. The static linker will generate appropriate dynamic relocations in the final executable (see objdump -R a.out) to instruct the dynamic linker on how to keep up the no-dynamic-linking illusion. For code references, the static linker will allocate space for a PLT entry and emit a JUMP_SLOT relocation (which will be handled by the dynamic linker). For data references, the static linker will allocate space according to the .size directive for the symbol and emit a COPY relocation in the executable. The dynamic linker will then copy the initial value for the symbol from the dynamic library's data section, and make all references to the glutBitmap8By13 from libglut.so point to the new copy in the executable's data section rather than to the original in libglut.so's data section. I am puzzled as to why dlsym seems to return the symbol's original address, rather than the one allocated within the executable's data section. This behaviour seems broken to me, but it also happens on my 32bit linux box. Note that dlsym( NULL, "glutBitmap8By13" ) == &glutBitmap8By13.

Now we get a R_X86_64_GOTPCREL and things work as expected. Alas, our GHC
Linker can't handle such a relocation,

That shouldn't be a lot of work. The same relocation is already implemented for Darwin/x86_64.

[...] and somehow this has to work even in
the non-PIC case. What we currently do in x86_64_high_symbol for the
R_X86_64_32 relocation is completely wrong for data references, and this is
even mentioned in the comment.

I think that it is next to impossible to implement this correctly. If a symbol is copied into the executable's data section, the references from shared libraries to the symbol have to be updated to point to the new symbol as well. When loading a dynamic library, the system dynamic linker decides whether it needs to do this; unless we ship GHCi with a modified version of ld.so, it will do so only for symbols where a COPY relocation is present.

My recommendation would be implement the PIC relocations in the ELF/ X86_64 linker and then to require -fPIC for GHCi libs on that platform.

Hope that helps,

Wolfgang

_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to