summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild-aux/stack.c.gen63
-rw-r--r--lib9p/srv.c6
-rw-r--r--libhw_generic/CMakeLists.txt1
-rw-r--r--libhw_generic/include/libhw/generic/net.h2
-rw-r--r--libhw_generic/net.c31
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");
+ }
+}