diff options
-rwxr-xr-x | build-aux/stack.c.gen | 63 | ||||
-rw-r--r-- | lib9p/srv.c | 6 | ||||
-rw-r--r-- | libhw_generic/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libhw_generic/include/libhw/generic/net.h | 2 | ||||
-rw-r--r-- | libhw_generic/net.c | 31 |
5 files changed, 98 insertions, 5 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: diff --git a/lib9p/srv.c b/lib9p/srv.c index 2fb2120..3535f9a 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -6,7 +6,6 @@ #include <alloca.h> #include <inttypes.h> /* for PRI* */ -#include <string.h> /* for strerror() */ #include <libcr/coroutine.h> #include <libcr_ipc/chan.h> @@ -14,6 +13,7 @@ #include <libcr_ipc/select.h> #include <libmisc/assert.h> #include <libmisc/vcall.h> +#include <libhw/generic/net.h> #define LOG_NAME 9P_SRV #include <libmisc/log.h> @@ -170,7 +170,7 @@ static void respond_error(struct _lib9p_srv_req *req) { req->net_bytes, decode_u32le(req->net_bytes)); cr_mutex_unlock(&sess->parent_conn->writelock); if (r < 0) - nonrespond_errorf("write: %s", strerror(-r)); + nonrespond_errorf("write: %s", net_strerror(-r)); } /* read coroutine *************************************************************/ @@ -182,7 +182,7 @@ static bool read_at_least(implements_net_stream_conn *fd, uint8_t *buf, size_t g while (*done < goal) { ssize_t r = VCALL(fd, read, &buf[*done], CONFIG_9P_MAX_MSG_SIZE - *done); if (r < 0) { - nonrespond_errorf("read: %s", strerror(-r)); + nonrespond_errorf("read: %s", net_strerror(-r)); return true; } else if (r == 0) { if (*done != 0) diff --git a/libhw_generic/CMakeLists.txt b/libhw_generic/CMakeLists.txt index 9c88937..0356770 100644 --- a/libhw_generic/CMakeLists.txt +++ b/libhw_generic/CMakeLists.txt @@ -12,4 +12,5 @@ target_link_libraries(libhw_generic INTERFACE target_sources(libhw_generic INTERFACE alarmclock.c + net.c ) diff --git a/libhw_generic/include/libhw/generic/net.h b/libhw_generic/include/libhw/generic/net.h index a016d51..0f9872e 100644 --- a/libhw_generic/include/libhw/generic/net.h +++ b/libhw_generic/include/libhw/generic/net.h @@ -23,6 +23,8 @@ #define NET_ECLOSED 6 #define NET_EMSGSIZE 7 +const char *net_strerror(int net_errno); + /* Address types **************************************************************/ struct net_ip4_addr { diff --git a/libhw_generic/net.c b/libhw_generic/net.c new file mode 100644 index 0000000..e2785ae --- /dev/null +++ b/libhw_generic/net.c @@ -0,0 +1,31 @@ +/* libhw_generic/net.c - Device-independent <libhw/generic/net.h> utilities + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/assert.h> + +#include <libhw/generic/net.h> + +#define NET_EOTHER 1 +#define NET_EARP_TIMEOUT 2 +#define NET_EACK_TIMEOUT 3 +#define NET_ERECV_TIMEOUT 4 +#define NET_ETHREAD 5 +#define NET_ECLOSED 6 +#define NET_EMSGSIZE 7 + +const char *net_strerror(int net_errno) { + switch (net_errno) { + case NET_EOTHER: return "unknown error"; + case NET_EARP_TIMEOUT: return "ARP timeout"; + case NET_EACK_TIMEOUT: return "TCP ACK timeout"; + case NET_ERECV_TIMEOUT: return "receive timeout"; + case NET_ETHREAD: return "thread error"; + case NET_ECLOSED: return "already closed"; + case NET_EMSGSIZE: return "message too long"; + default: + assert_notreached("invalid net_errno"); + } +} |