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