From cb69bb9caaf55b499fd573482f5039d52859872d Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Thu, 19 Mar 2026 23:41:49 +0100 Subject: [PATCH 1/7] Fix embedded images built with the clang compiler --- arch.mk | 5 ++++- test-app/Makefile | 14 +++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/arch.mk b/arch.mk index a9de6d9e0f..18d82ebf72 100644 --- a/arch.mk +++ b/arch.mk @@ -1282,7 +1282,9 @@ ifeq ($(USE_CLANG),1) CLANG_NEWLIB_INCLUDE?=$(abspath $(dir $(CLANG_LIBC_A))/../include) CC=$(CLANG_DRIVER) - LD=$(CLANG_DRIVER) + # Keep clang for compilation, but use the GNU linker driver so linker-script + # LMAs for RAM sections are preserved and objcopy does not emit sparse images. + LD=$(CLANG_GCC_NAME) AS=$(CLANG_DRIVER) AR=$(CROSS_COMPILE)ar OBJCOPY?=$(CROSS_COMPILE)objcopy @@ -1290,6 +1292,7 @@ ifeq ($(USE_CLANG),1) CFLAGS+=-isystem $(CLANG_NEWLIB_INCLUDE) CFLAGS+=-DWOLFSSL_NO_ATOMIC -DWOLFSSL_NO_ATOMICS + CFLAGS+=-Wno-unknown-attributes -Wno-error=unknown-attributes LDFLAGS+=-nostdlib endif diff --git a/test-app/Makefile b/test-app/Makefile index 1d0b1e5ad5..2d8bdbdd91 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -102,6 +102,14 @@ LDFLAGS+=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -nostartfiles # Setup default objcopy flags OBJCOPY_FLAGS+=--gap-fill $(FILL_BYTE) +OBJCOPY_IMAGE_FLAGS:= + +ifeq ($(USE_CLANG),1) + # Clang-built ARM ELFs can keep RAM sections as loadable segments, and raw + # objcopy output then expands the flash-to-RAM gap into a huge sparse image. + # The app image only needs the flash-backed output sections. + OBJCOPY_IMAGE_FLAGS+=-j .text -j .edidx +endif ifeq ($(DEBUG_UART),1) CFLAGS+=-DDEBUG_UART @@ -899,15 +907,15 @@ delta-extra-data:LDFLAGS=-Wl,-Map=image.map image.bin: image.elf @echo "\t[BIN] $@" - $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@ + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $(OBJCOPY_IMAGE_FLAGS) -O binary $^ $@ image.hex: image.elf @echo "\t[HEX] $@" - $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O ihex $^ $@ + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $(OBJCOPY_IMAGE_FLAGS) -O ihex $^ $@ image.srec: image.elf @echo "\t[SREC] $@" - $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O srec $^ $@ + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $(OBJCOPY_IMAGE_FLAGS) -O srec $^ $@ APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFSSL)/%, \ $(WOLFSSL_LOCAL_OBJDIR)/%, $(APP_OBJS)) From 6fbacaa42c375bfd71f552a1409ecc9b90a481b6 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 23 Mar 2026 17:25:17 +0100 Subject: [PATCH 2/7] Added explicit discard list for clang compiler --- arch.mk | 2 ++ hal/clang-discard.ld | 14 ++++++++++++++ hal/stm32l4.ld | 1 + test-app/Makefile | 1 + 4 files changed, 18 insertions(+) create mode 100644 hal/clang-discard.ld diff --git a/arch.mk b/arch.mk index 18d82ebf72..34fcce3d3f 100644 --- a/arch.mk +++ b/arch.mk @@ -1293,7 +1293,9 @@ ifeq ($(USE_CLANG),1) CFLAGS+=-isystem $(CLANG_NEWLIB_INCLUDE) CFLAGS+=-DWOLFSSL_NO_ATOMIC -DWOLFSSL_NO_ATOMICS CFLAGS+=-Wno-unknown-attributes -Wno-error=unknown-attributes + CFLAGS+=-fno-unwind-tables -fno-asynchronous-unwind-tables LDFLAGS+=-nostdlib + LSCRIPT_FLAGS+=-T hal/clang-discard.ld endif ifeq ($(USE_GCC),1) diff --git a/hal/clang-discard.ld b/hal/clang-discard.ld new file mode 100644 index 0000000000..1217dddbc5 --- /dev/null +++ b/hal/clang-discard.ld @@ -0,0 +1,14 @@ +SECTIONS +{ + /DISCARD/ : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.eh_frame* .gcc_except_table*) + *(.preinit_array*) + *(.init_array*) + *(.fini_array*) + *(.ctors*) + *(.dtors*) + *(.jcr*) + } +} diff --git a/hal/stm32l4.ld b/hal/stm32l4.ld index 822f01174d..933985c17e 100644 --- a/hal/stm32l4.ld +++ b/hal/stm32l4.ld @@ -15,6 +15,7 @@ SECTIONS . = ALIGN(4); _end_text = .; } > FLASH + .edidx : { . = ALIGN(4); diff --git a/test-app/Makefile b/test-app/Makefile index 2d8bdbdd91..64a4f3a5f3 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -109,6 +109,7 @@ ifeq ($(USE_CLANG),1) # objcopy output then expands the flash-to-RAM gap into a huge sparse image. # The app image only needs the flash-backed output sections. OBJCOPY_IMAGE_FLAGS+=-j .text -j .edidx + LDFLAGS+=-T ../hal/clang-discard.ld endif ifeq ($(DEBUG_UART),1) From 40d8c2e306ce9d2ce06da0141d99798537d4e85d Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 23 Mar 2026 17:33:56 +0100 Subject: [PATCH 3/7] Added clang pass for arm build tests --- .github/workflows/test-build.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 42f15f68ac..86051fb26a 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -77,6 +77,11 @@ jobs: run: | sudo apt-get install -y gcc-arm-none-eabi gcc-aarch64-linux-gnu gcc-powerpc-linux-gnu gnu-efi + - name: Install Clang + if: inputs.arch == 'arm' || inputs.arch == 'ARM' + run: | + sudo apt-get install -y clang + - name: make clean run: | make distclean @@ -92,3 +97,11 @@ jobs: - name: Build wolfboot run: | make ${{inputs.make-args}} + + - name: Rebuild wolfboot with Clang + if: inputs.arch == 'arm' || inputs.arch == 'ARM' + run: | + make distclean + cp ${{inputs.config-file}} .config + make -C tools/keytools && make -C tools/bin-assemble + make USE_CLANG=1 USE_GCC=0 ${{inputs.make-args}} From aa4917c079b8daea04e73de086669ff27783b792 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 23 Mar 2026 18:33:46 +0100 Subject: [PATCH 4/7] Discard volatile sections during app objcopy when compiling with clang --- Makefile | 9 ++++++++- test-app/Makefile | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 321322a9fe..05b0c8aac6 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ DEBUG_UART?=0 LIBS= SIGN_ALG= OBJCOPY_FLAGS= +OBJCOPY_BIN_FLAGS= BIG_ENDIAN?=0 USE_CLANG?=0 ifeq ($(USE_CLANG),1) @@ -196,6 +197,12 @@ ifeq ($(USE_GCC_HEADLESS),1) LSCRIPT_FLAGS+=-T $(LSCRIPT) OBJCOPY_FLAGS+=--gap-fill $(FILL_BYTE) endif + +ifeq ($(USE_CLANG),1) + ifeq ($(ARCH),ARM) + OBJCOPY_BIN_FLAGS+=-j .text -j .ramcode -j .keystore -j .edidx -j .gnu.sgstubs + endif +endif ifeq ($(TARGET),ti_hercules) LSCRIPT_FLAGS+=--run_linker $(LSCRIPT) endif @@ -322,7 +329,7 @@ wolfboot.efi: wolfboot.elf wolfboot.bin: wolfboot.elf @echo "\t[BIN] $@" - $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@ + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $(OBJCOPY_BIN_FLAGS) -O binary $^ $@ @echo @echo "\t[SIZE]" $(Q)$(SIZE) wolfboot.elf diff --git a/test-app/Makefile b/test-app/Makefile index 64a4f3a5f3..9c0ebbbe66 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -88,7 +88,7 @@ endif include ../arch.mk ifeq ($(USE_CLANG),1) - APP_OBJS+=../src/string.o + APP_NEEDS_STRING:=1 endif # Optional alias for clearer TZ PSA selection in app builds. @@ -114,6 +114,10 @@ endif ifeq ($(DEBUG_UART),1) CFLAGS+=-DDEBUG_UART + APP_NEEDS_STRING:=1 +endif + +ifeq ($(APP_NEEDS_STRING),1) APP_OBJS+=../src/string.o endif From 4cbf90ca67ca0d12563bd92bcdde3e84131c9554 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 23 Mar 2026 19:09:42 +0100 Subject: [PATCH 5/7] Fix stdlib in clang, limit test to a few targets --- .github/workflows/test-build.yml | 24 ++++++++++++++++++++++-- arch.mk | 1 - test-app/Makefile | 5 ++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 86051fb26a..65a3786b4b 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -78,7 +78,17 @@ jobs: sudo apt-get install -y gcc-arm-none-eabi gcc-aarch64-linux-gnu gcc-powerpc-linux-gnu gnu-efi - name: Install Clang - if: inputs.arch == 'arm' || inputs.arch == 'ARM' + if: | + inputs.config-file == './config/examples/stm32c0.config' || + inputs.config-file == './config/examples/stm32c0-rsa2048.config' || + inputs.config-file == './config/examples/stm32h5.config' || + inputs.config-file == './config/examples/stm32h5-dualbank.config' || + inputs.config-file == './config/examples/stm32h7.config' || + inputs.config-file == './config/examples/stm32h7-octospi.config' || + inputs.config-file == './config/examples/stm32u5.config' || + inputs.config-file == './config/examples/stm32u5-wolfcrypt-tz.config' || + inputs.config-file == './config/examples/stm32u5-nonsecure-dualbank.config' || + inputs.config-file == 'config/examples/stm32n567.config' run: | sudo apt-get install -y clang @@ -99,7 +109,17 @@ jobs: make ${{inputs.make-args}} - name: Rebuild wolfboot with Clang - if: inputs.arch == 'arm' || inputs.arch == 'ARM' + if: | + inputs.config-file == './config/examples/stm32c0.config' || + inputs.config-file == './config/examples/stm32c0-rsa2048.config' || + inputs.config-file == './config/examples/stm32h5.config' || + inputs.config-file == './config/examples/stm32h5-dualbank.config' || + inputs.config-file == './config/examples/stm32h7.config' || + inputs.config-file == './config/examples/stm32h7-octospi.config' || + inputs.config-file == './config/examples/stm32u5.config' || + inputs.config-file == './config/examples/stm32u5-wolfcrypt-tz.config' || + inputs.config-file == './config/examples/stm32u5-nonsecure-dualbank.config' || + inputs.config-file == 'config/examples/stm32n567.config' run: | make distclean cp ${{inputs.config-file}} .config diff --git a/arch.mk b/arch.mk index 34fcce3d3f..71dc2d554f 100644 --- a/arch.mk +++ b/arch.mk @@ -1294,7 +1294,6 @@ ifeq ($(USE_CLANG),1) CFLAGS+=-DWOLFSSL_NO_ATOMIC -DWOLFSSL_NO_ATOMICS CFLAGS+=-Wno-unknown-attributes -Wno-error=unknown-attributes CFLAGS+=-fno-unwind-tables -fno-asynchronous-unwind-tables - LDFLAGS+=-nostdlib LSCRIPT_FLAGS+=-T hal/clang-discard.ld endif diff --git a/test-app/Makefile b/test-app/Makefile index 9c0ebbbe66..3d723f3b4f 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -301,7 +301,10 @@ ifeq ($(TZEN),1) endif endif endif - CFLAGS+=-DWOLFBOOT_SECURE_CALLS -Wstack-usage=19184 + CFLAGS+=-DWOLFBOOT_SECURE_CALLS + ifneq ($(USE_CLANG),1) + CFLAGS+=-Wstack-usage=19184 + endif LDFLAGS+=--specs=nosys.specs -u _printf_float endif ifeq ($(WOLFCRYPT_TZ_PSA),1) From c1c130d7276fba509e4f943207f88b35b4e12df2 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 23 Mar 2026 19:41:33 +0100 Subject: [PATCH 6/7] Exclude stm32c0 (too small for clang) and stm32h5 (no ARMORED support) --- .github/workflows/test-build.yml | 8 -------- arch.mk | 2 +- options.mk | 3 +++ test-app/Makefile | 5 ++--- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 65a3786b4b..2a208cbf0c 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -79,10 +79,6 @@ jobs: - name: Install Clang if: | - inputs.config-file == './config/examples/stm32c0.config' || - inputs.config-file == './config/examples/stm32c0-rsa2048.config' || - inputs.config-file == './config/examples/stm32h5.config' || - inputs.config-file == './config/examples/stm32h5-dualbank.config' || inputs.config-file == './config/examples/stm32h7.config' || inputs.config-file == './config/examples/stm32h7-octospi.config' || inputs.config-file == './config/examples/stm32u5.config' || @@ -110,10 +106,6 @@ jobs: - name: Rebuild wolfboot with Clang if: | - inputs.config-file == './config/examples/stm32c0.config' || - inputs.config-file == './config/examples/stm32c0-rsa2048.config' || - inputs.config-file == './config/examples/stm32h5.config' || - inputs.config-file == './config/examples/stm32h5-dualbank.config' || inputs.config-file == './config/examples/stm32h7.config' || inputs.config-file == './config/examples/stm32h7-octospi.config' || inputs.config-file == './config/examples/stm32u5.config' || diff --git a/arch.mk b/arch.mk index 71dc2d554f..91d0e5ef96 100644 --- a/arch.mk +++ b/arch.mk @@ -1294,7 +1294,7 @@ ifeq ($(USE_CLANG),1) CFLAGS+=-DWOLFSSL_NO_ATOMIC -DWOLFSSL_NO_ATOMICS CFLAGS+=-Wno-unknown-attributes -Wno-error=unknown-attributes CFLAGS+=-fno-unwind-tables -fno-asynchronous-unwind-tables - LSCRIPT_FLAGS+=-T hal/clang-discard.ld + LSCRIPT_FLAGS+=-T $(abspath $(WOLFBOOT_ROOT)/hal/clang-discard.ld) endif ifeq ($(USE_GCC),1) diff --git a/options.mk b/options.mk index 814e1d9987..89a66ca225 100644 --- a/options.mk +++ b/options.mk @@ -12,6 +12,9 @@ ifeq ($(USE_CLANG),1) ifeq ($(USE_GCC),1) $(error USE_CLANG=1 is incompatible with USE_GCC=1; set USE_GCC=0) endif + ifeq ($(ARMORED),1) + $(error USE_CLANG=1 requires ARMORED=0) + endif endif # Support for Built-in ROT into OTP flash memory diff --git a/test-app/Makefile b/test-app/Makefile index 3d723f3b4f..1e5ff387c4 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -109,7 +109,6 @@ ifeq ($(USE_CLANG),1) # objcopy output then expands the flash-to-RAM gap into a huge sparse image. # The app image only needs the flash-backed output sections. OBJCOPY_IMAGE_FLAGS+=-j .text -j .edidx - LDFLAGS+=-T ../hal/clang-discard.ld endif ifeq ($(DEBUG_UART),1) @@ -933,7 +932,7 @@ ifeq ($(ELF_FLASH_SCATTER),1) SQUASHELF_TOOL = ../tools/squashelf/squashelf image-orig.elf: $(APP_OBJS) $(LSCRIPT) @echo "\t[LD] $@" - $(Q)$(LD) $(LDFLAGS) $(APP_OBJS) $(LIBS) $(OUTPUT_FLAG) $@ + $(Q)$(LD) $(LDFLAGS) $(LSCRIPT_FLAGS) $(APP_OBJS) $(LIBS) $(OUTPUT_FLAG) $@ image.elf: image-orig.elf @echo "\t[SQUASHELF] $@" @@ -942,7 +941,7 @@ else # Default behavior when ELF_FLASH_SCATTER is not set image.elf: $(APP_OBJS) $(LSCRIPT) @echo "\t[LD] $@" - $(Q)$(LD) $(LDFLAGS) $(APP_OBJS) $(LIBS) $(OUTPUT_FLAG) $@ + $(Q)$(LD) $(LDFLAGS) $(LSCRIPT_FLAGS) $(APP_OBJS) $(LIBS) $(OUTPUT_FLAG) $@ endif standalone: image.bin From 88ee56a18a43ef43e48b7648c50ff4d4ea7f6862 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 23 Mar 2026 19:44:43 +0100 Subject: [PATCH 7/7] Concentrate flags for clang in arch.mk --- Makefile | 2 +- arch.mk | 6 ++++++ test-app/Makefile | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 05b0c8aac6..87565445d9 100644 --- a/Makefile +++ b/Makefile @@ -200,7 +200,7 @@ endif ifeq ($(USE_CLANG),1) ifeq ($(ARCH),ARM) - OBJCOPY_BIN_FLAGS+=-j .text -j .ramcode -j .keystore -j .edidx -j .gnu.sgstubs + OBJCOPY_BIN_FLAGS+=$(CLANG_ARM_OBJCOPY_FLASH_FLAGS_BOOT) endif endif ifeq ($(TARGET),ti_hercules) diff --git a/arch.mk b/arch.mk index 91d0e5ef96..96ad331542 100644 --- a/arch.mk +++ b/arch.mk @@ -1295,6 +1295,12 @@ ifeq ($(USE_CLANG),1) CFLAGS+=-Wno-unknown-attributes -Wno-error=unknown-attributes CFLAGS+=-fno-unwind-tables -fno-asynchronous-unwind-tables LSCRIPT_FLAGS+=-T $(abspath $(WOLFBOOT_ROOT)/hal/clang-discard.ld) + # Keep Clang-specific raw-image section selection in one place. Both the + # bootloader and test-app need flash-backed sections only, but the bootloader + # has a few extra output sections that must be preserved. + CLANG_ARM_OBJCOPY_FLASH_FLAGS_BASE:=-j .text -j .edidx + CLANG_ARM_OBJCOPY_FLASH_FLAGS_BOOT:=$(CLANG_ARM_OBJCOPY_FLASH_FLAGS_BASE) -j .ramcode -j .keystore -j .gnu.sgstubs + CLANG_ARM_OBJCOPY_FLASH_FLAGS_APP:=$(CLANG_ARM_OBJCOPY_FLASH_FLAGS_BASE) endif ifeq ($(USE_GCC),1) diff --git a/test-app/Makefile b/test-app/Makefile index 1e5ff387c4..f45408204b 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -108,7 +108,7 @@ ifeq ($(USE_CLANG),1) # Clang-built ARM ELFs can keep RAM sections as loadable segments, and raw # objcopy output then expands the flash-to-RAM gap into a huge sparse image. # The app image only needs the flash-backed output sections. - OBJCOPY_IMAGE_FLAGS+=-j .text -j .edidx + OBJCOPY_IMAGE_FLAGS+=$(CLANG_ARM_OBJCOPY_FLASH_FLAGS_APP) endif ifeq ($(DEBUG_UART),1)