Huge binary freestanding / STM32 (Zig 0.14.0)

In my current embedded Zig/C blinky program (98% C code), the compiled binary output has become significantly larger since the Zig 0.14.0 release.
Normally, I override the C flag with -Og to keep the binary size reasonable, but even with this flag, the resulting program is much larger than before.

Compilation Test (Zig 0.14.0)

Programs available in my repository (Commit f0e18c5 on main branch).

Build command: zig build --release=off|safe|small

Program Debug (-O0) Debug (-Og) Safe Small
blinky 104680 52312 6944 5248
blinky_freertos (error) (1) 249688 28992 18088
blinky_picolibc 80708 52136 8156 6532

Error (1) blinky_freertos: Fails to fit in device memory.

error: ld.lld: section '.bss' will not fit in region 'RAM': overflowed by 2212 bytes  
error: ld.lld: section '._user_heap_stack' will not fit in region 'RAM': overflowed by 3752 bytes  

Previous Behavior (Zig 0.14.0-dev.3089)

When I wrote the picolibc topic, binary sizes were more closer between releases mode:

Mode newlib picolibc
Debug 29056 25140
ReleaseSafe 29480 25436
ReleaseSmall 26504 23012

Note: Binaries were slightly larger in ReleaseSafe and ReleaseSmall due to additional libc components.

Question

Could I be missing something in my build.zig configuration since Zig 0.14.0?

It looks like extra debug data, since release modes got smaller.
Have you inspected the binaries? Maybe look at the sizes of individual sections.
It’s possible zig is not passing along -Og anymore, or it is now using the flag that generates extra debug data (I forgot the name of the flag).

The -Og flag is passed. Here is a log with --verbose-cc for the blinky example:

zig build --release=off --verbose-cc
install
└─ run /opt/softs/xpack-arm-none-eabi-gcc-14.2.1-1.1/bin/arm-none-eabi-size
   └─ zig build-exe blinky.elf Debug thumb-freestanding-eabihf failure
