mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-01 23:40:28 +00:00
Implement swapcontext() and makecontext()
This change introduces support for Linux-style uc_context manipulation that's fast and works well on all supported OSes and architectures. It also integrates with the Cosmpolitan runtime which can show backtraces comprised of multiple stacks and fibers. See the test and example code for further details. This will be used by Mold once it's been vendored
This commit is contained in:
parent
7ec84655b4
commit
197aa0d465
28 changed files with 617 additions and 355 deletions
|
@ -214,7 +214,9 @@ o/$(MODE)/libc/calls/pledge-linux.o: private \
|
|||
# these assembly files are safe to build on aarch64
|
||||
o/$(MODE)/libc/calls/getcontext.o: libc/calls/getcontext.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/libc/calls/setcontext2.o: libc/calls/setcontext2.S
|
||||
o/$(MODE)/libc/calls/swapcontext.o: libc/calls/swapcontext.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/libc/calls/tailcontext.o: libc/calls/tailcontext.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
||||
|
|
|
@ -20,132 +20,14 @@
|
|||
|
||||
// Gets machine state.
|
||||
//
|
||||
// @return 0 on success, or -1 w/ errno
|
||||
// @see makecontext()
|
||||
// @see swapcontext()
|
||||
// @see setcontext()
|
||||
// @threadsafe
|
||||
.ftrace1
|
||||
getcontext:
|
||||
#ifdef __x86_64__
|
||||
|
||||
pushf
|
||||
pop 176(%rdi)
|
||||
movaps %xmm0,480(%rdi)
|
||||
movaps %xmm1,496(%rdi)
|
||||
movaps %xmm2,512(%rdi)
|
||||
movaps %xmm3,528(%rdi)
|
||||
movaps %xmm4,544(%rdi)
|
||||
movaps %xmm5,560(%rdi)
|
||||
movaps %xmm6,576(%rdi)
|
||||
movaps %xmm7,592(%rdi)
|
||||
movaps %xmm8,608(%rdi)
|
||||
movaps %xmm9,624(%rdi)
|
||||
movaps %xmm10,640(%rdi)
|
||||
movaps %xmm11,656(%rdi)
|
||||
movaps %xmm12,672(%rdi)
|
||||
movaps %xmm13,688(%rdi)
|
||||
movaps %xmm14,704(%rdi)
|
||||
movaps %xmm15,720(%rdi)
|
||||
mov %r8,40(%rdi)
|
||||
mov %r9,48(%rdi)
|
||||
mov %r10,56(%rdi)
|
||||
mov %r11,64(%rdi)
|
||||
mov %r12,72(%rdi)
|
||||
mov %r13,80(%rdi)
|
||||
mov %r14,88(%rdi)
|
||||
mov %r15,96(%rdi)
|
||||
mov %rdi,104(%rdi)
|
||||
mov %rsi,112(%rdi)
|
||||
mov %rbp,120(%rdi)
|
||||
mov %rbx,128(%rdi)
|
||||
mov %rdx,136(%rdi)
|
||||
mov %rax,144(%rdi)
|
||||
mov %rcx,152(%rdi)
|
||||
lea 320(%rdi),%rax
|
||||
mov %rax,224(%rdi)
|
||||
lea 8(%rsp),%rax
|
||||
mov %rax,160(%rdi)
|
||||
mov (%rsp),%rax
|
||||
mov %rax,168(%rdi)
|
||||
jmp __getcontext
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
stp x0,x1,[x0,184]
|
||||
stp x2,x3,[x0,200]
|
||||
stp x4,x5,[x0,216]
|
||||
stp x6,x7,[x0,232]
|
||||
stp x8,x9,[x0,248]
|
||||
stp x10,x11,[x0,264]
|
||||
stp x12,x13,[x0,280]
|
||||
stp x14,x15,[x0,296]
|
||||
stp x16,x17,[x0,312]
|
||||
stp x18,x19,[x0,328]
|
||||
stp x20,x21,[x0,344]
|
||||
stp x22,x23,[x0,360]
|
||||
stp x24,x25,[x0,376]
|
||||
stp x26,x27,[x0,392]
|
||||
stp x28,x29,[x0,408]
|
||||
str x30,[x0,424]
|
||||
mov x1,sp
|
||||
str x1,[x0,432] // sp = caller's sp
|
||||
str x30,[x0,440] // pc = caller's pc
|
||||
b __getcontext
|
||||
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
.ftrace2
|
||||
#include "libc/calls/getcontext.inc"
|
||||
jmp __getcontextsig
|
||||
.endfn getcontext,globl
|
||||
|
||||
.end
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
noasan noubsan dontinstrument int getcontext(ucontext_t *uc) {
|
||||
asm volatile("movaps\t%%xmm0,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[0]));
|
||||
asm volatile("movaps\t%%xmm1,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[1]));
|
||||
asm volatile("movaps\t%%xmm2,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[2]));
|
||||
asm volatile("movaps\t%%xmm3,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[3]));
|
||||
asm volatile("movaps\t%%xmm4,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[4]));
|
||||
asm volatile("movaps\t%%xmm5,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[5]));
|
||||
asm volatile("movaps\t%%xmm6,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[6]));
|
||||
asm volatile("movaps\t%%xmm7,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[7]));
|
||||
asm volatile("movaps\t%%xmm8,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[8]));
|
||||
asm volatile("movaps\t%%xmm9,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[9]));
|
||||
asm volatile("movaps\t%%xmm10,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[10]));
|
||||
asm volatile("movaps\t%%xmm11,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[11]));
|
||||
asm volatile("movaps\t%%xmm12,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[12]));
|
||||
asm volatile("movaps\t%%xmm13,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[13]));
|
||||
asm volatile("movaps\t%%xmm14,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[14]));
|
||||
asm volatile("movaps\t%%xmm15,%0" : /* no outputs */ : "m"(uc->__fpustate.xmm[15]));
|
||||
asm volatile("mov\t%%r8,%0" : "=m"(uc->uc_mcontext.r8));
|
||||
asm volatile("mov\t%%r9,%0" : "=m"(uc->uc_mcontext.r9));
|
||||
asm volatile("mov\t%%r10,%0" : "=m"(uc->uc_mcontext.r10));
|
||||
asm volatile("mov\t%%r11,%0" : "=m"(uc->uc_mcontext.r11));
|
||||
asm volatile("mov\t%%r12,%0" : "=m"(uc->uc_mcontext.r12));
|
||||
asm volatile("mov\t%%r13,%0" : "=m"(uc->uc_mcontext.r13));
|
||||
asm volatile("mov\t%%r14,%0" : "=m"(uc->uc_mcontext.r14));
|
||||
asm volatile("mov\t%%r15,%0" : "=m"(uc->uc_mcontext.r15));
|
||||
asm volatile("mov\t%%rdi,%0" : "=m"(uc->uc_mcontext.rdi));
|
||||
asm volatile("mov\t%%rsi,%0" : "=m"(uc->uc_mcontext.rsi));
|
||||
asm volatile("mov\t%%rbp,%0" : "=m"(uc->uc_mcontext.rbp));
|
||||
asm volatile("mov\t%%rbx,%0" : "=m"(uc->uc_mcontext.rbx));
|
||||
asm volatile("mov\t%%rdx,%0" : "=m"(uc->uc_mcontext.rdx));
|
||||
asm volatile("mov\t%%rax,%0" : "=m"(uc->uc_mcontext.rax));
|
||||
asm volatile("mov\t%%rcx,%0" : "=m"(uc->uc_mcontext.rcx));
|
||||
uc->uc_mcontext.fpregs = &uc->__fpustate;
|
||||
asm volatile("lea\t8(%%rsp),%%rax\n\t"
|
||||
"mov\t%%rax,%0"
|
||||
: "=m"(uc->uc_mcontext.rsp)
|
||||
: /* no inputs */
|
||||
: "rax");
|
||||
asm volatile("mov\t(%%rsp),%%rax\n\t"
|
||||
"mov\t%%rax,%0"
|
||||
: "=m"(uc->uc_mcontext.rip)
|
||||
: /* no inputs */
|
||||
: "rax");
|
||||
return 0;
|
||||
}
|
||||
|
||||
noasan noubsan dontinstrument int getcontext(ucontext_t *uc) {
|
||||
asm volatile("stp\tx0,x1,%0" : "=m"(uc->uc_mcontext.regs[0]));
|
||||
asm volatile("stp\tx2,x3,%0" : "=m"(uc->uc_mcontext.regs[2]));
|
||||
asm volatile("mov\tx1,sp\n\tstr\tx1,%0" : "=m"(uc->uc_mcontext.sp));
|
||||
asm volatile("str\tx30,%0" : "=m"(uc->uc_mcontext.pc));
|
||||
return 0;
|
||||
}
|
||||
|
|
89
libc/calls/getcontext.inc
Normal file
89
libc/calls/getcontext.inc
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
// @fileoverview textual include for loading processor state
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
mov %r8,40(%rdi)
|
||||
mov %r9,48(%rdi)
|
||||
mov %r10,56(%rdi)
|
||||
mov %r11,64(%rdi)
|
||||
mov %r12,72(%rdi)
|
||||
mov %r13,80(%rdi)
|
||||
mov %r14,88(%rdi)
|
||||
mov %r15,96(%rdi)
|
||||
mov %rdi,104(%rdi)
|
||||
mov %rsi,112(%rdi)
|
||||
mov %rbp,120(%rdi)
|
||||
mov %rbx,128(%rdi)
|
||||
mov %rdx,136(%rdi)
|
||||
mov %rcx,152(%rdi)
|
||||
lea 8(%rsp),%rax
|
||||
mov %rax,160(%rdi) // rsp = caller's rsp
|
||||
mov (%rsp),%rax
|
||||
mov %rax,168(%rdi) // rip = return address
|
||||
|
||||
lea 608(%rdi),%rax
|
||||
movaps %xmm0,-0x80(%rax)
|
||||
movaps %xmm1,-0x70(%rax)
|
||||
movaps %xmm2,-0x60(%rax)
|
||||
movaps %xmm3,-0x50(%rax)
|
||||
movaps %xmm4,-0x40(%rax)
|
||||
movaps %xmm5,-0x30(%rax)
|
||||
movaps %xmm6,-0x20(%rax)
|
||||
movaps %xmm7,-0x10(%rax)
|
||||
movaps %xmm8,0x00(%rax)
|
||||
movaps %xmm9,0x10(%rax)
|
||||
movaps %xmm10,0x20(%rax)
|
||||
movaps %xmm11,0x30(%rax)
|
||||
movaps %xmm12,0x40(%rax)
|
||||
movaps %xmm13,0x50(%rax)
|
||||
movaps %xmm14,0x60(%rax)
|
||||
movaps %xmm15,0x70(%rax)
|
||||
lea 320(%rdi),%rax // rax = &__fpustate
|
||||
mov %rax,224(%rdi) // fpregs = rax
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
#define REGS(i) 184+i*8
|
||||
|
||||
stp xzr,x1,[x0,REGS(0)] // x0 = 0
|
||||
stp x2,x3,[x0,REGS(2)]
|
||||
stp x4,x5,[x0,REGS(4)]
|
||||
stp x6,x7,[x0,REGS(6)]
|
||||
stp x8,x9,[x0,REGS(8)]
|
||||
stp x10,x11,[x0,REGS(10)]
|
||||
stp x12,x13,[x0,REGS(12)]
|
||||
stp x14,x15,[x0,REGS(14)]
|
||||
stp x16,x17,[x0,REGS(16)]
|
||||
stp x18,x19,[x0,REGS(18)]
|
||||
stp x20,x21,[x0,REGS(20)]
|
||||
stp x22,x23,[x0,REGS(22)]
|
||||
stp x24,x25,[x0,REGS(24)]
|
||||
stp x26,x27,[x0,REGS(26)]
|
||||
stp x28,x29,[x0,REGS(28)]
|
||||
str x30,[x0,REGS(30)]
|
||||
mov x15,sp
|
||||
stp x15,x30,[x0,REGS(31)] // sp, pc = caller sp, ret address
|
||||
str xzr,[x0,448] // pstate = 0
|
||||
str xzr,[x0,456] // no vectors yet
|
||||
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
|
@ -1,136 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// tailed called by setcontext() implementation
|
||||
__setcontext:
|
||||
#ifdef __x86_64__
|
||||
|
||||
mov 224(%rdi),%rax
|
||||
test %rax,%rax
|
||||
je 1f
|
||||
movaps 160(%rax),%xmm0
|
||||
movaps 176(%rax),%xmm1
|
||||
movaps 192(%rax),%xmm2
|
||||
movaps 208(%rax),%xmm3
|
||||
movaps 224(%rax),%xmm4
|
||||
movaps 240(%rax),%xmm5
|
||||
movaps 256(%rax),%xmm6
|
||||
movaps 272(%rax),%xmm7
|
||||
movaps 288(%rax),%xmm8
|
||||
movaps 304(%rax),%xmm9
|
||||
movaps 320(%rax),%xmm10
|
||||
movaps 336(%rax),%xmm11
|
||||
movaps 352(%rax),%xmm12
|
||||
movaps 368(%rax),%xmm13
|
||||
movaps 384(%rax),%xmm14
|
||||
movaps 400(%rax),%xmm15
|
||||
1: push 176(%rdi)
|
||||
popf
|
||||
mov %rsi,%rsp
|
||||
mov 40(%rdi),%r8
|
||||
mov 48(%rdi),%r9
|
||||
mov 56(%rdi),%r10
|
||||
mov 64(%rdi),%r11
|
||||
mov 72(%rdi),%r12
|
||||
mov 80(%rdi),%r13
|
||||
mov 88(%rdi),%r14
|
||||
mov 96(%rdi),%r15
|
||||
mov 112(%rdi),%rsi
|
||||
mov 120(%rdi),%rbp
|
||||
mov 128(%rdi),%rbx
|
||||
mov 136(%rdi),%rdx
|
||||
mov 144(%rdi),%rax
|
||||
mov 152(%rdi),%rcx
|
||||
xor %rax,%rax
|
||||
push 168(%rdi)
|
||||
mov 104(%rdi),%rdi
|
||||
ret
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
mov sp,x1 // sp = second argument
|
||||
ldr x30,[x0,440] // return address <- pc
|
||||
ldp x28,x29,[x0,408] // x0 and x30 discarded
|
||||
ldp x26,x27,[x0,392]
|
||||
ldp x24,x25,[x0,376]
|
||||
ldp x22,x23,[x0,360]
|
||||
ldp x20,x21,[x0,344]
|
||||
ldp x18,x19,[x0,328]
|
||||
ldp x16,x17,[x0,312]
|
||||
ldp x14,x15,[x0,296]
|
||||
ldp x12,x13,[x0,280]
|
||||
ldp x10,x11,[x0,264]
|
||||
ldp x8,x9,[x0,248]
|
||||
ldp x6,x7,[x0,232]
|
||||
ldp x4,x5,[x0,216]
|
||||
ldp x2,x3,[x0,200]
|
||||
ldr x1,[x0,192]
|
||||
mov w0,0
|
||||
ret
|
||||
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
.endfn __setcontext,globl
|
||||
|
||||
.end
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
noasan noubsan int __setcontext(const ucontext_t *uc) {
|
||||
if (uc->uc_mcontext.fpregs) {
|
||||
asm volatile("movaps\t%0,%%xmm0" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[0]));
|
||||
asm volatile("movaps\t%0,%%xmm1" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[1]));
|
||||
asm volatile("movaps\t%0,%%xmm2" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[2]));
|
||||
asm volatile("movaps\t%0,%%xmm3" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[3]));
|
||||
asm volatile("movaps\t%0,%%xmm4" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[4]));
|
||||
asm volatile("movaps\t%0,%%xmm5" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[5]));
|
||||
asm volatile("movaps\t%0,%%xmm6" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[6]));
|
||||
asm volatile("movaps\t%0,%%xmm7" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[7]));
|
||||
asm volatile("movaps\t%0,%%xmm8" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[8]));
|
||||
asm volatile("movaps\t%0,%%xmm9" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[9]));
|
||||
asm volatile("movaps\t%0,%%xmm10" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[10]));
|
||||
asm volatile("movaps\t%0,%%xmm11" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[11]));
|
||||
asm volatile("movaps\t%0,%%xmm12" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[12]));
|
||||
asm volatile("movaps\t%0,%%xmm13" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[13]));
|
||||
asm volatile("movaps\t%0,%%xmm14" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[14]));
|
||||
asm volatile("movaps\t%0,%%xmm15" : /* no outputs */ : "m"(uc->uc_mcontext.fpregs->xmm[15]));
|
||||
}
|
||||
asm volatile("mov\t%0,%%r8" : /* no outputs */ : "m"(uc->uc_mcontext.r8));
|
||||
asm volatile("mov\t%0,%%r9" : /* no outputs */ : "m"(uc->uc_mcontext.r9));
|
||||
asm volatile("mov\t%0,%%r10" : /* no outputs */ : "m"(uc->uc_mcontext.r10));
|
||||
asm volatile("mov\t%0,%%r11" : /* no outputs */ : "m"(uc->uc_mcontext.r11));
|
||||
asm volatile("mov\t%0,%%r12" : /* no outputs */ : "m"(uc->uc_mcontext.r12));
|
||||
asm volatile("mov\t%0,%%r13" : /* no outputs */ : "m"(uc->uc_mcontext.r13));
|
||||
asm volatile("mov\t%0,%%r14" : /* no outputs */ : "m"(uc->uc_mcontext.r14));
|
||||
asm volatile("mov\t%0,%%r15" : /* no outputs */ : "m"(uc->uc_mcontext.r15));
|
||||
asm volatile("mov\t%0,%%rsi" : /* no outputs */ : "m"(uc->uc_mcontext.rsi));
|
||||
asm volatile("mov\t%0,%%rbp" : /* no outputs */ : "m"(uc->uc_mcontext.rbp));
|
||||
asm volatile("mov\t%0,%%rbx" : /* no outputs */ : "m"(uc->uc_mcontext.rbx));
|
||||
asm volatile("mov\t%0,%%rdx" : /* no outputs */ : "m"(uc->uc_mcontext.rdx));
|
||||
asm volatile("mov\t%0,%%rax" : /* no outputs */ : "m"(uc->uc_mcontext.rax));
|
||||
asm volatile("mov\t%0,%%rcx" : /* no outputs */ : "m"(uc->uc_mcontext.rcx));
|
||||
asm volatile("mov\t%0,%%rsp" : /* no outputs */ : "m"(uc->uc_mcontext.rsp));
|
||||
asm volatile("xor\t%%rax,%%rax\n\t"
|
||||
"push\t%0\n\t"
|
||||
"mov\t%1,%%rdi\n\t"
|
||||
"ret"
|
||||
: /* no outputs */
|
||||
: "m"(uc->uc_mcontext.rip), "m"(uc->uc_mcontext.rdi));
|
||||
__builtin_unreachable();
|
||||
}
|
|
@ -6,9 +6,25 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define SP rsp
|
||||
#define PC rip
|
||||
#define SP rsp
|
||||
#define BP rbp
|
||||
#define ARG0 rdi
|
||||
#define ARG1 rsi
|
||||
#define ARG2 rdx
|
||||
#define ARG3 rcx
|
||||
#define ARG4 r8
|
||||
#define ARG5 r9
|
||||
#elif defined(__aarch64__)
|
||||
#define SP sp
|
||||
#define PC pc
|
||||
#define SP sp
|
||||
#define BP regs[29]
|
||||
#define ARG0 regs[0]
|
||||
#define ARG1 regs[1]
|
||||
#define ARG2 regs[2]
|
||||
#define ARG3 regs[3]
|
||||
#define ARG4 regs[4]
|
||||
#define ARG5 regs[5]
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,19 +16,45 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/ucontext.internal.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/ss.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// this is tail called by the getcontext() implementation
|
||||
int __getcontext(ucontext_t *uc) {
|
||||
uc->uc_flags = 0;
|
||||
uc->uc_link = 0;
|
||||
uc->uc_stack.ss_sp = (void *)uc->uc_mcontext.SP;
|
||||
uc->uc_stack.ss_flags = SS_ONSTACK;
|
||||
uc->uc_stack.ss_size = uc->uc_mcontext.SP - GetStackAddr();
|
||||
return sigprocmask(SIG_SETMASK, 0, &uc->uc_sigmask);
|
||||
}
|
||||
// Saves machine to 𝑥 and activates 𝑦, i.e.
|
||||
//
|
||||
// getcontext(x);
|
||||
// setcontext(y);
|
||||
//
|
||||
// Except using this API is safer and goes 2x faster:
|
||||
//
|
||||
// swapcontext(x, y);
|
||||
//
|
||||
// @return 0 on success, or -1 w/ errno
|
||||
// @returnstwice
|
||||
// @threadsafe
|
||||
.ftrace1
|
||||
swapcontext:
|
||||
.ftrace2
|
||||
#include "libc/calls/getcontext.inc"
|
||||
#ifdef __x86_64__
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
push %rsi
|
||||
push %rsi
|
||||
call __swapcontextsig
|
||||
pop %rdi
|
||||
pop %rdi
|
||||
pop %rbp
|
||||
test %eax,%eax
|
||||
jnz 1f
|
||||
#elif defined(__aarch64__)
|
||||
stp x29,x30,[sp,#-32]!
|
||||
mov x29,sp
|
||||
str x1,[sp,16]
|
||||
bl __swapcontextsig
|
||||
ldr x1,[sp,16]
|
||||
ldp x29,x30,[sp],#32
|
||||
cbnz w0,1f
|
||||
mov x0,x1
|
||||
#endif
|
||||
jmp __tailcontext
|
||||
1: ret
|
||||
.endfn swapcontext,globl
|
89
libc/calls/tailcontext.S
Normal file
89
libc/calls/tailcontext.S
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// tailed called by setcontext() implementation
|
||||
__tailcontext:
|
||||
#ifdef __x86_64__
|
||||
|
||||
lea 608(%rdi),%rax
|
||||
movaps -0x80(%rax),%xmm0
|
||||
movaps -0x70(%rax),%xmm1
|
||||
movaps -0x60(%rax),%xmm2
|
||||
movaps -0x50(%rax),%xmm3
|
||||
movaps -0x40(%rax),%xmm4
|
||||
movaps -0x30(%rax),%xmm5
|
||||
movaps -0x20(%rax),%xmm6
|
||||
movaps -0x10(%rax),%xmm7
|
||||
movaps 0x00(%rax),%xmm8
|
||||
movaps 0x10(%rax),%xmm9
|
||||
movaps 0x20(%rax),%xmm10
|
||||
movaps 0x30(%rax),%xmm11
|
||||
movaps 0x40(%rax),%xmm12
|
||||
movaps 0x50(%rax),%xmm13
|
||||
movaps 0x60(%rax),%xmm14
|
||||
movaps 0x70(%rax),%xmm15
|
||||
|
||||
mov 40(%rdi),%r8
|
||||
mov 48(%rdi),%r9
|
||||
mov 56(%rdi),%r10
|
||||
mov 64(%rdi),%r11
|
||||
mov 72(%rdi),%r12
|
||||
mov 80(%rdi),%r13
|
||||
mov 88(%rdi),%r14
|
||||
mov 96(%rdi),%r15
|
||||
mov 112(%rdi),%rsi
|
||||
mov 120(%rdi),%rbp
|
||||
mov 128(%rdi),%rbx
|
||||
mov 136(%rdi),%rdx
|
||||
mov 152(%rdi),%rcx
|
||||
mov 160(%rdi),%rsp
|
||||
push 168(%rdi)
|
||||
mov 104(%rdi),%rdi
|
||||
|
||||
xor %eax,%eax
|
||||
ret
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
#define REGS(i) 184+i*8
|
||||
|
||||
ldp x1,x16,[x0,REGS(31)] // sp, pc
|
||||
mov sp,x1
|
||||
ldr x30,[x0,REGS(30)]
|
||||
ldp x28,x29,[x0,REGS(28)]
|
||||
ldp x26,x27,[x0,REGS(26)]
|
||||
ldp x24,x25,[x0,REGS(24)]
|
||||
ldp x22,x23,[x0,REGS(22)]
|
||||
ldp x20,x21,[x0,REGS(20)]
|
||||
ldp x18,x19,[x0,REGS(18)]
|
||||
ldr x17,[x0,REGS(17)]
|
||||
ldp x14,x15,[x0,REGS(14)]
|
||||
ldp x12,x13,[x0,REGS(12)]
|
||||
ldp x10,x11,[x0,REGS(10)]
|
||||
ldp x8,x9,[x0,REGS(8)]
|
||||
ldp x6,x7,[x0,REGS(6)]
|
||||
ldp x4,x5,[x0,REGS(4)]
|
||||
ldp x2,x3,[x0,REGS(2)]
|
||||
ldp x0,x1,[x0,REGS(0)]
|
||||
br x16
|
||||
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
.endfn __tailcontext,globl
|
|
@ -16,26 +16,30 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/ucontext.internal.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/ss.h"
|
||||
|
||||
int __setcontext(const ucontext_t *, uintptr_t);
|
||||
int __tailcontext(const ucontext_t *);
|
||||
|
||||
/**
|
||||
* Sets machine context.
|
||||
*
|
||||
* @return -1 on error w/ errno, otherwise won't return unless sent back
|
||||
* @see swapcontext()
|
||||
* @see makecontext()
|
||||
* @see getcontext()
|
||||
* @threadsafe
|
||||
*/
|
||||
int setcontext(const ucontext_t *uc) {
|
||||
uintptr_t sp;
|
||||
if (sigprocmask(SIG_SETMASK, &uc->uc_sigmask, 0)) return -1;
|
||||
if (uc->uc_stack.ss_flags & (SS_DISABLE | SS_ONSTACK)) {
|
||||
sp = uc->uc_mcontext.SP;
|
||||
} else {
|
||||
sp = (uintptr_t)uc->uc_stack.ss_sp & -16;
|
||||
}
|
||||
return __setcontext(uc, sp);
|
||||
return __tailcontext(uc);
|
||||
}
|
||||
|
||||
int __getcontextsig(ucontext_t *uc) {
|
||||
return sigprocmask(SIG_SETMASK, 0, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
int __swapcontextsig(ucontext_t *x, const ucontext_t *y) {
|
||||
return sigprocmask(SIG_SETMASK, &y->uc_sigmask, &x->uc_sigmask);
|
||||
}
|
|
@ -41,24 +41,24 @@ struct sigcontext {
|
|||
#ifdef __x86_64__
|
||||
union {
|
||||
struct {
|
||||
uint64_t r8;
|
||||
uint64_t r9;
|
||||
uint64_t r10;
|
||||
uint64_t r11;
|
||||
uint64_t r12;
|
||||
uint64_t r13;
|
||||
uint64_t r14;
|
||||
uint64_t r15;
|
||||
uint64_t rdi;
|
||||
uint64_t rsi;
|
||||
uint64_t rbp;
|
||||
uint64_t rbx;
|
||||
uint64_t rdx;
|
||||
uint64_t rax;
|
||||
uint64_t rcx;
|
||||
uint64_t rsp;
|
||||
uint64_t rip;
|
||||
uint64_t eflags;
|
||||
uint64_t r8; /* 40 */
|
||||
uint64_t r9; /* 48 */
|
||||
uint64_t r10; /* 56 */
|
||||
uint64_t r11; /* 64 */
|
||||
uint64_t r12; /* 72 */
|
||||
uint64_t r13; /* 80 */
|
||||
uint64_t r14; /* 88 */
|
||||
uint64_t r15; /* 96 */
|
||||
uint64_t rdi; /* 104 */
|
||||
uint64_t rsi; /* 112 */
|
||||
uint64_t rbp; /* 120 */
|
||||
uint64_t rbx; /* 128 */
|
||||
uint64_t rdx; /* 136 */
|
||||
uint64_t rax; /* 144 */
|
||||
uint64_t rcx; /* 152 */
|
||||
uint64_t rsp; /* 160 */
|
||||
uint64_t rip; /* 168 */
|
||||
uint64_t eflags; /* 176 */
|
||||
uint16_t cs;
|
||||
uint16_t gs;
|
||||
uint16_t fs;
|
||||
|
@ -102,8 +102,10 @@ struct ucontext {
|
|||
|
||||
typedef struct ucontext ucontext_t;
|
||||
|
||||
int getcontext(ucontext_t *);
|
||||
int setcontext(const ucontext_t *);
|
||||
int getcontext(ucontext_t *) dontthrow;
|
||||
int setcontext(const ucontext_t *) dontthrow;
|
||||
int swapcontext(ucontext_t *, const ucontext_t *) dontthrow returnstwice;
|
||||
void makecontext(ucontext_t *, void (*)(), int, ...) dontthrow nocallback;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
#include "libc/calls/struct/ucontext.internal.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/intrin/describebacktrace.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/exceptionhandleractions.h"
|
||||
#include "libc/nt/enum/signal.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -90,6 +90,10 @@ unsigned __wincrash(struct NtExceptionPointers *ep) {
|
|||
code = SI_USER;
|
||||
sig = SIGABRT;
|
||||
break;
|
||||
case kNtStatusIntegerOverflow:
|
||||
code = FPE_INTOVF;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case kNtSignalFltDivideByZero:
|
||||
code = FPE_FLTDIV;
|
||||
sig = SIGFPE;
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_WINERR_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_WINERR_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_WINERR_INTERNAL_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue