[libc-commits] [libc] [libc] Implement getcontext and setcontext for x86_64 (PR #192343)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Thu Apr 16 01:16:01 PDT 2026


================
@@ -0,0 +1,97 @@
+//===-- Implementation of getcontext for x86_64 ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/ucontext/getcontext.h"
+#include "include/llvm-libc-types/ucontext_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+#include "hdr/types/size_t.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// We use naked because we need to capture the exact register state
+// at the moment of the function call, avoiding any compiler prologue/epilogue.
+__attribute__((naked)) LLVM_LIBC_FUNCTION(int, getcontext, (ucontext_t * ucp)) {
+  asm(R"(
+      # ucp is in rdi
+      
+      # Save general purpose registers
+      mov %%r8, %c[r8](%%rdi)
+      mov %%r9, %c[r9](%%rdi)
+      mov %%r10, %c[r10](%%rdi)
+      mov %%r11, %c[r11](%%rdi)
+      mov %%r12, %c[r12](%%rdi)
+      mov %%r13, %c[r13](%%rdi)
+      mov %%r14, %c[r14](%%rdi)
+      mov %%r15, %c[r15](%%rdi)
+      mov %%rdi, %c[rdi](%%rdi)
+      mov %%rsi, %c[rsi](%%rdi)
+      mov %%rbp, %c[rbp](%%rdi)
+      mov %%rbx, %c[rbx](%%rdi)
+      mov %%rdx, %c[rdx](%%rdi)
+      # getcontext should return 0 when resumed by setcontext.
+      # So we save 0 into the RAX register of the context.
+      movq $0, %c[rax](%%rdi)
+      mov %%rcx, %c[rcx](%%rdi)
+
+      # The stack pointer before the call is rsp + sizeof(void*).
+      # The return address was pushed when this function was called.
+      # Save instruction pointer and stack pointer
+      mov (%%rsp), %%rax
+      mov %%rax, %c[rip](%%rdi)
+      lea %c[ret_size](%%rsp), %%rax
+      mov %%rax, %c[rsp](%%rdi)
+
+      # Save floating point state
+      fxsaveq %c[fpregs_mem](%%rdi)
+      # Point mcontext.fpregs to our internal FP storage
+      lea %c[fpregs_mem](%%rdi), %%rax
+      mov %%rax, %c[fpregs_ptr](%%rdi)
+
+      # Capture the signal mask using rt_sigprocmask syscall.
+      # rt_sigprocmask(SIG_BLOCK, NULL, &ucp->uc_sigmask, sizeof(sigset_t))
+      leaq %c[sigmask](%%rdi), %%rdx # oldset = &ucp->uc_sigmask
+      xorq %%rsi, %%rsi # set = NULL
+      movq $0, %%rdi # SIG_BLOCK (captured mask in oldset)
----------------
labath wrote:

Maybe make this a constant as well.

https://github.com/llvm/llvm-project/pull/192343


More information about the libc-commits mailing list