mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
7e0a09feec
This change ports APE Loader to Linux AARCH64, so that Raspberry Pi users can run programs like redbean, without the executable needing to modify itself. Progress has also slipped into this change on the issue of making progress better conforming to user expectations and industry standards regarding which symbols we're allowed to declare
143 lines
4.5 KiB
C
143 lines
4.5 KiB
C
#ifndef COSMOPOLITAN_LIBC_RUNTIME_STACK_H_
|
|
#define COSMOPOLITAN_LIBC_RUNTIME_STACK_H_
|
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
#ifdef COSMO
|
|
|
|
/**
|
|
* Tunes APE stack maximum size.
|
|
*
|
|
* The bottom-most page will be protected to ensure your stack does not
|
|
* magically grow beyond this value. It's possible to detect stack
|
|
* overflows, by calling `ShowCrashReports()`. Your stack size must be a
|
|
* power of two; the linker will check this.
|
|
*
|
|
* If you want to know how much stack your programs needs, then
|
|
*
|
|
* __static_yoink("stack_usage_logging");
|
|
*
|
|
* will install an atexit() handler that appends to `o/$MODE/stack.log`
|
|
*
|
|
* @see libc/sysv/systemfive.S
|
|
* @see ape/ape.lds
|
|
*/
|
|
#define STATIC_STACK_SIZE(BYTES) \
|
|
_STACK_SYMBOL("ape_stack_memsz", _STACK_STRINGIFY(BYTES) _STACK_EXTRA)
|
|
|
|
/**
|
|
* Tunes APE stack virtual address.
|
|
*
|
|
* This value must be aligned according to your stack size, and that's
|
|
* checked by your linker script. This defaults to `0x700000000000` so
|
|
*
|
|
* 1. It's easy to see how close you are to the bottom
|
|
* 2. The linker script error is unlikely to happen
|
|
*
|
|
* This macro will be respected, with two exceptions
|
|
*
|
|
* 1. In MODE=tiny the operating system provided stack is used instead
|
|
* 2. Windows 7 doesn't support 64-bit addresses, so we'll instead use
|
|
* `0x10000000 - GetStackSize()` as the stack address
|
|
*
|
|
* @see libc/sysv/systemfive.S
|
|
* @see libc/nt/winmain.greg.c
|
|
* @see ape/ape.lds
|
|
*/
|
|
#define STATIC_STACK_ADDR(ADDR) \
|
|
_STACK_SYMBOL("ape_stack_vaddr", _STACK_STRINGIFY(ADDR))
|
|
|
|
/**
|
|
* Makes program stack executable if declared, e.g.
|
|
*
|
|
* STATIC_EXEC_STACK();
|
|
* int main() {
|
|
* char code[16] = {
|
|
* 0x55, // push %rbp
|
|
* 0xb8, 0007, 0x00, 0x00, 0x00, // mov $7,%eax
|
|
* 0x5d, // push %rbp
|
|
* 0xc3, // ret
|
|
* };
|
|
* int (*func)(void) = (void *)code;
|
|
* printf("result %d should be 7\n", func());
|
|
* }
|
|
*/
|
|
#define STATIC_EXEC_STACK() _STACK_SYMBOL("ape_stack_pf", "7")
|
|
|
|
#define _STACK_STRINGIFY(ADDR) #ADDR
|
|
#define _STACK_SYMBOL(NAME, VALUE) \
|
|
asm(".equ\t" NAME "," VALUE "\n\t" \
|
|
".globl\t" NAME)
|
|
|
|
#ifdef __SANITIZE_ADDRESS__
|
|
#define _STACK_EXTRA "*2"
|
|
#else
|
|
#define _STACK_EXTRA ""
|
|
#endif
|
|
|
|
#if defined(__GNUC__) && defined(__ELF__) && !defined(__STRICT_ANSI__)
|
|
COSMOPOLITAN_C_START_
|
|
|
|
extern char ape_stack_prot[] __attribute__((__weak__));
|
|
extern char ape_stack_memsz[] __attribute__((__weak__));
|
|
extern char ape_stack_align[] __attribute__((__weak__));
|
|
|
|
/**
|
|
* Returns size of stack, which is always a two power.
|
|
*/
|
|
#define GetStackSize() ((uintptr_t)ape_stack_memsz)
|
|
|
|
/**
|
|
* Returns address of bottom of stack.
|
|
*
|
|
* This takes into consideration threads and sigaltstack. This is
|
|
* implemented as a fast pure expression, since we're able to make the
|
|
* assumption that stack sizes are two powers and aligned. This is
|
|
* thanks to (1) the linker script checks the statically chosen sizes,
|
|
* and (2) the mmap() address picker will choose aligned addresses when
|
|
* the provided size is a two power.
|
|
*/
|
|
#define GetStackAddr() \
|
|
(((intptr_t)__builtin_frame_address(0) - 1) & -GetStackSize())
|
|
|
|
#ifdef __x86_64__
|
|
/**
|
|
* Returns preferred bottom address of stack.
|
|
*
|
|
* This is the stakc address of the main process. The only time that
|
|
* isn't guaranteed to be the case is in MODE=tiny, since it doesn't
|
|
* link the code for stack creation at startup. This generally isn't
|
|
* problematic, since MODE=tiny doesn't use any of the runtime codes
|
|
* which want the stack to be cheaply knowable, e.g. ftrace, kprintf
|
|
*/
|
|
#define GetStaticStackAddr(ADDEND) \
|
|
({ \
|
|
intptr_t vAddr; \
|
|
__asm__(".weak\tape_stack_vaddr\n\t" \
|
|
"movabs\t%1+ape_stack_vaddr,%0" \
|
|
: "=r"(vAddr) \
|
|
: "i"(ADDEND)); \
|
|
vAddr; \
|
|
})
|
|
#else
|
|
#define GetStaticStackAddr(ADDEND) (GetStackAddr() + ADDEND)
|
|
#endif
|
|
|
|
/**
|
|
* Returns true if at least `n` bytes of stack are available.
|
|
*/
|
|
#define HaveStackMemory(n) \
|
|
((intptr_t)__builtin_frame_address(0) >= GetStackAddr() + 16384 + (n))
|
|
|
|
forceinline void CheckLargeStackAllocation(void *p, ssize_t n) {
|
|
for (; n > 0; n -= 4096) {
|
|
((char *)p)[n - 1] = 0;
|
|
}
|
|
}
|
|
|
|
void *NewCosmoStack(void) vallocesque;
|
|
int FreeCosmoStack(void *) libcesque;
|
|
|
|
#endif /* COSMO */
|
|
COSMOPOLITAN_C_END_
|
|
#endif /* GNU ELF */
|
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_STACK_H_ */
|