diff --git a/lib/compiler/objdump.zig b/lib/compiler/objdump.zig new file mode 100644 index 0000000000000000000000000000000000000000..d2af9c09c6e6e344794d0aaaa26f45efc2ce5d4c --- /dev/null +++ b/lib/compiler/objdump.zig @@ -0,0 +1,93 @@ +const std = @import("std"); +const Io = std.Io; +const fatal = std.process.fatal; +const mem = std.mem; +const assert = std.debug.assert; + +var stdout_buffer: [4000]u8 = undefined; + +pub fn main(init: std.process.Init) !void { + const io = init.io; + const args = try init.minimal.args.toSlice(init.arena.allocator()); + + var opt_input_path: ?[]const u8 = null; + var i: usize = 1; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { + return Io.File.stdout().writeStreamingAll(io, usage); + } else { + fatal("unrecognized argument: {s}", .{arg}); + } + } else if (opt_input_path == null) { + opt_input_path = arg; + } else { + fatal("unexpected positional: {s}", .{arg}); + } + } + + const input_path = opt_input_path orelse fatal("missing input file path positional argument", .{}); + + var file = std.Io.Dir.cwd().openFile(io, input_path, .{}) catch |err| + fatal("failed to open {s}: {t}", .{ input_path, err }); + defer file.close(io); + + var buffer: [4000]u8 = undefined; + var file_reader = file.reader(io, &buffer); + var stdout_writer = std.Io.File.stdout().writerStreaming(io, &stdout_buffer); + dump(&file_reader.interface, &stdout_writer.interface) catch |err| switch (err) { + error.ReadFailed => return file_reader.err.?, + error.WriteFailed => return stdout_writer.err.?, + error.UnknownFile => fatal("unrecognized file: {s}", .{input_path}), + else => |e| return e, + }; + try stdout_writer.flush(); +} + +fn dump(r: *Io.Reader, w: *Io.Writer) !void { + try r.fill(4); + elf: { + if (!mem.eql(u8, r.buffered()[0..4], std.elf.MAGIC)) break :elf; + return elf.dump(r, w); + } + macho: { + if (mem.readInt(u32, r.buffered()[0..4], .little) != std.macho.MH_MAGIC_64) break :macho; + return macho.dump(r, w); + } + wasm: { + comptime assert(std.wasm.magic.len == 4); + if (!mem.eql(u8, r.buffered()[0..4], &std.wasm.magic)) break :wasm; + return wasm.dump(r, w); + } + return error.UnknownFile; +} + +const elf = struct { + fn dump(r: *Io.Reader, w: *Io.Writer) !void { + _ = r; + try w.writeAll("TODO dump elf file\n"); + } +}; + +const macho = struct { + fn dump(r: *Io.Reader, w: *Io.Writer) !void { + _ = r; + try w.writeAll("TODO dump macho file\n"); + } +}; + +const wasm = struct { + fn dump(r: *Io.Reader, w: *Io.Writer) !void { + _ = r; + try w.writeAll("TODO dump wasm file\n"); + } +}; + +const usage = + \\Usage: zig objdump [options] file + \\ + \\Options: + \\ -h, --help Print this help and exit + \\ +; diff --git a/src/main.zig b/src/main.zig index 0ba118025462ef94db94e5d7bca4ebd148a7aad3..0395a21a5ff5aaa04ba4d1cb43bc629ec6e8c0e2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -95,13 +95,14 @@ const normal_usage = \\ reduce Minimize a bug report \\ translate-c Convert C code to Zig code \\ - \\ ar Use Zig as a drop-in archiver + \\ ar Combine object files into static archive \\ cc Use Zig as a drop-in C compiler \\ c++ Use Zig as a drop-in C++ compiler \\ dlltool Use Zig as a drop-in dlltool.exe \\ lib Use Zig as a drop-in lib.exe + \\ objcopy Manipulate executables and relocatables + \\ objdump Print information about executables and relocatables \\ ranlib Use Zig as a drop-in ranlib - \\ objcopy Use Zig as a drop-in objcopy \\ rc Use Zig as a drop-in rc.exe \\ \\ env Print lib path, std path, cache directory, and version @@ -342,6 +343,11 @@ fn mainArgs( .cmd_name = "objcopy", .root_src_path = "objcopy.zig", }); + } else if (mem.eql(u8, cmd, "objdump")) { + return jitCmd(gpa, arena, io, cmd_args, environ_map, .{ + .cmd_name = "objdump", + .root_src_path = "objdump.zig", + }); } else if (mem.eql(u8, cmd, "fetch")) { return cmdFetch(gpa, arena, io, cmd_args, environ_map); } else if (mem.eql(u8, cmd, "libc")) {