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/link: linker produces invalid binaries on FreeBSD when cgo is used and linkflag -X passed twice #23273

Closed
knz opened this issue Dec 28, 2017 · 4 comments

Comments

Projects
None yet
5 participants
@knz
Copy link

commented Dec 28, 2017

tl;dr: generated binary segfaults on init if both 1) uses cgo and 2) -X is passed twice in -ldflags

  • What version of Go are you using (go version)?
go version go1.9.2 freebsd/amd64
  • Does this issue reproduce with the latest release?

yes

  • What operating system and processor architecture are you using (go env)?
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="freebsd"
GOOS="freebsd"
GOPATH="/data/home/kena/src/go"
GORACE=""
GOROOT="/data/home/kena/src/go1.9.2"
GOTOOLDIR="/data/home/kena/src/go1.9.2/pkg/tool/freebsd_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build623559632=/tmp/go-build -gno-record-gcc-switches"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
  • What did you do?

Using the following file test.go:

package main

import "fmt"

// #include <stdio.h>
// int x = 42;
import "C"

var test string

func init() {
        fmt.Println(test, C.x)
}

func main() {
        fmt.Println("world")
}

I ran:

go build -x -ldflags='-X main.test=hello -X main.test=hello'
./test
  • What did you expect to see?
hello 42
world
  • What did you see instead?
unexpected fault address 0x98b270
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0x98b270 pc=0x450982]

goroutine 1 [running, locked to thread]:
runtime.throw(0x4b4dae, 0x5)
        /data/home/kena/src/go1.9.2/src/runtime/panic.go:605 +0x95 fp=0xc42005bbf8 sp=0xc42005bbd8 pc=0x426c95
runtime.sigpanic()
        /data/home/kena/src/go1.9.2/src/runtime/signal_unix.go:374 +0x227 fp=0xc42005bc48 sp=0xc42005bbf8 pc=0x439b97
runtime.memmove(0xc42008c038, 0x98b270, 0x5)
        /data/home/kena/src/go1.9.2/src/runtime/memmove_amd64.s:161 +0x122 fp=0xc42005bc50 sp=0xc42005bc48 pc=0x450982
fmt.(*buffer).WriteString(...)
        /data/home/kena/src/go1.9.2/src/fmt/print.go:82
fmt.(*fmt).padString(0xc4200b0040, 0x98b270, 0x5)
        /data/home/kena/src/go1.9.2/src/fmt/format.go:110 +0x9c fp=0xc42005bcd8 sp=0xc42005bc50 pc=0x47ce2c
fmt.(*fmt).fmt_s(0xc4200b0040, 0x98b270, 0x5)
        /data/home/kena/src/go1.9.2/src/fmt/format.go:328 +0x61 fp=0xc42005bd10 sp=0xc42005bcd8 pc=0x47dbd1
fmt.(*pp).fmtString(0xc4200b0000, 0x98b270, 0x5, 0x76)
        /data/home/kena/src/go1.9.2/src/fmt/print.go:430 +0x11f fp=0xc42005bd48 sp=0xc42005bd10 pc=0x480d6f
fmt.(*pp).printArg(0xc4200b0000, 0x4965e0, 0xc4200841b0, 0x76)
        /data/home/kena/src/go1.9.2/src/fmt/print.go:664 +0x7b5 fp=0xc42005bdc8 sp=0xc42005bd48 pc=0x4830c5
fmt.(*pp).doPrintln(0xc4200b0000, 0xc42005bf40, 0x2, 0x2)
        /data/home/kena/src/go1.9.2/src/fmt/print.go:1136 +0x56 fp=0xc42005be58 sp=0xc42005bdc8 pc=0x486166
fmt.Fprintln(0x71c800, 0xc420094008, 0xc42005bf40, 0x2, 0x2, 0x4960a0, 0xc420084100, 0xc42008c030)
        /data/home/kena/src/go1.9.2/src/fmt/print.go:247 +0x58 fp=0xc42005bec0 sp=0xc42005be58 pc=0x47f568
fmt.Println(0xc42005bf40, 0x2, 0x2, 0xc42008c030, 0xc42005bf60, 0x486478)
        /data/home/kena/src/go1.9.2/src/fmt/print.go:257 +0x57 fp=0xc42005bf10 sp=0xc42005bec0 pc=0x47f667
main.init.0()
        /data/home/kena/src/go/src/github.com/cockroachdb/cockroach/t/test.go:12 +0xc7 fp=0xc42005bf70 sp=0xc42005bf10 pc=0x4866e7
main.init()
        <autogenerated>:1 +0x4e fp=0xc42005bf80 sp=0xc42005bf70 pc=0x4867ce
runtime.main()
        /data/home/kena/src/go1.9.2/src/runtime/proc.go:173 +0x1c5 fp=0xc42005bfe0 sp=0xc42005bf80 pc=0x428325
runtime.goexit()
        /data/home/kena/src/go1.9.2/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42005bfe8 sp=0xc42005bfe0 pc=0x4500b1

If I either remove the cgo usage in test.go or remove the duplicate -X flag in the link flags, the problem goes away and the program runs successfully.

@paulzhol

This comment has been minimized.

Copy link
Member

commented Dec 30, 2017

This reproduces on linux amd64 with go 1.9.2 as well, here's a minimal version:

package main

// int x = 42;
import "C"

var test string

func main() {
        println(test)
}

The relevant code is this, I think:

func addstrdata(ctxt *Link, name string, value string) {
p := fmt.Sprintf("%s.str", name)
sp := ctxt.Syms.Lookup(p, 0)
Addstring(sp, value)
sp.Type = SRODATA
s := ctxt.Syms.Lookup(name, 0)
s.Size = 0
s.Attr |= AttrDuplicateOK
reachable := s.Attr.Reachable()
Addaddr(ctxt, s, sp)
adduintxx(ctxt, s, uint64(len(value)), SysArch.PtrSize)
// addstring, addaddr, etc., mark the symbols as reachable.
// In this case that is not necessarily true, so stick to what
// we know before entering this function.
s.Attr.Set(AttrReachable, reachable)
strdata = append(strdata, s)
sp.Attr.Set(AttrReachable, reachable)
}

When called multiple times with the same symbol name, the second call will append the string value to main.test.str, as can be seen from objdump.

objdump -t test.ok (single -X arg):

000000000047cee0 l     O .rodata        0000000000000006              main.test.str
00000000006af170 l     O .data  0000000000000010              main.test
0

objdump -t test (two -X args):

000000000047d178 l     O .rodata        000000000000000c              main.test.str
00000000006af170 l     O .data  0000000000000010              main.test

Also the recorded address of main.test is made to no longer point to main.test.str, but to some inaccessible address, which triggers the panic.

@gopherbot

This comment has been minimized.

Copy link

commented Jan 1, 2018

Change https://golang.org/cl/85835 mentions this issue: cmd/link: make addstrdata overwrite the same symbol instead of appending

@rsc

This comment has been minimized.

Copy link
Contributor

commented Jan 9, 2018

golang.org/cl/86915 will fix this.

@gopherbot

This comment has been minimized.

Copy link

commented Jan 9, 2018

Change https://golang.org/cl/86915 mentions this issue: cmd/link: apply -X options after loading symbols

@gopherbot gopherbot closed this in 28639df Jan 9, 2018

@golang golang locked and limited conversation to collaborators Jan 9, 2019

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.