int __mprotect (__ptr_t addr, size_t len, int prot) { kern_return_t err; vm_prot_t vmprot; vmprot = VM_PROT_NONE; if (prot & PROT_READ) vmprot |= VM_PROT_READ; if (prot & PROT_WRITE) vmprot |= VM_PROT_WRITE; if (prot & PROT_EXEC) vmprot |= VM_PROT_EXECUTE; if (err = __vm_protect (__mach_task_self (), (vm_address_t) addr, (vm_size_t) len, 0, vmprot)) { errno = err; return -1; } return 0; }
kern_return_t __mach_setup_thread (task_t task, thread_t thread, void *pc, vm_address_t *stack_base, vm_size_t *stack_size) { kern_return_t error; struct machine_thread_state ts; mach_msg_type_number_t tssize = MACHINE_THREAD_STATE_COUNT; vm_address_t stack; vm_size_t size; int anywhere = 0; size = stack_size ? *stack_size ? : STACK_SIZE : STACK_SIZE; if (stack_base && *stack_base) stack = *stack_base; else if (size == STACK_SIZE) { /* Cthreads has a bug that makes its stack-probing code fail if the stack is too low in memory. It's bad to try and fix it there until cthreads is integrated into libc, so we'll just do it here by requesting a high address. When the cthreads bug is fixed, this assignment to STACK should be changed to 0, and the ANYWHERE argument to vm_allocate should be changed to 0. This comment should be left, however, in order to confuse people who wonder why its here. (Though perhaps that last sentence (and this one) should be deleted to maximize the effect.) */ #ifdef STACK_GROWTH_DOWN stack = VM_MAX_ADDRESS - size - __vm_page_size; #else stack = VM_MIN_ADDRESS; #endif } else anywhere = 1; if (error = __vm_allocate (task, &stack, size + __vm_page_size, anywhere)) return error; if (stack_size) *stack_size = size; memset (&ts, 0, sizeof (ts)); MACHINE_THREAD_STATE_SET_PC (&ts, pc); #ifdef STACK_GROWTH_DOWN if (stack_base) *stack_base = stack + __vm_page_size; ts.SP = stack + __vm_page_size + size; #elif defined (STACK_GROWTH_UP) if (stack_base) *stack_base = stack; ts.SP = stack; stack += size; #else #error stack direction unknown #endif /* Create the red zone. */ if (error = __vm_protect (task, stack, __vm_page_size, 0, VM_PROT_NONE)) return error; return __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR, (int *) &ts, tssize); }