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/go: -buildmode=pie does not build correct PIE binaries for ppc64le #28531

Open
laboger opened this Issue Nov 1, 2018 · 5 comments

Comments

Projects
None yet
2 participants
@laboger
Contributor

laboger commented Nov 1, 2018

Please answer these questions before submitting your issue. Thanks!

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

latest

Does this issue reproduce with the latest release?

yes

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

ppc64le

What did you do?

Tried to run binaries built as PIE.

What did you expect to see?

Correct execution

What did you see instead?

Error messages like this:
./main.exe: error while loading shared libraries: R_PPC64_ADDR16_HA re10f2f8fa4 for symbol `' out of range
2018/09/05 09:53:14 Failed: exit status 127
on newer distros.

The problem is related to issues #27510 and #21954 and can still be reproduced on many distros by passing -pie as a linker option.

The solution to the above issues was to use -buildmode=pie but that doesn't correct all problems. When linking a program with -pie on ppc64le then all code should be built as PIC. When some code is not PIC there could be relocations created like R_PPC64_ADDR16_HA which will fail with the above error if the relocated addresses are too big. On some distros/kernels we get lucky and no failures occur if the addresses stay small enough but on newer distros the runtime relocation errors can occur.

When using -buildmode=pie the -shared option is set to force the compiles to be built as PIC but it still links in stdlib which was not built as PIC. Likewise any library linked in should be PIC. When all the code is has been built as PIC then this relocation would not be generated and the PIE should work.

One further question is whether all code should be PIC if the gcc being used for the link passes -pie by default and stop setting -no-pie.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Nov 1, 2018

When you use -buildmode=pie the go tool is supposed to rebuild all dependencies using -shared, including the standard library. If that is not happening, something is wrong.

As far as a gcc defaulting to PIE, we already have support when using -compiler=gccgo for passing -fno-pie; perhaps we need to extend that support to the gc compiler side. See gccNoPie in cmd/go/internal/work/.

@ianlancetaylor ianlancetaylor added this to the Go1.12 milestone Nov 1, 2018

@laboger

This comment has been minimized.

Contributor

laboger commented Nov 1, 2018

I'm sorry there's some confusion here. This was reported to me through a bugzilla that even with -buildmode=pie a bad relocation is generated but I was mistaken above about whether stdlib is built with PIC in this case. In my experiments it seems to be. The reported failure is on RHEL8 which I don't have access to so I'm not sure yet where it is coming from.

One related question is whether golang should recognize whether the gcc on the system sets -pie by default when invoking the linker and if so just build it as -buildmode=pie. I'm not sure if that's the right answer but just what was suggested.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Nov 1, 2018

I don't think we should change the default of go build to the default of GCC. That seems like an unnecessary tying that will tend to increase confusion.

Perhaps we should have an easy way for a distro to change the default of go build, but that seems like a different issue. (For example, we could consider adding another environment variable recognized by src/make.bash.)

@laboger

This comment has been minimized.

Contributor

laboger commented Nov 5, 2018

@ianlancetaylor Is there a way to build a toolchain for ppc64le so that the default type of executable is always PIE through the use of existing environment variables or other options? Or is it more complicated than that?

I tried to just change the default in cmd/go/internal/work/init.go as a test to see what would happen and got this:

Building Go toolchain2 using go_bootstrap and Go toolchain1.
# cmd/cgo
loadinternal: cannot find runtime/cgo
# cmd/asm
loadinternal: cannot find runtime/cgo
# cmd/link
loadinternal: cannot find runtime/cgo
# cmd/compile
loadinternal: cannot find runtime/cgo
Building Go toolchain3 using go_bootstrap and Go toolchain2.
# cmd/cgo
loadinternal: cannot find runtime/cgo
# cmd/asm
loadinternal: cannot find runtime/cgo
# cmd/link
loadinternal: cannot find runtime/cgo
# cmd/compile
loadinternal: cannot find runtime/cgo
HASH[build runtime/internal/sys]
HASH[build runtime/internal/sys]: "devel +745ec8b Fri Nov 2 17:56:07 2018 +0000"
HASH[build runtime/internal/sys]: "compile\n"
HASH[build runtime/internal/sys]: "goos linux goarch ppc64le\n"
HASH[build runtime/internal/sys]: "import \"runtime/internal/sys\"\n"
HASH[build runtime/internal/sys]: "omitdebug false standard true local false prefix \"\"\n"
HASH[build runtime/internal/sys]: "compile ymJr-uldWHMJ1NKhKQaW X:framepointer [\"-shared\"] []\n"
HASH[build runtime/internal/sys]: "GO$GOARCH=\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/arch.go: d9b0b7e72538d421b2607acaba60ca49f20ef584b3d1d191c6729e35fbb8101d
HASH[build runtime/internal/sys]: "file arch.go 2bC35yU41CGyYHrKumDK\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/arch_ppc64le.go: d43466ea44c56eba4514ad41e6652168a0ce0dcb720578ea6dadea343266a24a
HASH[build runtime/internal/sys]: "file arch_ppc64le.go 1DRm6kTFbrpFFK1B5mUh\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/intrinsics.go: 8b469a461e1d983706e0b3635715ce70691adc5db7c4e067b88cc59f40cd66f4
HASH[build runtime/internal/sys]: "file intrinsics.go i0aaRh4dmDcG4LNjVxXO\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/stubs.go: 376cb070d0d0d7094a8a5ed372853e00c377c2aba3d8c118dee821dd526a6022
HASH[build runtime/internal/sys]: "file stubs.go N2ywcNDQ1wlKil7TcoU-\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/sys.go: 55e021891200a7e6a5c371c8a1ab71b6c15aeb16ea6c1b192185d17df8c8b18f
HASH[build runtime/internal/sys]: "file sys.go VeAhiRIAp-alw3HIoatx\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/zgoarch_ppc64le.go: 157322cbcc4e3c5d80effef8a81d3d9a480cc2558550fad0df46a10b48af334c
HASH[build runtime/internal/sys]: "file zgoarch_ppc64le.go FXMiy8xOPF2A7_74qB09\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/zgoos_linux.go: 32284a5a70366b56fe207ea3a16ad5d61dd208d425ad28b81cc2fe59db9180e8
HASH[build runtime/internal/sys]: "file zgoos_linux.go MihKWnA2a1b-IH6joWrV\n"
HASH /home/boger/golang/clean/go/src/runtime/internal/sys/zversion.go: a0901e5adb74da30a6a6643ab36cfaa28c4c5136142e9a1fdeec8ca6c30f000a
HASH[build runtime/internal/sys]: "file zversion.go oJAeWtt02jCmpmQ6s2z6\n"
HASH[build runtime/internal/sys]: 664409261b5745f2e0926a0ef91599e67e2adb4a49da5a0b03eef7256f034c44
runtime/internal/sys true
go tool dist: unexpected stale targets reported by /home/boger/golang/clean/go/pkg/tool/linux_ppc64le/go_bootstrap list -gcflags="" -ldflags="" for [cmd/asm cmd/cgo cmd/compile cmd/link runtime/internal/sys]:
	STALE cmd/asm: stale dependency: internal/cpu
	STALE cmd/cgo: stale dependency: internal/cpu
	STALE cmd/compile: stale dependency: internal/cpu
	STALE cmd/link: stale dependency: internal/cpu
	STALE runtime/internal/sys: build ID mismatch
@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Nov 5, 2018

There is no simple way today to force the gc toolchain to default to PIE.

I'm not sure why changing buildModeInit didn't work. It looks like it got confused with the cache. Maybe some extra step is required to add the different build mode to the cache key somehow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment