about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNguyễn Gia Phong <cnx@loang.net>2025-10-16 13:59:15 +0900
committerNguyễn Gia Phong <cnx@loang.net>2025-10-16 13:59:15 +0900
commit5d452d311477e171b78db16ba7860f3f5afe2c9a (patch)
tree7db9d05b2c6002a7a7651a9db1f2cccb61b65913
parent35059bc54f443ae105e3b66d719d18e2b1e879b8 (diff)
downloadtaosc-5d452d311477e171b78db16ba7860f3f5afe2c9a.tar.gz
Implement decoder for collected values
-rw-r--r--Makefile6
-rw-r--r--README.md11
-rw-r--r--collect.c34
-rw-r--r--synth.zig49
4 files changed, 80 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index a9994cf..3b1e5f5 100644
--- a/Makefile
+++ b/Makefile
@@ -25,12 +25,12 @@ measure-stack: measure-stack.o helpers.o
 scout: scout.o helpers.o
 	$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
-synth: synth.py
-	link $< $@
-
 trace-call: trace-call.o helpers.o
 	$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
+%: %.zig
+	zig build-exe -O ReleaseSafe $<
+
 %: %.c
 	e9compile $<
 
diff --git a/README.md b/README.md
index 260cad8..b1d40e9 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,8 @@ Taosc is an automated makeshift patcher for binary programs.
 
 ## Installation
 
-Taosc depends on [AFL++], [AFL Dyninst], [Dyninst], [E9Patch], [PatchELF]
-[pacfix-python], and [GNU Parallel].  To build taosc, you need
-`make(1p)`, a compiler for C and C++, [GNU M4], and `link(1p)`:
+Taosc depends on GDB, [Dyninst] and [E9Patch] and POSIX utilities.
+To build taosc, you need [GNU M4] and a compiler for C++23 and [Zig] 0.15:
 
     make -j$(nproc)
 
@@ -25,11 +24,7 @@ under the terms of the GNU Affero General Public License as published
 by the Free Software Foundation, either version 3 of the License,
 or (at your option) any later version.
 
-[AFL++]: https://aflplus.plus
-[AFL Dyninst]: https://trong.loang.net/~cnx/afl-dyninst
 [Dyninst]: https://github.com/dyninst/dyninst
 [E9Patch]: https://github.com/gjduck/e9patch
-[PatchELF]: https://github.com/NixOS/patchelf
-[pacfix-python]: https://github.com/hsh814/pacfix-python
-[GNU Parallel]: https://www.gnu.org/software/parallel
 [GNU M4]: https://www.gnu.org/software/m4
+[Zig]: https://ziglang.org
diff --git a/collect.c b/collect.c
index cf32283..a092555 100644
--- a/collect.c
+++ b/collect.c
@@ -20,39 +20,55 @@
 
 #include "stdlib.c"
 
-static uint64_t stack_size;
+static uint32_t stack_size;
 static int output_file = -1;
 
 /*
  * Get an environment variable and parse as a number.
  * Return 0 on error.
  */
-uint64_t getenvull(const char *name)
+uint32_t getenvul(const char *name)
 {
-	const char *const s = getenv(name);
-	if (s == NULL)
+	const char *const str = getenv(name);
+	if (str == NULL)
 		return 0ULL;
 	errno = 0;
-	const uint64_t u = strtoull(s, NULL, 0);
+	const uint32_t ul = strtoul(str, NULL, 0);
 	if (errno)
 		return 0ULL;
-	return u;
+	return ul;
 }
 
 void init(int argc, const char *const *argv, char **envp)
 {
 	environ = envp;
-	stack_size = getenvull("TAOSC_STACK_SIZE");
+	stack_size = getenvul("TAOSC_STACK_SIZE");
 	const char *const path = getenv("TAOSC_OUTPUT");
 	if (path != NULL)
 		output_file = open(path, O_WRONLY | O_CREAT, 0644);
-	if (output_file == -1)
-		output_file = 2; /* stderr */
+	if (output_file == -1) {
+		const char *msg = "cannot open $TAOSC_OUTPUT for writing\n";
+		write(2, msg, strlen(msg));
+		fsync(2);
+		exit(128);
+	}
 }
 
 void log(const struct STATE *state)
 {
+
+	static mutex_t mutex = MUTEX_INITIALIZER;
+	while (mutex_lock(&mutex) < 0);
 	write(output_file, (const char *)state, sizeof(struct STATE));
+	/*
+	 * struct STATE starts with a 16-bit member flags,
+	 * followed by 64-bit registers, leaving 6 bytes in between.
+	 */
+	const int offset = (int) sizeof(uint32_t) - (int) sizeof(struct STATE);
+	lseek(output_file, offset, SEEK_END);
+	write(output_file, (const char *)&stack_size, sizeof(uint32_t));
+	lseek(output_file, 0, SEEK_END);
 	write(output_file, (const char *)state->rsp, stack_size);
 	fsync(output_file);
+	mutex_unlock(&mutex);
 }
diff --git a/synth.zig b/synth.zig
new file mode 100644
index 0000000..2914b6c
--- /dev/null
+++ b/synth.zig
@@ -0,0 +1,49 @@
+//! Patch's predicate synthesizer
+// Copyright (C) 2025  Nguyễn Gia Phong
+//
+// This file is part of taosc.
+//
+// Taosc is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Taosc is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with taosc.  If not, see <https://www.gnu.org/licenses/>.
+
+const assert = std.debug.assert;
+const std = @import("std");
+
+const State = extern struct {
+    flags: u16,
+    stack_size: u32,
+    r15: i64,
+    r14: i64,
+    r13: i64,
+    r12: i64,
+    r11: i64,
+    r10: i64,
+    r9: i64,
+    r8: i64,
+    rdi: i64,
+    rsi: i64,
+    rbp: i64,
+    rbx: i64,
+    rdx: i64,
+    rcx: i64,
+    rax: i64,
+    rsp: i64,
+    rip: i64,
+};
+
+pub fn main() !void {
+    var reader = std.fs.File.stdin().reader(&.{});
+    var state: State = undefined;
+    assert(try reader.read(@ptrCast(&state)) == @sizeOf(State));
+    std.debug.print("{}\n", .{ state });
+}