| ... | @@ -395,3 +395,71 @@ pub const ucontext_t = extern struct { | ... | @@ -395,3 +395,71 @@ pub const ucontext_t = extern struct { |
| 395 | sigmask: sigset_t, | 395 | sigmask: sigset_t, |
| 396 | fpregs_mem: [64]usize, | 396 | fpregs_mem: [64]usize, |
| 397 | }; | 397 | }; |
| | 398 | |
| | 399 | fn gpRegisterOffset(comptime reg_index: comptime_int) usize { |
| | 400 | return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index; |
| | 401 | } |
| | 402 | |
| | 403 | pub inline fn getcontext(context: *ucontext_t) usize { |
| | 404 | asm volatile ( |
| | 405 | \\ movq %%r8, (%[r8_offset])(%[context]) |
| | 406 | \\ movq %%r9, (%[r9_offset])(%[context]) |
| | 407 | \\ movq %%r10, (%[r10_offset])(%[context]) |
| | 408 | \\ movq %%r11, (%[r11_offset])(%[context]) |
| | 409 | \\ movq %%r12, (%[r12_offset])(%[context]) |
| | 410 | \\ movq %%r13, (%[r13_offset])(%[context]) |
| | 411 | \\ movq %%r14, (%[r14_offset])(%[context]) |
| | 412 | \\ movq %%r15, (%[r15_offset])(%[context]) |
| | 413 | \\ movq %%rdi, (%[rdi_offset])(%[context]) |
| | 414 | \\ movq %%rsi, (%[rsi_offset])(%[context]) |
| | 415 | \\ movq %%rbp, (%[rbp_offset])(%[context]) |
| | 416 | \\ movq %%rbx, (%[rbx_offset])(%[context]) |
| | 417 | \\ movq %%rdx, (%[rdx_offset])(%[context]) |
| | 418 | \\ movq %%rax, (%[rax_offset])(%[context]) |
| | 419 | \\ movq %%rcx, (%[rcx_offset])(%[context]) |
| | 420 | \\ movq %%rsp, (%[rsp_offset])(%[context]) |
| | 421 | \\ leaq (%%rip), %%rcx |
| | 422 | \\ movq %%rcx, (%[rip_offset])(%[context]) |
| | 423 | \\ pushfq |
| | 424 | \\ popq (%[efl_offset])(%[context]) |
| | 425 | \\ leaq (%[fpmem_offset])(%[context]), %%rcx |
| | 426 | \\ movq %%rcx, (%[fpstate_offset])(%[context]) |
| | 427 | \\ fnstenv (%%rcx) |
| | 428 | \\ stmxcsr (%[mxcsr_offset])(%[context]) |
| | 429 | : |
| | 430 | : [context] "{rdi}" (context), |
| | 431 | [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)), |
| | 432 | [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)), |
| | 433 | [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)), |
| | 434 | [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)), |
| | 435 | [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)), |
| | 436 | [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)), |
| | 437 | [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)), |
| | 438 | [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)), |
| | 439 | [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)), |
| | 440 | [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)), |
| | 441 | [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)), |
| | 442 | [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)), |
| | 443 | [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)), |
| | 444 | [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)), |
| | 445 | [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)), |
| | 446 | [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)), |
| | 447 | [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)), |
| | 448 | [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)), |
| | 449 | [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), |
| | 450 | [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")), |
| | 451 | [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")), |
| | 452 | : "memory", "rcx" |
| | 453 | ); |
| | 454 | |
| | 455 | // TODO: Read GS/FS registers? |
| | 456 | |
| | 457 | // TODO: `flags` isn't present in the getcontext man page, figure out what to write here |
| | 458 | context.flags = 0; |
| | 459 | context.link = null; |
| | 460 | |
| | 461 | const altstack_result = linux.sigaltstack(null, &context.stack); |
| | 462 | if (altstack_result != 0) return altstack_result; |
| | 463 | |
| | 464 | return linux.sigprocmask(0, null, &context.sigmask); |
| | 465 | } |