diff options
Diffstat (limited to 'lib/std/debug.zig')
| -rw-r--r-- | lib/std/debug.zig | 233 |
1 files changed, 128 insertions, 105 deletions
diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 558b7e0513..5c56490519 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -55,7 +55,7 @@ pub const LineInfo = struct { var stderr_file: File = undefined; var stderr_file_out_stream: File.OutStream = undefined; -var stderr_stream: ?*io.OutStream(File.WriteError) = null; +var stderr_stream: ?*File.OutStream = null; var stderr_mutex = std.Mutex.init(); pub fn warn(comptime fmt: []const u8, args: var) void { @@ -65,13 +65,13 @@ pub fn warn(comptime fmt: []const u8, args: var) void { noasync stderr.print(fmt, args) catch return; } -pub fn getStderrStream() *io.OutStream(File.WriteError) { +pub fn getStderrStream() *File.OutStream { if (stderr_stream) |st| { return st; } else { stderr_file = io.getStdErr(); stderr_file_out_stream = stderr_file.outStream(); - const st = &stderr_file_out_stream.stream; + const st = &stderr_file_out_stream; stderr_stream = st; return st; } @@ -408,15 +408,15 @@ pub const TTY = struct { windows_api, fn setColor(conf: Config, out_stream: var, color: Color) void { - switch (conf) { + noasync switch (conf) { .no_color => return, .escape_codes => switch (color) { - .Red => noasync out_stream.write(RED) catch return, - .Green => noasync out_stream.write(GREEN) catch return, - .Cyan => noasync out_stream.write(CYAN) catch return, - .White, .Bold => noasync out_stream.write(WHITE) catch return, - .Dim => noasync out_stream.write(DIM) catch return, - .Reset => noasync out_stream.write(RESET) catch return, + .Red => out_stream.writeAll(RED) catch return, + .Green => out_stream.writeAll(GREEN) catch return, + .Cyan => out_stream.writeAll(CYAN) catch return, + .White, .Bold => out_stream.writeAll(WHITE) catch return, + .Dim => out_stream.writeAll(DIM) catch return, + .Reset => out_stream.writeAll(RESET) catch return, }, .windows_api => if (builtin.os.tag == .windows) { const S = struct { @@ -455,7 +455,7 @@ pub const TTY = struct { } else { unreachable; }, - } + }; } }; }; @@ -565,38 +565,40 @@ fn printLineInfo( tty_config: TTY.Config, comptime printLineFromFile: var, ) !void { - tty_config.setColor(out_stream, .White); + noasync { + tty_config.setColor(out_stream, .White); - if (line_info) |*li| { - try noasync out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column }); - } else { - try noasync out_stream.write("???:?:?"); - } + if (line_info) |*li| { + try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column }); + } else { + try out_stream.writeAll("???:?:?"); + } - tty_config.setColor(out_stream, .Reset); - try noasync out_stream.write(": "); - tty_config.setColor(out_stream, .Dim); - try noasync out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name }); - tty_config.setColor(out_stream, .Reset); - try noasync out_stream.write("\n"); - - // Show the matching source code line if possible - if (line_info) |li| { - if (noasync printLineFromFile(out_stream, li)) { - if (li.column > 0) { - // The caret already takes one char - const space_needed = @intCast(usize, li.column - 1); - - try noasync out_stream.writeByteNTimes(' ', space_needed); - tty_config.setColor(out_stream, .Green); - try noasync out_stream.write("^"); - tty_config.setColor(out_stream, .Reset); + tty_config.setColor(out_stream, .Reset); + try out_stream.writeAll(": "); + tty_config.setColor(out_stream, .Dim); + try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name }); + tty_config.setColor(out_stream, .Reset); + try out_stream.writeAll("\n"); + + // Show the matching source code line if possible + if (line_info) |li| { + if (printLineFromFile(out_stream, li)) { + if (li.column > 0) { + // The caret already takes one char + const space_needed = @intCast(usize, li.column - 1); + + try out_stream.writeByteNTimes(' ', space_needed); + tty_config.setColor(out_stream, .Green); + try out_stream.writeAll("^"); + tty_config.setColor(out_stream, .Reset); + } + try out_stream.writeAll("\n"); + } else |err| switch (err) { + error.EndOfFile, error.FileNotFound => {}, + error.BadPathName => {}, + else => return err, } - try noasync out_stream.write("\n"); - } else |err| switch (err) { - error.EndOfFile, error.FileNotFound => {}, - error.BadPathName => {}, - else => return err, } } } @@ -609,21 +611,21 @@ pub const OpenSelfDebugInfoError = error{ }; /// TODO resources https://github.com/ziglang/zig/issues/4353 -/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented, -/// make this `noasync fn` and remove the individual noasync calls. pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo { - if (builtin.strip_debug_info) - return error.MissingDebugInfo; - if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) { - return noasync root.os.debug.openSelfDebugInfo(allocator); - } - switch (builtin.os.tag) { - .linux, - .freebsd, - .macosx, - .windows, - => return DebugInfo.init(allocator), - else => @compileError("openSelfDebugInfo unsupported for this platform"), + noasync { + if (builtin.strip_debug_info) + return error.MissingDebugInfo; + if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) { + return root.os.debug.openSelfDebugInfo(allocator); + } + switch (builtin.os.tag) { + .linux, + .freebsd, + .macosx, + .windows, + => return DebugInfo.init(allocator), + else => @compileError("openSelfDebugInfo unsupported for this platform"), + } } } @@ -808,45 +810,64 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 { /// TODO resources https://github.com/ziglang/zig/issues/4353 pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo { - const mapped_mem = try mapWholeFile(elf_file_path); - - var seekable_stream = io.SliceSeekableInStream.init(mapped_mem); - var efile = try noasync elf.Elf.openStream( - allocator, - @ptrCast(*DW.DwarfSeekableStream, &seekable_stream.seekable_stream), - @ptrCast(*DW.DwarfInStream, &seekable_stream.stream), - ); - defer noasync efile.close(); + noasync { + const mapped_mem = try mapWholeFile(elf_file_path); + const hdr = @ptrCast(*const elf.Ehdr, &mapped_mem[0]); + if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic; + if (hdr.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; + + const endian: builtin.Endian = switch (hdr.e_ident[elf.EI_DATA]) { + elf.ELFDATA2LSB => .Little, + elf.ELFDATA2MSB => .Big, + else => return error.InvalidElfEndian, + }; + assert(endian == std.builtin.endian); // this is our own debug info + + const shoff = hdr.e_shoff; + const str_section_off = shoff + @as(u64, hdr.e_shentsize) * @as(u64, hdr.e_shstrndx); + const header_strings = mapped_mem[str_section_off..str_section_off + hdr.e_shentsize]; + const shdrs = @ptrCast([*]const elf.Shdr, @alignCast(@alignOf(elf.Shdr), &mapped_mem[shoff]))[0..hdr.e_shnum]; + + var opt_debug_info: ?[]const u8 = null; + var opt_debug_abbrev: ?[]const u8 = null; + var opt_debug_str: ?[]const u8 = null; + var opt_debug_line: ?[]const u8 = null; + var opt_debug_ranges: ?[]const u8 = null; + + for (shdrs) |*shdr| { + if (shdr.sh_type == elf.SHT_NULL) continue; + + const name = std.mem.span(@ptrCast([*:0]const u8, header_strings[shdr.sh_name..].ptr)); + if (mem.eql(u8, name, ".debug_info")) { + opt_debug_info = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); + } else if (mem.eql(u8, name, ".debug_abbrev")) { + opt_debug_abbrev = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); + } else if (mem.eql(u8, name, ".debug_str")) { + opt_debug_str = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); + } else if (mem.eql(u8, name, ".debug_line")) { + opt_debug_line = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); + } else if (mem.eql(u8, name, ".debug_ranges")) { + opt_debug_ranges = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); + } + } - const debug_info = (try noasync efile.findSection(".debug_info")) orelse - return error.MissingDebugInfo; - const debug_abbrev = (try noasync efile.findSection(".debug_abbrev")) orelse - return error.MissingDebugInfo; - const debug_str = (try noasync efile.findSection(".debug_str")) orelse - return error.MissingDebugInfo; - const debug_line = (try noasync efile.findSection(".debug_line")) orelse - return error.MissingDebugInfo; - const opt_debug_ranges = try noasync efile.findSection(".debug_ranges"); - - var di = DW.DwarfInfo{ - .endian = efile.endian, - .debug_info = try chopSlice(mapped_mem, debug_info.sh_offset, debug_info.sh_size), - .debug_abbrev = try chopSlice(mapped_mem, debug_abbrev.sh_offset, debug_abbrev.sh_size), - .debug_str = try chopSlice(mapped_mem, debug_str.sh_offset, debug_str.sh_size), - .debug_line = try chopSlice(mapped_mem, debug_line.sh_offset, debug_line.sh_size), - .debug_ranges = if (opt_debug_ranges) |debug_ranges| - try chopSlice(mapped_mem, debug_ranges.sh_offset, debug_ranges.sh_size) - else - null, - }; + var di = DW.DwarfInfo{ + .endian = endian, + .debug_info = opt_debug_info orelse return error.MissingDebugInfo, + .debug_abbrev = opt_debug_abbrev orelse return error.MissingDebugInfo, + .debug_str = opt_debug_str orelse return error.MissingDebugInfo, + .debug_line = opt_debug_line orelse return error.MissingDebugInfo, + .debug_ranges = opt_debug_ranges, + }; - try noasync DW.openDwarfDebugInfo(&di, allocator); + try DW.openDwarfDebugInfo(&di, allocator); - return ModuleDebugInfo{ - .base_address = undefined, - .dwarf = di, - .mapped_memory = mapped_mem, - }; + return ModuleDebugInfo{ + .base_address = undefined, + .dwarf = di, + .mapped_memory = mapped_mem, + }; + } } /// TODO resources https://github.com/ziglang/zig/issues/4353 @@ -982,22 +1003,24 @@ const MachoSymbol = struct { } }; -fn mapWholeFile(path: []const u8) ![]const u8 { - const file = try noasync fs.openFileAbsolute(path, .{ .always_blocking = true }); - defer noasync file.close(); - - const file_len = try math.cast(usize, try file.getEndPos()); - const mapped_mem = try os.mmap( - null, - file_len, - os.PROT_READ, - os.MAP_SHARED, - file.handle, - 0, - ); - errdefer os.munmap(mapped_mem); +fn mapWholeFile(path: []const u8) ![]align(mem.page_size) const u8 { + noasync { + const file = try fs.openFileAbsolute(path, .{ .always_blocking = true }); + defer file.close(); - return mapped_mem; + const file_len = try math.cast(usize, try file.getEndPos()); + const mapped_mem = try os.mmap( + null, + file_len, + os.PROT_READ, + os.MAP_SHARED, + file.handle, + 0, + ); + errdefer os.munmap(mapped_mem); + + return mapped_mem; + } } pub const DebugInfo = struct { |
