Skip to content

Commit d5aefbe

Browse files
schouleucarlescufi
authored andcommitted
[nrf fromtree] scripts: code_relocate: support section filter
One might want to select the symbols to be relocated inside a file or a library. To do this, one can use the FILTER argument of zephyr_code_relocate which must contain a regular expression of the section names to be selected for relocation. The test_function_in_sram2 test case in `tests/application_development/code_relocation` has been updated to verify that only one function `function_in_sram()` is relocated to ram and that the function `function_not_relocated()` is not being relocated when using relocation filter. Signed-off-by: Sylvain Chouleur <[email protected]> Signed-off-by: Torsten Rasmussen <[email protected]> (cherry picked from commit 4454734)
1 parent 1e22329 commit d5aefbe

File tree

6 files changed

+95
-26
lines changed

6 files changed

+95
-26
lines changed

cmake/modules/extensions.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,7 +1452,7 @@ endmacro()
14521452
# - PHDR [program_header]: add program header. Used on Xtensa platforms.
14531453
function(zephyr_code_relocate)
14541454
set(options NOCOPY NOKEEP)
1455-
set(single_args LIBRARY LOCATION PHDR)
1455+
set(single_args LIBRARY LOCATION PHDR FILTER)
14561456
set(multi_args FILES)
14571457
cmake_parse_arguments(CODE_REL "${options}" "${single_args}"
14581458
"${multi_args}" ${ARGN})
@@ -1529,7 +1529,7 @@ function(zephyr_code_relocate)
15291529
PROPERTY INTERFACE_SOURCES)
15301530
set_property(TARGET code_data_relocation_target
15311531
PROPERTY INTERFACE_SOURCES
1532-
"${code_rel_str}\n${CODE_REL_LOCATION}:${flag_list}:${file_list}")
1532+
"${code_rel_str}\n${CODE_REL_LOCATION}:${flag_list}:${file_list},${CODE_REL_FILTER}")
15331533
endfunction()
15341534

15351535
# Usage:

doc/kernel/code-relocation.rst

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,23 @@ This script provides a robust way to re-order the memory contents without
1414
actually having to modify the code. In simple terms this script will do the job
1515
of ``__attribute__((section("name")))`` for a bunch of files together.
1616

17+
A regular expression filter can be used to select only the required sections to be relocated.
18+
1719
Details
1820
*******
19-
The memory region and file are given to the :ref:`gen_relocate_app.py` script in the form of a string.
21+
The memory region and file are given to the :ref:`gen_relocate_app.py` script
22+
through a file where each line specifies a list of files to be placed in the
23+
given region.
24+
25+
An example of such a file is:
26+
27+
.. code-block:: none
2028
21-
An example of such a string is:
22-
``SRAM2:/home/xyz/zephyr/samples/hello_world/src/main.c,SRAM1:/home/xyz/zephyr/samples/hello_world/src/main2.c``
29+
SRAM2:/home/xyz/zephyr/samples/hello_world/src/main.c,
30+
SRAM1:/home/xyz/zephyr/samples/hello_world/src/main2.c,
2331
2432
This script is invoked with the following parameters:
25-
``python3 gen_relocate_app.py -i input_string -o generated_linker -c generated_code``
33+
``python3 gen_relocate_app.py -i input_file -o generated_linker -c generated_code``
2634

2735
Kconfig :kconfig:option:`CONFIG_CODE_DATA_RELOCATION` option, when enabled in
2836
``prj.conf``, will invoke the script and do the required relocation.
@@ -97,6 +105,24 @@ This section shows additional configuration options that can be set in
97105
zephyr_code_relocate(FILES ${sources} LOCATION SRAM)
98106
zephyr_code_relocate(FILES $<TARGET_PROPERTY:my_tgt,SOURCES> LOCATION SRAM)
99107
108+
Section Filtering
109+
=================
110+
111+
By default, all sections of the specified files will be relocated. If
112+
``FILTER`` is used, a regular expression is provided to select only
113+
the sections to be relocated.
114+
115+
The regular expression applies to sections names which can be used to
116+
select the file's symbols when this one has been built with
117+
``-ffunction-sections`` and ``-fdata-sections`` which is the case by
118+
default.
119+
120+
.. code-block:: none
121+
122+
zephyr_code_relocate(FILES src/file1.c FILTER ".*\\.func1|.*\\.func2" LOCATION SRAM2_TEXT)
123+
124+
The example above will only relocate ``func1()`` and ``func2()`` of file ``src/file1.c``
125+
100126
NOKEEP flag
101127
===========
102128

scripts/build/gen_relocate_app.py

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,22 @@
88
"""
99
This script will relocate .text, .rodata, .data and .bss sections from required files
1010
and places it in the required memory region. This memory region and file
11-
are given to this python script in the form of a string.
11+
are given to this python script in the form of a file.
12+
A regular expression filter can be applied to select only the required sections from the file.
1213
13-
Example of such a string would be::
14+
Example of content in such an input file would be::
1415
15-
SRAM2:COPY:/home/xyz/zephyr/samples/hello_world/src/main.c,\
16-
SRAM1:COPY:/home/xyz/zephyr/samples/hello_world/src/main2.c, \
17-
FLASH2:NOCOPY:/home/xyz/zephyr/samples/hello_world/src/main3.c
16+
SRAM2:COPY:/home/xyz/zephyr/samples/hello_world/src/main.c,.*foo|.*bar
17+
SRAM1:COPY:/home/xyz/zephyr/samples/hello_world/src/main2.c,.*bar
18+
FLASH2:NOCOPY:/home/xyz/zephyr/samples/hello_world/src/main3.c,
1819
1920
One can also specify the program header for a given memory region:
2021
21-
SRAM2\\ :phdr0:COPY:/home/xyz/zephyr/samples/hello_world/src/main.c
22+
SRAM2\\ :phdr0:COPY:/home/xyz/zephyr/samples/hello_world/src/main.c,
2223
2324
To invoke this script::
2425
25-
python3 gen_relocate_app.py -i input_string -o generated_linker -c generated_code
26+
python3 gen_relocate_app.py -i input_file -o generated_linker -c generated_code
2627
2728
Configuration that needs to be sent to the python script.
2829
@@ -45,6 +46,7 @@
4546
import argparse
4647
import os
4748
import glob
49+
import re
4850
import warnings
4951
from collections import defaultdict
5052
from enum import Enum
@@ -225,7 +227,7 @@ def region_is_default_ram(region_name: str) -> bool:
225227
return region_name == args.default_ram_region
226228

227229

228-
def find_sections(filename: str) -> 'dict[SectionKind, list[OutputSection]]':
230+
def find_sections(filename: str, symbol_filter: str) -> 'dict[SectionKind, list[OutputSection]]':
229231
"""
230232
Locate relocatable sections in the given object file.
231233
@@ -243,6 +245,9 @@ def find_sections(filename: str) -> 'dict[SectionKind, list[OutputSection]]':
243245
out = defaultdict(list)
244246

245247
for section in sections:
248+
if not re.search(symbol_filter, section.name):
249+
# Section is filtered-out
250+
continue
246251
section_kind = SectionKind.for_section_named(section.name)
247252
if section_kind is None:
248253
continue
@@ -501,9 +506,10 @@ def get_obj_filename(searchpath, filename):
501506

502507

503508
# Extracts all possible components for the input string:
504-
# <mem_region>[\ :program_header]:<flag_1>[;<flag_2>...]:<file_1>[;<file_2>...]
505-
# Returns a 4-tuple with them: (mem_region, program_header, flags, files)
509+
# <mem_region>[\ :program_header]:<flag_1>[;<flag_2>...]:<file_1>[;<file_2>...][,filter]
510+
# Returns a 5-tuple with them: (mem_region, program_header, flags, files, filter)
506511
# If no `program_header` is defined, returns an empty string
512+
# If no `filter` is defined, returns an empty string
507513
def parse_input_string(line):
508514
# Be careful when splitting by : to avoid breaking absolute paths on Windows
509515
mem_region, rest = line.split(':', 1)
@@ -513,13 +519,19 @@ def parse_input_string(line):
513519
mem_region = mem_region.rstrip()
514520
phdr, rest = rest.split(':', 1)
515521

516-
# Split lists by semicolons, in part to support generator expressions
517-
flag_list, file_list = (lst.split(';') for lst in rest.split(':', 1))
522+
flag_list, rest = rest.split(':', 1)
523+
flag_list = flag_list.split(';')
524+
525+
526+
# Split file list by semicolons, in part to support generator expressions
527+
file_list, symbol_filter = rest.split(',', 1)
528+
file_list = file_list.split(';')
518529

519-
return mem_region, phdr, flag_list, file_list
530+
return mem_region, phdr, flag_list, file_list, symbol_filter
520531

521532

522-
# Create a dict with key as memory type and files as a list of values.
533+
# Create a dict with key as memory type and (files, symbol_filter) tuple
534+
# as a list of values.
523535
# Also, return another dict with program headers for memory regions
524536
def create_dict_wrt_mem():
525537
# need to support wild card *
@@ -529,11 +541,12 @@ def create_dict_wrt_mem():
529541
input_rel_dict = args.input_rel_dict.read().splitlines()
530542
if not input_rel_dict:
531543
sys.exit("Disable CONFIG_CODE_DATA_RELOCATION if no file needs relocation")
544+
532545
for line in input_rel_dict:
533546
if ':' not in line:
534547
continue
535548

