Build: Refactor code-sharing primitives

Makes the interface more aligned with modern cmake, and generally
streamlines the experience.

Change-Id: Iad289c7e6be1af1e7ae80d3792698a31b2d9368e
Signed-off-by: Raef Coles <raef.coles@arm.com>
diff --git a/bl2/CMakeLists.txt b/bl2/CMakeLists.txt
index f2c3365..5ad6a8b 100644
--- a/bl2/CMakeLists.txt
+++ b/bl2/CMakeLists.txt
@@ -136,7 +136,7 @@
 ############################### CODE SHARING ###################################
 
 if (TFM_CODE_SHARING)
-    compiler_create_shared_code(bl2 ${CMAKE_CURRENT_SOURCE_DIR}/src/shared_symbol_template.txt)
+    target_share_symbols(bl2 ${CMAKE_CURRENT_SOURCE_DIR}/bl2_shared_symbols.txt)
 
     if (NOT EXISTS ${MBEDCRYPTO_PATH}/library/code_share.c)
         message(FATAL_ERROR "File ${MBEDCRYPTO_PATH}/library/code_share.c does not exist.
diff --git a/bl2/bl2_shared_symbols.txt b/bl2/bl2_shared_symbols.txt
new file mode 100644
index 0000000..b7a1935
--- /dev/null
+++ b/bl2/bl2_shared_symbols.txt
@@ -0,0 +1,18 @@
+mbedtls_asn1*
+mbedtls_mpi*
+mbedtls_platform*
+mbedtls_rsa*
+
+mbedtls_md*
+
+mbedtls_internal_sha256*
+mbedtls_sha256_free
+mbedtls_sha256_init
+mbedtls_sha256_finish
+mbedtls_sha256_starts
+
+mbedtls_calloc*
+mbedtls_free*
+
+mbedtls_exit*
+memset_func*
diff --git a/bl2/src/shared_symbol_template.txt b/bl2/src/shared_symbol_template.txt
deleted file mode 100644
index 429e0bd..0000000
--- a/bl2/src/shared_symbol_template.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-# -----------------------------------------------------------
-# Copyright (c) 2020, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-# -----------------------------------------------------------
-
-#Groups of functions that can be always shared with no exceptions
-mbedtls_asn1
-
-mbedtls_mpi
-
-mbedtls_platform
-
-mbedtls_rsa
-
-#This group is only relevant if BL2 image encryption is on
-mbedtls_md
-
-#This group has two functions that cause runtime errors when shared, so the
-#error-free ones are listed piece by piece
-mbedtls_internal_sha256
-mbedtls_sha256_free
-mbedtls_sha256_init
-mbedtls_sha256_ret
-mbedtls_sha256_starts_ret
-
-#Symbols necessary to make sharing additional functions possible
-mbedtls_calloc
-mbedtls_free
-
-#Miscellaneous functions
-mbedtls_exit
-memset_func
\ No newline at end of file
diff --git a/cmake/Common/FilterSharedSymbols.cmake b/cmake/Common/FilterSharedSymbols.cmake
deleted file mode 100644
index 9a10b9f..0000000
--- a/cmake/Common/FilterSharedSymbols.cmake
+++ /dev/null
@@ -1,60 +0,0 @@
-#-------------------------------------------------------------------------------
-# 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.
-# 'D' is necessary to share two specific function pointers: 'mbedtls_calloc_func'
-# and 'mbedtls_free_func'. These also need the 'static' keyword removed in mbed-crypto
-set(_SHARED_SYMBOL_TYPES "T;D")
-
-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)
-            foreach(_TEXT IN LISTS _SHARED_SYMBOL_TYPES)
-                string(FIND ${_ONE_SYMBOL} "${_TEXT} ${_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 "${_TEXT} " "" _ONE_SYMBOL_NAME ${_ONE_SYMBOL_NAME})
-                    list(APPEND SHARED_SYMBOL_NAME_LIST "${_ONE_SYMBOL_NAME}")
-                endif()
-            endforeach()
-        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
deleted file mode 100644
index a2df391..0000000
--- a/cmake/Common/StripUnsharedCode.cmake
+++ /dev/null
@@ -1,40 +0,0 @@
-#-------------------------------------------------------------------------------
-# 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
deleted file mode 100644
index 0ae53d3..0000000
--- a/cmake/Common/WeakenSymbols.cmake
+++ /dev/null
@@ -1,77 +0,0 @@
-#-------------------------------------------------------------------------------
-# 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/check_config.cmake b/config/check_config.cmake
index d9338f6..2195729 100644
--- a/config/check_config.cmake
+++ b/config/check_config.cmake
@@ -74,7 +74,6 @@
 set(TFM_CODE_SHARING_PLATFORM_LISTS arm/mps2/an521 arm/musca_b1/sse_200) # Without crypto hw acceleration
 tfm_invalid_config(NOT TFM_CODE_SHARING STREQUAL "OFF" AND NOT TFM_PLATFORM IN_LIST TFM_CODE_SHARING_PLATFORM_LISTS)
 tfm_invalid_config(NOT TFM_CODE_SHARING STREQUAL "OFF" AND CRYPTO_HW_ACCELERATOR)
-tfm_invalid_config(TFM_CODE_SHARING STREQUAL "OFF" AND TFM_CODE_SHARING_PATH)
 
 ########################## Platform ############################################
 
diff --git a/config/config_default.cmake b/config/config_default.cmake
index 990cdda..424e73a 100755
--- a/config/config_default.cmake
+++ b/config/config_default.cmake
@@ -41,7 +41,6 @@
 set(TFM_PARTITION_LOG_LEVEL             TFM_PARTITION_LOG_LEVEL_INFO    CACHE STRING    "Set default Secure Partition 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")
 
 set(TFM_INSTALL_PATH                    ${CMAKE_BINARY_DIR}/install CACHE PATH "Path to which to install TF-M files")
 
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 6c1d654..40f055a 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -127,30 +127,38 @@
 
 ############################### CODE SHARING ###################################
 if (TFM_CODE_SHARING)
-    set(LIB_LIST mbedcrypto
-                 crypto_service_cc312
-                 platform_s
-                 tfm_psa_rot_partition_crypto
-                 tfm_psa_rot_partition_audit
-                 tfm_psa_rot_partition_attestation
-                 tfm_app_rot_partition_ps
-                 tfm_psa_rot_partition_its
-                 tfm_psa_rot_partition_platform
-                 platform_s
-                 tfm_sprt
-                 tfm_spm
+    target_link_shared_code(tfm_s
+        bl2
     )
-    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()
+
+    # mbedtls is build outside of tree, so we have to use the _from_dependency
+    # version of this function to attach the custom_command to the tfm_s target.
+    # It's also picky about stripping the symbols, so we just make them weak
+    # instead.
+    target_weaken_symbols_from_dependency(tfm_s crypto_service_mbedcrypto
+        mbedtls_asn1*
+        mbedtls_mpi*
+        mbedtls_platform*
+        mbedtls_rsa*
+
+        #This group is only relevant if BL2 image encryption is on
+        mbedtls_md*
+
+        #This group has two functions that cause runtime errors when shared, so the
+        #error-free ones are listed piece by piece
+        mbedtls_internal_sha256*
+        mbedtls_sha256_free
+        mbedtls_sha256_init
+        mbedtls_sha256_finish
+        mbedtls_sha256_starts
+
+        #Symbols necessary to make sharing additional functions possible
+        mbedtls_calloc*
+        mbedtls_free*
+
+        #Miscellaneous functions
+        mbedtls_exit*
+        memset_func*
+    )
+
 endif()
diff --git a/toolchain_ARMCLANG.cmake b/toolchain_ARMCLANG.cmake
index 8843484..b6e3e3a 100644
--- a/toolchain_ARMCLANG.cmake
+++ b/toolchain_ARMCLANG.cmake
@@ -313,74 +313,127 @@
     )
 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)
+macro(target_share_symbols target symbol_name_file)
+    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()
 
-    set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " --symdefs=${ALL_SYMBOLS}")
+    FILE(STRINGS ${symbol_name_file} KEEP_SYMBOL_LIST
+        LENGTH_MINIMUM 1
+    )
 
-    # 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)
+    # strip all the symbols except those proveded as arguments. Long inline
+    # python scripts aren't ideal, but this is both portable and possibly easier
+    # to maintain than trying to filter files at build time in cmake.
+    add_custom_command(TARGET ${target}
+        POST_BUILD
+        VERBATIM
+        COMMAND python3 -c "from sys import argv; import re; f = open(argv[1], 'rt'); p = [x.replace('*', '.*') for x in argv[2:]]; l = [x for x in f.readlines() if re.search(r'(?=('+'$|'.join(p + ['SYMDEFS']) + r'))', x)]; f.close(); f = open(argv[1], 'wt'); f.writelines(l); f.close();" $<TARGET_FILE_DIR:${target}>/${target}_shared_symbols.txt ${KEEP_SYMBOL_LIST})
 
-    # Single step, just filter the unwanted symbols from symdefs file
-    add_custom_command(TARGET ${TARGET}
-                        POST_BUILD
+    # Force the target to not remove the symbols if they're unused. Not
+    # currently possible on GNU, has to be part of the linker script.
+    list(TRANSFORM KEEP_SYMBOL_LIST PREPEND --keep=)
+    target_link_options(${target}
+        PRIVATE
+            ${KEEP_SYMBOL_LIST}
+    )
 
-                        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"
+    # Ask armclang to produce a symdefs file that will
+    target_link_options(${target}
+        PRIVATE
+            --symdefs=$<TARGET_FILE_DIR:${target}>/${target}_shared_symbols.txt
     )
 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)
+macro(target_link_shared_code target)
+    get_target_property(TARGET_SOURCE_DIR ${target} SOURCE_DIR)
 
