cosmopolitan/libc/calls/ucontext.h
Justine Tunney f4f4caab0e Add x86_64-linux-gnu emulator
I wanted a tiny scriptable meltdown proof way to run userspace programs
and visualize how program execution impacts memory. It helps to explain
how things like Actually Portable Executable works. It can show you how
the GCC generated code is going about manipulating matrices and more. I
didn't feel fully comfortable with Qemu and Bochs because I'm not smart
enough to understand them. I wanted something like gVisor but with much
stronger levels of assurances. I wanted a single binary that'll run, on
all major operating systems with an embedded GPL barrier ZIP filesystem
that is tiny enough to transpile to JavaScript and run in browsers too.

https://justine.storage.googleapis.com/emulator625.mp4
2020-08-25 04:43:42 -07:00

157 lines
3.5 KiB
C

#ifndef COSMOPOLITAN_LIBC_CALLS_UCONTEXT_H_
#define COSMOPOLITAN_LIBC_CALLS_UCONTEXT_H_
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaltstack.h"
#include "libc/calls/struct/sigset.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define REG_R8 REG_R8
#define REG_R9 REG_R9
#define REG_R10 REG_R10
#define REG_R11 REG_R11
#define REG_R12 REG_R12
#define REG_R13 REG_R13
#define REG_R14 REG_R14
#define REG_R15 REG_R15
#define REG_RDI REG_RDI
#define REG_RSI REG_RSI
#define REG_RBP REG_RBP
#define REG_RBX REG_RBX
#define REG_RDX REG_RDX
#define REG_RAX REG_RAX
#define REG_RCX REG_RCX
#define REG_RSP REG_RSP
#define REG_RIP REG_RIP
#define REG_EFL REG_EFL
#define REG_CSGSFS REG_CSGSFS
#define REG_ERR REG_ERR
#define REG_TRAPNO REG_TRAPNO
#define REG_OLDMASK REG_OLDMASK
#define REG_CR2 REG_CR2
enum GeneralRegister {
REG_R8,
REG_R9,
REG_R10,
REG_R11,
REG_R12,
REG_R13,
REG_R14,
REG_R15,
REG_RDI,
REG_RSI,
REG_RBP,
REG_RBX,
REG_RDX,
REG_RAX,
REG_RCX,
REG_RSP,
REG_RIP,
REG_EFL,
REG_CSGSFS,
REG_ERR,
REG_TRAPNO,
REG_OLDMASK,
REG_CR2
};
struct XmmRegister {
uint64_t u64[2];
};
struct FpuStackEntry {
uint16_t significand[4];
uint16_t exponent;
uint16_t padding[3];
};
struct FpuState {
uint16_t cwd;
uint16_t swd;
uint16_t ftw;
uint16_t fop;
uint64_t rip;
uint64_t rdp;
uint32_t mxcsr;
uint32_t mxcr_mask;
struct FpuStackEntry st[8];
struct XmmRegister xmm[16];
uint32_t __padding[24];
};
typedef uint64_t greg_t;
typedef greg_t gregset_t[23];
typedef struct FpuState *fpregset_t;
struct MachineContext {
union {
struct {
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rdi;
uint64_t rsi;
uint64_t rbp;
uint64_t rbx;
uint64_t rdx;
uint64_t rax;
uint64_t rcx;
uint64_t rsp;
uint64_t rip;
uint64_t eflags;
uint16_t cs;
uint16_t gs;
uint16_t fs;
uint16_t __pad0;
uint64_t err;
uint64_t trapno;
uint64_t oldmask;
uint64_t cr2;
};
gregset_t gregs;
};
struct FpuState *fpregs;
uint64_t __pad1[8];
};
typedef struct MachineContext mcontext_t;
struct ucontext {
union {
uint64_t uc_flags;
struct {
unsigned cf : 1; /* bit 0: carry flag */
unsigned vf : 1; /* bit 1: V flag: was 8085 signed-number overflow */
unsigned pf : 1; /* bit 2: parity flag */
unsigned rf : 1; /* bit 3: always zero [undoc] */
unsigned af : 1; /* bit 4: auxiliary flag */
unsigned kf : 1; /* bit 5: K flag = V flag ⊕ sgn(result) [undoc] */
unsigned zf : 1; /* bit 6: zero flag */
unsigned sf : 1; /* bit 7: sign flag */
unsigned tf : 1; /* bit 8: trap flag */
unsigned if_ : 1; /* bit 9: interrupt enable flag */
unsigned df : 1; /* bit 10: direction flag */
unsigned of : 1; /* bit 11: overflow flag */
unsigned pl : 2; /* b12-13: i/o privilege level (80286+) */
unsigned nt : 1; /* bit 14: nested task flag (80286+) */
unsigned pc : 1; /* bit 15: oldskool flag */
};
};
struct ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
uint8_t uc_sigmask[128 + 16]; /* ?!? wut */
struct FpuState fpustate;
};
typedef struct ucontext ucontext_t;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_UCONTEXT_H_ */