About -ffunction-sections -fdata-sections and --gc-sections options - gcc

In my ARM project, I use following to build os-less application binary:
arm-linux-gcc -Os -ffunction-sections -fdata-sections -o boot.o boot.S
arm-linux-gcc -Os -ffunction-sections -fdata-sections -o main.o main.c
arm-linux-ld -T link.lds --gc-sections -o target.bin boot.o main.o
These works fine. Because If I remove "-ffunction-sections", "-fdata-sections" and "--gc-sections" options, the target.bin file size will increase nearly twice..
But on the x86 platform, same method, I found that:
If I don't use those gcc and ld options, the output is normal, but the output file will be 0 byte if I use those options as arm platform.

-Os -ffunction-sections -fdata-sections and --gc-sections should work on x86 system. Are you sure your program and your linker script are suitable for x86 ? As your program is meant for bare-metal ARM, it probably does not have entry points for your x86 OS, and if there is no entry point, everything is garbaged by --gc-sections option.
BTW, your "question" actually enclose no question.

Related

GCC: include math.h function in bare-metal software on ARM (arm-none-eabi-gcc)

I am working on a bare-metal free standing software on a STM32H753. I'm not using neither the libc nor the crt.
Here is the link command line:
arm-none-eabi-gcc -T"xxx.ld" -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -ffreestanding -nostdlib -nostartfiles --specs=nosys.specs -Wl,--start-group -lc -lm -Wl,--end-group -Wl,-Map=xxx.map -o xxx.elf <list of .o>
Now I need to include math library since I am using sqrt function. i thought the link command line would be sufficient but I get a "sqrt undefined" error.
I tried to add the path to the libm.a: (also tried without -Wl)
arm-none-eabi-gcc -T"xxx.ld" -Wl,-L/opt/gcc-arm-none-eabi-10-2020-q4-major/arm-none-eabi/lib/ -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -ffreestanding -nostdlib -nostartfiles --specs=nosys.specs -Wl,--start-group -lc -lm -Wl,--end-group -Wl,-Map=build_uP1/base_gen_uP1.map -o build_uP1/base_gen_uP1.elf <list of .o>
But I still get the same error.
I don't understand what options to choose to link with the correct library
Sorry for this self answer but I think I 've found the solution.
my first mistake is that the library must be put at the end of the command line. the order of arguments does matter.
then there are many versions of libm.a in the gcc install so I had to pick the right one
The following line is working:
arm-none-eabi-gcc -T"xxx.ld" -L/opt/gcc-arm-none-eabi-10-2020-q4-major/arm-none-eabi/lib/thumb/v7+fp/hard/ -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -ffreestanding -nostdlib -nostartfiles --specs=nosys.specs -Wl,-Map=xxx.map -o xxx.elf <list of .o> -lm -lc
I've noticed that one symbol and some data from libc.a are needed: __errno, and impure_data

Stripping unused library functions / dead code from a static executable

I'm compiling code for an ARM Cortex-M0 mcu with GCC arm-none-eabi-g++ (4.8.3).
All is fine, but I noticed that when I include and use any function from cstdlib, all functions from that file are included as well. How to get rid of them?
I'm calling malloc() and free() only, but the resulting ELF has system() and isatty() machine code as well.
The mcu has only 32kB flash, so ~0.7kB ballast matters, especially if this keeps happening for other headers.
Right now I use -ffunction-sections -fdata-sections for compiling and -Wl,--gc-sections -Wl,--static while linking, as follows:
arm-none-eabi-g++ -c --std=c++11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
-ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
-DTARGET=LPC11xx -fno-builtin -flto -fno-exceptions -o main.o main.cpp
arm-none-eabi-gcc -c --std=c11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
-ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
-DTARGET=LPC11xx -fno-builtin -flto -o core_cm0.o lpc1xxx/nxp/core_cm0.c
arm-none-eabi-gcc -nostartfiles -mcpu=cortex-m0 -mthumb -Wl,--gc-sections -flto \
-Os -Wl,--static -T lpc1xxx/memory.ld -o firmware.elf main.o core_cm0.o \
libaeabi-cortexm0/libaeabi-cortexm0.a LPC11xx_handlers.o LPC1xxx_startup.o
Edit: Warning: The -flto flag in my example is wrong – somehow it discards interrupt routines.
The result is that when I do arm-none-eabi-objdump -t firmware.elf, I get among others:
00000fbc g F .text 0000002c _isatty
00001798 g F .text 00000018 fclose
00000e4c g F .text 00000030 _kill
00000e7c g F .text 00000018 _exit
00000fe8 g F .text 00000050 _system
These functions are clearly redundant (and quite useless on mcu at all), yet GCC keeps them in the executable. There are no calls to them, these symbols are not referenced anywhere. It's effectively dead code.
How to get rid of them? Some extra compiler/linker flags?
Edit:
Minimal code to reproduce my problem:
#include <cstdlib>
int main(){
[[gnu::unused]] volatile void * x = malloc(1);
return 0;
}
Command used to compile that:
arm-none-eabi-g++ --std=c++11 -Os -Wall -mthumb -ffunction-sections
-fdata-sections -fmessage-length=0 -mcpu=cortex-m0 -fno-builtin -flto
-fno-exceptions -Wl,--static -Wl,--gc-sections -o main.elf main.cpp
And the main.elf file still has all stdlib bloat.
Using -ffunction-sections is the right thing here, but the issue is that the object file that provides malloc and free is built without it (either LPC11xx_handlers.o, LPC1xxx_startup.o or some of the object files within libaeabi-cortexm0.a). In that case, the linker can only include the whole object file (or with -Wl,--gc-sections, the whole section) that contain functions you need.
The layout of functions in object files and sections is the only thing that actually matters, not which function is defined in the same header as another function.
So to fix your issue, rebuild your standard library files with -ffunction-sections -fdata-sections.

Negate previous -D[efine] flag for GCC

Under GNUStep on Arch Linux, I'm running into an interesting error on a fresh install.
Using my build system I run
gcc `gnustep-config --debug-flags` [other command line args]
in order to build up the command line per the operating system's necessary flags.
This works fine under Ubuntu, but on Arch Linux I'm getting a rather random error:
/usr/include/features.h:328:4: error: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Werror=cpp]
Well, gnustep-config --debug-flags spits out the following:
-MMD -MP -D_FORTIFY_SOURCE=2 -DGNUSTEP -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGNUSTEP_BASE_LIBRARY=1 -fno-strict-aliasing -pthread -fPIC -g -DDEBUG -fno-omit-frame-pointer -Wall -DGSWARN -DGSDIAGNOSE -Wno-import -march=x86-64 -mtune=generic -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -fgnu-runtime -fconstant-string-class=NSConstantString -fexec-charset=UTF-8 -I. -I/home/qix/GNUstep/Library/Headers -I/usr/include -D_FORTIFY_SOURCE=2 -I/usr/include -I/usr/include -I/usr/include -I/usr/lib/libffi-3.1/include/ -I/usr/lib/libffi-3.1/include -I/usr/include/libxml2 -I/usr/include/p11-kit-1
As well, I wish not to have optimizations on my debug builds (and later on I even override GNUStep's -g parameter to -g2).
Is there a way to explicitly undefine -D_FORTIFY_SOURCE later on in the command line, after the call to gnustep-config?
For example, something like
gcc `gnustep-config --debug-flags` -U_FORTIFY_SOURCE ...
where the -U undefines the previously defined macro?
Something to mention; I have -Werror enabled on purpose, and I'd like to keep it.
For now, using sed to work around this works. It appears this is a known issue with _FORTIFY_SOURCE causing issues, and there isn't a straightforward fix.
`gnustep-config --debug-flags | sed 's/-D_FORTIFY_SOURCE=2//g'`

Bootloader issues due to GCC-4.7.0

This is a weird problem. I am having a custom bootloader for MIPS 34Kc processor which was consistently booting my target. This was compiled with GCC-4.2.4. Recently we had moved to GCC-4.7.0 and the bootloader is failing to boot the target all the time.
The optimizations are as below:
W_OPTS = -Wimplicit -Wformat -Werror
CC_OPTS = -c -O -mips32r2 $(W_OPTS) -fomit-frame-pointer -fno-pic -nostdinc -mno-abicalls
CC_OPTS_16 = -c -O -mips16 $(W_OPTS) -fomit-frame-pointer -fno-pic -nostdinc -mno-abicalls
CC_OPTS_A = $(CC_OPTS) -D_ASSEMBLER_
Any pointers to debug this issue would be helpful.

gcc and linking files with CFLAGS

I am trying to run program from the Learn C Hard Way book
I need to pass the library filename 'build/liblcthw.a' as the last parameter.
For eg :
Doesnt Work on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
Works on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/list_tests.c -o tests/list_tests build/liblcthw.a
How do I handle this in Makefile ? CFLAGS will only add it before the source filename and it doesnt work. How do I force CFALGS to add the library filename at the end of the command ?
CFLAGS are flags for the C compiler. Libraries typically go into a variable called LDLIBS. Set LDLIBS=build/liblcthw.a and see if that works.
The first invocation doesn't succeed because the order of sources and libraries in the command line is wrong. The correct order is source files, then object files, followed by static libraries followed by dynamic libraries.

Resources