diff options
Diffstat (limited to 'build-aux/measurestack/app_plugins.py')
-rw-r--r-- | build-aux/measurestack/app_plugins.py | 158 |
1 files changed, 108 insertions, 50 deletions
diff --git a/build-aux/measurestack/app_plugins.py b/build-aux/measurestack/app_plugins.py index 7eb7706..519e6b8 100644 --- a/build-aux/measurestack/app_plugins.py +++ b/build-aux/measurestack/app_plugins.py @@ -6,7 +6,7 @@ import re import typing -from . import util +from . import analyze, util from .analyze import BaseName, Node, QName from .util import synthetic_node @@ -51,8 +51,8 @@ class CmdPlugin: return [QName("get_root")], False return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} re_comment = re.compile(r"/\*.*?\*/") @@ -130,8 +130,8 @@ class LibObjPlugin: ], False return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} class LibHWPlugin: @@ -199,8 +199,8 @@ class LibHWPlugin: ], False return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} class LibCRPlugin: @@ -223,8 +223,8 @@ class LibCRPlugin: ) -> tuple[typing.Collection[QName], bool] | None: return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} class LibCRIPCPlugin: @@ -252,8 +252,8 @@ class LibCRIPCPlugin: ], False return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} re_tmessage_handler = re.compile( @@ -263,6 +263,9 @@ 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]).*)$" +) class Lib9PPlugin: @@ -372,21 +375,48 @@ class Lib9PPlugin: return [QName(f"{meth}_{msg}") for msg in self.lib9p_msgs], True return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - if "lib9p/srv.c:srv_util_pathfree" in str(call): - assert isinstance(self.CONFIG_9P_SRV_MAX_DEPTH, int) - if len(chain) >= self.CONFIG_9P_SRV_MAX_DEPTH and all( - ("lib9p/srv.c:srv_util_pathfree" in str(c)) + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + ret: dict[BaseName, analyze.SkipModel] = { + BaseName("_lib9p_validate"): analyze.SkipModel( + 2, + self._skipmodel__lib9p_validate_unmarshal_marshal, + ), + BaseName("_lib9p_unmarshal"): analyze.SkipModel( + 2, + self._skipmodel__lib9p_validate_unmarshal_marshal, + ), + BaseName("_lib9p_marshal"): analyze.SkipModel( + 2, + self._skipmodel__lib9p_validate_unmarshal_marshal, + ), + } + if isinstance(self.CONFIG_9P_SRV_MAX_DEPTH, int): + ret[BaseName("srv_util_pathfree")] = analyze.SkipModel( + self.CONFIG_9P_SRV_MAX_DEPTH, + self._skipmodel_srv_util_pathfree, + ) + return ret + + def _skipmodel__lib9p_validate_unmarshal_marshal( + self, chain: typing.Sequence[QName], call: QName + ) -> bool: + m_caller = re_lib9p_caller.fullmatch(str(chain[-2].base())) + assert m_caller + + m_callee = re_lib9p_callee.fullmatch(str(call.base())) + if not m_callee: + return False + return m_caller.group("grp") != m_callee.group("grp") + + def _skipmodel_srv_util_pathfree( + self, chain: typing.Sequence[QName], call: QName + ) -> bool: + assert isinstance(self.CONFIG_9P_SRV_MAX_DEPTH, int) + if call.base() == BaseName("srv_util_pathfree"): + return len(chain) >= self.CONFIG_9P_SRV_MAX_DEPTH and all( + c.base() == BaseName("srv_util_pathfree") for c in chain[-self.CONFIG_9P_SRV_MAX_DEPTH :] - ): - return True - wrapper = next((c for c in chain if re_lib9p_caller.match(str(c))), None) - if wrapper: - m = re_lib9p_caller.match(str(wrapper)) - assert m - deny = m.group("meth") + "_" + ("R" if m.group("grp") == "T" else "T") - if str(call.base()).startswith(deny): - return True + ) return False @@ -408,14 +438,20 @@ class LibMiscPlugin: ) -> tuple[typing.Collection[QName], bool] | None: return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - if ( - len(chain) > 1 - and chain[-1].base() == BaseName("__assert_msg_fail") - and call.base() == BaseName("__lm_printf") - and any(c.base() == BaseName("__assert_msg_fail") for c in chain[:-1]) - ): - return True + 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], call: QName + ) -> bool: + if call.base() in [BaseName("__lm_printf")]: + return any( + c.base() == BaseName("__assert_msg_fail") for c in reversed(chain[:-1]) + ) return False @@ -462,23 +498,45 @@ class PicoFmtPlugin: return [x.as_qname() for x in self.known_fct.values()], False return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + ret: dict[BaseName, analyze.SkipModel] = { + BaseName("_out_rev"): analyze.SkipModel( + self.known_out.keys(), self._skipmodel_outcaller + ), + BaseName("_etoa"): analyze.SkipModel( + self.known_out.keys(), self._skipmodel_outcaller + ), + BaseName("_vsnprintf"): analyze.SkipModel( + self.known_out.keys(), self._skipmodel_outcaller + ), + BaseName("_out_fct"): analyze.SkipModel( + self.known_fct.keys(), self._skipmodel__out_fct + ), + } + return ret + + def _skipmodel_outcaller(self, chain: typing.Sequence[QName], call: QName) -> bool: if call.base() in self.known_out.values(): out: BaseName | None = None - for pcall in chain: + for pcall in reversed(chain): if pcall.base() in self.known_out: out = self.known_out[pcall.base()] - if out == BaseName("_out_buffer") and call.base() == BaseName( - "_out_null" - ): # XXX: Gross hack - out = BaseName("_out_null") - return call.base() != out + if out == BaseName("_out_buffer") and call.base() == BaseName( + "_out_null" + ): # XXX: Gross hack + out = BaseName("_out_null") + return call.base() != out + return True + return False + + def _skipmodel__out_fct(self, chain: typing.Sequence[QName], call: QName) -> bool: if call.base() in self.known_fct.values(): fct: BaseName | None = None - for pcall in chain: + for pcall in reversed(chain): if pcall.base() in self.known_fct: fct = self.known_fct[pcall.base()] - return call.base() != fct + return call.base() != fct + return True return False @@ -588,8 +646,8 @@ class PicoSDKPlugin: return self.app_preinit_array, False return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} def extra_nodes(self) -> typing.Collection[Node]: ret = [] @@ -820,8 +878,8 @@ class TinyUSBDevicePlugin: return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} class NewlibPlugin: @@ -887,8 +945,8 @@ class NewlibPlugin: ) -> tuple[typing.Collection[QName], bool] | None: return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} class LibGCCPlugin: @@ -917,5 +975,5 @@ class LibGCCPlugin: ) -> tuple[typing.Collection[QName], bool] | None: return None - def skip_call(self, chain: typing.Sequence[QName], call: QName) -> bool: - return False + def skipmodels(self) -> dict[BaseName, analyze.SkipModel]: + return {} |