Issue #29 new

External linker doesn't work if gcc uses GNU ld

Aram Hăvărneanu
repo owner created an issue

Works fine if the gcc used uses Solaris ld:

6l -tmpdir obj -linkmode=external  -extld=/opt/gcc-4.8.1/bin/gcc -L /home/aram/go/alt/pkg/go -o prog73.xgbin obj/prog73.__go__.6
: oos:alt; prog73.xgbin
Hello.
: oos:alt; 6l -tmpdir obj -linkmode=external -L /home/aram/go/alt/pkg/go -o prog73.xgbin obj/prog73.__go__.6
: oos:alt; prog73.xgbin
SIGSEGV: segmentation violation
PC=0x0
signal arrived during cgo execution

runtime.cgocall(0x41e7f0, 0xfffffd7ffefafcd0)
    /home/aram/go/src/pkg/runtime/cgocall.c:149 +0x10b fp=0xfffffd7ffefafcc0
syscall.dlopen(0xc210000008, 0x1, 0xc210000008, 0x0)
    /home/aram/go/src/pkg/runtime/syscall_solaris.goc:141 +0x50 fp=0xfffffd7ffefafd08
syscall.LoadSo(0x42f5b0, 0x7, 0xc210039010, 0x0, 0x0)
    /home/aram/go/src/pkg/syscall/so_solaris.go:41 +0xa7 fp=0xfffffd7ffefafd98
syscall.(*LazySo).Load(0xc21001e000, 0x0, 0x0)
    /home/aram/go/src/pkg/syscall/so_solaris.go:163 +0xc2 fp=0xfffffd7ffefafdc8
syscall.(*LazyProc).Find(0xc210038e10, 0x0, 0x0)
    /home/aram/go/src/pkg/syscall/so_solaris.go:218 +0xbc fp=0xfffffd7ffefafe00
syscall.(*LazyProc).mustFind(0xc210038e10)
    /home/aram/go/src/pkg/syscall/so_solaris.go:236 +0x27 fp=0xfffffd7ffefafe28
syscall.(*LazyProc).Addr(0xc210038e10, 0x6)
    /home/aram/go/src/pkg/syscall/so_solaris.go:245 +0x27 fp=0xfffffd7ffefafe38
syscall.write(0x1, 0xc210000000, 0x7, 0x7, 0x8, ...)
    /home/aram/go/src/pkg/syscall/zsyscall_solaris_amd64.go:845 +0x72 fp=0xfffffd7ffefafea8
syscall.Write(0x1, 0xc210000000, 0x7, 0x7, 0xc210038f30, ...)
    /home/aram/go/src/pkg/syscall/syscall_unix.go:151 +0x5c fp=0xfffffd7ffefafee8
main.main()
    /home/aram/go/alt/prog73.go:8 +0x99 fp=0xfffffd7ffefaff48
runtime.main()
    /home/aram/go/src/pkg/runtime/proc.c:220 +0x11f fp=0xfffffd7ffefaffa0
runtime.goexit()
    /home/aram/go/src/pkg/runtime/proc.c:1394 fp=0xfffffd7ffefaffa8

rax     0x0
rbx     0x679720
rcx     0x0
rdx     0xc210000008
rdi     0xc210000008
rsi     0x1
rbp     0x679720
rsp     0xfffffd7fffdff018
r8      0x0
r9      0x406f58
r10     0x2
r11     0xfffffd7ffefafd08
r12     0x0
r13     0x0
r14     0x0
r15     0x0
rip     0x0
rflags  0x10282
cs      0x53
fs      0x0
gs      0x0
: oos:alt; 
: oos:alt; /opt/gcc-4.8.1/bin/gcc -v
Using built-in specs.
COLLECT_GCC=/opt/gcc-4.8.1/bin/gcc
COLLECT_LTO_WRAPPER=/opt/gcc-4.8.1/libexec/gcc/i386-pc-solaris2.11/4.8.1/lto-wrapper
Target: i386-pc-solaris2.11
Configured with: ./configure --prefix=/opt/gcc-4.8.1 --host i386-pc-solaris2.11 --build i386-pc-solaris2.11 --target i386-pc-solaris2.11 --with-boot-ldflags=-R/opt/gcc-4.8.1/lib --with-gmp=/opt/gcc-4.8.1 --with-mpfr=/opt/gcc-4.8.1 --with-mpc=/opt/gcc-4.8.1 --enable-languages=c,c++,fortran,lto --enable-ld=no --with-as=/usr/bin/gas --with-gnu-as --with-build-time-tools=/usr/gnu/i386-pc-solaris2.11/bin
Thread model: posix
gcc version 4.8.1 (GCC) 
: oos:alt; gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/gcc482/bin/../libexec/gcc/x86_64-sun-solaris2.11/4.8.2/lto-wrapper
Target: x86_64-sun-solaris2.11
Configured with: ../src/configure --prefix=/home/aram/gcc482 --build=x86_64-sun-solaris2.11 --host=x86_64-sun-solaris2.11 --disable-multilib --disable-shared --enable-threads=posix --enable-languages=c,c++,go --disable-libssp --disable-nls --with-gnu-as --with-gnu-ld --enable-ld --disable-gold
Thread model: posix
gcc version 4.8.2 (GCC) 
: oos:alt; 

