feat(start): _start, __libc_start_main, exit/atexit/environ
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
#ifndef VLIBC_INTERNAL_START_TCB_H
|
||||
#define VLIBC_INTERNAL_START_TCB_H
|
||||
|
||||
/*
|
||||
* vlibc — AUTHORITATIVE x86_64 TCB / thread-pointer layout (todo 3).
|
||||
*
|
||||
* This header defines the thread control block (TCB) layout ONCE, for the
|
||||
* whole library. Later layers reference these constants and NEVER redefine
|
||||
* them:
|
||||
*
|
||||
* #44 threading substrate: clones this layout for every new thread and
|
||||
* initializes the fenv slot per thread.
|
||||
* #45 sizes new-thread TLS from the static TLS block arithmetic below.
|
||||
* #62 ld.so: performs the dynamic-case equivalent of this bootstrap (the
|
||||
* FS-already-set guard in tls.c skips this code in that case).
|
||||
* #42 fenv: reads/writes the reserved fenv slot through the fixed
|
||||
* offsets below; the slot is per-thread lazy storage for the x87
|
||||
* control word and MXCSR.
|
||||
*
|
||||
* ABI model — ELF TLS variant II on x86_64:
|
||||
*
|
||||
* The thread pointer (TP) is delivered by the %fs segment and points
|
||||
* DIRECTLY at the TCB (this is what "variant II" means; variant I, used by
|
||||
* e.g. 32-bit x86, points at the end of the TLS data instead). Static TLS
|
||||
* data live at NEGATIVE offsets from TP (%fs:N with N < 0, the LE model);
|
||||
* the TCB fields live at positive offsets. Slot 0 is required to hold the
|
||||
* TCB's own address because __builtin_thread_pointer() reads %fs:0 — that
|
||||
* is the entire mechanism by which C code recovers TP from a register.
|
||||
*
|
||||
* TCB field map (offsets are byte offsets from TP, i.e. from %fs:0):
|
||||
*
|
||||
* TP + 0 VLIBC_TCB_SELF_OFF TCB self pointer (TP itself).
|
||||
* TP + 8 VLIBC_TCB_ERRNO_OFF per-thread errno slot: 8 bytes, errno
|
||||
* occupies the low 4. This offset is OWNED
|
||||
* by src/internal/errno.h (task 1 fixed it
|
||||
* as an ABI constant) and is consumed
|
||||
* here, never re-derived.
|
||||
* TP + 16 VLIBC_TCB_FENV_OFF per-thread fenv reservation, 8 bytes:
|
||||
* +16 VLIBC_TCB_FENV_X87CW_OFF uint16 x87 control word,
|
||||
* reset default 0x037F (double
|
||||
* precision, round-to-nearest)
|
||||
* +18 (pad, reserved)
|
||||
* +20 VLIBC_TCB_FENV_MXCSR_OFF uint32 MXCSR, reset default
|
||||
* 0x1F80 (all exceptions masked)
|
||||
* TP + 24 end of the fixed layout; VLIBC_TCB_SIZE = 24.
|
||||
*
|
||||
* The layout grows FORWARD from TP if later layers need more TCB fields;
|
||||
* the fixed slots above are never renumbered. A DTV pointer is deliberately
|
||||
* NOT reserved: the static TLS model needs no DTV (every access is
|
||||
* %fs-relative with a link-time offset; there is no __tls_get_addr). Should
|
||||
* #62's dynamic TLS ever require a DTV, add it at TP + VLIBC_TCB_SIZE —
|
||||
* glibc's variant-II convention keeps the DTV at a negative offset relative
|
||||
* to a separately allocated block; vlibc deliberately keeps the simpler
|
||||
* grow-upward model documented here.
|
||||
*
|
||||
* Static TLS placement contract (tls.c implements this; the linker bakes
|
||||
* its TPOFF arithmetic against the same formula, verified empirically with
|
||||
* GNU ld):
|
||||
*
|
||||
* - tp = base + round_up(p_memsz, p_align), with base page-aligned.
|
||||
* - the PT_TLS image is copied to [base, base + p_filesz), the BSS tail
|
||||
* [base + p_filesz, base + p_memsz) is zeroed, and the TCB occupies
|
||||
* [tp, tp + VLIBC_TCB_SIZE).
|
||||
* - TP alignment equals p_align EXACTLY (never bumped to 16): the linker
|
||||
* computes tpoff = var_offset - round_up(p_memsz, p_align), so any
|
||||
* other rounding breaks every %fs offset when p_memsz is not a
|
||||
* multiple of the runtime's alignment. When the program has no PT_TLS
|
||||
* at all, p_align is taken as 16 and the block is TCB-only.
|
||||
*
|
||||
* TCB fields only need 8-byte alignment, and the linker guarantees
|
||||
* p_align >= the alignment of every TLS object, so the exact-p_align
|
||||
* rule is always sufficient.
|
||||
*/
|
||||
|
||||
#include "../internal/errno.h" /* VLIBC_TCB_ERRNO_OFF */
|
||||
|
||||
#define VLIBC_TCB_SELF_OFF 0
|
||||
|
||||
/* VLIBC_TCB_ERRNO_OFF (8) is consumed from src/internal/errno.h. */
|
||||
|
||||
#define VLIBC_TCB_FENV_OFF 16
|
||||
#define VLIBC_TCB_FENV_X87CW_OFF (VLIBC_TCB_FENV_OFF + 0)
|
||||
#define VLIBC_TCB_FENV_MXCSR_OFF (VLIBC_TCB_FENV_OFF + 4)
|
||||
|
||||
#define VLIBC_TCB_SIZE 24
|
||||
|
||||
#endif /* VLIBC_INTERNAL_START_TCB_H */
|
||||
Reference in New Issue
Block a user