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
should end up in.
The output is a linker script fragment containing the definition of the
app shared memory section, which is further divided, for each partition
found, into data and BSS for each partition.
The output is either a linker script fragment or linker-script generator
fragments containing the definition of the app shared memory section, which
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 argparse
import json
@ -50,60 +187,133 @@ LIB = 'libraries'
# application shared memory partitions.
# these are later read by the macros defined in app_memdomain.h for
# initialization purpose when USERSPACE is enabled.
data_template = """
class LDScriptTemlate:
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*))
"""
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*))
"""
library_data_template = """
\"*{0}:*\"(.data .data.* .sdata .sdata.*)
"""
library_data_template = """
\"*{lib}:*\"(.data .data.* .sdata .sdata.*)
"""
bss_template = """
z_data_smem_{0}_bss_start = .;
KEEP(*(data_smem_{0}_bss*))
"""
bss_template = """
z_data_smem_{partition}_bss_start = .;
KEEP(*(data_smem_{partition}_bss*))
"""
library_bss_template = """
\"*{0}:*\"(.bss .bss.* .sbss .sbss.* COMMON COMMON.*)
"""
library_bss_template = """
\"*{lib}:*\"(.bss .bss.* .sbss .sbss.* COMMON COMMON.*)
"""
footer_template = """
z_data_smem_{0}_bss_end = .;
SMEM_PARTITION_ALIGN(z_data_smem_{0}_bss_end - z_data_smem_{0}_part_start);
z_data_smem_{0}_part_end = .;
"""
footer_template = """
z_data_smem_{partition}_bss_end = .;
SMEM_PARTITION_ALIGN(z_data_smem_{partition}_bss_end - z_data_smem_{partition}_part_start);
z_data_smem_{partition}_part_end = .;
"""
linker_start_seq = """
SECTION_PROLOGUE(_APP_SMEM{1}_SECTION_NAME,,)
linker_start_seq = """
SECTION_PROLOGUE(_APP_SMEM{SECTION}_SECTION_NAME,,)
{{
APP_SHARED_ALIGN;
_app_smem{0}_start = .;
"""
_app_smem{section}_start = .;
"""
linker_end_seq = """
linker_end_seq = """
APP_SHARED_ALIGN;
_app_smem{0}_end = .;
_app_smem{section}_end = .;
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
"""
"""
empty_app_smem = """
SECTION_PROLOGUE(_APP_SMEM{1}_SECTION_NAME,,)
empty_app_smem = """
SECTION_PROLOGUE(_APP_SMEM{SECTION}_SECTION_NAME,,)
{{
#ifdef EMPTY_APP_SHARED_ALIGN
#ifdef EMPTY_APP_SHARED_ALIGN
EMPTY_APP_SHARED_ALIGN;
#endif
_app_smem{0}_start = .;
_app_smem{0}_end = .;
#endif
_app_smem{section}_start = .;
_app_smem{section}_end = .;
}} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
"""
"""
size_cal_string = """
z_data_smem_{0}_part_size = z_data_smem_{0}_part_end - z_data_smem_{0}_part_start;
z_data_smem_{0}_bss_size = z_data_smem_{0}_bss_end - z_data_smem_{0}_bss_start;
"""
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)*')
@ -200,34 +410,45 @@ def parse_elf_file(partitions):
else:
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 = ""
props = { 'section' : lnkr_sect, 'SECTION' : lnkr_sect.upper() }
if len(partitions) > 0:
string = linker_start_seq.format(lnkr_sect, lnkr_sect.upper())
string = template.linker_start_seq.format(**props)
size_string = ''
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:
for lib in item[LIB]:
string += library_data_template.format(lib)
string += bss_template.format(partition, lnkr_sect)
lib_props = part_props
lib_props["lib"] = lib
string += template.library_data_template.format(**lib_props)
string += template.bss_template.format(**part_props)
if LIB in item:
for lib in item[LIB]:
string += library_bss_template.format(lib)
string += footer_template.format(partition)
size_string += size_cal_string.format(partition)
lib_props = part_props
lib_props["lib"] = lib
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
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:
fw.write(string)
def parse_args():
global args
parser = argparse.ArgumentParser(
@ -294,7 +515,8 @@ def main():
partsorted = OrderedDict(decreasing_tuples)
generate_final_linker(args.output, partsorted)
generate_final(args.output, partsorted)
if args.verbose:
print("Partitions retrieved:")
for key in partsorted:
@ -308,7 +530,7 @@ def main():
partsorted = OrderedDict(decreasing_tuples)
generate_final_linker(args.pinoutput, partsorted, lnkr_sect="_pinned")
generate_final(args.pinoutput, partsorted, lnkr_sect="_pinned")
if args.verbose:
print("Pinned partitions retrieved:")
for key in partsorted: