aboutsummaryrefslogtreecommitdiff
path: root/lib/std/debug.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-02-25 21:04:23 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-02-25 21:04:23 -0700
commit0b58b617998b79a765b54f88fbe90ca2798b3d3e (patch)
treeca6cc4b6bcc2b93166d196049ee49416afe781ad /lib/std/debug.zig
parentdc325669e360f7a9dfa24f85a62fa386529dade6 (diff)
parentfd208d9d5913a0929e444deb97b91092c427bb14 (diff)
downloadzig-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.zig120
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 => {