Undefined references to any libc symbol despite direct link with archive - linux

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)

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

Related

How does make use variables when expanding and compiling before linking?

Info:
Linux watvde0453 3.10.0-1062.1.1.el7.x86_64 #1 SMP Fri Sep 13 22:55:44 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Hi
I have been playing around with a make file to allow builds of shared, static libraries and an exe (and also to get some sort of understanding about how it works) and came across some behavior I do not understand.
I was trying to separate out the flags used for lib / exe into separate variables, but when using a line to compile and link all in one it looks like only the CFLAGS variable is being included for the compile step.
When using the following makefile:
LIBCFLAGS := -fPIC
CFLAGS := -O3 -g -Wall -Werror
CC := gcc
SRCS=hashfunction.c hashtable.c hashtablelinkedlist.c
OBJS=hashfunction.o hashtable.o hashtablelinkedlist.o
LIBSO = lib$(NAME).so
libso: $(OBJS)
$(CC) $(LIBCFLAGS) $(CFLAGS) -shared -o $(LIBSO) $(OBJS)
I get the following output when running the make command for libso:
$ make libso
gcc -O3 -g -Wall -Werror -c -o hashfunction.o hashfunction.c
gcc -O3 -g -Wall -Werror -c -o hashtable.o hashtable.c
gcc -O3 -g -Wall -Werror -c -o hashtablelinkedlist.o hashtablelinkedlist.c
gcc -fPIC -O3 -g -Wall -Werror -shared -o lib.so hashfunction.o hashtable.o hashtablelinkedlist.o
/tools/oss/packages/x86_64-centos7/binutils/default/bin/ld: hashtable.o: relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object; recompile with -fPIC
hashtable.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:12: libso] Error 1
I can get it all working by sticking all the flags in CFLAGS, but I was wondering if anyone could explain what make is doing underneath ?
It looks like the $(LIBCFLAGS) is being ignored for the implicit compile lines, but $(CFLAGS) is not. Is CFALGS used implicitly by make for all compilations ?
You can see all the built-in rules make knows about by running make -p -f/dev/null. There you'll see:
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
which is the built-in rule make uses to create a .o file from a .c file. Looking elsewhere in the output you'll see:
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
so these are the variables make uses to compile .c files into .o files.

GCC cross compiler for i686 using cygwin (windows) - fail in building GCC

