1cmake_minimum_required(VERSION 3.20.0) 2 3set(SORT_TYPE_NAME Lexical) 4 5# This function post process the region for easier use. 6# 7# Tasks: 8# - Symbol translation using a steering file is configured. 9function(process_region) 10 cmake_parse_arguments(REGION "" "OBJECT" "" ${ARGN}) 11 12 process_region_common(${ARGN}) 13 14 get_property(empty GLOBAL PROPERTY ${REGION_OBJECT}_EMPTY) 15 if(NOT empty) 16 # For scatter files we move any system symbols into first non-empty load section. 17 get_parent(OBJECT ${REGION_OBJECT} PARENT parent TYPE SYSTEM) 18 get_property(symbols GLOBAL PROPERTY ${parent}_SYMBOLS) 19 set_property(GLOBAL APPEND PROPERTY ${REGION_OBJECT}_SYMBOLS ${symbols}) 20 set_property(GLOBAL PROPERTY ${parent}_SYMBOLS) 21 endif() 22 23 get_property(sections GLOBAL PROPERTY ${REGION_OBJECT}_SECTION_LIST_ORDERED) 24 foreach(section ${sections}) 25 26 get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN) 27 get_property(noinput GLOBAL PROPERTY ${section}_NOINPUT) 28 get_property(type GLOBAL PROPERTY ${section}_TYPE) 29 30 get_property(indicies GLOBAL PROPERTY ${section}_SETTINGS_INDICIES) 31 list(LENGTH indicies length) 32 foreach(idx ${indicies}) 33 set(steering_postfixes Base Limit) 34 get_property(symbols GLOBAL PROPERTY ${section}_SETTING_${idx}_SYMBOLS) 35 get_property(sort GLOBAL PROPERTY ${section}_SETTING_${idx}_SORT) 36 get_property(offset GLOBAL PROPERTY ${section}_SETTING_${idx}_OFFSET) 37 if(DEFINED offset) 38 foreach(symbol ${symbols}) 39 list(POP_FRONT steering_postfixes postfix) 40 math(EXPR offset_dec "${offset}") 41 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C 42 "Image$$${name_clean}_${offset_dec}$$${postfix}" 43 ) 44 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 45 "RESOLVE ${symbol} AS Image$$${name_clean}_${offset_dec}$$${postfix}\n" 46 ) 47 endforeach() 48 elseif(sort) 49 foreach(symbol ${symbols}) 50 list(POP_FRONT steering_postfixes postfix) 51 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C 52 "Image$$${name_clean}_${idx}$$${postfix}" 53 ) 54 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 55 "RESOLVE ${symbol} AS Image$$${name_clean}_${idx}$$${postfix}\n" 56 ) 57 endforeach() 58 elseif(DEFINED symbols AND ${length} EQUAL 1 AND noinput) 59 set(steering_postfixes Base Limit) 60 foreach(symbol ${symbols}) 61 list(POP_FRONT steering_postfixes postfix) 62 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C 63 "Image$$${name_clean}$$${postfix}" 64 ) 65 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 66 "RESOLVE ${symbol} AS Image$$${name_clean}$$${postfix}\n" 67 ) 68 endforeach() 69 endif() 70 endforeach() 71 72 if("${type}" STREQUAL BSS) 73 set(ZI "$$ZI") 74 endif() 75 76 # Symbols translation here. 77 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${name_clean}${ZI}$$Base") 78 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${name_clean}${ZI}$$Length") 79 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Load$$${name_clean}${ZI}$$Base") 80 81 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 82 "RESOLVE __${name_clean}_start AS Image$$${name_clean}${ZI}$$Base\n" 83 "RESOLVE __${name_clean}_load_start AS Load$$${name_clean}${ZI}$$Base\n" 84 "EXPORT __${name_clean}_start AS __${name_clean}_start\n" 85 ) 86 87 get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end) 88 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${symbol_val}${ZI}$$Limit") 89 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 90 "RESOLVE __${name_clean}_end AS Image$$${symbol_val}${ZI}$$Limit\n" 91 ) 92 93 if("${symbol_val}" STREQUAL "${name_clean}") 94 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 95 "RESOLVE __${name_clean}_size AS Image$$${name_clean}${ZI}$$Length\n" 96 ) 97 else() 98 create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_size 99 EXPR "(ImageLimit(${symbol_val}${ZI}) - ImageBase(${name_clean}${ZI}))" 100 ) 101 endif() 102 set(ZI) 103 104 endforeach() 105 106 get_property(groups GLOBAL PROPERTY ${REGION_OBJECT}_GROUP_LIST_ORDERED) 107 foreach(group ${groups}) 108 get_property(name GLOBAL PROPERTY ${group}_NAME) 109 string(TOLOWER ${name} name) 110 111 get_objects(LIST sections OBJECT ${group} TYPE SECTION) 112 list(GET sections 0 section) 113 get_property(first_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN) 114 list(POP_BACK sections section) 115 get_property(last_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN) 116 117 # Symbols translation here. 118 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${first_section_name}$$Base") 119 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Load$$${first_section_name}$$Base") 120 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${last_section_name}$$Limit") 121 122 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 123 "RESOLVE __${name}_start AS Image$$${first_section_name}$$Base\n" 124 "EXPORT __${name}_start AS __${name}_start\n" 125 "RESOLVE __${name}_load_start AS Load$$${first_section_name}$$Base\n" 126 "EXPORT __${name}_load_start AS __${name}_load_start\n" 127 ) 128 129 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 130 "RESOLVE __${name}_end AS Image$$${last_section_name}$$Limit\n" 131 ) 132 133 create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_size 134 EXPR "(ImageLimit(${last_section_name}) - ImageBase(${first_section_name}))" 135 ) 136 endforeach() 137 138 get_property(symbols GLOBAL PROPERTY ${REGION_OBJECT}_SYMBOLS) 139 foreach(symbol ${symbols}) 140 get_property(name GLOBAL PROPERTY ${symbol}_NAME) 141 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_C "Image$$${name}$$Base") 142 143 set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE 144 "RESOLVE ${name} AS Image$$${name}$$Base\n" 145 ) 146 endforeach() 147 148endfunction() 149 150# 151# String functions - start 152# 153 154function(system_to_string) 155 cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN}) 156 157 get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME) 158 get_property(regions GLOBAL PROPERTY ${STRING_OBJECT}_REGIONS) 159 get_property(format GLOBAL PROPERTY ${STRING_OBJECT}_FORMAT) 160 161 foreach(region ${regions}) 162 get_property(empty GLOBAL PROPERTY ${region}_EMPTY) 163 if(NOT empty) 164 to_string(OBJECT ${region} STRING ${STRING_STRING}) 165 endif() 166 endforeach() 167 168 set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE) 169endfunction() 170 171function(group_to_string) 172 cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN}) 173 174 get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE) 175 if(${type} STREQUAL REGION) 176 get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME) 177 get_property(address GLOBAL PROPERTY ${STRING_OBJECT}_ADDRESS) 178 get_property(size GLOBAL PROPERTY ${STRING_OBJECT}_SIZE) 179 set(${STRING_STRING} "${${STRING_STRING}}\n${name} ${address} NOCOMPRESS ${size}\n{\n") 180 endif() 181 182 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED) 183 foreach(section ${sections}) 184 to_string(OBJECT ${section} STRING ${STRING_STRING}) 185 endforeach() 186 187 get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS) 188 foreach(group ${groups}) 189 to_string(OBJECT ${group} STRING ${STRING_STRING}) 190 endforeach() 191 192 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS) 193 foreach(section ${sections}) 194 to_string(OBJECT ${section} STRING ${STRING_STRING}) 195 endforeach() 196 197 get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM) 198 get_property(regions GLOBAL PROPERTY ${parent}_REGIONS) 199 list(REMOVE_ITEM regions ${STRING_OBJECT}) 200 foreach(region ${regions}) 201 get_property(vma GLOBAL PROPERTY ${region}_NAME) 202 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED) 203 foreach(section ${sections}) 204 to_string(OBJECT ${section} STRING ${STRING_STRING}) 205 endforeach() 206 207 get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS) 208 foreach(group ${groups}) 209 to_string(OBJECT ${group} STRING ${STRING_STRING}) 210 endforeach() 211 212 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS) 213 foreach(section ${sections}) 214 to_string(OBJECT ${section} STRING ${STRING_STRING}) 215 endforeach() 216 endforeach() 217 218 get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS) 219 foreach(symbol ${symbols}) 220 to_string(OBJECT ${symbol} STRING ${STRING_STRING}) 221 endforeach() 222 223 if(${type} STREQUAL REGION) 224 set(${STRING_STRING} "${${STRING_STRING}}\n}\n") 225 endif() 226 set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE) 227endfunction() 228 229 230function(section_to_string) 231 cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN}) 232 233 get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME) 234 get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS) 235 get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE) 236 get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN) 237 get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN) 238 get_property(endalign GLOBAL PROPERTY ${STRING_SECTION}_ENDALIGN) 239 get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA) 240 get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA) 241 get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT) 242 get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT) 243 244 string(REGEX REPLACE "^[\.]" "" name_clean "${name}") 245 string(REPLACE "." "_" name_clean "${name_clean}") 246 247 set(TEMP " ${name_clean}") 248 if(DEFINED address) 249 set(TEMP "${TEMP} ${address}") 250 else() 251 set(TEMP "${TEMP} +0") 252 endif() 253 254 if(noinit) 255 # Currently we simply uses offset +0, but we must support offset defined 256 # externally. 257 set(TEMP "${TEMP} UNINIT") 258 endif() 259 260 if(subalign) 261 # Currently we simply uses offset +0, but we must support offset defined 262 # externally. 263 set(TEMP "${TEMP} ALIGN ${subalign}") 264 endif() 265 266 if(NOT noinput) 267 set(TEMP "${TEMP}\n {") 268 269 if("${type}" STREQUAL NOLOAD) 270 set(TEMP "${TEMP}\n *.o(${name}*)") 271 set(TEMP "${TEMP}\n *.o(${name}*.*)") 272 elseif(VMA_FLAGS) 273 # ToDo: Proper names as provided by armclang 274# set(TEMP "${TEMP}\n *.o(${SEC_NAME}*, +${VMA_FLAGS})") 275# set(TEMP "${TEMP}\n *.o(${SEC_NAME}*.*, +${VMA_FLAGS})") 276 set(TEMP "${TEMP}\n *.o(${name}*)") 277 set(TEMP "${TEMP}\n *.o(${name}*.*)") 278 else() 279 set(TEMP "${TEMP}\n *.o(${name}*)") 280 set(TEMP "${TEMP}\n *.o(${name}*.*)") 281 endif() 282 else() 283 set(empty TRUE) 284 endif() 285 286 get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES) 287 foreach(idx ${indicies}) 288 get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN) 289 get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY) 290 get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST) 291 get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP) 292 get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT) 293 get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS) 294 get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT) 295 get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_OFFSET) 296 if(DEFINED offset) 297 set(section_close TRUE) 298 math(EXPR offset_dec "${offset} + 0") 299 if(empty) 300 set(TEMP "${TEMP} EMPTY 0x0\n {") 301 set(empty FALSE) 302 endif() 303 set(last_index ${offset_dec}) 304 if(sort) 305 set(sorttype "SORTTYPE ${SORT_TYPE_${sort}}") 306 endif() 307 set(TEMP "${TEMP}\n }") 308 set(TEMP "${TEMP}\n ${name_clean}_${offset_dec} (ImageBase(${name_clean}) + ${offset}) ${sorttype}\n {") 309 elseif(sort) 310 set(section_close TRUE) 311 if(empty) 312 set(TEMP "${TEMP} EMPTY 0x0\n {") 313 set(empty FALSE) 314 endif() 315 set(last_index ${idx}) 316 set(TEMP "${TEMP}\n }") 317 set(TEMP "${TEMP}\n ${name_clean}_${idx} +0 SORTTYPE ${SORT_TYPE_${sort}}\n {") 318 endif() 319 320 if(empty) 321 set(TEMP "${TEMP}\n {") 322 set(empty FALSE) 323 endif() 324 325 foreach(setting ${input}) 326 #set(SETTINGS ${SETTINGS_INPUT}) 327 328# # ToDo: The code below had en error in original implementation, causing 329# # settings not to be applied 330# # Verify behaviour and activate if working as intended. 331# if(align) 332# set(setting "${setting}, OVERALIGN ${align}") 333# endif() 334 335 #if(SETTINGS_KEEP) 336 # armlink has --keep=<section_id>, but is there an scatter equivalent ? 337 #endif() 338 339 if(first) 340 set(setting "${setting}, +First") 341 set(first "") 342 endif() 343 344 set(TEMP "${TEMP}\n *.o(${setting})") 345 endforeach() 346 347 if(any) 348 if(NOT flags) 349 message(FATAL_ERROR ".ANY requires flags to be set.") 350 endif() 351 string(REPLACE ";" " " flags "${flags}") 352 353 set(TEMP "${TEMP}\n .ANY (${flags})") 354 endif() 355 endforeach() 356 357 if(section_close OR DEFINED endalign) 358 set(section_close) 359 set(TEMP "${TEMP}\n }") 360 361 if(DEFINED endalign) 362 if(DEFINED last_index) 363 set(align_expr "AlignExpr(ImageLimit(${name_clean}_${last_index}), ${endalign}) FIXED") 364 else() 365 set(align_expr "AlignExpr(ImageLimit(${name_clean}), ${endalign}) FIXED") 366 endif() 367 else() 368 set(align_expr "+0") 369 endif() 370 371 set(TEMP "${TEMP}\n ${name_clean}_end ${align_expr} EMPTY 0x0\n {") 372 set(last_index) 373 endif() 374 375 set(TEMP "${TEMP}") 376 # ToDo: add patterns here. 377 378 if("${type}" STREQUAL BSS) 379 set(ZI "$$ZI") 380 endif() 381 382 set(TEMP "${TEMP}\n }") 383 384 set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE) 385endfunction() 386 387function(symbol_to_string) 388 cmake_parse_arguments(STRING "" "SYMBOL;STRING" "" ${ARGN}) 389 390 get_property(name GLOBAL PROPERTY ${STRING_SYMBOL}_NAME) 391 get_property(expr GLOBAL PROPERTY ${STRING_SYMBOL}_EXPR) 392 get_property(size GLOBAL PROPERTY ${STRING_SYMBOL}_SIZE) 393 get_property(symbol GLOBAL PROPERTY ${STRING_SYMBOL}_SYMBOL) 394 get_property(subalign GLOBAL PROPERTY ${STRING_SYMBOL}_SUBALIGN) 395 396 string(REPLACE "\\" "" expr "${expr}") 397 string(REGEX MATCHALL "@([^@]*)@" match_res ${expr}) 398 399 foreach(match ${match_res}) 400 string(REPLACE "@" "" match ${match}) 401 get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match}) 402 string(REPLACE "@${match}@" "ImageBase(${symbol_val})" expr ${expr}) 403 endforeach() 404 405 if(DEFINED subalign) 406 set(subalign "ALIGN ${subalign}") 407 endif() 408 409 if(NOT DEFINED size) 410 set(size "0x0") 411 endif() 412 413 set(${STRING_STRING} 414 "${${STRING_STRING}}\n ${symbol} ${expr} ${subalign} ${size} { }\n" 415 PARENT_SCOPE 416 ) 417endfunction() 418 419include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake) 420 421if(DEFINED STEERING_C) 422 get_property(symbols_c GLOBAL PROPERTY SYMBOL_STEERING_C) 423 file(WRITE ${STEERING_C} "/* AUTO-GENERATED - Do not modify\n") 424 file(APPEND ${STEERING_C} " * AUTO-GENERATED - All changes will be lost\n") 425 file(APPEND ${STEERING_C} " */\n") 426 foreach(symbol ${symbols_c}) 427 file(APPEND ${STEERING_C} "extern char ${symbol}[];\n") 428 endforeach() 429 430 file(APPEND ${STEERING_C} "\nint __armlink_symbol_steering(void) {\n") 431 file(APPEND ${STEERING_C} "\treturn\n") 432 foreach(symbol ${symbols_c}) 433 file(APPEND ${STEERING_C} "\t\t${OPERAND} (int)${symbol}\n") 434 set(OPERAND "&") 435 endforeach() 436 file(APPEND ${STEERING_C} "\t;\n}\n") 437endif() 438 439if(DEFINED STEERING_FILE) 440 get_property(steering_content GLOBAL PROPERTY SYMBOL_STEERING_FILE) 441 file(WRITE ${STEERING_FILE} "; AUTO-GENERATED - Do not modify\n") 442 file(APPEND ${STEERING_FILE} "; AUTO-GENERATED - All changes will be lost\n") 443 file(APPEND ${STEERING_FILE} ${steering_content}) 444endif() 445