1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
//! 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 Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const Dir = std.fs.Dir;
const File = std.fs.File;
const Reader = std.Io.Reader;
const argsAlloc = std.process.argsAlloc;
const argsFree = std.process.argsFree;
const assert = std.debug.assert;
const cwd = std.fs.cwd;
const exit = std.process.exit;
const page_allocator = std.heap.page_allocator;
const parseUnsigned = std.fmt.parseUnsigned;
const print = std.debug.print;
const std = @import("std");
const State = extern struct {
flags: u16,
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: u64, // internal use only
rip: i64,
};
fn countFiles(dir: Dir) Dir.Iterator.Error!usize {
var count: usize = 0;
var entries = dir.iterate();
while (try entries.next()) |entry| {
assert(entry.kind == .file);
count += 1;
}
return count;
}
const ReadError = Dir.Iterator.Error || File.OpenError || Reader.Error;
const Data = struct {
states: []const State,
memory: []const u8,
fn init(allocator: Allocator, dir: Dir,
stack_len: u64) (Allocator.Error || ReadError)!Data {
const count = try countFiles(dir);
const states = try allocator.alloc(State, count);
const memory = try allocator.alloc(u8, stack_len * count);
var entries = dir.iterate();
var sp: u64 = 0;
for (states) |*state| {
const entry = try entries.next();
const file = try dir.openFile(entry.?.name, .{});
defer file.close();
var buffer: [4096]u8 = undefined;
var reader = file.reader(&buffer);
assert(try reader.read(@ptrCast(state)) == @sizeOf(State));
state.rsp = sp;
assert(try reader.read(memory[sp..][0..stack_len]) == stack_len);
sp += stack_len;
print("{}\n", .{ state });
}
return .{ .states = states, .memory = memory };
}
fn deinit(data: Data, allocator: Allocator) void {
allocator.free(data.states);
allocator.free(data.memory);
}
};
pub fn main() !void {
var arena = ArenaAllocator.init(page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
const args = try argsAlloc(allocator);
defer argsFree(allocator, args);
if (args.len != 4) {
print("Usage: taosc-synth OFF-DIR ON-DIR STACK-SIZE", .{});
exit(1);
}
var off_dir = try cwd().openDir(args[1], .{ .iterate = true });
defer off_dir.close();
var on_dir = try cwd().openDir(args[2], .{ .iterate = true });
defer on_dir.close();
const stack_len = try parseUnsigned(u64, args[3], 0);
const off_data = try Data.init(allocator, off_dir, stack_len);
defer off_data.deinit(allocator);
const on_data = try Data.init(allocator, on_dir, stack_len);
defer on_data.deinit(allocator);
}
|