Repository: go
Issue: runtime,cmd/compile: -buildmode=c-shared and dlopen-ing a shared library
Labels: NeedsInvestigation,early-in-cycle,compiler/runtime

consider the following `GOPATH`:

```
sh> tree .
.
├── mylib.so
└── src
    ├── main.go
    ├── my-cmd
    │   └── main.go
    ├── pkg1
    │   └── pkg.go
    └── pkg2
        └── pkg.go

5 directories, 6 files
```

with:

``` go
// src/pkg1
package pkg1

import "fmt"

var Int = 0
var Map = make(map[string]int)

func init() {
    fmt.Printf("pkg1.Int: %p\n", &Int)
    fmt.Printf("pkg1.Map: %p\n", &Map)
}
```

``` go
// src/pkg2
package pkg2

import "C"
import (
    "fmt"
    "pkg1"
)

//export Load
func Load() {
    fmt.Printf("pkg2.Load...\n")
}

func init() {
    fmt.Printf(">>> pkg2: pkg1.Int: %p\n", &pkg1.Int)
    fmt.Printf(">>> pkg2: pkg1.Map: %p\n", &pkg1.Map)
}
```

``` go
// src/my-cmd/main.go
package main

import "C"

import _ "pkg2"

func main() {}
```

and:

``` go
// src/main.go
package main

// #include <dlfcn.h>
// #cgo LDFLAGS: -ldl
// #include <stdlib.h>
// #include <stdio.h>
//
// void loadPlugin(void *lib) {
//   void (*f)(void) = NULL;
//   char *error = NULL;
//   f = (void (*)(void))(dlsym(lib, "Load"));
//   error = dlerror();
//   if (f == NULL || error != NULL) {
//      fprintf(stderr, "ERROR no such symbol!!! (%s)\n", error);
//      return;
//   }
//   fprintf(stderr, "symbol 'Load' loaded...\n");
//   (*f)();
// }
import "C"

import (
    "fmt"
    "log"
    "pkg1"
    "unsafe"
)

func main() {
    fmt.Printf("main.pkg1.Int: %p\n", &pkg1.Int)
    fmt.Printf("main.pkg1.Map: %p\n", &pkg1.Map)

    fmt.Printf("loading DLL...\n")
    cstr := C.CString("./mylib.so")
    defer C.free(unsafe.Pointer(cstr))
    h := C.dlopen(cstr, C.RTLD_NOW)
    if h == nil {
        log.Fatalf("error loading %s\n", C.GoString(cstr))
    }
    defer C.dlclose(h)

    fmt.Printf("loading plugin...\n")
    C.loadPlugin(h)
    fmt.Printf("loading plugin... [done]\n")

}
```

running the following command, gives:

```
sh> go build -buildmode=c-shared -o mylib.so ./src/my-cmd && go run ./src/main.go 
pkg1.Int: 0x728c48
pkg1.Map: 0x70e1e0
main.pkg1.Int: 0x728c48
main.pkg1.Map: 0x70e1e0
loading DLL...
loading plugin...
symbol 'Load' loaded...
pkg1.Int: 0x7f925f7f9a48
pkg1.Map: 0x7f925f7df038
>>> pkg2: pkg1.Int: 0x7f925f7f9a48
>>> pkg2: pkg1.Map: 0x7f925f7df038
pkg2.Load...
loading plugin... [done]
```

ie: the addresses of `pkg1.Int` and `pkg1.Map` are not the same when inspected from the `go.main()` or `pkg1.init` and when inspected from the dynamically loaded `mylib.so` shared library.
also, `pkg1.init()` is run twice.

here is my environment:

```
sh> go version
go version go1.7 linux/amd64

sh> go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/binet/work/igo/src/github.com/go-interpreter/example/cshared-bug"
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build549233304=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
```

from my reading of https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit# this shouldn't happen, even when using the `c-shared` buildmode instead of the `plugin` buildmode.

@ianlancetaylor @crawshaw : right ?