diff options
-rw-r--r-- | build-aux/measurestack/app_main.py | 2 | ||||
-rw-r--r-- | build-aux/measurestack/app_plugins.py | 26 | ||||
-rw-r--r-- | build-aux/measurestack/test_app_plugins.py | 185 |
3 files changed, 200 insertions, 13 deletions
diff --git a/build-aux/measurestack/app_main.py b/build-aux/measurestack/app_main.py index c670325..f705876 100644 --- a/build-aux/measurestack/app_main.py +++ b/build-aux/measurestack/app_main.py @@ -48,7 +48,7 @@ def main( plugins += [ app_plugins.CmdPlugin(), libmisc_plugin, - app_plugins.PicoFmtPlugin(arg_pico_platform), + app_plugins.PicoFmtPlugin(arg_pico_platform, lib9p_plugin.formatters), app_plugins.LibHWPlugin(arg_pico_platform, libmisc_plugin), app_plugins.LibCRPlugin(), app_plugins.LibCRIPCPlugin(), diff --git a/build-aux/measurestack/app_plugins.py b/build-aux/measurestack/app_plugins.py index 8eda36c..e365f82 100644 --- a/build-aux/measurestack/app_plugins.py +++ b/build-aux/measurestack/app_plugins.py @@ -410,9 +410,6 @@ class Lib9PPlugin: 1, self._skipmodel__lib9p_validate_unmarshal_marshal, ), - BaseName("_vfctprintf"): analyze.SkipModel( - self.formatters, self._skipmodel__vfctprintf - ), } return ret @@ -427,18 +424,14 @@ class Lib9PPlugin: return False return m_caller.group("grp") != m_callee.group("grp") - 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.formatters for c in chain) - return False - class PicoFmtPlugin: known_fct: dict[BaseName, BaseName] + wont_call_v: typing.Collection[BaseName] - def __init__(self, arg_pico_platform: str) -> None: + 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"), @@ -462,6 +455,7 @@ class PicoFmtPlugin: 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 @@ -506,6 +500,9 @@ class PicoFmtPlugin: 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 @@ -521,6 +518,13 @@ class PicoFmtPlugin: 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 + class PicoSDKPlugin: get_init_array: typing.Callable[[], typing.Collection[QName]] diff --git a/build-aux/measurestack/test_app_plugins.py b/build-aux/measurestack/test_app_plugins.py index d7e95b1..da8be65 100644 --- a/build-aux/measurestack/test_app_plugins.py +++ b/build-aux/measurestack/test_app_plugins.py @@ -174,7 +174,7 @@ def test_fct() -> None: # if host: # __lm_printf => fct=libfmt_libc_fct # __lm_light_printf => fct=libfmt_libc_fct - app_plugins.PicoFmtPlugin("rp2040"), + app_plugins.PicoFmtPlugin("rp2040", []), ] def test_filter(name: QName) -> tuple[int, bool]: @@ -194,3 +194,186 @@ def test_fct() -> None: 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) |