diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-12-10 14:46:21 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-12-10 14:46:21 -0700 |
commit | 37f062800c05badab4c8787e403f7935afff831f (patch) | |
tree | 24381745e0c90407da9ed6ebd80dec030423d510 /build-aux | |
parent | 20fffeabddb5754e1c26bb099229df4507265fda (diff) |
Start getting lib9p stack analysis dialed in
Diffstat (limited to 'build-aux')
-rwxr-xr-x | build-aux/stack.c.gen | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/build-aux/stack.c.gen b/build-aux/stack.c.gen index 7af8bc4..47696e1 100755 --- a/build-aux/stack.c.gen +++ b/build-aux/stack.c.gen @@ -362,6 +362,39 @@ def main( elif re_vtable_start.search(line): in_vtable = True + tmessage_handlers: set[str] | None = None + if any(fname.endswith("lib9p/srv.c") for fname in c_fnames): + srv_c = next(fname for fname in c_fnames if fname.endswith("lib9p/srv.c")) + re_tmessage_handler = re.compile( + r"^\s*\[LIB9P_TYP_T[^]]+\]\s*=\s*\(tmessage_handler\)\s*(?P<handler>\S+),\s*$" + ) + tmessage_handlers = set() + with open(srv_c, "r") as fh: + for line in fh: + line = line.rstrip() + if m := re_tmessage_handler.fullmatch(line): + tmessage_handlers.add(m.group("handler")) + + lib9p_versions: dict[str, set[str]] | None = None + if any(fname.endswith("lib9p/9p.c") for fname in c_fnames): + generated_c = next( + fname for fname in c_fnames if fname.endswith("lib9p/9p.generated.c") + ) + re_lib9p_msg_entry = re.compile(r"^\s*_MSG\((?P<typ>\S+)\),$") + lib9p_versions = { + "validate": set(), + "marshal": set(), + "unmarshal": set(), + } + with open(generated_c, "r") as fh: + for line in fh: + line = line.rstrip() + if m := re_lib9p_msg_entry.fullmatch(line): + typ = m.group("typ") + lib9p_versions["validate"].add(f"validate_{typ}") + lib9p_versions["unmarshal"].add(f"unmarshal_{typ}") + lib9p_versions["marshal"].add(f"marshal_{typ}") + re_call_vcall = re.compile(r"VCALL\((?P<obj>[^,]+), (?P<meth>[^,)]+)[,)].*") def sbc_indirect_callees(loc: str, line: str) -> list[str] | None: @@ -382,6 +415,12 @@ def main( "_cr_chan_dequeue", "_cr_select_dequeue", ] + if tmessage_handlers and "/srv.c:" in loc and "tmessage_handlers[typ](" in line: + return sorted(tmessage_handlers) + if lib9p_versions and "/9p.c:" in loc: + for meth in lib9p_versions.keys(): + if line.startswith(f"table.{meth}("): + return sorted(lib9p_versions[meth]) return None hooks_indirect_callees += [sbc_indirect_callees] @@ -407,6 +446,13 @@ def main( "w5500_intrhandler", ] + # 1=just root directory + # 2=just files in root directory + # 3=just 1 level of subdirectories + # 4=just 2 levels of subdirectories + # ... + sbc_9p_max_depth = 3 + def sbc_skip_call(chain: list[str], call: str) -> bool: if ( len(chain) > 1 @@ -415,6 +461,14 @@ def main( and any(c.endswith(":__assert_msg_fail") for c in chain[:-1]) ): return True + if ( + len(chain) >= sbc_9p_max_depth + and call.endswith("/srv.c:util_release") + and all( + c.endswith("/srv.c:util_release") for c in chain[-sbc_9p_max_depth:] + ) + ): + return True return False hooks_skip_call += [sbc_skip_call] @@ -673,9 +727,10 @@ def main( synthetic_node("memcmp", 0), # TODO synthetic_node("memcpy", 0), # TODO synthetic_node("memset", 0), # TODO + synthetic_node("strcmp", 0), # TODO synthetic_node("strlen", 0), # TODO - synthetic_node("strnlen", 0), # TODO synthetic_node("strncpy", 0), # TODO + synthetic_node("strnlen", 0), # TODO # other synthetic_node("random", 0), # TODO ] @@ -716,7 +771,11 @@ def main( if ret is not None: return ret - return [f"__indirect_call:" + location_xform(elem.attrs.get("label", ""))] + placeholder = "__indirect_call" + if m := re_call_other.fullmatch(line): + placeholder += ":" + m.group("func") + placeholder += " at " + location_xform(elem.attrs.get("label", "")) + return [placeholder] def skip_call(chain: list[str], call: str) -> bool: for hook in hooks_skip_call: |