Open daenney opened 4 years ago
To cross-compile with pie, you need to set CC to a cross-compiler toolchain, e.g. CC=arm-none-eabi-gcc
in your case. Are you doing this?
I was not, thank you for pointing this out. However, the error now changed:
$ env GOOS=linux env GOARCH=arm env GOARM=7 env CC=arm-none-eabi-gcc go build -o test -buildmode pie
/home/daenney/Applications/asdf/installs/golang/1.13.6/go/pkg/tool/linux_amd64/link: running arm-none-eabi-gcc failed: exit status 1
arm-none-eabi-gcc: error: unrecognized command line option '-rdynamic'
What is arm-none-eabi-gcc --version
?
Same as my GCC version, 9.2.0.
But I think I found the issue:
arm-none-eabi-gcc --help
-pie Create a dynamically linked position independent
executable.
I can't find a -r
flag for it, but I did find -pie
. It appears that this might've changed between GCC versions?
Hmm, no, I'm misunderstanding things I think.
-rdynamic
comes from https://github.com/golang/go/blob/master/src/cmd/link/internal/ld/lib.go#L1374-L1376
-pie
does get passed, by https://github.com/golang/go/blob/master/src/cmd/link/internal/ld/lib.go#L1262-L1269
For completeness sake:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-shared --enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto gdc_include_dir=/usr/include/dlang/gdc
Thread model: posix
gcc version 9.2.0 (GCC)
$ arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-none-eabi/9.2.0/lto-wrapper
Target: arm-none-eabi
Configured with: /build/arm-none-eabi-gcc/src/gcc-9.2.0/configure --target=arm-none-eabi --prefix=/usr --with-sysroot=/usr/arm-none-eabi --with-native-system-header-dir=/include --libexecdir=/usr/lib --enable-languages=c,c++ --enable-plugins --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --with-gnu-as --with-gnu-ld --with-system-zlib --with-newlib --with-headers=/usr/arm-none-eabi/include --with-python-dir=share/gcc-arm-none-eabi --with-gmp --with-mpfr --with-mpc --with-isl --with-libelf --enable-gnu-indirect-function --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-pkgversion='Arch Repository' --with-bugurl=https://bugs.archlinux.org/ --with-multilib-list=rmprofile
Thread model: single
gcc version 9.2.0 (Arch Repository)
I can also trigger this using -buildmode plugin
it turns out.
env GOOS=linux env GOARCH=arm env GOARM=7 env CC=arm-none-eabi-gcc go build -buildmode plugin
/home/daenney/Applications/asdf/installs/golang/1.13.6/go/pkg/tool/linux_amd64/link: running arm-none-eabi-gcc failed: exit status 1
arm-none-eabi-gcc: error: unrecognized command line option '-rdynamic'
I'm a little confused. The error says that the arm-none-eabi-gcc
invocation with -rdynamic
is failing because -rdynamic
is not a recognized option.
The gcc9.2 documentation says that -rdynamic is supported, so it hasn't been removed:
-rdynamic
Pass the flag -export-dynamic to the ELF linker, on targets that support it.
If you manually invoke arm-none-eabi-gcc
with -rdynamic
, does it fail?
It does, in my case:
$ arm-none-eabi-gcc -rdynamic
arm-none-eabi-gcc: error: unrecognized command line option '-rdynamic'
arm-none-eabi-gcc: fatal error: no input files
compilation terminated.
Interestingly, the Arch manpage for it does have the option: https://jlk.fjfi.cvut.cz/arch/manpages/man/gcc.1. The one thing I'm seeing is that it seems to need an invocation of <object-file-name> -rdynamic
so I wonder if we're getting the order of argument wrong?
Adding -x
to the Go build command will make it print the exact gcc commands it is running, that may help with the debugging.
I might be adding the -x
in the wrong place, but all I seem to get from it is:
/home/daenney/Applications/asdf/installs/golang/1.13.6/go/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -installsuffix shared -buildmode=pie -buildid=R8nBSB93JaMvrM2xsyrO/1-WJp2sTmpzMqiDxJUbL/-svvvBDZWEBTMwJydl1o/R8nBSB93JaMvrM2xsyrO -extld=arm-none-eabi-gcc /home/daenney/.cache/go-build/74/74a893b4cd5c0830e9f773af20b07c81429188d5afbfccdbaa7878e9329c478f-d
env GOOS=linux env GOARCH=arm go build -x [...]
and if the executable test
exists already delete it before running the command.
$ env GOOS=linux env GOARCH=arm env GOARM=7 env CC=arm-none-eabi-gcc go build -x -o test -buildmode pie main.go
WORK=/tmp/go-build048415045
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=/home/daenney/.cache/go-build/74/74a893b4cd5c0830e9f773af20b07c81429188d5afbfccdbaa7878e9329c478f-d
packagefile runtime=/home/daenney/.cache/go-build/c6/c65897af6473754413f8930f1ade7692d71e24a176e78e4d87b0f47f1964f0c5-d
packagefile math=/home/daenney/.cache/go-build/8a/8ac1e42be9f20855149a4f57fc06b9cd09f4b87469660f3a2f195335ddb4768c-d
packagefile internal/bytealg=/home/daenney/.cache/go-build/e5/e553582227b9b61ee7eaa669bd5c753bdbaf897f700909a26e774ef9ad5052bc-d
packagefile internal/cpu=/home/daenney/.cache/go-build/be/be8b55e27bfd9a8d3e5c40ae0e3a61a5388019039863fb19d461c849a7bf98d4-d
packagefile runtime/internal/atomic=/home/daenney/.cache/go-build/de/de33b9513fa0572f490cc74c48514f43abf17617b4982cf5a63a5536f28b8d9b-d
packagefile runtime/internal/math=/home/daenney/.cache/go-build/74/742fe70977dc1066d498a6daa262f78fb011720c4758315a124012efc3346fd1-d
packagefile runtime/internal/sys=/home/daenney/.cache/go-build/e1/e10af778fbdcbbb256cf554e5c44ab6469cb3095575839116b62170e91154e65-d
packagefile math/bits=/home/daenney/.cache/go-build/73/73631338431639e3d4f0be7f7b8fcf9eb60e4d16c29fd352e4db41ba35150608-d
EOF
mkdir -p $WORK/b001/exe/
cd .
/home/daenney/Applications/asdf/installs/golang/1.13.6/go/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -installsuffix shared -buildmode=pie -buildid=R8nBSB93JaMvrM2xsyrO/1-WJp2sTmpzMqiDxJUbL/-svvvBDZWEBTMwJydl1o/R8nBSB93JaMvrM2xsyrO -extld=arm-none-eabi-gcc /home/daenney/.cache/go-build/74/74a893b4cd5c0830e9f773af20b07c81429188d5afbfccdbaa7878e9329c478f-d
# command-line-arguments
/home/daenney/Applications/asdf/installs/golang/1.13.6/go/pkg/tool/linux_amd64/link: running arm-none-eabi-gcc failed: exit status 1
arm-none-eabi-gcc: error: unrecognized command line option '-rdynamic'
Although -rdynamic
is documented as being supported by GCC in general, in fact support for it is added on a target-specific basis. It looks like nobody has added support for -rdynamic
for the arm-none-eabi target.
We could probably fix this in the Go linker by using -Wl,-export-dynamic
instead of -rdynamic
in cmd/link/internal/ld/lib.go, but I wonder if we should file a bug against GCC instead.
It might be worthwhile to consider both. Even if we file a bug against GCC and that gets fixed, it'll still cause problems for people on older GCC versions that do not have the patch. Some distros might backport it, but I doubt it'll be done consistently.
If you're willing to accept a patch, I'm happy to attempt the changes myself and submit it.
My main concern with a patch is that on Solaris GCC does not always translate -rdynamic
to -Wl,-export-dynamic
. I think it is consistent on other ELF systems. But in principle a patch is OK.
Any updates or possible solutions for this?
No updates. A possible patch is sketched out above. Anybody want to work on that? Thanks.
I'm not sure if this is supposed to work, i.e
-buildmode pie
for ARM, but nothing seems to suggest it shouldn't.What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
main.go:
What did you expect to see?
No error, and a resulting
test
binary.What did you see instead?
The error also occurs if I add
GOARM=7
. It triggers on a combination of-buildmode pie
andGOARCH=arm
. Dropping-buildmode pie
the build succeeds.