1# ToDo: 2# - Ensure LMA / VMA sections are correctly grouped similar to scatter file creation. 3cmake_minimum_required(VERSION 3.20.0) 4 5set(SORT_TYPE_NAME SORT_BY_NAME) 6 7function(system_to_string) 8 cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN}) 9 10 get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME) 11 get_property(regions GLOBAL PROPERTY ${STRING_OBJECT}_REGIONS) 12 get_property(format GLOBAL PROPERTY ${STRING_OBJECT}_FORMAT) 13 get_property(entry GLOBAL PROPERTY ${STRING_OBJECT}_ENTRY) 14 get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS) 15 16 set(${STRING_STRING} "OUTPUT_FORMAT(\"${format}\")\n\n") 17 18 set(${STRING_STRING} "${${STRING_STRING}}MEMORY\n{\n") 19 foreach(region ${regions}) 20 get_property(name GLOBAL PROPERTY ${region}_NAME) 21 get_property(address GLOBAL PROPERTY ${region}_ADDRESS) 22 get_property(flags GLOBAL PROPERTY ${region}_FLAGS) 23 get_property(size GLOBAL PROPERTY ${region}_SIZE) 24 25 if(DEFINED flags) 26 set(flags "(${flags})") 27 endif() 28 29 if(DEFINED address) 30 set(start ": ORIGIN = (${address})") 31 endif() 32 33 if(DEFINED size) 34 set(size ", LENGTH = (${size})") 35 endif() 36 set(memory_region " ${name} ${flags} ${start}${size}") 37 38 set(${STRING_STRING} "${${STRING_STRING}}${memory_region}\n") 39 endforeach() 40 41 set(${STRING_STRING} "${${STRING_STRING}}}\n\n") 42 43 set(${STRING_STRING} "${${STRING_STRING}}ENTRY(\"${entry}\")\n\n") 44 45 set(${STRING_STRING} "${${STRING_STRING}}SECTIONS\n{") 46 foreach(region ${regions}) 47 to_string(OBJECT ${region} STRING ${STRING_STRING}) 48 endforeach() 49 50 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED) 51 foreach(section ${sections}) 52 to_string(OBJECT ${section} STRING ${STRING_STRING}) 53 endforeach() 54 55 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS) 56 foreach(section ${sections}) 57 to_string(OBJECT ${section} STRING ${STRING_STRING}) 58 endforeach() 59 60 foreach(symbol ${symbols}) 61 to_string(OBJECT ${symbol} STRING ${STRING_STRING}) 62 endforeach() 63 64 set(${STRING_STRING} "${${STRING_STRING}}\n}\n" PARENT_SCOPE) 65endfunction() 66 67function(symbol_to_string) 68 cmake_parse_arguments(STRING "" "SYMBOL;STRING" "" ${ARGN}) 69 70 get_property(name GLOBAL PROPERTY ${STRING_SYMBOL}_NAME) 71 get_property(expr GLOBAL PROPERTY ${STRING_SYMBOL}_EXPR) 72 get_property(size GLOBAL PROPERTY ${STRING_SYMBOL}_SIZE) 73 get_property(symbol GLOBAL PROPERTY ${STRING_SYMBOL}_SYMBOL) 74 get_property(subalign GLOBAL PROPERTY ${STRING_SYMBOL}_SUBALIGN) 75 76 string(REPLACE "\\" "" expr "${expr}") 77 string(REGEX MATCHALL "@([^@]*)@" match_res ${expr}) 78 79 foreach(match ${match_res}) 80 string(REPLACE "@" "" match ${match}) 81 string(REPLACE "@${match}@" "${match}" expr ${expr}) 82 endforeach() 83 84 set(${STRING_STRING} "${${STRING_STRING}}\n${symbol} = ${expr};\n" PARENT_SCOPE) 85endfunction() 86 87function(group_to_string) 88 cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN}) 89 90 get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE) 91 if(${type} STREQUAL REGION) 92 get_property(empty GLOBAL PROPERTY ${STRING_OBJECT}_EMPTY) 93 if(empty) 94 return() 95 endif() 96 97 get_property(address GLOBAL PROPERTY ${STRING_OBJECT}_ADDRESS) 98 set(${STRING_STRING} "${${STRING_STRING}}\n . = ${address};\n\n") 99 else() 100 get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME) 101 get_property(symbol GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOL) 102 string(TOLOWER ${name} name) 103 104 get_objects(LIST sections OBJECT ${STRING_OBJECT} TYPE SECTION) 105 list(GET sections 0 section) 106 get_property(first_section_name GLOBAL PROPERTY ${section}_NAME) 107 108 if(DEFINED first_section_name AND "${symbol}" STREQUAL "SECTION") 109 set_property(GLOBAL APPEND PROPERTY ${section}_START_SYMBOLS __${name}_start) 110 else() 111 set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_start = .;\n") 112 endif() 113 114 set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_size = __${name}_end - __${name}_start;\n") 115 set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_load_start = LOADADDR(${first_section_name});\n") 116 endif() 117 118 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED) 119 foreach(section ${sections}) 120 to_string(OBJECT ${section} STRING ${STRING_STRING}) 121 endforeach() 122 123 get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS) 124 foreach(group ${groups}) 125 to_string(OBJECT ${group} STRING ${STRING_STRING}) 126 endforeach() 127 128 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS) 129 foreach(section ${sections}) 130 to_string(OBJECT ${section} STRING ${STRING_STRING}) 131 endforeach() 132 133 get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM) 134 get_property(regions GLOBAL PROPERTY ${parent}_REGIONS) 135 list(REMOVE_ITEM regions ${STRING_OBJECT}) 136 foreach(region ${regions}) 137 if(${type} STREQUAL REGION) 138 get_property(address GLOBAL PROPERTY ${region}_ADDRESS) 139 set(${STRING_STRING} "${${STRING_STRING}}\n . = ${address};\n\n") 140 endif() 141 142 get_property(vma GLOBAL PROPERTY ${region}_NAME) 143 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED) 144 foreach(section ${sections}) 145 to_string(OBJECT ${section} STRING ${STRING_STRING}) 146 endforeach() 147 148 get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS) 149 foreach(group ${groups}) 150 to_string(OBJECT ${group} STRING ${STRING_STRING}) 151 endforeach() 152 153 get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS) 154 foreach(section ${sections}) 155 to_string(OBJECT ${section} STRING ${STRING_STRING}) 156 endforeach() 157 endforeach() 158 159 if(NOT ${type} STREQUAL REGION) 160 set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_end = .;\n") 161 endif() 162 163 get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS) 164 foreach(symbol ${symbols}) 165 to_string(OBJECT ${symbol} STRING ${STRING_STRING}) 166 endforeach() 167 168 set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE) 169endfunction() 170 171function(section_to_string) 172 cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN}) 173 174 get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME) 175 get_property(name_clean GLOBAL PROPERTY ${STRING_SECTION}_NAME_CLEAN) 176 get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS) 177 get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE) 178 get_property(align_in GLOBAL PROPERTY ${STRING_SECTION}_ALIGN_WITH_INPUT) 179 get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN) 180 get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN) 181 get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA) 182 get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA) 183 get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT) 184 get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT) 185 get_property(nosymbols GLOBAL PROPERTY ${STRING_SECTION}_NOSYMBOLS) 186 get_property(parent GLOBAL PROPERTY ${STRING_SECTION}_PARENT) 187 get_property(start_syms GLOBAL PROPERTY ${STRING_SECTION}_START_SYMBOLS) 188 189 string(REGEX REPLACE "^[\.]" "" name_clean "${name}") 190 string(REPLACE "." "_" name_clean "${name_clean}") 191 192 set(SECTION_TYPE_NOLOAD NOLOAD) 193 set(SECTION_TYPE_BSS NOLOAD) 194 if(DEFINED type) 195 set(type " (${SECTION_TYPE_${type}})") 196 endif() 197 198 set(TEMP "${TEMP} :") 199 set(secalign "") 200 201 if(align_in) 202 set(secalign " ALIGN_WITH_INPUT") 203 endif() 204 205 if(DEFINED align) 206 set(secalign "${secalign} ALIGN(${align})") 207 endif() 208 209 if(DEFINED subalign) 210 set(secalign "${secalign} SUBALIGN(${subalign})") 211 endif() 212 213 set(TEMP "${name} ${address}${type} :${secalign}\n{") 214 215 foreach(start_symbol ${start_syms}) 216 set(TEMP "${TEMP}\n ${start_symbol} = .;") 217 endforeach() 218 219 if(NOT nosymbols) 220 set(TEMP "${TEMP}\n __${name_clean}_start = .;") 221 endif() 222 223 if(NOT noinput) 224 set(TEMP "${TEMP}\n *(${name})") 225 set(TEMP "${TEMP}\n *(\"${name}.*\")") 226 endif() 227 228 get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES) 229 foreach(idx ${indicies}) 230 get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN) 231 get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY) 232 get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST) 233 get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP) 234 get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT) 235 get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS) 236 get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT) 237 get_property(symbols GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SYMBOLS) 238 get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_OFFSET) 239 240 if(DEFINED SETTINGS_ALIGN) 241 set(TEMP "${TEMP}\n . = ALIGN(${align});") 242 endif() 243 244 if(DEFINED symbols) 245 list(LENGTH symbols symbols_count) 246 if(${symbols_count} GREATER 0) 247 list(GET symbols 0 symbol_start) 248 endif() 249 if(${symbols_count} GREATER 1) 250 list(GET symbols 1 symbol_end) 251 endif() 252 endif() 253 254 if(DEFINED symbol_start) 255 set(TEMP "${TEMP}\n ${symbol_start} = .;") 256 endif() 257 258 foreach(setting ${input}) 259 if(DEFINED offset AND NOT ("${offset}" STREQUAL "${current_offset}")) 260 set(TEMP "${TEMP}\n . = ${offset};") 261 set(current_offset ${offset}) 262 endif() 263 264 if(keep AND sort) 265 set(TEMP "${TEMP}\n KEEP(*(${SORT_TYPE_${sort}}(${setting})));") 266 elseif(SETTINGS_SORT) 267 message(WARNING "Not tested") 268 set(TEMP "${TEMP}\n *(${SORT_TYPE_${sort}}(${setting}));") 269 elseif(keep) 270 set(TEMP "${TEMP}\n KEEP(*(${setting}));") 271 else() 272 set(TEMP "${TEMP}\n *(${setting})") 273 endif() 274 endforeach() 275 276 if(DEFINED symbol_end) 277 set(TEMP "${TEMP}\n ${symbol_end} = .;") 278 endif() 279 280 set(symbol_start) 281 set(symbol_end) 282 endforeach() 283 284 if(NOT nosymbols) 285 set(TEMP "${TEMP}\n __${name_clean}_end = .;") 286 endif() 287 288 if(DEFINED extra_symbol_end) 289 set(TEMP "${TEMP}\n ${extra_symbol_end} = .;") 290 endif() 291 292 set(TEMP "${TEMP}\n}") 293 294 get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE) 295 if(${parent_type} STREQUAL GROUP) 296 get_property(vma GLOBAL PROPERTY ${parent}_VMA) 297 get_property(lma GLOBAL PROPERTY ${parent}_LMA) 298 endif() 299 300 if(DEFINED vma) 301 set(TEMP "${TEMP} > ${vma}") 302 endif() 303 304 if(DEFINED vma AND DEFINED lma) 305 set(TEMP "${TEMP} AT") 306 endif() 307 308 if(DEFINED lma) 309 set(TEMP "${TEMP} > ${lma}") 310 endif() 311 312 if(NOT nosymbols) 313 set(TEMP "${TEMP}\n__${name_clean}_size = __${name_clean}_end - __${name_clean}_start;") 314 set(TEMP "${TEMP}\nPROVIDE(__${name_clean}_align = ALIGNOF(${name}));") 315 set(TEMP "${TEMP}\n__${name_clean}_load_start = LOADADDR(${name});") 316 endif() 317 318 set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE) 319endfunction() 320 321# /DISCARD/ is an ld specific section, so let's append it here before processing. 322list(APPEND SECTIONS "{NAME\;/DISCARD/\;NOINPUT\;TRUE\;NOSYMBOLS\;TRUE}") 323 324function(process_region) 325 cmake_parse_arguments(REGION "" "OBJECT" "" ${ARGN}) 326 327 process_region_common(${ARGN}) 328 329 set(groups) 330 get_objects(LIST groups OBJECT ${REGION_OBJECT} TYPE GROUP) 331 foreach(group ${groups}) 332 get_property(parent GLOBAL PROPERTY ${group}_PARENT) 333 get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE) 334 335 if(${parent_type} STREQUAL GROUP) 336 get_property(vma GLOBAL PROPERTY ${parent}_VMA) 337 get_property(lma GLOBAL PROPERTY ${parent}_LMA) 338 339 set_property(GLOBAL PROPERTY ${group}_VMA ${vma}) 340 set_property(GLOBAL PROPERTY ${group}_LMA ${lma}) 341 endif() 342 endforeach() 343endfunction() 344 345include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake) 346