5 #include <minix/param.h>
6 #include <machine/vmparam.h>
8 static int do_exec(int proc_e
, char *exec
, size_t exec_len
, char *progname
,
9 char *frame
, int frame_len
, vir_bytes ps_str
);
10 static int exec_restart(int proc_e
, int result
, vir_bytes pc
, vir_bytes ps_str
);
11 static int read_seg(struct exec_info
*execi
, off_t off
,
12 vir_bytes seg_addr
, size_t seg_bytes
);
14 /* Array of loaders for different object formats */
15 static struct exec_loaders
{
16 libexec_exec_loadfunc_t load_object
;
17 } const exec_loaders
[] = {
22 int srv_execve(int proc_e
, char *exec
, size_t exec_len
, char **argv
,
25 size_t frame_size
= 0; /* Size of the new initial stack. */
26 int argc
= 0; /* Argument count. */
27 int envc
= 0; /* Environment count */
28 char overflow
= 0; /* No overflow yet. */
30 struct ps_strings
*psp
;
31 int vsp
= 0; /* (virtual) Stack pointer in new address space. */
36 minix_stack_params(argv
[0], argv
, envp
, &frame_size
, &overflow
,
39 /* The party is off if there is an overflow. */
45 /* Allocate space for the stack frame. */
46 if ((frame
= (char *) sbrk(frame_size
)) == (char *) -1) {
51 minix_stack_fill(argv
[0], argc
, argv
, envc
, envp
, frame_size
, frame
,
54 (progname
=strrchr(argv
[0], '/')) ? progname
++ : (progname
=argv
[0]);
56 r
= do_exec(proc_e
, exec
, exec_len
, progname
, frame
, frame_size
,
57 vsp
+ ((char *)psp
- frame
));
59 /* Failure, return the memory used for the frame and exit. */
60 (void) sbrk(-frame_size
);
66 static int do_exec(int proc_e
, char *exec
, size_t exec_len
, char *progname
,
67 char *frame
, int frame_len
, vir_bytes ps_str
)
71 struct exec_info execi
;
74 memset(&execi
, 0, sizeof(execi
));
76 execi
.stack_high
= kinfo
.user_sp
;
77 execi
.stack_size
= DEFAULT_STACK_LIMIT
;
78 execi
.proc_e
= proc_e
;
80 execi
.filesize
= execi
.hdr_len
= exec_len
;
81 strncpy(execi
.progname
, progname
, PROC_NAME_LEN
-1);
82 execi
.progname
[PROC_NAME_LEN
-1] = '\0';
83 execi
.frame_len
= frame_len
;
85 /* callback functions and data */
86 execi
.copymem
= read_seg
;
87 execi
.clearproc
= libexec_clearproc_vm_procctl
;
88 execi
.clearmem
= libexec_clear_sys_memset
;
89 execi
.allocmem_prealloc_cleared
= libexec_alloc_mmap_prealloc_cleared
;
90 execi
.allocmem_prealloc_junk
= libexec_alloc_mmap_prealloc_junk
;
91 execi
.allocmem_ondemand
= libexec_alloc_mmap_ondemand
;
93 for(i
= 0; exec_loaders
[i
].load_object
!= NULL
; i
++) {
94 r
= (*exec_loaders
[i
].load_object
)(&execi
);
95 /* Loaded successfully, so no need to try other loaders */
99 /* No exec loader could load the object */
101 printf("RS: do_exec: loading error %d\n", r
);
106 if((r
= libexec_pm_newexec(execi
.proc_e
, &execi
)) != OK
)
109 /* Patch up stack and copy it from RS to new core image. */
110 vsp
= execi
.stack_high
- frame_len
;
111 r
= sys_datacopy(SELF
, (vir_bytes
) frame
,
112 proc_e
, (vir_bytes
) vsp
, (phys_bytes
)frame_len
);
114 printf("do_exec: copying out new stack failed: %d\n", r
);
115 exec_restart(proc_e
, r
, execi
.pc
, ps_str
);
119 return exec_restart(proc_e
, OK
, execi
.pc
, ps_str
);
122 /*===========================================================================*
124 *===========================================================================*/
125 static int exec_restart(int proc_e
, int result
, vir_bytes pc
, vir_bytes ps_str
)
130 memset(&m
, 0, sizeof(m
));
131 m
.m_type
= PM_EXEC_RESTART
;
132 m
.PM_EXEC_RESTART_ENDPT
= proc_e
;
133 m
.PM_EXEC_RESTART_RESULT
= result
;
134 m
.PM_EXEC_RESTART_PC
= (void *)pc
;
135 m
.PM_EXEC_RESTART_PS_STR
= (void *)ps_str
;
137 r
= ipc_sendrec(PM_PROC_NR
, &m
);
144 /*===========================================================================*
146 *===========================================================================*/
148 struct exec_info
*execi
, /* various data needed for exec */
149 off_t off
, /* offset in file */
150 vir_bytes seg_addr
, /* address to load segment */
151 size_t seg_bytes
/* how much is to be transferred? */
155 * The byte count on read is usually smaller than the segment count, because
156 * a segment is padded out to a click multiple, and the data segment is only
157 * partially initialized.
162 if (off
+seg_bytes
> execi
->hdr_len
) return ENOEXEC
;
163 if((r
= sys_datacopy(SELF
, ((vir_bytes
)execi
->hdr
)+off
,
164 execi
->proc_e
, seg_addr
, seg_bytes
)) != OK
) {
165 printf("RS: exec read_seg: copy 0x%x bytes into %i at 0x%08lx failed: %i\n",
166 seg_bytes
, execi
->proc_e
, seg_addr
, r
);