scatter_script.cmake 16 KB

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