Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/ld: corrupted binaries with -linkmode=external #7234

Closed
dvyukov opened this issue Jan 29, 2014 · 8 comments
Closed

cmd/ld: corrupted binaries with -linkmode=external #7234

dvyukov opened this issue Jan 29, 2014 · 8 comments
Milestone

Comments

@dvyukov
Copy link
Member

dvyukov commented Jan 29, 2014

parent: 18972:d92b32d188ec tip, linux/amd64

$ go run -ldflags="-linkmode=external" test.go
want runtime/cgo:true, got �jz�u�:true

test.go is:
=============================
package main
import "fmt"
var cgoExclude = map[string]bool{
    "runtime/cgo": true,
}
func main() {
    for k, v := range cgoExclude {
        if k != "runtime/cgo" || v != true {
            fmt.Printf("want runtime/cgo:true, got %v:%v\n", k, v)
        }
    }
}
=============================
@dvyukov
Copy link
Member Author

dvyukov commented Jan 29, 2014

Comment 1:

I've discovered this while doing race-related changes here:
https://golang.org/cl/55100044/
It makes cmd/go broken. The strange thing is that currently -race uses external linking
via cgo, and everything works...

@ianlancetaylor
Copy link
Contributor

Comment 2:

It works fine as long as you change the string so that it is not exactly "runtime/cgo".
Perhaps you could use a different string.

@ianlancetaylor
Copy link
Contributor

Comment 3:

The problem is this call in ld/lib.c:
        // Provided by the code that imports the package.
        // Since we are simulating the import, we have to provide this string.
        addstrdata("go.string.\"runtime/cgo\"", "runtime/cgo");
That defines a symbol go.string."runtime/cgo".  When the compiler sees the string
constant, it defines the same symbol to hold the string.  The compiler builds the symbol
as a string header followed immediately by the string data, and it builds a relocation
that knows that layout: a relocation to the symbol plus the size of the string header
(datastring in gobj.c).  The linker uses a different layout in addstrdata--it puts the
string header in one section and the string data in a different section.  But the symbol
name go.string."runtime/cgo" is the same in both cases, and it has to be the same or we
get other linker confusion.
So it fails when using external linking because we get a reference to an offset from the
string symbol expecting to find the string data there, but it isn't there.
I haven't quite worked out why works when using internal linking.

@ianlancetaylor
Copy link
Contributor

Comment 4:

Status changed to Started.

@ianlancetaylor
Copy link
Contributor

Comment 5:

Actually, it's obvious why it works when using internal linking: the linker only adds
the string constant when using external linking.

@ianlancetaylor
Copy link
Contributor

Comment 6:

https://golang.org/cl/58410043

@dvyukov
Copy link
Member Author

dvyukov commented Jan 30, 2014

Comment 7:

>Perhaps you could use a different string.
I can't. It happens in cmd/go, and it needs special handling of "runtime/cgo".

@ianlancetaylor
Copy link
Contributor

Comment 8:

This issue was closed by revision 1683dab.

Status changed to Fixed.

@rsc rsc added this to the Go1.3 milestone Apr 14, 2015
@rsc rsc removed the release-go1.3 label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 25, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants