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>
This commit is contained in:
parent
2628db7262
commit
4351ec2b4d
|
@ -136,7 +136,7 @@ target_compile_options(bl2_mbedx509
|
|||
############################### 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.
|
||||
|
|
|
@ -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*
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -74,7 +74,6 @@ tfm_invalid_config(BL2 AND (NOT MCUBOOT_ALIGN_VAL IN_LIST MCUBOOT_ALIGN_VAL_LIST
|
|||
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 ############################################
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ set(TFM_SPM_LOG_LEVEL TFM_SPM_LOG_LEVEL_INFO CACHE ST
|
|||
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")
|
||||
|
||||
|
|
|
@ -127,30 +127,38 @@ endif()
|
|||
|
||||
############################### 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()
|
||||
|
|
|
@ -313,74 +313,127 @@ macro(add_convert_to_bin_target target)
|
|||
)
|
||||
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})
|
||||
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()
|
||||
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)
|
||||
FILE(STRINGS ${symbol_name_file} KEEP_SYMBOL_LIST
|
||||
LENGTH_MINIMUM 1
|
||||
)
|
||||
|
||||
compiler_weaken_symbols(${TARGET}
|
||||
${SHARED_CODE_PATH}
|
||||
${ORIG_TARGET}
|
||||
"${LIB_LIST}"
|
||||
# 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})
|
||||
|
||||
# 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}
|
||||
)
|
||||
|
||||
# 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(target_link_shared_code target)
|
||||
get_target_property(TARGET_SOURCE_DIR ${target} SOURCE_DIR)
|
||||
|
||||
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_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(target_strip_symbols target)
|
||||
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}
|
||||
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()
|
||||
|
|
|
@ -256,95 +256,85 @@ macro(add_convert_to_bin_target target)
|
|||
)
|
||||
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()
|
||||
|
|
Loading…
Reference in New Issue