How to include syscalls.c from a separate library file? - c

My code includes indirect calls to functions like _write() and _sbrk(). Within the project I have a file called syscalls.c that defines my custom implementations of these functions, and the compiler/linker finds this file, and links to the functions correctly when I run make. The compile line make creates looks something like this:
arm-none-eabi-gcc -nostartfiles -mcpu=arm7tdmi -Wl,--gc-sections -Wl,--cref -L../hardware_drivers/lib -L../framework/lib -T../linker-script.lds -Wl,-Map,./build/bin/Mapfile.map -o build/bin/Elffile.elf ./build/obj/Main.o ./build/obj/SomeCode.o ./build/obj/syscalls.o -Wl,--start-group -lhardware_drivers -lframework -Wl,--end-group
This works perfectly. However, I want to move syscalls.c to the hardware_drivers project that I have, so they should be included in the libharware_drivers.a file that gets created when I compile hardware_drivers, and included by the gcc line above. Moving the file and recompiling all my projects does include my syscalls.c in the .a file (shown using arm-none-eabi-ar). However, when it comes to compile my top level project, I get this error:
../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'
I'm using arm-none-eabi-gcc v4.8 from code sourcery and I'm compiling it for a AT91SAM7A1 chip, if that has any relevance.
Is there something special you need to do to point the linker to syscalls when it's in a separate library file?

You use,
-nostartfiles
You create a file with _fstat in libhardware_drivers.a
You use some code with _fstat_r calling ../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o)
Here is the error message,
../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function '_fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to '_fstat'
You can try to find the code which uses the _fstat_r from a map file or with -nodefaultlibs or -nostdlibs. The issue is that libraries are resolved in a first to last order. You have an implicit -lc at the end of your linker list. If you intend to use the the 'C' library, then you must alter your linker command to position libhardware_drivers.a later in the link.
For example,
arm-none-eabi-gcc -nostartfiles -mcpu=arm7tdmi -Wl,--gc-sections -Wl,--cref\
-L../hardware_drivers/lib -L../framework/lib -T../linker-script.lds \
-Wl,-Map,./build/bin/Mapfile.map -o build/bin/Elffile.elf ./build/obj/Main.o\
./build/obj/SomeCode.o ./build/obj/syscalls.o \
-Wl,--start-group -lc -lhardware_drivers -lframework -Wl,--end-group
Here, a -lc is placed before -lhardware_drivers. This will let the linker resolve the lib_a-fstatr.o reference to _fstat in your syscall.o. Another way is to force some synthetic reference earlier in another object file (like Main.o). A macro can force the link,
#define FORCE_LINK(x) void* __ ## x ## _force_link =(void*)&x
FORCE_LINK(fstat);
Most likely you have circular references in your static libraries. Ie, hardware_drivers refers to framework refers to libc (and libc refers back to hardware_drivers to make things work). Methods to overcome this are to list the libraries multiple times on the command line or restructure your code which is probably better long term.
The restructure is as simple as a separate libsyscall.a, which is listed after -lc.

Related

_sbrk function not found when placed in a static library

