Dynamic linking weirdness

Sven Panne sven.panne at aedion.de
Mon Sep 17 13:20:26 EDT 2007


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.  [...]

I thought about this as well, but things seem to be a bit more complicated. My 
example wasn't chosen very well, so let's repeat it with the *real* problem, 
which is a reference to data, not a reference to a funtion:

-------- strange.c -----------------------------------------
#include <dlfcn.h>
#include <stdio.h>

// cut-n-paste from freeglut, used in
// #define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13)

extern void* glutBitmap8By13;

int main(void) {
  void *handle = dlopen("libglut.so", RTLD_NOW | RTLD_GLOBAL);
  printf("%p    %p\n", dlsym(handle, "glutBitmap8By13"), &glutBitmap8By13);
  return dlclose(handle);
}
------------------------------------------------------------

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:

------------------------------------------------------------
panne at spock:~> gcc strange.c -ldl -lglut && ./a.out
0x2af96db92f00    0x601040
panne at spock:~> gcc strange.c -ldl -lglut -fpic && ./a.out
0x2b8fd4596f00    0x2b8fd4596f00
------------------------------------------------------------

Let's look at the code and the relocations, first for the non-PIC case:

------------------------------------------------------------
panne at spock:~> gcc -c strange.c
panne at spock:~> objdump --disassemble strange.o

strange.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 83 ec 10          	sub    $0x10,%rsp
   8:	be 02 01 00 00       	mov    $0x102,%esi
   d:	bf 00 00 00 00       	mov    $0x0,%edi
  12:	e8 00 00 00 00       	callq  17 <main+0x17>
  17:	48 89 45 f8          	mov    %rax,0xfffffffffffffff8(%rbp)
  1b:	48 8b 7d f8          	mov    0xfffffffffffffff8(%rbp),%rdi
  1f:	be 00 00 00 00       	mov    $0x0,%esi
  24:	e8 00 00 00 00       	callq  29 <main+0x29>
  29:	48 89 c6             	mov    %rax,%rsi
  2c:	ba 00 00 00 00       	mov    $0x0,%edx
  31:	bf 00 00 00 00       	mov    $0x0,%edi
  36:	b8 00 00 00 00       	mov    $0x0,%eax
  3b:	e8 00 00 00 00       	callq  40 <main+0x40>
  40:	48 8b 7d f8          	mov    0xfffffffffffffff8(%rbp),%rdi
  44:	e8 00 00 00 00       	callq  49 <main+0x49>
  49:	c9                   	leaveq 
  4a:	c3                   	retq   
panne at spock:~> readelf --relocs strange.o

Relocation section '.rela.text' at offset 0x670 contains 8 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + 
Addend
00000000000e  00050000000a R_X86_64_32       0000000000000000 .rodata + 0
000000000013  000a00000002 R_X86_64_PC32     0000000000000000 dlopen + 
fffffffffffffffc
000000000020  00050000000a R_X86_64_32       0000000000000000 .rodata + b
000000000025  000b00000002 R_X86_64_PC32     0000000000000000 dlsym + 
fffffffffffffffc
00000000002d  000c0000000a R_X86_64_32       0000000000000000 glutBitmap8By13 
+ 0
000000000032  00050000000a R_X86_64_32       0000000000000000 .rodata + 1b
00000000003c  000d00000002 R_X86_64_PC32     0000000000000000 printf + 
fffffffffffffffc
000000000045  000e00000002 R_X86_64_PC32     0000000000000000 dlclose + 
fffffffffffffffc

Relocation section '.rela.eh_frame' at offset 0x730 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + 
Addend
000000000020  00020000000a R_X86_64_32       0000000000000000 .text + 0
------------------------------------------------------------

Note that glutBitmap8By13 is referenced via a R_X86_64_32 relocation. The same 
again for PIC:

------------------------------------------------------------
panne at spock:~> gcc -c -fpic strange.c
panne at spock:~> objdump --disassemble strange.o

strange.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 83 ec 10          	sub    $0x10,%rsp
   8:	be 02 01 00 00       	mov    $0x102,%esi
   d:	48 8d 3d 00 00 00 00 	lea    0(%rip),%rdi        # 14 <main+0x14>
  14:	e8 00 00 00 00       	callq  19 <main+0x19>
  19:	48 89 45 f8          	mov    %rax,0xfffffffffffffff8(%rbp)
  1d:	48 8b 7d f8          	mov    0xfffffffffffffff8(%rbp),%rdi
  21:	48 8d 35 00 00 00 00 	lea    0(%rip),%rsi        # 28 <main+0x28>
  28:	e8 00 00 00 00       	callq  2d <main+0x2d>
  2d:	48 89 c6             	mov    %rax,%rsi
  30:	48 8b 15 00 00 00 00 	mov    0(%rip),%rdx        # 37 <main+0x37>
  37:	48 8d 3d 00 00 00 00 	lea    0(%rip),%rdi        # 3e <main+0x3e>
  3e:	b8 00 00 00 00       	mov    $0x0,%eax
  43:	e8 00 00 00 00       	callq  48 <main+0x48>
  48:	48 8b 7d f8          	mov    0xfffffffffffffff8(%rbp),%rdi
  4c:	e8 00 00 00 00       	callq  51 <main+0x51>
  51:	c9                   	leaveq 
  52:	c3                   	retq   
panne at spock:~> readelf --relocs strange.o

Relocation section '.rela.text' at offset 0x6a8 contains 8 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + 
Addend
000000000010  000500000002 R_X86_64_PC32     0000000000000000 .rodata + 
fffffffffffffffc
000000000015  000b00000004 R_X86_64_PLT32    0000000000000000 dlopen + 
fffffffffffffffc
000000000024  000500000002 R_X86_64_PC32     0000000000000000 .rodata + 7
000000000029  000c00000004 R_X86_64_PLT32    0000000000000000 dlsym + 
fffffffffffffffc
000000000033  000d00000009 R_X86_64_GOTPCREL 0000000000000000 glutBitmap8By13 
+ fffffffffffffffc
00000000003a  000500000002 R_X86_64_PC32     0000000000000000 .rodata + 17
000000000044  000e00000004 R_X86_64_PLT32    0000000000000000 printf + 
fffffffffffffffc
00000000004d  000f00000004 R_X86_64_PLT32    0000000000000000 dlclose + 
fffffffffffffffc

Relocation section '.rela.eh_frame' at offset 0x768 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + 
Addend
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
------------------------------------------------------------

Now we get a R_X86_64_GOTPCREL and things work as expected. Alas, our GHC 
Linker can't handle such a relocation, 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.

Still clueless,
   S.



More information about the Cvs-ghc mailing list