[libc] Add ucontext types and headers (#191789)

Added mcontext_t and ucontext_t types for x86_64 Linux, and the
ucontext.h header definition. Used a dispatcher pattern for mcontext_t
and ucontext_t to support future architecture ports, mirroring the
pattern used in FPUtil.

Definitions are based on the Linux kernel ABI for x86_64.

Co-authored-by: Pavel Labath <pavel@labath.sk>
This commit is contained in:
Jeff Bailey
2026-04-14 13:52:36 +01:00
committed by GitHub
parent 224c429e85
commit d8c95e6ea4
8 changed files with 292 additions and 0 deletions

View File

@@ -461,6 +461,20 @@ add_header_macro(
.llvm_libc_common_h
)
if(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64")
add_header_macro(
ucontext
../libc/include/ucontext.yaml
ucontext.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.mcontext_t
.llvm-libc-types.ucontext_t
.llvm-libc-types.sigset_t
.llvm-libc-types.stack_t
)
endif()
add_header_macro(
sched
../libc/include/sched.yaml

View File

@@ -126,6 +126,31 @@ add_header(union_sigval HDR union_sigval.h)
add_header(siginfo_t HDR siginfo_t.h DEPENDS .union_sigval .pid_t .uid_t .clock_t)
add_header(sig_atomic_t HDR sig_atomic_t.h)
add_header(sigset_t HDR sigset_t.h DEPENDS libc.include.llvm-libc-macros.signal_macros)
set(mcontext_deps)
set(ucontext_deps .sigset_t .stack_t)
if(LIBC_TARGET_ARCHITECTURE STREQUAL "x86_64")
file(COPY x86_64 DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_header(
mcontext_t_arch
HDR
x86_64/mcontext_t.h
)
add_header(
ucontext_t_arch
HDR
x86_64/ucontext_t.h
DEPENDS
.mcontext_t_arch
.sigset_t
.stack_t
)
list(APPEND mcontext_deps .mcontext_t_arch)
list(APPEND ucontext_deps .ucontext_t_arch)
endif()
add_header(mcontext_t HDR mcontext_t.h DEPENDS ${mcontext_deps})
add_header(ucontext_t HDR ucontext_t.h DEPENDS .mcontext_t ${ucontext_deps})
add_header(__jmp_buf HDR __jmp_buf.h DEPENDS .sigset_t)
add_header(jmp_buf HDR jmp_buf.h DEPENDS .__jmp_buf)
add_header(sigjmp_buf HDR sigjmp_buf.h DEPENDS .__jmp_buf)

View File

@@ -0,0 +1,18 @@
//===-- Definition of type mcontext_t -------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_TYPES_MCONTEXT_T_H
#define LLVM_LIBC_TYPES_MCONTEXT_T_H
#if defined(__x86_64__)
#include "x86_64/mcontext_t.h"
#else
#error "mcontext_t not available for your target architecture."
#endif
#endif // LLVM_LIBC_TYPES_MCONTEXT_T_H

View File

@@ -0,0 +1,18 @@
//===-- Definition of type ucontext_t -------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_TYPES_UCONTEXT_T_H
#define LLVM_LIBC_TYPES_UCONTEXT_T_H
#if defined(__x86_64__)
#include "x86_64/ucontext_t.h"
#else
#error "ucontext_t not available for your target architecture."
#endif
#endif // LLVM_LIBC_TYPES_UCONTEXT_T_H

View File

@@ -0,0 +1,121 @@
//===-- Definition of type mcontext_t -------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// Note: Definitions in this file are based on the Linux kernel ABI.
#ifndef LLVM_LIBC_TYPES_MCONTEXT_T_H
#define LLVM_LIBC_TYPES_MCONTEXT_T_H
// The following definitions correspond to the general purpose registers.
// The layout of gregset_t and the enum indices must match the layout of
// 'struct sigcontext' in the Linux kernel on x86_64 (see
// arch/x86/include/uapi/asm/sigcontext.h). The kernel uses named fields
// (like r8, r9) while we use an array indexed by these enum values.
//
// Note: The kernel defines segment registers (cs, gs, fs, ss) as four
// separate 16-bit fields. In our flat 64-bit array representation, they
// are packed into a single 64-bit slot at index REG_CSGSFS, occupying
// the exact same 8 bytes of memory.
typedef long long int greg_t;
typedef greg_t gregset_t[23];
enum {
REG_R8 = 0,
#define REG_R8 REG_R8
REG_R9,
#define REG_R9 REG_R9
REG_R10,
#define REG_R10 REG_R10
REG_R11,
#define REG_R11 REG_R11
REG_R12,
#define REG_R12 REG_R12
REG_R13,
#define REG_R13 REG_R13
REG_R14,
#define REG_R14 REG_R14
REG_R15,
#define REG_R15 REG_R15
REG_RDI,
#define REG_RDI REG_RDI
REG_RSI,
#define REG_RSI REG_RSI
REG_RBP,
#define REG_RBP REG_RBP
REG_RBX,
#define REG_RBX REG_RBX
REG_RDX,
#define REG_RDX REG_RDX
REG_RAX,
#define REG_RAX REG_RAX
REG_RCX,
#define REG_RCX REG_RCX
REG_RSP,
#define REG_RSP REG_RSP
REG_RIP,
#define REG_RIP REG_RIP
REG_EFL,
#define REG_EFL REG_EFL
REG_CSGSFS,
#define REG_CSGSFS REG_CSGSFS
REG_ERR,
#define REG_ERR REG_ERR
REG_TRAPNO,
#define REG_TRAPNO REG_TRAPNO
REG_OLDMASK,
#define REG_OLDMASK REG_OLDMASK
REG_CR2
#define REG_CR2 REG_CR2
};
// The following structures (_libc_fpxreg, _libc_xmmreg, _libc_fpstate)
// represent the floating-point state and must match the layout used by the
// x86 FXSAVE instruction and the kernel's 'struct _fpstate' (see
// arch/x86/include/uapi/asm/sigcontext.h).
struct _libc_fpxreg {
unsigned short significand[4];
unsigned short exponent;
unsigned short padding[3];
};
struct _libc_xmmreg {
unsigned int element[4];
};
// Note: The kernel's 'struct _fpstate' uses flat arrays like 'st_space[32]'
// and 'xmm_space[64]'. We use structured arrays '_st[8]' and '_xmm[16]'
// instead to allow focused access, but the memory layout and total sizes
// (128 bytes for _st and 256 bytes for _xmm) are identical to FXSAVE.
struct _libc_fpstate {
unsigned short cwd;
unsigned short swd;
unsigned short ftw; // Maps to 'twd' (Tag Word) in the kernel's _fpstate.
unsigned short fop;
unsigned long long rip;
unsigned long long rdp;
unsigned int mxcsr;
unsigned int mxcr_mask;
struct _libc_fpxreg _st[8];
struct _libc_xmmreg _xmm[16];
unsigned int padding[24];
};
// fpregset_t is the type used to represent the floating-point register set.
// On x86_64, this is defined as a pointer to the state structure, matching
// the 'fpstate' pointer in the kernel's sigcontext.
typedef struct _libc_fpstate *fpregset_t;
// mcontext_t represents the machine state. This structure must match the
// layout of 'struct sigcontext' in the Linux kernel on x86_64.
typedef struct {
gregset_t gregs;
fpregset_t fpregs;
unsigned long long __reserved1[8];
} mcontext_t;
#endif // LLVM_LIBC_TYPES_MCONTEXT_T_H

View File

@@ -0,0 +1,43 @@
//===-- Definition of type ucontext_t -------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// Note: Definitions in this file are based on the Linux kernel ABI.
#ifndef LLVM_LIBC_TYPES_UCONTEXT_T_H
#define LLVM_LIBC_TYPES_UCONTEXT_T_H
#include "../sigset_t.h"
#include "../stack_t.h"
#include "mcontext_t.h"
typedef struct alignas(16) ucontext_t {
// The following fields must match the Linux kernel's struct ucontext
// on x86_64 to ensure ABI compatibility for signal handling.
unsigned long uc_flags;
struct ucontext_t *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
sigset_t uc_sigmask;
// Additional fields appended by the C library. These are not part of the
// kernel's struct ucontext, but are needed for user-space context management.
// Since they are at the end, they do not break ABI compatibility with the
// kernel.
// On x86_64, uc_mcontext contains a pointer to the floating point state
// rather than the state itself. To make ucontext_t self-contained, we
// provide space here for the FP state, and the pointer in uc_mcontext
// can be set to point here. 64 long ints provide 512 bytes, which is
// the size required for FXSAVE.
alignas(16) long int __fpregs_mem[64];
// Support for Shadow Stack Pointer (Intel CET).
unsigned long long __ssp[4];
} ucontext_t;
#endif // LLVM_LIBC_TYPES_UCONTEXT_T_H

View File

@@ -0,0 +1,16 @@
//===-- POSIX header ucontext.h --------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_UCONTEXT_H
#define LLVM_LIBC_UCONTEXT_H
#include "__llvm-libc-common.h"
%%public_api()
#endif // LLVM_LIBC_UCONTEXT_H

View File

@@ -0,0 +1,37 @@
header: ucontext.h
standards:
- posix
types:
- type_name: mcontext_t
- type_name: ucontext_t
- type_name: sigset_t
- type_name: stack_t
functions:
- name: getcontext
standards:
- posix
return_type: int
arguments:
- type: ucontext_t *
- name: setcontext
standards:
- posix
return_type: int
arguments:
- type: const ucontext_t *
- name: makecontext
standards:
- posix
return_type: void
arguments:
- type: ucontext_t *
- type: void(*)(void)
- type: int
- type: ...
- name: swapcontext
standards:
- posix
return_type: int
arguments:
- type: ucontext_t *__restrict
- type: const ucontext_t *__restrict