5 #include <machine/vmparam.h>
7 static int do_exec(int proc_e
, char *exec
, size_t exec_len
, char *progname
,
8 char *frame
, int frame_len
);
9 static int exec_restart(int proc_e
, int result
, vir_bytes pc
);
10 static int read_seg(struct exec_info
*execi
, off_t off
,
11 off_t seg_addr
, size_t seg_bytes
);
12 static int exec_restart(int proc_e
, int result
, vir_bytes pc
);
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
,
37 /* Assumptions: size_t and char *, it's all the same thing. */
39 /* Create a stack image that only needs to be patched up slightly
40 * by the kernel to be used for the process to be executed.
43 ov
= 0; /* No overflow yet. */
44 frame_size
= 0; /* Size of the new initial stack. */
45 string_off
= 0; /* Offset to start of the strings. */
46 argc
= 0; /* Argument count. */
48 for (ap
= argv
; *ap
!= NULL
; ap
++) {
49 n
= sizeof(*ap
) + strlen(*ap
) + 1;
51 if (frame_size
< n
) ov
= 1;
52 string_off
+= sizeof(*ap
);
56 /* Add an argument count and two terminating nulls. */
57 frame_size
+= sizeof(argc
) + sizeof(*ap
) + sizeof(*ep
);
58 string_off
+= sizeof(argc
) + sizeof(*ap
) + sizeof(*ep
);
61 frame_size
= (frame_size
+ sizeof(char *) - 1) & ~(sizeof(char *) - 1);
63 /* The party is off if there is an overflow. */
64 if (ov
|| frame_size
< 3 * sizeof(char *)) {
69 /* Allocate space for the stack frame. */
70 frame
= (char *) malloc(frame_size
);
76 /* Set arg count, init pointers to vector and string tables. */
77 * (size_t *) frame
= argc
;
78 vp
= (char **) (frame
+ sizeof(argc
));
79 sp
= frame
+ string_off
;
81 /* Load the argument vector and strings. */
82 for (ap
= argv
; *ap
!= NULL
; ap
++) {
83 *vp
++= (char *) (sp
- frame
);
91 /* Load the environment vector and strings. */
92 for (ep
= envp
; *ep
!= NULL
; ep
++) {
93 *vp
++= (char *) (sp
- frame
);
102 while (sp
< frame
+ frame_size
) *sp
++= 0;
104 (progname
=strrchr(argv
[0], '/')) ? progname
++ : (progname
=argv
[0]);
105 r
= do_exec(proc_e
, exec
, exec_len
, progname
, frame
, frame_size
);
107 /* Return the memory used for the frame and exit. */
113 static int do_exec(int proc_e
, char *exec
, size_t exec_len
, char *progname
,
114 char *frame
, int frame_len
)
118 struct exec_info execi
;
121 memset(&execi
, 0, sizeof(execi
));
123 execi
.stack_high
= kinfo
.user_sp
;
124 execi
.stack_size
= DEFAULT_STACK_LIMIT
;
125 execi
.proc_e
= proc_e
;
127 execi
.filesize
= execi
.hdr_len
= exec_len
;
128 strncpy(execi
.progname
, progname
, PROC_NAME_LEN
-1);
129 execi
.progname
[PROC_NAME_LEN
-1] = '\0';
130 execi
.frame_len
= frame_len
;
132 /* callback functions and data */
133 execi
.copymem
= read_seg
;
134 execi
.clearproc
= libexec_clearproc_vm_procctl
;
135 execi
.clearmem
= libexec_clear_sys_memset
;
136 execi
.allocmem_prealloc
= libexec_alloc_mmap_prealloc
;
137 execi
.allocmem_ondemand
= libexec_alloc_mmap_ondemand
;
139 for(i
= 0; exec_loaders
[i
].load_object
!= NULL
; i
++) {
140 r
= (*exec_loaders
[i
].load_object
)(&execi
);
141 /* Loaded successfully, so no need to try other loaders */
145 /* No exec loader could load the object */
147 printf("RS: do_exec: loading error %d\n", r
);
152 if((r
= libexec_pm_newexec(execi
.proc_e
, &execi
)) != OK
)
155 /* Patch up stack and copy it from RS to new core image. */
156 vsp
= execi
.stack_high
;
158 libexec_patch_ptr(frame
, vsp
);
159 r
= sys_datacopy(SELF
, (vir_bytes
) frame
,
160 proc_e
, (vir_bytes
) vsp
, (phys_bytes
)frame_len
);
162 printf("do_exec: copying out new stack failed: %d\n", r
);
163 exec_restart(proc_e
, r
, execi
.pc
);
167 return exec_restart(proc_e
, OK
, execi
.pc
);
170 /*===========================================================================*
172 *===========================================================================*/
173 static int exec_restart(int proc_e
, int result
, vir_bytes pc
)
178 m
.m_type
= EXEC_RESTART
;
179 m
.EXC_RS_PROC
= proc_e
;
180 m
.EXC_RS_RESULT
= result
;
181 m
.EXC_RS_PC
= (void*)pc
;
182 r
= sendrec(PM_PROC_NR
, &m
);
188 /*===========================================================================*
190 *===========================================================================*/
192 struct exec_info
*execi
, /* various data needed for exec */
193 off_t off
, /* offset in file */
194 off_t seg_addr
, /* address to load segment */
195 size_t seg_bytes
/* how much is to be transferred? */
199 * The byte count on read is usually smaller than the segment count, because
200 * a segment is padded out to a click multiple, and the data segment is only
201 * partially initialized.
206 if (off
+seg_bytes
> execi
->hdr_len
) return ENOEXEC
;
207 if((r
= sys_vircopy(SELF
, ((vir_bytes
)execi
->hdr
)+off
,
208 execi
->proc_e
, seg_addr
, seg_bytes
)) != OK
) {
209 printf("RS: exec read_seg: copy 0x%x bytes into %i at 0x%08x failed: %i\n",
210 seg_bytes
, execi
->proc_e
, seg_addr
, r
);