Search code examples
androidandroid-ndkgnuldbinutils

How do you update the GNU linker for an Android NDK?


I am working on a native Android project using NDK r12b. This NDK (and it looks like all others since) ships with a prebuilt GNU linker version 2.25. We have recently tried to pull up lots of our project's submodules which has introduced a build error that looks like it is caused by this bug in ld.

build error output:

/opt/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: internal error in do_relocate_sections, at /usr/local/google/buildbot/src/android/gcc/toolchain/build/../binutils/binutils-2.25/gold/reloc.cc:953
collect2: error: ld returned 1 exit status

I thought I would attempt to update the linker but have had no luck finding prebuilt binaries. So I went down the rabbit hole of trying to compile ld/binutils myself. Either my Google skills are failing me, or documentation for doing this is truly rare or presumes the user has a lot of introductory knowledge that I don't have.

When building binutils 2.29.1 with target=arm-linux my application build errors out with this result:

/opt/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: unrecognised emulation mode: armelf_linux_eabi
Supported emulations: armelf_linux armelf armelfb armelfb_linux
collect2: error: ld returned 1 exit status

For reference, the -V output of our current version of ld is:

me@linux-vm:/opt/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin$ ./ld-2.25 -V
GNU gold (binutils-2.25-0666073 2.25.51.20141117) 1.11
Supported targets:
   elf64-littleaarch64
   elf64-bigaarch64
   elf32-littleaarch64
   elf32-bigaarch64
   elf64-tradlittlemips
   elf32-tradlittlemips-nacl
   elf64-tradbigmips
   elf32-tradlittlemips-nacl
   elf32-tradlittlemips
   elf32-tradlittlemips-nacl
   elf32-tradbigmips
   elf32-tradlittlemips-nacl
   elf32-tilegx-be
   elf64-tilegx-be
   elf32-tilegx-le
   elf64-tilegx-le
   elf32-bigarm
   elf32-bigarm-nacl
   elf32-littlearm
   elf32-littlearm-nacl
   elf64-powerpcle
   elf64-powerpc
   elf32-powerpcle
   elf32-powerpc
   elf64-sparc
   elf32-sparc
   elf32-x86-64
   elf32-x86-64-freebsd
   elf32-x86-64-nacl
   elf64-x86-64
   elf64-x86-64-freebsd
   elf64-x86-64-nacl
   elf32-i386
   elf32-i386-freebsd
   elf32-i386-nacl
  Supported emulations:
   aarch64_elf64_le_vec
   aarch64_elf64_be_vec
   aarch64_elf32_le_vec
   aarch64_elf32_be_vec
   elf64-tradlittlemips
   elf32-tradlittlemips-nacl
   elf64-tradbigmips
   elf32-tradlittlemips-nacl
   elf32-tradlittlemips
   elf32-tradlittlemips-nacl
   elf32-tradbigmips
   elf32-tradlittlemips-nacl
   elf32tilegx_be
   elf64tilegx_be
   elf32tilegx
   elf64tilegx
   armelfb
   armelfb_nacl
   armelf
   armelf_nacl
   elf64lppc
   elf64ppc
   elf32lppc
   elf32ppc
   elf64_sparc
   elf32_sparc
   elf32_x86_64
   elf32_x86_64_nacl
   elf_x86_64
   elf_x86_64_nacl
   elf_i386
   elf_i386_nacl

So apparently I'm missing some important configuration parameters. I also tried using an older (r8e) Android NDK's build/tools/build-gcc.sh script to build the entire compiler toolchain but with a newer binutils version. This resulted in an unknown build error:

me@linux-vm:/opt/android-ndk-r8e/build/tools$ ./build-gcc.sh --gmp-version=5.0.5 --mpfr-version=3.1.1 --mpc-version=1.0.1 --binutils-version=2.26 
$(pwd)/src $(pwd) arm-linux-androideabi-4.7
To follow build in another terminal, please use: tail -F /tmp/ndk-me/build/toolchain/config.log
Using C compiler: gcc -m32
Using C++ compiler: g++ -m32
Sysroot  : Copying: /opt/android-ndk-r8e/platforms/android-9/arch-arm --> /tmp/ndk-me/build/toolchain/prefix/sysroot
Configure: arm-linux-androideabi-4.7 toolchain build
Building : arm-linux-androideabi-4.7 toolchain [this can take a long time].
Error while building toolchain. See /tmp/ndk-me/build/toolchain/config.log

Last entries of config.log:

ar cru libintl.a bindtextdom.o dcgettext.o dgettext.o gettext.o finddomain.o loadmsgcat.o localealias.o textdomain.o l10nflist.o explodename.o dcigettext.o dcngettext.o dngettext.o ngettext.o plural.o plural-exp.o localcharset.o relocatable.o localename.o log.o osdep.o intl-compat.o
ranlib libintl.a
make[1]: Leaving directory `/tmp/ndk-me/build/toolchain/libbfd-binutils-2.26/intl'

At this point I'm just spinning my tires and trying to brute force success with different combinations of configuration parameters and source package versions. It seems as simple as adding emulation support for armelf_linux_eabi, but like I said, I have failed to find any documentation or guides that show how to do this. Surely there is a GNU wizard out there somewhere who could point me down a better path? Any help is appreciated!


Solution

  • I would try --enable-targets=all first. It is a bit of a big hammer, but maybe it helps you to avoid figuring out the exact target triplets you need (my guess would be arm-unknown-linux-eabi).