I am trying to cross compile the gcc for linux - i686-elf platform from windows PC (cygwin). As per the toolchain steps, I have successfully compiled:
binutils using
/binutils-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
basic gcc 1st step using
gcc-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
linux headers using
make headers_install ARCH=i386 CROSS_COMPILE=i386-linux- INDTALL_HDR_PATH=my/path/
glibc using
CC=${TARGET}-gcc ../glibc-2.29/configure --target=$TARGET --host=i686-pc-linux-gnu --prefix=$PREFIX --with-headers=my/path/
and then, make install-headers
Now, while building 2nd part og GCC using:../gcc-7.4.0/configure --target=$TARGET --prefix=$PREFIX --with-sysroot=$HOME/opt/cross --disable-libssp --disable-libgomp --disable-libmudflap --enable-languages=c,c++ --disable-multilib
I am getting the follwing errors:
make[2]: Entering directory '/home/MyPcUserName/src/build-gcc/i686-elf/libgcc
- If this is the top-level multilib, build all the other multilibs.
ln -s ../../../gcc-7.4.0/libgcc/enable-execute-stack-empty.c enable-execute-stack.c
ln -s ../../../gcc-7.4.0/libgcc/unwind-generic.h unwind.h
ln -s ../../../gcc-7.4.0/libgcc/config/no-unwind.h md-unwind-support.h
ln -s ../../../gcc-7.4.0/libgcc/config/i386/sfp-machine.h sfp-machine.h
ln -s ../../../gcc-7.4.0/libgcc/gthr-single.h gthr-default.h
DEFINES='' HEADERS='' \
../../../gcc-7.4.0/libgcc/mkheader.sh > tmp-libgcc_tm.h
/bin/sh ../../../gcc-7.4.0/libgcc/../move-if-change tmp-libgcc_tm.h libgcc_tm.h
echo timestamp > libgcc_tm.stamp
/home/MyPcUserName/src/build-gcc/./gcc/xgcc -B/home/MyPcUserName/src/build-gcc/./gcc/ -B/home/MyPcUserName/opt/cross/i686-elf/bin/ -B/home/MyPcUserName/opt/cross/i686-elf/lib/ -isystem /home/MyPcUserName/opt/cross/i686-elf/include -isystem /home/MyPcUserName/opt/cross/i686-elf/sys-include -g -O2 -O2 -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -isystem ./include -fpic -g -DIN_LIBGCC2 -fbuilding-libgcc -fno-stack-protector -fpic -I. -I. -I../.././gcc -I../../../gcc-7.4.0/libgcc -I../../../gcc-7.4.0/libgcc/. -I../../../gcc-7.4.0/libgcc/../gcc -I../../../gcc-7.4.0/libgcc/../include -DHAVE_CC_TLS -o _muldi3.o -MT _muldi3.o -MD -MP -MF _muldi3.dep -DL_muldi3 -c ../../../gcc-7.4.0/libgcc/libgcc2.c -fvisibility=hidden -DHIDE_EXPORTS
In file included from /home/MyPcUserName/opt/cross/usr/include/bits/libc-header-start.h:33:0,
from /home/MyPcUserName/opt/cross/usr/include/stdio.h:27,
from ../../../gcc-7.4.0/libgcc/../gcc/tsystem.h:87,
from ../../../gcc-7.4.0/libgcc/libgcc2.c:27:
/home/MyPcUserName/opt/cross/usr/include/features.h:474:10: fatal error: gnu/stubs.h: No such file or directory
#include <gnu/stubs.h>
^~~~~~~~~~~~~
compilation terminated.
make[2]: *** [Makefile:491: _muldi3.o] Error 1
make[2]: Leaving directory '/home/MyPcUserName/src/build-gcc/i686-elf/libgcc'
make[1]: *** [Makefile:11875: all-target-libgcc] Error 2
make[1]: Leaving directory '/home/MyPcUserName/src/build-gcc'
make: *** [Makefile:893: all] Error 2
I have tried --disable-multilib to disable the mulilib so as to ignore this gnu issue on 64-bit PC.
I tried to rebuilt all of it again, but still I am facing this issue.
Please let me know if anyone can help. Thanks a lot for your time
After building the glibc, we shouldn't directly start building 2nd part of GCC. Rather, few more steps should be followed for glibc as indicated below:
$ CC=${TARGET}-gcc ../glibc-2.29/configure --target=$TARGET --host=i686-pc-linux-gnu --prefix=$PREFIX --with-headers=my/path/
$ make install-bootstrap-headers=yes install-headers
$ make -j4 csu/subdir_lib
$ install csu/crt1.o csu/crti.o csu/crtn.o /opt/cross/$TARGET/lib
$ $TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /opt/cross/$TARGET/lib/libc.so
$ touch /opt/cross/$TARGET/include/gnu/stubs.h
Then, we can start building the 2nd part of GCC.

How to make .so file with libtool

I am currently using the following method to create shared libraries:
gcc -c test1.c -fPIC -o test1.o
gcc -c test2.c -fPIC -o test2.o
...
gcc test1.o test2.o ... -shared -o libtest.so
How can I do this same task with libtool? This is what I have done so far:
libtool compile gcc -c test1.c -o test1.o
libtool compile gcc -c test2.c -o test2.o
...
libtool link gcc test1.lo test2.lo ... -o libtest.la
However, this only creates libtest.la and libtest.a. I need the shared library libtest.so.
Try to add -rpath option like:
libtool --mode=link gcc -o libtest.la test1.lo -rpath /tmp
-rpath option tells Libtool where to install the library
If the path's missed, it won't generate the shared library.
I was bothered by this problem for quite a while until later I read carefully through the log file from configure, the script detects that LD was not able to generate dynamic linked file (.so). The problem was my environment variable LD was set to g++. Unset it or change to ld fixed the problem.