-    add_custom_command(TARGET ${TARGET}
-                        PRE_LINK
+    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()
 
-                        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()
+        add_dependencies(${target} ${symbol_provider})
+        # Some cmake functions don't allow generator expressions, so get the
+        # property as a backup. If the symbol provider hasn't been created yet,
+        # then use the output dir of the target.
+        if (TARGET ${symbol_provider})
+            get_target_property(SYMBOL_PROVIDER_OUTPUT_DIR ${symbol_provider} RUNTIME_OUTPUT_DIRECTORY)
+        else()
+            get_target_property(SYMBOL_PROVIDER_OUTPUT_DIR ${target} RUNTIME_OUTPUT_DIRECTORY)
+        endif()
+        # Set these properties so that cmake will allow us to use a source file
+        # that doesn't exist at cmake-time, but we guarantee will exist at
+        # compile-time.
+        set_source_files_properties(${SYMBOL_PROVIDER_OUTPUT_DIR}/${symbol_provider}_shared_symbols.txt
+            DIRECTORY ${TARGET_SOURCE_DIR}
+            PROPERTIES
+                EXTERNAL_OBJECT true
+                GENERATED true
+        )
+        target_sources(${target}
+            PRIVATE
+                $<TARGET_FILE_DIR:${symbol_provider}>/${symbol_provider}_shared_symbols.txt
+        )
+    endforeach()
 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)
+macro(target_strip_symbols target)
+    set(SYMBOL_LIST "${ARGN}")
+    list(TRANSFORM SYMBOL_LIST PREPEND  --strip-symbol=)
 
-    compiler_weaken_symbols(${TARGET}
-                            ${SHARED_CODE_PATH}
-                            ${ORIG_TARGET}
-                            "${LIB_LIST}"
+    # TODO we assume that arm-none-eabi-objcopy is available - since we're using
+    # armclang this isn't necessarily true.
+    add_custom_command(
+        TARGET ${target}
+        POST_BUILD
+        COMMAND ${CROSS_COMPILE}-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=)
+
+    # TODO we assume that arm-none-eabi-objcopy is available - since we're using
+    # armclang this isn't necessarily true.
+    add_custom_command(
+        TARGET ${target}
+        PRE_LINK
+        COMMAND ${CROSS_COMPILE}-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=)
+
+    # TODO we assume that arm-none-eabi-objcopy is available - since we're using
+    # armclang this isn't necessarily true.
+    add_custom_command(
+        TARGET ${target}
+        POST_BUILD
+        COMMAND ${CROSS_COMPILE}-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=)
+
+    # TODO we assume that arm-none-eabi-objcopy is available - since we're using
+    # armclang this isn't necessarily true.
+    add_custom_command(
+        TARGET ${target}
+        PRE_LINK
+        COMMAND ${CROSS_COMPILE}-objcopy
+        ARGS $<TARGET_FILE:${dependency}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${dependency}>
     )
 endmacro()
diff --git a/toolchain_GNUARM.cmake b/toolchain_GNUARM.cmake
index 83eab4b..4efd4d0 100644
--- a/toolchain_GNUARM.cmake
+++ b/toolchain_GNUARM.cmake
@@ -256,95 +256,85 @@
     )
 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.")
+macro(target_share_symbols target symbol_name_file)
+    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()
 
-    # 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
+    FILE(STRINGS ${symbol_name_file} KEEP_SYMBOL_LIST
+        LENGTH_MINIMUM 1
+    )
 
-                        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"
+    list(TRANSFORM KEEP_SYMBOL_LIST PREPEND  --keep-symbol=)
+    # strip all the symbols except those proveded as arguments
+    add_custom_command(
+        TARGET ${target}
+        POST_BUILD
+        COMMAND ${CROSS_COMPILE}-objcopy
+        ARGS $<TARGET_FILE:${target}> --wildcard ${KEEP_SYMBOL_LIST} --strip-all $<TARGET_FILE_DIR:${target}>/${target}_shared_symbols.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)
+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()
 
-    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()
+        add_dependencies(${target} ${symbol_provider})
+        target_link_options(${target} PRIVATE LINKER:-R$<TARGET_FILE_DIR:${symbol_provider}>/${symbol_provider}_shared_symbols.axf)
+    endforeach()
 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)
+macro(target_strip_symbols target)
+    set(SYMBOL_LIST "${ARGN}")
+    list(TRANSFORM SYMBOL_LIST PREPEND  --strip-symbol=)
 
-    compiler_weaken_symbols(${TARGET}
-                            ${SHARED_CODE_PATH}
-                            ${ORIG_TARGET}
-                            "${LIB_LIST}"
+    add_custom_command(
+        TARGET ${target}
+        POST_BUILD
+        COMMAND ${CROSS_COMPILE}-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 ${CROSS_COMPILE}-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 ${CROSS_COMPILE}-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 ${CROSS_COMPILE}-objcopy
+        ARGS $<TARGET_FILE:${dependency}> --wildcard ${SYMBOL_LIST} $<TARGET_FILE:${dependency}>
     )
 endmacro()