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: Link bug on darwin arm64 #53495

Open
578559967 opened this issue Jun 22, 2022 · 11 comments
Open

cmd/link: Link bug on darwin arm64 #53495

578559967 opened this issue Jun 22, 2022 · 11 comments
Labels
NeedsInvestigation WaitingForInfo
Milestone

Comments

@578559967
Copy link

@578559967 578559967 commented Jun 22, 2022

What version of Go are you using (go version)?

$ go version
go version go1.18.3 darwin/arm64

Does this issue reproduce with the latest release?

Yes, it can reproduce with 1.17.5、1.17.6、1.17.10、1.18.1、1.18.2、1.18.3.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/r/Library/Caches/go-build"
GOENV="/Users/r/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/r/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/r/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/Users/r/workspace/testgo/go1.18.3/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/r/workspace/testgo/go1.18.3/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.3"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/r/workspace/testcode/testassert/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/9k/p8mmy7xs2p71m74wg554rsvw0000gn/T/go-build954074863=/tmp/go-build -gno-record-gcc-switches -fno-common"
GOROOT/bin/go version: go version go1.18.3 darwin/arm64
GOROOT/bin/go tool compile -V: compile version go1.18.3
uname -v: Darwin Kernel Version 21.2.0: Sun Nov 28 20:28:41 PST 2021; root:xnu-8019.61.5~1/RELEASE_ARM64_T6000
ProductName:	macOS
ProductVersion:	12.1
BuildVersion:	21C52
lldb --version: lldb-1316.0.9.46
Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12)

What did you do?

test_1.18.go.tar.gz
Download the attachment, then run it with go 1.18 or 1.18.1 or 1.18.2 or 1.18.3.

tar zxvf ../test_1.18.go.tar.gz
go run ./test_1.18.go

What did you expect to see?

Expect to output:

ok

What did you see instead?

Output:

Field name not right:  92292 rstuvwxyz91869a91870abcdefghijklmnopqrstuvwxyz91870a91871abcdefghijklmnopqrstuvwxyz91871a91872abcdefghij

For lower versions of go, use these attachments instead:
test_1.17.10.go.tar.gz
test_1.17.6.go.tar.gz

This bug only happens on mac with arm64. Other platforms work fine.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jun 22, 2022

CC @randall77 @cherrymui

@ianlancetaylor ianlancetaylor added the NeedsInvestigation label Jun 22, 2022
@ianlancetaylor ianlancetaylor added this to the Go1.20 milestone Jun 22, 2022
@mengzhuo
Copy link
Contributor

@mengzhuo mengzhuo commented Jun 22, 2022

cc @golang/arm

@erifan
Copy link
Contributor

@erifan erifan commented Jun 22, 2022

I can't reproduce the problem with the latest code, but with go1.18.3. Maybe this problem has been fixed after go1.18.3 ?

$ go version
go version devel go1.19-527ace0ffa Sat Jun 18 00:48:50 2022 +0000 darwin/arm64

@578559967
Copy link
Author

@578559967 578559967 commented Jun 22, 2022

More environment info:

