Correct signal bits for MIPS

Also enable the segfault handler for all the supported architectures
beside MIPS.
This commit is contained in:
LemonBoy 2019-10-01 15:57:38 +02:00 committed by Andrew Kelley
parent bed4bfa69a
commit 17f2af10b5
11 changed files with 264 additions and 84 deletions

View File

@ -2336,7 +2336,7 @@ 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 have_segfault_handling_support = builtin.os == .linux or builtin.os == .windows;
pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
root.enable_segfault_handler
else
@ -2390,12 +2390,31 @@ extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *con
// 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]);
const bp = @intCast(usize, ctx.mcontext.gregs[os.REG_RBP]);
const addr = @ptrToInt(info.fields.sigfault.addr);
std.debug.warn("Segmentation fault at address 0x{x}\n", addr);
dumpStackTraceFromBase(bp, ip);
switch (builtin.arch) {
.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]);
dumpStackTraceFromBase(bp, ip);
},
.arm => {
const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
const ip = @intCast(usize, ctx.mcontext.arm_pc);
const bp = @intCast(usize, ctx.mcontext.arm_fp);
dumpStackTraceFromBase(bp, ip);
},
.aarch64 => {
const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
const ip = @intCast(usize, ctx.mcontext.pc);
// x29 is the ABI-designated frame pointer
const bp = @intCast(usize, ctx.mcontext.regs[29]);
dumpStackTraceFromBase(bp, ip);
},
else => {},
}
// We cannot allow the signal handler to return because when it runs the original instruction
// again, the memory may be mapped and undefined behavior would occur rather than repeating

View File

