Commit Diff


commit - e24fa9f6d4fd3018196358ea4be202b60f9c6a88
commit + 9cb5624e66351c704ec986b94d38389a923eafdf
blob - ad3b92558169ad5a4f69fdba5a972d750e48c16f
blob + 4c921f64a2976a7a459f2cb885b1080547dda6ff
--- src/data.dst
+++ src/data.dst
@@ -26,3 +26,8 @@ struct elf64_phdr {
 	memsz: u64,
 	aign: u64,
 };
+
+struct linux_iovec {
+	base: u64,
+	len: u64,
+};
blob - 5ce02ee3ef69ce0d1b9549ae62ac662c1fd8bbd2
blob + ebb28a6be67eeb7b23209862c78f9fd75a3a20c9
--- src/ecall.c
+++ src/ecall.c
@@ -480,13 +480,32 @@ void ecall (void)
 		dbg ("write(%d, %p, %zu)", i0, ptr (const void, a1), (size_t)a2);
 		break;
 	case SYS_readv:
-		ret = map (readv (i0, ptr (const struct iovec, a1), i2));
-		dbg ("readv(%d, %p, %d)", i0, ptr (const struct iovec, a1), i2);
-		break;
 	case SYS_writev:
-		ret = map (writev (i0, ptr (const struct iovec, a1), i2));
-		dbg ("writev(%d, %p, %d)", i0, ptr (const struct iovec, a1), i2);
+	{
+		const uint8_t *piv = ptr (const uint8_t, a1);
+		struct linux_iovec liv;
+		struct iovec *iov;
+		size_t num = i2;
+
+		iov = calloc (num, sizeof (*iov));
+
+		for (size_t i = 0; i < num; ++i) {
+			decode_linux_iovec (&liv, piv + i * sizeof (liv));
+			iov[i].iov_base = (void *)liv.base;
+			iov[i].iov_len = (size_t)liv.len;
+		}
+
+		if (a7 == SYS_readv) {
+			ret = map (readv (i0, iov, num));
+			dbg ("readv(%d, %p, %zu)", i0, piv, num);
+		} else {
+			ret = map (writev (i0, iov, i2));
+			dbg ("writev(%d, %p, %d)", i0, piv, i2);
+		}
+
+		free (iov);
 		break;
+	}
 	case SYS_pread:
 		ret = map (pread (i0, ptr (void, a1), (size_t)a2, (off_t)a3));
 		dbg ("pread(%d, %p, %zu, %llu)", i0, ptr (void, a1), (size_t)a2, (unsigned long long)a3);