sherrellbc
sherrellbc

Reputation: 4853

Undefined references to any libc symbol despite direct link with archive

I am working with the ARM-gcc cross compiler and am having issues linking to any implementation within libc.

Compiling prog.c, writing to prog.o...
~/.programs/arm-gcc/bin/arm-none-eabi-gcc -Wall -fno-common -mcpu=cortex-m4 -mthumb -O0 -g -DF_CPU=72000000 -I~/.programs/arm-gcc/arm-none-eabi/include -I../include -I. -I../src/include -c prog.c -o prog.o > prog.lst

Compiling ../common/sysinit.c, writing to sysinit.o...
~/.programs/arm-gcc/bin/arm-none-eabi-gcc -Wall -fno-common -mcpu=cortex-m4 -mthumb -O0 -g -DF_CPU=72000000 -I~/.programs/arm-gcc/arm-none-eabi/include -I../include -I. -I../src/include -c ../common/sysinit.c -o sysinit.o > sysinit.lst

Assembling ../common/crt0.s, writing to crt0.o...
~/.programs/arm-gcc/bin/arm-none-eabi-as -mcpu=cortex-m4 -o crt0.o ../common/crt0.s  > crt0.lst

Compiling uart.c, writing to uart.o...
~/.programs/arm-gcc/bin/arm-none-eabi-gcc -Wall -fno-common -mcpu=cortex-m4 -mthumb -O0 -g -DF_CPU=72000000 -I~/.programs/arm-gcc/arm-none-eabi/include -I../include -I. -I../src/include -c uart.c -o uart.o > uart.lst

~/.programs/arm-gcc/bin/arm-none-eabi-ld prog.o sysinit.o crt0.o uart.o -Map=prog.map -T../common/Teensy31_flash.ld -L~/.programs/arm-gcc/arm-none-eabi/lib  -o prog.elf
prog.o: In function `print_char':
/home/user/workspace/prog/src/prog.c:47: undefined reference to `sprintf'
/home/user/workspace/prog/src/prog.c:48: undefined reference to `printf'
/home/user/workspace/prog/src/prog.c:49: undefined reference to `strlen'
prog.o: In function `main':
/home/user/workspace/prog/src/prog.c:72: undefined reference to `memset'
make: *** [makefile:133: prog.elf] Error 1

I threw in a few calls to stdlib to make the point. I have tried to explicitly link against libc using -lc but am met with:

/home/prog/.programs/arm-gcc/bin/arm-none-eabi-ld: cannot find -lc

The archive directory is passed to the linker via:

L~/.programs/arm-gcc/arm-none-eabi/lib

I have checked the contents of this directory and verified the archive to be present:

$ ls ~/.programs/arm-gcc/arm-none-eabi/lib
aprofile-validation.specs  libc_s.a            linux.specs
aprofile-ve.specs          libg.a              nano.specs
armv6-m                    libgloss-linux.a    nosys.specs
armv7-ar                   libg_s.a            pid.specs
armv7e-m                   libm.a              rdimon-crt0.o
armv7-m                    libnosys.a          rdimon.specs
cpu-init                   librdimon.a         rdpmon-crt0.o
crt0.o                     librdimon_s.a       rdpmon.specs
fpu                        librdpmon.a         redboot-crt0.o
iq80310.specs              libstdc++.a         redboot.ld
ldscripts                  libstdc++.a-gdb.py  redboot.specs
libarm_cortexM0l_math.a    libstdc++_s.a       redboot-syscalls.o
libarm_cortexM4lf_math.a   libsupc++.a         thumb
libarm_cortexM4l_math.a    libsupc++_s.a
libc.a                     linux-crt0.o

And, finally, the libc does export sprintf (and others)

$ nm libc.a | grep "sprintf"
...
lib_a-sprintf.o:
00000000 T sprintf
00000000 T _sprintf_r
         U sprintf
         U _sprintf_r
...

Info on the ARM-GCC build I am using:

$ ./arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=./arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/home/user/.programs/arm-gcc/bin/../lib/gcc/arm-none-eabi/5.4.1/lto-wrapper
Target: arm-none-eabi
Configured with: /home/build/work/GCC-5-0-build/src/gcc/configure --target=arm-none-eabi --prefix=/home/build/work/GCC-5-0-build/install-native --libexecdir=/home/build/work/GCC-5-0-build/install-native/lib --infodir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/info --mandir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/man --htmldir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/html --pdfdir=/home/build/work/GCC-5-0-build/install-native/share/doc/gcc-arm-none-eabi/pdf --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-newlib --with-headers=yes --with-python-dir=share/gcc-arm-none-eabi --with-sysroot=/home/build/work/GCC-5-0-build/install-native/arm-none-eabi --build=i686-linux-gnu --host=i686-linux-gnu --with-gmp=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-mpfr=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-mpc=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-isl=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-cloog=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-libelf=/home/build/work/GCC-5-0-build/build-native/host-libs/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-pkgversion='GNU Tools for ARM Embedded Processors' --with-multilib-list=armv6-m,armv7-m,armv7e-m,armv7-r,armv8-m.base,armv8-m.main
Thread model: single
gcc version 5.4.1 20160609 (release) [ARM/embedded-5-branch revision 237715] (GNU Tools for ARM Embedded Processors) 

Upvotes: 1

Views: 1683

Answers (1)

Arnout
Arnout

Reputation: 3464

The ~ in -L~/.programs/arm-gcc/arm-none-eabi/lib doesn't get expanded. It is the shell that expands ~ into /home/user, but only when it is at the beginning of a word.

Actually, it isn't necessary to add this -L option, because this is already in gcc's default search path. However, you link directly with ld instead of with gcc. That is not a good idea. It is better to link with gcc and allow it to add the default search paths and other required libraries, like libc and libgcc. Since you supply your own crt0, add -nostartfiles to the arguments. So link with:

~/.programs/arm-gcc/bin/arm-none-eabi-gcc prog.o sysinit.o crt0.o uart.o \
    -Wl,-Map=prog.map -Wl,-T../common/Teensy31_flash.ld -nostartfiles -o prog.elf

Upvotes: 1

Related Questions