Build: Enable code sharing between bootloader and SPE

Add CMake functions to allow sharing regions of code between
independently linked binaries.

Signed-off-by: Tamas Ban <tamas.ban@arm.com>
Change-Id: I6a6132d6c1558b242d8da1dedab14f93a852f81a
diff --git a/bl2/CMakeLists.txt b/bl2/CMakeLists.txt
index 1496a19..42cd65f 100644
--- a/bl2/CMakeLists.txt
+++ b/bl2/CMakeLists.txt
@@ -100,3 +100,9 @@
     PUBLIC
         bl2_mbedcrypto_config
 )
+
+############################### CODE SHARING ###################################
+
+if (TFM_CODE_SHARING)
+    compiler_create_shared_code(bl2 ${CMAKE_CURRENT_SOURCE_DIR}/src/shared_symbol_template.txt)
+endif()
diff --git a/bl2/src/shared_symbol_template.txt b/bl2/src/shared_symbol_template.txt
new file mode 100644
index 0000000..65e305a
--- /dev/null
+++ b/bl2/src/shared_symbol_template.txt
@@ -0,0 +1,25 @@
+# -----------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# -----------------------------------------------------------
+mbedtls_internal
+mbedtls_sha256
+mbedtls_rsa
+mpi
+mbedtls_mpi_write_binary
+mbedtls_asn1_get_len
+mbedtls_asn1_get_tag
+mbedtls_mpi_bitlen
+mbedtls_cmp_abs
+mbedtls_cmp_int
+mbedtls_cmp_mpi
+mbedtls_mpi_get_bit
+mbedtls_mpi_init
+mbedtls_mpi_size
+mbedtls_aes_free
+mbedtls_aes_init
+mbedtls_entropy_free
+mbedtls_ctr_drbg_free
+mbedtls_mpi_cmp_mpi
diff --git a/cmake/Common/FilterSharedSymbols.cmake b/cmake/Common/FilterSharedSymbols.cmake
new file mode 100644
index 0000000..feac891
--- /dev/null
+++ b/cmake/Common/FilterSharedSymbols.cmake
@@ -0,0 +1,56 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# A CMake script which is meant to filter some wanted symbols based on a template file
+# from another text file, which contains all the extracted symbols from an executable.
+#
+# INPUT parameters:
+#   SHARED_SYMBOL_TEMPLATE - Text file contains wanted symbol name templates to be shared (i.e.: mbedtls_)
+#   ALL_SYMBOLS        - Text file, which contains all the extracted symbols from an executable.
+#                        Produced in previous step of the code sharing process.
+#
+# OUTPUTS produced by this script:
+#   - shared_symbols_addr.txt  List of the name, type and absolute address of symbols which
+#                              match with the patterns in the symbol template file
+#   - shared_symbols_name.txt  List of only the names of symbols which match with the
+#                              patterns in the symbol template file
+
+file(STRINGS ${SHARED_SYMBOL_TEMPLATE} SHARED_SYMBOL_TEMPLATE)
+file(STRINGS ${ALL_SYMBOLS}        ALL_SYMBOLS)
+
+# In 'arm-none-eabi-nm' and 'armclang --symdefs' output 'T' indicates the global
+# symbols which can be shared between independently linked executables.
+set(_GLOBAL_TEXT_SYMBOL "T")
+
+foreach(_SYMBOL_TEMPLATE IN LISTS SHARED_SYMBOL_TEMPLATE)
+    string(SUBSTRING _SYMBOL_TEMPLATE 0 1 FIRST_CHAR)
+    if(NOT _SYMBOL_TEMPLATE STREQUAL "" AND NOT FIRST_CHAR STREQUAL "#")
+        foreach(_ONE_SYMBOL IN LISTS ALL_SYMBOLS)
+            string(FIND ${_ONE_SYMBOL} "${_GLOBAL_TEXT_SYMBOL} ${_SYMBOL_TEMPLATE}" POSITION)
+            if (NOT POSITION EQUAL -1)
+                # Get matching symbol name and its address
+                list(APPEND SHARED_SYMBOL_ADDR_LIST "${_ONE_SYMBOL}")
+
+                # Get matching symbol name
+                string(SUBSTRING ${_ONE_SYMBOL} ${POSITION} 200 _ONE_SYMBOL_NAME)
+                string(REPLACE "${_GLOBAL_TEXT_SYMBOL} " "" _ONE_SYMBOL_NAME ${_ONE_SYMBOL_NAME})
+                list(APPEND SHARED_SYMBOL_NAME_LIST "${_ONE_SYMBOL_NAME}")
+            endif()
+        endforeach()
+    endif()
+endforeach()
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_addr.txt "#<SYMDEFS>#\n")
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_name.txt "")
+
+foreach(_SYMBOL IN LISTS SHARED_SYMBOL_ADDR_LIST)
+    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_addr.txt "${_SYMBOL}\n")
+endforeach()
+
+foreach(_SYMBOL IN LISTS SHARED_SYMBOL_NAME_LIST)
+    file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_name.txt "${_SYMBOL}\n")
+endforeach()
diff --git a/cmake/Common/StripUnsharedCode.cmake b/cmake/Common/StripUnsharedCode.cmake
new file mode 100644
index 0000000..a2df391
--- /dev/null
+++ b/cmake/Common/StripUnsharedCode.cmake
@@ -0,0 +1,40 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# A CMake script to strip that part of an executable which is not meant to be
+# shared among distinct binaries (code reuse). Only used by GNUARM tool chain.
+#
+# INPUT parameters:
+#   SHARED_SYMBOLS_FILE  -  File which contains the list of shared symbols.
+#   EXECUTABLE_TO_STRIP  -  A copy of the original executable, which contains the sharable code.
+#                           From this copy of the executable the unshared code and symbols
+#                           are removed.
+#
+# OUTPUTS produced by this script:
+#   - EXECUTABLE_TO_STRIP  -  Output file (stripped) has the same name as input file.
+
+find_program(GNUARM_STRIP arm-none-eabi-strip)
+if (GNUARM_STRIP STREQUAL "GNUARM_STRIP-NOTFOUND")
+    message(FATAL_ERROR "StripUnsharedCode.cmake: mandatory tool '${GNUARM_STRIP}' is missing.")
+endif()
+
+# Want to strip all unwanted symbols in one go, so concatenate those which must be kept
+file(STRINGS ${SHARED_SYMBOLS_FILE} SHARED_SYMBOL_NAME)
+foreach(_SYMBOL IN LISTS SHARED_SYMBOL_NAME)
+    list(APPEND ARGUMENT "-K${_SYMBOL}")
+endforeach()
+
+execute_process(COMMAND ${GNUARM_STRIP} ${ARGUMENT} ${EXECUTABLE_TO_STRIP}
+                TIMEOUT 120
+                OUTPUT_VARIABLE _RES
+                ERROR_VARIABLE  _RES
+                RESULT_VARIABLE _STATUS_CODE
+                OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if (_STATUS_CODE GREATER 0)
+    message(FATAL_ERROR "ERROR: Failed to execute ${GNUARM_STRIP} ${_RES}")
+endif()
diff --git a/cmake/Common/WeakenSymbols.cmake b/cmake/Common/WeakenSymbols.cmake
new file mode 100644
index 0000000..0ae53d3
--- /dev/null
+++ b/cmake/Common/WeakenSymbols.cmake
@@ -0,0 +1,77 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# A CMake script to weaken identical symbols in the target linked libraries to avoid
+# symbol collision at linking time between shared code and other libraries.
+# i.e.: Shared cryptographic code between MCUBoot and secure runtime firmware.
+#
+# INPUT parameters:
+#   LIB_LIST          - List of all libraries which are linked to the target, and are using
+#                       the shared code.
+#   SHARED_CODE_PATH  - The location of the shared code. It could be outside of TF-M repository.
+#
+# OUTPUTS produced by this script:
+#   The libraries might be modified by this script, if they contain the same symbols
+#   as the shared code.
+
+# TODO: Library search path is modified manually to include path for platform
+#       related libraries.
+
+find_program(OBJCOPY arm-none-eabi-objcopy)
+if (OBJCOPY STREQUAL "OBJCOPY-NOTFOUND")
+    message(FATAL_ERROR "WeakenSymbols.cmake: mandatory tool 'arm-none-eabi-objcopy' is missing.")
+endif()
+
+# Macro to collect all libraries where an *.a file is found
+macro(LIBRARY_DIRECTORIES return_list)
+    file(GLOB_RECURSE new_list *.a)
+    set(dir_list "")
+    foreach(file_path ${new_list})
+        get_filename_component(dir_path ${file_path} PATH)
+        set(dir_list ${dir_list} ${dir_path})
+    endforeach()
+    list(REMOVE_DUPLICATES dir_list)
+    set(${return_list} ${dir_list})
+endmacro()
+
+# Create a library search path for static libraries
+LIBRARY_DIRECTORIES(LIBRARY_PATH)
+
+# Workaround to include directories outside of 'secure_fw' folder for platform
+list(APPEND LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}/../platform/ext/accelerator/cc312/crypto_service_cc312 # Musca-B1: libcrypto_service_cc312.a
+                         ${CMAKE_CURRENT_BINARY_DIR}/../platform/ext/accelerator
+                         ${CMAKE_CURRENT_BINARY_DIR}/../platform
+)
+
+# When invoking the CMake scripts the original list separator(;) is replaced with space.
+# Need to convert back to be able to handle as a list.
+string(REPLACE " " ";" _LIB_LIST ${LIB_LIST})
+
+# Want to weaken all shared symbols in one go, so first concatenate them.
+# There are libraries which might not contain any of these, but it does
+# not cause any issue, the command does not return with error code.
+file(STRINGS ${SHARED_CODE_PATH}/shared_symbols_name.txt SHARED_SYMBOL_NAME)
+foreach(_SYMBOL IN LISTS SHARED_SYMBOL_NAME)
+    list(APPEND ARGUMENT "-W${_SYMBOL}")
+endforeach()
+
+# Iterate over each library and set potentially colliding symbols to be weak
+foreach(LIB IN LISTS _LIB_LIST)
+    find_file(LIB_FULL_PATH "lib${LIB}.a" PATHS ${LIBRARY_PATH} PATH_SUFFIXES Common NO_DEFAULT_PATH)
+    if (NOT ${LIB_FULL_PATH} STREQUAL "LIB_FULL_PATH-NOTFOUND")
+        execute_process(COMMAND ${OBJCOPY} ${ARGUMENT} ${LIB_FULL_PATH}
+                        TIMEOUT 120
+                        OUTPUT_VARIABLE _RES
+                        ERROR_VARIABLE  _RES
+                        RESULT_VARIABLE _STATUS_CODE
+                        OUTPUT_STRIP_TRAILING_WHITESPACE)
+        if (_STATUS_CODE GREATER 0)
+            message(FATAL_ERROR "ERROR: Failed to execute ${OBJCOPY} ${_RES}")
+        endif()
+    endif()
+    unset(LIB_FULL_PATH CACHE)
+endforeach()
diff --git a/config/config_default.cmake b/config/config_default.cmake
index c7fcde4..9f4d84d 100644
--- a/config/config_default.cmake
+++ b/config/config_default.cmake
@@ -28,6 +28,9 @@
 
 set(TFM_SPM_LOG_LEVEL                   2           CACHE STRING    "Set default SPM log level as INFO level")
 
