diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-02-25 21:04:23 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-02-25 21:04:23 -0700 |
| commit | 0b58b617998b79a765b54f88fbe90ca2798b3d3e (patch) | |
| tree | ca6cc4b6bcc2b93166d196049ee49416afe781ad /lib/std/debug.zig | |
| parent | dc325669e360f7a9dfa24f85a62fa386529dade6 (diff) | |
| parent | fd208d9d5913a0929e444deb97b91092c427bb14 (diff) | |
| download | zig-0b58b617998b79a765b54f88fbe90ca2798b3d3e.tar.gz zig-0b58b617998b79a765b54f88fbe90ca2798b3d3e.zip | |
Merge remote-tracking branch 'origin/master' into llvm12
Conflicts:
* src/clang.zig
* src/llvm.zig
- this file got moved to src/llvm/bindings.zig in master branch so I
had to put the new LLVM arch/os enum tags into it.
* lib/std/target.zig, src/stage1/target.cpp
- haiku had an inconsistency with its default target ABI, gnu vs
eabi. In this commit we make it gnu in both places to match the
latest changes by @hoanga.
* src/translate_c.zig
Diffstat (limited to 'lib/std/debug.zig')
| -rw-r--r-- | lib/std/debug.zig | 120 |
1 files changed, 82 insertions, 38 deletions
diff --git a/lib/std/debug.zig b/lib/std/debug.zig index be5635ee8f..f32c1a6156 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2015-2020 Zig Contributors +// Copyright (c) 2015-2021 Zig Contributors // This file is part of [zig](https://ziglang.org/), which is MIT licensed. // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. @@ -50,7 +50,7 @@ pub const LineInfo = struct { } }; -var stderr_mutex = std.Mutex{}; +var stderr_mutex = std.Thread.Mutex{}; /// Deprecated. Use `std.log` functions for logging or `std.debug.print` for /// "printf debugging". @@ -65,7 +65,7 @@ pub fn print(comptime fmt: []const u8, args: anytype) void { nosuspend stderr.print(fmt, args) catch return; } -pub fn getStderrMutex() *std.Mutex { +pub fn getStderrMutex() *std.Thread.Mutex { return &stderr_mutex; } @@ -108,11 +108,11 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { return; } const debug_info = getSelfDebugInfo() catch |err| { - stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; + stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; return; }; writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| { - stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; + stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; return; }; } @@ -129,7 +129,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { return; } const debug_info = getSelfDebugInfo() catch |err| { - stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; + stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; return; }; const tty_config = detectTTYConfig(); @@ -199,11 +199,11 @@ pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { return; } const debug_info = getSelfDebugInfo() catch |err| { - stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; + stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; return; }; writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| { - stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; + stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; return; }; } @@ -235,7 +235,7 @@ pub fn panic(comptime format: []const u8, args: anytype) noreturn { var panicking: u8 = 0; // Locked to avoid interleaving panic messages from multiple threads. -var panic_mutex = std.Mutex{}; +var panic_mutex = std.Thread.Mutex{}; /// Counts how many times the panic handler is invoked by this thread. /// This is used to catch and handle panics triggered by the panic handler. @@ -250,6 +250,24 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c resetSegfaultHandler(); } + if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) + nosuspend { + // As a workaround for not having threadlocal variable support in LLD for this target, + // we have a simpler panic implementation that does not use threadlocal variables. + // TODO https://github.com/ziglang/zig/issues/7527 + const stderr = io.getStdErr().writer(); + if (@atomicRmw(u8, &panicking, .Add, 1, .SeqCst) == 0) { + stderr.print("panic: " ++ format ++ "\n", args) catch os.abort(); + if (trace) |t| { + dumpStackTrace(t.*); + } + dumpCurrentStackTrace(first_trace_addr); + } else { + stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort(); + } + os.abort(); + }; + nosuspend switch (panic_stage) { 0 => { panic_stage = 1; @@ -262,6 +280,12 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c defer held.release(); const stderr = io.getStdErr().writer(); + if (builtin.single_threaded) { + stderr.print("panic: ", .{}) catch os.abort(); + } else { + const current_thread_id = std.Thread.getCurrentThreadId(); + stderr.print("thread {d} panic: ", .{current_thread_id}) catch os.abort(); + } stderr.print(format ++ "\n", args) catch os.abort(); if (trace) |t| { dumpStackTrace(t.*); @@ -274,9 +298,8 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c // and call abort() // Sleep forever without hammering the CPU - var event = std.ResetEvent.init(); + var event: std.Thread.StaticResetEvent = .{}; event.wait(); - unreachable; } }, @@ -512,15 +535,15 @@ fn populateModule(di: *ModuleDebugInfo, mod: *Module) !void { const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo; - const signature = try modi.inStream().readIntLittle(u32); + const signature = try modi.reader().readIntLittle(u32); if (signature != 4) return error.InvalidDebugInfo; mod.symbols = try allocator.alloc(u8, mod.mod_info.SymByteSize - 4); - try modi.inStream().readNoEof(mod.symbols); + try modi.reader().readNoEof(mod.symbols); mod.subsect_info = try allocator.alloc(u8, mod.mod_info.C13ByteSize); - try modi.inStream().readNoEof(mod.subsect_info); + try modi.reader().readNoEof(mod.subsect_info); var sect_offset: usize = 0; var skip_len: usize = undefined; @@ -606,7 +629,7 @@ fn printLineInfo( tty_config.setColor(out_stream, .White); if (line_info) |*li| { - try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column }); + try out_stream.print("{s}:{d}:{d}", .{ li.file_name, li.line, li.column }); } else { try out_stream.writeAll("???:?:?"); } @@ -614,7 +637,7 @@ fn printLineInfo( 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 }); + try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name }); tty_config.setColor(out_stream, .Reset); try out_stream.writeAll("\n"); @@ -634,6 +657,7 @@ fn printLineInfo( } else |err| switch (err) { error.EndOfFile, error.FileNotFound => {}, error.BadPathName => {}, + error.AccessDenied => {}, else => return err, } } @@ -699,11 +723,11 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf try di.pdb.openFile(di.coff, path); var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo; - const version = try pdb_stream.inStream().readIntLittle(u32); - const signature = try pdb_stream.inStream().readIntLittle(u32); - const age = try pdb_stream.inStream().readIntLittle(u32); + const version = try pdb_stream.reader().readIntLittle(u32); + const signature = try pdb_stream.reader().readIntLittle(u32); + const age = try pdb_stream.reader().readIntLittle(u32); var guid: [16]u8 = undefined; - try pdb_stream.inStream().readNoEof(&guid); + try pdb_stream.reader().readNoEof(&guid); if (version != 20000404) // VC70, only value observed by LLVM team return error.UnknownPDBVersion; if (!mem.eql(u8, &di.coff.guid, &guid) or di.coff.age != age) @@ -711,9 +735,9 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf // We validated the executable and pdb match. const string_table_index = str_tab_index: { - const name_bytes_len = try pdb_stream.inStream().readIntLittle(u32); + const name_bytes_len = try pdb_stream.reader().readIntLittle(u32); const name_bytes = try allocator.alloc(u8, name_bytes_len); - try pdb_stream.inStream().readNoEof(name_bytes); + try pdb_stream.reader().readNoEof(name_bytes); const HashTableHeader = packed struct { Size: u32, @@ -723,17 +747,17 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf return cap * 2 / 3 + 1; } }; - const hash_tbl_hdr = try pdb_stream.inStream().readStruct(HashTableHeader); + const hash_tbl_hdr = try pdb_stream.reader().readStruct(HashTableHeader); if (hash_tbl_hdr.Capacity == 0) return error.InvalidDebugInfo; if (hash_tbl_hdr.Size > HashTableHeader.maxLoad(hash_tbl_hdr.Capacity)) return error.InvalidDebugInfo; - const present = try readSparseBitVector(&pdb_stream.inStream(), allocator); + const present = try readSparseBitVector(&pdb_stream.reader(), allocator); if (present.len != hash_tbl_hdr.Size) return error.InvalidDebugInfo; - const deleted = try readSparseBitVector(&pdb_stream.inStream(), allocator); + const deleted = try readSparseBitVector(&pdb_stream.reader(), allocator); const Bucket = struct { first: u32, @@ -741,8 +765,8 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf }; const bucket_list = try allocator.alloc(Bucket, present.len); for (present) |_| { - const name_offset = try pdb_stream.inStream().readIntLittle(u32); - const name_index = try pdb_stream.inStream().readIntLittle(u32); + const name_offset = try pdb_stream.reader().readIntLittle(u32); + const name_index = try pdb_stream.reader().readIntLittle(u32); const name = mem.spanZ(std.meta.assumeSentinel(name_bytes.ptr + name_offset, 0)); if (mem.eql(u8, name, "/names")) { break :str_tab_index name_index; @@ -757,7 +781,7 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf const dbi = di.pdb.dbi; // Dbi Header - const dbi_stream_header = try dbi.inStream().readStruct(pdb.DbiStreamHeader); + const dbi_stream_header = try dbi.reader().readStruct(pdb.DbiStreamHeader); if (dbi_stream_header.VersionHeader != 19990903) // V70, only value observed by LLVM team return error.UnknownPDBVersion; if (dbi_stream_header.Age != age) @@ -771,7 +795,7 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf // Module Info Substream var mod_info_offset: usize = 0; while (mod_info_offset != mod_info_size) { - const mod_info = try dbi.inStream().readStruct(pdb.ModInfo); + const mod_info = try dbi.reader().readStruct(pdb.ModInfo); var this_record_len: usize = @sizeOf(pdb.ModInfo); const module_name = try dbi.readNullTermString(allocator); @@ -809,14 +833,14 @@ fn readCoffDebugInfo(allocator: *mem.Allocator, coff_file: File) !ModuleDebugInf var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); var sect_cont_offset: usize = 0; if (section_contrib_size != 0) { - const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.inStream().readIntLittle(u32)); + const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.reader().readIntLittle(u32)); if (ver != pdb.SectionContrSubstreamVersion.Ver60) return error.InvalidDebugInfo; sect_cont_offset += @sizeOf(u32); } while (sect_cont_offset != section_contrib_size) { const entry = try sect_contribs.addOne(); - entry.* = try dbi.inStream().readStruct(pdb.SectionContribEntry); + entry.* = try dbi.reader().readStruct(pdb.SectionContribEntry); sect_cont_offset += @sizeOf(pdb.SectionContribEntry); if (sect_cont_offset > section_contrib_size) @@ -1101,12 +1125,15 @@ pub const DebugInfo = struct { } pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo { - if (comptime std.Target.current.isDarwin()) - return self.lookupModuleDyld(address) - else if (builtin.os.tag == .windows) - return self.lookupModuleWin32(address) - else + if (comptime std.Target.current.isDarwin()) { + return self.lookupModuleDyld(address); + } else if (builtin.os.tag == .windows) { + return self.lookupModuleWin32(address); + } else if (builtin.os.tag == .haiku) { + return self.lookupModuleHaiku(address); + } else { return self.lookupModuleDl(address); + } } fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ModuleDebugInfo { @@ -1312,6 +1339,10 @@ pub const DebugInfo = struct { return obj_di; } + + fn lookupModuleHaiku(self: *DebugInfo, address: usize) !*ModuleDebugInfo { + @panic("TODO implement lookup module for Haiku"); + } }; const SymbolInfo = struct { @@ -1696,6 +1727,7 @@ fn getDebugInfoAllocator() *mem.Allocator { pub const have_segfault_handling_support = switch (builtin.os.tag) { .linux, .netbsd => true, .windows => true, + .freebsd, .openbsd => @hasDecl(os, "ucontext_t"), else => false, }; pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) @@ -1757,7 +1789,9 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v const addr = switch (builtin.os.tag) { .linux => @ptrToInt(info.fields.sigfault.addr), + .freebsd => @ptrToInt(info.addr), .netbsd => @ptrToInt(info.info.reason.fault.addr), + .openbsd => @ptrToInt(info.data.fault.addr), else => unreachable, }; @@ -1781,8 +1815,18 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v }, .x86_64 => { const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); - const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]); - const bp = @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]); + const ip = switch (builtin.os.tag) { + .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]), + .freebsd => @intCast(usize, ctx.mcontext.rip), + .openbsd => @intCast(usize, ctx.sc_rip), + else => unreachable, + }; + const bp = switch (builtin.os.tag) { + .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]), + .openbsd => @intCast(usize, ctx.sc_rbp), + .freebsd => @intCast(usize, ctx.mcontext.rbp), + else => unreachable, + }; dumpStackTraceFromBase(bp, ip); }, .arm => { |