$ ld -v
@(#)PROGRAM:ld  PROJECT:ld64-764
BUILD 11:22:55 Apr 28 2022
configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em
LTO support using: LLVM version 13.1.6, (clang-1316.0.21.2.5) (static support for 28, runtime is 28)
TAPI support using: Apple TAPI version 13.1.6 (tapi-1316.0.7.3)

@578559967
Copy link
Author

@578559967 578559967 commented Jun 22, 2022

I can't reproduce the problem with the latest code, but with go1.18.3. Maybe this problem has been fixed after go1.18.3 ?

$ go version go version devel go1.19-527ace0ffa Sat Jun 18 00:48:50 2022 +0000 darwin/arm64

For 1.19, use this attachment:
test_1.19.go.tar.gz
It will output:

Field name not right:  92184 rstuvwxyz91761a91762abcdefghijklmnopqrstuvwxyz91762a91763abcdefghijklmnopqrstuvwxyz91763a91764abcdefghij

@578559967
Copy link
Author

@578559967 578559967 commented Jun 22, 2022

Why I think this is a link bug, my analysis is as follows:

  1. The direct reason is that the types info saved in the binary gets mistakes:
    The field 'name' in type structField of reflect/type.go points to wrong address.
        type structField struct {
            name        name    // This field got wrong
            typ         *rtype
            offsetEmbed uintptr 
        }
        type name struct {
            bytes *byte    // this field points to wrong address
        }
  1. Then I debug the program and get the address of name which store the wrong address.
    As the address is an virtual address, I did some calculation and converted the address to an address in the executable binary which is 0x1008ac200.

  2. Then I use objdump --full-contents --macho ./test_1.18 to view the binary. The value at 0x1008ac200 is 4ebf4200 00001000.

  3. Then I convert the value to an address 0x10042bf4e, and find values start at the address in the binary. I got the chars which is the same as the output of the program.
    截屏2022-06-19 22 18 34

  4. The test code uses cgo.

  5. The go linker links all go code to an object file named go.o

  6. Then the go linker calls the host linker to link go.o and other object files to the final binary.

  7. I check the go.o and use the value nearby that address to locate the address in go.o. I found that the value stored in that address is right.

  8. So I think it may be a bug of the host linker which is /usr/bin/ld provided by apple. The linker does the relocation job wrong at that address.

  9. I modify the go linker to use lld provided by llvm to do the host link job. And the program works well and print "ok".

  10. I objdump the new binary and found that the value at that address is right.

  11. The address which stores the wrong value has an offset of 0x800000 from the __rodata section. This may be a special address handled in the host linker.

@erifan
Copy link
Contributor

@erifan erifan commented Jun 22, 2022

I can't reproduce the problem with the latest code, but with go1.18.3. Maybe this problem has been fixed after go1.18.3 ?
$ go version go version devel go1.19-527ace0ffa Sat Jun 18 00:48:50 2022 +0000 darwin/arm64

For 1.19, use this attachment: test_1.19.go.tar.gz It will output:

Field name not right:  92184 rstuvwxyz91761a91762abcdefghijklmnopqrstuvwxyz91762a91763abcdefghijklmnopqrstuvwxyz91763a91764abcdefghij

This cannot be reproduced either.

@578559967
Copy link
Author

@578559967 578559967 commented Jun 22, 2022

I can't reproduce the problem with the latest code, but with go1.18.3. Maybe this problem has been fixed after go1.18.3 ?
$ go version go version devel go1.19-527ace0ffa Sat Jun 18 00:48:50 2022 +0000 darwin/arm64

For 1.19, use this attachment: test_1.19.go.tar.gz It will output:

Field name not right:  92184 rstuvwxyz91761a91762abcdefghijklmnopqrstuvwxyz91762a91763abcdefghijklmnopqrstuvwxyz91763a91764abcdefghij

This cannot be reproduced either.

Do you use mac with arm64?
What's your default ld version?

@erifan
Copy link
Contributor

@erifan erifan commented Jun 22, 2022

Do you use mac with arm64?

Yes

What's your default ld version?

$ ld -v
@(#)PROGRAM:ld PROJECT:ld64-609.8
BUILD 15:07:50 Dec 18 2020
configured to support archs: armv6 armv7 armv7s arm64 arm64e arm64_32 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em
LTO support using: LLVM version 12.0.0, (clang-1200.0.32.29) (static support for 27, runtime is 27)
TAPI support using: Apple TAPI version 12.0.0 (tapi-1200.0.23.5)

@cherrymui
Copy link
Member

@cherrymui cherrymui commented Jun 22, 2022

I cannot reproduce either with Go tip (be0b2a3) and test_1.19.go.tar.gz, with both ld64-816 and ld64-764.

@cherrymui cherrymui added the WaitingForInfo label Jun 22, 2022
@578559967
Copy link
Author

@578559967 578559967 commented Jun 23, 2022

1.19beta1 can reproduce with test_1.19.go.tar.gz.

Maybe this commit has fixed the bug somehow: https://go.dev/cl/411912
I don't know the root cause and not sure whether this commit fixed it completely.
If it really fixed the bug, I think this commit should be picked back to 1.18 and 1.17.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation WaitingForInfo
Projects
None yet
Development

No branches or pull requests

5 participants