Skip to content

Commit e9e47a4

Browse files
tejlmandnashif
authored andcommitted
cmake: ld: adding ld linker script generator
Adding intial version of ld_script.cmake. This script can generate ld linker script from the Zephyr CMake linker functions. This script is called by the build system and all linker settings, such as memory regions, groups, output sections, linker symbols defined with Zephyr CMake linker functions are passed to this script in order to generate an ld linker script. Signed-off-by: Torsten Rasmussen <[email protected]>
1 parent 02fb26d commit e9e47a4

File tree

1 file changed

+328
-0
lines changed

1 file changed

+328
-0
lines changed

cmake/linker/ld/ld_script.cmake

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
# ToDo:
2+
# - Ensure LMA / VMA sections are correctly grouped similar to scatter file creation.
3+
cmake_minimum_required(VERSION 3.18)
4+
5+
set(SORT_TYPE_NAME SORT_BY_NAME)
6+
7+
function(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)
65+
endfunction()
66+
67+
function(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)
85+
endfunction()
86+
87+
function(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+
string(TOLOWER ${name} name)
102+
set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_start = .;\n")
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+
set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_size = __${name}_end - __${name}_start;\n")
109+
set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_load_start = LOADADDR(${first_section_name});\n")
110+
endif()
111+
112+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED)
113+
foreach(section ${sections})
114+
to_string(OBJECT ${section} STRING ${STRING_STRING})
115+
endforeach()
116+
117+
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS)
118+
foreach(group ${groups})
119+
to_string(OBJECT ${group} STRING ${STRING_STRING})
120+
endforeach()
121+
122+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS)
123+
foreach(section ${sections})
124+
to_string(OBJECT ${section} STRING ${STRING_STRING})
125+
endforeach()
126+
127+
get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM)
128+
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
129+
list(REMOVE_ITEM regions ${STRING_OBJECT})
130+
foreach(region ${regions})
131+
if(${type} STREQUAL REGION)
132+
get_property(address GLOBAL PROPERTY ${region}_ADDRESS)
133+
set(${STRING_STRING} "${${STRING_STRING}}\n . = ${address};\n\n")
134+
endif()
135+
136+
get_property(vma GLOBAL PROPERTY ${region}_NAME)
137+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED)
138+
foreach(section ${sections})
139+
to_string(OBJECT ${section} STRING ${STRING_STRING})
140+
endforeach()
141+
142+
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS)
143+
foreach(group ${groups})
144+
to_string(OBJECT ${group} STRING ${STRING_STRING})
145+
endforeach()
146+
147+
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS)
148+
foreach(section ${sections})
149+
to_string(OBJECT ${section} STRING ${STRING_STRING})
150+
endforeach()
151+
endforeach()
152+
153+
if(NOT ${type} STREQUAL REGION)
154+
set(${STRING_STRING} "${${STRING_STRING}}\n __${name}_end = .;\n")
155+
endif()
156+
157+
get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS)
158+
foreach(symbol ${symbols})
159+
to_string(OBJECT ${symbol} STRING ${STRING_STRING})
160+
endforeach()
161+
162+
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
163+
endfunction()
164+
165+
function(section_to_string)
166+
cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN})
167+
168+
get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME)
169+
get_property(name_clean GLOBAL PROPERTY ${STRING_SECTION}_NAME_CLEAN)
170+
get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS)
171+
get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE)
172+
get_property(align_in GLOBAL PROPERTY ${STRING_SECTION}_ALIGN_WITH_INPUT)
173+
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN)
174+
get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN)
175+
get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA)
176+
get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA)
177+
get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT)
178+
get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT)
179+
get_property(nosymbols GLOBAL PROPERTY ${STRING_SECTION}_NOSYMBOLS)
180+
get_property(parent GLOBAL PROPERTY ${STRING_SECTION}_PARENT)
181+
182+
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
183+
string(REPLACE "." "_" name_clean "${name_clean}")
184+
185+
set(SECTION_TYPE_NOLOAD NOLOAD)
186+
set(SECTION_TYPE_BSS NOLOAD)
187+
if(DEFINED type)
188+
set(type " (${SECTION_TYPE_${type}})")
189+
endif()
190+
191+
set(TEMP "${TEMP} :")
192+
set(secalign "")
193+
194+
if(align_in)
195+
set(secalign " ALIGN_WITH_INPUT")
196+
endif()
197+
198+
if(DEFINED align)
199+
set(secalign "${secalign} ALIGN(${align})")
200+
endif()
201+
202+
if(DEFINED subalign)
203+
set(secalign "${secalign} SUBALIGN(${subalign})")
204+
endif()
205+
206+
set(TEMP "${name} ${address}${type} :${secalign}\n{")
207+
if(NOT nosymbols)
208+
set(TEMP "${TEMP}\n __${name_clean}_start = .;")
209+
endif()
210+
211+
if(NOT noinput)
212+
set(TEMP "${TEMP}\n *(${name})")
213+
set(TEMP "${TEMP}\n *(\"${name}.*\")")
214+
endif()
215+
216+
get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
217+
foreach(idx ${indicies})
218+
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN)
219+
get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY)
220+
get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST)
221+
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP)
222+
get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT)
223+
get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS)
224+
get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT)
225+
get_property(symbols GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SYMBOLS)
226+
get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_OFFSET)
227+
228+
if(DEFINED SETTINGS_ALIGN)
229+
set(TEMP "${TEMP}\n . = ALIGN(${align});")
230+
endif()
231+
232+
if(DEFINED symbols)
233+
list(LENGTH symbols symbols_count)
234+
if(${symbols_count} GREATER 0)
235+
list(GET symbols 0 symbol_start)
236+
endif()
237+
if(${symbols_count} GREATER 1)
238+
list(GET symbols 1 symbol_end)
239+
endif()
240+
endif()
241+
242+
if(DEFINED symbol_start)
243+
set(TEMP "${TEMP}\n ${symbol_start} = .;")
244+
endif()
245+
246+
foreach(setting ${input})
247+
if(DEFINED offset AND NOT ("${offset}" STREQUAL "${current_offset}"))
248+
set(TEMP "${TEMP}\n . = ${offset};")
249+
set(current_offset ${offset})
250+
endif()
251+
252+
if(keep AND sort)
253+
set(TEMP "${TEMP}\n KEEP(*(${SORT_TYPE_${sort}}(${setting})));")
254+
elseif(SETTINGS_SORT)
255+
message(WARNING "Not tested")
256+
set(TEMP "${TEMP}\n *(${SORT_TYPE_${sort}}(${setting}));")
257+
elseif(keep)
258+
set(TEMP "${TEMP}\n KEEP(*(${setting}));")
259+
else()
260+
set(TEMP "${TEMP}\n *(${setting})")
261+
endif()
262+
endforeach()
263+
264+
if(DEFINED symbol_end)
265+
set(TEMP "${TEMP}\n ${symbol_end} = .;")
266+
endif()
267+
268+
set(symbol_start)
269+
set(symbol_end)
270+
endforeach()
271+
272+
if(NOT nosymbols)
273+
set(TEMP "${TEMP}\n __${name_clean}_end = .;")
274+
endif()
275+
276+
set(TEMP "${TEMP}\n}")
277+
278+
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
279+
if(${parent_type} STREQUAL GROUP)
280+
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
281+
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
282+
endif()
283+
284+
if(DEFINED vma)
285+
set(TEMP "${TEMP} > ${vma}")
286+
endif()
287+
288+
if(DEFINED vma AND DEFINED lma)
289+
set(TEMP "${TEMP} AT")
290+
endif()
291+
292+
if(DEFINED lma)
293+
set(TEMP "${TEMP} > ${lma}")
294+
endif()
295+
296+
if(NOT nosymbols)
297+
set(TEMP "${TEMP}\n__${name_clean}_size = __${name_clean}_end - __${name_clean}_start;")
298+
set(TEMP "${TEMP}\n__${name_clean}_load_start = LOADADDR(${name});")
299+
endif()
300+
301+
set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE)
302+
endfunction()
303+
304+
# /DISCARD/ is an ld specific section, so let's append it here before processing.
305+
list(APPEND SECTIONS "{NAME\;/DISCARD/\;NOINPUT\;TRUE\;NOSYMBOLS\;TRUE}")
306+
307+
function(process_region)
308+
cmake_parse_arguments(REGION "" "OBJECT" "" ${ARGN})
309+
310+
process_region_common(${ARGN})
311+
312+
set(groups)
313+
get_objects(LIST groups OBJECT ${REGION_OBJECT} TYPE GROUP)
314+
foreach(group ${groups})
315+
get_property(parent GLOBAL PROPERTY ${group}_PARENT)
316+
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
317+
318+
if(${parent_type} STREQUAL GROUP)
319+
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
320+
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
321+
322+
set_property(GLOBAL PROPERTY ${group}_VMA ${vma})
323+
set_property(GLOBAL PROPERTY ${group}_LMA ${lma})
324+
endif()
325+
endforeach()
326+
endfunction()
327+
328+
include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake)

0 commit comments

Comments
 (0)