diff options
Diffstat (limited to 'lib/std/os/linux')
| -rw-r--r-- | lib/std/os/linux/arm-eabi.zig | 44 | ||||
| -rw-r--r-- | lib/std/os/linux/arm64.zig | 7 | ||||
| -rw-r--r-- | lib/std/os/linux/mips.zig | 10 | ||||
| -rw-r--r-- | lib/std/os/linux/mips64.zig | 10 | ||||
| -rw-r--r-- | lib/std/os/linux/powerpc.zig | 5 | ||||
| -rw-r--r-- | lib/std/os/linux/powerpc64.zig | 5 | ||||
| -rw-r--r-- | lib/std/os/linux/riscv64.zig | 5 | ||||
| -rw-r--r-- | lib/std/os/linux/thumb.zig | 8 | ||||
| -rw-r--r-- | lib/std/os/linux/tls.zig | 20 | ||||
| -rw-r--r-- | lib/std/os/linux/x86.zig | 114 | ||||
| -rw-r--r-- | lib/std/os/linux/x86_64.zig | 134 |
11 files changed, 196 insertions, 166 deletions
diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm-eabi.zig index 057ecc763a..f4870dccbb 100644 --- a/lib/std/os/linux/arm-eabi.zig +++ b/lib/std/os/linux/arm-eabi.zig @@ -103,20 +103,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; /// This matches the libc clone function. pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; -pub fn restore() callconv(.Naked) void { - return asm volatile ("svc #0" - : - : [number] "{r7}" (@intFromEnum(SYS.sigreturn)), - : "memory" - ); +pub fn restore() callconv(.Naked) noreturn { + switch (@import("builtin").zig_backend) { + .stage2_c => asm volatile ( + \\ mov r7, %[number] + \\ svc #0 + : + : [number] "I" (@intFromEnum(SYS.sigreturn)), + : "memory" + ), + else => asm volatile ( + \\ svc #0 + : + : [number] "{r7}" (@intFromEnum(SYS.sigreturn)), + : "memory" + ), + } } -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ("svc #0" - : - : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)), - : "memory" - ); +pub fn restore_rt() callconv(.Naked) noreturn { + switch (@import("builtin").zig_backend) { + .stage2_c => asm volatile ( + \\ mov r7, %[number] + \\ svc #0 + : + : [number] "I" (@intFromEnum(SYS.rt_sigreturn)), + : "memory" + ), + else => asm volatile ( + \\ svc #0 + : + : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)), + : "memory" + ), + } } pub const MMAP2_UNIT = 4096; diff --git a/lib/std/os/linux/arm64.zig b/lib/std/os/linux/arm64.zig index 0824a9e9a4..b87e774306 100644 --- a/lib/std/os/linux/arm64.zig +++ b/lib/std/os/linux/arm64.zig @@ -105,16 +105,17 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: * pub const restore = restore_rt; -pub fn restore_rt() callconv(.Naked) void { +pub fn restore_rt() callconv(.Naked) noreturn { switch (@import("builtin").zig_backend) { - .stage2_c => return asm volatile ( + .stage2_c => asm volatile ( \\ mov x8, %[number] \\ svc #0 : : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), : "memory", "cc" ), - else => return asm volatile ("svc #0" + else => asm volatile ( + \\ svc #0 : : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)), : "memory", "cc" diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index 781003bedc..cfb2d73bfd 100644 --- a/lib/std/os/linux/mips.zig +++ b/lib/std/os/linux/mips.zig @@ -195,16 +195,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; /// This matches the libc clone function. pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; -pub fn restore() callconv(.Naked) void { - return asm volatile ("syscall" +pub fn restore() callconv(.Naked) noreturn { + asm volatile ( + \\ syscall : : [number] "{$2}" (@intFromEnum(SYS.sigreturn)), : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" ); } -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ("syscall" +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ syscall : : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)), : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig index 8d55dee37f..d986110979 100644 --- a/lib/std/os/linux/mips64.zig +++ b/lib/std/os/linux/mips64.zig @@ -180,16 +180,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; /// This matches the libc clone function. pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; -pub fn restore() callconv(.Naked) void { - return asm volatile ("syscall" +pub fn restore() callconv(.Naked) noreturn { + asm volatile ( + \\ syscall : : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)), : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" ); } -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ("syscall" +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ syscall : : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)), : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" diff --git a/lib/std/os/linux/powerpc.zig b/lib/std/os/linux/powerpc.zig index 31c30f2d30..87feba3f0a 100644 --- a/lib/std/os/linux/powerpc.zig +++ b/lib/std/os/linux/powerpc.zig @@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: pub const restore = restore_rt; -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ("sc" +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ sc : : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)), : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" diff --git a/lib/std/os/linux/powerpc64.zig b/lib/std/os/linux/powerpc64.zig index 722bd64687..dc142abc4f 100644 --- a/lib/std/os/linux/powerpc64.zig +++ b/lib/std/os/linux/powerpc64.zig @@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: pub const restore = restore_rt; -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ("sc" +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ sc : : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)), : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig index cbdaa76282..473cab7b31 100644 --- a/lib/std/os/linux/riscv64.zig +++ b/lib/std/os/linux/riscv64.zig @@ -101,8 +101,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: * pub const restore = restore_rt; -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ("ecall" +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ ecall : : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)), : "memory" diff --git a/lib/std/os/linux/thumb.zig b/lib/std/os/linux/thumb.zig index 2241d79bde..7c7cfde50a 100644 --- a/lib/std/os/linux/thumb.zig +++ b/lib/std/os/linux/thumb.zig @@ -141,8 +141,8 @@ pub fn syscall6( ); } -pub fn restore() callconv(.Naked) void { - return asm volatile ( +pub fn restore() callconv(.Naked) noreturn { + asm volatile ( \\ mov r7, %[number] \\ svc #0 : @@ -150,8 +150,8 @@ pub fn restore() callconv(.Naked) void { ); } -pub fn restore_rt() callconv(.Naked) void { - return asm volatile ( +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( \\ mov r7, %[number] \\ svc #0 : diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 94fa0d1a09..dfd5200d45 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -48,7 +48,7 @@ const TLSVariant = enum { }; const tls_variant = switch (native_arch) { - .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, + .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpcle, .powerpc64, .powerpc64le => TLSVariant.VariantI, .x86_64, .x86, .sparc64 => TLSVariant.VariantII, else => @compileError("undefined tls_variant for this architecture"), }; @@ -115,12 +115,14 @@ pub fn setThreadPointer(addr: usize) void { .entry_number = tls_image.gdt_entry_number, .base_addr = addr, .limit = 0xfffff, - .seg_32bit = 1, - .contents = 0, // Data - .read_exec_only = 0, - .limit_in_pages = 1, - .seg_not_present = 0, - .useable = 1, + .flags = .{ + .seg_32bit = 1, + .contents = 0, // Data + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 1, + }, }; const rc = std.os.linux.syscall1(.set_thread_area, @intFromPtr(&user_desc)); assert(rc == 0); @@ -138,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void { const rc = std.os.linux.syscall2(.arch_prctl, std.os.linux.ARCH.SET_FS, addr); assert(rc == 0); }, - .aarch64 => { + .aarch64, .aarch64_be => { asm volatile ( \\ msr tpidr_el0, %[addr] : @@ -160,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void { const rc = std.os.linux.syscall1(.set_thread_area, addr); assert(rc == 0); }, - .powerpc => { + .powerpc, .powerpcle => { asm volatile ( \\ mr 2, %[addr] : diff --git a/lib/std/os/linux/x86.zig b/lib/std/os/linux/x86.zig index e5d75c1831..721fdecb82 100644 --- a/lib/std/os/linux/x86.zig +++ b/lib/std/os/linux/x86.zig @@ -123,46 +123,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; /// This matches the libc clone function. pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; -pub fn restore() callconv(.Naked) void { +pub fn restore() callconv(.Naked) noreturn { switch (@import("builtin").zig_backend) { .stage2_c => asm volatile ( \\ movl %[number], %%eax \\ int $0x80 - \\ ret : : [number] "i" (@intFromEnum(SYS.sigreturn)), : "memory" ), else => asm volatile ( \\ int $0x80 - \\ ret : : [number] "{eax}" (@intFromEnum(SYS.sigreturn)), : "memory" ), } - unreachable; } -pub fn restore_rt() callconv(.Naked) void { +pub fn restore_rt() callconv(.Naked) noreturn { switch (@import("builtin").zig_backend) { .stage2_c => asm volatile ( \\ movl %[number], %%eax \\ int $0x80 - \\ ret : : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), : "memory" ), else => asm volatile ( \\ int $0x80 - \\ ret : : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)), : "memory" ), } - unreachable; } pub const O = struct { @@ -354,16 +348,19 @@ pub const ucontext_t = extern struct { pub const Elf_Symndx = u32; -pub const user_desc = packed struct { +pub const user_desc = extern struct { entry_number: u32, base_addr: u32, limit: u32, - seg_32bit: u1, - contents: u2, - read_exec_only: u1, - limit_in_pages: u1, - seg_not_present: u1, - useable: u1, + flags: packed struct(u32) { + seg_32bit: u1, + contents: u2, + read_exec_only: u1, + limit_in_pages: u1, + seg_not_present: u1, + useable: u1, + _: u25 = undefined, + }, }; /// socketcall() call numbers @@ -398,77 +395,80 @@ noinline fn getContextReturnAddress() usize { return @returnAddress(); } -pub fn getContextInternal() callconv(.Naked) void { +pub fn getContextInternal() callconv(.Naked) usize { asm volatile ( - \\ movl $0, (%[flags_offset])(%%edx) - \\ movl $0, (%[link_offset])(%%edx) - \\ movl %%edi, (%[edi_offset])(%%edx) - \\ movl %%esi, (%[esi_offset])(%%edx) - \\ movl %%ebp, (%[ebp_offset])(%%edx) - \\ movl %%ebx, (%[ebx_offset])(%%edx) - \\ movl %%edx, (%[edx_offset])(%%edx) - \\ movl %%ecx, (%[ecx_offset])(%%edx) - \\ movl %%eax, (%[eax_offset])(%%edx) + \\ movl $0, %[flags_offset:c](%%edx) + \\ movl $0, %[link_offset:c](%%edx) + \\ movl %%edi, %[edi_offset:c](%%edx) + \\ movl %%esi, %[esi_offset:c](%%edx) + \\ movl %%ebp, %[ebp_offset:c](%%edx) + \\ movl %%ebx, %[ebx_offset:c](%%edx) + \\ movl %%edx, %[edx_offset:c](%%edx) + \\ movl %%ecx, %[ecx_offset:c](%%edx) + \\ movl %%eax, %[eax_offset:c](%%edx) \\ movl (%%esp), %%ecx - \\ movl %%ecx, (%[eip_offset])(%%edx) + \\ movl %%ecx, %[eip_offset:c](%%edx) \\ leal 4(%%esp), %%ecx - \\ movl %%ecx, (%[esp_offset])(%%edx) + \\ movl %%ecx, %[esp_offset:c](%%edx) \\ xorl %%ecx, %%ecx \\ movw %%fs, %%cx - \\ movl %%ecx, (%[fs_offset])(%%edx) - \\ leal (%[regspace_offset])(%%edx), %%ecx - \\ movl %%ecx, (%[fpregs_offset])(%%edx) + \\ movl %%ecx, %[fs_offset:c](%%edx) + \\ leal %[regspace_offset:c](%%edx), %%ecx + \\ movl %%ecx, %[fpregs_offset:c](%%edx) \\ fnstenv (%%ecx) \\ fldenv (%%ecx) \\ pushl %%ebx \\ pushl %%esi \\ xorl %%ebx, %%ebx \\ movl %[sigaltstack], %%eax - \\ leal (%[stack_offset])(%%edx), %%ecx + \\ leal %[stack_offset:c](%%edx), %%ecx \\ int $0x80 - \\ cmpl $0, %%eax - \\ jne return + \\ testl %%eax, %%eax + \\ jnz 0f \\ movl %[sigprocmask], %%eax \\ xorl %%ecx, %%ecx - \\ leal (%[sigmask_offset])(%%edx), %%edx + \\ leal %[sigmask_offset:c](%%edx), %%edx \\ movl %[sigset_size], %%esi \\ int $0x80 - \\ return: + \\0: \\ popl %%esi \\ popl %%ebx + \\ retl : - : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")), - [link_offset] "p" (@offsetOf(ucontext_t, "link")), - [edi_offset] "p" (comptime gpRegisterOffset(REG.EDI)), - [esi_offset] "p" (comptime gpRegisterOffset(REG.ESI)), - [ebp_offset] "p" (comptime gpRegisterOffset(REG.EBP)), - [esp_offset] "p" (comptime gpRegisterOffset(REG.ESP)), - [ebx_offset] "p" (comptime gpRegisterOffset(REG.EBX)), - [edx_offset] "p" (comptime gpRegisterOffset(REG.EDX)), - [ecx_offset] "p" (comptime gpRegisterOffset(REG.ECX)), - [eax_offset] "p" (comptime gpRegisterOffset(REG.EAX)), - [eip_offset] "p" (comptime gpRegisterOffset(REG.EIP)), - [fs_offset] "p" (comptime gpRegisterOffset(REG.FS)), - [fpregs_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), - [regspace_offset] "p" (@offsetOf(ucontext_t, "regspace")), + : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")), + [link_offset] "i" (@offsetOf(ucontext_t, "link")), + [edi_offset] "i" (comptime gpRegisterOffset(REG.EDI)), + [esi_offset] "i" (comptime gpRegisterOffset(REG.ESI)), + [ebp_offset] "i" (comptime gpRegisterOffset(REG.EBP)), + [esp_offset] "i" (comptime gpRegisterOffset(REG.ESP)), + [ebx_offset] "i" (comptime gpRegisterOffset(REG.EBX)), + [edx_offset] "i" (comptime gpRegisterOffset(REG.EDX)), + [ecx_offset] "i" (comptime gpRegisterOffset(REG.ECX)), + [eax_offset] "i" (comptime gpRegisterOffset(REG.EAX)), + [eip_offset] "i" (comptime gpRegisterOffset(REG.EIP)), + [fs_offset] "i" (comptime gpRegisterOffset(REG.FS)), + [fpregs_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), + [regspace_offset] "i" (@offsetOf(ucontext_t, "regspace")), [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), - [stack_offset] "p" (@offsetOf(ucontext_t, "stack")), + [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), - [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")), + [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), [sigset_size] "i" (linux.NSIG / 8), - : "memory", "eax", "ecx", "edx" + : "cc", "memory", "eax", "ecx", "edx" ); } pub inline fn getcontext(context: *ucontext_t) usize { // This method is used so that getContextInternal can control // its prologue in order to read ESP from a constant offset. - // The unused &getContextInternal input is required so the function is included in the binary. + // An aligned stack is not needed for getContextInternal. + var clobber_edx: usize = undefined; return asm volatile ( - \\ call os.linux.x86.getContextInternal - : [ret] "={eax}" (-> usize), - : [context] "{edx}" (context), + \\ calll %[getContextInternal:P] + : [_] "={eax}" (-> usize), + [_] "={edx}" (clobber_edx), + : [_] "{edx}" (context), [getContextInternal] "X" (&getContextInternal), - : "memory", "ecx" + : "cc", "memory", "ecx" ); } diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig index e5febce14d..14f9aed51b 100644 --- a/lib/std/os/linux/x86_64.zig +++ b/lib/std/os/linux/x86_64.zig @@ -107,25 +107,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: pub const restore = restore_rt; -pub fn restore_rt() callconv(.Naked) void { +pub fn restore_rt() callconv(.Naked) noreturn { switch (@import("builtin").zig_backend) { .stage2_c => asm volatile ( \\ movl %[number], %%eax \\ syscall - \\ retq : : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), : "rcx", "r11", "memory" ), else => asm volatile ( \\ syscall - \\ retq : : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)), : "rcx", "r11", "memory" ), } - unreachable; } pub const mode_t = usize; @@ -400,92 +397,95 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize { return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index; } -fn getContextInternal() callconv(.Naked) void { +fn getContextInternal() callconv(.Naked) usize { // TODO: Read GS/FS registers? asm volatile ( - \\ movq $0, (%[flags_offset])(%%rdi) - \\ movq $0, (%[link_offset])(%%rdi) - \\ movq %%r8, (%[r8_offset])(%%rdi) - \\ movq %%r9, (%[r9_offset])(%%rdi) - \\ movq %%r10, (%[r10_offset])(%%rdi) - \\ movq %%r11, (%[r11_offset])(%%rdi) - \\ movq %%r12, (%[r12_offset])(%%rdi) - \\ movq %%r13, (%[r13_offset])(%%rdi) - \\ movq %%r14, (%[r14_offset])(%%rdi) - \\ movq %%r15, (%[r15_offset])(%%rdi) - \\ movq %%rdi, (%[rdi_offset])(%%rdi) - \\ movq %%rsi, (%[rsi_offset])(%%rdi) - \\ movq %%rbp, (%[rbp_offset])(%%rdi) - \\ movq %%rbx, (%[rbx_offset])(%%rdi) - \\ movq %%rdx, (%[rdx_offset])(%%rdi) - \\ movq %%rax, (%[rax_offset])(%%rdi) - \\ movq %%rcx, (%[rcx_offset])(%%rdi) + \\ movq $0, %[flags_offset:c](%%rdi) + \\ movq $0, %[link_offset:c](%%rdi) + \\ movq %%r8, %[r8_offset:c](%%rdi) + \\ movq %%r9, %[r9_offset:c](%%rdi) + \\ movq %%r10, %[r10_offset:c](%%rdi) + \\ movq %%r11, %[r11_offset:c](%%rdi) + \\ movq %%r12, %[r12_offset:c](%%rdi) + \\ movq %%r13, %[r13_offset:c](%%rdi) + \\ movq %%r14, %[r14_offset:c](%%rdi) + \\ movq %%r15, %[r15_offset:c](%%rdi) + \\ movq %%rdi, %[rdi_offset:c](%%rdi) + \\ movq %%rsi, %[rsi_offset:c](%%rdi) + \\ movq %%rbp, %[rbp_offset:c](%%rdi) + \\ movq %%rbx, %[rbx_offset:c](%%rdi) + \\ movq %%rdx, %[rdx_offset:c](%%rdi) + \\ movq %%rax, %[rax_offset:c](%%rdi) + \\ movq %%rcx, %[rcx_offset:c](%%rdi) \\ movq (%%rsp), %%rcx - \\ movq %%rcx, (%[rip_offset])(%%rdi) + \\ movq %%rcx, %[rip_offset:c](%%rdi) \\ leaq 8(%%rsp), %%rcx - \\ movq %%rcx, (%[rsp_offset])(%%rdi) + \\ movq %%rcx, %[rsp_offset:c](%%rdi) \\ pushfq - \\ popq (%[efl_offset])(%%rdi) - \\ leaq (%[fpmem_offset])(%%rdi), %%rcx - \\ movq %%rcx, (%[fpstate_offset])(%%rdi) + \\ popq %[efl_offset:c](%%rdi) + \\ leaq %[fpmem_offset:c](%%rdi), %%rcx + \\ movq %%rcx, %[fpstate_offset:c](%%rdi) \\ fnstenv (%%rcx) \\ fldenv (%%rcx) - \\ stmxcsr (%[mxcsr_offset])(%%rdi) - \\ leaq (%[stack_offset])(%%rdi), %%rsi + \\ stmxcsr %[mxcsr_offset:c](%%rdi) + \\ leaq %[stack_offset:c](%%rdi), %%rsi \\ movq %%rdi, %%r8 - \\ xorq %%rdi, %%rdi + \\ xorl %%edi, %%edi \\ movq %[sigaltstack], %%rax \\ syscall - \\ cmpq $0, %%rax - \\ jne return + \\ testq %%rax, %%rax + \\ jnz 0f \\ movq %[sigprocmask], %%rax - \\ xorq %%rsi, %%rsi - \\ leaq (%[sigmask_offset])(%%r8), %%rdx - \\ movq %[sigset_size], %%r10 + \\ xorl %%esi, %%esi + \\ leaq %[sigmask_offset:c](%%r8), %%rdx + \\ movl %[sigset_size], %%r10d \\ syscall - \\ return: + \\0: + \\ retq : - : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")), - [link_offset] "p" (@offsetOf(ucontext_t, "link")), - [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)), - [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)), - [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)), - [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)), - [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)), - [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)), - [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)), - [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)), - [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)), - [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)), - [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)), - [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)), - [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)), - [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)), - [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)), - [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)), - [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)), - [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)), - [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), - [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")), - [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")), + : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")), + [link_offset] "i" (@offsetOf(ucontext_t, "link")), + [r8_offset] "i" (comptime gpRegisterOffset(REG.R8)), + [r9_offset] "i" (comptime gpRegisterOffset(REG.R9)), + [r10_offset] "i" (comptime gpRegisterOffset(REG.R10)), + [r11_offset] "i" (comptime gpRegisterOffset(REG.R11)), + [r12_offset] "i" (comptime gpRegisterOffset(REG.R12)), + [r13_offset] "i" (comptime gpRegisterOffset(REG.R13)), + [r14_offset] "i" (comptime gpRegisterOffset(REG.R14)), + [r15_offset] "i" (comptime gpRegisterOffset(REG.R15)), + [rdi_offset] "i" (comptime gpRegisterOffset(REG.RDI)), + [rsi_offset] "i" (comptime gpRegisterOffset(REG.RSI)), + [rbp_offset] "i" (comptime gpRegisterOffset(REG.RBP)), + [rbx_offset] "i" (comptime gpRegisterOffset(REG.RBX)), + [rdx_offset] "i" (comptime gpRegisterOffset(REG.RDX)), + [rax_offset] "i" (comptime gpRegisterOffset(REG.RAX)), + [rcx_offset] "i" (comptime gpRegisterOffset(REG.RCX)), + [rsp_offset] "i" (comptime gpRegisterOffset(REG.RSP)), + [rip_offset] "i" (comptime gpRegisterOffset(REG.RIP)), + [efl_offset] "i" (comptime gpRegisterOffset(REG.EFL)), + [fpstate_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), + [fpmem_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem")), + [mxcsr_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")), [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), - [stack_offset] "p" (@offsetOf(ucontext_t, "stack")), + [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), - [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")), + [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), [sigset_size] "i" (linux.NSIG / 8), - : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" + : "cc", "memory", "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" ); } pub inline fn getcontext(context: *ucontext_t) usize { // This method is used so that getContextInternal can control // its prologue in order to read RSP from a constant offset - // The unused &getContextInternal input is required so the function is included in the binary. + // An aligned stack is not needed for getContextInternal. + var clobber_rdi: usize = undefined; return asm volatile ( - \\ call os.linux.x86_64.getContextInternal - : [ret] "={rax}" (-> usize), - : [context] "{rdi}" (context), + \\ callq %[getContextInternal:P] + : [_] "={rax}" (-> usize), + [_] "={rdi}" (clobber_rdi), + : [_] "{rdi}" (context), [getContextInternal] "X" (&getContextInternal), - : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" + : "cc", "memory", "rcx", "rdx", "rsi", "r8", "r10", "r11" ); } |
