summaryrefslogtreecommitdiff
path: root/build-aux/measurestack
diff options
context:
space:
mode:
Diffstat (limited to 'build-aux/measurestack')
-rw-r--r--build-aux/measurestack/app_main.py12
-rw-r--r--build-aux/measurestack/app_plugins.py215
-rw-r--r--build-aux/measurestack/test_app_plugins.py379
3 files changed, 34 insertions, 572 deletions
diff --git a/build-aux/measurestack/app_main.py b/build-aux/measurestack/app_main.py
index f705876..4fdfd5c 100644
--- a/build-aux/measurestack/app_main.py
+++ b/build-aux/measurestack/app_main.py
@@ -28,7 +28,7 @@ def main(
# sbc-harness ####################################################
libmisc_plugin = app_plugins.LibMiscPlugin(arg_c_fnames)
- lib9p_plugin = app_plugins.Lib9PPlugin(arg_base_dir, arg_c_fnames, libmisc_plugin)
+ lib9p_plugin = app_plugins.Lib9PPlugin(arg_base_dir, arg_c_fnames)
def sbc_is_thread(name: QName) -> int:
if str(name).endswith("_cr") and name.base() != BaseName("lib9p_srv_read_cr"):
@@ -48,7 +48,6 @@ def main(
plugins += [
app_plugins.CmdPlugin(),
libmisc_plugin,
- app_plugins.PicoFmtPlugin(arg_pico_platform, lib9p_plugin.formatters),
app_plugins.LibHWPlugin(arg_pico_platform, libmisc_plugin),
app_plugins.LibCRPlugin(),
app_plugins.LibCRIPCPlugin(),
@@ -88,12 +87,13 @@ def main(
def misc_filter(name: QName) -> tuple[int, bool]:
if name in [
QName("__assert_msg_fail"),
- QName("__lm_printf"),
- QName("__lm_light_printf"),
- QName("fmt_vfctprintf"),
- QName("fmt_vsnprintf"),
]:
return 1, False
+ for prefix in ["fmt_print_", "_fmt_print_"]:
+ if str(name.base()).startswith(prefix):
+ return 1, False
+ if str(name.base()).endswith("_putb"):
+ return 1, False
return 0, False
extra_includes: list[BaseName] = []
diff --git a/build-aux/measurestack/app_plugins.py b/build-aux/measurestack/app_plugins.py
index e365f82..6fc81ec 100644
--- a/build-aux/measurestack/app_plugins.py
+++ b/build-aux/measurestack/app_plugins.py
@@ -19,7 +19,6 @@ __all__ = [
"LibCRIPCPlugin",
"Lib9PPlugin",
"LibMiscPlugin",
- "PicoFmtPlugin",
"PicoSDKPlugin",
"TinyUSBDevicePlugin",
"NewlibPlugin",
@@ -129,20 +128,7 @@ class LibMiscPlugin:
return None
def skipmodels(self) -> dict[BaseName, analyze.SkipModel]:
- return {
- BaseName("__assert_msg_fail"): analyze.SkipModel(
- {BaseName("__assert_msg_fail")}, self._skipmodel___assert_msg_fail
- ),
- }
-
- def _skipmodel___assert_msg_fail(
- self, chain: typing.Sequence[QName], node: Node, call: QName
- ) -> bool:
- if call.base() in [BaseName("__lm_printf"), BaseName("__lm_light_printf")]:
- return any(
- c.base() == BaseName("__assert_msg_fail") for c in reversed(chain)
- )
- return False
+ return {}
class LibHWPlugin:
@@ -268,35 +254,17 @@ class LibCRIPCPlugin:
class Lib9PPlugin:
- re_tmessage_handler = re.compile(
- r"^\s*\[LIB9P_TYP_T[^]]+\]\s*=\s*\(tmessage_handler\)\s*(?P<handler>\S+),\s*$"
- )
- re_lib9p_msg_entry = re.compile(r"^\s*_MSG_(?:[A-Z]+)\((?P<typ>\S+)\),$")
- re_lib9p_caller = re.compile(
- r"^lib9p_(?P<grp>[TR])msg_(?P<meth>validate|unmarshal|marshal)$"
- )
- re_lib9p_callee = re.compile(
- r"^(?P<meth>validate|unmarshal|marshal)_(?P<msg>(?P<grp>[TR]).*)$"
- )
+ re_lib9p_msg_entry = re.compile(r"^\s*_MSG\((?P<typ>\S+)\),$")
- tmessage_handlers: set[QName] | None
lib9p_msgs: set[str]
_CONFIG_9P_MAX_CONNS: int | None
_CONFIG_9P_MAX_REQS: int | None
- formatters: typing.Collection[BaseName]
def __init__(
self,
arg_base_dir: str,
arg_c_fnames: typing.Collection[str],
- libmisc_plugin: LibMiscPlugin,
) -> None:
- self.formatters = {
- x.base()
- for x in libmisc_plugin.objcalls["format"]
- if str(x.base()).startswith("lib9p_")
- }
-
# Find filenames #######################################################
def _is_config_h(fname: str) -> bool:
@@ -314,7 +282,7 @@ class Lib9PPlugin:
)
lib9p_generated_c_fname = util.get_zero_or_one(
- lambda fname: fname.endswith("lib9p/_core_generated.c"), arg_c_fnames
+ lambda fname: fname.endswith("lib9p/core_generated.c"), arg_c_fnames
)
# Read config ##########################################################
@@ -336,16 +304,6 @@ class Lib9PPlugin:
# Read sources #########################################################
- tmessage_handlers: set[QName] | None = None
- if lib9p_srv_c_fname:
- tmessage_handlers = set()
- with open(lib9p_srv_c_fname, "r", encoding="utf-8") as fh:
- for line in fh:
- line = line.rstrip()
- if m := self.re_tmessage_handler.fullmatch(line):
- tmessage_handlers.add(QName(m.group("handler")))
- self.tmessage_handlers = tmessage_handlers
-
lib9p_msgs: set[str] = set()
if lib9p_generated_c_fname:
with open(lib9p_generated_c_fname, "r", encoding="utf-8") as fh:
@@ -377,153 +335,37 @@ class Lib9PPlugin:
def extra_nodes(self) -> typing.Collection[Node]:
return []
- def indirect_callees(
- self, loc: str, line: str
- ) -> tuple[typing.Collection[QName], bool] | None:
- if "/3rd-party/" in loc:
- return None
- if (
- self.tmessage_handlers
- and "/srv.c:" in loc
- and "tmessage_handlers[typ](" in line
- ):
- # Functions for disabled protocol extensions will be missing.
- return self.tmessage_handlers, True
- if self.lib9p_msgs and "/9p.c:" in loc:
- for meth in ["validate", "unmarshal", "marshal"]:
- if line.startswith(f"tentry.{meth}("):
- # Functions for disabled protocol extensions will be missing.
- return [QName(f"{meth}_{msg}") for msg in self.lib9p_msgs], True
- return None
-
- def skipmodels(self) -> dict[BaseName, analyze.SkipModel]:
- ret: dict[BaseName, analyze.SkipModel] = {
- BaseName("_lib9p_validate"): analyze.SkipModel(
- 1,
- self._skipmodel__lib9p_validate_unmarshal_marshal,
- ),
- BaseName("_lib9p_unmarshal"): analyze.SkipModel(
- 1,
- self._skipmodel__lib9p_validate_unmarshal_marshal,
- ),
- BaseName("_lib9p_marshal"): analyze.SkipModel(
- 1,
- self._skipmodel__lib9p_validate_unmarshal_marshal,
- ),
- }
- return ret
-
- def _skipmodel__lib9p_validate_unmarshal_marshal(
- self, chain: typing.Sequence[QName], node: Node, call: QName
- ) -> bool:
- m_caller = self.re_lib9p_caller.fullmatch(str(chain[-1].base()))
- assert m_caller
-
- m_callee = self.re_lib9p_callee.fullmatch(str(call.base()))
- if not m_callee:
- return False
- return m_caller.group("grp") != m_callee.group("grp")
-
-
-class PicoFmtPlugin:
- known_fct: dict[BaseName, BaseName]
- wont_call_v: typing.Collection[BaseName]
-
- def __init__(
- self, arg_pico_platform: str, wont_call_v: typing.Collection[BaseName]
- ) -> None:
- self.known_fct = {
- # pico_fmt
- BaseName("fmt_vsnprintf"): BaseName("_out_buffer"),
- }
- match arg_pico_platform:
- case "rp2040":
- self.known_fct.update(
- {
- # pico_stdio
- BaseName("__wrap_vprintf"): BaseName("stdio_buffered_printer"),
- BaseName("stdio_vprintf"): BaseName("stdio_buffered_printer"),
- # libfmt
- BaseName("__lm_light_printf"): BaseName("libfmt_light_fct"),
- }
- )
- case "host":
- self.known_fct.update(
- {
- # libfmt
- BaseName("__lm_printf"): BaseName("libfmt_libc_fct"),
- BaseName("__lm_light_printf"): BaseName("libfmt_libc_fct"),
- }
- )
- self.wont_call_v = set([*self.known_fct.values(), *wont_call_v])
-
- def is_intrhandler(self, name: QName) -> bool:
- return False
-
- def init_array(self) -> typing.Collection[QName]:
- return []
-
- def extra_includes(self) -> typing.Collection[BaseName]:
- return []
-
- def extra_nodes(self) -> typing.Collection[Node]:
- return []
+ re_table_call = re.compile(
+ r"\s*_lib9p_(?P<meth>validate|unmarshal|marshal)\(.*(?P<grp>[RT])msg.*\);\s*"
+ )
+ re_print_call = re.compile(r".*lib9p_table_msg.*\.print\(.*")
def indirect_callees(
self, loc: str, line: str
) -> tuple[typing.Collection[QName], bool] | None:
- if "/3rd-party/pico-fmt/" not in loc:
+ if "/3rd-party/" in loc:
return None
- if "/printf.c:" in loc:
- m = util.re_call_other.fullmatch(line)
- call: str | None = m.group("func") if m else None
- if "->fct" in line:
- return [x.as_qname() for x in self.known_fct.values()], False
- if "specifier_table" in line:
+ if self.lib9p_msgs and "lib9p/core.c:" in loc:
+ if m := self.re_table_call.fullmatch(line):
+ meth = m.group("meth")
+ grp = m.group("grp")
+ # Functions for disabled protocol extensions will be missing.
return [
- # pico-fmt
- QName("conv_sint"),
- QName("conv_uint"),
- # QName("conv_double"),
- QName("conv_char"),
- QName("conv_str"),
- QName("conv_ptr"),
- QName("conv_pct"),
- # libfmt
- QName("libfmt_conv_formatter"),
- QName("libfmt_conv_quote"),
- ], False
+ QName(f"{meth}_{msg}")
+ for msg in self.lib9p_msgs
+ if msg.startswith(grp)
+ ], True
+ if self.re_print_call.fullmatch(line):
+ # Functions for disabled protocol extensions will be missing.
+ return [QName(f"fmt_print_{msg}") for msg in self.lib9p_msgs], True
+ if "lib9p/srv.c:" in loc:
+ if "srv->msglog(" in line:
+ # Actual ROMs shouldn't set this, and so will be missing on rp2040 builds.
+ return [QName("log_msg")], True
return None
def skipmodels(self) -> dict[BaseName, analyze.SkipModel]:
- ret: dict[BaseName, analyze.SkipModel] = {
- BaseName("fmt_state_putchar"): analyze.SkipModel(
- self.known_fct.keys(), self._skipmodel_fmt_state_putchar
- ),
- BaseName("_vfctprintf"): analyze.SkipModel(
- self.wont_call_v, self._skipmodel__vfctprintf
- ),
- }
- return ret
-
- def _skipmodel_fmt_state_putchar(
- self, chain: typing.Sequence[QName], node: Node, call: QName
- ) -> bool:
- if call.base() in self.known_fct.values():
- fct: BaseName | None = None
- for pcall in reversed(chain):
- if pcall.base() in self.known_fct:
- fct = self.known_fct[pcall.base()]
- return call.base() != fct
- return True
- return False
-
- def _skipmodel__vfctprintf(
- self, chain: typing.Sequence[QName], node: Node, call: QName
- ) -> bool:
- if call.base() == BaseName("libfmt_conv_formatter"):
- return any(c.base() in self.wont_call_v for c in chain)
- return False
+ return {}
class PicoSDKPlugin:
@@ -604,6 +446,8 @@ class PicoSDKPlugin:
return [QName("rom_func_lookup(ROM_FUNC_FLASH_RANGE_ERASE)")], False
case "flash_flush_cache_func":
return [QName("rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)")], False
+ case "flash_range_program_func":
+ return [QName("rom_func_lookup(ROM_FUNC_FLASH_RANGE_PROGRAM)")], False
case "rom_table_lookup":
return [QName("rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)")], False
if "/flash.c:" in loc and "boot2_copyout" in line:
@@ -941,10 +785,7 @@ class LibGCCPlugin:
return False
def init_array(self) -> typing.Collection[QName]:
- return [
- QName("libfmt_install_formatter"),
- QName("libfmt_install_quote"),
- ]
+ return []
def extra_includes(self) -> typing.Collection[BaseName]:
return []
diff --git a/build-aux/measurestack/test_app_plugins.py b/build-aux/measurestack/test_app_plugins.py
deleted file mode 100644
index da8be65..0000000
--- a/build-aux/measurestack/test_app_plugins.py
+++ /dev/null
@@ -1,379 +0,0 @@
-# build-aux/measurestack/test_app_plugins.py - Tests for app_plugins.py
-#
-# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
-# SPDX-License-Identifier: AGPL-3.0-or-later
-
-# pylint: disable=unused-variable
-
-import typing
-
-from . import analyze, app_plugins, testutil, util
-from .analyze import BaseName, Node, QName, SkipModel
-
-
-def test_assert_msg_fail() -> None:
- # 1 2 3 4 5 6 7 <= call_depth
- # - main()
- # - __assert_msg_fail() *
- # - __lm_light_printf()
- # - fmt_vfctprintf()
- # - stdio_putchar()
- # - __assert_msg_fail() **
- # - __lm_abort()
- # - stdio_flush() (inconsequential)
- # - __lm_abort() (inconsequential)
- max_call_depth = 7
- exp = [
- "main",
- "__assert_msg_fail",
- "__lm_light_printf",
- "fmt_vfctprintf",
- "stdio_putchar",
- "__assert_msg_fail",
- "__lm_abort",
- ]
- graph: typing.Sequence[tuple[str, typing.Collection[str]]] = [
- # main.c
- ("main", {"__assert_msg_fail"}),
- # assert.c
- ("__assert_msg_fail", {"__lm_light_printf", "__lm_abort"}),
- # intercept.c / libfmt/libmisc.c
- ("__lm_abort", {}),
- ("__lm_light_printf", {"fmt_vfctprintf", "stdio_flush"}),
- ("stdio_flush", {}),
- ("stdio_putchar", {"__assert_msg_fail"}),
- # printf.c
- ("fmt_vfctprintf", {"stdio_putchar"}),
- ]
- graph_plugin = testutil.GraphProviderPlugin(max_call_depth, graph)
-
- class SkipPlugin(testutil.NopPlugin):
- def skipmodels(self) -> dict[BaseName, SkipModel]:
- models = app_plugins.LibMiscPlugin(arg_c_fnames=[]).skipmodels()
- assert BaseName("__assert_msg_fail") in models
- orig_model = models[BaseName("__assert_msg_fail")]
-
- def wrapped_model_fn(
- chain: typing.Sequence[QName], node: Node, call: QName
- ) -> bool:
- dbgstr = (
- ("=>".join(str(c) for c in [*chain, node.funcname]))
- + "=?=>"
- + str(call)
- )
- assert dbgstr in [
- "__assert_msg_fail=?=>__lm_light_printf",
- "__assert_msg_fail=?=>__lm_abort",
- "__assert_msg_fail=>__lm_light_printf=>fmt_vfctprintf=>stdio_putchar=>__assert_msg_fail=?=>__lm_light_printf",
- "__assert_msg_fail=>__lm_light_printf=>fmt_vfctprintf=>stdio_putchar=>__assert_msg_fail=?=>__lm_abort",
- ]
- return orig_model.fn(chain, node, call)
-
- models[BaseName("__assert_msg_fail")] = SkipModel(
- orig_model.nchain, wrapped_model_fn
- )
- return models
-
- def test_filter(name: QName) -> tuple[int, bool]:
- if name.base() == BaseName("main"):
- return 1, True
- return 0, False
-
- result = analyze.analyze(
- ci_fnames=[],
- app_func_filters={
- "Main": test_filter,
- },
- app=util.PluginApplication(
- testutil.nop_location_xform, [graph_plugin, SkipPlugin()]
- ),
- cfg_max_call_depth=max_call_depth,
- )
-
- graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("main")].nstatic, exp)
-
-
-def test_fct() -> None:
- # 1. | a + | b + | c + |*
- # 2. | fmt_vsnprintf + | vprintf + | __lm_light_printf + |*
- # 3. | fmt_vfctprintf + | fmt_vfctprintf + | fmt_vfctprintf + |
- # 4. | fmt_state_putchar + | fmt_state_putchar + | fmt_state_putchar + |
- # 5. | _out_buffer + | stdio_buffered_printer + | libfmt_light_fct + |*
- # 6. | | __assert_msg_fail + | __assert_msg_fail + |
- # 7. | | a. __lm_light_printf + | a. __lm_light_printf + |
- # 8. | | a. fmt_vfctprintf + | a. fmt_vfctprintf + |
- # 9. | | a. fmt_state_putchar + | a. fmt_state_putchar + |
- # 10. | | a. libfmt_light_fct + | a. libfmt_light_fct + |
- # 11. | | a. __assert_msg_fail + | a. __assert_msg_fail + |
- # 12. | | a. __lm_abort + | a. __lm_abort + |
- # 7. | | b. __lm_abort | b. __lm_abort |
- max_call_depth = 12
- exp_a = ["a", "fmt_vsnprintf", "fmt_vfctprintf", "fmt_state_putchar", "_out_buffer"]
- exp_b = [
- "b",
- "__wrap_vprintf",
- "fmt_vfctprintf",
- "fmt_state_putchar",
- "stdio_buffered_printer",
- "__assert_msg_fail",
- "__lm_light_printf",
- "fmt_vfctprintf",
- "fmt_state_putchar",
- "libfmt_light_fct",
- "__assert_msg_fail",
- "__lm_abort",
- ]
- exp_c = [
- "c",
- "__lm_light_printf",
- "fmt_vfctprintf",
- "fmt_state_putchar",
- "libfmt_light_fct",
- "__assert_msg_fail",
- "__lm_light_printf",
- "fmt_vfctprintf",
- "fmt_state_putchar",
- "libfmt_light_fct",
- "__assert_msg_fail",
- "__lm_abort",
- ]
- graph: typing.Sequence[tuple[str, typing.Collection[str]]] = [
- # main.c
- ("a", {"fmt_vsnprintf"}), # _out_buffer
- ("b", {"vprintf"}), # stdio_buffered_printer
- ("c", {"__lm_light_printf"}), # libfmt_light_printf
- # wrappers
- ("fmt_vsnprintf", {"fmt_vfctprintf"}),
- ("__wrap_vprintf", {"fmt_vfctprintf"}),
- ("__lm_light_printf", {"fmt_vfctprintf"}),
- # printf.c
- ("fmt_vfctprintf", {"fmt_state_putchar"}),
- (
- "fmt_state_putchar",
- {"_out_buffer", "stdio_buffered_printer", "libfmt_light_fct"},
- ),
- # fcts
- ("_out_buffer", {}),
- ("stdio_buffered_printer", {"__assert_msg_fail"}),
- ("libfmt_light_fct", {"__assert_msg_fail"}),
- # assert.c
- ("__assert_msg_fail", {"__lm_light_printf", "__lm_abort"}),
- # intercept.c / libfmt/libmisc.c
- ("__lm_abort", {}),
- ]
- graph_plugin = testutil.GraphProviderPlugin(max_call_depth, graph)
-
- plugins: list[util.Plugin] = [
- graph_plugin,
- app_plugins.LibMiscPlugin(arg_c_fnames=[]),
- # fmt_vsnprintf => fct=_out_buffer
- # if rp2040:
- # __wrap_vprintf => fct=stdio_buffered_printer
- # stdio_vprintf => fct=stdio_buffered_printer
- # __lm_light_printf => fct=libfmt_light_fct
- # if host:
- # __lm_printf => fct=libfmt_libc_fct
- # __lm_light_printf => fct=libfmt_libc_fct
- app_plugins.PicoFmtPlugin("rp2040", []),
- ]
-
- def test_filter(name: QName) -> tuple[int, bool]:
- if str(name.base()) in ["a", "b", "c"]:
- return 1, True
- return 0, False
-
- result = analyze.analyze(
- ci_fnames=[],
- app_func_filters={
- "Main": test_filter,
- },
- app=util.PluginApplication(testutil.nop_location_xform, plugins),
- cfg_max_call_depth=max_call_depth,
- )
-
- graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("a")].nstatic, exp_a)
- graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("b")].nstatic, exp_b)
- graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("c")].nstatic, exp_c)
-
-
-def test_assert_formatter() -> None:
- # _________________________________________________________
- # | |
- # | |
- # | main |
- # | | |
- # | _ __wrap_vprintf |
- # | / \ | _______________ |
- # | | fmt_vfctprintf / \ |
- # | | \ fmt_state_printf | |
- # | | \____ ____/ | |
- # | | \ / | |
- # | | _vfctprintf | |
- # | | ____/ \____ ^ |
- # | | / ?<---snip | |
- # | | conv_builtin \ | |
- # | | | libfmt_conv_formatter | |
- # | | | | | |
- # | ^ \ lib9p_msg_Rread_format | |
- # | | \ _____________/ | \______/ |
- # | | \ / \ |
- # | | fmt_state_putchar \ |
- # | | ?<-?<--------snip | |
- # | | / \_________ | |
- # | | / \ | |
- # | | stdio_buffered_printer \ | |
- # | | \ libfmt_light_fct | |
- # | | \ | / |
- # | | \_______ | ________/ |
- # | | \ | / |
- # | | __assert_msg_fail |
- # | | ___/ \____ |
- # | | snip--->? \ |
- # | | / \ |
- # | | __lm_light_printf \ |
- # | \____________/ __lm_abort |
- # | |
- # |_________________________________________________________|
- #
- graph: typing.Sequence[tuple[str, typing.Collection[str]]] = [
- ("main", {"vprintf"}),
- ("__wrap_vprintf", {"fmt_vfctprintf"}),
- ("fmt_vfctprintf", {"_vfctprintf"}),
- ("fmt_state_printf", {"_vfctprintf"}),
- ("_vfctprintf", {"conv_builtin", "libfmt_conv_formatter"}),
- ("conv_builtin", {"fmt_state_putchar"}),
- ("libfmt_conv_formatter", {"lib9p_msg_Rread_format"}),
- (
- "lib9p_msg_Rread_format",
- {"fmt_state_putchar", "__assert_msg_fail", "fmt_state_printf"},
- ),
- ("fmt_state_putchar", {"stdio_buffered_printer", "libfmt_light_fct"}),
- ("stdio_buffered_printer", {"__assert_msg_fail"}),
- ("libfmt_light_fct", {"__assert_msg_fail"}),
- ("__assert_msg_fail", {"__lm_light_printf", "__lm_abort"}),
- ("__lm_light_printf", {"fmt_vfctprintf"}),
- ("__lm_abort", {}),
- ]
-
- # fct-determining wrappers have their callees marked with "|":
- #
- # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <= call_depth
- # - main() ; +
- # - __wrap__vprintf() ; +
- # |- fmt_vfctprintf() ; +
- # | - _vfctprintf() ; +
- # | - conv_builtin() ;
- # | - fmt_state_putchar() ;
- # | - stdio_buffered_printer() ;
- # | - __assert_msg_fail() ;
- # | - __lm_light_printf() ;
- # | |- fmt_vfctprintf() ;
- # | | - _vfctprintf() ;
- # | | - conv_builtin() ;
- # | | - fmt_state_putchar() ;
- # | | - stdio_buffered_printer() ; skip (wrong fct)
- # | | - libfmt_light_fct() ;
- # | | - __assert_msg_fail() ;
- # | | - __lm_light_printf() ; skip (nested __assert_msg_fail)
- # | | - __lm_abort() ;
- # | | - libfmt_conv_formatter() ; skip (fct won't use %v)
- # | - __lm_abort() ;
- # | - libfmt_light_fct() ; skip (wrong fct)
- # | - libfmt_conv_formatter() ; +
- # | - lib9p_msg_Rread_format() ; +
- # | - fmt_state_putchar() ;
- # | - stdio_buffered_printer() ;
- # | - __assert_msg_fail() ;
- # | - __lm_light_printf() ;
- # | |- fmt_vfctprintf() ;
- # | | - _vfctprintf() ;
- # | | - conv_builtin() ;
- # | | - fmt_state_putchar() ;
- # | | - stdio_buffered_printer() ; skip (wrong fct)
- # | | - libfmt_light_fct() ;
- # | | - __assert_msg_fail() ;
- # | | - __lm_light_printf() ; skip (neseted __assert_msg_fail)
- # | | - __lm_abort() ;
- # | | - libfmt_conv_formatter() ; skip (fct won't use %v)
- # | - __lm_abort() ;
- # | - libfmt_light_fct() ; skip (wrong fct)
- # | - __assert_msg_fail() ;
- # | - __lm_light_printf() ;
- # | |- fmt_vfctprintf() ;
- # | | - _vfctprintf() ;
- # | | - conv_builtin() ;
- # | | - fmt_state_putchar() ;
- # | | - stdio_buffered_printer() ; skip (wrong fct)
- # | | - libfmt_light_fct() ;
- # | | - __assert_msg_fail() ;
- # | | - __lm_light_printf() ; skip (nested__assert_msg_fail)
- # | | - __lm_abort() ;
- # | | - libfmt_conv_formatter() ; skip (formatter won't use %v)
- # | - __lm_abort() ;
- # | - fmt_state_printf() ; +
- # | - _vfctprintf() ; +
- # | - conv_builtin() ; +
- # | - fmt_state_putchar() ; +
- # | - stdio_buffered_printer() ; +
- # | - __assert_msg_fail() ; +
- # | - __lm_light_printf() ; +
- # | |- fmt_vfctprintf() ; +
- # | | - _vfctprintf() ; +
- # | | - conv_builtin() ; +
- # | | - fmt_state_putchar() ; +
- # | | - stdio_buffered_printer() ; skip (wrong fct)
- # | | - libfmt_light_fct() ; +
- # | | - __assert_msg_fail() ; +
- # | | - __lm_light_printf() ; skip (neseted __assert_msg_fail)
- # | | - __lm_abort() ; +
- # | | - libfmt_conv_formatter() ; skip (fct won't use %v)
- # | - __lm_abort() ;
- # | - libfmt_light_fct() ; skip (wrong fct)
- # | - libfmt_conv_formatter() ; skip (formatter won't use %v)
- max_call_depth = 20
- exp = [
- "main",
- "__wrap_vprintf",
- "fmt_vfctprintf",
- "_vfctprintf",
- "libfmt_conv_formatter",
- "lib9p_msg_Rread_format",
- "fmt_state_printf",
- "_vfctprintf",
- "conv_builtin",
- "fmt_state_putchar",
- "stdio_buffered_printer",
- "__assert_msg_fail",
- "__lm_light_printf",
- "fmt_vfctprintf",
- "_vfctprintf",
- "conv_builtin",
- "fmt_state_putchar",
- "libfmt_light_fct",
- "__assert_msg_fail",
- "__lm_abort",
- ]
-
- graph_plugin = testutil.GraphProviderPlugin(max_call_depth, graph)
-
- plugins: list[util.Plugin] = [
- graph_plugin,
- app_plugins.LibMiscPlugin(arg_c_fnames=[]),
- app_plugins.PicoFmtPlugin("rp2040", [BaseName("lib9p_msg_Rread_format")]),
- ]
-
- def test_filter(name: QName) -> tuple[int, bool]:
- if name.base() == BaseName("main"):
- return 1, True
- return 0, False
-
- result = analyze.analyze(
- ci_fnames=[],
- app_func_filters={
- "Main": test_filter,
- },
- app=util.PluginApplication(testutil.nop_location_xform, plugins),
- cfg_max_call_depth=max_call_depth,
- )
-
- graph_plugin.assert_nstatic(result.groups["Main"].rows[QName("main")].nstatic, exp)