536-
mem_region, phdr, flag_list, file_list = parse_input_string(line)
549+
mem_region, phdr, flag_list, file_list, symbol_filter = parse_input_string(line)
537550

538551
# Handle any program header
539552
if phdr != '':
@@ -556,12 +569,15 @@ def create_dict_wrt_mem():
556569
if args.verbose:
557570
print("Memory region ", mem_region, " Selected for files:", file_name_list)
558571

572+
# Apply filter on files
573+
file_name_filter_list = [(f, symbol_filter) for f in file_name_list]
574+
559575
mem_region = "|".join((mem_region, *flag_list))
560576

561577
if mem_region in rel_dict:
562-
rel_dict[mem_region].extend(file_name_list)
578+
rel_dict[mem_region].extend(file_name_filter_list)
563579
else:
564-
rel_dict[mem_region] = file_name_list
580+
rel_dict[mem_region] = file_name_filter_list
565581

566582
return rel_dict, phdrs
567583

@@ -585,13 +601,13 @@ def main():
585601
for memory_type, files in rel_dict.items():
586602
full_list_of_sections: 'dict[SectionKind, list[OutputSection]]' = defaultdict(list)
587603

588-
for filename in files:
604+
for filename, symbol_filter in files:
589605
obj_filename = get_obj_filename(searchpath, filename)
590606
# the obj file wasn't found. Probably not compiled.
591607
if not obj_filename:
592608
continue
593609

594-
file_sections = find_sections(obj_filename)
610+
file_sections = find_sections(obj_filename, symbol_filter)
595611
# Merge sections from file into collection of sections for all files
596612
for category, sections in file_sections.items():
597613
full_list_of_sections[category].extend(sections)

tests/application_development/code_relocation/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ endif()
1717
# Code relocation feature
1818
zephyr_code_relocate(FILES src/test_file1.c ${SRAM2_PHDR} LOCATION SRAM2)
1919

20-
zephyr_code_relocate(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/test_file2.c ${RAM_PHDR} LOCATION RAM)
20+
zephyr_code_relocate(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/test_file2.c ${RAM_PHDR} LOCATION RAM FILTER ".*sram")
2121

2222
# Add custom library that we can relocate code for
2323
add_subdirectory(test_lib)

tests/application_development/code_relocation/src/test_file1.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ __in_section(rodata, sram2, var) const uint32_t var_sram2_rodata = 100U;
2323
__in_section(custom_section, static, var) uint32_t var_custom_data = 1U;
2424

2525
extern void function_in_sram(int32_t value);
26+
extern void function_not_relocated(int32_t value);
2627
void function_in_custom_section(void);
2728

2829
#define HAS_SRAM2_DATA_SECTION (CONFIG_ARM)
2930

3031
ZTEST(code_relocation, test_function_in_sram2)
3132
{
33+
extern uintptr_t __ram_text_reloc_start;
34+
extern uintptr_t __ram_text_reloc_end;
3235
extern uintptr_t __sram2_text_reloc_start;
3336
extern uintptr_t __sram2_text_reloc_end;
3437
extern uintptr_t __sram2_data_reloc_start;
@@ -64,7 +67,20 @@ ZTEST(code_relocation, test_function_in_sram2)
6467
"var_sram2_bss not in sram2_bss region");
6568

6669
/* Print values from sram */
70+
printk("Address of function_in_sram %p\n", &function_in_sram);
71+
zassert_between_inclusive((uintptr_t)&function_in_sram,
72+
(uintptr_t)&__ram_text_reloc_start,
73+
(uintptr_t)&__ram_text_reloc_end,
74+
"function_in_sram is not in ram region");
6775
function_in_sram(var_sram2_data);
76+
77+
/* Print values from non-relocated function */
78+
printk("Address of function_not_relocated %p\n", &function_not_relocated);
79+
zassert_between_inclusive((uintptr_t)&function_not_relocated,
80+
(uintptr_t)&__text_region_start,
81+
(uintptr_t)&__text_region_end,
82+
"function_not_relocated is not in flash region");
83+
function_not_relocated(var_sram2_data);
6884
/* Call library function */
6985
relocated_library();
7086

tests/application_development/code_relocation/src/test_file2.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,14 @@ void function_in_sram(int32_t value)
1919
printk("Address of memcpy %p\n\n", &memcpy);
2020
zassert_mem_equal(src, dst, 8, "memcpy compare error");
2121
}
22+
23+
void function_not_relocated(int32_t value)
24+
{
25+
char src[8] = "data\n";
26+
char dst[8];
27+
28+
printk("Hello World! %s\n", CONFIG_BOARD);
29+
memcpy(dst, src, 8);
30+
printk("Address of memcpy %p\n\n", &memcpy);
31+
zassert_mem_equal(src, dst, 8, "memcpy compare error");
32+
}

0 commit comments

Comments
 (0)