| ... | ... | @@ -395,3 +395,71 @@ pub const ucontext_t = extern struct { |
| 395 | 395 | sigmask: sigset_t, |
| 396 | 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 | } |