printf() usage in RX toolchain 20.04 change when optimisation change
printf() usage in RX toolchain 20.04 change when optimisation change
Hello GNU Tools – Thanks for maintaining a wonderful and efficient toolchain!
I recently discovered a strange behaviour, when using printf from the RX toolchain (Windows version 20.04).
Until now (many versions of GNU toolchains for RX and H8), I have implemented the following 2 functions (overwrite of weak declared library functions) in order to have printf output on a UART.
int _fstat(int filedes, struct stat *buf)
{
(void)filedes; // Tell compiler not to warn of unused arguments
(void)buf;
return 0;
}
int _write(int file, char* ptr, int len)
{
(void)file;
// Direct output from printf to service port
UARTWrite(SERVICE_PORT, (unsigned char*)ptr, len);
return len;
}
That still works fine with no optimisation (-O0)
When I raise optimisation to -O3, linking fails. The following list of functions is not found:
ssize_t read(int fd, void *buf, size_t count);
off_t lseek(int fd, off_t offset, int whence);
int kill(pid_t pid, int sig);
int close(int fd);
int isatty(int fd);
pid_t getpid(void);
int fstat(int filedes, struct stat *buf);
int write(int file, char* ptr, int len);
When I implement those mentioned functions – only write needs to have real functionality – printf works and the program compiles without warnings and errors.
Why does no weak references exist when optimisation is -O3?
Best regards Frank Kjul Larsen
Hello Frank,
I also try to build my test project using your functions, but it still shows many linker warnings. Now I guess that you are using your own makefile and you aren’t using e2 studio. Many compiler/linker options may be different from ours. Or, your project is obtained from web. Its makefile may change/switch some source files depending on optimization level.
——–
#include <stdio.h>
int _fstat(int filedes, struct stat *buf)
{
(void)filedes; // Tell compiler not to warn of unused arguments
(void)buf;
return 0;
}
int _write(int file, char* ptr, int len)
{
(void)file;
// Direct output from printf to service port
//////// UARTWrite(SERVICE_PORT, (unsigned char*)ptr, len);
return len;
}
int main(void)
{
printf(“OK”);
return 0;
}
——–
‘rx-elf-gcc -O0 -ffunction-sections -fdata-sections -fdiagnostics-parseable-fixits -g2 -Wstack-usage=100 -mcpu=rx64m -misa=v2 -mlittle-endian-data -I”C:/Renesas/GitHubDesktop/workspaces/workspace_e2v780/TestGUNRXprintf/generate” -Wa,-adlnh=”TestGUNRXprintf.lst” -MMD -MP -MF”src/TestGUNRXprintf.d” -MT”src/TestGUNRXprintf.o” “../src/TestGUNRXprintf.c” -c -o “src/TestGUNRXprintf.o”‘
../src/TestGUNRXprintf.c:46:32: warning: ‘struct stat’ declared inside parameter list will not be visible outside of this definition or declaration
int _fstat(int filedes, struct stat *buf)
^~~~
‘rx-elf-gcc -O0 -ffunction-sections -fdata-sections -fdiagnostics-parseable-fixits -g2 -Wstack-usage=100 -mcpu=rx64m -misa=v2 -mlittle-endian-data -o “TestGUNRXprintf.elf” ./src/TestGUNRXprintf.o ./generate/hwinit.o ./generate/inthandler.o ./generate/start.o ./generate/vects.o -T “C:/Renesas/GitHubDesktop/workspaces/workspace_e2v780/TestGUNRXprintf/generate/linker_script.ld” -Wl,–start-group -lm -lc -lgcc -Wl,–end-group -nostartfiles -Wl,-e_PowerON_Reset -Wl,-M=TestGUNRXprintf.map’
rx-elf-gcc @”TestGUNRXprintf.elf.in”
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-closer.o): In function `_close_r’:
(.text._close_r+0x10): warning: _close is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-fstatr.o): In function `_fstat_r’:
(.text._fstat_r+0x12): warning: _fstat is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-isattyr.o): In function `_isatty_r’:
(.text._isatty_r+0x10): warning: _isatty is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-lseekr.o): In function `_lseek_r’:
(.text._lseek_r+0x14): warning: _lseek is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-readr.o): In function `_read_r’:
(.text._read_r+0x14): warning: _read is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-writer.o): In function `_write_r’:
(.text._write_r+0x14): warning: _write is not implemented and will always fail
rx-elf-objcopy “TestGUNRXprintf.elf” -O srec -I elf32-rx-be-ns “TestGUNRXprintf.mot”
rx-elf-size –format=berkeley “TestGUNRXprintf.elf”
text data bss dec hex filename
23536 2596 64 26196 6654 TestGUNRXprintf.elf
——–
Best regards,
NoMaY
Hello Frank,
When I change write() –> _write() in moderator’s source code, the following messages are displayed. Since anyhow our results seem to be different from you. I think it is better that you will post all files of your project.
‘rx-elf-gcc -O0 -ffunction-sections -fdata-sections -fdiagnostics-parseable-fixits -g2 -Wstack-usage=100 -mcpu=rx64m -misa=v2 -mlittle-endian-data -I”C:/Renesas/GitHubDesktop/workspaces/workspace_e2v780/TestGUNRXprintf/generate” -Wa,-adlnh=”TestGUNRXprintf.lst” -MMD -MP -MF”src/TestGUNRXprintf.d” -MT”src/TestGUNRXprintf.o” “../src/TestGUNRXprintf.c” -c -o “src/TestGUNRXprintf.o”‘
‘rx-elf-gcc -O0 -ffunction-sections -fdata-sections -fdiagnostics-parseable-fixits -g2 -Wstack-usage=100 -mcpu=rx64m -misa=v2 -mlittle-endian-data -o “TestGUNRXprintf.elf” ./src/TestGUNRXprintf.o ./generate/hwinit.o ./generate/inthandler.o ./generate/start.o ./generate/vects.o -T “C:/Renesas/GitHubDesktop/workspaces/workspace_e2v780/TestGUNRXprintf/generate/linker_script.ld” -Wl,–start-group -lm -lc -lgcc -Wl,–end-group -nostartfiles -Wl,-e_PowerON_Reset -Wl,-M=TestGUNRXprintf.map’
rx-elf-gcc @”TestGUNRXprintf.elf.in”
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-closer.o): In function `_close_r’:
(.text._close_r+0x10): warning: _close is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-fstatr.o): In function `_fstat_r’:
(.text._fstat_r+0x12): warning: _fstat is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-isattyr.o): In function `_isatty_r’:
(.text._isatty_r+0x10): warning: _isatty is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-lseekr.o): In function `_lseek_r’:
(.text._lseek_r+0x14): warning: _lseek is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-readr.o): In function `_read_r’:
(.text._read_r+0x14): warning: _read is not implemented and will always fail
c:/renesas/gcc/redhat/gnurx-elf/8.3.0.202004/rx-elf/rx-elf/bin/../lib/gcc/rx-elf/8.3.0.202004-GNURX/../../../../rx-elf/lib/rxv2\libc.a(lib_a-writer.o): In function `_write_r’:
(.text._write_r+0x14): warning: _write is not implemented and will always fail
rx-elf-objcopy “TestGUNRXprintf.elf” -O srec -I elf32-rx-be-ns “TestGUNRXprintf.mot”
rx-elf-size –format=berkeley “TestGUNRXprintf.elf”
text data bss dec hex filename
23520 2596 64 26180 6644 TestGUNRXprintf.elf
Best regards,
NoMaY
Dear Frank Kjul Larsen,
We have investigated the issue and we see similar behavior for -O0 and -O3. Please let us know if we missed anything. We used the latest e2 studio and the same RX toolchain version (2020.04).
Without implementing the functions write, read, lseek, isatty, fstat, and close we get warnings (as expected) for each of them, both using -O3 and -O0:
However, if we add our own write function, we do not get a warning for the write function anymore (which is correct), both when using -O3 and -O0.
int write(int file, char* ptr, int len) {
(void)file; return 0;
}
int main(void) {
printf("OK"); return 0;
}
Please note that the write function we used does not have a leading underscore, which is where we believe lies the root cause of your problem.
Let us know if we can be of any more help, or if you are still experiencing a different behavior for -O0 and -O3.
__
Best regards,
The GNU Tools Team
Hello moderators,
First of all, I’m sorry for moderators that I did flag mistakenly when I reply to Flank’s answer to my answer. Always I’m confused how to reply to answer…
Hello Frank,
By the way, in my memory, assert() is a keypoint to understand why such functions are necessary in case of newlib.
As you know, other than MCU world, assert() will kill the process of the program if assert fails. Therefore newlib’s assert() needs functions such as kill(), getpid(), etc. Unfortunately if assert() is used unexpectedly in newlib, even if MCU world, such functions are required.
That is my understanding as of today. And now, as you wonder, I wonder why -O0 doesn’t need such functions. I will try to check newlib source code which are provided in GNURX installer package.
Best regards,
NoMaY
Hello Frank,
Is this the first time that you use -O3(or maybe -O2, etc)? In my memory, not only 202004 but also earlier version of GNURX needs something like stab functions (in other words, empty functions you said) to link newlib’s printf() (and moreover, sprintf()/sscanf(), in my memory) successfully.
Of course, I know that this reply isn’t an answer about weak reference you said, but I understood for a long time that I had to add such functions to use newlib’s printf(). I thought that it is the newlib’s way.
Best regards,
NoMaY