+set(TFM_CODE_SHARING                    OFF         CACHE PATH      "Enable code sharing between MCUboot and secure firmware")
+set(TFM_CODE_SHARING_PATH               ""          CACHE PATH      "Path to repo which shares code with secure firmware")
+
 ########################## BL2 #################################################
 
 set(MCUBOOT_IMAGE_NUMBER                2           CACHE STRING    "Whether to combine S and NS into either 1 image, or sign each seperately")
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 97bc2fb..fbf8572 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -114,3 +114,33 @@
             ${LINKER_VENEER_OUTPUT_FLAG}${CMAKE_CURRENT_BINARY_DIR}/s_veneers.o
     )
 endif()
+
+############################### CODE SHARING ###################################
+if (TFM_CODE_SHARING)
+    set(LIB_LIST mbedcrypto
+                 crypto_service_cc312
+                 platform_s
+                 tfm_partition_crypto
+                 tfm_partition_audit
+                 tfm_partition_attestation
+                 tfm_partition_ps
+                 tfm_partition_its
+                 tfm_partition_platform
+                 platform_s
+                 tfm_sprt
+                 tfm_spm
+    )
+    if (TFM_CODE_SHARING_PATH)
+        compiler_link_shared_code(tfm_s
+                                  ${TFM_CODE_SHARING_PATH} # Path to shared code
+                                  EXTERNAL_TARGET # Not produced by tf-m build
+                                  "${LIB_LIST}"
+        )
+    else()
+        compiler_link_shared_code(tfm_s
+                                  ${CMAKE_CURRENT_BINARY_DIR}/../bl2
+                                  bl2
+                                  "${LIB_LIST}"
+        )
+    endif()
+endif()
diff --git a/toolchain_ARMCLANG.cmake b/toolchain_ARMCLANG.cmake
index 3857bd2..43bf595 100644
--- a/toolchain_ARMCLANG.cmake
+++ b/toolchain_ARMCLANG.cmake
@@ -239,3 +239,75 @@
         DEPENDS ${target}_hex
     )
 endmacro()
+
+# Macro for sharing code among independent binaries. This function extracts
+# some parts of the code based on a symbol template file and creates a text
+# file, which contains the symbols with their absolute addresses, which can be
+# picked up by the linker when linking the other target.
+# INPUTS:
+#     TARGET -                -  Target to extract the symbols/objects from
+#     SHARED_SYMBOL_TEMPLATE  -  Template with names of symbols to share
+macro(compiler_create_shared_code TARGET SHARED_SYMBOL_TEMPLATE)
+    # Create a temporary file, which contains all extracted symbols from 'TARGET'
+    set(ALL_SYMBOLS ${CMAKE_CURRENT_BINARY_DIR}/all_symbols.txt)
+
+    set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --symdefs=${ALL_SYMBOLS}")
+
+    # Find the CMake script doing the symbol filtering.
+    find_file(FILTER_SYMBOLS_SCRIPT "FilterSharedSymbols.cmake" PATHS ${CMAKE_MODULE_PATH} PATH_SUFFIXES Common NO_DEFAULT_PATH)
+
+    # Single step, just filter the unwanted symbols from symdefs file
+    add_custom_command(TARGET ${TARGET}
+                        POST_BUILD
+
+                        COMMAND ${CMAKE_COMMAND}
+                            -DSHARED_SYMBOL_TEMPLATE=${SHARED_SYMBOL_TEMPLATE}
+                            -DALL_SYMBOLS=${ALL_SYMBOLS}
+                            -P ${FILTER_SYMBOLS_SCRIPT}
+                        BYPRODUCTS
+                            ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_name.txt
+                            ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_addr.txt
+                        COMMENT "Filtering shared symbols"
+    )
+endmacro()
+
+macro(compiler_weaken_symbols TARGET SHARED_CODE_PATH ORIG_TARGET LIB_LIST)
+    # Find the CMake scripts
+    find_file(WEAKEN_SYMBOLS_SCRIPT "WeakenSymbols.cmake" PATHS ${CMAKE_MODULE_PATH} PATH_SUFFIXES Common NO_DEFAULT_PATH)
+
+    add_custom_command(TARGET ${TARGET}
+                        PRE_LINK
+
+                        COMMAND ${CMAKE_COMMAND}
+                            -DLIB_LIST='${LIB_LIST}'
+                            -DSHARED_CODE_PATH=${SHARED_CODE_PATH}
+                            -P ${WEAKEN_SYMBOLS_SCRIPT}
+                        COMMENT "Set conflicting symbols to be weak in the original libraries to avoid collision")
+
+    # If sharing target is defined by TF-M build then setup dependency
+    if(NOT ${ORIG_TARGET} STREQUAL "EXTERNAL_TARGET")
+        add_dependencies(${TARGET} ${ORIG_TARGET})
+    endif()
+endmacro()
+
+# Macro for linking shared code to given target. Location of shared code could
+# be outside of the TF-M project. Its location can be defined with the CMake
+# command line argument "SHARED_CODE_PATH". The file containing the shared objects
+# must be named "shared_symbols_addr.txt".
+# INPUTS:
+#     TARGET            Target to link the shared code to
+#     SHARED_CODE_PATH  Shared code located in this folder
+#     ORIG_TARGET       Target that shared code was extraced from <TARGET | "EXTERNAL_TARGET">
+#     LIB_LIST          List of libraries which are linked to top level target
+macro(compiler_link_shared_code TARGET SHARED_CODE_PATH ORIG_TARGET LIB_LIST)
+    # ARMCLANG requires adding a symbol definition file to the source file list.
+    # This is the output of the -symdefs compiler switch.
+    set_source_files_properties(${SHARED_CODE_PATH}/shared_symbols_addr.txt PROPERTIES EXTERNAL_OBJECT true GENERATED true)
+    target_sources(${TARGET} PRIVATE ${SHARED_CODE_PATH}/shared_symbols_addr.txt)
+
+    compiler_weaken_symbols(${TARGET}
+                            ${SHARED_CODE_PATH}
+                            ${ORIG_TARGET}
+                            "${LIB_LIST}"
+    )
+endmacro()
diff --git a/toolchain_GNUARM.cmake b/toolchain_GNUARM.cmake
index e530bf7..716a2cc 100644
--- a/toolchain_GNUARM.cmake
+++ b/toolchain_GNUARM.cmake
@@ -175,3 +175,96 @@
         DEPENDS ${target}_hex
     )
 endmacro()