The problem is that dlopen resolves to 0 with GNU ld:

oos:alt$ elfdump prog73.xgbin | grep dlopen
prog73.xgbin: .dynsym: index[1]: suspicious local symbol entry: _END_: lies within global symbol range (index >= 1)
prog73.xgbin: .dynsym: index[43]: suspicious local symbol entry: _START_: lies within global symbol range (index >= 1)
      [73]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D    7 ABS            dlopen
    [1845]  0x000000000041c800 0x000000000000007c  FUNC LOCL  D    0 .text          syscall.dlopen
    [2062]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D    0 ABS            dlopen@@SUNW_1.22
        36  [73]        dlopen
      [-2]  0x000000000066e360  0x0000000000000000  R_AMD64_GLOB_DATA         dlopen
  R_AMD64_GLOB_DATA                  0x66e360                  0  .rela.dyn      dlopen

Look at [73]. The reason it does this is because GNU ld looks inside libc.so for dlopen, because we #pragma dynimport it from there. Inside libc.so it finds

oos:alt$ elfdump /lib/amd64/libc.so | grep dlopen
    [1051]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D   16 ABS            dlopen
    [1776]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D   48 ABS            _dlopen
    [3462]  0x0000000000124940 0x0000000000000004  OBJT LOCL  D    0 .rodata        dlopen_version
    [3463]  0x0000000000124944 0x000000000000000d  OBJT LOCL  D    0 .rodata        dlopen_format
    [9303]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D    0 ABS            dlopen
   [10028]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D    0 ABS            _dlopen
            [1051]      dlopen
            [1776]      _dlopen
       [8]  0x0000000000188040  0x0000000000071a76  R_AMD64_JUMP_SLOT         dlopen
    [1051]  F            [0] /usr/lib/amd64/ld.so.1   dlopen
    [1776]  F            [0] /usr/lib/amd64/ld.so.1   _dlopen
  R_AMD64_JUMP_SLOT                  0x188040                  0  .rela.plt      dlopen

That's because dlopen is actually implemented in ld.so.1. We can't import dlopen directly from ld.so.1 (why?). Solaris ld works fine. The binary linked with Solaris ld:

oos:alt$ elfdump prog73.xgbin | grep dlopen
     [488]  0x0000000000423720 0x000000000000007c  FUNC LOCL  D    0 .text          syscall.dlopen
      [36]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D    3 UNDEF          dlopen
    [1854]  0x0000000000423720 0x000000000000007c  FUNC LOCL  D    0 .text          syscall.dlopen
    [2035]  0x0000000000000000 0x0000000000000000  FUNC GLOB  D    0 UNDEF          dlopen
     [488]  0x0000000000423720 0x000000000000007c  FUNC LOCL  D    0 .text          syscall.dlopen
        31  [36]        dlopen
      [39]  0x00000000004850f0  0x0000000000000000  R_AMD64_GLOB_DATA         dlopen
  R_AMD64_GLOB_DATA                  0x4850f0                  0  .SUNW_reloc    dlopen

A look at the intermediary ELF .o object generated by 6l when external linking:

oos:alt$ elfdump obj/prog73.o | grep dlopen
    [1792]  0x000000000001b1c0 0x000000000000007c  FUNC LOCL  D    0 .text          syscall.dlopen
    [1945]  0x0000000000000000 0x0000000000000000  NOTY GLOB  D    0 UNDEF          dlopen
  R_AMD64_GOTPCREL                    0x1b1dc 0xfffffffffffffffc  .rela.text     dlopen
  R_AMD64_64                           0xd68a                  0  .rela.gosymtab syscall.dlopen
  R_AMD64_64                           0x1dc0                  0  .rela.gopclnta syscall.dlopen
  R_AMD64_64                          0x156e0                  0  .rela.gopclnta syscall.dlopen
obj/prog73.o: .rela.noptrdata: zero size or zero entry size information
  R_AMD64_64                          0x17df2                  0  .rela.debug_in syscall.dlopen
  R_AMD64_64                          0x17dfa               0x7c  .rela.debug_in syscall.dlopen
  R_AMD64_64                           0x47d8                  0  .rela.debug_fr syscall.dlopen

Comments (2)

  1. Log in to comment