From 7bc1e8049dbbf572a773d01547eb9b587b112061 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Tue, 10 Dec 2024 00:41:14 -0700 Subject: Analyze host stacks too --- build-aux/stack.c.gen | 559 +++++++++++++++++++++++++++----------------------- 1 file changed, 299 insertions(+), 260 deletions(-) (limited to 'build-aux') diff --git a/build-aux/stack.c.gen b/build-aux/stack.c.gen index 22b18d5..86bca26 100755 --- a/build-aux/stack.c.gen +++ b/build-aux/stack.c.gen @@ -137,8 +137,9 @@ def analyze( re_node_label = re.compile( r"(?P[^\n]+)\n" + r"(?P[^\n]+:[0-9]+:[0-9]+)\n" - + r"(?P[0-9]+) bytes \(static\)\n" - + r"(?P[0-9]+) dynamic objects", + + r"(?P[0-9]+) bytes \((?Pstatic|dynamic|dynamic,bounded)\)\n" + + r"(?P[0-9]+) dynamic objects" + + r"(?:\n.*)?", flags=re.MULTILINE, ) @@ -162,6 +163,9 @@ def analyze( raise ValueError( f"unexpected label value {repr(v)}" ) + if m.group("usage_kind") == "dynamic": + pass + #raise ValueError(f"can't handle dynamic stack usage: {repr(elem.attrs.get("title", ""))}") node.location = m.group("location") node.nstatic = int(m.group("nstatic")) node.ndynamic = int(m.group("ndynamic")) @@ -312,11 +316,20 @@ def read_source(location: str) -> str: def main( - *, arg_base_dir: str, arg_ci_fnames: list[str], arg_c_fnames: list[str] + *, + arg_pico_platform: str, + arg_base_dir: str, + arg_ci_fnames: list[str], + arg_c_fnames: list[str], ) -> None: re_call_other = re.compile(r"(?P[^(]+)\(.*") + all_nodes: list[Node] = [] + hooks_is_intrhandler: list[typing.Callable([str], bool)] = [] + hooks_indirect_callees: list[typing.Callable[[str, str], list[str] | None]] = [] + hooks_skip_call: list[typing.Callable[[list[str], str], bool]] = [] + # The sbc-harness codebase ####################################### vcalls: dict[str, set[str]] = {} @@ -363,6 +376,8 @@ def main( ] return None + hooks_indirect_callees += [sbc_indirect_callees] + def sbc_is_thread(name: str) -> bool: return name.endswith("_cr") or name == "main" @@ -374,6 +389,8 @@ def main( "hostnet_handle_sig_io", ] + hooks_is_intrhandler += [sbc_is_intrhandler] + sbc_gpio_handlers = [ "w5500_intrhandler", ] @@ -386,268 +403,298 @@ def main( and any(c.endswith(":__assert_msg_fail") for c in chain[:-1]) ): return True - if call == "_cr_select_dequeue": + if call == "_cr_select_dequeue": # TODO: FIXME return True return False + hooks_skip_call += [sbc_skip_call] + # pico-sdk ####################################################### - def pico_is_intrhandler(name: str) -> bool: - return name in [ - "gpio_default_irq_handler", - ] + if arg_pico_platform == "rp2040": - def pico_indirect_callees(loc: str, line: str) -> list[str] | None: - if "/3rd-party/pico-sdk/" not in loc or "/3rd-party/pico-sdk/lib/" in loc: + def pico_is_intrhandler(name: str) -> bool: + return name in [ + "gpio_default_irq_handler", + ] + + hooks_is_intrhandler += [pico_is_intrhandler] + + def pico_indirect_callees(loc: str, line: str) -> list[str] | None: + if "/3rd-party/pico-sdk/" not in loc or "/3rd-party/pico-sdk/lib/" in loc: + return None + m = re_call_other.fullmatch(line) + call: str | None = m.group("func") if m else None + + match call: + case "connect_internal_flash_func": + return ["rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH)"] + case "flash_exit_xip_func": + return ["rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP)"] + case "flash_range_erase_func": + return ["rom_func_lookup(ROM_FUNC_FLASH_RANGE_ERASE)"] + case "flash_flush_cache_func": + return ["rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)"] + case "rom_table_lookup": + return ["rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)"] + if "/flash.c:" in loc and "boot2_copyout" in line: + return ["_stage2_boot"] + if "/gpio.c:" in loc and call == "callback": + return sbc_gpio_handlers + if "/printf.c:" in loc: + if call == "out": + return [ + "_out_buffer", + "_out_null", + "_out_fct", + ] + if "->fct(" in line: + return ["stdio_buffered_printer"] + if "/stdio.c:" in loc: + if call == "out_func": + return [ + "stdio_out_chars_crlf", + "stdio_out_chars_no_crlf", + ] + if call and (call.startswith("d->") or call.startswith("driver->")): + _, meth = call.split("->", 1) + match meth: + case "out_chars": + return ["stdio_uart_out_chars"] + case "out_flush": + return ["stdio_uart_out_flush"] + case "in_chars": + return ["stdio_uart_in_chars"] return None - m = re_call_other.fullmatch(line) - call: str | None = m.group("func") if m else None - - match call: - case "connect_internal_flash_func": - return ["rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH)"] - case "flash_exit_xip_func": - return ["rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP)"] - case "flash_range_erase_func": - return ["rom_func_lookup(ROM_FUNC_FLASH_RANGE_ERASE)"] - case "flash_flush_cache_func": - return ["rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)"] - case "rom_table_lookup": - return ["rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)"] - if "/flash.c:" in loc and "boot2_copyout" in line: - return ["_stage2_boot"] - if "/gpio.c:" in loc and call == "callback": - return sbc_gpio_handlers - if "/printf.c:" in loc: - if call == "out": - return [ - "_out_buffer", - "_out_null", - "_out_fct", - ] - if "->fct(" in line: - return ["stdio_buffered_printer"] - if "/stdio.c:" in loc: - if call == "out_func": - return [ - "stdio_out_chars_crlf", - "stdio_out_chars_no_crlf", - ] - if call and (call.startswith("d->") or call.startswith("driver->")): - _, meth = call.split("->", 1) - match meth: - case "out_chars": - return ["stdio_uart_out_chars"] - case "out_flush": - return ["stdio_uart_out_flush"] - case "in_chars": - return ["stdio_uart_in_chars"] - return None - def pico_skip_call(chain: list[str], call: str) -> bool: - if call == "_out_buffer" or call == "_out_fct": - last = "" - for pcall in chain: - if pcall in [ - "__wrap_sprintf", - "__wrap_snprintf", - "__wrap_vsnprintf", - "vfctprintf", - ]: - last = pcall - if last == "vfctprintf": - return call != "_out_fct" - else: - return call == "_out_buffer" - return False + hooks_indirect_callees += [pico_indirect_callees] + + def pico_skip_call(chain: list[str], call: str) -> bool: + if call == "_out_buffer" or call == "_out_fct": + last = "" + for pcall in chain: + if pcall in [ + "__wrap_sprintf", + "__wrap_snprintf", + "__wrap_vsnprintf", + "vfctprintf", + ]: + last = pcall + if last == "vfctprintf": + return call != "_out_fct" + else: + return call == "_out_buffer" + return False + + hooks_skip_call += [pico_skip_call] - # src/rp2_common/hardware_divider/include/hardware/divider_helper.S - save_div_state_and_lr = 5 * 4 - # src/rp2_common/pico_divider/divider_hardware.S - save_div_state_and_lr_64 = 5 * 4 - pico_nodes: list[Node] = [ - # src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S - synthetic_node("__aeabi_lmul", 4), + # src/rp2_common/hardware_divider/include/hardware/divider_helper.S + save_div_state_and_lr = 5 * 4 # src/rp2_common/pico_divider/divider_hardware.S - # s32 aliases - synthetic_node("div_s32s32", 0, {"divmod_s32s32"}), - synthetic_node("__aeabi_idiv", 0, {"divmod_s32s32"}), - synthetic_node("__aeabi_idivmod", 0, {"divmod_s32s32"}), - # s32 impl - synthetic_node("divmod_s32s32", 0, {"divmod_s32s32_savestate"}), - synthetic_node( - "divmod_s32s32_savestate", save_div_state_and_lr, {"divmod_s32s32_unsafe"} - ), - synthetic_node("divmod_s32s32_unsafe", 2 * 4, {"__aeabi_idiv0"}), - # u32 aliases - synthetic_node("div_u32u32", 0, {"divmod_u32u32"}), - synthetic_node("__aeabi_uidiv", 0, {"divmod_u32u32"}), - synthetic_node("__aeabi_uidivmod", 0, {"divmod_u32u32"}), - # u32 impl - synthetic_node("divmod_u32u32", 0, {"divmod_u32u32_savestate"}), - synthetic_node( - "divmod_u32u32_savestate", save_div_state_and_lr, {"divmod_u32u32_unsafe"} - ), - synthetic_node("divmod_u32u32_unsafe", 2 * 4, {"__aeabi_idiv0"}), - # s64 aliases - synthetic_node("div_s64s64", 0, {"divmod_s64s64"}), - synthetic_node("__aeabi_ldiv", 0, {"divmod_s64s64"}), - synthetic_node("__aeabi_ldivmod", 0, {"divmod_s64s64"}), - # s64 impl - synthetic_node("divmod_s64s64", 0, {"divmod_s64s64_savestate"}), - synthetic_node( - "divmod_s64s64_savestate", - save_div_state_and_lr_64 + (2 * 4), - {"divmod_s64s64_unsafe"}, - ), - synthetic_node( - "divmod_s64s64_unsafe", 4, {"divmod_u64u64_unsafe", "__aeabi_ldiv0"} - ), - # u64 aliases - synthetic_node("div_u64u64", 0, {"divmod_u64u64"}), - synthetic_node("__aeabi_uldiv", 0, {"divmod_u64u64"}), - synthetic_node("__aeabi_uldivmod", 0, {"divmod_u64u64"}), - # u64 impl - synthetic_node("divmod_u64u64", 0, {"divmod_u64u64_savestate"}), - synthetic_node( - "divmod_u64u64_savestate", - save_div_state_and_lr_64 + (2 * 4), - {"divmod_u64u64_unsafe"}, - ), - synthetic_node( - "divmod_u64u64_unsafe", (1 + 1 + 2 + 5 + 5 + 2) * 4, {"__aeabi_ldiv0"} - ), - # *_rem - synthetic_node("divod_s64s64_rem", 2 * 4, {"divmod_s64s64"}), - synthetic_node("divod_u64u64_rem", 2 * 4, {"divmod_u64u64"}), - # src/rp2040/boot_stage2/boot2_${name,,}.S for name=W25Q080, - # controlled by `#define PICO_BOOT_STAGE2_{name} 1` in - # src/boards/include/boards/pico.h - synthetic_node("_stage2_boot", 0), # TODO - # https://github.com/raspberrypi/pico-bootrom-rp2040 - synthetic_node("rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH)", 0), # TODO - synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP)", 0), # TODO - synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)", 0), # TODO - synthetic_node("rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)", 0), # TODO - ] + save_div_state_and_lr_64 = 5 * 4 + all_nodes += [ + # src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S + synthetic_node("__aeabi_lmul", 4), + # src/rp2_common/pico_divider/divider_hardware.S + # s32 aliases + synthetic_node("div_s32s32", 0, {"divmod_s32s32"}), + synthetic_node("__aeabi_idiv", 0, {"divmod_s32s32"}), + synthetic_node("__aeabi_idivmod", 0, {"divmod_s32s32"}), + # s32 impl + synthetic_node("divmod_s32s32", 0, {"divmod_s32s32_savestate"}), + synthetic_node( + "divmod_s32s32_savestate", + save_div_state_and_lr, + {"divmod_s32s32_unsafe"}, + ), + synthetic_node("divmod_s32s32_unsafe", 2 * 4, {"__aeabi_idiv0"}), + # u32 aliases + synthetic_node("div_u32u32", 0, {"divmod_u32u32"}), + synthetic_node("__aeabi_uidiv", 0, {"divmod_u32u32"}), + synthetic_node("__aeabi_uidivmod", 0, {"divmod_u32u32"}), + # u32 impl + synthetic_node("divmod_u32u32", 0, {"divmod_u32u32_savestate"}), + synthetic_node( + "divmod_u32u32_savestate", + save_div_state_and_lr, + {"divmod_u32u32_unsafe"}, + ), + synthetic_node("divmod_u32u32_unsafe", 2 * 4, {"__aeabi_idiv0"}), + # s64 aliases + synthetic_node("div_s64s64", 0, {"divmod_s64s64"}), + synthetic_node("__aeabi_ldiv", 0, {"divmod_s64s64"}), + synthetic_node("__aeabi_ldivmod", 0, {"divmod_s64s64"}), + # s64 impl + synthetic_node("divmod_s64s64", 0, {"divmod_s64s64_savestate"}), + synthetic_node( + "divmod_s64s64_savestate", + save_div_state_and_lr_64 + (2 * 4), + {"divmod_s64s64_unsafe"}, + ), + synthetic_node( + "divmod_s64s64_unsafe", 4, {"divmod_u64u64_unsafe", "__aeabi_ldiv0"} + ), + # u64 aliases + synthetic_node("div_u64u64", 0, {"divmod_u64u64"}), + synthetic_node("__aeabi_uldiv", 0, {"divmod_u64u64"}), + synthetic_node("__aeabi_uldivmod", 0, {"divmod_u64u64"}), + # u64 impl + synthetic_node("divmod_u64u64", 0, {"divmod_u64u64_savestate"}), + synthetic_node( + "divmod_u64u64_savestate", + save_div_state_and_lr_64 + (2 * 4), + {"divmod_u64u64_unsafe"}, + ), + synthetic_node( + "divmod_u64u64_unsafe", (1 + 1 + 2 + 5 + 5 + 2) * 4, {"__aeabi_ldiv0"} + ), + # *_rem + synthetic_node("divod_s64s64_rem", 2 * 4, {"divmod_s64s64"}), + synthetic_node("divod_u64u64_rem", 2 * 4, {"divmod_u64u64"}), + # src/rp2040/boot_stage2/boot2_${name,,}.S for name=W25Q080, + # controlled by `#define PICO_BOOT_STAGE2_{name} 1` in + # src/boards/include/boards/pico.h + synthetic_node("_stage2_boot", 0), # TODO + # https://github.com/raspberrypi/pico-bootrom-rp2040 + synthetic_node( + "rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH)", 0 + ), # TODO + synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP)", 0), # TODO + synthetic_node("rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE)", 0), # TODO + synthetic_node("rom_hword_as_ptr(BOOTROM_TABLE_LOOKUP_OFFSET)", 0), # TODO + ] - # TinyUSB ######################################################## + # TinyUSB device ################################################# + + if any(fname.endswith("/tinyusb/src/device/usbd.c") for fname in c_fnames): + tusb_config_fname = ( + arg_base_dir + "/cmd/sbc_harness/config/tusb_config.h" + ) # TODO: FIXME + re_tud_class = re.compile( + r"^\s*#\s*define\s+(?PCFG_TUD_(?:\S{3}|AUDIO|VIDEO|MIDI|VENDOR|USBTMC|DFU_RUNTIME|ECM_RNDIS))\s+(?P\S+).*" + ) + tusb_config: dict[str, bool] = {} + with open(tusb_config_fname, "r") as fh: + in_table = False + for line in fh: + line = line.rstrip() + if m := re_tud_class.fullmatch(line): + k = m.group("k") + v = m.group("v") + tusb_config[k] = bool(int(v)) + + usbd_fname = next( + fname for fname in c_fnames if fname.endswith("/tinyusb/src/device/usbd.c") + ) + tud_drivers: dict[str, set[str]] = {} + re_tud_entry = re.compile( + r"^\s+\.(?P\S+)\s*=\s*(?P[a-zA-Z0-9_]+)(?:,.*)?" + ) + re_tud_if1 = re.compile(r"^\s*#\s*if (\S+)\s*") + re_tud_if2 = re.compile(r"^\s*#\s*if (\S+)\s*\|\|\s*(\S+)\s*") + re_tud_endif = re.compile(r"^\s*#\s*endif\s*") + with open(usbd_fname, "r") as fh: + in_table = False + enabled = True + for line in fh: + line = line.rstrip() + if in_table: + if m := re_tud_if1.fullmatch(line): + enabled = tusb_config[m.group(1)] + elif m := re_tud_if2.fullmatch(line): + enabled = tusb_config[m.group(1)] or tusb_config[m.group(2)] + elif re_tud_endif.fullmatch(line): + enabled = True + if m := re_tud_entry.fullmatch(line): + meth = m.group("meth") + impl = m.group("impl") + if meth == "name" or not enabled: + continue + if meth not in tud_drivers: + tud_drivers[meth] = set() + if impl != "NULL": + tud_drivers[meth].add(impl) + if line.startswith("}"): + in_table = False + elif " _usbd_driver[] = {" in line: + in_table = True + + def tud_indirect_callees(loc: str, line: str) -> list[str] | None: + if ( + "/tinyusb/" not in loc + or "/tinyusb/src/host/" in loc + or "_host.c:" in loc + ): + return None + m = re_call_other.fullmatch(line) + assert m + call = m.group("func") + if call == "_ctrl_xfer.complete_cb": + return [ + # "process_test_mode_cb", + "tud_vendor_control_xfer_cb", + *sorted(tud_drivers["control_xfer_cb"]), + ] + elif call.startswith("driver->"): + return sorted(tud_drivers[call[len("driver->") :]]) + elif call == "event.func_call.func": + # callback from usb_defer_func() + return [] - tusb_config_fname = ( - arg_base_dir + "/cmd/sbc_harness/config/tusb_config.h" - ) # TODO: FIXME - re_tud_class = re.compile( - r"^\s*#\s*define\s+(?PCFG_TUD_(?:\S{3}|AUDIO|VIDEO|MIDI|VENDOR|USBTMC|DFU_RUNTIME|ECM_RNDIS))\s+(?P\S+).*" - ) - tusb_config: dict[str, bool] = {} - with open(tusb_config_fname, "r") as fh: - in_table = False - for line in fh: - line = line.rstrip() - if m := re_tud_class.fullmatch(line): - k = m.group("k") - v = m.group("v") - tusb_config[k] = bool(int(v)) - - usbd_fname = next( - fname for fname in c_fnames if fname.endswith("/tinyusb/src/device/usbd.c") - ) - tud_drivers: dict[str, set[str]] = {} - re_tud_entry = re.compile( - r"^\s+\.(?P\S+)\s*=\s*(?P[a-zA-Z0-9_]+)(?:,.*)?" - ) - re_tud_if1 = re.compile(r"^\s*#\s*if (\S+)\s*") - re_tud_if2 = re.compile(r"^\s*#\s*if (\S+)\s*\|\|\s*(\S+)\s*") - re_tud_endif = re.compile(r"^\s*#\s*endif\s*") - with open(usbd_fname, "r") as fh: - in_table = False - enabled = True - for line in fh: - line = line.rstrip() - if in_table: - if m := re_tud_if1.fullmatch(line): - enabled = tusb_config[m.group(1)] - elif m := re_tud_if2.fullmatch(line): - enabled = tusb_config[m.group(1)] or tusb_config[m.group(2)] - elif re_tud_endif.fullmatch(line): - enabled = True - if m := re_tud_entry.fullmatch(line): - meth = m.group("meth") - impl = m.group("impl") - if meth == "name" or not enabled: - continue - if meth not in tud_drivers: - tud_drivers[meth] = set() - if impl != "NULL": - tud_drivers[meth].add(impl) - if line.startswith("}"): - in_table = False - elif " _usbd_driver[] = {" in line: - in_table = True - - def tud_indirect_callees(loc: str, line: str) -> list[str] | None: - if "/tinyusb/" not in loc or "/tinyusb/src/host/" in loc or "_host.c:" in loc: return None - m = re_call_other.fullmatch(line) - assert m - call = m.group("func") - if call == "_ctrl_xfer.complete_cb": - return [ - # "process_test_mode_cb", - "tud_vendor_control_xfer_cb", - *sorted(tud_drivers["control_xfer_cb"]), - ] - elif call.startswith("driver->"): - return sorted(tud_drivers[call[len("driver->") :]]) - elif call == "event.func_call.func": - # callback from usb_defer_func() - return [] - return None + hooks_indirect_callees += [tud_indirect_callees] - def tud_skip_call(chain: list[str], call: str) -> bool: - if call == "usbd_app_driver_get_cb": - return True - return False + def tud_skip_call(chain: list[str], call: str) -> bool: + if call == "usbd_app_driver_get_cb": # TODO: FIXME + return True + return False + + hooks_skip_call += [tud_skip_call] # newlib ######################################################### - newlib_nodes: list[Node] = [ - # malloc - synthetic_node("free", 0), # TODO - synthetic_node("malloc", 0), # TODO - synthetic_node("realloc", 0), # TODO - synthetic_node("aligned_alloc", 0), # TODO - synthetic_node("reallocarray", 0), # TODO - # execution - synthetic_node("abort", 0), # TODO - synthetic_node("longjmp", 0), # TODO - synthetic_node("setjmp", 0), # TODO - # - synthetic_node("memcmp", 0), # TODO - synthetic_node("memcpy", 0), # TODO - synthetic_node("memset", 0), # TODO - synthetic_node("strlen", 0), # TODO - synthetic_node("strncpy", 0), # TODO - # other - synthetic_node("random", 0), # TODO - ] + if arg_pico_platform == "rp2040": + all_nodes += [ + # malloc + synthetic_node("free", 0), # TODO + synthetic_node("malloc", 0), # TODO + synthetic_node("realloc", 0), # TODO + synthetic_node("aligned_alloc", 0), # TODO + synthetic_node("reallocarray", 0), # TODO + # execution + synthetic_node("abort", 0), # TODO + synthetic_node("longjmp", 0), # TODO + synthetic_node("setjmp", 0), # TODO + # + synthetic_node("memcmp", 0), # TODO + synthetic_node("memcpy", 0), # TODO + synthetic_node("memset", 0), # TODO + synthetic_node("strlen", 0), # TODO + synthetic_node("strncpy", 0), # TODO + # other + synthetic_node("random", 0), # TODO + ] # libgcc ######################################################### - gcc_nodes: list[Node] = [ - synthetic_node("__aeabi_idiv0", 0), # TODO - synthetic_node("__aeabi_ldiv0", 0), # TODO - ] + if arg_pico_platform == "rp2040": + all_nodes += [ + synthetic_node("__aeabi_idiv0", 0), # TODO + synthetic_node("__aeabi_ldiv0", 0), # TODO + ] - # main ########################################################### + # Tie it all together ############################################ def thread_filter(name: str) -> bool: return sbc_is_thread(name) def intrhandler_filter(name: str) -> bool: name = name.rsplit(":", 1)[-1] - return sbc_is_intrhandler(name) or pico_is_intrhandler(name) + for hook in hooks_is_intrhandler: + if hook(name): + return True + return False def location_xform(loc: str) -> str: if not loc.startswith("/"): @@ -660,30 +707,22 @@ def main( loc = elem.attrs.get("label", "") line = read_source(loc) - ret = sbc_indirect_callees(loc, line) - if ret is not None: - return ret - - ret = pico_indirect_callees(loc, line) - if ret is not None: - return ret - - ret = tud_indirect_callees(loc, line) - if ret is not None: - return ret + for hook in hooks_indirect_callees: + ret = hook(loc, line) + if ret is not None: + return ret return [f"__indirect_call:" + location_xform(elem.attrs.get("label", ""))] def skip_call(chain: list[str], call: str) -> bool: - return ( - sbc_skip_call(chain, call) - or pico_skip_call(chain, call) - or tud_skip_call(chain, call) - ) + for hook in hooks_skip_call: + if hook(chain, call): + return True + return False analyze( ci_fnames=arg_ci_fnames, - extra_nodes=pico_nodes + newlib_nodes + gcc_nodes, + extra_nodes=all_nodes, app_func_filters={ "Threads": thread_filter, "Interrupt handlers": intrhandler_filter, @@ -696,19 +735,19 @@ def main( if __name__ == "__main__": - base_dir = sys.argv[1] + pico_platform = sys.argv[1] + base_dir = sys.argv[2] + fnames = sys.argv[3:] re_suffix = re.compile(r"\.c\.o(bj)?$") - ci_fnames = [ - re_suffix.sub(".c.ci", fname) - for fname in sys.argv[2:] - if re_suffix.search(fname) + re_suffix.sub(".c.ci", fname) for fname in fnames if re_suffix.search(fname) ] - c_fnames = [fname for fname in sys.argv[2:] if fname.endswith(".c")] + c_fnames = [fname for fname in fnames if fname.endswith(".c")] main( + arg_pico_platform=pico_platform, arg_base_dir=base_dir, arg_ci_fnames=ci_fnames, arg_c_fnames=c_fnames, -- cgit v1.2.3-2-g168b