Functions which are in the linked library are not seen in executable

1

I am trying to compile FreeRTOS project for stm32f4 using cmake. Everything goes smooth except for linking syscalls.c.

Project structure looks like this:

project structure

Everyting that is not in src folder is compiled as a static library i.e. SPL, startup files, FreeRTOS and etc. My last compilation step:

[100%] Linking C executable bin/stm32f4_template.elf

/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-gcc  
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -march=armv7e-m -fsingle-precision-constant 
-finline-functions -Wdouble-promotion -std=gnu99 -Os -g -Wall -ffunction-sections 
-fdata-sections -specs=nano.specs -u _scanf_float -u printf_float -fno-exceptions 
-Wl,--gc-sections,-T/home/kript0n/Documents/projects/STM32F4-FreeRTOS/Utilities/stm32_flash.ld,
-Map,/home/kript0n/Documents/projects/STM32F4-FreeRTOS/build/bin/stm32f4_template.elf.map 
CMakeFiles/stm32f4_template.elf.dir/src/main.c.obj CMakeFiles/stm32f4_template.elf.dir/src/controller.c.obj  -o bin/stm32f4_template.elf 
Libraries/STM32F4xx_StdPeriph_Driver/libdriverlib.a FreeRTOS/libFreeRTOS.a hardware/libhardware.a -lm Libraries/TM/libtm.a Libraries/syscall/libsyscalls.a 

And output:

/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x10): undefined reference to `_write'
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg_nano.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x10): undefined reference to `_read'
collect2: error: ld returned 1 exit status
CMakeFiles/stm32f4_template.elf.dir/build.make:126: recipe for target 'bin/stm32f4_template.elf' failed
make[2]: *** [bin/stm32f4_template.elf] Error 1

As you can see syscalls.c is linked however system calls are still not found. Here is contents of syscalls.c and all the missing functions are presented inside:

#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "stdio.h"
#include "stm32f4xx_usart.h"

/***************************************************************************/

int _open(const char *name, int flags, int mode){
  return -1;
}

int _read(int file, char * ptr, int len) {
  ptr = ptr;
  len = len;
  errno = EINVAL;
  return -1;
}

/***************************************************************************/

int _lseek(int file, int ptr, int dir) {
  file = file;
  ptr = ptr;
  dir = dir;
  return 0;
}

/***************************************************************************/

int _write(int file, char * ptr, int len) {
  int index;
  if (!ptr) {
    return 0;
  }
  for (index = 0; index < len; index++) {
    while (!(USART3->SR & 0x00000040));
    USART_SendData(USART3, ptr[index]);
  }
  return len;
}

/***************************************************************************/

int _close(int file) {
  return 0;
}

/***************************************************************************/

/* Register name faking - works in collusion with the linker.  */
register char * stack_ptr asm ("sp");

caddr_t _sbrk(int incr) {
  extern char   end asm ("end"); // Defined by the linker.
  static char * heap_end;
  char *        prev_heap_end;
  if (heap_end == NULL)
    heap_end = & end;
  prev_heap_end = heap_end;
  if (heap_end + incr > stack_ptr) {
    // Some of the libstdc++-v3 tests rely upon detecting
    // out of memory errors, so do not abort here.
#if 0
    extern void abort (void);
    _write (1, "_sbrk: Heap and stack collision\n", 32);
    abort ();
#else
    errno = ENOMEM;
    return (caddr_t) -1;
#endif
  }
  heap_end += incr;
  return (caddr_t) prev_heap_end;
}

/***************************************************************************/

int _fstat(int file, struct stat * st) {
  file = file;
  memset (st, 0, sizeof (* st));
  st->st_mode = S_IFCHR;
  return 0;
}

/***************************************************************************/

int _isatty(int fd) {
  fd = fd;
  return 1;
}

int _kill(int pid, int sig) {
  errno=EINVAL;
  return(-1);
}

int _getpid(void) {
  return 1;
}

And its' building step:

[ 85%] Building C object Libraries/syscall/CMakeFiles/syscalls.dir/syscalls.c.obj
cd /home/kript0n/Documents/projects/STM32F4-FreeRTOS/build/Libraries/syscall && /home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-gcc  -DARM_MATH_CM4 -DHSE_VALUE=8000000 -DSTM32F40_41xxx -DSTM32F4XX -DUSESTD_PERIPH_DRIVER -D__FPU_PRESENT=1 -D__FPU_USED=1 -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/Libraries/CMSIS/Device/ST/STM32F4xx/Include -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/Libraries/CMSIS/Include -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/Libraries/STM32F4xx_StdPeriph_Driver/inc -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/Libraries/TM/TM_SPL -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/FreeRTOS/include -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/FreeRTOS/portable/GCC/ARM_CM4F -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/config -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/hardware -I/home/kript0n/Documents/projects/STM32F4-FreeRTOS/include  -mcpu=cortex-m4     -mthumb     -mfloat-abi=hard     -mfpu=fpv4-sp-d16     -march=armv7e-m     -fsingle-precision-constant     -finline-functions     -Wdouble-promotion     -std=gnu99     -Os     -g     -Wall     -ffunction-sections     -fdata-sections     -specs=nano.specs   -o CMakeFiles/syscalls.dir/syscalls.c.obj   -c /home/kript0n/Documents/projects/STM32F4-FreeRTOS/Libraries/syscall/syscalls.c
[ 89%] Linking C static library libsyscalls.a
cd /home/kript0n/Documents/projects/STM32F4-FreeRTOS/build/Libraries/syscall && /usr/bin/cmake -P CMakeFiles/syscalls.dir/cmake_clean_target.cmake
cd /home/kript0n/Documents/projects/STM32F4-FreeRTOS/build/Libraries/syscall && /usr/bin/cmake -E cmake_link_script CMakeFiles/syscalls.dir/link.txt --verbose=1
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-ar qc libsyscalls.a  CMakeFiles/syscalls.dir/syscalls.c.obj
/home/kript0n/Applications/EmbeddedArm/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-ranlib libsyscalls.a
make[2]: Leaving directory '/home/kript0n/Documents/projects/STM32F4-FreeRTOS/build'
[ 89%] Built target syscalls

It seems that file is compiled into a library, functions are presented and it is linked. So what's wrong with it?

Thanks!

c
linker
stm32
asked on Stack Overflow Nov 26, 2017 by Long Smith • edited Nov 26, 2017 by Long Smith

1 Answer

1

The rules that determine which symbol will be linked in, and when do they get marked as used, and not dropped by the linker, are somewhat different for standalone object files and libraries. Your problem might be correted by carefully rearranging the linker command line.

I have stopped caring about it, and just force marking the dropped functions as 'used'.

#define USED __attribute__ ((used))
#define UU __attribute__((unused))

int USED _close(int x UU) {
  return -1;
}

int USED _fstat(int file UU, struct stat *st) {
  st->st_mode = S_IFCHR;
  return 0;
}

User contributions licensed under CC BY-SA 3.0