summaryrefslogtreecommitdiff
path: root/src/elfo-pretty.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/elfo-pretty.zig')
-rw-r--r--src/elfo-pretty.zig164
1 files changed, 96 insertions, 68 deletions
diff --git a/src/elfo-pretty.zig b/src/elfo-pretty.zig
index 798fd10..ea0b246 100644
--- a/src/elfo-pretty.zig
+++ b/src/elfo-pretty.zig
@@ -10,7 +10,7 @@ const SymbolRange = struct {
fn iterateSymbols(
h: std.elf.Header,
- file_reader: *std.fs.File.Reader,
+ file_reader: *std.Io.File.Reader,
symtab: std.elf.Elf64_Shdr,
) SymbolIterator {
return .{
@@ -22,7 +22,7 @@ fn iterateSymbols(
const SymbolIterator = struct {
elf_header: std.elf.Header,
- file_reader: *std.fs.File.Reader,
+ file_reader: *std.Io.File.Reader,
symtab: std.elf.Elf64_Shdr,
index: usize = 0,
@@ -40,21 +40,19 @@ const SymbolIterator = struct {
}
};
-pub fn main() !void {
- var args = std.process.args();
- _ = args.skip(); // skip argv[0]
+pub fn main(init: std.process.Init) !void {
+ // var args = init.environ_map.iterator();
+ // _ = args.next(); // skip argv[0]
- const bw = std.debug.lockStderrWriter(&.{});
- defer std.debug.unlockStderrWriter();
- const ttyconf = std.io.tty.detectConfig(.stderr());
+ var buffer: [64]u8 = undefined;
+ const stderr = try init.io.lockStderr(&buffer, .escape_codes);
- var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
- const allocator = gpa.allocator();
try printElf(
- allocator,
- args.next() orelse "./study-samples/split",
- bw,
- ttyconf,
+ init.gpa,
+ init.io,
+ // args.next() orelse "./study-samples/split",
+ "./study-samples/split",
+ stderr.terminal(),
.{
// .show_unaddressable_sections = true,
// .skip_sections_content = true,
@@ -63,19 +61,22 @@ pub fn main() !void {
}
pub fn printElf(
- allocator: std.mem.Allocator,
+ gpa: std.mem.Allocator,
+ io: std.Io,
path: []const u8,
- bw: *std.Io.Writer,
- ttyconf: std.io.tty.Config,
+ term: std.Io.Terminal,
options: struct {
show_unaddressable_sections: bool = false,
skip_sections_content: bool = false,
},
) !void {
- const f = try std.fs.cwd().openFile(path, .{ .mode = .read_only });
- var buffer = try allocator.alignedAlloc(u8, std.mem.Alignment.of(u64), 1024 * 100);
- // const buffer = try allocator.alloc(u8, 1024 * 10000000);
- var reader = f.reader(buffer);
+ const f = try std.Io.Dir.cwd().openFile(io, path, .{ .mode = .read_only });
+ const bw = term.writer;
+ defer bw.flush() catch {};
+ var buffer = try gpa.alignedAlloc(u8, std.mem.Alignment.of(u64), 1024 * 100);
+ defer gpa.free(buffer);
+
+ var reader = f.reader(io, buffer);
const header = try std.elf.Header.read(&reader.interface);
var handle: usize = undefined;
@@ -99,9 +100,13 @@ pub fn printElf(
break :blk null;
try reader.seekTo(shstrtab.?.sh_offset);
- const slice = try reader.interface.readAlloc(allocator, shstrtab.?.sh_size);
+ const slice = try reader.interface.readAlloc(gpa, shstrtab.?.sh_size);
break :blk slice;
};
+ defer {
+ if (elf_shstrtab_slice != null)
+ gpa.free(elf_shstrtab_slice.?);
+ }
const strtab = blk: {
if (elf_shstrtab_slice == null)
@@ -124,27 +129,38 @@ pub fn printElf(
break :blk null;
try reader.seekTo(strtab.?.sh_offset);
- const slice = try reader.interface.readAlloc(allocator, strtab.?.sh_size);
+ const slice = try reader.interface.readAlloc(gpa, strtab.?.sh_size);
break :blk slice;
};
- var strs: std.ArrayList([]const u8) = try .initCapacity(allocator, 8);
+ defer {
+ if (elf_strtab_slice != null)
+ gpa.free(elf_strtab_slice.?);
+ }
+
+ var strs: std.ArrayList([]const u8) = try .initCapacity(gpa, 8);
{
if (elf_shstrtab_slice != null) {
var str_it = std.mem.splitScalar(u8, elf_shstrtab_slice.?, 0);
while (str_it.next()) |str| {
- const owned_str = try allocator.alloc(u8, str.len);
+ const owned_str = try gpa.alloc(u8, str.len);
@memcpy(owned_str, str);
- try strs.append(allocator, owned_str);
+ try strs.append(gpa, owned_str);
}
}
}
+ defer {
+ for (strs.items) |s| {
+ gpa.free(s);
+ }
+ strs.deinit(gpa);
+ }
- var sections: std.ArrayList(std.elf.Elf64_Shdr) = try .initCapacity(allocator, 8);
+ var sections: std.ArrayList(std.elf.Elf64_Shdr) = try .initCapacity(gpa, 8);
{
var section_it = header.iterateSectionHeaders(&reader);
while (try section_it.next()) |section| {
- try sections.append(allocator, section);
+ try sections.append(gpa, section);
}
std.mem.sort(std.elf.Elf64_Shdr, sections.items, {}, struct {
pub fn inner(_: void, x: std.elf.Elf64_Shdr, y: std.elf.Elf64_Shdr) bool {
@@ -152,6 +168,7 @@ pub fn printElf(
}
}.inner);
}
+ defer sections.deinit(gpa);
const symtab = blk: {
var section_it = header.iterateSectionHeaders(&reader);
@@ -176,16 +193,16 @@ pub fn printElf(
};
try bw.print("dynsym: {any}\n", .{dynsym});
- const symbols_index = blk: {
- var syms: std.ArrayList(SymbolRange) = try .initCapacity(allocator, 8);
+ var symbols_index = blk: {
+ var syms: std.ArrayList(SymbolRange) = try .initCapacity(gpa, 8);
if (symtab != null) {
var sym_it = iterateSymbols(header, &reader, symtab.?);
while (try sym_it.next()) |s| {
const t = s.st_info & 0xf;
const name = std.mem.sliceTo(elf_strtab_slice.?[s.st_name..], 0);
- const owned_name = try allocator.alloc(u8, name.len);
+ const owned_name = try gpa.alloc(u8, name.len);
@memcpy(owned_name, name);
- try syms.append(allocator, .{
+ try syms.append(gpa, .{
.start = s.st_value,
.end = s.st_value + s.st_size,
.name = owned_name,
@@ -200,9 +217,9 @@ pub fn printElf(
while (try sym_it.next()) |s| {
const t = s.st_info & 0xf;
const name = std.mem.sliceTo(elf_strtab_slice.?[s.st_name..], 0);
- const owned_name = try allocator.alloc(u8, name.len);
+ const owned_name = try gpa.alloc(u8, name.len);
@memcpy(owned_name, name);
- try syms.append(allocator, .{
+ try syms.append(gpa, .{
.start = s.st_value,
.end = s.st_value + s.st_size,
.name = owned_name,
@@ -215,35 +232,41 @@ pub fn printElf(
return x.start < y.start;
}
}.inner);
- break :blk syms.items;
+ break :blk syms;
};
+ defer {
+ for (symbols_index.items) |sym| {
+ gpa.free(sym.name);
+ }
+ symbols_index.deinit(gpa);
+ }
- for (symbols_index) |sym| {
+ for (symbols_index.items) |sym| {
if (sym.kind == std.elf.STT_FUNC and sym.name.len > 0)
try bw.print("{s} {x}-{x}\n", .{ sym.name, sym.start, sym.end });
}
for (sections.items) |section| {
if (section.sh_size > 0 and section.sh_addr > 0) {
- try ttyconf.setColor(bw, .reset);
- try ttyconf.setColor(bw, .dim);
+ try term.setColor(.reset);
+ try term.setColor(.dim);
try bw.print("\n{x}-{x} (t: {x}) -- ", .{
section.sh_addr,
section.sh_addr + section.sh_size,
section.sh_type,
});
- try ttyconf.setColor(bw, .bright_green);
+ 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("\n", .{});
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
// --
try reader.seekTo(section.sh_offset);
if (buffer.len < section.sh_size) {
- buffer = try allocator.realloc(buffer, section.sh_size);
- reader = f.reader(buffer);
+ buffer = try gpa.realloc(buffer, section.sh_size);
+ reader = f.reader(io, buffer);
}
const section_slice = reader.interface.take(section.sh_size) catch |e| blk: {
switch (e) {
@@ -263,9 +286,9 @@ pub fn printElf(
break :blk insn[0..count];
};
- try dumpInstr(allocator, bw, ttyconf, instrs, symbols_index);
+ try dumpInstr(gpa, bw, term, instrs, symbols_index.items);
} else {
- try dumpHexFallible(u64, bw, ttyconf, section_slice.?, section.sh_addr);
+ try dumpHexFallible(u64, bw, term, section_slice.?, section.sh_addr);
}
}
}
@@ -274,25 +297,25 @@ pub fn printElf(
if (options.show_unaddressable_sections) {
for (sections.items) |section| {
if (section.sh_size > 0 and section.sh_addr == 0) {
- try ttyconf.setColor(bw, .reset);
- try ttyconf.setColor(bw, .dim);
+ try term.setColor(.reset);
+ try term.setColor(.dim);
try bw.print("{x}-{x} (t: {x}) -- ", .{
section.sh_addr,
section.sh_addr + section.sh_size,
section.sh_type,
});
- try ttyconf.setColor(bw, .bright_cyan);
+ try term.setColor(.bright_cyan);
if (elf_shstrtab_slice != null)
try bw.print("{s}", .{std.mem.sliceTo(elf_shstrtab_slice.?[section.sh_name..], 0)});
try bw.print("\n", .{});
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
// --
try reader.seekTo(section.sh_offset);
if (buffer.len < section.sh_size) {
- buffer = try allocator.realloc(buffer, section.sh_size);
- reader = f.reader(buffer);
+ buffer = try gpa.realloc(buffer, section.sh_size);
+ reader = f.reader(io, buffer);
}
const section_slice = reader.interface.take(section.sh_size) catch |e| blk: {
switch (e) {
@@ -303,7 +326,7 @@ pub fn printElf(
}
};
if (section_slice != null and !options.skip_sections_content) {
- try dumpHexFallible(u64, bw, ttyconf, section_slice.?, section.sh_addr);
+ try dumpHexFallible(u64, bw, term, section_slice.?, section.sh_addr);
}
}
}
@@ -348,7 +371,7 @@ fn allocComment(
fn dumpInstr(
gpa: std.mem.Allocator,
bw: *std.Io.Writer,
- ttyconf: std.io.tty.Config,
+ term: std.Io.Terminal,
instrs: []cs.cs_insn,
symbols: []SymbolRange,
) !void {
@@ -361,44 +384,54 @@ fn dumpInstr(
}.inner);
if (idx < symbols.len and symbols[idx].start == addr and symbols[idx].name.len > 0) {
- try ttyconf.setColor(bw, .blue);
+ try term.setColor(.blue);
try bw.print("\n{x:0>16} {s}:\n", .{
addr,
symbols[idx].name,
});
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
}
- try ttyconf.setColor(bw, .dim);
+ try term.setColor(.dim);
try bw.print("{x:0>[1]} ", .{ addr, @sizeOf(usize) * 2 });
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
// if(instr.detail.)
- try ttyconf.setColor(bw, .bright_green);
+ try term.setColor(.bright_green);
try bw.print("{s} ", .{instr.mnemonic});
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
try bw.print("{s}", .{instr.op_str});
const asm_comment = try allocComment(gpa, @ptrCast(@constCast(&instr.op_str)), symbols);
+ defer {
+ if (asm_comment != null)
+ gpa.free(asm_comment.?);
+ }
if (asm_comment != null and asm_comment.?.len > 0) {
- try ttyconf.setColor(bw, .blue);
+ try term.setColor(.blue);
try bw.print(" <{s}>", .{asm_comment.?});
}
try bw.print("\n", .{});
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
}
}
/// Prints a hexadecimal view of the bytes, returning any error that occurs.
-pub fn dumpHexFallible(_: type, bw: *std.Io.Writer, ttyconf: std.io.tty.Config, bytes: []const u8, offset: u64) !void {
+pub fn dumpHexFallible(
+ _: type,
+ bw: *std.Io.Writer,
+ term: std.Io.Terminal,
+ bytes: []const u8,
+ offset: u64,
+) !void {
// @breakpoint();
const nbytes = 16;
var chunks = std.mem.window(u8, @ptrCast(@alignCast(bytes)), nbytes, nbytes);
while (chunks.next()) |window| {
// 1. Print the address.
const address = ((0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, nbytes) catch unreachable)) - 0x10) + offset;
- try ttyconf.setColor(bw, .dim);
+ try term.setColor(.dim);
// We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more.
// Also, make sure all lines are aligned by padding the address.
try bw.print("{x:0>[1]} ", .{ address, @sizeOf(usize) * 2 });
- try ttyconf.setColor(bw, .reset);
+ try term.setColor(.reset);
// 2. Print the bytes.
for (window, 0..) |byte, index| {
@@ -419,11 +452,6 @@ pub fn dumpHexFallible(_: type, bw: *std.Io.Writer, ttyconf: std.io.tty.Config,
if (std.ascii.isPrint(byte)) {
try bw.writeByte(byte);
} else {
- // Related: https://github.com/ziglang/zig/issues/7600
- if (ttyconf == .windows_api) {
- try bw.writeByte('.');
- continue;
- }
// Let's print some common control codes as graphical Unicode symbols.
// We don't want to do this for all control codes because most control codes apart from