error: zig clang /blinky/Core/Src/stm32l4xx_it.c --no-default-config -fno-caret-diagnostics -target thumbv7em-unknown-unknown-eabihf -mthumb -mabi=aapcs -mfloat-abi=hard -fno-PIC -gdwarf-4 -gdwarf32 -flto=full -MD -MV -MF /blinky/.zig-cache/tmp/9dce247a5145b243-stm32l4xx_it.o.d -ffreestanding -fno-omit-frame-pointer -fno-stack-protector -fbuiltin -ffunction-sections -fdata-sections -fasynchronous-unwind-tables -nostdinc -isystem /opt/softs/zig-linux-x86_64-0.14.0/lib/include -fno-spell-checking -Xclang -target-cpu -Xclang cortex-m4 -Xclang -target-feature -Xclang -32bit -Xclang -target-feature -Xclang -8msecext -Xclang -target-feature -Xclang -aapcs-frame-chain -Xclang -target-feature -Xclang -aclass -Xclang -target-feature -Xclang -acquire-release -Xclang -target-feature -Xclang -aes -Xclang -target-feature -Xclang -atomics-32 -Xclang -target-feature -Xclang -avoid-movs-shop -Xclang -target-feature -Xclang -avoid-partial-cpsr -Xclang -target-feature -Xclang -bf16 -Xclang -target-feature -Xclang -big-endian-instructions -Xclang -target-feature -Xclang -cde -Xclang -target-feature -Xclang -cdecp0 -Xclang -target-feature -Xclang -cdecp1 -Xclang -target-feature -Xclang -cdecp2 -Xclang -target-feature -Xclang -cdecp3 -Xclang -target-feature -Xclang -cdecp4 -Xclang -target-feature -Xclang -cdecp5 -Xclang -target-feature -Xclang -cdecp6 -Xclang -target-feature -Xclang -cdecp7 -Xclang -target-feature -Xclang -cheap-predicable-cpsr -Xclang -target-feature -Xclang -clrbhb -Xclang -target-feature -Xclang -crc -Xclang -target-feature -Xclang -crypto -Xclang -target-feature -Xclang -d32 -Xclang -target-feature -Xclang +db -Xclang -target-feature -Xclang -dfb -Xclang -target-feature -Xclang -disable-postra-scheduler -Xclang -target-feature -Xclang -dont-widen-vmovs -Xclang -target-feature -Xclang -dotprod -Xclang -target-feature -Xclang +dsp -Xclang -target-feature -Xclang -execute-only -Xclang -target-feature -Xclang -expand-fp-mlx -Xclang -target-feature -Xclang -fix-cmse-cve-2021-35465 -Xclang -target-feature -Xclang -fix-cortex-a57-aes-1742098 -Xclang -target-feature -Xclang +fp16 -Xclang -target-feature -Xclang -fp16fml -Xclang -target-feature -Xclang -fp64 -Xclang -target-feature -Xclang -fp-armv8 -Xclang -target-feature -Xclang -fp-armv8d16 -Xclang -target-feature -Xclang -fp-armv8d16sp -Xclang -target-feature -Xclang -fp-armv8sp -Xclang -target-feature -Xclang -fpao -Xclang -target-feature -Xclang +fpregs -Xclang -target-feature -Xclang -fpregs16 -Xclang -target-feature -Xclang -fpregs64 -Xclang -target-feature -Xclang -fullfp16 -Xclang -target-feature -Xclang -fuse-aes -Xclang -target-feature -Xclang -fuse-literals -Xclang -target-feature -Xclang -harden-sls-blr -Xclang -target-feature -Xclang -harden-sls-nocomdat -Xclang -target-feature -Xclang -harden-sls-retbr -Xclang -target-feature -Xclang +v4t -Xclang -target-feature -Xclang +v5t -Xclang -target-feature -Xclang +v5te -Xclang -target-feature -Xclang +v6 -Xclang -target-feature -Xclang +v6k -Xclang -target-feature -Xclang +v6m -Xclang -target-feature -Xclang +v6t2 -Xclang -target-feature -Xclang +v7 -Xclang -target-feature -Xclang +v7clrex -Xclang -target-feature -Xclang -v8 -Xclang -target-feature -Xclang -v8.1a -Xclang -target-feature -Xclang -v8.1m.main -Xclang -target-feature -Xclang -v8.2a -Xclang -target-feature -Xclang -v8.3a -Xclang -target-feature -Xclang -v8.4a -Xclang -target-feature -Xclang -v8.5a -Xclang -target-feature -Xclang -v8.6a -Xclang -target-feature -Xclang -v8.7a -Xclang -target-feature -Xclang -v8.8a -Xclang -target-feature -Xclang -v8.9a -Xclang -target-feature -Xclang +v8m -Xclang -target-feature -Xclang -v8m.main -Xclang -target-feature -Xclang -v9.1a -Xclang -target-feature -Xclang -v9.2a -Xclang -target-feature -Xclang -v9.3a -Xclang -target-feature -Xclang -v9.4a -Xclang -target-feature -Xclang -v9.5a -Xclang -target-feature -Xclang -v9a -Xclang -target-feature -Xclang +hwdiv -Xclang -target-feature -Xclang -hwdiv-arm -Xclang -target-feature -Xclang -i8mm -Xclang -target-feature -Xclang -iwmmxt -Xclang -target-feature -Xclang -iwmmxt2 -Xclang -target-feature -Xclang -lob -Xclang -target-feature -Xclang -long-calls -Xclang -target-feature -Xclang +loop-align -Xclang -target-feature -Xclang +mclass -Xclang -target-feature -Xclang -mp -Xclang -target-feature -Xclang -muxed-units -Xclang -target-feature -Xclang -mve -Xclang -target-feature -Xclang -mve1beat -Xclang -target-feature -Xclang -mve2beat -Xclang -target-feature -Xclang -mve4beat -Xclang -target-feature -Xclang -mve.fp -Xclang -target-feature -Xclang -nacl-trap -Xclang -target-feature -Xclang -neon -Xclang -target-feature -Xclang -neon-fpmovs -Xclang -target-feature -Xclang -neonfp -Xclang -target-feature -Xclang +no-branch-predictor -Xclang -target-feature -Xclang -no-bti-at-return-twice -Xclang -target-feature -Xclang -no-movt -Xclang -target-feature -Xclang -no-neg-immediates -Xclang -target-feature -Xclang +noarm -Xclang -target-feature -Xclang -nonpipelined-vfp -Xclang -target-feature -Xclang -pacbti -Xclang -target-feature -Xclang -perfmon -Xclang -target-feature -Xclang -prefer-ishst -Xclang -target-feature -Xclang -prefer-vmovsr -Xclang -target-feature -Xclang -prof-unpr -Xclang -target-feature -Xclang -ras -Xclang -target-feature -Xclang -rclass -Xclang -target-feature -Xclang -read-tp-tpidrprw -Xclang -target-feature -Xclang -read-tp-tpidruro -Xclang -target-feature -Xclang -read-tp-tpidrurw -Xclang -target-feature -Xclang -reserve-r9 -Xclang -target-feature -Xclang -ret-addr-stack -Xclang -target-feature -Xclang -sb -Xclang -target-feature -Xclang -sha2 -Xclang -target-feature -Xclang -slow-fp-brcc -Xclang -target-feature -Xclang -slow-load-D-subreg -Xclang -target-feature -Xclang -slow-odd-reg -Xclang -target-feature -Xclang -slow-vdup32 -Xclang -target-feature -Xclang -slow-vgetlni32 -Xclang -target-feature -Xclang +slowfpvfmx -Xclang -target-feature -Xclang +slowfpvmlx -Xclang -target-feature -Xclang -splat-vfp-neon -Xclang -target-feature -Xclang -strict-align -Xclang -target-feature -Xclang +thumb2 -Xclang -target-feature -Xclang +thumb-mode -Xclang -target-feature -Xclang -trustzone -Xclang -target-feature -Xclang -use-mipipeliner -Xclang -target-feature -Xclang +use-misched -Xclang -target-feature -Xclang -armv4 -Xclang -target-feature -Xclang -armv4t -Xclang -target-feature -Xclang -armv5t -Xclang -target-feature -Xclang -armv5te -Xclang -target-feature -Xclang -armv5tej -Xclang -target-feature -Xclang -armv6 -Xclang -target-feature -Xclang -armv6j -Xclang -target-feature -Xclang -armv6k -Xclang -target-feature -Xclang -armv6kz -Xclang -target-feature -Xclang -armv6-m -Xclang -target-feature -Xclang -armv6s-m -Xclang -target-feature -Xclang -armv6t2 -Xclang -target-feature -Xclang -armv7-a -Xclang -target-feature -Xclang +armv7e-m -Xclang -target-feature -Xclang -armv7-m -Xclang -target-feature -Xclang -armv7-r -Xclang -target-feature -Xclang -armv7ve -Xclang -target-feature -Xclang -armv8.1-a -Xclang -target-feature -Xclang -armv8.1-m.main -Xclang -target-feature -Xclang -armv8.2-a -Xclang -target-feature -Xclang -armv8.3-a -Xclang -target-feature -Xclang -armv8.4-a -Xclang -target-feature -Xclang -armv8.5-a -Xclang -target-feature -Xclang -armv8.6-a -Xclang -target-feature -Xclang -armv8.7-a -Xclang -target-feature -Xclang -armv8.8-a -Xclang -target-feature -Xclang -armv8.9-a -Xclang -target-feature -Xclang -armv8-a -Xclang -target-feature -Xclang -armv8-m.base -Xclang -target-feature -Xclang -armv8-m.main -Xclang -target-feature -Xclang -armv8-r -Xclang -target-feature -Xclang -armv9.1-a -Xclang -target-feature -Xclang -armv9.2-a -Xclang -target-feature -Xclang -armv9.3-a -Xclang -target-feature -Xclang -armv9.4-a -Xclang -target-feature -Xclang -armv9.5-a -Xclang -target-feature -Xclang -armv9-a -Xclang -target-feature -Xclang -vfp2 -Xclang -target-feature -Xclang +vfp2sp -Xclang -target-feature -Xclang -vfp3 -Xclang -target-feature -Xclang -vfp3d16 -Xclang -target-feature -Xclang +vfp3d16sp -Xclang -target-feature -Xclang -vfp3sp -Xclang -target-feature -Xclang -vfp4 -Xclang -target-feature -Xclang -vfp4d16 -Xclang -target-feature -Xclang +vfp4d16sp -Xclang -target-feature -Xclang -vfp4sp -Xclang -target-feature -Xclang -virtualization -Xclang -target-feature -Xclang -vldn-align -Xclang -target-feature -Xclang -vmlx-forwarding -Xclang -target-feature -Xclang -vmlx-hazards -Xclang -target-feature -Xclang -wide-stride-vfp -Xclang -target-feature -Xclang -xscale -Xclang -target-feature -Xclang -zcz -fsanitize=undefined -fno-sanitize=vptr -fno-sanitize=function -D_DEBUG -O0 -isystem /opt/softs/xpack-arm-none-eabi-gcc-14.2.1-1.1/arm-none-eabi/include -I /blinky/Drivers/STM32L4xx_HAL_Driver/Inc -I /blinky/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy -I /blinky/Drivers/CMSIS/Device/ST/STM32L4xx/Include -I /blinky/Drivers/CMSIS/Include -I /blinky/Core/Inc -DUSE_HAL_DRIVER= -DSTM32L476xx= -Og -std=gnu17 -Wall -Wextra -c -o /blinky/.zig-cache/tmp/9dce247a5145b243-stm32l4xx_it.o --serialize-diagnostics /blinky/.zig-cache/tmp/9dce247a5145b243-stm32l4xx_it.o.diag
...
zig clang /blinky/Core/Src/stm32l4xx_hal_msp.c --no-default-config -fno-caret-diagnostics -target thumbv7em-unknown-unknown-eabihf -mthumb -mabi=aapcs -mfloat-abi=hard -fno-PIC -gdwarf-4 -gdwarf32 -flto=full -MD -MV -MF /blinky/.zig-cache/tmp/c7054f54cc9ab453-stm32l4xx_hal_msp.o.d -ffreestanding -fno-omit-frame-pointer -fno-stack-protector -fbuiltin -ffunction-sections -fdata-sections -fasynchronous-unwind-tables -nostdinc -isystem /opt/softs/zig-linux-x86_64-0.14.0/lib/include -fno-spell-checking -Xclang -target-cpu -Xclang cortex-m4 -Xclang -target-feature -Xclang -32bit -Xclang -target-feature -Xclang -8msecext -Xclang -target-feature -Xclang -aapcs-frame-chain -Xclang -target-feature -Xclang -aclass -Xclang -target-feature -Xclang -acquire-release -Xclang -target-feature -Xclang -aes -Xclang -target-feature -Xclang -atomics-32 -Xclang -target-feature -Xclang -avoid-movs-shop -Xclang -target-feature -Xclang -avoid-partial-cpsr -Xclang -target-feature -Xclang -bf16 -Xclang -target-feature -Xclang -big-endian-instructions -Xclang -target-feature -Xclang -cde -Xclang -target-feature -Xclang -cdecp0 -Xclang -target-feature -Xclang -cdecp1 -Xclang -target-feature -Xclang -cdecp2 -Xclang -target-feature -Xclang -cdecp3 -Xclang -target-feature -Xclang -cdecp4 -Xclang -target-feature -Xclang -cdecp5 -Xclang -target-feature -Xclang -cdecp6 -Xclang -target-feature -Xclang -cdecp7 -Xclang -target-feature -Xclang -cheap-predicable-cpsr -Xclang -target-feature -Xclang -clrbhb -Xclang -target-feature -Xclang -crc -Xclang -target-feature -Xclang -crypto -Xclang -target-feature -Xclang -d32 -Xclang -target-feature -Xclang +db -Xclang -target-feature -Xclang -dfb -Xclang -target-feature -Xclang -disable-postra-scheduler -Xclang -target-feature -Xclang -dont-widen-vmovs -Xclang -target-feature -Xclang -dotprod -Xclang -target-feature -Xclang +dsp -Xclang -target-feature -Xclang -execute-only -Xclang -target-feature -Xclang -expand-fp-mlx -Xclang -target-feature -Xclang -fix-cmse-cve-2021-35465 -Xclang -target-feature -Xclang -fix-cortex-a57-aes-1742098 -Xclang -target-feature -Xclang +fp16 -Xclang -target-feature -Xclang -fp16fml -Xclang -target-feature -Xclang -fp64 -Xclang -target-feature -Xclang -fp-armv8 -Xclang -target-feature -Xclang -fp-armv8d16 -Xclang -target-feature -Xclang -fp-armv8d16sp -Xclang -target-feature -Xclang -fp-armv8sp -Xclang -target-feature -Xclang -fpao -Xclang -target-feature -Xclang +fpregs -Xclang -target-feature -Xclang -fpregs16 -Xclang -target-feature -Xclang -fpregs64 -Xclang -target-feature -Xclang -fullfp16 -Xclang -target-feature -Xclang -fuse-aes -Xclang -target-feature -Xclang -fuse-literals -Xclang -target-feature -Xclang -harden-sls-blr -Xclang -target-feature -Xclang -harden-sls-nocomdat -Xclang -target-feature -Xclang -harden-sls-retbr -Xclang -target-feature -Xclang +v4t -Xclang -target-feature -Xclang +v5t -Xclang -target-feature -Xclang +v5te -Xclang -target-feature -Xclang +v6 -Xclang -target-feature -Xclang +v6k -Xclang -target-feature -Xclang +v6m -Xclang -target-feature -Xclang +v6t2 -Xclang -target-feature -Xclang +v7 -Xclang -target-feature -Xclang +v7clrex -Xclang -target-feature -Xclang -v8 -Xclang -target-feature -Xclang -v8.1a -Xclang -target-feature -Xclang -v8.1m.main -Xclang -target-feature -Xclang -v8.2a -Xclang -target-feature -Xclang -v8.3a -Xclang -target-feature -Xclang -v8.4a -Xclang -target-feature -Xclang -v8.5a -Xclang -target-feature -Xclang -v8.6a -Xclang -target-feature -Xclang -v8.7a -Xclang -target-feature -Xclang -v8.8a -Xclang -target-feature -Xclang -v8.9a -Xclang -target-feature -Xclang +v8m -Xclang -target-feature -Xclang -v8m.main -Xclang -target-feature -Xclang -v9.1a -Xclang -target-feature -Xclang -v9.2a -Xclang -target-feature -Xclang -v9.3a -Xclang -target-feature -Xclang -v9.4a -Xclang -target-feature -Xclang -v9.5a -Xclang -target-feature -Xclang -v9a -Xclang -target-feature -Xclang +hwdiv -Xclang -target-feature -Xclang -hwdiv-arm -Xclang -target-feature -Xclang -i8mm -Xclang -target-feature -Xclang -iwmmxt -Xclang -target-feature -Xclang -iwmmxt2 -Xclang -target-feature -Xclang -lob -Xclang -target-feature -Xclang -long-calls -Xclang -target-feature -Xclang +loop-align -Xclang -target-feature -Xclang +mclass -Xclang -target-feature -Xclang -mp -Xclang -target-feature -Xclang -muxed-units -Xclang -target-feature -Xclang -mve -Xclang -target-feature -Xclang -mve1beat -Xclang -target-feature -Xclang -mve2beat -Xclang -target-feature -Xclang -mve4beat -Xclang -target-feature -Xclang -mve.fp -Xclang -target-feature -Xclang -nacl-trap -Xclang -target-feature -Xclang -neon -Xclang -target-feature -Xclang -neon-fpmovs -Xclang -target-feature -Xclang -neonfp -Xclang -target-feature -Xclang +no-branch-predictor -Xclang -target-feature -Xclang -no-bti-at-return-twice -Xclang -target-feature -Xclang -no-movt -Xclang -target-feature -Xclang -no-neg-immediates -Xclang -target-feature -Xclang +noarm -Xclang -target-feature -Xclang -nonpipelined-vfp -Xclang -target-feature -Xclang -pacbti -Xclang -target-feature -Xclang -perfmon -Xclang -target-feature -Xclang -prefer-ishst -Xclang -target-feature -Xclang -prefer-vmovsr -Xclang -target-feature -Xclang -prof-unpr -Xclang -target-feature -Xclang -ras -Xclang -target-feature -Xclang -rclass -Xclang -target-feature -Xclang -read-tp-tpidrprw -Xclang -target-feature -Xclang -read-tp-tpidruro -Xclang -target-feature -Xclang -read-tp-tpidrurw -Xclang -target-feature -Xclang -reserve-r9 -Xclang -target-feature -Xclang -ret-addr-stack -Xclang -target-feature -Xclang -sb -Xclang -target-feature -Xclang -sha2 -Xclang -target-feature -Xclang -slow-fp-brcc -Xclang -target-feature -Xclang -slow-load-D-subreg -Xclang -target-feature -Xclang -slow-odd-reg -Xclang -target-feature -Xclang -slow-vdup32 -Xclang -target-feature -Xclang -slow-vgetlni32 -Xclang -target-feature -Xclang +slowfpvfmx -Xclang -target-feature -Xclang +slowfpvmlx -Xclang -target-feature -Xclang -splat-vfp-neon -Xclang -target-feature -Xclang -strict-align -Xclang -target-feature -Xclang +thumb2 -Xclang -target-feature -Xclang +thumb-mode -Xclang -target-feature -Xclang -trustzone -Xclang -target-feature -Xclang -use-mipipeliner -Xclang -target-feature -Xclang +use-misched -Xclang -target-feature -Xclang -armv4 -Xclang -target-feature -Xclang -armv4t -Xclang -target-feature -Xclang -armv5t -Xclang -target-feature -Xclang -armv5te -Xclang -target-feature -Xclang -armv5tej -Xclang -target-feature -Xclang -armv6 -Xclang -target-feature -Xclang -armv6j -Xclang -target-feature -Xclang -armv6k -Xclang -target-feature -Xclang -armv6kz -Xclang -target-feature -Xclang -armv6-m -Xclang -target-feature -Xclang -armv6s-m -Xclang -target-feature -Xclang -armv6t2 -Xclang -target-feature -Xclang -armv7-a -Xclang -target-feature -Xclang +armv7e-m -Xclang -target-feature -Xclang -armv7-m -Xclang -target-feature -Xclang -armv7-r -Xclang -target-feature -Xclang -armv7ve -Xclang -target-feature -Xclang -armv8.1-a -Xclang -target-feature -Xclang -armv8.1-m.main -Xclang -target-feature -Xclang -armv8.2-a -Xclang -target-feature -Xclang -armv8.3-a -Xclang -target-feature -Xclang -armv8.4-a -Xclang -target-feature -Xclang -armv8.5-a -Xclang -target-feature -Xclang -armv8.6-a -Xclang -target-feature -Xclang -armv8.7-a -Xclang -target-feature -Xclang -armv8.8-a -Xclang -target-feature -Xclang -armv8.9-a -Xclang -target-feature -Xclang -armv8-a -Xclang -target-feature -Xclang -armv8-m.base -Xclang -target-feature -Xclang -armv8-m.main -Xclang -target-feature -Xclang -armv8-r -Xclang -target-feature -Xclang -armv9.1-a -Xclang -target-feature -Xclang -armv9.2-a -Xclang -target-feature -Xclang -armv9.3-a -Xclang -target-feature -Xclang -armv9.4-a -Xclang -target-feature -Xclang -armv9.5-a -Xclang -target-feature -Xclang -armv9-a -Xclang -target-feature -Xclang -vfp2 -Xclang -target-feature -Xclang +vfp2sp -Xclang -target-feature -Xclang -vfp3 -Xclang -target-feature -Xclang -vfp3d16 -Xclang -target-feature -Xclang +vfp3d16sp -Xclang -target-feature -Xclang -vfp3sp -Xclang -target-feature -Xclang -vfp4 -Xclang -target-feature -Xclang -vfp4d16 -Xclang -target-feature -Xclang +vfp4d16sp -Xclang -target-feature -Xclang -vfp4sp -Xclang -target-feature -Xclang -virtualization -Xclang -target-feature -Xclang -vldn-align -Xclang -target-feature -Xclang -vmlx-forwarding -Xclang -target-feature -Xclang -vmlx-hazards -Xclang -target-feature -Xclang -wide-stride-vfp -Xclang -target-feature -Xclang -xscale -Xclang -target-feature -Xclang -zcz -fsanitize=undefined -fno-sanitize=vptr -fno-sanitize=function -D_DEBUG -O0 -isystem /opt/softs/xpack-arm-none-eabi-gcc-14.2.1-1.1/arm-none-eabi/include -I /blinky/Drivers/STM32L4xx_HAL_Driver/Inc -I /blinky/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy -I /blinky/Drivers/CMSIS/Device/ST/STM32L4xx/Include -I /blinky/Drivers/CMSIS/Include -I /blinky/Core/Inc -DUSE_HAL_DRIVER= -DSTM32L476xx= -Og -std=gnu17 -Wall -Wextra -c -o /blinky/.zig-cache/tmp/c7054f54cc9ab453-stm32l4xx_hal_msp.o --serialize-diagnostics /blinky/.zig-cache/tmp/c7054f54cc9ab453-stm32l4xx_hal_msp.o.diag
clang -x c --no-default-config -fno-caret-diagnostics -target thumbv7em-unknown-unknown-eabihf -mthumb -mabi=aapcs -mfloat-abi=hard -fno-PIC -gdwarf-4 -gdwarf32 -flto=full -MD -MV -MF /blinky/.zig-cache/o/e7da661d47b5ec8b3f3a1c319a406889/cimport.h.d -ffreestanding -fno-omit-frame-pointer -fno-stack-protector -fbuiltin -ffunction-sections -fdata-sections -fasynchronous-unwind-tables -nostdinc -isystem /opt/softs/zig-linux-x86_64-0.14.0/lib/include -fno-spell-checking -Xclang -target-cpu -Xclang cortex-m4 -Xclang -target-feature -Xclang -32bit -Xclang -target-feature -Xclang -8msecext -Xclang -target-feature -Xclang -aapcs-frame-chain -Xclang -target-feature -Xclang -aclass -Xclang -target-feature -Xclang -acquire-release -Xclang -target-feature -Xclang -aes -Xclang -target-feature -Xclang -atomics-32 -Xclang -target-feature -Xclang -avoid-movs-shop -Xclang -target-feature -Xclang -avoid-partial-cpsr -Xclang -target-feature -Xclang -bf16 -Xclang -target-feature -Xclang -big-endian-instructions -Xclang -target-feature -Xclang -cde -Xclang -target-feature -Xclang -cdecp0 -Xclang -target-feature -Xclang -cdecp1 -Xclang -target-feature -Xclang -cdecp2 -Xclang -target-feature -Xclang -cdecp3 -Xclang -target-feature -Xclang -cdecp4 -Xclang -target-feature -Xclang -cdecp5 -Xclang -target-feature -Xclang -cdecp6 -Xclang -target-feature -Xclang -cdecp7 -Xclang -target-feature -Xclang -cheap-predicable-cpsr -Xclang -target-feature -Xclang -clrbhb -Xclang -target-feature -Xclang -crc -Xclang -target-feature -Xclang -crypto -Xclang -target-feature -Xclang -d32 -Xclang -target-feature -Xclang +db -Xclang -target-feature -Xclang -dfb -Xclang -target-feature -Xclang -disable-postra-scheduler -Xclang -target-feature -Xclang -dont-widen-vmovs -Xclang -target-feature -Xclang -dotprod -Xclang -target-feature -Xclang +dsp -Xclang -target-feature -Xclang -execute-only -Xclang -target-feature -Xclang -expand-fp-mlx -Xclang -target-feature -Xclang -fix-cmse-cve-2021-35465 -Xclang -target-feature -Xclang -fix-cortex-a57-aes-1742098 -Xclang -target-feature -Xclang +fp16 -Xclang -target-feature -Xclang -fp16fml -Xclang -target-feature -Xclang -fp64 -Xclang -target-feature -Xclang -fp-armv8 -Xclang -target-feature -Xclang -fp-armv8d16 -Xclang -target-feature -Xclang -fp-armv8d16sp -Xclang -target-feature -Xclang -fp-armv8sp -Xclang -target-feature -Xclang -fpao -Xclang -target-feature -Xclang +fpregs -Xclang -target-feature -Xclang -fpregs16 -Xclang -target-feature -Xclang -fpregs64 -Xclang -target-feature -Xclang -fullfp16 -Xclang -target-feature -Xclang -fuse-aes -Xclang -target-feature -Xclang -fuse-literals -Xclang -target-feature -Xclang -harden-sls-blr -Xclang -target-feature -Xclang -harden-sls-nocomdat -Xclang -target-feature -Xclang -harden-sls-retbr -Xclang -target-feature -Xclang +v4t -Xclang -target-feature -Xclang +v5t -Xclang -target-feature -Xclang +v5te -Xclang -target-feature -Xclang +v6 -Xclang -target-feature -Xclang +v6k -Xclang -target-feature -Xclang +v6m -Xclang -target-feature -Xclang +v6t2 -Xclang -target-feature -Xclang +v7 -Xclang -target-feature -Xclang +v7clrex -Xclang -target-feature -Xclang -v8 -Xclang -target-feature -Xclang -v8.1a -Xclang -target-feature -Xclang -v8.1m.main -Xclang -target-feature -Xclang -v8.2a -Xclang -target-feature -Xclang -v8.3a -Xclang -target-feature -Xclang -v8.4a -Xclang -target-feature -Xclang -v8.5a -Xclang -target-feature -Xclang -v8.6a -Xclang -target-feature -Xclang -v8.7a -Xclang -target-feature -Xclang -v8.8a -Xclang -target-feature -Xclang -v8.9a -Xclang -target-feature -Xclang +v8m -Xclang -target-feature -Xclang -v8m.main -Xclang -target-feature -Xclang -v9.1a -Xclang -target-feature -Xclang -v9.2a -Xclang -target-feature -Xclang -v9.3a -Xclang -target-feature -Xclang -v9.4a -Xclang -target-feature -Xclang -v9.5a -Xclang -target-feature -Xclang -v9a -Xclang -target-feature -Xclang +hwdiv -Xclang -target-feature -Xclang -hwdiv-arm -Xclang -target-feature -Xclang -i8mm -Xclang -target-feature -Xclang -iwmmxt -Xclang -target-feature -Xclang -iwmmxt2 -Xclang -target-feature -Xclang -lob -Xclang -target-feature -Xclang -long-calls -Xclang -target-feature -Xclang +loop-align -Xclang -target-feature -Xclang +mclass -Xclang -target-feature -Xclang -mp -Xclang -target-feature -Xclang -muxed-units -Xclang -target-feature -Xclang -mve -Xclang -target-feature -Xclang -mve1beat -Xclang -target-feature -Xclang -mve2beat -Xclang -target-feature -Xclang -mve4beat -Xclang -target-feature -Xclang -mve.fp -Xclang -target-feature -Xclang -nacl-trap -Xclang -target-feature -Xclang -neon -Xclang -target-feature -Xclang -neon-fpmovs -Xclang -target-feature -Xclang -neonfp -Xclang -target-feature -Xclang +no-branch-predictor -Xclang -target-feature -Xclang -no-bti-at-return-twice -Xclang -target-feature -Xclang -no-movt -Xclang -target-feature -Xclang -no-neg-immediates -Xclang -target-feature -Xclang +noarm -Xclang -target-feature -Xclang -nonpipelined-vfp -Xclang -target-feature -Xclang -pacbti -Xclang -target-feature -Xclang -perfmon -Xclang -target-feature -Xclang -prefer-ishst -Xclang -target-feature -Xclang -prefer-vmovsr -Xclang -target-feature -Xclang -prof-unpr -Xclang -target-feature -Xclang -ras -Xclang -target-feature -Xclang -rclass -Xclang -target-feature -Xclang -read-tp-tpidrprw -Xclang -target-feature -Xclang -read-tp-tpidruro -Xclang -target-feature -Xclang -read-tp-tpidrurw -Xclang -target-feature -Xclang -reserve-r9 -Xclang -target-feature -Xclang -ret-addr-stack -Xclang -target-feature -Xclang -sb -Xclang -target-feature -Xclang -sha2 -Xclang -target-feature -Xclang -slow-fp-brcc -Xclang -target-feature -Xclang -slow-load-D-subreg -Xclang -target-feature -Xclang -slow-odd-reg -Xclang -target-feature -Xclang -slow-vdup32 -Xclang -target-feature -Xclang -slow-vgetlni32 -Xclang -target-feature -Xclang +slowfpvfmx -Xclang -target-feature -Xclang +slowfpvmlx -Xclang -target-feature -Xclang -splat-vfp-neon -Xclang -target-feature -Xclang -strict-align -Xclang -target-feature -Xclang +thumb2 -Xclang -target-feature -Xclang +thumb-mode -Xclang -target-feature -Xclang -trustzone -Xclang -target-feature -Xclang -use-mipipeliner -Xclang -target-feature -Xclang +use-misched -Xclang -target-feature -Xclang -armv4 -Xclang -target-feature -Xclang -armv4t -Xclang -target-feature -Xclang -armv5t -Xclang -target-feature -Xclang -armv5te -Xclang -target-feature -Xclang -armv5tej -Xclang -target-feature -Xclang -armv6 -Xclang -target-feature -Xclang -armv6j -Xclang -target-feature -Xclang -armv6k -Xclang -target-feature -Xclang -armv6kz -Xclang -target-feature -Xclang -armv6-m -Xclang -target-feature -Xclang -armv6s-m -Xclang -target-feature -Xclang -armv6t2 -Xclang -target-feature -Xclang -armv7-a -Xclang -target-feature -Xclang +armv7e-m -Xclang -target-feature -Xclang -armv7-m -Xclang -target-feature -Xclang -armv7-r -Xclang -target-feature -Xclang -armv7ve -Xclang -target-feature -Xclang -armv8.1-a -Xclang -target-feature -Xclang -armv8.1-m.main -Xclang -target-feature -Xclang -armv8.2-a -Xclang -target-feature -Xclang -armv8.3-a -Xclang -target-feature -Xclang -armv8.4-a -Xclang -target-feature -Xclang -armv8.5-a -Xclang -target-feature -Xclang -armv8.6-a -Xclang -target-feature -Xclang -armv8.7-a -Xclang -target-feature -Xclang -armv8.8-a -Xclang -target-feature -Xclang -armv8.9-a -Xclang -target-feature -Xclang -armv8-a -Xclang -target-feature -Xclang -armv8-m.base -Xclang -target-feature -Xclang -armv8-m.main -Xclang -target-feature -Xclang -armv8-r -Xclang -target-feature -Xclang -armv9.1-a -Xclang -target-feature -Xclang -armv9.2-a -Xclang -target-feature -Xclang -armv9.3-a -Xclang -target-feature -Xclang -armv9.4-a -Xclang -target-feature -Xclang -armv9.5-a -Xclang -target-feature -Xclang -armv9-a -Xclang -target-feature -Xclang -vfp2 -Xclang -target-feature -Xclang +vfp2sp -Xclang -target-feature -Xclang -vfp3 -Xclang -target-feature -Xclang -vfp3d16 -Xclang -target-feature -Xclang +vfp3d16sp -Xclang -target-feature -Xclang -vfp3sp -Xclang -target-feature -Xclang -vfp4 -Xclang -target-feature -Xclang -vfp4d16 -Xclang -target-feature -Xclang +vfp4d16sp -Xclang -target-feature -Xclang -vfp4sp -Xclang -target-feature -Xclang -virtualization -Xclang -target-feature -Xclang -vldn-align -Xclang -target-feature -Xclang -vmlx-forwarding -Xclang -target-feature -Xclang -vmlx-hazards -Xclang -target-feature -Xclang -wide-stride-vfp -Xclang -target-feature -Xclang -xscale -Xclang -target-feature -Xclang -zcz -fsanitize=undefined -fno-sanitize=vptr -fno-sanitize=function -D_DEBUG -O0 -isystem /opt/softs/xpack-arm-none-eabi-gcc-14.2.1-1.1/arm-none-eabi/include -I /blinky/Drivers/STM32L4xx_HAL_Driver/Inc -I /blinky/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy -I /blinky/Drivers/CMSIS/Device/ST/STM32L4xx/Include -I /blinky/Drivers/CMSIS/Include -I /blinky/Core/Inc -DUSE_HAL_DRIVER= -DSTM32L476xx= -Xclang -detailed-preprocessing-record /blinky/.zig-cache/o/e7da661d47b5ec8b3f3a1c319a406889/cimport.h
  • Sections (arm-none-eabi-readelf -S zig-out/bin/blinky.elf) :
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .isr_vector       PROGBITS        08000000 010000 000188 00   A  0   0  1
  [ 2] .text             PROGBITS        08000188 010188 009318 00  AX  0   0  4
  [ 3] .rodata           PROGBITS        080094a0 0194a0 002e58 00 AMS  0   0 16
  [ 4] .ARM.extab        PROGBITS        0800c2f8 01c2f8 000220 00   A  0   0  4
  [ 5] .eh_frame_hdr     PROGBITS        0800c518 01c518 00000c 00   A  0   0  4
  [ 6] .ARM              ARM_EXIDX       0800c524 01c524 000214 00  AL  2   0  4
  [ 7] .preinit_array    PROGBITS        0800c738 01c738 000000 00   A  0   0  1
  [ 8] .init_array       INIT_ARRAY      0800c738 01c738 000008 04  WA  0   0  4
  [ 9] .fini_array       FINI_ARRAY      0800c740 01c740 000008 04  WA  0   0  4
  [10] .data             PROGBITS        20000000 020000 000508 00  WA  0   0 16
  [11] .bss              NOBITS          20000508 020508 00027c 00  WA  0   0  4
  [12] ._user_heap_stack NOBITS          20000784 020508 000604 00  WA  0   0  1
  [13] .ARM.attributes   ARM_ATTRIBUTES  00000000 020508 000020 00      0   0  1
  [14] .comment          PROGBITS        00000000 020528 00010a 01  MS  0   0  1
  [15] .debug_info       PROGBITS        00000000 020632 037887 00      0   0  1
  [16] .debug_abbrev     PROGBITS        00000000 057eb9 000d3d 00      0   0  1
  [17] .debug_aranges    PROGBITS        00000000 058bf6 000028 00      0   0  1
  [18] .debug_ranges     PROGBITS        00000000 058c1e 00f818 00      0   0  1
  [19] .debug_line       PROGBITS        00000000 068436 023613 00      0   0  1
  [20] .debug_loc        PROGBITS        00000000 08ba49 07a0e0 00      0   0  1
  [21] .debug_str        PROGBITS        00000000 105b29 00eacd 01  MS  0   0  1
  [22] .debug_pubnames   PROGBITS        00000000 1145f6 0042ed 00      0   0  1
  [23] .debug_pubtypes   PROGBITS        00000000 1188e3 001688 00      0   0  1
  [24] .debug_frame      PROGBITS        00000000 119f6c 003e40 00      0   0  4
  [25] .symtab           SYMTAB          00000000 11ddac 001e50 10     27 335  4
  [26] .shstrtab         STRTAB          00000000 11fbfc 000136 00      0   0  1
  [27] .strtab           STRTAB          00000000 11fd32 001ff5 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), y (purecode), p (processor specific)
  • Symbol size (arm-none-eabi-nm -r -t dec --size-sort zig-out/bin/blinky.elf)
00014886 t ubsan_rt.Value.format__anon_6451
00002848 r fmt.format_float.FLOAT128_POW5_SPLIT
00002848 r fmt.format_float.FLOAT128_POW5_INV_SPLIT
00001798 t fmt.format_float.mul_128_256_shift
00001718 t fmt.formatBuf__anon_6387
00001696 t fmt.format_float.writeDecimal__anon_7923
00001684 t MX_USART2_UART_Init
00001248 r .Lanon.be54888b7f04376941d55ec9b1f8fa9e.153
00001232 r .Lanon.be54888b7f04376941d55ec9b1f8fa9e.152
00001202 W __udivmoddi4
00000896 r fmt.format_float.FLOAT128_POW5_TABLE
00000856 T main
00000854 t HAL_GPIO_Init
00000646 t debug.panicExtra__anon_2354
00000536 t main.myPanic
00000468 t debug.panicExtra__anon_2397
00000444 t __ubsan_handle_shift_out_of_bounds
00000398 t debug.panicExtra__anon_2366
00000386 t debug.panicExtra__anon_2407
00000356 t debug.panicExtra__anon_6317
00000356 t debug.panicExtra__anon_2700
00000356 t debug.panicExtra__anon_2325
00000356 t debug.panicExtra__anon_2317
00000356 t debug.panicExtra__anon_2312
00000344 t debug.panicExtra__anon_2278
00000344 t debug.panicExtra__anon_2197
00000330 t debug.panicExtra__anon_2299
00000330 t debug.panicExtra__anon_2291
00000318 t debug.panicExtra__anon_2344
00000316 t debug.panicExtra__anon_2381
00000312 B __sf
00000290 t debug.panicExtra__anon_6489
00000290 t debug.panicExtra__anon_2359
00000278 t HAL_UART_Transmit
00000268 t UART_EndRxTransfer
00000252 W __extenddftf2
00000248 t fmt.formatInt__anon_7159
00000248 t debug.panicExtra__anon_2284
00000248 t debug.panicExtra__anon_2203
00000234 t HAL_RCC_GetSysClockFreq
00000234 W __aeabi_memcpy
00000220 t __ubsan_handle_type_mismatch_v1
00000214 W __extendsftf2
00000201 r __anon_7609
...