+
+# Macro for sharing code among independent binaries. This function extracts
+# some parts of the code based on a symbol template file and creates a text
+# file, which contains the symbols with their absolute addresses, which can be
+# picked up by the linker when linking the other target.
+# INPUTS:
+#     TARGET -                -  Target to extract the symbols/objects from
+#     SHARED_SYMBOL_TEMPLATE  -  Template with names of symbols to share
+macro(compiler_create_shared_code TARGET SHARED_SYMBOL_TEMPLATE)
+    # Create a temporary file, which contains all extracted symbols from 'TARGET'
+    set(ALL_SYMBOLS ${CMAKE_CURRENT_BINARY_DIR}/all_symbols.txt)
+
+    # Find the CMake script doing the symbol filtering.
+    find_file(FILTER_SYMBOLS_SCRIPT "FilterSharedSymbols.cmake" PATHS ${CMAKE_MODULE_PATH} PATH_SUFFIXES Common NO_DEFAULT_PATH)
+    find_file(STRIP_UNSHARED_CODE   "StripUnsharedCode.cmake"   PATHS ${CMAKE_MODULE_PATH} PATH_SUFFIXES Common NO_DEFAULT_PATH)
+
+    find_program(GNUARM_NM arm-none-eabi-nm)
+    if (GNUARM_NM STREQUAL "GNUARM_NM-NOTFOUND")
+        message(FATAL_ERROR "toolchain_GNUARM.cmake: mandatory tool '${GNUARM_NM}' is missing.")
+    endif()
+
+    # Multiple steps are required:
+    #   - Extract all symbols from sharing target
+    #   - Filter the unwanted symbols from all_symbols.txt
+    #   - Create a stripped shared_code.axf file which contains only the symbols which are meant to be shared
+    add_custom_command(TARGET ${TARGET}
+                        POST_BUILD
+
+                        COMMAND ${GNUARM_NM}
+                        ARGS
+                            ${CMAKE_BINARY_DIR}/bin/${TARGET}.axf > ${ALL_SYMBOLS}
+                        COMMENT "Dumping all symbols"
+
+                        COMMAND ${CMAKE_COMMAND}
+                            -DSHARED_SYMBOL_TEMPLATE=${SHARED_SYMBOL_TEMPLATE}
+                            -DALL_SYMBOLS=${ALL_SYMBOLS}
+                            -P ${FILTER_SYMBOLS_SCRIPT}
+                        BYPRODUCTS
+                            ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_name.txt
+                            ${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_addr.txt
+                        COMMENT "Filtering shared symbols"
+
+                        COMMAND ${CMAKE_COMMAND}
+                            -E copy ${CMAKE_BINARY_DIR}/bin/${TARGET}.axf ${CMAKE_CURRENT_BINARY_DIR}/shared_code.axf
+                        COMMENT "Copy and rename ${TARGET} to strip"
+
+                        COMMAND ${CMAKE_COMMAND}
+                            -DSHARED_SYMBOLS_FILE=${CMAKE_CURRENT_BINARY_DIR}/shared_symbols_name.txt
+                            -DEXECUTABLE_TO_STRIP=${CMAKE_CURRENT_BINARY_DIR}/shared_code.axf
+                            -P ${STRIP_UNSHARED_CODE}
+                        COMMENT "Stripping unshared code from ${CMAKE_CURRENT_BINARY_DIR}/shared_code.axf"
+    )
+endmacro()
+
+macro(compiler_weaken_symbols TARGET SHARED_CODE_PATH ORIG_TARGET LIB_LIST)
+    # Find the CMake scripts
+    find_file(WEAKEN_SYMBOLS_SCRIPT "WeakenSymbols.cmake" PATHS ${CMAKE_MODULE_PATH} PATH_SUFFIXES Common NO_DEFAULT_PATH)
+
+    add_custom_command(TARGET ${TARGET}
+                        PRE_LINK
+
+                        COMMAND ${CMAKE_COMMAND}
+                            -DLIB_LIST='${LIB_LIST}'
+                            -DSHARED_CODE_PATH=${SHARED_CODE_PATH}
+                            -P ${WEAKEN_SYMBOLS_SCRIPT}
+                        COMMENT "Set conflicting symbols to be weak in the original libraries to avoid collision")
+
+    # If sharing target is defined by TF-M build then setup dependency
+    if(NOT ${ORIG_TARGET} STREQUAL "EXTERNAL_TARGET")
+        add_dependencies(${TARGET} ${ORIG_TARGET})
+    endif()
+endmacro()
+
+# Macro for linking shared code to given target. Location of shared code could
+# be outside of the TF-M project. Its location can be defined with the CMake
+# command line argument "SHARED_CODE_PATH". The file containing the shared objects
+# must be named "shared_symbols_addr.txt".
+# INPUTS:
+#     TARGET            Target to link the shared code to
+#     SHARED_CODE_PATH  Shared code located in this folder
+#     ORIG_TARGET       Target that shared code was extraced from <TARGET | "EXTERNAL_TARGET">
+#     LIB_LIST          List of libraries which are linked to top level target
+macro(compiler_link_shared_code TARGET SHARED_CODE_PATH ORIG_TARGET LIB_LIST)
+    # GNUARM requires to link a stripped version (only containing the shared symbols) of the
+    # original executable to the executable which want to rely on the shared symbols.
+    target_link_options(${TARGET} PRIVATE -Wl,-R${SHARED_CODE_PATH}/shared_code.axf)
+
+    compiler_weaken_symbols(${TARGET}
+                            ${SHARED_CODE_PATH}
+                            ${ORIG_TARGET}
+                            "${LIB_LIST}"
+    )
+endmacro()
\ No newline at end of file
diff --git a/toolchain_IARARM.cmake b/toolchain_IARARM.cmake
index 4a9662f..f471b7d 100644
--- a/toolchain_IARARM.cmake
+++ b/toolchain_IARARM.cmake
@@ -184,3 +184,11 @@
         DEPENDS ${target}_hex
     )
 endmacro()
+
+macro(compiler_create_shared_code TARGET SHARED_SYMBOL_TEMPLATE)
+    message(FATAL_ERROR "Code sharing support is not implemented by IAR.")
+endmacro()
+
+macro(compiler_link_shared_code TARGET SHARED_CODE_PATH ORIG_TARGET LIB_LIST)
+    message(FATAL_ERROR "Code sharing support is not implemented by IAR.")
+endmacro()
\ No newline at end of file