summaryrefslogtreecommitdiff
path: root/build-aux
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-12-10 14:46:21 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-12-10 14:46:21 -0700
commit37f062800c05badab4c8787e403f7935afff831f (patch)
tree24381745e0c90407da9ed6ebd80dec030423d510 /build-aux
parent20fffeabddb5754e1c26bb099229df4507265fda (diff)
Start getting lib9p stack analysis dialed in
Diffstat (limited to 'build-aux')
-rwxr-xr-xbuild-aux/stack.c.gen63
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: