diff options
| author | Gabriel Schneider <[email protected]> | 2026-02-06 14:51:17 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-02-06 14:51:17 -0300 |
| commit | 632a8daeb6377bdfde47cf83dcffd116d88e999a (patch) | |
| tree | 566f0da3f5495c95611bf18bdccee695e602e082 /src/elfo-pretty.zig | |
| parent | 19101e2358f00cc8c4bebb320181e05f96080564 (diff) | |
| download | codenomicon-632a8daeb6377bdfde47cf83dcffd116d88e999a.tar.gz codenomicon-632a8daeb6377bdfde47cf83dcffd116d88e999a.zip | |
updated to zig 0.16.0 and fixed memory leaks
Diffstat (limited to 'src/elfo-pretty.zig')
| -rw-r--r-- | src/elfo-pretty.zig | 164 |
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 |