I'm creating a bare-metal application for the stm32f407 microcontroller, which has an ARM Cortex M4 core. As such, I'm delivering the implementation of functions like _sbrk myself. I now find that when I try to create a static library containing _sbrk, and link it with my main.c into an application, the linker says
"c:/progra~2/gnutoo~1/4947e~1.920/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/softfp\libg_nano.a(lib_a-sbrkr.o): In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'".
If I take that same function out of the static library, and put it into main.c, everything compiles/links/runs just fine.
I am almost certain that this has something to do with the order in which the linker reads in all libraries, and that when my own static library is read, no definition of _sbrk is required yet, and is therefore thrown out, only to find that it was needed anyway when later one of the standard libraries is linked in. However, I do not specify any standard libraries myself, and can therefore not change the order of linking those libraries. I also tried to declare the _sbrk function as __attribute __ ((__ used__ )), thinking that the linker would not throw away that function, but alas, this has not solved my problem.
So my question is, how can I put _sbrk into a static library, without running into unresolved references?
Update: The command to link the final application is:
C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\AR10B2~1.EXE -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -fno-rtti -fno-exceptions -std=c++11 -fno-use-cxa-atexit -fno-threadsafe-statics -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/mem.ld" -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/sections.ld" "CMakeFiles\http_server.http_server.dir\src\main.cpp.obj" "CMakeFiles\http_server.http_server.dir\src\vectors_stm32f4xx.c.obj" "CMakeFiles\http_server.http_server.dir\http_server.http_server_linker_script_dummy.c.obj" -o "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\http_server.http_server\Generic-stm32f4xx\bin\http_server.http_server.elf" "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Where AR10B2~.EXE resolves to arm-none-eabi-g++.exe.
Adding the following makes the thing link:
-lc -lg "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Th libcmsis_stm.cmsis_stm.a library is built with the following command:
C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\ARM-NO~2.EXE cq "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a" CMakeFiles/cmsis_stm.cmsis_stm.dir/src/cmsis/system_stm32f4xx.c.obj
Where ARM-NO~2.EXE resolves to arm-none-eabi-ar.exe
So one question remains: I would like to place the interrupt vector table, which is a variable, into the static library, but the linker throws that variable away because no source file needs that variable. Is there a mechanism to keep that variable until the linker processes the output sections in the linker file?
When ld links against a library, it will only pick those functions which are required at that time (because of references to functions from translation units which have been linked in before). The linker will forget all other functions (and the library won't be considered later).
Therefore the linking order does matter. Normally you would link in your application object file (which references malloc), then the standard library (which provides malloc and in turn references _sbrk), and then your (application) library which provides _sbrk.
So linking should look like
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -lm -lapp
with the _sbrk function being provided by libapp.
So the order of the objects to be linked does matter.
Update
As stated in one of the comments: If you add debug symbols using -g during compilation, then you have to link against libg as well (-lg).
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -g -lm -lapp

What is the proper sequence of options for gcc & the importance of that sequence?

I used this command for compiling my program:
gcc -g -Wall -Werror -lpthread multi_thread_server.c -o multi_thread_socket_v4
It gave undefined reference to <function_name> error.
After of lot of trial and error to fix the error, finally I (by mistake) rearranged the options to gcc as:
gcc multi_thread_server.c -lpthread -Wall -Werror -o multi_thread_server -g
and it worked.
I read this question at SO, I got the reason as why it happened.
Here I want to know that, is there any rule for the sequence of options used for gcc?
P.S.: I know there are infinite options available for gcc, I want to know the sequence according to the category of options.
List libraries last.
After compiling, GCC passes files to the linker for linking (unless linking is not to be performed, as happens when you request compilation-only with the -c switch). It passes the files to the linker in the order you list them (or their corresponding inputs) on the command line.
You listed -lpthread (which means the pthread library, named libpthread.a or something similar) followed by multi_thread_server.c (which gets compiled to an object file named multi_thread_server.o. So the linker receives the library first, then the object file.
When the linker processes a library file, it extracts from it only the modules that supply a definition of a symbol that is needed to satisfy earlier references to the symbol. Since the library is the first file, there are no earlier references. When the linker processes multi_thread_server.o, it sees the references, but it is too late; the linker does not go back to the library.
If you list multi_thread_server.c first, the linker will see multi_thread_server.o first, and it will see that it has unsatisfied referencs. Then, when the linker processes the library, it will find the definitions for those references and will extract those modules from the library.

How are newlibc stubs supposed to be included/linked into one's code

During my project's linking process the linker fails with the following errors unless I make an explicit call in my code to one of of the stub functions (i.e. _sbrk):
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-abort.o): In function `abort':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\stdlib/../../../../../newlib-1.19.0/newlib/libc/stdlib/abort.c:63: undefined reference to `_exit'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-signalr.o): In function `_kill_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/signalr.c:61: undefined reference to `_kill'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-signalr.o): In function `_getpid_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/signalr.c:96: undefined reference to `_getpid'
c:/toolchains/yagarto/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libg.a(lib_a-sbrkr.o): In function `_sbrk_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/../../../../../newlib-1.19.0/newlib/libc/reent/sbrkr.c:60: undefined reference to `_sbrk'
collect2: ld returned 1 exit status
I am aware that I need some stubs functions that newlibc requires and I have a "C" file that contains all of the ones mentioned above as missing and I am also positive that the file is being compiled and added to an archive file (*.a) that is later linked.
I am calling the linker using the following commands
arm-none-eabi-gcc -L -T linkerscript.ld -nostartfiles -Wl,-Map,$(TARGET).map -lc archive.a
My question is simple (I hope) How can I make sure that the linker links my stub functions into the elf file without having to make an explicit function call from one of my project files?
I think those errors you're getting refer to the linker not being able to find the appropriate library. My first suspicion is in how you're using your arguments, specifically your specification of archive directory (-L) and the archive.a file. I'm thinking it should go like this:
arm-none-eabi-gcc -L. -T linkerscript.ld -nostartfiles -Wl,-Map,$(TARGET).map -lc -larchive
where the changes I'd make are:
-L. means use the current directory to look for library files to link.
-lc specifies to use the archive file libc.a.
-larchive specifies to use the archive file libarchive.a.
For more info I'd suggest checking out theGNU GCC reference.
Pass --verbose to gcc to see exactly where archive.a is showing up in the list of libraries and objects passed to the linker.
You need to arrange things so that archive.a is searched after libg.a since that's the archive that contains the objects that end up with undefined references.
You might be able to fix this by adding -lg before archive.a on the gcc command line.
-lg should in libg.a earlier than where it's getting pulled in now by default and more importantly pull it in before archive.a.