@ -140,9 +140,27 @@ pub const WEXITED = 4;
pub const WCONTINUED = 8;
pub const WNOWAIT = 0x1000000;
pub const SA_NOCLDSTOP = 1;
pub const SA_NOCLDWAIT = 2;
pub const SA_SIGINFO = 4;
pub usingnamespace if (is_mips)
struct {
pub const SA_NOCLDSTOP = 1;
pub const SA_NOCLDWAIT = 0x10000;
pub const SA_SIGINFO = 8;
pub const SIG_BLOCK = 1;
pub const SIG_UNBLOCK = 2;
pub const SIG_SETMASK = 3;
}
else
struct {
pub const SA_NOCLDSTOP = 1;
pub const SA_NOCLDWAIT = 2;
pub const SA_SIGINFO = 4;
pub const SIG_BLOCK = 0;
pub const SIG_UNBLOCK = 1;
pub const SIG_SETMASK = 2;
};
pub const SA_ONSTACK = 0x08000000;
pub const SA_RESTART = 0x10000000;
pub const SA_NODEFER = 0x40000000;
@ -209,10 +227,6 @@ pub const SEEK_SET = 0;
pub const SEEK_CUR = 1;
pub const SEEK_END = 2;
pub const SIG_BLOCK = 0;
pub const SIG_UNBLOCK = 1;
pub const SIG_SETMASK = 2;
pub const PROTO_ip = 0o000;
pub const PROTO_icmp = 0o001;
pub const PROTO_igmp = 0o002;
@ -786,17 +800,34 @@ pub const winsize = extern struct {
ws_ypixel: u16,
};
pub const NSIG = 65;
pub const NSIG = if (is_mips) 128 else 65;
pub const sigset_t = [128 / @sizeOf(usize)]usize;
pub const all_mask = [_]u32{ 0xffffffff, 0xffffffff };
pub const app_mask = [_]u32{ 0xfffffffc, 0x7fffffff };
pub const k_sigaction = extern struct {
sigaction: ?extern fn (i32, *siginfo_t, *c_void) void,
flags: usize,
restorer: extern fn () void,
mask: [2]u32,
};
pub usingnamespace if (NSIG == 65)
struct {
pub const all_mask = [2]u32{ 0xffffffff, 0xffffffff };
pub const app_mask = [2]u32{ 0xfffffffc, 0x7fffffff };
}
else
struct {
pub const all_mask = [4]u32{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
pub const app_mask = [4]u32{ 0xfffffffc, 0x7fffffff, 0xffffffff, 0xffffffff };
};
pub const k_sigaction = if (is_mips)
extern struct {
flags: usize,
sigaction: ?extern fn (i32, *siginfo_t, *c_void) void,
mask: [4]u32,
restorer: extern fn () void,
}
else
extern struct {
sigaction: ?extern fn (i32, *siginfo_t, *c_void) void,
flags: usize,
restorer: extern fn () void,
mask: [2]u32,
};
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
pub const Sigaction = extern struct {
@ -1030,12 +1061,12 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
pub const MINSIGSTKSZ = switch (builtin.arch) {
.i386, .x86_64, .arm => 2048,
.i386, .x86_64, .arm, .mipsel => 2048,
.aarch64 => 5120,
else => @compileError("MINSIGSTKSZ not defined for this architecture"),
};
pub const SIGSTKSZ = switch (builtin.arch) {
.i386, .x86_64, .arm => 8192,
.i386, .x86_64, .arm, .mipsel => 8192,
.aarch64 => 16384,
else => @compileError("SIGSTKSZ not defined for this architecture"),
};
@ -1050,6 +1081,70 @@ pub const stack_t = extern struct {
ss_size: isize,
};
pub const sigval = extern union {
int: i32,
ptr: *c_void,
};
const siginfo_fields_union = extern union {
pad: [128 - 2 * @sizeOf(c_int) - @sizeOf(c_long)]u8,
common: extern struct {
first: extern union {
piduid: extern struct {
pid: pid_t,
uid: uid_t,
},
timer: extern struct {
timerid: i32,
overrun: i32,
},
},
second: extern union {
value: sigval,
sigchld: extern struct {
status: i32,
utime: clock_t,
stime: clock_t,
},
},
},
sigfault: extern struct {
addr: *c_void,
addr_lsb: i16,
first: extern union {
addr_bnd: extern struct {
lower: *c_void,
upper: *c_void,
},
pkey: u32,
},
},
sigpoll: extern struct {
band: isize,
fd: i32,
},
sigsys: extern struct {
call_addr: *c_void,
syscall: i32,
arch: u32,
},
};
pub const siginfo_t = if (is_mips)
extern struct {
signo: i32,
code: i32,
errno: i32,
fields: siginfo_fields_union,
}
else
extern struct {
signo: i32,
errno: i32,
code: i32,
fields: siginfo_fields_union,
};
pub const io_uring_params = extern struct {
sq_entries: u32,
cq_entries: u32,

View File

@ -1,10 +1,11 @@
// arm-eabi-specific declarations that are intended to be imported into the POSIX namespace.
const std = @import("../../std.zig");
const std = @import("../../../std.zig");
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
const iovec = linux.iovec;
const iovec_const = linux.iovec_const;
const stack_t = linux.stack_t;
const sigset_t = linux.sigset_t;
pub const SYS_restart_syscall = 0;
pub const SYS_exit = 1;
@ -565,4 +566,37 @@ pub const timezone = extern struct {
tz_dsttime: i32,
};
pub const mcontext_t = extern struct {
trap_no: usize,
error_code: usize,
oldmask: usize,
arm_r0: usize,
arm_r1: usize,
arm_r2: usize,
arm_r3: usize,
arm_r4: usize,
arm_r5: usize,
arm_r6: usize,
arm_r7: usize,
arm_r8: usize,
arm_r9: usize,
arm_r10: usize,
arm_fp: usize,
arm_ip: usize,
arm_sp: usize,
arm_lr: usize,
arm_pc: usize,
arm_cpsr: usize,
fault_address: usize,
};
pub const ucontext_t = extern struct {
flags: usize,
link: *ucontext_t,
stack: stack_t,
mcontext: mcontext_t,
sigmask: sigset_t,
regspace: [64]u64,
};
pub const Elf_Symndx = u32;

View File

@ -8,6 +8,8 @@ const iovec = linux.iovec;
const iovec_const = linux.iovec_const;
const uid_t = linux.uid_t;
const gid_t = linux.gid_t;
const stack_t = linux.stack_t;
const sigset_t = linux.sigset_t;
pub const SYS_io_setup = 0;
pub const SYS_io_destroy = 1;
@ -445,4 +447,23 @@ pub const timezone = extern struct {
tz_dsttime: i32,
};
pub const mcontext_t = extern struct {
fault_address: usize,
regs: [31]usize,
sp: usize,
pc: usize,
pstate: usize,
// Make sure the field is correctly aligned since this area
// holds various FP/vector registers
reserved1: [256 * 16]u8 align(16),
};
pub const ucontext_t = extern struct {
flags: usize,
link: *ucontext_t,
stack: stack_t,
sigmask: sigset_t,
mcontext: mcontext_t,
};
pub const Elf_Symndx = u32;

View File

@ -536,60 +536,6 @@ pub const timezone = extern struct {
pub const Elf_Symndx = u32;
pub const sigval = extern union {
int: i32,
ptr: *c_void,
};
pub const siginfo_t = extern struct {
signo: i32,
errno: i32,
code: i32,
fields: extern union {
pad: [128 - 2 * @sizeOf(c_int) - @sizeOf(c_long)]u8,
common: extern struct {
first: extern union {
piduid: extern struct {
pid: pid_t,
uid: uid_t,
},
timer: extern struct {
timerid: i32,
overrun: i32,
},
},
second: extern union {
value: sigval,
sigchld: extern struct {
status: i32,
utime: clock_t,
stime: clock_t,
},
},
},
sigfault: extern struct {
addr: *c_void,
addr_lsb: i16,
first: extern union {
addr_bnd: extern struct {
lower: *c_void,
upper: *c_void,
},
pkey: u32,
},
},
sigpoll: extern struct {
band: isize,
fd: i32,
},
sigsys: extern struct {
call_addr: *c_void,
syscall: i32,
arch: u32,
},
},
};
pub const greg_t = usize;
pub const gregset_t = [23]greg_t;
pub const fpstate = extern struct {

View File

@ -673,15 +673,18 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
assert(sig >= 1);
assert(sig != SIGKILL);
assert(sig != SIGSTOP);
const restorer_fn = if ((act.flags & SA_SIGINFO) != 0) restore_rt else restore;
var ksa = k_sigaction{
.sigaction = act.sigaction,
.flags = act.flags | SA_RESTORER,
.mask = undefined,
.restorer = @ptrCast(extern fn () void, restore_rt),
.restorer = @ptrCast(extern fn () void, restorer_fn),
};
var ksa_old: k_sigaction = undefined;
@memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
const ksa_mask_size = @sizeOf(@typeOf(ksa_old.mask));
@memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size);
const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size);
const err = getErrno(result);
if (err != 0) {
return result;
@ -689,7 +692,7 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
if (oact) |old| {
old.sigaction = ksa_old.sigaction;
old.flags = @truncate(u32, ksa_old.flags);
@memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
@memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), ksa_mask_size);
}
return 0;
}

View File

@ -1,3 +1,5 @@
usingnamespace @import("../bits.zig");
pub fn syscall0(number: usize) usize {
return asm volatile ("svc #0"
: [ret] "={r0}" (-> usize)
@ -94,3 +96,19 @@ pub extern fn getThreadPointer() usize {
: [ret] "=r" (-> usize)
);
}
pub nakedcc fn restore() void {
return asm volatile ("svc #0"
:
: [number] "{r7}" (usize(SYS_sigreturn))
: "memory"
);
}
pub nakedcc fn restore_rt() void {
return asm volatile ("svc #0"
:
: [number] "{r7}" (usize(SYS_rt_sigreturn))
: "memory"
);
}

View File

@ -1,3 +1,5 @@
usingnamespace @import("../bits.zig");
pub fn syscall0(number: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
@ -85,3 +87,13 @@ pub fn syscall6(
/// This matches the libc clone function.
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub const restore = restore_rt;
pub nakedcc fn restore_rt() void {
return asm volatile ("svc #0"
:
: [number] "{x8}" (usize(SYS_rt_sigreturn))
: "memory", "cc"
);
}

View File

@ -1,3 +1,5 @@
usingnamespace @import("../bits.zig");
pub fn syscall0(number: usize) usize {
return asm volatile (
\\ syscall
@ -122,3 +124,19 @@ pub fn syscall6(
/// This matches the libc clone function.
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub nakedcc fn restore() void {
return asm volatile ("syscall"
:
: [number] "{$2}" (usize(SYS_sigreturn))
: "memory", "cc", "$7"
);
}
pub nakedcc fn restore_rt() void {
return asm volatile ("syscall"
:
: [number] "{$2}" (usize(SYS_rt_sigreturn))
: "memory", "cc", "$7"
);
}

View File

@ -1,3 +1,5 @@
usingnamespace @import("../bits.zig");
pub fn syscall0(number: usize) usize {
return asm volatile ("ecall"
: [ret] "={x10}" (-> usize)
@ -84,3 +86,13 @@ pub fn syscall6(
}
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub const restore = restore_rt;
pub nakedcc fn restore_rt() void {
return asm volatile ("ecall"
:
: [number] "{x17}" (usize(SYS_rt_sigreturn))
: "memory"
);
}

View File

@ -88,10 +88,12 @@ pub fn syscall6(
/// This matches the libc clone function.
pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub const restore = restore_rt;
pub nakedcc fn restore_rt() void {
return asm volatile ("syscall"
:
: [number] "{rax}" (usize(SYS_rt_sigreturn))
: "rcx", "r11"
: "rcx", "r11", "memory"
);
}