scripts: Make gen_app_partitions.py cmake linker generator savvy

Tweak gen_app_partitions.py to be able to generate cmake linker
generator output as well as ld-script fragments.

Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
This commit is contained in:
Björn Bergman 2025-02-04 17:40:00 +01:00 committed by Benjamin Cabé
commit 6c197f8961

View file

@ -27,11 +27,148 @@ This script takes as inputs:
- key/value pairs mapping static library files to what partitions their globals - key/value pairs mapping static library files to what partitions their globals
should end up in. should end up in.
The output is a linker script fragment containing the definition of the The output is either a linker script fragment or linker-script generator
app shared memory section, which is further divided, for each partition fragments containing the definition of the app shared memory section, which
found, into data and BSS for each partition. is further divided, for each partition found, into data and BSS for each
partition.
""" """
#The linker script fragments looks something like this:
# SECTION_PROLOGUE(_APP_SMEM_SECTION_NAME,,)
# {
# APP_SHARED_ALIGN;
# _app_smem_start = .;
# /* Auto generated code do not modify */
# SMEM_PARTITION_ALIGN(z_data_smem_ztest_mem_partition_bss_end - z_data_smem_ztest_mem_partition_part_start);
# z_data_smem_ztest_mem_partition_part_start = .;
# KEEP(*(data_smem_ztest_mem_partition_data*))
# z_data_smem_ztest_mem_partition_bss_start = .;
# KEEP(*(data_smem_ztest_mem_partition_bss*))
# z_data_smem_ztest_mem_partition_bss_end = .;
# SMEM_PARTITION_ALIGN(z_data_smem_ztest_mem_partition_bss_end - z_data_smem_ztest_mem_partition_part_start);
# z_data_smem_ztest_mem_partition_part_end = .;
# /* Auto generated code do not modify */
# SMEM_PARTITION_ALIGN(z_data_smem_z_libc_partition_bss_end - z_data_smem_z_libc_partition_part_start);
# z_data_smem_z_libc_partition_part_start = .;
# KEEP(*(data_smem_z_libc_partition_data*))
# z_data_smem_z_libc_partition_bss_start = .;
# KEEP(*(data_smem_z_libc_partition_bss*))
# z_data_smem_z_libc_partition_bss_end = .;
# SMEM_PARTITION_ALIGN(z_data_smem_z_libc_partition_bss_end - z_data_smem_z_libc_partition_part_start);
# z_data_smem_z_libc_partition_part_end = .;
# APP_SHARED_ALIGN;
# _app_smem_end = .;
# } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
# z_data_smem_ztest_mem_partition_part_size = z_data_smem_ztest_mem_partition_part_end - z_data_smem_ztest_mem_partition_part_start;
# z_data_smem_ztest_mem_partition_bss_size = z_data_smem_ztest_mem_partition_bss_end - z_data_smem_ztest_mem_partition_bss_start;
# z_data_smem_z_libc_partition_part_size = z_data_smem_z_libc_partition_part_end - z_data_smem_z_libc_partition_part_start;
# z_data_smem_z_libc_partition_bss_size = z_data_smem_z_libc_partition_bss_end - z_data_smem_z_libc_partition_bss_start;
# the linker script generator fragments looks something like this:
# There is a zephyr_linker_group() called APP_SMEM_GROUP for these sections
# defined in linker.cmake
# _APP_SMEM_SECTION_NAME is #defined in sections.h to "app_smem". Ideally we should have that here too.
#
# zephyr_linker_section(NAME _APP_SMEM_SECTION_NAME GROUP APP_SMEM_GROUP NOINPUT ALIGN_WITH_INPUT)
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# SYMBOLS
# _app_smem_start
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# INPUT
# "data_smem_ztest_mem_partition_data*"
# KEEP
# SYMBOLS
# z_data_smem_ztest_mem_partition_part_start
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# INPUT
# "data_smem_ztest_mem_partition_bss*"
# KEEP
# SYMBOLS
# z_data_smem_ztest_mem_partition_bss_start
# z_data_smem_ztest_mem_partition_bss_end
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# SYMBOLS
# z_data_smem_ztest_mem_partition_part_end
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# INPUT
# "data_smem_z_libc_partition_data*"
# KEEP
# SYMBOLS
# z_data_smem_z_libc_partition_part_start
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# INPUT
# "data_smem_z_libc_partition_bss*"
# KEEP
# SYMBOLS
# z_data_smem_z_libc_partition_bss_start
# z_data_smem_z_libc_partition_bss_end
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# SYMBOLS
# z_data_smem_z_libc_partition_part_end
# )
# zephyr_linker_section_configure(
# SECTION
# _APP_SMEM_SECTION_NAME
# SYMBOLS
# _app_smem_end
# )
# zephyr_linker_symbol(
# SYMBOL
# z_data_smem_ztest_mem_partition_part_size
# EXPR
# "(@z_data_smem_ztest_mem_partition_part_end@ - @z_data_smem_ztest_mem_partition_part_start@)"
# )
# zephyr_linker_symbol(
# SYMBOL
# z_data_smem_ztest_mem_partition_bss_size
# EXPR
# "(@z_data_smem_ztest_mem_partition_bss_end@ - @z_data_smem_ztest_mem_partition_bss_start@)"
# )
# zephyr_linker_symbol(
# SYMBOL
# z_data_smem_z_libc_partition_part_size
# EXPR
# "(@z_data_smem_z_libc_partition_part_end@ - @z_data_smem_z_libc_partition_part_start@)"
# )
# zephyr_linker_symbol(
# SYMBOL
# z_data_smem_z_libc_partition_bss_size
# EXPR
# "(@z_data_smem_z_libc_partition_bss_end@ - @z_data_smem_z_libc_partition_bss_start@)"
# )
import sys import sys
import argparse import argparse
import json import json
@ -50,60 +187,133 @@ LIB = 'libraries'
# application shared memory partitions. # application shared memory partitions.
# these are later read by the macros defined in app_memdomain.h for # these are later read by the macros defined in app_memdomain.h for
# initialization purpose when USERSPACE is enabled. # initialization purpose when USERSPACE is enabled.
data_template = """
/* Auto generated code do not modify */
SMEM_PARTITION_ALIGN(z_data_smem_{0}_bss_end - z_data_smem_{0}_part_start);
z_data_smem_{0}_part_start = .;
KEEP(*(data_smem_{0}_data*))
"""
library_data_template = """ class LDScriptTemlate:
\"*{0}:*\"(.data .data.* .sdata .sdata.*) data_template = """
""" /* Auto generated code do not modify */
SMEM_PARTITION_ALIGN(z_data_smem_{partition}_bss_end - z_data_smem_{partition}_part_start);
z_data_smem_{partition}_part_start = .;
KEEP(*(data_smem_{partition}_data*))
"""
bss_template = """ library_data_template = """
z_data_smem_{0}_bss_start = .; \"*{lib}:*\"(.data .data.* .sdata .sdata.*)
KEEP(*(data_smem_{0}_bss*)) """
"""
library_bss_template = """ bss_template = """
\"*{0}:*\"(.bss .bss.* .sbss .sbss.* COMMON COMMON.*) z_data_smem_{partition}_bss_start = .;
""" KEEP(*(data_smem_{partition}_bss*))
"""
footer_template = """ library_bss_template = """
z_data_smem_{0}_bss_end = .; \"*{lib}:*\"(.bss .bss.* .sbss .sbss.* COMMON COMMON.*)
SMEM_PARTITION_ALIGN(z_data_smem_{0}_bss_end - z_data_smem_{0}_part_start); """
z_data_smem_{0}_part_end = .;
"""
linker_start_seq = """ footer_template = """
SECTION_PROLOGUE(_APP_SMEM{1}_SECTION_NAME,,) z_data_smem_{partition}_bss_end = .;
{{ SMEM_PARTITION_ALIGN(z_data_smem_{partition}_bss_end - z_data_smem_{partition}_part_start);
APP_SHARED_ALIGN; z_data_smem_{partition}_part_end = .;
_app_smem{0}_start = .; """
"""
linker_end_seq = """ linker_start_seq = """
APP_SHARED_ALIGN; SECTION_PROLOGUE(_APP_SMEM{SECTION}_SECTION_NAME,,)
_app_smem{0}_end = .; {{
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) APP_SHARED_ALIGN;
""" _app_smem{section}_start = .;
"""
empty_app_smem = """ linker_end_seq = """
SECTION_PROLOGUE(_APP_SMEM{1}_SECTION_NAME,,) APP_SHARED_ALIGN;
{{ _app_smem{section}_end = .;
#ifdef EMPTY_APP_SHARED_ALIGN }} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
EMPTY_APP_SHARED_ALIGN; """
#endif
_app_smem{0}_start = .;
_app_smem{0}_end = .;
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
"""
size_cal_string = """ empty_app_smem = """
z_data_smem_{0}_part_size = z_data_smem_{0}_part_end - z_data_smem_{0}_part_start; SECTION_PROLOGUE(_APP_SMEM{SECTION}_SECTION_NAME,,)
z_data_smem_{0}_bss_size = z_data_smem_{0}_bss_end - z_data_smem_{0}_bss_start; {{
""" #ifdef EMPTY_APP_SHARED_ALIGN
EMPTY_APP_SHARED_ALIGN;
#endif
_app_smem{section}_start = .;
_app_smem{section}_end = .;
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
"""
size_cal_string = """
z_data_smem_{partition}_part_size = z_data_smem_{partition}_part_end - z_data_smem_{partition}_part_start;
z_data_smem_{partition}_bss_size = z_data_smem_{partition}_bss_end - z_data_smem_{partition}_bss_start;
"""
def cmake_list_append(list, props):
tokens = [fr"{key}\;{value}" for key, value in props.items()]
stuff = r"\;".join(tokens)
return """list(APPEND """+ list + """ \"{{""" + stuff + """}}\")\n"""
def zephyr_linker_section(name, group, align = None, noinput = True, align_with_input = True, hidden = False, noinit = False):
props = {"""NAME""": name, """GROUP""": group}
if align :
props['ALIGN'] = align
#The bool flags are always there:
props['NOIPUT'] = noinput
props['ALIGN_WITH_INPUT'] = align_with_input
props['HIDDEN'] = hidden
props['NOINIT'] = noinit
return cmake_list_append("SECTIONS", props)
def zephyr_linker_section_configure(section, input = None, symbols = None, align = None, any = False, first = False, keep = False):
props = {"SECTION": section}
if input:
props["INPUT"] = input
#ANY\;FALSE\;FIRST\;FALSE\;KEEP\;FALSE\
props['ANY'] = any
props['FIRST'] = first
props['KEEP'] = keep
if symbols:
props["SYMBOLS"] = symbols
if align:
props["ALIGN"] = align
return cmake_list_append("SECTION_SETTINGS", props)
def zephyr_linker_symbol(symbol, expr) :
return cmake_list_append("SYMBOLS", {'SYMBOL': symbol, 'EXPR':expr})
class CmakeTemplate:
section_name = "@_APP_SMEM{SECTION}_SECTION_NAME@"
data_template = (
zephyr_linker_section_configure(section=section_name, align="@SMEM_PARTITION_ALIGN_BYTES@")+
zephyr_linker_section_configure(section=section_name, input="data_smem_{partition}_data*", symbols="z_data_smem_{partition}_part_start", keep=True)
)
library_data_template = zephyr_linker_section_configure(section=section_name, input="*{lib}:*(.data .data.* .sdata .sdata.*)")
bss_template = (
zephyr_linker_section_configure(section=section_name, input="data_smem_{partition}_bss*", symbols="z_data_smem_{partition}_bss_start", keep=True)
)
library_bss_template = zephyr_linker_section_configure(section=section_name, input="*{lib}:*(.bss .bss.* .sbss .sbss.* COMMON COMMON.*)")
footer_template = (
zephyr_linker_section_configure(section=section_name, symbols="z_data_smem_{partition}_bss_end", keep=True) +
zephyr_linker_section_configure(section=section_name, align="@SMEM_PARTITION_ALIGN_BYTES@") +
zephyr_linker_section_configure(section=section_name, symbols="z_data_smem_{partition}_part_end", keep=True)
)
linker_start_seq = (
zephyr_linker_section(name=section_name, group="APP_SMEM_GROUP", noinput=True, align_with_input=True) +
zephyr_linker_section_configure(section=section_name, align="@APP_SHARED_ALIGN_BYTES@", symbols="_app_smem{section}_start"))
linker_end_seq = (
zephyr_linker_section_configure(section=section_name, align="@APP_SHARED_ALIGN_BYTES@") +
zephyr_linker_section_configure(section=section_name, symbols="_app_smem{section}_end") )
empty_app_smem = (
zephyr_linker_section(name=section_name, group="APP_SMEM_GROUP", align="@APP_SHARED_ALIGN_BYTES@", noinput=True, align_with_input=True) +
zephyr_linker_section_configure(section = section_name, symbols="_app_smem{section}_start") +
zephyr_linker_section_configure(section = section_name, symbols="_app_smem{section}_end") )
size_cal_string = (
zephyr_linker_symbol(symbol='z_data_smem_{partition}_part_size', expr='@z_data_smem_{partition}_part_end@ - @z_data_smem_{partition}_part_start@') +
zephyr_linker_symbol(symbol='z_data_smem_{partition}_bss_size', expr='@z_data_smem_{partition}_bss_end@ - @z_data_smem_{partition}_bss_start@'))
section_regex = re.compile(r'data_smem_([A-Za-z0-9_]*)_(data|bss)*') section_regex = re.compile(r'data_smem_([A-Za-z0-9_]*)_(data|bss)*')
@ -200,34 +410,45 @@ def parse_elf_file(partitions):
else: else:
partitions[partition_name][SZ] += size partitions[partition_name][SZ] += size
def generate_final(linker_file, partitions, lnkr_sect=""):
if linker_file.endswith(".ld"):
template = LDScriptTemlate
else:
template = CmakeTemplate
generate_final_linker(template, linker_file, partitions, lnkr_sect)
def generate_final_linker(linker_file, partitions, lnkr_sect=""): def generate_final_linker(template, linker_file, partitions, lnkr_sect):
string = "" string = ""
props = { 'section' : lnkr_sect, 'SECTION' : lnkr_sect.upper() }
if len(partitions) > 0: if len(partitions) > 0:
string = linker_start_seq.format(lnkr_sect, lnkr_sect.upper()) string = template.linker_start_seq.format(**props)
size_string = '' size_string = ''
for partition, item in partitions.items(): for partition, item in partitions.items():
string += data_template.format(partition) part_props = props
part_props["partition"] = partition
string += template.data_template.format(**part_props)
if LIB in item: if LIB in item:
for lib in item[LIB]: for lib in item[LIB]:
string += library_data_template.format(lib) lib_props = part_props
string += bss_template.format(partition, lnkr_sect) lib_props["lib"] = lib
string += template.library_data_template.format(**lib_props)
string += template.bss_template.format(**part_props)
if LIB in item: if LIB in item:
for lib in item[LIB]: for lib in item[LIB]:
string += library_bss_template.format(lib) lib_props = part_props
string += footer_template.format(partition) lib_props["lib"] = lib
size_string += size_cal_string.format(partition) string += template.library_bss_template.format(**lib_props)
string += template.footer_template.format(**part_props)
size_string += template.size_cal_string.format(**part_props)
string += linker_end_seq.format(lnkr_sect) string += template.linker_end_seq.format(**props)
string += size_string string += size_string
else: else:
string = empty_app_smem.format(lnkr_sect, lnkr_sect.upper()) string = template.empty_app_smem.format(**props) #lnkr_sect, lnkr_sect.upper())
with open(linker_file, "w") as fw: with open(linker_file, "w") as fw:
fw.write(string) fw.write(string)
def parse_args(): def parse_args():
global args global args
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
@ -294,7 +515,8 @@ def main():
partsorted = OrderedDict(decreasing_tuples) partsorted = OrderedDict(decreasing_tuples)
generate_final_linker(args.output, partsorted) generate_final(args.output, partsorted)
if args.verbose: if args.verbose:
print("Partitions retrieved:") print("Partitions retrieved:")
for key in partsorted: for key in partsorted:
@ -308,7 +530,7 @@ def main():
partsorted = OrderedDict(decreasing_tuples) partsorted = OrderedDict(decreasing_tuples)
generate_final_linker(args.pinoutput, partsorted, lnkr_sect="_pinned") generate_final(args.pinoutput, partsorted, lnkr_sect="_pinned")
if args.verbose: if args.verbose:
print("Pinned partitions retrieved:") print("Pinned partitions retrieved:")
for key in partsorted: for key in partsorted: