10

I'm working on a bare-metal STM32 project, compiling on a Linux x64 host.

After upgrading my toolchain from gcc-arm-none-eabi-11.2-2022.02 to arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi, I get the following linker warnings:

warning: _close is not implemented and will always fail
warning: _fstat is not implemented and will always fail
warning: _getpid is not implemented and will always fail
warning: _isatty is not implemented and will always fail
warning: _kill is not implemented and will always fail
warning: _lseek is not implemented and will always fail
warning: _open is not implemented and will always fail
warning: _read is not implemented and will always fail
warning: _write is not implemented and will always fail

More comprehensively, I get this:

~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(libc_a-closer.o): in function `_close_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/closer.c:47: warning: _close is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(libc_a-fstatr.o): in function `_fstat_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/fstatr.c:55: warning: _fstat is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(libc_a-signalr.o): in function `_getpid_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/signalr.c:83: warning: _getpid is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(libc_a-isattyr.o): in function `_isatty_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/isattyr.c:52: warning: _isatty is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(libc_a-signalr.o): in function `_kill_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/signalr.c:53: warning: _kill is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(libc_a-lseekr.o): in function `_lseek_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/lseekr.c:49: warning: _lseek is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(libc_a-openr.o): in function `_open_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/openr.c:50: warning: _open is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(libc_a-readr.o): in function `_read_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/readr.c:49: warning: _read is not implemented and will always fail
~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: ~/dev_tools/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(libc_a-writer.o): in function `_write_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/writer.c:49: warning: _write is not implemented and will always fail

Other than that, the project seems to compile fine. Reading the release note (available here), I can't see what could cause this.

  1. What change caused this?
  2. Can I disregard these warnings? It looks like system calls, so I guess I can?
  3. If so, can they be silenced?
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nebular Noise
  • 388
  • 3
  • 15
  • 2
    `gcc-arm-none-eabi` implies bare metal, so why would those libs be present in the first place? Seems like some mismatch with the standard lib, maybe you need to update or tweak newlib. – Lundin Sep 16 '22 at 09:49
  • 1
    Also always compile as `-ffreestanding` but I don't think it's related to the problem you are having. – Lundin Sep 16 '22 at 09:50
  • 1
    You need to provide a minimal example, you are showing C library backend stuff, so you have to explain not only the version of one part of the toolchain, but also the C library and your code and the backend you wrote for that C library. Several components have to come together and you are asking about only 1. – old_timer Sep 16 '22 at 10:11
  • ive been building for stm32 with gcc 12.x.x for a while now, no issues. passed through the 11.x.x versions a while back when they were new...no issues. – old_timer Sep 16 '22 at 10:13
  • Does gcc not have that `--nostdlib` linker option anymore? – kesselhaus Sep 17 '22 at 07:23

4 Answers4

7

The library supplied with gcc-arm-none-eabi is called 'newlib'. You can download a copy from git://sourceware.org/git/newlib-cygwin.git. It has tags and you can determine the specific version released with your compiler and get the tagged version.

For example, syscalls.c is one implementation. The Libc stubs document contains functions to implement. However, you may wonder why you get these warnings. There are various 'C' library function calls, such as srand(), assert(), etc which will drag in the 'C' file libraries. You need to look at a map file and avoid these function calls if you wish to minimize overhead.

I am not sure of your code base and sub-sections of a map file would be helpful. Here you have,

  • _open_r
  • _close_r
  • _read_r

Which are from the 'reent' for re-entrant library. Typically, the re-entrant functions are only needed for an RTOS or desktop operating system. If you have a bare metal single main thread, you do not need these functions. You can not call open() in an interrupt handler with this option :) So, there is really only one context (and a single errno as well). The 're-entrant' functionality is useless. As is .fini sections, embedded devices don't 'shutdown' normally, they reboot.

What change caused this ?

You have linked with something (called a function) that brought in file system primitives in the 'C' library.

Can I disregard these warnings ?

It depends on your use case. Are you a safety critical system? Generally I would recommend fixing them so the next person is not confused. Most likely if the code follows the path to these functions, something is already wrong/unhandled.

It looks like system calls, so I guess I can?

Not a question?

If so, can they be silenced ?

Either avoid the functions or provide alternate implementations that 'do the right thing'. The 'right thing' will depend on your platform.

Here is a list of options when you have linker errors.

  1. Change the build options.
  2. Provide the library.
  3. Provide an alternative library.
  4. Avoid the function call/data use.

You can implement your own close_r(), open_r(), and read_r(). For instance, you can use an embedded read-only file system with a linked blob (option 3). Most likely the write is to stderr, so it may not be appropriate (option 4). The option 2 is actually the issue in this case; but it might be fine... it is just the authors of newlib are not sure what the right things is, hence the warning.

artless noise
  • 21,212
  • 6
  • 68
  • 105
4

These are the methods that the system call needs to implement, you use the functions of the standard library (NEWLIB), so you should implement these methods according to your own platform If you're sure you don't need to implement these, just add an empty implementation to the link add link

void _close(void)
{
}
void _lseek(void)
{

}
void _read(void)
{
}
void _write(void)
{
}

before

[ 50%] Building C object CMakeFiles/xpad.dir/src/main.c.o
[100%] Linking C executable xpad
/home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/libc.a(libc_a-closer.o): in function `_close_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/closer.c:47: warning: _close is not implemented and will always fail
/home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/libc.a(libc_a-lseekr.o): in function `_lseek_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/lseekr.c:49: warning: _lseek is not implemented and will always fail
/home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/libc.a(libc_a-readr.o): in function `_read_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/readr.c:49: warning: _read is not implemented and will always fail
/home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /home/wangkai/workspace/xpad/toolchain/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/lib/libc.a(libc_a-writer.o): in function `_write_r':
/data/jenkins/workspace/GNU-toolchain/arm-11/src/newlib-cygwin/newlib/libc/reent/writer.c:49: warning: _write is not implemented and will always fail
[100%] Built target xpad

after

[ 33%] Building C object CMakeFiles/xpad.dir/src/system_call.c.o
[ 66%] Linking C executable xpad
[100%] Built target xpad
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wangkai
  • 56
  • 1
  • 2
    Your example is partially correct and will get rid of the error, but they do cause a bit of a time bomb. The prototype for `read()`, etc. return values which are error codes. Since 'C' does not have name mangling, code requiring `read()`, etc.will compile and link, but they may use a garbage 'r0' value as a buffer size, etc. think they are reading data. The examples that return default failure (the ones provided and warned about) are probably better to have. As per [newlib stubs](https://sourceware.org/newlib/libc.html#Stubs) `int close(int file) { return -1;}` etc are better. – artless noise Sep 19 '22 at 13:57
  • As noted, files like `assert()`, etc may call these functions to try and write to stdio. Not all embedded programmers are cognizant of platform issues. A lot of people will think `assert()` is a good thing. Then on the occasion the `assert()` tiggers, the system will crash and no one will understand why. This maybe better than executing the case, but could also be worse. Sometimes `assert()` is just unexpected parameters, that are still handled by the code for production non-assert cases. – artless noise Sep 19 '22 at 14:02
  • Thanks, my original intention is just to clear the warning, it does introduce some problems, and the reference needs to be carefully evaluated in the project to implement these methods – wangkai Sep 20 '22 at 01:25
4

The warnings you encountered were placed in syscalls implementation of libnosys (e.g. see close.c, and relevant warning.h. At some point, you link against libnosys - either by

  • -lnosys link flag (common in Makefiles, generated by STM32CubeMX),
  • --specs=nosys.specs compile/link flag

The developers used a neat trick to embed warning messages into object files, using .gnu.warning.SYMBOL_NAME - Unfortunately I couldn't find official documentation, but you can read more about it here, and here.

The reason you see these warnings is that those syscalls are referenced "somewhere"... It might be a stray printf/putchar in your code, exit(), rand(), or some usage in libc itself.

Regarding the severity of the warnings

In freestanding, bare metal environments it is absolutely normal to use dummy syscalls, as we don't expect to interact with the operating system. If you use an RTOS on your platform, there is probably a dedicated syscalls implementation waiting for you. So there is probably nothing to worry about this warning. I think that the warning message itself is a little bit misleading - by "fail" it means "do nothing and return error status", which is well-defined behavior that should not lead to abnormal program execution.

Side note: I checked libnosys.a from 10-2020-q4-major release of arm-none-eabi with objdump, and it didn't have those warning symbols.

Finally, how to get rid of the messages

As others mentioned, in freestanding environment, you can provide your own dummy syscalls, and don't link against libnosys. I searched through ld documentation and source code, and didn't find a linker option to suppress this warning.

Note that if you rely on dynamic memory allocation using malloc in C, or new in C++, your implementation of _sbrk must actually work (more info here), otherwise you may enter "debugging so funny that it lasts for weeks" zone.

Funnily enough, libnosys's implementation of _sbrk works AND doesn't have embedded warning symbol. I strongly recommend using it, unless you need to allocate heap on external RAM, etc.

The added benefit of using libnosys is the fact that you don't need to write your custom syscalls in every project you make, which could be tiresome and error-prone.

TL;DR

Having said that, there is actually a method to get rid of the warnings from libnosys permanently: Look for libnosys.a in your toolchain directory (in arm-none-abi case there will one for each architecture and float ABI), and delete .gnu.warning symbols from archives using:

arm-none-eabi-objcopy -w -R .gnu.warning.* libnosys.a

Note that this will irreversibly modify your toolchain files. Most likely in intended, and non-harmful way, but still. Use with caution.

If you use CMake to build your project I would consider creating PRE_LINK command that copies relevant libnosys, strips it of warnings, and link with it instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
elMaczete
  • 41
  • 2
  • 1
    Indeed, I had the same issue and apparently the only solution is to implement your own dummy syscalls, thus defeating the point of libnosys. I don't think there's a legitimate use case for libnosys where those warnings will not appear. Either a) the dummies are never referenced, in which case you don't need libnosys to begin with or b) the dummies are referenced, and thus the warning appears. Is my understanding incorrect somehow? – Kafein Feb 08 '23 at 15:13
  • @Kafein I believe you are correct. There is a _sbrk case (while using malloc), where warnings would come from its depencency on other syscalls - not by _sbrk itself... The use of those dependencies might be configurable compilation flags, that toolchain vendor used to compile libc. Anyway, I extended my answer to provide "nasty but working" workaround to get rid of the warnings while still using libnosys – elMaczete Feb 09 '23 at 18:59
-1

Same thing happened with me when I updated my STM32CubeIDE (Eclipse-based). It's becuase of the updated GNU toolchain.

Go to your project's properties, C/C++ Build, Settings, Open Toolchain Manager, then install a toolchain older than your current one. When done, use the GNU toolchain that you just installed and the issues should go away.

enter image description here

Moe Eshaq
  • 1
  • 2