445 lines
16 KiB
CMake
445 lines
16 KiB
CMake
cmake_minimum_required(VERSION 3.20.0)
|
|
|
|
set(SORT_TYPE_NAME Lexical)
|
|
|
|
# This function post process the region for easier use.
|
|
#
|
|
# Tasks:
|
|
# - Symbol translation using a steering file is configured.
|
|
function(process_region)
|
|
cmake_parse_arguments(REGION "" "OBJECT" "" ${ARGN})
|
|
|
|
process_region_common(${ARGN})
|
|
|
|
get_property(empty GLOBAL PROPERTY ${REGION_OBJECT}_EMPTY)
|
|
if(NOT empty)
|
|
# For scatter files we move any system symbols into first non-empty load section.
|
|
get_parent(OBJECT ${REGION_OBJECT} PARENT parent TYPE SYSTEM)
|
|
get_property(symbols GLOBAL PROPERTY ${parent}_SYMBOLS)
|
|
set_property(GLOBAL APPEND PROPERTY ${REGION_OBJECT}_SYMBOLS ${symbols})
|
|
set_property(GLOBAL PROPERTY ${parent}_SYMBOLS)
|
|
endif()
|
|
|
|
get_property(sections GLOBAL PROPERTY ${REGION_OBJECT}_SECTION_LIST_ORDERED)
|
|
foreach(section ${sections})
|
|
|
|
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
get_property(noinput GLOBAL PROPERTY ${section}_NOINPUT)
|
|
get_property(type GLOBAL PROPERTY ${section}_TYPE)
|
|
|
|
get_property(indicies GLOBAL PROPERTY ${section}_SETTINGS_INDICIES)
|
|
list(LENGTH indicies length)
|
|
foreach(idx ${indicies})
|
|
set(steering_postfixes Base Limit)
|
|
get_property(symbols GLOBAL PROPERTY ${section}_SETTING_${idx}_SYMBOLS)
|
|
get_property(sort GLOBAL PROPERTY ${section}_SETTING_${idx}_SORT)
|
|
get_property(offset GLOBAL PROPERTY ${section}_SETTING_${idx}_OFFSET)
|
|
if(DEFINED offset)
|
|
foreach(symbol ${symbols})
|
|
list(POP_FRONT steering_postfixes postfix)
|
|
math(EXPR offset_dec "${offset}")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C
|
|
"Image$$${name_clean}_${offset_dec}$$${postfix}"
|
|
)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE ${symbol} AS Image$$${name_clean}_${offset_dec}$$${postfix}\n"
|
|
)
|
|
endforeach()
|
|
elseif(sort)
|
|
foreach(symbol ${symbols})
|
|
list(POP_FRONT steering_postfixes postfix)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C
|
|
"Image$$${name_clean}_${idx}$$${postfix}"
|
|
)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE ${symbol} AS Image$$${name_clean}_${idx}$$${postfix}\n"
|
|
)
|
|
endforeach()
|
|
elseif(DEFINED symbols AND ${length} EQUAL 1 AND noinput)
|
|
set(steering_postfixes Base Limit)
|
|
foreach(symbol ${symbols})
|
|
list(POP_FRONT steering_postfixes postfix)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C
|
|
"Image$$${name_clean}$$${postfix}"
|
|
)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE ${symbol} AS Image$$${name_clean}$$${postfix}\n"
|
|
)
|
|
endforeach()
|
|
endif()
|
|
endforeach()
|
|
|
|
if("${type}" STREQUAL BSS)
|
|
set(ZI "$$ZI")
|
|
endif()
|
|
|
|
# Symbols translation here.
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${name_clean}${ZI}$$Base")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${name_clean}${ZI}$$Length")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Load$$${name_clean}${ZI}$$Base")
|
|
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE __${name_clean}_start AS Image$$${name_clean}${ZI}$$Base\n"
|
|
"RESOLVE __${name_clean}_load_start AS Load$$${name_clean}${ZI}$$Base\n"
|
|
"EXPORT __${name_clean}_start AS __${name_clean}_start\n"
|
|
)
|
|
|
|
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${symbol_val}${ZI}$$Limit")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE __${name_clean}_end AS Image$$${symbol_val}${ZI}$$Limit\n"
|
|
)
|
|
|
|
if("${symbol_val}" STREQUAL "${name_clean}")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE __${name_clean}_size AS Image$$${name_clean}${ZI}$$Length\n"
|
|
)
|
|
else()
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_size
|
|
EXPR "(ImageLimit(${symbol_val}${ZI}) - ImageBase(${name_clean}${ZI}))"
|
|
)
|
|
endif()
|
|
set(ZI)
|
|
|
|
endforeach()
|
|
|
|
get_property(groups GLOBAL PROPERTY ${REGION_OBJECT}_GROUP_LIST_ORDERED)
|
|
foreach(group ${groups})
|
|
get_property(name GLOBAL PROPERTY ${group}_NAME)
|
|
string(TOLOWER ${name} name)
|
|
|
|
get_objects(LIST sections OBJECT ${group} TYPE SECTION)
|
|
list(GET sections 0 section)
|
|
get_property(first_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
list(POP_BACK sections section)
|
|
get_property(last_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
|
|
# Symbols translation here.
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${first_section_name}$$Base")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Load$$${first_section_name}$$Base")
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${last_section_name}$$Limit")
|
|
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE __${name}_start AS Image$$${first_section_name}$$Base\n"
|
|
"EXPORT __${name}_start AS __${name}_start\n"
|
|
"RESOLVE __${name}_load_start AS Load$$${first_section_name}$$Base\n"
|
|
"EXPORT __${name}_load_start AS __${name}_load_start\n"
|
|
)
|
|
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE __${name}_end AS Image$$${last_section_name}$$Limit\n"
|
|
)
|
|
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_size
|
|
EXPR "(ImageLimit(${last_section_name}) - ImageBase(${first_section_name}))"
|
|
)
|
|
endforeach()
|
|
|
|
get_property(symbols GLOBAL PROPERTY ${REGION_OBJECT}_SYMBOLS)
|
|
foreach(symbol ${symbols})
|
|
get_property(name GLOBAL PROPERTY ${symbol}_NAME)
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${name}$$Base")
|
|
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"RESOLVE ${name} AS Image$$${name}$$Base\n"
|
|
)
|
|
endforeach()
|
|
|
|
endfunction()
|
|
|
|
#
|
|
# String functions - start
|
|
#
|
|
|
|
function(system_to_string)
|
|
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
|
|
|
|
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
|
|
get_property(regions GLOBAL PROPERTY ${STRING_OBJECT}_REGIONS)
|
|
get_property(format GLOBAL PROPERTY ${STRING_OBJECT}_FORMAT)
|
|
|
|
foreach(region ${regions})
|
|
get_property(empty GLOBAL PROPERTY ${region}_EMPTY)
|
|
if(NOT empty)
|
|
to_string(OBJECT ${region} STRING ${STRING_STRING})
|
|
endif()
|
|
endforeach()
|
|
|
|
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(group_to_string)
|
|
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
|
|
|
|
get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
|
|
if(${type} STREQUAL REGION)
|
|
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
|
|
get_property(address GLOBAL PROPERTY ${STRING_OBJECT}_ADDRESS)
|
|
get_property(size GLOBAL PROPERTY ${STRING_OBJECT}_SIZE)
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n${name} ${address} NOCOMPRESS ${size}\n{\n")
|
|
endif()
|
|
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS)
|
|
foreach(group ${groups})
|
|
to_string(OBJECT ${group} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM)
|
|
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
|
|
list(REMOVE_ITEM regions ${STRING_OBJECT})
|
|
foreach(region ${regions})
|
|
get_property(vma GLOBAL PROPERTY ${region}_NAME)
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS)
|
|
foreach(group ${groups})
|
|
to_string(OBJECT ${group} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
endforeach()
|
|
endforeach()
|
|
|
|
get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS)
|
|
foreach(symbol ${symbols})
|
|
to_string(OBJECT ${symbol} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
if(${type} STREQUAL REGION)
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n}\n")
|
|
endif()
|
|
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
|
|
function(section_to_string)
|
|
cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN})
|
|
|
|
get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME)
|
|
get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS)
|
|
get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE)
|
|
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN)
|
|
get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN)
|
|
get_property(endalign GLOBAL PROPERTY ${STRING_SECTION}_ENDALIGN)
|
|
get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA)
|
|
get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT)
|
|
get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT)
|
|
|
|
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
|
|
string(REPLACE "." "_" name_clean "${name_clean}")
|
|
|
|
set(TEMP " ${name_clean}")
|
|
if(DEFINED address)
|
|
set(TEMP "${TEMP} ${address}")
|
|
else()
|
|
set(TEMP "${TEMP} +0")
|
|
endif()
|
|
|
|
if(noinit)
|
|
# Currently we simply uses offset +0, but we must support offset defined
|
|
# externally.
|
|
set(TEMP "${TEMP} UNINIT")
|
|
endif()
|
|
|
|
if(subalign)
|
|
# Currently we simply uses offset +0, but we must support offset defined
|
|
# externally.
|
|
set(TEMP "${TEMP} ALIGN ${subalign}")
|
|
endif()
|
|
|
|
if(NOT noinput)
|
|
set(TEMP "${TEMP}\n {")
|
|
|
|
if("${type}" STREQUAL NOLOAD)
|
|
set(TEMP "${TEMP}\n *.o(${name}*)")
|
|
set(TEMP "${TEMP}\n *.o(${name}*.*)")
|
|
elseif(VMA_FLAGS)
|
|
# ToDo: Proper names as provided by armclang
|
|
# set(TEMP "${TEMP}\n *.o(${SEC_NAME}*, +${VMA_FLAGS})")
|
|
# set(TEMP "${TEMP}\n *.o(${SEC_NAME}*.*, +${VMA_FLAGS})")
|
|
set(TEMP "${TEMP}\n *.o(${name}*)")
|
|
set(TEMP "${TEMP}\n *.o(${name}*.*)")
|
|
else()
|
|
set(TEMP "${TEMP}\n *.o(${name}*)")
|
|
set(TEMP "${TEMP}\n *.o(${name}*.*)")
|
|
endif()
|
|
else()
|
|
set(empty TRUE)
|
|
endif()
|
|
|
|
get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
|
|
foreach(idx ${indicies})
|
|
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN)
|
|
get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY)
|
|
get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST)
|
|
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP)
|
|
get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT)
|
|
get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS)
|
|
get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT)
|
|
get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_OFFSET)
|
|
if(DEFINED offset)
|
|
set(section_close TRUE)
|
|
math(EXPR offset_dec "${offset} + 0")
|
|
if(empty)
|
|
set(TEMP "${TEMP} EMPTY 0x0\n {")
|
|
set(empty FALSE)
|
|
endif()
|
|
set(last_index ${offset_dec})
|
|
if(sort)
|
|
set(sorttype "SORTTYPE ${SORT_TYPE_${sort}}")
|
|
endif()
|
|
set(TEMP "${TEMP}\n }")
|
|
set(TEMP "${TEMP}\n ${name_clean}_${offset_dec} (ImageBase(${name_clean}) + ${offset}) ${sorttype}\n {")
|
|
elseif(sort)
|
|
set(section_close TRUE)
|
|
if(empty)
|
|
set(TEMP "${TEMP} EMPTY 0x0\n {")
|
|
set(empty FALSE)
|
|
endif()
|
|
set(last_index ${idx})
|
|
set(TEMP "${TEMP}\n }")
|
|
set(TEMP "${TEMP}\n ${name_clean}_${idx} +0 SORTTYPE ${SORT_TYPE_${sort}}\n {")
|
|
endif()
|
|
|
|
if(empty)
|
|
set(TEMP "${TEMP}\n {")
|
|
set(empty FALSE)
|
|
endif()
|
|
|
|
foreach(setting ${input})
|
|
#set(SETTINGS ${SETTINGS_INPUT})
|
|
|
|
# # ToDo: The code below had en error in original implementation, causing
|
|
# # settings not to be applied
|
|
# # Verify behaviour and activate if working as intended.
|
|
# if(align)
|
|
# set(setting "${setting}, OVERALIGN ${align}")
|
|
# endif()
|
|
|
|
#if(SETTINGS_KEEP)
|
|
# armlink has --keep=<section_id>, but is there an scatter equivalent ?
|
|
#endif()
|
|
|
|
if(first)
|
|
set(setting "${setting}, +First")
|
|
set(first "")
|
|
endif()
|
|
|
|
set(TEMP "${TEMP}\n *.o(${setting})")
|
|
endforeach()
|
|
|
|
if(any)
|
|
if(NOT flags)
|
|
message(FATAL_ERROR ".ANY requires flags to be set.")
|
|
endif()
|
|
string(REPLACE ";" " " flags "${flags}")
|
|
|
|
set(TEMP "${TEMP}\n .ANY (${flags})")
|
|
endif()
|
|
endforeach()
|
|
|
|
if(section_close OR DEFINED endalign)
|
|
set(section_close)
|
|
set(TEMP "${TEMP}\n }")
|
|
|
|
if(DEFINED endalign)
|
|
if(DEFINED last_index)
|
|
set(align_expr "AlignExpr(ImageLimit(${name_clean}_${last_index}), ${endalign}) FIXED")
|
|
else()
|
|
set(align_expr "AlignExpr(ImageLimit(${name_clean}), ${endalign}) FIXED")
|
|
endif()
|
|
else()
|
|
set(align_expr "+0")
|
|
endif()
|
|
|
|
set(TEMP "${TEMP}\n ${name_clean}_end ${align_expr} EMPTY 0x0\n {")
|
|
set(last_index)
|
|
endif()
|
|
|
|
set(TEMP "${TEMP}")
|
|
# ToDo: add patterns here.
|
|
|
|
if("${type}" STREQUAL BSS)
|
|
set(ZI "$$ZI")
|
|
endif()
|
|
|
|
set(TEMP "${TEMP}\n }")
|
|
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(symbol_to_string)
|
|
cmake_parse_arguments(STRING "" "SYMBOL;STRING" "" ${ARGN})
|
|
|
|
get_property(name GLOBAL PROPERTY ${STRING_SYMBOL}_NAME)
|
|
get_property(expr GLOBAL PROPERTY ${STRING_SYMBOL}_EXPR)
|
|
get_property(size GLOBAL PROPERTY ${STRING_SYMBOL}_SIZE)
|
|
get_property(symbol GLOBAL PROPERTY ${STRING_SYMBOL}_SYMBOL)
|
|
get_property(subalign GLOBAL PROPERTY ${STRING_SYMBOL}_SUBALIGN)
|
|
|
|
string(REPLACE "\\" "" expr "${expr}")
|
|
string(REGEX MATCHALL "@([^@]*)@" match_res ${expr})
|
|
|
|
foreach(match ${match_res})
|
|
string(REPLACE "@" "" match ${match})
|
|
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match})
|
|
string(REPLACE "@${match}@" "ImageBase(${symbol_val})" expr ${expr})
|
|
endforeach()
|
|
|
|
if(DEFINED subalign)
|
|
set(subalign "ALIGN ${subalign}")
|
|
endif()
|
|
|
|
if(NOT DEFINED size)
|
|
set(size "0x0")
|
|
endif()
|
|
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}\n ${symbol} ${expr} ${subalign} ${size} { }\n"
|
|
PARENT_SCOPE
|
|
)
|
|
endfunction()
|
|
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake)
|
|
|
|
if(DEFINED STEERING_C)
|
|
get_property(symbols_c GLOBAL PROPERTY SYMBOL_STEERING_C)
|
|
file(WRITE ${STEERING_C} "/* AUTO-GENERATED - Do not modify\n")
|
|
file(APPEND ${STEERING_C} " * AUTO-GENERATED - All changes will be lost\n")
|
|
file(APPEND ${STEERING_C} " */\n")
|
|
foreach(symbol ${symbols_c})
|
|
file(APPEND ${STEERING_C} "extern char ${symbol}[];\n")
|
|
endforeach()
|
|
|
|
file(APPEND ${STEERING_C} "\nint __armlink_symbol_steering(void) {\n")
|
|
file(APPEND ${STEERING_C} "\treturn\n")
|
|
foreach(symbol ${symbols_c})
|
|
file(APPEND ${STEERING_C} "\t\t${OPERAND} (int)${symbol}\n")
|
|
set(OPERAND "&")
|
|
endforeach()
|
|
file(APPEND ${STEERING_C} "\t;\n}\n")
|
|
endif()
|
|
|
|
if(DEFINED STEERING_FILE)
|
|
get_property(steering_content GLOBAL PROPERTY SYMBOL_STEERING_FILE)
|
|
file(WRITE ${STEERING_FILE} "; AUTO-GENERATED - Do not modify\n")
|
|
file(APPEND ${STEERING_FILE} "; AUTO-GENERATED - All changes will be lost\n")
|
|
file(APPEND ${STEERING_FILE} ${steering_content})
|
|
endif()
|