[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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
18
libc/include/llvm-libc-types/mcontext_t.h
Normal file
18
libc/include/llvm-libc-types/mcontext_t.h
Normal 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
|
||||
18
libc/include/llvm-libc-types/ucontext_t.h
Normal file
18
libc/include/llvm-libc-types/ucontext_t.h
Normal 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
|
||||
121
libc/include/llvm-libc-types/x86_64/mcontext_t.h
Normal file
121
libc/include/llvm-libc-types/x86_64/mcontext_t.h
Normal 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
|
||||
43
libc/include/llvm-libc-types/x86_64/ucontext_t.h
Normal file
43
libc/include/llvm-libc-types/x86_64/ucontext_t.h
Normal 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
|
||||
16
libc/include/ucontext.h.def
Normal file
16
libc/include/ucontext.h.def
Normal 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
|
||||
37
libc/include/ucontext.yaml
Normal file
37
libc/include/ucontext.yaml
Normal 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
|
||||
Reference in New Issue
Block a user