My lib_LTLIBRARIES library links, but check_LTLIBRARIES one does not?

I have a new c++ project built with autoconf, automake and libtool. Functionality is divided up into support libraries and user binaries. There is also a set of unittests binaries which link against these libraries, are built and run at make check time, but are not installed.
I said the the project is new. I'm actually just now getting around to extracting the first library that should be installed. Until now the (small amount of) written code was just compiled directly into a unittests.
My attempted Makefile.am snippet looks like this:
lib_LTLIBRARIES += libfoo.la
libfoo_la_SOURCES = foo.cc
In make check, I get this:
/bin/bash ./libtool --tag=CXX --mode=link g++ -Wall -Wextra -Werror -ansi -fprofile-arcs -ftest-coverage -g -O0 -fprofile-arcs -ftest-coverage -L/usr/local/lib -Wl,-rpath /usr/local/lib -o libfoo.la -rpath /usr/local/lib foo.lo -lboost_thread-mt -lboost_system-mt -pthread
libtool: link: g++ -fPIC -DPIC -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.6.1/crtbeginS.o .libs/foo.o -L/usr/local/lib -lboost_thread-mt -lboost_system-mt -L/usr/lib/gcc/x86_64-linux-gnu/4.6.1 -L/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../.. -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-linux-gnu/4.6.1/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu/crtn.o -fprofile-arcs -O0 -fprofile-arcs -Wl,-rpath -pthread -pthread -Wl,-soname -Wl,libfoo.so.0 -o .libs/libfoo.so.0.0.0
/usr/bin/ld: cannot find libfoo.so.0: No such file or directory
collect2: ld returned 1 exit status
Notice the missing library is precisely the one I'm trying to compile.
(The library is not libfoo, but I am able to reproduce the same error with this stub library. The Makefile.am and error lines above are literal and unedited.)
If I change the automake lines to
check_LTLIBRARIES += libfoo.la
libfoo_la_SOURCES = foo.cc
then the compile looks like this:
/bin/bash ./libtool --tag=CXX --mode=link g++ -Wall -Wextra -Werror -ansi -fprofile-arcs -ftest-coverage -g -O0 -fprofile-arcs -ftest-coverage -L/usr/local/lib -Wl,-rpath /usr/local/lib -o libfoo.la foo.lo -lboost_thread-mt -lboost_system-mt -pthread
libtool: link: ar cru .libs/libfoo.a .libs/foo.o
libtool: link: ranlib .libs/libfoo.a
libtool: link: ( cd ".libs" && rm -f "libfoo.la" && cp -p "../libfoo.la" "libfoo.la" )
..and everything works fine (except my library isn't installed, being in check_.)
Notice the only difference in the command lines is some additional arguments in the 2nd one:
... -Wl,-rpath /usr/local/lib -o libfoo.la -rpath /usr/local/lib foo.lo -lboost_thread-mt ...
I don't know offhand if this new argument shouldn't be there, but it does appear to be causing the problem. Does anyone know what I'm missing?
Some more details:
On osx lion, this works fine (and the command lines are different.) This error manifests on
ubuntu 12.04, possibly other linuxes.
noinst_LTLIBRARIES and EXTRA_LTLIBRARIES work like check_LTLIBRARIES: no extra arguments, and it links. It seems libtool 'convenience' libraries are specifically the ones without these arguments.
automake 1.11.1
autoconf 2.68
libtool 2.4
EDIT
(Manually) dropping -Wl,-rpath /usr/local/lib from the arguments also fixes the problem.
I did it to myself. While bringing in autoconf support for boost, I encountered a bug described here. My work-around followed the suggestion of one post:
diff --git a/m4/boost.m4 b/m4/boost.m4
index 3d4e47c..9dd0c43 100644
--- a/m4/boost.m4
+++ b/m4/boost.m4
## -403,7 +403,7 ## dnl generated only once above (before we start the for loops).
LDFLAGS=$boost_save_LDFLAGS
LIBS=$boost_save_LIBS
if test x"$Boost_lib" = xyes; then
- Boost_lib_LDFLAGS="-L$boost_ldpath -Wl,-R$boost_ldpath"
+ Boost_lib_LDFLAGS="-L$boost_ldpath -Wl,-rpath $boost_ldpath"
Boost_lib_LDPATH="$boost_ldpath"
break 6
else
The -rpath introduced here is the same one apparently causing the issue. If I revert this change, the problem goes away (I am of course left with the first issue, but that's another story.)

Firefox not loading XPCOM Component under Fedora

I am trying to build simple XPCOM component for Firefox 3.6.13 under LINUX operating system. I successfully compiled the component using Xulrunner SDK 1.9.2.13. I kept it under components directory. But when I start my firefox firefox console shows error
'Failed to load XPCOM component:
/home/mypc/.mozilla/firefox/cxsm79p6.default/extensions/{1280606b-2510-4fe0-97ef-9b5a22eafe80}/components/MyComponent.so
By referring to this link https://developer.mozilla.org/en/Troubleshooting_XPCOM_components_registration, I followed instructions under title 'Linux-specific hints'. It says to use special linking time option -Wl,-z,defs while linking. So I added these options but now while compiling its showing error as
make: Warning: File `Makefile' has modification time 0.25 s in the future
c++ -Os -Wall -o MyComponent.so
-include xpcom-config.h -DXPCOM_GLUE_USE_NSPR -I /mnt/hgfs/C/Users/sunil/SDKS/LINUX/xulrunner-sdk/include
-I./ -L /mnt/hgfs/C/Users/sunil/SDKS/LINUX/xulrunner-sdk/lib
-lxpcomglue_s -lxpcom -lnspr4 -fno-rtti -fno-exceptions -shared -Wl,-z,defs MyComponent.cpp MyComponentModule.cpp
/tmp/ccMGUTql.o: In function
MyComponent::QueryInterface(nsID
const&, void**)':
MyComponent.cpp:(.text+0x9b):
undefined reference to
NS_TableDrivenQI(void*, QITableEntry
const*, nsID const&, void**)'
/tmp/ccbkZLTz.o: In function
NSGetModule':
MyComponentModule.cpp:(.text+0x15):
undefined reference to
NS_NewGenericModule2(nsModuleInfo
const*, nsIModule*)' collect2: ld
returned 1 exit status make: **
[build] Error 1
My New makefile is as follows
CXX = c++
CPPFLAGS += -fno-rtti \
-fno-exceptions \
-shared \
-Wl,-z,defs
# Change this to point at your Gecko SDK directory.
GECKO_SDK_PATH =/mnt/hgfs/C/Users/sunil/SDKS/LINUX/xulrunner-sdk
# GCC only define which allows us to not have to #include mozilla-config
# in every .cpp file. If your not using GCC remove this line and add
# #include "mozilla-config.h" to each of your .cpp files.
GECKO_CONFIG_INCLUDE = -include xpcom-config.h
GECKO_DEFINES = -DXPCOM_GLUE_USE_NSPR
GECKO_INCLUDES = -I $(GECKO_SDK_PATH)/include
GECKO_LDFLAGS = -L $(GECKO_SDK_PATH)/lib -lxpcomglue_s -lxpcom \
-lnspr4
FILES = MyComponent.cpp MyComponentModule.cpp
TARGET = MyComponent.so
build:
$(CXX) -Os -Wall -o $(TARGET) $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) $(GECKO_INCLUDES) -I./ $(GECKO_LDFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(FILES)
chmod +x $(TARGET)
strip $(TARGET)
clean:
rm $(TARGET)
Can somebody help me get around this ?
I think you get this error if your libraries aren't specified correctly. One of these lines might fix it:
GECKO_LDFLAGS = -L$(GECKO_SDK_PATH)/lib -L$(GECKO_SDK_PATH)/bin -Wl,-rpath-link,$(GECKO_SDK_PATH)/bin -lxpcomglue_s -lxpcom -lnspr4
or
$(CXX) -Os -Wall -o $(TARGET) $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) $(GECKO_INCLUDES) -I./ $(CPPFLAGS) $(CXXFLAGS) $(FILES) $(GECKO_LDFLAGS)

Resources