gcc detect duplicate symbols/functions in static libraries

Is there any way we can get gcc to detect a duplicate symbol in static libraries vs the main code (Or another static library ?)
Here's the situation:
main.c erroneously contained a function definition, e.g. with the signature uint foohash(const char*)
foo.c also contains a function definition with the signature uint foohash(const char*)
foo.c and other source files are compiled to a static util library, which the main program links in, i.e. something like:
gcc -o main main.o util.o -L ./libs -lfooutils
So, now main.o and libs/libfooutils.a both contain a foohash function. Presumably the linker found that symbol in main.o and doesn't bother looking for it elsewhere.
Is there any way we can get gcc to detect such a situation ?
Indeed as Simon Richter stated, --whole-archive option can be useful. Try to change your command-line to:
gcc -o main main.o util.o -L ./libs -Wl,--whole-archive -lfooutils -Wl,--no-whole-archive
and you'll see a multiple definition error.
gcc calls the ld program for linking. The relevant ld options are:
--no-define-common
--traditional-format
--warn-common
See the man page for ld. These should be what you need to experiment with to get the warnings sought.
Short answer: no.
GCC does not actually do anything with libraries. It is the task of ld, the linker (called automatically by GCC) to pull in symbols from libraries, and that's really a fairly dumb tool.
The linker has lots of complex jiggery pokery for combining different types of data from different sources, and supporting different file formats, and all the evil little details of binary executables, but in the end, all it really does is look for undefined symbols and find the definitions.
What you can do is a link trace (pass -t to gcc) to see what comes from where. Or else run nm on all the object files and libraries in your system, and write a script to detect duplicates.

Statically linking against LAPACK

I'm attempting to do a release of some software and am currently working through a script for the build process. I'm stuck on something I never thought I would be, statically linking LAPACK on x86_64 linux. During configuration AC_SEARCH_LIB([main],[lapack]) works, but compilation of the lapack units do not work, for example undefiend reference to 'dsyev_' --no lapack/blas routine goes unnoticed.
I've confirmed I have the libraries installed and even compiled them myself with the appropriate options to make them static with the same results.
Here is an example I had used in my first experience with LAPACK a few years ago that works dynamically, but not statically: http://pastebin.com/cMm3wcwF
The two methods I'm using to compile are the following,
gcc -llapack -o eigen eigen.c
gcc -static -llapack -o eigen eigen.c
Your linking order is wrong. Link libraries after the code that requires them, not before. Like this:
gcc -o eigen eigen.c -llapack
gcc -static -o eigen eigen.c -llapack
That should resolve the linkage problems.
To answer the subsequent question why this works, the GNU ld documentation say this:
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, foo.o -lz bar.o' searches libraryz' after
file foo.o but before bar.o. If bar.o refers to functions in `z',
those functions may not be loaded.
........
Normally the files found this way are library files—archive files
whose members are object files. The linker handles an archive file by
scanning through it for members which define symbols that have so far
been referenced but not defined. But if the file that is found is an
ordinary object file, it is linked in the usual fashion.
ie. the linker is going to make one pass through a file looking for unresolved symbols, and it follows files in the order you provide them (ie. "left to right"). If you have not yet specified a dependency when a file is read, the linker will not be able to satisfy the dependency. Every object in the link list is parsed only once.
Note also that GNU ld can do reordering in cases where circular dependencies are detected when linking shared libraries or object files. But static libraries are only parsed for unknown symbols once.

Resources