123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- cmake_minimum_required(VERSION 3.17)
- 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 equivalant ?
- #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()
|