1433d6423SLionel Sambuc #include "inc.h"
2433d6423SLionel Sambuc #include <assert.h>
3433d6423SLionel Sambuc #include <sys/exec.h>
4433d6423SLionel Sambuc #include <libexec.h>
5433d6423SLionel Sambuc #include <machine/vmparam.h>
6433d6423SLionel Sambuc
7433d6423SLionel Sambuc static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
8433d6423SLionel Sambuc char *frame, int frame_len, vir_bytes ps_str);
9433d6423SLionel Sambuc static int exec_restart(int proc_e, int result, vir_bytes pc, vir_bytes ps_str);
10433d6423SLionel Sambuc static int read_seg(struct exec_info *execi, off_t off,
11433d6423SLionel Sambuc vir_bytes seg_addr, size_t seg_bytes);
12433d6423SLionel Sambuc
13433d6423SLionel Sambuc /* Array of loaders for different object formats */
14433d6423SLionel Sambuc static struct exec_loaders {
15433d6423SLionel Sambuc libexec_exec_loadfunc_t load_object;
16433d6423SLionel Sambuc } const exec_loaders[] = {
17433d6423SLionel Sambuc { libexec_load_elf },
18433d6423SLionel Sambuc { NULL }
19433d6423SLionel Sambuc };
20433d6423SLionel Sambuc
srv_execve(int proc_e,char * exec,size_t exec_len,char * progname,char ** argv,char ** envp)21*23199f62SDavid van Moolenbroek int srv_execve(int proc_e, char *exec, size_t exec_len, char *progname,
22*23199f62SDavid van Moolenbroek char **argv, char **envp)
23433d6423SLionel Sambuc {
24433d6423SLionel Sambuc size_t frame_size = 0; /* Size of the new initial stack. */
25433d6423SLionel Sambuc int argc = 0; /* Argument count. */
26433d6423SLionel Sambuc int envc = 0; /* Environment count */
27433d6423SLionel Sambuc char overflow = 0; /* No overflow yet. */
28433d6423SLionel Sambuc char *frame;
29433d6423SLionel Sambuc struct ps_strings *psp;
30433d6423SLionel Sambuc int vsp = 0; /* (virtual) Stack pointer in new address space. */
31433d6423SLionel Sambuc
32433d6423SLionel Sambuc int r;
33433d6423SLionel Sambuc
34433d6423SLionel Sambuc minix_stack_params(argv[0], argv, envp, &frame_size, &overflow,
35433d6423SLionel Sambuc &argc, &envc);
36433d6423SLionel Sambuc
37433d6423SLionel Sambuc /* The party is off if there is an overflow. */
38433d6423SLionel Sambuc if (overflow) {
39433d6423SLionel Sambuc errno = E2BIG;
40433d6423SLionel Sambuc return -1;
41433d6423SLionel Sambuc }
42433d6423SLionel Sambuc
43433d6423SLionel Sambuc /* Allocate space for the stack frame. */
44433d6423SLionel Sambuc if ((frame = (char *) sbrk(frame_size)) == (char *) -1) {
45433d6423SLionel Sambuc errno = E2BIG;
46433d6423SLionel Sambuc return -1;
47433d6423SLionel Sambuc }
48433d6423SLionel Sambuc
49433d6423SLionel Sambuc minix_stack_fill(argv[0], argc, argv, envc, envp, frame_size, frame,
50433d6423SLionel Sambuc &vsp, &psp);
51433d6423SLionel Sambuc
52433d6423SLionel Sambuc r = do_exec(proc_e, exec, exec_len, progname, frame, frame_size,
53433d6423SLionel Sambuc vsp + ((char *)psp - frame));
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc /* Failure, return the memory used for the frame and exit. */
56433d6423SLionel Sambuc (void) sbrk(-frame_size);
57433d6423SLionel Sambuc
58433d6423SLionel Sambuc return r;
59433d6423SLionel Sambuc }
60433d6423SLionel Sambuc
61433d6423SLionel Sambuc
do_exec(int proc_e,char * exec,size_t exec_len,char * progname,char * frame,int frame_len,vir_bytes ps_str)62433d6423SLionel Sambuc static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
63433d6423SLionel Sambuc char *frame, int frame_len, vir_bytes ps_str)
64433d6423SLionel Sambuc {
65433d6423SLionel Sambuc int r;
66433d6423SLionel Sambuc vir_bytes vsp;
67433d6423SLionel Sambuc struct exec_info execi;
68433d6423SLionel Sambuc int i;
69433d6423SLionel Sambuc
70433d6423SLionel Sambuc memset(&execi, 0, sizeof(execi));
71433d6423SLionel Sambuc
7220054ae9SDavid van Moolenbroek execi.stack_high = minix_get_user_sp();
73433d6423SLionel Sambuc execi.stack_size = DEFAULT_STACK_LIMIT;
74433d6423SLionel Sambuc execi.proc_e = proc_e;
75433d6423SLionel Sambuc execi.hdr = exec;
76433d6423SLionel Sambuc execi.filesize = execi.hdr_len = exec_len;
77433d6423SLionel Sambuc strncpy(execi.progname, progname, PROC_NAME_LEN-1);
78433d6423SLionel Sambuc execi.progname[PROC_NAME_LEN-1] = '\0';
79433d6423SLionel Sambuc execi.frame_len = frame_len;
80433d6423SLionel Sambuc
81433d6423SLionel Sambuc /* callback functions and data */
82433d6423SLionel Sambuc execi.copymem = read_seg;
83433d6423SLionel Sambuc execi.clearproc = libexec_clearproc_vm_procctl;
84433d6423SLionel Sambuc execi.clearmem = libexec_clear_sys_memset;
85433d6423SLionel Sambuc execi.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared;
86433d6423SLionel Sambuc execi.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk;
87433d6423SLionel Sambuc execi.allocmem_ondemand = libexec_alloc_mmap_ondemand;
88433d6423SLionel Sambuc
89433d6423SLionel Sambuc for(i = 0; exec_loaders[i].load_object != NULL; i++) {
90433d6423SLionel Sambuc r = (*exec_loaders[i].load_object)(&execi);
91433d6423SLionel Sambuc /* Loaded successfully, so no need to try other loaders */
92433d6423SLionel Sambuc if (r == OK) break;
93433d6423SLionel Sambuc }
94433d6423SLionel Sambuc
95433d6423SLionel Sambuc /* No exec loader could load the object */
96433d6423SLionel Sambuc if (r != OK) {
97433d6423SLionel Sambuc printf("RS: do_exec: loading error %d\n", r);
98433d6423SLionel Sambuc return r;
99433d6423SLionel Sambuc }
100433d6423SLionel Sambuc
101433d6423SLionel Sambuc /* Inform PM */
102433d6423SLionel Sambuc if((r = libexec_pm_newexec(execi.proc_e, &execi)) != OK)
103433d6423SLionel Sambuc return r;
104433d6423SLionel Sambuc
105433d6423SLionel Sambuc /* Patch up stack and copy it from RS to new core image. */
106433d6423SLionel Sambuc vsp = execi.stack_high - frame_len;
107433d6423SLionel Sambuc r = sys_datacopy(SELF, (vir_bytes) frame,
108433d6423SLionel Sambuc proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
109433d6423SLionel Sambuc if (r != OK) {
110433d6423SLionel Sambuc printf("do_exec: copying out new stack failed: %d\n", r);
111433d6423SLionel Sambuc exec_restart(proc_e, r, execi.pc, ps_str);
112433d6423SLionel Sambuc return r;
113433d6423SLionel Sambuc }
114433d6423SLionel Sambuc
115433d6423SLionel Sambuc return exec_restart(proc_e, OK, execi.pc, ps_str);
116433d6423SLionel Sambuc }
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc /*===========================================================================*
119433d6423SLionel Sambuc * exec_restart *
120433d6423SLionel Sambuc *===========================================================================*/
exec_restart(int proc_e,int result,vir_bytes pc,vir_bytes ps_str)121433d6423SLionel Sambuc static int exec_restart(int proc_e, int result, vir_bytes pc, vir_bytes ps_str)
122433d6423SLionel Sambuc {
123433d6423SLionel Sambuc int r;
124433d6423SLionel Sambuc message m;
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc memset(&m, 0, sizeof(m));
127433d6423SLionel Sambuc m.m_type = PM_EXEC_RESTART;
128433d6423SLionel Sambuc m.m_rs_pm_exec_restart.endpt = proc_e;
129433d6423SLionel Sambuc m.m_rs_pm_exec_restart.result = result;
130433d6423SLionel Sambuc m.m_rs_pm_exec_restart.pc = pc;
131433d6423SLionel Sambuc m.m_rs_pm_exec_restart.ps_str = ps_str;
132433d6423SLionel Sambuc
133433d6423SLionel Sambuc r = ipc_sendrec(PM_PROC_NR, &m);
134433d6423SLionel Sambuc if (r != OK)
135433d6423SLionel Sambuc return r;
136433d6423SLionel Sambuc
137433d6423SLionel Sambuc return m.m_type;
138433d6423SLionel Sambuc }
139433d6423SLionel Sambuc
140433d6423SLionel Sambuc /*===========================================================================*
141433d6423SLionel Sambuc * read_seg *
142433d6423SLionel Sambuc *===========================================================================*/
read_seg(struct exec_info * execi,off_t off,vir_bytes seg_addr,size_t seg_bytes)143433d6423SLionel Sambuc static int read_seg(
144433d6423SLionel Sambuc struct exec_info *execi, /* various data needed for exec */
145433d6423SLionel Sambuc off_t off, /* offset in file */
146433d6423SLionel Sambuc vir_bytes seg_addr, /* address to load segment */
147433d6423SLionel Sambuc size_t seg_bytes /* how much is to be transferred? */
148433d6423SLionel Sambuc )
149433d6423SLionel Sambuc {
150433d6423SLionel Sambuc /*
151433d6423SLionel Sambuc * The byte count on read is usually smaller than the segment count, because
152433d6423SLionel Sambuc * a segment is padded out to a click multiple, and the data segment is only
153433d6423SLionel Sambuc * partially initialized.
154433d6423SLionel Sambuc */
155433d6423SLionel Sambuc
156433d6423SLionel Sambuc int r;
157433d6423SLionel Sambuc
158433d6423SLionel Sambuc if (off+seg_bytes > execi->hdr_len) return ENOEXEC;
159433d6423SLionel Sambuc if((r= sys_datacopy(SELF, ((vir_bytes)execi->hdr)+off,
160433d6423SLionel Sambuc execi->proc_e, seg_addr, seg_bytes)) != OK) {
161433d6423SLionel Sambuc printf("RS: exec read_seg: copy 0x%x bytes into %i at 0x%08lx failed: %i\n",
1623c8950ccSBen Gras (int) seg_bytes, execi->proc_e, seg_addr, r);
163433d6423SLionel Sambuc }
164433d6423SLionel Sambuc return r;
165433d6423SLionel Sambuc }
166