Skip to content

tools: add find-reachable-from-loader-func cmd to check_callgraph.py#554

Open
almir-okato wants to merge 1 commit into
zephyrproject-rtos:mainfrom
almir-okato:check_callgraph_loader_seg
Open

tools: add find-reachable-from-loader-func cmd to check_callgraph.py#554
almir-okato wants to merge 1 commit into
zephyrproject-rtos:mainfrom
almir-okato:check_callgraph_loader_seg

Conversation

@almir-okato

@almir-okato almir-okato commented May 12, 2026

Copy link
Copy Markdown
Contributor

find-reachable-from-loader-func find the call/object references from a given root function that should be placed in the i/dram_loader_seg of MCUboot bootloader (works for Espressif Port and Zephyr Port).

Comment thread tools/ci/check_callgraph.py Outdated
Comment thread tools/ci/check_callgraph.py Outdated
@sylvioalves

Copy link
Copy Markdown
Collaborator

In _classify_placement, default DRAM matching only triggers on .dram* sections.. does that mean a function/object placed in plain .rodata.x/.bss.x/.data.x is intentionally skipped from DRAM_LOADER classification unless the caller passes --dram-sections? Also, in the --summary output, was it intended to print the IRAM linker fragment (.literal .text .iram0 ...) for DRAM_LOADER groups and the BSS/data fragments for IRAM_LOADER groups? Both seem to point the user at the wrong segment.

find-reachable-from-loader-func find the call/object references
reachable from a given root function that should be placed in the
i/dram_loader_seg of MCUboot bootloader.

Signed-off-by: Almir Okato <almir.okato@espressif.com>
@almir-okato almir-okato force-pushed the check_callgraph_loader_seg branch from 8315325 to 66f22df Compare May 19, 2026 14:16
@almir-okato almir-okato changed the title tools: add find-loader-minset option to check_callgraph.py tools: add find-reachable-from-loader-func cmd to check_callgraph.py May 19, 2026
@almir-okato

Copy link
Copy Markdown
Contributor Author

In _classify_placement, default DRAM matching only triggers on .dram* sections.. does that mean a function/object placed in plain .rodata.x/.bss.x/.data.x is intentionally skipped from DRAM_LOADER classification unless the caller passes --dram-sections? Also, in the --summary output, was it intended to print the IRAM linker fragment (.literal .text .iram0 ...) for DRAM_LOADER groups and the BSS/data fragments for IRAM_LOADER groups? Both seem to point the user at the wrong segment.

Checking sec.startswith( ... ) should cover this kind of case, there are some default name checking.

Regarding the --summary, I changed it to print the linker script's placement recommendation of the objects containing the symbols found.

@almir-okato almir-okato requested a review from sylvioalves May 19, 2026 15:21
return 'IRAM_LOADER'
# DRAM data/rodata/bss placement
if (sym.is_object() or sec.startswith('.rodata') or sec.startswith('.bss') or '.rodata' in sec or '.bss' in sec or '.data' in sec):
if any(sec.startswith(s) for s in dram_like + ['.dram', '.dram0', '.dram0.bss', '.dram0.data', '.dram0.rodata']):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you also add here '.rodata', '.bss', '.data', '.sbss', '.sdata', '.srodata' as well? In bootloader.ld files, those areas lives in DRAM area, right?

from collections import deque
from functools import partial
from typing import BinaryIO, Callable, Dict, Generator, List, Optional, Tuple
from typing import BinaryIO, Callable, Dict, Generator, List, Optional, Tuple, Set

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Deque here?

# Optionally annotate symbols with origin from map
if map_path:
symbol_names: Set[str] = {s.name for s in symbols}
origin_map = build_origin_map(map_path, symbol_names)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when two same-named static symbols from different object files? Perhaps it should check name,addr instead?

),
]

def print_loader_linker_summary(origins: List[str]) -> None:

@raffarost raffarost Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From AI assisted review:

When the --summary path runs, it always emits linker fragments for all three segments regardless of what was actually found. If a user runs this against a binary where only IRAM symbols are out of place, the output will still suggest adding object patterns to .dram_loader.bss and .dram_loader.data — which would be wrong linker script additions. That can actively mislead whoever is acting on the output.

The fix is straightforward: pass two separate origin sets to the summary function (one for IRAM, one for DRAM) and only emit the segment entries that have at least one pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants