Build: Add LLVM toolchain support for an521 only.
Support for other platforms will follow.
Signed-off-by: Anton Komlev <anton.komlev@arm.com>
Change-Id: Id036ecd78bf8e8909af30f78b2bfe5262b78c6b9
diff --git a/bl2/CMakeLists.txt b/bl2/CMakeLists.txt
index 63e6364..5e38af8 100644
--- a/bl2/CMakeLists.txt
+++ b/bl2/CMakeLists.txt
@@ -118,6 +118,7 @@
add_executable(bl2
src/flash_map.c
+ $<$<C_COMPILER_ID:Clang>:src/crt_exit.c>
$<$<BOOL:${DEFAULT_MCUBOOT_SECURITY_COUNTERS}>:src/security_cnt.c>
$<$<BOOL:${DEFAULT_MCUBOOT_FLASH_MAP}>:src/default_flash_map.c>
$<$<BOOL:${MCUBOOT_DATA_SHARING}>:src/shared_data.c>
@@ -158,6 +159,7 @@
$<$<C_COMPILER_ID:GNU>:-Wl,-Map=${CMAKE_BINARY_DIR}/bin/bl2.map>
$<$<C_COMPILER_ID:ARMClang>:--map>
$<$<C_COMPILER_ID:IAR>:--map\;${CMAKE_BINARY_DIR}/bin/bl2.map>
+ $<$<C_COMPILER_ID:Clang>:-lcrt0 -Wl,-Map=${CMAKE_BINARY_DIR}/bin/bl2.map>
${BL2_LINKER_CP_OPTION}
)
diff --git a/bl2/ext/mcuboot/CMakeLists.txt b/bl2/ext/mcuboot/CMakeLists.txt
index 425212c..4f05fce 100644
--- a/bl2/ext/mcuboot/CMakeLists.txt
+++ b/bl2/ext/mcuboot/CMakeLists.txt
@@ -169,6 +169,7 @@
$<$<C_COMPILER_ID:GNU>:-E\;-xc>
$<$<C_COMPILER_ID:ARMClang>:-E\;-xc>
$<$<C_COMPILER_ID:IAR>:--preprocess=ns\;$<TARGET_OBJECTS:signing_layout_s>>
+ $<$<C_COMPILER_ID:Clang>:-E\;-xc>
)
target_compile_definitions(signing_layout_s
PRIVATE
@@ -185,7 +186,6 @@
SOURCES tfm_s_signed.bin
)
add_custom_command(OUTPUT tfm_s_signed.bin
- DEPENDS $<TARGET_FILE_DIR:tfm_s>/tfm_s.bin
DEPENDS tfm_s_bin signing_layout_s
DEPENDS $<IF:$<BOOL:${MCUBOOT_GENERATE_SIGNING_KEYPAIR}>,generated_private_key,>
WORKING_DIRECTORY ${MCUBOOT_PATH}/scripts
@@ -222,6 +222,7 @@
$<$<C_COMPILER_ID:GNU>:-E\;-xc>
$<$<C_COMPILER_ID:ARMClang>:-E\;-xc>
$<$<C_COMPILER_ID:IAR>:--preprocess=ns\;$<TARGET_OBJECTS:signing_layout_ns>>
+ $<$<C_COMPILER_ID:Clang>:-E\;-xc>
)
target_compile_definitions(signing_layout_ns
PRIVATE
diff --git a/bl2/src/crt_exit.c b/bl2/src/crt_exit.c
new file mode 100644
index 0000000..39e742f
--- /dev/null
+++ b/bl2/src/crt_exit.c
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ */
+
+void _exit(void)
+{
+ while (1)
+ ;
+}
diff --git a/cmake/install.cmake b/cmake/install.cmake
index d98bef1..b2e2d69 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -263,6 +263,7 @@
install(FILES ${PLATFORM_DIR}/ns/toolchain_ns_GNUARM.cmake
${PLATFORM_DIR}/ns/toolchain_ns_ARMCLANG.cmake
${PLATFORM_DIR}/ns/toolchain_ns_IARARM.cmake
+ ${PLATFORM_DIR}/ns/toolchain_ns_LLVM.cmake
DESTINATION ${INSTALL_CMAKE_DIR})
install(FILES
diff --git a/cmake/spe-CMakeLists.cmake b/cmake/spe-CMakeLists.cmake
index 2c5323b..dab6115 100644
--- a/cmake/spe-CMakeLists.cmake
+++ b/cmake/spe-CMakeLists.cmake
@@ -169,7 +169,8 @@
SOURCES ${CMAKE_BINARY_DIR}/bin/${NS_TARGET_NAME}_signed.bin
)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${NS_TARGET_NAME}_signed.bin
- DEPENDS ${NS_TARGET_NAME}_bin $<TARGET_FILE_DIR:${NS_TARGET_NAME}>/${NS_TARGET_NAME}.bin
+ DEPENDS ${NS_TARGET_NAME}_bin
+ DEPENDS $<TARGET_FILE_DIR:${NS_TARGET_NAME}>/${NS_TARGET_NAME}.bin
DEPENDS $<IF:$<BOOL:${MCUBOOT_GENERATE_SIGNING_KEYPAIR}>,generated_private_key,>
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/layout_files/signing_layout_ns.o
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/scripts
@@ -201,7 +202,7 @@
# support
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/tfm_s_ns_signed.bin
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/tfm_s_signed.bin
- DEPENDS ${NS_TARGET_NAME}_signed_bin ${CMAKE_BINARY_DIR}/bin/${NS_TARGET_NAME}_signed.bin
+ DEPENDS ${CMAKE_BINARY_DIR}/bin/${NS_TARGET_NAME}_signed.bin
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/layout_files/signing_layout_s.o
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/scripts
diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt
index c6c7de3..4cc2b83 100644
--- a/platform/CMakeLists.txt
+++ b/platform/CMakeLists.txt
@@ -46,6 +46,7 @@
INTERFACE
"$<$<C_COMPILER_ID:GNU>:SHELL:-include ${CMSIS_OVERRIDE_HEADER}>"
"$<$<AND:$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>,$<C_COMPILER_ID:IAR>>:SHELL:--preinclude ${CMSIS_OVERRIDE_HEADER}>"
+ "$<$<C_COMPILER_ID:Clang>:SHELL:-include ${CMSIS_OVERRIDE_HEADER}>"
)
#========================= Platform Common interface ==========================#
diff --git a/platform/ext/common/generated_file_list.yaml b/platform/ext/common/generated_file_list.yaml
index eaafe30..0986c6a 100644
--- a/platform/ext/common/generated_file_list.yaml
+++ b/platform/ext/common/generated_file_list.yaml
@@ -47,5 +47,10 @@
"template": "platform/ext/common/iar/tfm_isolation_s.icf.template",
"output": "platform/ext/common/iar/tfm_isolation_s.icf"
},
+ {
+ "description": "isolation l1-l3 linker script",
+ "template": "platform/ext/common/llvm/tfm_isolation_s.ld.template",
+ "output": "platform/ext/common/llvm/tfm_isolation_s.ld"
+ }
]
}
diff --git a/platform/ext/common/llvm/tfm_common_bl2.ld b/platform/ext/common/llvm/tfm_common_bl2.ld
new file mode 100644
index 0000000..96f9695
--- /dev/null
+++ b/platform/ext/common/llvm/tfm_common_bl2.ld
@@ -0,0 +1,125 @@
+;/*
+; * Copyright (c) 2022-2024 Arm Limited. All rights reserved.
+; *
+; * Licensed under the Apache License, Version 2.0 (the "License");
+; * you may not use this file except in compliance with the License.
+; * You may obtain a copy of the License at
+; *
+; * http://www.apache.org/licenses/LICENSE-2.0
+; *
+; * Unless required by applicable law or agreed to in writing, software
+; * distributed under the License is distributed on an "AS IS" BASIS,
+; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; * See the License for the specific language governing permissions and
+; * limitations under the License.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 gcc_arm.ld
+; */
+
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+
+#include "region_defs.h"
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = BL2_CODE_START, LENGTH = BL2_CODE_SIZE
+ RAM (rwx) : ORIGIN = BL2_DATA_START, LENGTH = BL2_DATA_SIZE
+}
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ __vectors_start = .;
+ KEEP(*(.vectors))
+ __vectors_end = .;
+
+ *(.text*)
+ *(.rodata*)
+ } > FLASH
+
+#ifdef CODE_SHARING
+ /* The code sharing between bootloader and runtime firmware requires to
+ * share the global variables. Section size must be equal with
+ * SHARED_SYMBOL_AREA_SIZE defined in region_defs.h
+ */
+ .tfm_shared_symbols (NOLOAD) : ALIGN(4)
+ {
+ *(.data.mbedtls_calloc_func)
+ *(.data.mbedtls_free_func)
+ *(.data.mbedtls_exit)
+ *(.data.memset_func)
+ . = ALIGN(SHARED_SYMBOL_AREA_SIZE);
+ } > RAM AT > FLASH
+
+ ASSERT(SHARED_SYMBOL_AREA_SIZE % 4 == 0, "SHARED_SYMBOL_AREA_SIZE must be divisible by 4")
+#endif
+
+ .tfm_bl2_shared_data (NOLOAD) : ALIGN(32)
+ {
+ . += BOOT_TFM_SHARED_DATA_SIZE;
+ } > RAM
+ Image$$SHARED_DATA$$RW$$Base = ADDR(.tfm_bl2_shared_data);
+ Image$$SHARED_DATA$$RW$$Limit = ADDR(.tfm_bl2_shared_data) + SIZEOF(.tfm_bl2_shared_data);
+ /*
+ * Bootoader will clear region [Image$$ER_DATA$$Base - Image$$ARM_LIB_HEAP$$ZI$$Limit]
+ * It's important to keep .tfm_bl2_shared_data out of that region
+ */
+ .data : ALIGN(4)
+ {
+ *(.data*)
+ } > RAM AT > FLASH
+
+ .bss (NOLOAD) : ALIGN(4)
+ {
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ } > RAM
+ __bss_start = ADDR(.bss);
+ __bss_end = ADDR(.bss) + SIZEOF(.bss);
+ __bss_size = SIZEOF(.bss);
+
+ .msp_stack (NOLOAD) : ALIGN(32)
+ {
+ . += BL2_MSP_STACK_SIZE;
+ } > RAM
+ Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack) - 0x8;
+ __stack_seal = Image$$ARM_LIB_STACK$$ZI$$Limit;
+#else
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+ __stack = Image$$ARM_LIB_STACK$$ZI$$Limit;
+
+ .heap (NOLOAD): ALIGN(8)
+ {
+ . += BL2_HEAP_SIZE;
+ __tls_base = .; /* dummy. for picolib crt0 only */
+ __arm32_tls_tcb_offset = .; /* dummy. for picolib crt0 only */
+ } > RAM
+ __heap_start = ADDR(.heap);
+ __heap_end = ADDR(.heap) + SIZEOF(.heap);
+ __heap_size = SIZEOF(.heap);
+
+ /* Those 2 symbols defines the region for clearing on boot completion */
+ Image$$ER_DATA$$Base = ADDR(.data);
+ Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap);
+
+#ifdef CODE_SHARING
+ __data_start = ADDR(.tfm_shared_symbols);
+ __data_source = LOADADDR(.tfm_shared_symbols);
+ __data_size = SIZEOF(tfm_shared_symbols) + SIZEOF(tfm_bl2_shared_data) + SIZEOF(.data);
+#else /* CODE_SHARING */
+ __data_start = ADDR(.data);
+ __data_source = LOADADDR(.data);
+ __data_size = SIZEOF(.data);
+#endif /* CODE_SHARING */
+
+/* PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit); */
+}
diff --git a/platform/ext/common/llvm/tfm_common_ns.ldc b/platform/ext/common/llvm/tfm_common_ns.ldc
new file mode 100644
index 0000000..83c341e
--- /dev/null
+++ b/platform/ext/common/llvm/tfm_common_ns.ldc
@@ -0,0 +1,131 @@
+;/*
+; * Copyright (c) 2021-2024 Arm Limited. All rights reserved.
+; *
+; * Licensed under the Apache License, Version 2.0 (the "License");
+; * you may not use this file except in compliance with the License.
+; * You may obtain a copy of the License at
+; *
+; * http://www.apache.org/licenses/LICENSE-2.0
+; *
+; * Unless required by applicable law or agreed to in writing, software
+; * distributed under the License is distributed on an "AS IS" BASIS,
+; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; * See the License for the specific language governing permissions and
+; * limitations under the License.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 gcc_arm.ld
+; */
+
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+
+#include "region_defs.h"
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = NS_CODE_START, LENGTH = NS_CODE_SIZE
+ RAM (rwx) : ORIGIN = NS_DATA_START, LENGTH = NS_DATA_SIZE
+}
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ __vectors_start = .;
+ KEEP(*(.vectors))
+ __vectors_end = .;
+
+ *(.text*)
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ .data :
+ {
+ *(vtable)
+ *(.data*)
+ KEEP(*(.jcr*))
+ } > RAM AT > FLASH
+ __data_start = ADDR(.data);
+ __data_source = LOADADDR(.data);
+ __data_size = SIZEOF(.data);
+
+ .bss (NOLOAD): ALIGN(4)
+ {
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __tls_base = . ; /* to satisfy crt0 */
+; __arm32_tls_tcb_offset = . ; /* to satisfy crt0 */
+ } > RAM
+ __bss_start = ADDR(.bss);
+ __bss_size = SIZEOF(.bss);
+
+ .stack (NOLOAD): ALIGN(32)
+ {
+ . += NS_STACK_SIZE;
+ } > RAM
+ __stack_limit = ADDR(.stack);
+ __stack = ADDR(.stack) + SIZEOF(.stack);
+
+ .heap (NOLOAD): ALIGN(8)
+ {
+ . += NS_HEAP_SIZE;
+ } > RAM
+ __heap_start = ADDR(.heap);
+ __heap_end = ADDR(.heap) + SIZEOF(.heap);
+ __heap_size = SIZEOF(.heap);
+}
diff --git a/platform/ext/common/llvm/tfm_isolation_s.ld.template b/platform/ext/common/llvm/tfm_isolation_s.ld.template
new file mode 100644
index 0000000..dd34129
--- /dev/null
+++ b/platform/ext/common/llvm/tfm_isolation_s.ld.template
@@ -0,0 +1,574 @@
+;/*
+; * Copyright (c) 2009-2024 Arm Limited
+; * Copyright (c) 2022-2024 Cypress Semiconductor Corporation (an Infineon company)
+; * or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
+; *
+; * Licensed under the Apache License, Version 2.0 (the "License");
+; * you may not use this file except in compliance with the License.
+; * You may obtain a copy of the License at
+; *
+; * http://www.apache.org/licenses/LICENSE-2.0
+; *
+; * Unless required by applicable law or agreed to in writing, software
+; * distributed under the License is distributed on an "AS IS" BASIS,
+; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; * See the License for the specific language governing permissions and
+; * limitations under the License.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 gcc_arm.ld
+; */
+
+/***********{{utilities.donotedit_warning}}***********/
+
+/* Linker script to configure memory regions. */
+/* This file will be run through the pre-processor. */
+
+#include "region_defs.h"
+
+/* Include file with definitions for section alignments.
+ * Note: it should be included after region_defs.h to let platform define
+ * default values if needed. */
+#include "tfm_s_linker_alignments.h"
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
+ RAM (rw) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
+#ifdef S_RAM_CODE_START
+ CODE_RAM (rwx) : ORIGIN = S_RAM_CODE_START, LENGTH = S_RAM_CODE_SIZE
+#endif
+}
+
+#ifndef TFM_LINKER_VENEERS_START
+#define TFM_LINKER_VENEERS_START ALIGN(TFM_LINKER_VENEERS_ALIGNMENT)
+#endif
+
+#ifndef TFM_LINKER_VENEERS_END
+#define TFM_LINKER_VENEERS_END ALIGN(TFM_LINKER_VENEERS_ALIGNMENT)
+#endif
+
+#define VENEERS() \
+/* \
+ * Place the CMSE Veneers (containing the SG instruction) after the code, in \
+ * a separate at least 32 bytes aligned region so that the SAU can \
+ * programmed to just set this region as Non-Secure Callable. \
+ */ \
+.gnu.sgstubs TFM_LINKER_VENEERS_START : \
+{ \
+ *(.gnu.sgstubs*) \
+} > FLASH \
+/* GCC always places veneers at the end of .gnu.sgstubs section, so the only \
+ * way to align the end of .gnu.sgstubs section is to align start of the \
+ * next section */ \
+.sgstubs_end : TFM_LINKER_VENEERS_END \
+{ \
+} > FLASH
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ /* Position tag: Start of code + RO-data */
+ Image$$PT_RO_START$$Base = ADDR(.TFM_VECTORS);
+
+ .TFM_VECTORS : ALIGN(4)
+ {
+ __vectors_start = .;
+ KEEP(*(.vectors))
+ __vectors_end = .;
+ } > FLASH
+
+ ASSERT(__vectors_start != __vectors_end, ".vectors should not be empty")
+
+#ifdef S_CODE_VECTOR_TABLE_SIZE
+ ASSERT(. <= ADDR(.TFM_VECTORS) + S_CODE_VECTOR_TABLE_SIZE, ".TFM_VECTORS section size overflow.")
+ . = ADDR(.TFM_VECTORS) + S_CODE_VECTOR_TABLE_SIZE;
+#endif
+
+#if defined(CONFIG_TFM_USE_TRUSTZONE) && !defined(TFM_LINKER_VENEERS_LOCATION_END)
+ VENEERS()
+#endif
+ /* Position tag: Start of unprivileged code (shared, not PXN) */
+
+ .ER_UNPRIV_CODE : ALIGN(TFM_LINKER_PT_UNPRIV_CODE_ALIGNMENT)
+ {
+ Image$$PT_UNPRIV_CODE_START$$Base = .;
+ /* Shared library code */
+ *builtins*:*(SORT_BY_ALIGNMENT(.text*))
+ *libtfm_sprt*:*(SORT_BY_ALIGNMENT(.text*))
+ *libtfm_sp_log*:*(SORT_BY_ALIGNMENT(.text*))
+ *libqcbor*:*(SORT_BY_ALIGNMENT(.text*))
+ *libtfm_t_cose_s*:*(SORT_BY_ALIGNMENT(.text*))
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+ /* Position tag: End of unprivileged code (shared, not PXN) */
+ . = ALIGN(TFM_LINKER_PT_UNPRIV_CODE_ALIGNMENT);
+ Image$$PT_UNPRIV_CODE_END$$Base = .;
+
+
+ .ER_APP_ROT_CODE : ALIGN(TFM_LINKER_PT_APP_ROT_CODE_ALIGNMENT)
+ {
+ /* Position tag: Start of Application RoT code (unprivileged, PXN) */
+ Image$$PT_APP_ROT_CODE_START$$Base = .;
+ *tfm_app_rot_partition*:*(SORT_BY_ALIGNMENT(.text*))
+ *(TFM_*_APP-ROT_ATTR_FN)
+{% for partition in partitions %}
+ {% if partition.manifest.type == 'APPLICATION-ROT' %}
+ {% if partition.attr.linker_pattern.library_list %}
+ {% for pattern in partition.attr.linker_pattern.library_list %}
+ {{pattern}}:*(SORT_BY_ALIGNMENT(.text*))
+ {% endfor %}
+ {% endif %}
+ {% if partition.attr.linker_pattern.object_list %}
+ {% for pattern in partition.attr.linker_pattern.object_list %}
+ {{pattern}}(SORT_BY_ALIGNMENT(.text*))
+ {% endfor %}
+ {% endif %}
+ *({{partition.manifest.name}}_APP-ROT_ATTR_FN)
+ {% endif %}
+{% endfor %}
+ } > FLASH
+
+ /* Position tag: End of Application RoT code (unprivileged, PXN) */
+ . = ALIGN(TFM_LINKER_PT_APP_ROT_CODE_ALIGNMENT);
+ Image$$PT_APP_ROT_CODE_END$$Base = .;
+
+ .ER_PSA_ROT_CODE : ALIGN(TFM_LINKER_PT_PSA_ROT_CODE_ALIGNMENT)
+ {
+ /* Position tag: Start of PSA RoT code (privileged) */
+ Image$$PT_PSA_ROT_CODE_START$$Base = .;
+ *tfm_psa_rot_partition*:*(SORT_BY_ALIGNMENT(.text*))
+ *(TFM_*_PSA-ROT_ATTR_FN)
+{% for partition in partitions %}
+ {% if partition.manifest.type == 'PSA-ROT' %}
+ {% if partition.attr.linker_pattern.library_list %}
+ {% for pattern in partition.attr.linker_pattern.library_list %}
+ {{pattern}}:*(SORT_BY_ALIGNMENT(.text*))
+ {% endfor %}
+ {% endif %}
+ {% if partition.attr.linker_pattern.object_list %}
+ {% for pattern in partition.attr.linker_pattern.object_list %}
+ {{pattern}}(SORT_BY_ALIGNMENT(.text*))
+ {% endfor %}
+ {% endif %}
+ *({{partition.manifest.name}}_PSA-ROT_ATTR_FN)
+ {% endif %}
+{% endfor %}
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ .ER_TFM_CODE ALIGN(4) :
+ {
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ /* .copy.table */
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+#ifdef RAM_VECTORS_SUPPORT
+ /* Copy interrupt vectors from flash to RAM */
+ LONG (__vectors_start__) /* From */
+ LONG (__ram_vectors_start__) /* To */
+ LONG ((__vectors_end__ - __vectors_start__) / 4) /* Size */
+#endif
+ LONG (LOADADDR(.TFM_DATA))
+ LONG (ADDR(.TFM_DATA))
+ LONG (SIZEOF(.TFM_DATA) / 4)
+
+{% for partition in partitions %}
+ LONG (LOADADDR(.ER_{{partition.manifest.name}}_DATA))
+ LONG (ADDR(.ER_{{partition.manifest.name}}_DATA))
+ LONG (SIZEOF(.ER_{{partition.manifest.name}}_DATA) / 4)
+{% endfor %}
+
+#ifdef S_RAM_CODE_START
+ LONG (LOADADDR(.ER_CODE_SRAM))
+ LONG (ADDR(.ER_CODE_SRAM))
+ LONG (SIZEOF(.ER_CODE_SRAM) / 4)
+#endif
+ __copy_table_end__ = .;
+
+ /* .zero.table */
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ LONG (ADDR(.TFM_BSS))
+ LONG (SIZEOF(.TFM_BSS) / 4)
+{% for partition in partitions %}
+ LONG (ADDR(.ER_{{partition.manifest.name}}_BSS))
+ LONG (SIZEOF(.ER_{{partition.manifest.name}}_BSS) / 4)
+{% endfor %}
+
+#ifdef CONFIG_TFM_PARTITION_META
+ LONG (ADDR(.TFM_SP_META_PTR))
+ LONG (SIZEOF(.TFM_SP_META_PTR) / 4)
+#endif
+ __zero_table_end__ = .;
+
+ /* Capture all remaining code (except RAM code) in the privileged TF-M
+ * code region.
+ */
+ EXCLUDE_FILE (*libflash_drivers*:) *(SORT_BY_ALIGNMENT(.text*))
+ } > FLASH
+
+ /* Collect all RO-data into a single unprivileged region */
+ .ER_RO_DATA ALIGN(TFM_LINKER_PT_RO_DATA_ALIGNMENT) :
+ {
+ Image$$PT_PSA_ROT_CODE_END$$Base = .;
+ Image$$PT_RO_DATA_START$$Base = .;
+ /* Position tag: Start of RO-data (unprivileged, execute-never) */
+ EXCLUDE_FILE (*libflash_drivers*:) *(SORT_BY_ALIGNMENT(.rodata*))
+ } > FLASH
+
+ /**** Section for holding partition RO load data */
+ /*
+ * Sort the partition info by priority to guarantee the initing order.
+ * The first loaded partition will be inited at last in SFN model.
+ */
+ .TFM_SP_LOAD_LIST ALIGN(4) :
+ {
+ KEEP(*(.part_load_priority_00))
+ KEEP(*(.part_load_priority_01))
+ KEEP(*(.part_load_priority_02))
+ KEEP(*(.part_load_priority_03))
+ } > FLASH
+ Image$$TFM_SP_LOAD_LIST$$RO$$Base = ADDR(.TFM_SP_LOAD_LIST);
+ Image$$TFM_SP_LOAD_LIST$$RO$$Limit = ADDR(.TFM_SP_LOAD_LIST) + SIZEOF(.TFM_SP_LOAD_LIST);
+
+ /* Position tag: End of RO-data (unprivileged, execute-never) */
+ . = ALIGN(TFM_LINKER_PT_RO_DATA_ALIGNMENT);
+ Image$$PT_RO_DATA_END$$Base = .;
+
+#if defined(CONFIG_TFM_USE_TRUSTZONE) && defined(TFM_LINKER_VENEERS_LOCATION_END)
+ VENEERS()
+#endif
+
+ /* Position tag: End of code + RO-data */
+ . = ALIGN(TFM_LINKER_PT_RO_ALIGNMENT);
+ Image$$PT_RO_END$$Base = .;
+
+#ifdef S_RAM_CODE_START
+ /* Flash drivers code that gets copied from Flash */
+ .ER_CODE_SRAM ALIGN(S_RAM_CODE_START, 4) :
+ {
+ *libflash_drivers*:*(SORT_BY_ALIGNMENT(.text*))
+ *libflash_drivers*:*(SORT_BY_ALIGNMENT(.rodata*))
+ KEEP(*(.ramfunc))
+ . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */
+ } > CODE_RAM AT > FLASH
+
+ ASSERT(S_RAM_CODE_START % 4 == 0, "S_RAM_CODE_START must be divisible by 4")
+
+ Image$$ER_CODE_SRAM$$RO$$Base = ADDR(.ER_CODE_SRAM);
+ Image$$ER_CODE_SRAM$$RO$$Limit = ADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM);
+ Image$$ER_CODE_SRAM$$Base = ADDR(.ER_CODE_SRAM);
+ Image$$ER_CODE_SRAM$$Limit = ADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM);
+#endif
+
+ /**** Base address of secure data area */
+ .tfm_secure_data_start :
+ {
+ /* Relocate current position to RAM */
+ . = ALIGN(4);
+ } > RAM
+
+ /*
+ * MPU on Armv6-M/v7-M core in multi-core topology may require more strict
+ * alignment that MPU region base address must align with the MPU region
+ * size.
+ * As a result, on Armv6-M/v7-M cores, to save memory resource and MPU
+ * regions, unprivileged data sections and privileged data sections can be
+ * separated and gathered in unprivileged/privileged data area respectively
+ * by defining S_DATA_PRIV_START. If so, the BL2 shared data area is moved
+ * to the beginning of the privileged data area, otherwise it is kept at the
+ * beginning of the secure data area.
+ */
+#ifndef S_DATA_PRIV_START
+#ifdef CODE_SHARING
+ /* The code sharing between bootloader and runtime requires to share the
+ * global variables.
+ */
+ .TFM_SHARED_SYMBOLS ALIGN(TFM_LINKER_SHARED_SYMBOLS_ALIGNMENT) :
+ {
+ . += SHARED_SYMBOL_AREA_SIZE;
+ } > RAM
+#endif
+
+ /* Shared area between BL2 and runtime to exchange data */
+ .tfm_bl2_shared_data ALIGN(TFM_LINKER_BL2_SHARED_DATA_ALIGNMENT) (NOLOAD) :
+ {
+ . += BOOT_TFM_SHARED_DATA_SIZE;
+ } > RAM
+#endif /* !S_DATA_PRIV_START */
+
+ /* Position tag: Start of Application RoT data (unprivileged) */
+ . = ALIGN(TFM_LINKER_PT_APP_ROT_DATA_ALIGNMENT);
+ Image$$PT_APP_ROT_DATA_START$$Base = .;
+
+#ifdef CONFIG_TFM_PARTITION_META
+ .TFM_SP_META_PTR ALIGN(TFM_LINKER_SP_META_PTR_ALIGNMENT) (NOLOAD) :
+ {
+ *(.bss.SP_META_PTR_SPRTL_INST)
+ . = ALIGN(TFM_LINKER_SP_META_PTR_ALIGNMENT);
+ } > RAM
+ Image$$TFM_SP_META_PTR$$ZI$$Base = ADDR(.TFM_SP_META_PTR);
+ Image$$TFM_SP_META_PTR$$ZI$$Limit = ADDR(.TFM_SP_META_PTR) + SIZEOF(.TFM_SP_META_PTR);
+ /* This is needed for the uniform configuration of MPU region. */
+ Image$$TFM_SP_META_PTR_END$$ZI$$Limit = Image$$TFM_SP_META_PTR$$ZI$$Limit;
+#endif
+
+{% for partition in partitions %}
+ {% if partition.manifest.type == 'APPLICATION-ROT' %}
+
+
+ .ER_{{partition.manifest.name}}_DATA : ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT)
+ {
+ /* Position tag: Start of Application RoT partition's private data */
+ Image$$PT_{{partition.manifest.name}}_PRIVATE_DATA_START$$Base = .;
+ {% if partition.attr.linker_pattern.library_list %}
+ {% for pattern in partition.attr.linker_pattern.library_list %}
+ {{pattern}}:*(SORT_BY_ALIGNMENT(.data*))
+ {% endfor %}
+ {% endif %}
+ {% if partition.attr.linker_pattern.object_list %}
+ {% for pattern in partition.attr.linker_pattern.object_list %}
+ {{pattern}}(SORT_BY_ALIGNMENT(.data*))
+ {% endfor %}
+ {% endif %}
+ *({{partition.manifest.name}}_APP-ROT_ATTR_RW)
+ . = ALIGN(4);
+ } > RAM AT > FLASH
+
+ .ER_{{partition.manifest.name}}_BSS ALIGN(8) (NOLOAD) :
+ {
+ start_of_{{partition.manifest.name}}_bss = .;
+ {% if partition.attr.linker_pattern.library_list %}
+ {% for pattern in partition.attr.linker_pattern.library_list %}
+ {{pattern}}:*(SORT_BY_ALIGNMENT(.bss*))
+ {{pattern}}:*(COMMON)
+ {% endfor %}
+ {% endif %}
+ {% if partition.attr.linker_pattern.object_list %}
+ {% for pattern in partition.attr.linker_pattern.object_list %}
+ {{pattern}}(SORT_BY_ALIGNMENT(.bss*))
+ {{pattern}}(COMMON)
+ {% endfor %}
+ {% endif %}
+ *({{partition.manifest.name}}_APP-ROT_ATTR_ZI)
+ . += (. - start_of_{{partition.manifest.name}}_bss) ? 0 : 4;
+ } > RAM
+
+ /* Position tag: End of Application RoT partition's private data */
+ . = ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT);
+ Image$$PT_{{partition.manifest.name}}_PRIVATE_DATA_END$$Base = .;
+
+ {% endif %}
+{% endfor %}
+
+ /* Position tag: End of Application RoT data (unprivileged) */
+ . = ALIGN(TFM_LINKER_PT_APP_ROT_DATA_ALIGNMENT);
+ Image$$PT_APP_ROT_DATA_END$$Base = .;
+
+#ifdef S_DATA_PRIV_START
+ /**** Privileged data area base address specified by Armv6-M/v7-M platform */
+ .tfm_secure_priv_data_boundary :
+ {
+ . = ABSOLUTE(S_DATA_PRIV_START) ;
+ } > RAM
+
+ /*
+ * Move BL2 shared area to the beginning of privileged data area on
+ * Armv6-M/v7-M platforms.
+ */
+ /* Shared area between BL2 and runtime to exchange data */
+ .tfm_bl2_shared_data ALIGN(TFM_LINKER_BL2_SHARED_DATA_ALIGNMENT) :
+ {
+ . += BOOT_TFM_SHARED_DATA_SIZE;
+ } > RAM
+#endif /* S_DATA_PRIV_START */
+
+ /* Position tag: Start of PSA RoT data (privileged) */
+ . = ALIGN(TFM_LINKER_PT_PSA_ROT_DATA_ALIGNMENT);
+ Image$$PT_PSA_ROT_DATA_START$$Base = .;
+
+ .msp_stack ALIGN(TFM_LINKER_MSP_STACK_ALIGNMENT) (NOLOAD) :
+ {
+ . += S_MSP_STACK_SIZE;
+ } > RAM
+ Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
+
+#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) || \
+ defined(__ARM_ARCH_8_1M_MAIN__)
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack) - 0x8;
+ __stack_seal = Image$$ARM_LIB_STACK$$ZI$$Limit;
+#else
+ Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+#endif
+ __stack = Image$$ARM_LIB_STACK$$ZI$$Limit;
+
+#ifdef ENABLE_HEAP
+ .heap (NOLOAD) : ALIGN(8)
+ {
+ . += S_HEAP_SIZE;
+ } > RAM
+ __heap_start = ADDR(.heap);
+ __heap_end = ADDR(.heap) + SIZEOF(.heap);
+ __heap_size = SIZEOF(.heap);
+#endif
+
+{% for partition in partitions %}
+ {% if partition.manifest.type == 'PSA-ROT' %}
+
+ .ER_{{partition.manifest.name}}_DATA : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
+ {
+ /* Position tag: Start of PSA RoT partition's private data */
+ Image$$PT_{{partition.manifest.name}}_PRIVATE_DATA_START$$Base = .;
+ {% if partition.attr.linker_pattern.library_list %}
+ {% for pattern in partition.attr.linker_pattern.library_list %}
+ {{pattern}}:*(SORT_BY_ALIGNMENT(.data*))
+ {% endfor %}
+ {% endif %}
+ {% if partition.attr.linker_pattern.object_list %}
+ {% for pattern in partition.attr.linker_pattern.object_list %}
+ {{pattern}}(SORT_BY_ALIGNMENT(.data*))
+ {% endfor %}
+ {% endif %}
+ *({{partition.manifest.name}}_PSA-ROT_ATTR_RW)
+ . = ALIGN(4);
+ } > RAM AT > FLASH
+
+ .ER_{{partition.manifest.name}}_BSS ALIGN(8) (NOLOAD) :
+ {
+ start_of_{{partition.manifest.name}}_bss = .;
+ {% if partition.attr.linker_pattern.library_list %}
+ {% for pattern in partition.attr.linker_pattern.library_list %}
+ {{pattern}}:*(SORT_BY_ALIGNMENT(.bss*))
+ {{pattern}}:*(COMMON)
+ {% endfor %}
+ {% endif %}
+ {% if partition.attr.linker_pattern.object_list %}
+ {% for pattern in partition.attr.linker_pattern.object_list %}
+ {{pattern}}(SORT_BY_ALIGNMENT(.bss*))
+ {{pattern}}(COMMON)
+ {% endfor %}
+ {% endif %}
+ *({{partition.manifest.name}}_PSA-ROT_ATTR_ZI)
+ . += (. - start_of_{{partition.manifest.name}}_bss) ? 0 : 4;
+ } > RAM
+
+ /* Position tag: End of PSA RoT partition's private data */
+ . = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
+ Image$$PT_{{partition.manifest.name}}_PRIVATE_DATA_END$$Base = .;
+
+ {% endif %}
+{% endfor %}
+
+ .TFM_DATA ALIGN(4) :
+ {
+ *(SORT_BY_ALIGNMENT(.data*))
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ } > RAM AT > FLASH
+
+ .TFM_BSS ALIGN(TFM_LINKER_DEFAULT_ALIGNMENT) (NOLOAD) :
+ {
+ /* The runtime partition placed order is same as load partition */
+ __partition_runtime_start__ = .;
+ KEEP(*(.bss.part_runtime_priority_00))
+ KEEP(*(.bss.part_runtime_priority_01))
+ KEEP(*(.bss.part_runtime_priority_02))
+ KEEP(*(.bss.part_runtime_priority_03))
+ __partition_runtime_end__ = .;
+ . = ALIGN(4);
+
+ /* The runtime service placed order is same as load partition */
+ __service_runtime_start__ = .;
+ KEEP(*(.bss.serv_runtime_priority_00))
+ KEEP(*(.bss.serv_runtime_priority_01))
+ KEEP(*(.bss.serv_runtime_priority_02))
+ KEEP(*(.bss.serv_runtime_priority_03))
+ __service_runtime_end__ = .;
+ *(SORT_BY_ALIGNMENT(.bss*))
+ *(COMMON)
+ . = ALIGN(4);
+ } > RAM
+ Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__;
+ Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__;
+ Image$$ER_SERV_RT_POOL$$ZI$$Base = __service_runtime_start__;
+ Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__;
+
+ /* Position tag: End of PSA RoT data (privileged) */
+ . = ALIGN(TFM_LINKER_PT_PSA_ROT_DATA_ALIGNMENT);
+ Image$$PT_PSA_ROT_DATA_END$$Base = .;
+
+#ifdef RAM_VECTORS_SUPPORT
+ .ramVectors ALIGN(TFM_LINKER_RAM_VECTORS_ALIGNMENT) (NOLOAD) :
+ {
+ __ram_vectors_start__ = .;
+ KEEP(*(.ram_vectors))
+ __ram_vectors_end__ = .;
+ } > RAM
+#endif
+
+#ifdef CONFIG_TFM_USE_TRUSTZONE
+ Image$$ER_VENEER$$Base = ADDR(.gnu.sgstubs);
+ Image$$VENEER_ALIGN$$Limit = ADDR(.sgstubs_end);
+
+#ifdef TFM_LINKER_VENEERS_SIZE
+ ASSERT ((Image$$VENEER_ALIGN$$Limit - Image$$ER_VENEER$$Base) <= TFM_LINKER_VENEERS_SIZE, "Veneer region overflowed")
+#endif
+#endif
+
+ Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
+
+#ifdef BL2
+ Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
+#endif /* BL2 */
+}
diff --git a/platform/ext/common/uart_stdout.c b/platform/ext/common/uart_stdout.c
index 6e9277f..fec035a 100644
--- a/platform/ext/common/uart_stdout.c
+++ b/platform/ext/common/uart_stdout.c
@@ -81,6 +81,28 @@
/* Return character written */
return ch;
}
+
+/* Redirect sdtio for PicoLib in LLVM toolchain
+ as per https://github.com/picolibc/picolibc/blob/main/doc/os.md
+ 'fputch()' named intentionally different from 'fputc()' from picolib */
+#elif defined(__clang_major__)
+
+int fputch(char ch, struct __file *f)
+{
+ (void)f;
+
+ /* Send byte to USART */
+ (void)stdio_output_string((const char *)&ch, 1);
+
+ /* Return character written */
+ return ch;
+}
+
+static FILE __stdio = FDEV_SETUP_STREAM(fputch, NULL, NULL, _FDEV_SETUP_WRITE);
+FILE *const stdin = &__stdio;
+__strong_reference(stdin, stdout);
+__strong_reference(stdin, stderr);
+
#elif defined(__GNUC__)
/* Redirects printf to STDIO_DRIVER in case of GNUARM */
int _write(int fd, char *str, int len)
diff --git a/platform/ext/target/arm/mps2/an521/CMakeLists.txt b/platform/ext/target/arm/mps2/an521/CMakeLists.txt
index ed98be0..d327576 100644
--- a/platform/ext/target/arm/mps2/an521/CMakeLists.txt
+++ b/platform/ext/target/arm/mps2/an521/CMakeLists.txt
@@ -33,6 +33,7 @@
$<$<C_COMPILER_ID:ARMClang>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_isolation_s.sct>
$<$<C_COMPILER_ID:GNU>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_isolation_s.ld>
$<$<C_COMPILER_ID:IAR>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/iar/tfm_isolation_s.icf>
+ $<$<C_COMPILER_ID:Clang>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/llvm/tfm_isolation_s.ld>
)
if(BL2)
@@ -44,6 +45,7 @@
$<$<C_COMPILER_ID:ARMClang>:${PLATFORM_DIR}/ext/common/armclang/tfm_common_bl2.sct>
$<$<C_COMPILER_ID:GNU>:${PLATFORM_DIR}/ext/common/gcc/tfm_common_bl2.ld>
$<$<C_COMPILER_ID:IAR>:${PLATFORM_DIR}/ext/common/iar/tfm_common_bl2.icf>
+ $<$<C_COMPILER_ID:Clang>:${PLATFORM_DIR}/ext/common/llvm/tfm_common_bl2.ld>
)
endif()
@@ -171,6 +173,7 @@
install(FILES ${PLATFORM_DIR}/ext/common/gcc/tfm_common_ns.ld
${PLATFORM_DIR}/ext/common/armclang/tfm_common_ns.sct
${PLATFORM_DIR}/ext/common/iar/tfm_common_ns.icf
+ ${PLATFORM_DIR}/ext/common/llvm/tfm_common_ns.ldc
DESTINATION ${INSTALL_PLATFORM_NS_DIR}/linker_scripts)
# copy all files from active platform directory
diff --git a/platform/ns/toolchain_ns_LLVM.cmake b/platform/ns/toolchain_ns_LLVM.cmake
new file mode 100644
index 0000000..9d066bd
--- /dev/null
+++ b/platform/ns/toolchain_ns_LLVM.cmake
@@ -0,0 +1,212 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#-------------------------------------------------------------------------------
+
+set(CMAKE_SYSTEM_NAME Generic)
+
+# Specify the cross compiler
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_ASM_COMPILER clang)
+set(CMAKE_C_COMPILER_FORCED TRUE)
+set(CMAKE_ASM_COMPILER_FORCED TRUE)
+
+if(NOT DEFINED CROSS_COMPILE)
+ set(CROSS_COMPILE arm-none-eabi CACHE STRING "Cross-compiler prefix")
+endif()
+set(CMAKE_C_COMPILER_TARGET ${CROSS_COMPILE})
+set(CMAKE_ASM_COMPILER_TARGET ${CROSS_COMPILE})
+
+set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_LIST_DIR}/set_extensions.cmake)
+
+# CMAKE_C_COMPILER_VERSION is not guaranteed to be defined.
+EXECUTE_PROCESS( COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE LLVM_VERSION )
+if (LLVM_VERSION VERSION_LESS 18.1.3)
+ message(FATAL_ERROR "Please use newer LLVM compiler version starting from 18.1.3")
+endif()
+
+# ===================== Set toolchain CPU and Arch =============================
+# -mcpu gives better optimisation than -march so -mcpu shall be in preference
+
+if (TFM_SYSTEM_PROCESSOR)
+ if(TFM_SYSTEM_DSP)
+ string(APPEND TFM_SYSTEM_PROCESSOR "+dsp")
+ else()
+ string(APPEND TFM_SYSTEM_PROCESSOR "+nodsp")
+ endif()
+ if(CONFIG_TFM_ENABLE_FP)
+ string(APPEND TFM_SYSTEM_PROCESSOR "+fp")
+ else()
+ string(APPEND TFM_SYSTEM_PROCESSOR "+nofp")
+ endif()
+
+ set(CMAKE_C_FLAGS "-mcpu=${TFM_SYSTEM_PROCESSOR}")
+ set(CMAKE_ASM_FLAGS "-mcpu=${TFM_SYSTEM_PROCESSOR}")
+else()
+ if(CONFIG_TFM_ENABLE_FP)
+ string(APPEND TFM_SYSTEM_ARCHITECTURE "+fp")
+ endif()
+ if(TFM_SYSTEM_DSP)
+ string(APPEND TFM_SYSTEM_ARCHITECTURE "+dsp")
+ endif()
+ set(CMAKE_C_FLAGS "-march=${TFM_SYSTEM_ARCHITECTURE}")
+ set(CMAKE_ASM_FLAGS "-march=${TFM_SYSTEM_ARCHITECTURE}")
+ set(CMAKE_ASM_CPU_FLAG ${TFM_SYSTEM_ARCHITECTURE})
+endif()
+
+if (CONFIG_TFM_FLOAT_ABI STREQUAL "hard")
+ set(COMPILER_CP_FLAG -mfloat-abi=hard)
+ set(LINKER_CP_OPTION -mfloat-abi=hard)
+ if (CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE_FP)
+ set(COMPILER_CP_FLAG -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
+ set(LINKER_CP_OPTION -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
+ endif()
+else()
+ set(COMPILER_CP_FLAG -mfloat-abi=soft)
+ set(LINKER_CP_OPTION -mfloat-abi=soft)
+endif()
+
+set(BL1_COMPILER_CP_FLAG -mfloat-abi=soft)
+set(BL1_LINKER_CP_OPTION -mfloat-abi=soft)
+
+set(BL2_COMPILER_CP_FLAG -mfloat-abi=soft)
+set(BL2_LINKER_CP_OPTION -mfloat-abi=soft)
+
+add_compile_options(
+ -Wno-ignored-optimization-argument
+ -Wno-unused-command-line-argument
+ -Wall
+ -Wno-error=cpp
+ -c
+ -fdata-sections
+ -ffunction-sections
+ -fno-builtin
+ -fshort-enums
+ -fshort-wchar
+ -funsigned-char
+ -std=c99
+)
+
+# Pointer Authentication Code and Branch Target Identification (PACBTI) Options
+# Not currently supported for LLVM.
+if(NOT ${CONFIG_TFM_BRANCH_PROTECTION_FEAT} STREQUAL BRANCH_PROTECTION_DISABLED)
+ message(FATAL_ERROR "BRANCH_PROTECTION NOT supported for LLVM")
+endif()
+
+add_link_options(
+ LINKER:-check-sections
+ LINKER:-fatal-warnings
+ LINKER:--gc-sections
+ LINKER:--print-memory-usage
+ LINKER:-lcrt0 -ldummyhost
+ LINKER:--Map=bin/tfm_ns.map
+)
+
+#add_compile_definitions($<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv8.1-m.main>:__ARM_ARCH_8_1M_MAIN__=1>)
+
+# Specify the scatter file used to link `target`.
+# Behaviour for handling scatter files is so wildly divergent between compilers
+# that this macro is required.
+#
+# Vendor platform can set a scatter file as property INTERFACE_LINK_DEPENDS of platform_ns.
+# `target` can fetch the scatter file from platform_ns.
+#
+# Alternatively, NS build can call target_add_scatter_file() with the install directory of
+# scatter files.
+# target_add_scatter_file(target, install_dir)
+#
+# target_add_scatter_file() fetch a scatter file from the install directory.
+macro(target_add_scatter_file target)
+
+ # Try if scatter_file is passed from platform_ns
+ get_target_property(scatter_file
+ platform_ns
+ INTERFACE_LINK_DEPENDS
+ )
+
+ # If scatter_file is not passed from platform_ns
+ # Try if any scatter file is exported in install directory
+ # The intall directory is passed as an optinal argument
+ if(${scatter_file} STREQUAL "scatter_file-NOTFOUND")
+ set(install_dir ${ARGN})
+ list(LENGTH install_dir nr_install_dir)
+
+ # If nr_install_dir == 1, search for sct file under install dir
+ if(${nr_install_dir} EQUAL 1)
+ file(GLOB scatter_file "${install_dir}/*.ldc")
+ endif()
+ endif()
+
+ if(NOT EXISTS ${scatter_file})
+ message(FATAL_ERROR "Unable to find NS scatter file ${scatter_file}")
+ endif()
+
+ add_library(${target}_scatter OBJECT)
+ target_sources(${target}_scatter
+ PRIVATE
+ ${scatter_file}
+ )
+
+ # Cmake cannot use generator expressions in the
+ # set_source_file_properties command, so instead we just parse the regex
+ # for the filename and set the property on all files, regardless of if
+ # the generator expression would evaluate to true or not.
+ string(REGEX REPLACE ".*>:(.*)>$" "\\1" SCATTER_FILE_PATH "${scatter_file}")
+ set_source_files_properties(${SCATTER_FILE_PATH}
+ PROPERTIES
+ LANGUAGE C
+ KEEP_EXTENSION True # Avoid *.o extension for the preprocessed file
+ )
+
+ target_link_libraries(${target}_scatter PRIVATE platform_region_defs)
+
+ target_compile_options(${target}_scatter PRIVATE -E -xc)
+
+ target_link_options(${target} PRIVATE -T $<TARGET_OBJECTS:${target}_scatter>)
+
+ add_dependencies(${target} ${target}_scatter)
+ set_target_properties(${target} PROPERTIES LINK_DEPENDS $<TARGET_OBJECTS:${target}_scatter>)
+
+endmacro()
+
+# Macro for converting the output *.axf file to finary files: bin, elf, hex
+macro(add_convert_to_bin_target target)
+ get_target_property(bin_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
+
+ add_custom_target(${target}_bin
+ SOURCES ${bin_dir}/${target}.bin
+ )
+ add_custom_command(OUTPUT ${bin_dir}/${target}.bin
+ DEPENDS ${target}
+ COMMAND ${CMAKE_OBJCOPY}
+ -O binary $<TARGET_FILE:${target}>
+ ${bin_dir}/${target}.bin
+ )
+
+ add_custom_target(${target}_elf
+ SOURCES ${bin_dir}/${target}.elf
+ )
+ add_custom_command(OUTPUT ${bin_dir}/${target}.elf
+ DEPENDS ${target}
+ COMMAND ${CMAKE_OBJCOPY}
+ -O elf32-littlearm $<TARGET_FILE:${target}>
+ ${bin_dir}/${target}.elf
+ )
+
+ add_custom_target(${target}_hex
+ SOURCES ${bin_dir}/${target}.hex
+ )
+ add_custom_command(OUTPUT ${bin_dir}/${target}.hex
+ DEPENDS ${target}
+ COMMAND ${CMAKE_OBJCOPY}
+ -O ihex $<TARGET_FILE:${target}>
+ ${bin_dir}/${target}.hex
+ )
+
+ add_custom_target(${target}_binaries
+ ALL
+ DEPENDS ${target}_bin
+ DEPENDS ${target}_elf
+ DEPENDS ${target}_hex
+ )
+endmacro()
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 87b7943..de39ad4 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -76,10 +76,10 @@
target_link_options(tfm_s
PRIVATE
- --entry=Reset_Handler
$<$<C_COMPILER_ID:GNU>:-Wl,-Map=${CMAKE_BINARY_DIR}/bin/tfm_s.map>
$<$<C_COMPILER_ID:ARMClang>:--map>
$<$<C_COMPILER_ID:IAR>:--map\;${CMAKE_BINARY_DIR}/bin/tfm_s.map>
+ $<$<C_COMPILER_ID:Clang>:-Wl,-Map=${CMAKE_BINARY_DIR}/bin/tfm_s.map -nostdlib>
PUBLIC
${LINKER_CP_OPTION}
)
diff --git a/secure_fw/include/security_defs.h b/secure_fw/include/security_defs.h
index a048356..a5929d4 100644
--- a/secure_fw/include/security_defs.h
+++ b/secure_fw/include/security_defs.h
@@ -21,6 +21,12 @@
/* Attributes for psa api secure gateway functions */
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
/*
+ * LLVM offers 'noduplicate' attribute as 'noclone' equivalent in GNUARM
+ */
+#if defined(__clang__)
+#define noclone noduplicate
+#endif /* __clang__ */
+/*
* GNUARM requires noclone attribute to protect gateway function symbol from
* being renamed and cloned
*/
diff --git a/secure_fw/partitions/crypto/CMakeLists.txt b/secure_fw/partitions/crypto/CMakeLists.txt
index 38545fb..ddd16f2 100644
--- a/secure_fw/partitions/crypto/CMakeLists.txt
+++ b/secure_fw/partitions/crypto/CMakeLists.txt
@@ -203,6 +203,7 @@
$<$<C_COMPILER_ID:GNU>:-Wno-unused-parameter>
$<$<C_COMPILER_ID:ARMClang>:-Wno-unused-const-variable>
$<$<C_COMPILER_ID:ARMClang>:-Wno-unused-parameter>
+ $<$<C_COMPILER_ID:Clang>:-Wno-unused-parameter>
)
if(MBEDTLS_P256M_ENABLED)
diff --git a/secure_fw/partitions/lib/runtime/CMakeLists.txt b/secure_fw/partitions/lib/runtime/CMakeLists.txt
index 1fdad7a..12e3116 100644
--- a/secure_fw/partitions/lib/runtime/CMakeLists.txt
+++ b/secure_fw/partitions/lib/runtime/CMakeLists.txt
@@ -20,10 +20,13 @@
PUBLIC
$<$<BOOL:${CONFIG_GNU_SYSCALL_STUB_ENABLED}>:${CMAKE_SOURCE_DIR}/platform/ext/common/syscalls_stub.c>
PRIVATE
- ./crt_memcmp.c
- ./crt_memmove.c
- ./crt_strnlen.c
- ./service_api.c
+ crt_memcmp.c
+ crt_memmove.c
+ crt_strnlen.c
+ $<$<C_COMPILER_ID:Clang>:crt_start.c>
+ $<$<C_COMPILER_ID:Clang>:crt_exit.c>
+ $<$<C_COMPILER_ID:Clang>:crt_strlen.c>
+ service_api.c
${CMAKE_SOURCE_DIR}/secure_fw/shared/crt_memcpy.c
${CMAKE_SOURCE_DIR}/secure_fw/shared/crt_memset.c
$<$<BOOL:${CONFIG_TFM_PARTITION_META}>:./sprt_partition_metadata_indicator.c>
diff --git a/secure_fw/partitions/lib/runtime/crt_exit.c b/secure_fw/partitions/lib/runtime/crt_exit.c
new file mode 100644
index 0000000..1c80e66
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/crt_exit.c
@@ -0,0 +1,10 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ */
+
+void exit(void)
+{
+ while (1)
+ ;
+}
diff --git a/secure_fw/partitions/lib/runtime/crt_start.c b/secure_fw/partitions/lib/runtime/crt_start.c
new file mode 100644
index 0000000..5833072
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/crt_start.c
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ */
+
+#include "utilities.h"
+
+#if defined(__clang_major__) && defined(__GNUC__)
+
+/*
+ * We can not use CMSIS support for LLVM toolchain because it's incompatible
+ * with it. That's why we manunally implement the startup routine below.
+ */
+
+typedef struct __copy_table {
+ uint32_t const *src;
+ uint32_t *dest;
+ uint32_t wlen;
+} __copy_table_t;
+
+typedef struct __zero_table {
+ uint32_t *dest;
+ uint32_t wlen;
+} __zero_table_t;
+
+extern const __copy_table_t __copy_table_start__;
+extern const __copy_table_t __copy_table_end__;
+extern const __zero_table_t __zero_table_start__;
+extern const __zero_table_t __zero_table_end__;
+
+extern int main(int argc, char **argv);
+
+void _start(void)
+{
+ for (__copy_table_t const *pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
+ for (uint32_t i = 0u; i < pTable->wlen; ++i) {
+ pTable->dest[i] = pTable->src[i];
+ }
+ }
+
+ for (__zero_table_t const *pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
+ for (uint32_t i = 0u; i < pTable->wlen; ++i) {
+ pTable->dest[i] = 0u;
+ }
+ }
+ main(0, NULL);
+ while (1)
+ ;
+}
+#else
+#error This startup file shall be used in LLVM toolchain only.
+#endif
diff --git a/secure_fw/partitions/lib/runtime/crt_strlen.c b/secure_fw/partitions/lib/runtime/crt_strlen.c
new file mode 100644
index 0000000..7213cb0
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/crt_strlen.c
@@ -0,0 +1,17 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+ *
+ */
+
+#include <stddef.h>
+
+size_t strlen(const char *s)
+{
+ size_t idx = 0;
+
+ while (s[idx] != '\0') {
+ idx++;
+ }
+ return idx;
+}
diff --git a/toolchain_LLVM.cmake b/toolchain_LLVM.cmake
new file mode 100644
index 0000000..d0f88f7
--- /dev/null
+++ b/toolchain_LLVM.cmake
@@ -0,0 +1,257 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
+#-------------------------------------------------------------------------------
+
+set(CMAKE_SYSTEM_NAME Generic)
+
+# Specify the cross compiler
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_C_COMPILER_TARGET ${CROSS_COMPILE})
+
+set(CMAKE_ASM_COMPILER clang)
+set(CMAKE_ASM_COMPILER_TARGET ${CROSS_COMPILE})
+
+set(LINKER_VENEER_OUTPUT_FLAG -Wl,--cmse-implib,--out-implib=)
+set(COMPILER_CMSE_FLAG -mcmse -mfix-cmse-cve-2021-35465)
+
+set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_LIST_DIR}/cmake/set_extensions.cmake)
+
+# CMAKE_C_COMPILER_VERSION is not guaranteed to be defined.
+EXECUTE_PROCESS( COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE LLVM_VERSION )
+if (LLVM_VERSION VERSION_LESS 18.1.3)
+ message(FATAL_ERROR "Please use newer LLVM compiler version starting from 18.1.3")
+endif()
+
+# ===================== Set toolchain CPU and Arch =============================
+# -mcpu gives better optimisation than -march so -mcpu shall be in preference
+
+if (TFM_SYSTEM_PROCESSOR)
+ if(TFM_SYSTEM_DSP)
+ string(APPEND TFM_SYSTEM_PROCESSOR "+dsp")
+ else()
+ string(APPEND TFM_SYSTEM_PROCESSOR "+nodsp")
+ endif()
+ if(CONFIG_TFM_ENABLE_FP)
+ string(APPEND TFM_SYSTEM_PROCESSOR "+fp")
+ else()
+ string(APPEND TFM_SYSTEM_PROCESSOR "+nofp")
+ endif()
+
+ set(CMAKE_C_FLAGS "-mcpu=${TFM_SYSTEM_PROCESSOR}")
+ set(CMAKE_ASM_FLAGS "-mcpu=${TFM_SYSTEM_PROCESSOR}")
+else()
+ if(CONFIG_TFM_ENABLE_FP)
+ string(APPEND TFM_SYSTEM_ARCHITECTURE "+fp")
+ endif()
+ if(NOT TFM_SYSTEM_DSP)
+ string(APPEND TFM_SYSTEM_ARCHITECTURE "+nodsp")
+ endif()
+ set(CMAKE_C_FLAGS "-march=${TFM_SYSTEM_ARCHITECTURE}")
+ set(CMAKE_CXX_FLAGS "-march=${TFM_SYSTEM_ARCHITECTURE}")
+ set(CMAKE_ASM_FLAGS "-march=${TFM_SYSTEM_ARCHITECTURE}")
+ set(CMAKE_ASM_CPU_FLAG ${TFM_SYSTEM_ARCHITECTURE})
+endif()
+
+if (CONFIG_TFM_FLOAT_ABI STREQUAL "hard")
+ set(COMPILER_CP_FLAG -mfloat-abi=hard)
+ set(LINKER_CP_OPTION -mfloat-abi=hard)
+ if (CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE_FP)
+ set(COMPILER_CP_FLAG -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
+ set(LINKER_CP_OPTION -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
+ endif()
+else()
+ set(COMPILER_CP_FLAG -mfloat-abi=soft)
+ set(LINKER_CP_OPTION -mfloat-abi=soft)
+endif()
+
+set(BL1_COMPILER_CP_FLAG -mfloat-abi=soft)
+set(BL1_LINKER_CP_OPTION -mfloat-abi=soft)
+
+set(BL2_COMPILER_CP_FLAG -mfloat-abi=soft)
+set(BL2_LINKER_CP_OPTION -mfloat-abi=soft)
+
+add_compile_options(
+ -Wno-ignored-optimization-argument
+ -Wno-unused-command-line-argument
+ -Wall
+ -Wno-error=cpp
+ -c
+ -fdata-sections
+ -ffunction-sections
+ -fno-builtin
+ -fshort-enums
+ -fshort-wchar
+ -funsigned-char
+ -std=c99
+)
+
+# Pointer Authentication Code and Branch Target Identification (PACBTI) Options
+# Not currently supported for LLVM.
+if(NOT ${CONFIG_TFM_BRANCH_PROTECTION_FEAT} STREQUAL BRANCH_PROTECTION_DISABLED)
+ message(FATAL_ERROR "BRANCH_PROTECTION NOT supported for LLVM")
+endif()
+
+add_link_options(
+ -lclang_rt.builtins # needed for __aeabi_memclr4(), __aeabi_memclr8(), __aeabi_memcpy4()
+ LINKER:-check-sections
+ LINKER:-fatal-warnings
+ LINKER:--gc-sections
+)
+
+if(NOT CONFIG_TFM_MEMORY_USAGE_QUIET)
+ add_link_options(LINKER:--print-memory-usage)
+endif()
+
+# Macro for adding scatter files. Supports multiple files
+macro(target_add_scatter_file target)
+ target_link_options(${target} PRIVATE -T $<TARGET_OBJECTS:${target}_scatter>)
+
+ add_library(${target}_scatter OBJECT)
+ foreach(scatter_file ${ARGN})
+ target_sources(${target}_scatter
+ PRIVATE
+ ${scatter_file}
+ )
+ # Cmake cannot use generator expressions in the
+ # set_source_file_properties command, so instead we just parse the regex
+ # for the filename and set the property on all files, regardless of if
+ # the generator expression would evaluate to true or not.
+ string(REGEX REPLACE ".*>:(.*)>$" "\\1" SCATTER_FILE_PATH "${scatter_file}")
+ set_source_files_properties(${SCATTER_FILE_PATH}
+ PROPERTIES
+ LANGUAGE C
+ KEEP_EXTENSION True # Don't use .o extension for the preprocessed file
+ )
+ endforeach()
+
+ add_dependencies(${target} ${target}_scatter)
+
+ set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS $<TARGET_OBJECTS:${target}_scatter>)
+
+ target_link_libraries(${target}_scatter
+ platform_region_defs
+ psa_interface
+ tfm_config
+ )
+
+ target_compile_options(${target}_scatter PRIVATE -E -P -xc)
+endmacro()
+
+# Macro for converting the output *.axf file to finary files: bin, elf, hex
+macro(add_convert_to_bin_target target)
+ get_target_property(bin_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
+ add_custom_target(${target}_bin
+ ALL DEPENDS ${target}
+ COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${target}> ${bin_dir}/${target}.bin
+ COMMAND ${CMAKE_OBJCOPY} -O elf32-littlearm $<TARGET_FILE:${target}> ${bin_dir}/${target}.elf
+ COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${target}> ${bin_dir}/${target}.hex
+ )
+endmacro()
+
+# Set of macrots for sharing code between BL2 and RunTime, targeted for sharing MbedTLS library
+macro(target_share_symbols target)
+ get_target_property(TARGET_TYPE ${target} TYPE)
+ if (NOT TARGET_TYPE STREQUAL "EXECUTABLE")
+ message(FATAL_ERROR "${target} is not an executable. Symbols cannot be shared from libraries.")
+ endif()
+
+ foreach(symbol_file ${ARGN})
+ FILE(STRINGS ${symbol_file} SYMBOLS
+ LENGTH_MINIMUM 1
+ )
+ list(APPEND KEEP_SYMBOL_LIST ${SYMBOLS})
+ endforeach()
+
+ set(STRIP_SYMBOL_KEEP_LIST ${KEEP_SYMBOL_LIST})
+
+ # Force the target to not remove the symbols if they're unused.
+ list(TRANSFORM KEEP_SYMBOL_LIST PREPEND "-Wl,--undefined=")
+ target_link_options(${target}
+ PRIVATE
+ ${KEEP_SYMBOL_LIST}
+ )
+
+ list(TRANSFORM STRIP_SYMBOL_KEEP_LIST PREPEND --keep-symbol=)
+ # strip all the symbols except those proveded as arguments
+ add_custom_target(${target}_shared_symbols
+ COMMAND ${CMAKE_OBJCOPY}
+ $<TARGET_FILE:${target}>
+ --wildcard ${STRIP_SYMBOL_KEEP_LIST}
+ --strip-all
+ $<TARGET_FILE_DIR:${target}>/${target}${CODE_SHARING_OUTPUT_FILE_SUFFIX}
+ )
+
+ # Ensure ${target} is built before $<TARGET_FILE:${target}> is used to generate ${target}_shared_symbols
+ add_dependencies(${target}_shared_symbols ${target})
+ # Allow the global clean target to rm the ${target}_shared_symbols created
+ set_target_properties(${target}_shared_symbols PROPERTIES
+ ADDITIONAL_CLEAN_FILES $<TARGET_FILE_DIR:${target}>/${target}${CODE_SHARING_OUTPUT_FILE_SUFFIX}
+ )
+endmacro()
+
+macro(target_link_shared_code target)
+ foreach(symbol_provider ${ARGN})
+ if (TARGET ${symbol_provider})
+ get_target_property(SYMBOL_PROVIDER_TYPE ${symbol_provider} TYPE)
+ if (NOT SYMBOL_PROVIDER_TYPE STREQUAL "EXECUTABLE")
+ message(FATAL_ERROR "${symbol_provider} is not an executable. Symbols cannot be shared from libraries.")
+ endif()
+ endif()
+
+ # Ensure ${symbol_provider}_shared_symbols is built before ${target}
+ add_dependencies(${target} ${symbol_provider}_shared_symbols)
+ # ${symbol_provider}_shared_symbols - a custom target is always considered out-of-date
+ # To only link when necessary, depend on ${symbol_provider} instead
+ set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS $<TARGET_OBJECTS:${symbol_provider}>)
+ target_link_options(${target} PRIVATE LINKER:-R$<TARGET_FILE_DIR:${symbol_provider}>/${symbol_provider}${CODE_SHARING_INPUT_FILE_SUFFIX})
+ endforeach()
+endmacro()
+
+macro(target_strip_symbols target)
+ set(SYMBOL_LIST "${ARGN}")
+ list(TRANSFORM SYMBOL_LIST PREPEND --strip-symbol=)
+
+ add_custom_command(
+ TARGET ${target}
+ POST_BUILD
+ COMMAND ${CMAKE_OBJCOPY}
+ ARGS $<TARGET_FILE:${target}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${target}>
+ )
+endmacro()
+
+macro(target_strip_symbols_from_dependency target dependency)
+ set(SYMBOL_LIST "${ARGN}")
+ list(TRANSFORM SYMBOL_LIST PREPEND --strip-symbol=)
+
+ add_custom_command(
+ TARGET ${target}
+ PRE_LINK
+ COMMAND ${CMAKE_OBJCOPY}
+ ARGS $<TARGET_FILE:${dependency}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${dependency}>
+ )
+endmacro()
+
+macro(target_weaken_symbols target)
+ set(SYMBOL_LIST "${ARGN}")
+ list(TRANSFORM SYMBOL_LIST PREPEND --weaken-symbol=)
+
+ add_custom_command(
+ TARGET ${target}
+ POST_BUILD
+ COMMAND ${CMAKE_OBJCOPY}
+ ARGS $<TARGET_FILE:${target}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${target}>
+ )
+endmacro()
+
+macro(target_weaken_symbols_from_dependency target dependency)
+ set(SYMBOL_LIST "${ARGN}")
+ list(TRANSFORM SYMBOL_LIST PREPEND --weaken-symbol=)
+
+ add_custom_command(
+ TARGET ${target}
+ PRE_LINK
+ COMMAND ${CMAKE_OBJCOPY}
+ ARGS $<TARGET_FILE:${dependency}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${dependency}>
+ )
+endmacro()