It seems that for my blinky program, float formatting and ubsan account for the largest portion of the binary.

A trade-off to reduce debug binary size is to disable the C sanitizer in each module.

 .sanitize_c = if (optimization == .Debug) false else true,
Program Debug
blinky 6816
blinky_freertos 34176
blinky_picolibc 8044

But now I can do undefined behavior (like division by zero) and keep running! :smiley:

Yup, I encountered this as well and ended up tracking it down to mostly being related to the C UBSAN code added in 0.14.0. Adding:

exe.root_module.sanitize_c = false;

To your build.zig should hopefully remove a lot of this extra code. For freestanding systems sanitize_c = false should probably be the default behavior, I’ll check in the Zig embedded discord if someone’s made an issue for it yet since this has been a topic of discussion there.

If I disable sanitize_c for other release profiles like safe, this C code will execute without trapping errors:

    uint32_t a = 0;
    uint32_t b = 45 / a;
    char test[20];
    sprintf(test,"%d",b);

However, if sanitize_c is enabled, the code triggers an hardfault and HardFault_Handler function is called.
However, I don’t know why my custom Panic function isn’t called in this case. It was being called when UBSan was enabled in debug mode.

Interesting! I need to look more into the ubsan code, I honestly didn’t really think it would even work without an OS.

One thing to note is make sure you can differentiate a Zig panic from a processor hard fault. In your divide by zero case, that can cause a hard fault at the processor level depending on which processor you’re using /if you’ve configured it to hard fault on a divide by zero. But it can also cause a Zig panic before it would hit the actual instruction that would generate a processor hard fault.

Maybe step through with a debugger and see what the code path is with and without ubsan on?

I did a little digging into this behavior:

With UBsan enabled in debug mode (-Og), I got the following assembly code:

  • Debug (-Og) + sanitize_c = true : In this case, Zig calls divRemHandler and panics.

  • Safe (-O2) + sanitize_c = true : In this case, the compiler also triggers an intentional hardfault with the udf instruction.


When I disable UBsan (sanitize_c = false), the compiler simply optimizes out the code and it runs without issues.

But If I compile with -O0, the code also runs. If I want a hardware hardfault, I need to explicitly enable it with:

SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
  • Debug (-O0) + sanitize_c = false : It will hardfault at udiv instruction

Nice good work! Super interesting about the undefined instruction the compiler put in in the sanitization case. I’ll have to dig more into how the UB sanitizer works exactly.

2 Likes