aboutsummaryrefslogtreecommitdiff
path: root/std/debug.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-08-03 12:39:15 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-08-03 12:39:15 -0400
commit63ebd9d12e48765514777418e12f55576ff63509 (patch)
tree05f40973b86f91bffd6458247bd9cd2c3d66b72d /std/debug.zig
parenta2e1be0346c364c4327dc2b81bbcdeca12414dab (diff)
parent5687323cd2a759dfdf9533e46e3de8cddb1b55b7 (diff)
downloadzig-63ebd9d12e48765514777418e12f55576ff63509.tar.gz
zig-63ebd9d12e48765514777418e12f55576ff63509.zip
Merge remote-tracking branch 'origin/master' into llvm9
Diffstat (limited to 'std/debug.zig')
-rw-r--r--std/debug.zig75
1 files changed, 54 insertions, 21 deletions
diff --git a/std/debug.zig b/std/debug.zig
index d81e62901a..32f96d3e15 100644
--- a/std/debug.zig
+++ b/std/debug.zig
@@ -12,6 +12,7 @@ const coff = std.coff;
const pdb = std.pdb;
const ArrayList = std.ArrayList;
const builtin = @import("builtin");
+const root = @import("root");
const maxInt = std.math.maxInt;
const File = std.fs.File;
const windows = std.os.windows;
@@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool
pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn {
@setCold(true);
+ if (enable_segfault_handler) {
+ // If a segfault happens while panicking, we want it to actually segfault, not trigger
+ // the handler.
+ resetSegfaultHandler();
+ }
+
if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
// Panicked during a panic.
@@ -368,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
const obj_basename = fs.path.basename(mod.obj_file_name);
var symbol_i: usize = 0;
- const symbol_name = while (symbol_i != mod.symbols.len) {
+ const symbol_name = if (!mod.populated) "???" else while (symbol_i != mod.symbols.len) {
const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]);
if (prefix.RecordLen < 2)
return error.InvalidDebugInfo;
@@ -851,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
const age = try pdb_stream.stream.readIntLittle(u32);
var guid: [16]u8 = undefined;
try pdb_stream.stream.readNoEof(guid[0..]);
+ 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)
- return error.InvalidDebugInfo;
+ return error.PDBMismatch;
// We validated the executable and pdb match.
const string_table_index = str_tab_index: {
@@ -896,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
return error.MissingDebugInfo;
};
- di.pdb.string_table = di.pdb.getStreamById(string_table_index) orelse return error.InvalidDebugInfo;
+ di.pdb.string_table = di.pdb.getStreamById(string_table_index) orelse return error.MissingDebugInfo;
di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo;
const dbi = di.pdb.dbi;
// Dbi Header
const dbi_stream_header = try dbi.stream.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)
+ return error.UnmatchingPDB;
+
const mod_info_size = dbi_stream_header.ModInfoSize;
const section_contrib_size = dbi_stream_header.SectionContributionSize;
@@ -2312,39 +2326,58 @@ fn getDebugInfoAllocator() *mem.Allocator {
/// Whether or not the current target can print useful debug information when a segfault occurs.
pub const have_segfault_handling_support = (builtin.arch == builtin.Arch.x86_64 and builtin.os == .linux) or builtin.os == .windows;
+pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
+ root.enable_segfault_handler
+else
+ runtime_safety and have_segfault_handling_support;
+
+pub fn maybeEnableSegfaultHandler() void {
+ if (enable_segfault_handler) {
+ std.debug.attachSegfaultHandler();
+ }
+}
+
+var windows_segfault_handle: ?windows.HANDLE = null;
/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");
pub fn attachSegfaultHandler() void {
if (!have_segfault_handling_support) {
@compileError("segfault handler not supported for this target");
}
- switch (builtin.os) {
- .linux => {
- var act = os.Sigaction{
- .sigaction = handleSegfaultLinux,
- .mask = os.empty_sigset,
- .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
- };
-
- os.sigaction(os.SIGSEGV, &act, null);
- },
- .windows => {
- _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
- },
- else => unreachable,
+ if (windows.is_the_target) {
+ windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
+ return;
}
+ var act = os.Sigaction{
+ .sigaction = handleSegfaultLinux,
+ .mask = os.empty_sigset,
+ .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
+ };
+
+ os.sigaction(os.SIGSEGV, &act, null);
}
-extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
- // Reset to the default handler so that if a segfault happens in this handler it will crash
- // the process. Also when this handler returns, the original instruction will be repeated
- // and the resulting segfault will crash the process rather than continually dump stack traces.
+fn resetSegfaultHandler() void {
+ if (windows.is_the_target) {
+ if (windows_segfault_handle) |handle| {
+ assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
+ windows_segfault_handle = null;
+ }
+ return;
+ }
var act = os.Sigaction{
.sigaction = os.SIG_DFL,
.mask = os.empty_sigset,
.flags = 0,
};
os.sigaction(os.SIGSEGV, &act, null);
+}
+
+extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
+ // Reset to the default handler so that if a segfault happens in this handler it will crash
+ // the process. Also when this handler returns, the original instruction will be repeated
+ // and the resulting segfault will crash the process rather than continually dump stack traces.
+ resetSegfaultHandler();
const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]);