From 80ba1db819a80e784a488d6d660a890e14b19282 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Thu, 5 Mar 2026 13:00:01 -0300 Subject: simple shock --- src/elfo.zig | 56 +++++++++++++++++++++++++++++--------------------------- src/hooks.zig | 32 +------------------------------- src/shock.zig | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 58 deletions(-) create mode 100644 src/shock.zig (limited to 'src') diff --git a/src/elfo.zig b/src/elfo.zig index 5e0d780..264ba4d 100644 --- a/src/elfo.zig +++ b/src/elfo.zig @@ -1,7 +1,7 @@ const std = @import("std"); const cs = @import("capstone"); const hooks = @import("hooks.zig"); -const meta_opts = @import("meta"); +const meta = @import("meta"); pub fn main(init: std.process.Init.Minimal) !void { var debug_alloc: std.heap.DebugAllocator(.{}) = .init; @@ -21,21 +21,22 @@ pub fn main(init: std.process.Init.Minimal) !void { var buffer: [64]u8 = undefined; const stderr = try io.lockStderr(&buffer, .escape_codes); - const hook = hooks.init( - if (meta_opts.gdb) .breakpoint else .none, - // TODO: this needs to be comptime, it'd be cool to don't need that - std.heap.page_allocator, - false, - ); - - const mem_config: cs.cs_opt_mem = .{ - .malloc = @ptrCast(&hook.malloc), - .free = @ptrCast(&hook.free), - .calloc = @ptrCast(&hook.calloc), - .realloc = @ptrCast(&hook.realloc), - .vsnprintf = @ptrCast(&hook.vsnprintf), - }; - std.debug.assert(cs.cs_option(0, cs.CS_OPT_MEM, @intFromPtr(&mem_config)) == cs.CS_ERR_OK); + // const hook = hooks.init( + // if (meta.gdb) .breakpoint else .none, + // // TODO: this needs to be comptime, it'd be cool to don't need that + // std.heap.page_allocator, + // false, + // ); + + // const mem_config: cs.cs_opt_mem = .{ + // .malloc = @ptrCast(&hook.malloc), + // .free = @ptrCast(&hook.free), + // .calloc = @ptrCast(&hook.calloc), + // .realloc = @ptrCast(&hook.realloc), + // // TODO: this function needs to be properly implemented. + // .vsnprintf = @ptrCast(&hook.vsnprintf), + // }; + // std.debug.assert(cs.cs_option(0, cs.CS_OPT_MEM, @intFromPtr(&mem_config)) == cs.CS_ERR_OK); try printElf( alloc, @@ -43,8 +44,8 @@ pub fn main(init: std.process.Init.Minimal) !void { args.next() orelse "./study-samples/split", stderr.terminal(), .{ - .show_unaddressable_sections = true, - .skip_sections_content = true, + // .show_unaddressable_sections = true, + // .skip_sections_content = true, }, ); } @@ -73,7 +74,7 @@ pub fn printElf( const opts: struct { arch: u64, mode: u64 } = switch (header.machine) { .X86_64 => .{ .arch = cs.CS_ARCH_X86, .mode = cs.CS_MODE_64 }, // The arm mode isn't working with symbols on the .text section correctly - .ARM => .{ .arch = cs.CS_ARCH_ARM, .mode = cs.CS_MODE_ARM }, + .ARM => .{ .arch = cs.CS_ARCH_ARM, .mode = if (header.is_64) cs.CS_MODE_64 else cs.CS_MODE_32 }, else => { std.debug.print("found machine: {any}\n", .{header.machine}); @panic("unhandled arch"); @@ -258,10 +259,11 @@ pub fn printElf( section.sh_addr + section.sh_size, section.sh_type, }); + try term.setColor(.bright_green); if (elf_shstrtab_slice != null) try bw.print("{s}", .{std.mem.sliceTo(elf_shstrtab_slice.?[section.sh_name..], 0)}); - try bw.print("", .{}); + try bw.print("\n", .{}); try term.setColor(.reset); // -- @@ -292,9 +294,9 @@ pub fn printElf( break :blk insn[0..count]; }; - try dumpInstr(gpa, bw, term, instrs, symbols_index.items); + try printDisassembly(gpa, bw, term, instrs, symbols_index.items); } else { - try dumpHexFallible(u64, bw, term, section_slice.?, section.sh_addr); + try printHexdump(u64, bw, term, section_slice.?, section.sh_addr); } } } @@ -332,7 +334,7 @@ pub fn printElf( } }; if (section_slice != null and !options.skip_sections_content) { - try dumpHexFallible(u64, bw, term, section_slice.?, section.sh_addr); + try printHexdump(u64, bw, term, section_slice.?, section.sh_addr); } } } @@ -375,7 +377,7 @@ fn allocComment( return null; } -fn dumpInstr( +fn printDisassembly( gpa: std.mem.Allocator, bw: *std.Io.Writer, term: std.Io.Terminal, @@ -407,8 +409,8 @@ fn dumpInstr( try term.setColor(.reset); const mnemonic_strlen: u64 = @intCast(std.mem.find(u8, &instr.mnemonic, &.{0}).?); - const mnemonic_pad: u64 = 10; - for (0..(mnemonic_pad - mnemonic_strlen)) |_| { + const mnemonic_pad: u64 = 5; + for (0..(if (mnemonic_pad >= mnemonic_strlen) mnemonic_pad - mnemonic_strlen else 0)) |_| { try bw.printAsciiChar(' ', .{}); } try bw.print("{s}", .{instr.op_str}); @@ -427,7 +429,7 @@ fn dumpInstr( } /// Prints a hexadecimal view of the bytes, returning any error that occurs. -pub fn dumpHexFallible( +pub fn printHexdump( _: type, bw: *std.Io.Writer, term: std.Io.Terminal, diff --git a/src/hooks.zig b/src/hooks.zig index 549d871..2fda734 100644 --- a/src/hooks.zig +++ b/src/hooks.zig @@ -7,35 +7,6 @@ pub const Kind = enum { const Self = @This(); pub const Hook = @This(); -// pub fn init(comptime kind: Kind, comptime alloc: std.mem.Allocator) type { -// return struct { -// alloc: std.mem.Allocator = alloc, - -// pub fn malloc(size: usize) callconv(.c) ?*anyopaque { -// if (kind == .breakpoint) @breakpoint(); -// return std.c.malloc(size); -// } - -// pub fn calloc(n: usize, size: usize) callconv(.c) ?*anyopaque { -// if (kind == .breakpoint) @breakpoint(); -// return std.c.calloc(n, size); -// } -// pub fn realloc(ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque { -// if (kind == .breakpoint) @breakpoint(); -// return std.c.realloc(ptr, size); -// } -// pub fn free(ptr: ?*anyopaque) callconv(.c) void { -// if (kind == .breakpoint) @breakpoint(); -// return std.c.free(ptr); -// } -// pub fn vsnprintf(_: [*c]u8, _: usize, _: [*c]const u8, _: [*c]u8) callconv(.c) ?*anyopaque { -// if (kind == .breakpoint) @breakpoint(); -// return null; -// } -// }; -// } -// - pub fn init(comptime kind: Kind, comptime alloc: std.mem.Allocator, comptime uselibc: bool) type { return struct { alloc: std.mem.Allocator = alloc, @@ -108,8 +79,7 @@ pub fn init(comptime kind: Kind, comptime alloc: std.mem.Allocator, comptime use } pub fn vsnprintf(_: [*c]u8, _: usize, _: [*c]const u8, _: [*c]u8) callconv(.c) ?*anyopaque { - if (kind == .breakpoint) @breakpoint(); - return null; + @compileError("Unimplemented!"); } }; } diff --git a/src/shock.zig b/src/shock.zig new file mode 100644 index 0000000..262b176 --- /dev/null +++ b/src/shock.zig @@ -0,0 +1,45 @@ +const std = @import("std"); + +pub fn main(init: std.process.Init.Minimal) !void { + var args = init.args.iterate(); + _ = args.skip(); + const subject = args.next() orelse "./study-samples/frog"; + + std.debug.print("arg: {s}\n", .{subject}); + + var debug_alloc: std.heap.DebugAllocator(.{}) = .init; + const alloc = debug_alloc.allocator(); + + // var threaded: std.Io.Threaded = .init(alloc, .{ + // .argv0 = .init(init.args), + // .environ = init.environ, + // }); + // defer threaded.deinit(); + // const io = threaded.io(); + + var evented: std.Io.Evented = undefined; + try evented.init(alloc, .{ + .argv0 = .init(init.args), + .environ = init.environ, + .backing_allocator_needs_mutex = false, + }); + defer evented.deinit(); + const io = evented.io(); + + // const f = try std.Io.Dir.cwd().openFile(io, subject, .{ .mode = .read_only }); + // std.debug.print("file: {any}\n", .{f}); + var child = try std.process.spawn(io, .{ + .argv = &.{subject}, + .stdout = .pipe, + .stdin = .inherit, + }); + + const buf = try alloc.alloc(u8, 0x400); + defer alloc.free(buf); + _ = try child.stdout.?.readPositionalAll(io, buf, 0); + + std.debug.print("spawned child: {any}\n", .{child}); + + const term = try child.wait(io); + std.debug.print("waited term: {any}\n", .{term}); +} -- cgit v1.3