1*433d6423SLionel Sambuc /* Utilities to generate a proper C stack. 2*433d6423SLionel Sambuc * 3*433d6423SLionel Sambuc * Author: Lionel A. Sambuc. 4*433d6423SLionel Sambuc */ 5*433d6423SLionel Sambuc 6*433d6423SLionel Sambuc #define _MINIX_SYSTEM 7*433d6423SLionel Sambuc 8*433d6423SLionel Sambuc #include <sys/cdefs.h> 9*433d6423SLionel Sambuc #include "namespace.h" 10*433d6423SLionel Sambuc #include <lib.h> 11*433d6423SLionel Sambuc 12*433d6423SLionel Sambuc #include <unistd.h> 13*433d6423SLionel Sambuc #include <string.h> 14*433d6423SLionel Sambuc #include <stddef.h> 15*433d6423SLionel Sambuc #include <minix/param.h> 16*433d6423SLionel Sambuc #include <sys/exec_elf.h> 17*433d6423SLionel Sambuc #include <sys/exec.h> 18*433d6423SLionel Sambuc 19*433d6423SLionel Sambuc extern struct minix_kerninfo *_minix_kerninfo; 20*433d6423SLionel Sambuc 21*433d6423SLionel Sambuc /* Create a stack image that only needs to be patched up slightly by 22*433d6423SLionel Sambuc * the kernel to be used for the process to be executed. 23*433d6423SLionel Sambuc * 24*433d6423SLionel Sambuc * Every pointers are stored here as offset from the frame base, and 25*433d6423SLionel Sambuc * will be adapted as required for the new process address space. 26*433d6423SLionel Sambuc * 27*433d6423SLionel Sambuc * The following parameters are passed by register to either __start 28*433d6423SLionel Sambuc * for static binaries, or _rtld_start for dynamic ones: 29*433d6423SLionel Sambuc * *fct, *ObjEntry, *ps_string 30*433d6423SLionel Sambuc * 31*433d6423SLionel Sambuc * The following stack layout is expected by _rtld(): 32*433d6423SLionel Sambuc * 33*433d6423SLionel Sambuc * | XXXXXXXXXX | 0x0000_00000 34*433d6423SLionel Sambuc * | ... | 35*433d6423SLionel Sambuc * | ... | Top of the stack 36*433d6423SLionel Sambuc * | argc | 37*433d6423SLionel Sambuc * | *argv1 | points to the first char of the argv1 38*433d6423SLionel Sambuc * | ... | 39*433d6423SLionel Sambuc * | *argvN | 40*433d6423SLionel Sambuc * | NULL | 41*433d6423SLionel Sambuc * | *env1 | 42*433d6423SLionel Sambuc * | ... | 43*433d6423SLionel Sambuc * | *envN | 44*433d6423SLionel Sambuc * | NULL | 45*433d6423SLionel Sambuc * | ElfAuxV1 | 46*433d6423SLionel Sambuc * | ... | 47*433d6423SLionel Sambuc * | ElfAuxVX | 48*433d6423SLionel Sambuc * | AuxExecName| fully resolve executable name, as an ASCIIZ string, 49*433d6423SLionel Sambuc * at most PMEF_EXECNAMELEN1 long. 50*433d6423SLionel Sambuc * 51*433d6423SLionel Sambuc * Here we put first the strings, then word-align, then ps_strings, to 52*433d6423SLionel Sambuc * comply with the expected layout of NetBSD. This seems to matter for 53*433d6423SLionel Sambuc * the NetBSD ps command, so let's make sure we are compatible... 54*433d6423SLionel Sambuc * 55*433d6423SLionel Sambuc * | strings | Maybe followed by some padding to word-align. 56*433d6423SLionel Sambuc * | **argv | \ 57*433d6423SLionel Sambuc * | argc | +---> ps_string structure content. 58*433d6423SLionel Sambuc * | **env | | 59*433d6423SLionel Sambuc * | envc | / 60*433d6423SLionel Sambuc * | sigcode | On NetBSD, there may be a compatibility stub here, 61*433d6423SLionel Sambuc * +------------+ for native code, it is not present. 62*433d6423SLionel Sambuc * Stack Base , 0xF000_0000, descending stack. 63*433d6423SLionel Sambuc */ 64*433d6423SLionel Sambuc 65*433d6423SLionel Sambuc /* The minimum size of the frame is composed of: 66*433d6423SLionel Sambuc * argc, the NULL terminator for argv as well as one for 67*433d6423SLionel Sambuc * environ, the ELF Aux vectors, executable name and the 68*433d6423SLionel Sambuc * ps_strings struct. */ 69*433d6423SLionel Sambuc #define STACK_MIN_SZ \ 70*433d6423SLionel Sambuc ( \ 71*433d6423SLionel Sambuc sizeof(int) + sizeof(void *) * 2 + \ 72*433d6423SLionel Sambuc sizeof(AuxInfo) * PMEF_AUXVECTORS + PMEF_EXECNAMELEN1 + \ 73*433d6423SLionel Sambuc sizeof(struct ps_strings) \ 74*433d6423SLionel Sambuc ) 75*433d6423SLionel Sambuc 76*433d6423SLionel Sambuc /***************************************************************************** 77*433d6423SLionel Sambuc * Computes stack size, argc, envc, for a given set of path, argv, envp. * 78*433d6423SLionel Sambuc *****************************************************************************/ 79*433d6423SLionel Sambuc void minix_stack_params(const char *path, char * const *argv, char * const *envp, 80*433d6423SLionel Sambuc size_t *stack_size, char *overflow, int *argc, int *envc) 81*433d6423SLionel Sambuc { 82*433d6423SLionel Sambuc char * const *p; 83*433d6423SLionel Sambuc size_t const min_size = STACK_MIN_SZ; 84*433d6423SLionel Sambuc 85*433d6423SLionel Sambuc *stack_size = min_size; /* Size of the new initial stack. */ 86*433d6423SLionel Sambuc *overflow = 0; /* No overflow yet. */ 87*433d6423SLionel Sambuc *argc = 0; /* Argument count. */ 88*433d6423SLionel Sambuc *envc = 0; /* Environment count */ 89*433d6423SLionel Sambuc 90*433d6423SLionel Sambuc /* Compute and add the size required to store argv and env. */ 91*433d6423SLionel Sambuc for (p = argv; *p != NULL; p++) { 92*433d6423SLionel Sambuc size_t const n = sizeof(*p) + strlen(*p) + 1; 93*433d6423SLionel Sambuc *stack_size += n; 94*433d6423SLionel Sambuc if (*stack_size < n) { 95*433d6423SLionel Sambuc *overflow = 1; 96*433d6423SLionel Sambuc } 97*433d6423SLionel Sambuc (*argc)++; 98*433d6423SLionel Sambuc } 99*433d6423SLionel Sambuc 100*433d6423SLionel Sambuc for (p = envp; p && *p != NULL; p++) { 101*433d6423SLionel Sambuc size_t const n = sizeof(*p) + strlen(*p) + 1; 102*433d6423SLionel Sambuc *stack_size += n; 103*433d6423SLionel Sambuc if (*stack_size < n) { 104*433d6423SLionel Sambuc *overflow = 1; 105*433d6423SLionel Sambuc } 106*433d6423SLionel Sambuc (*envc)++; 107*433d6423SLionel Sambuc } 108*433d6423SLionel Sambuc 109*433d6423SLionel Sambuc /* Compute the aligned frame size. */ 110*433d6423SLionel Sambuc *stack_size = (*stack_size + sizeof(void *) - 1) & 111*433d6423SLionel Sambuc ~(sizeof(void *) - 1); 112*433d6423SLionel Sambuc 113*433d6423SLionel Sambuc if (*stack_size < min_size) { 114*433d6423SLionel Sambuc /* This is possible only in case of overflow. */ 115*433d6423SLionel Sambuc *overflow = 1; 116*433d6423SLionel Sambuc } 117*433d6423SLionel Sambuc } 118*433d6423SLionel Sambuc 119*433d6423SLionel Sambuc /***************************************************************************** 120*433d6423SLionel Sambuc * Generate a stack in the buffer frame, ready to be used. * 121*433d6423SLionel Sambuc *****************************************************************************/ 122*433d6423SLionel Sambuc void minix_stack_fill(const char *path, int argc, char * const *argv, 123*433d6423SLionel Sambuc int envc, char * const *envp, size_t stack_size, char *frame, 124*433d6423SLionel Sambuc int *vsp, struct ps_strings **psp) 125*433d6423SLionel Sambuc { 126*433d6423SLionel Sambuc char * const *p; 127*433d6423SLionel Sambuc 128*433d6423SLionel Sambuc /* Frame pointers (a.k.a stack pointer within the buffer in current 129*433d6423SLionel Sambuc * address space.) */ 130*433d6423SLionel Sambuc char *fp; /* byte aligned */ 131*433d6423SLionel Sambuc char **fpw; /* word aligned */ 132*433d6423SLionel Sambuc 133*433d6423SLionel Sambuc size_t const min_size = STACK_MIN_SZ; 134*433d6423SLionel Sambuc 135*433d6423SLionel Sambuc /* Virtual address of the stack pointer, in new memory space. */ 136*433d6423SLionel Sambuc *vsp = _minix_kerninfo->kinfo->user_sp - stack_size; 137*433d6423SLionel Sambuc 138*433d6423SLionel Sambuc /* Fill in the frame now. */ 139*433d6423SLionel Sambuc fpw = (char **) frame; 140*433d6423SLionel Sambuc *fpw++ = (char *) argc; 141*433d6423SLionel Sambuc 142*433d6423SLionel Sambuc /* The strings themselves are stored after the aux vectors, 143*433d6423SLionel Sambuc * cf. top comment. */ 144*433d6423SLionel Sambuc fp = frame + (min_size - sizeof(struct ps_strings)) + 145*433d6423SLionel Sambuc (envc + argc) * sizeof(char *); 146*433d6423SLionel Sambuc 147*433d6423SLionel Sambuc /* Fill in argv and the environment, as well as copy the strings 148*433d6423SLionel Sambuc * themselves. */ 149*433d6423SLionel Sambuc for (p = argv; *p != NULL; p++) { 150*433d6423SLionel Sambuc size_t const n = strlen(*p) + 1; 151*433d6423SLionel Sambuc *fpw++= (char *)(*vsp + (fp - frame)); 152*433d6423SLionel Sambuc memcpy(fp, *p, n); 153*433d6423SLionel Sambuc fp += n; 154*433d6423SLionel Sambuc } 155*433d6423SLionel Sambuc *fpw++ = NULL; 156*433d6423SLionel Sambuc 157*433d6423SLionel Sambuc for (p = envp; p && *p != NULL; p++) { 158*433d6423SLionel Sambuc size_t const n = strlen(*p) + 1; 159*433d6423SLionel Sambuc *fpw++= (char *)(*vsp + (fp - frame)); 160*433d6423SLionel Sambuc memcpy(fp, *p, n); 161*433d6423SLionel Sambuc fp += n; 162*433d6423SLionel Sambuc } 163*433d6423SLionel Sambuc *fpw++ = NULL; 164*433d6423SLionel Sambuc 165*433d6423SLionel Sambuc /* Padding, because of the stack alignement. */ 166*433d6423SLionel Sambuc while ((size_t)fp % sizeof(void *)) *fp++= 0; 167*433d6423SLionel Sambuc 168*433d6423SLionel Sambuc /* Fill in the ps_string struct*/ 169*433d6423SLionel Sambuc *psp = (struct ps_strings *) fp; 170*433d6423SLionel Sambuc 171*433d6423SLionel Sambuc (*psp)->ps_argvstr = (char **)(*vsp + sizeof(argc)); 172*433d6423SLionel Sambuc (*psp)->ps_nargvstr = argc; 173*433d6423SLionel Sambuc (*psp)->ps_envstr = (*psp)->ps_argvstr + argc + 1; 174*433d6423SLionel Sambuc (*psp)->ps_nenvstr = envc; 175*433d6423SLionel Sambuc } 176