How do I include syscalls.c from a separate library file?

My code includes indirect calls for functions like _write()

and _sbrk()

. Within a project, I have a file named 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 make compilation line 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 great. However, I want to move syscalls.c into the hardware_drivers project that I have, so they must be included in the libharware_drivers.a file that is created when the hardware_drivers is compiled and included in the gcc line above. Moving the file and recompiling all my projects include my syscalls.c in an .a file (shown with arm-none-eabi-ar

). However, when it comes to compiling 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 am using arm-none-eabi-gcc

v4.8 from the sourcery code and I am compiling it for the AT91SAM7A1 chip in case it makes any difference.

Is there something special to do to tell the linker to make system calls when it is in a separate library file?

+3


source to share


1 answer


You're using

  • -nostartfiles

  • You create a file with _fstat

    at libhardware_drivers.a
  • You are using some code calling _fstat_r

    ../../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 that uses _fstat_r

from the map file or with -nodefaultlibs

or -nostdlibs

. The problem is that libraries are resolved in order from first to last. You have an implicit one -lc

at the end of your linker list. If you are going to use the 'C' library, then you must change the linker command to 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 -lc is placed before -lhardware_drivers

. This will allow the linker to resolve the lib_a-fstatr.o reference to _fstat

in your syscall.o. Another way is to force the synthetic link earlier in another object file (like Main.o). A macro can force a link,

#define FORCE_LINK(x) void* __ ## x ## _force_link =(void*)&x
FORCE_LINK(fstat);

      

You most likely have circular references in your static libraries. That is, hardware_drivers refers to the framework, refers to libc (and libc refers to hardware_drivers to make things work). The methods to overcome this are to list the libraries multiple times on the command line, or rebuild your code, which is likely to be longer.

Restructuring is as easy as the separate libsyscall.a listed after -lc

.

+3


source







All Articles