OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [posix/] [mm0/] [mm/] [execve.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Program execution
3
 *
4
 * Copyright (C) 2008 Bahadir Balban
5
 */
6
#include L4LIB_INC_ARCH(syslib.h)
7
#include L4LIB_INC_ARCH(syscalls.h)
8
#include <l4lib/ipcdefs.h>
9
#include <l4lib/types.h>
10
#include <l4/macros.h>
11
#include <l4/api/errno.h>
12
#include <malloc/malloc.h>
13
#include <vm_area.h>
14
#include <syscalls.h>
15
#include <string.h>
16
#include <exec.h>
17
#include <file.h>
18
#include <user.h>
19
#include <task.h>
20
#include <exit.h>
21
#include <lib/elf/elf.h>
22
#include <init.h>
23
#include <stat.h>
24
#include <alloca.h>
25
 
26
/*
27
 * Probes and parses the low-level executable file format and creates a
28
 * generic execution description that can be used to run the task.
29
 */
30
int task_setup_from_executable(struct vm_file *vmfile,
31
                               struct tcb *task,
32
                               struct exec_file_desc *efd)
33
{
34
        memset(efd, 0, sizeof(*efd));
35
 
36
        return elf_parse_executable(task, vmfile, efd);
37
}
38
 
39
int init_execve(char *filepath)
40
{
41
        struct vm_file *vmfile;
42
        struct exec_file_desc efd;
43
        struct tcb *new_task, *self;
44
        struct args_struct args, env;
45
        char env_string[30];
46
        int err;
47
        int fd;
48
 
49
        struct task_ids ids = {
50
                .tid = TASK_ID_INVALID,
51
                .spid = TASK_ID_INVALID,
52
                .tgid = TASK_ID_INVALID,
53
        };
54
 
55
        sprintf(env_string, "pagerid=%d", self_tid());
56
 
57
        /* Set up args_struct */
58
        args.argc = 1;
59
        args.argv = alloca(sizeof(args.argv));
60
        args.argv[0] = alloca(strlen(filepath) + 1);
61
        strncpy(args.argv[0], filepath, strlen(filepath) + 1);
62
        args.size = sizeof(args.argv) * args.argc + strlen(filepath) + 1;
63
 
64
        /* Set up environment */
65
        env.argc = 1;
66
        env.argv = alloca(sizeof(env.argv));
67
        env.argv[0] = alloca(strlen(env_string) + 1);
68
        strncpy(env.argv[0], env_string, strlen(env_string) + 1);
69
        env.size = sizeof(env.argv) + strlen(env_string) + 1;
70
 
71
        self = find_task(self_tid());
72
        if ((fd = sys_open(self, filepath,
73
                           O_RDONLY, 0)) < 0) {
74
                printf("FATAL: Could not open file "
75
                       "to write initial task.\n");
76
                BUG();
77
        }
78
        /* Get the low-level vmfile */
79
        vmfile = self->files->fd[fd].vmfile;
80
 
81
        if (IS_ERR(new_task = task_create(0, &ids,
82
                                          TCB_NO_SHARING,
83
                                          TC_NEW_SPACE))) {
84
                sys_close(self, fd);
85
                return (int)new_task;
86
        }
87
 
88
        /*
89
         * Fill and validate tcb memory
90
         * segment markers from executable file
91
         */
92
        if ((err = task_setup_from_executable(vmfile,
93
                                              new_task,
94
                                              &efd)) < 0) {
95
                sys_close(self, fd);
96
                kfree(new_task);
97
                return err;
98
        }
99
 
100
        /* Map task's new segment markers as virtual memory regions */
101
        if ((err = task_mmap_segments(new_task, vmfile,
102
                                      &efd, &args, &env)) < 0) {
103
                sys_close(self, fd);
104
                kfree(new_task);
105
                return err;
106
        }
107
 
108
        /* Set up task registers via exchange_registers() */
109
        task_setup_registers(new_task, 0,
110
                             new_task->args_start,
111
                             new_task->pagerid);
112
 
113
 
114
        /* Add new task to global list */
115
        global_add_task(new_task);
116
 
117
        /* Start the task */
118
        task_start(new_task);
119
 
120
        return 0;
121
}
122
 
123
 
124
/*
125
 * TODO:
126
 *
127
 * Dynamic Linking.
128
 * See if an interpreter (dynamic linker) is needed
129
 * Find the interpreter executable file, if needed
130
 * Map all dynamic linker file segments
131
 * (should not clash with original executable
132
 * Set up registers to run dynamic linker (exchange_registers())
133
 * Run the interpreter
134
 *
135
 * The interpreter will:
136
 * - Need some initial info (dyn sym tables) at a certain location
137
 * - Find necessary shared library files in userspace
138
 *   (will use open/read).
139
 * - Map them into process address space via mmap()
140
 * - Reinitialise references to symbols in the shared libraries
141
 * - Jump to the entry point of main executable.
142
 */
143
 
144
int do_execve(struct tcb *sender, char *filename,
145
              struct args_struct *args,
146
              struct args_struct *env)
147
{
148
        struct vm_file *vmfile;
149
        struct exec_file_desc efd;
150
        struct tcb *new_task, *tgleader, *self;
151
        int err;
152
        int fd;
153
 
154
        self = find_task(self_tid());
155
        if ((fd = sys_open(self, filename, O_RDONLY, 0)) < 0)
156
                return fd;
157
 
158
        /* Get the low-level vmfile */
159
        vmfile = self->files->fd[fd].vmfile;
160
 
161
        /* Create a new tcb */
162
        if (IS_ERR(new_task = tcb_alloc_init(TCB_NO_SHARING))) {
163
                sys_close(self, fd);
164
                return (int)new_task;
165
        }
166
 
167
        /*
168
         * Fill and validate tcb memory
169
         * segment markers from executable file
170
         */
171
        if ((err = task_setup_from_executable(vmfile,
172
                                              new_task,
173
                                              &efd)) < 0) {
174
                sys_close(self, fd);
175
                kfree(new_task);
176
                return err;
177
        }
178
 
179
        /*
180
         * If sender is a thread in a group, need to find the
181
         * group leader and destroy all threaded children in
182
         * the group.
183
         */
184
        if (sender->clone_flags & TCB_SHARED_TGROUP) {
185
                struct tcb *thread;
186
 
187
                /* Find the thread group leader of sender */
188
                BUG_ON(!(tgleader = find_task(sender->tgid)));
189
 
190
                /* Destroy all children threads. */
191
                list_foreach_struct(thread,
192
                                    &tgleader->children,
193
                                    child_ref)
194
                        do_exit(thread, 0);
195
        } else {
196
                /* Otherwise group leader is same as sender */
197
                tgleader = sender;
198
        }
199
 
200
        /*
201
         * Copy data to be retained from exec'ing task to new one.
202
         * Release all task resources, do everything done in
203
         * exit() except destroying the actual thread.
204
         */
205
        if ((err = execve_recycle_task(new_task, tgleader)) < 0) {
206
                sys_close(self, fd);
207
                kfree(new_task);
208
                return err;
209
        }
210
 
211
        /* Map task's new segment markers as virtual memory regions */
212
        if ((err = task_mmap_segments(new_task, vmfile,
213
                                      &efd, args, env)) < 0) {
214
                sys_close(self, fd);
215
                kfree(new_task);
216
                return err;
217
        }
218
 
219
        /* Set up task registers via exchange_registers() */
220
        task_setup_registers(new_task, 0,
221
                             new_task->args_start,
222
                             new_task->pagerid);
223
 
224
        /* Add new task to global list */
225
        global_add_task(new_task);
226
 
227
        /* Start the task */
228
        task_start(new_task);
229
 
230
        return 0;
231
}
232
 
233
int sys_execve(struct tcb *sender, char *pathname,
234
               char *argv[], char *envp[])
235
{
236
        int ret;
237
        char *path;
238
        struct args_struct args;
239
        struct args_struct env;
240
 
241
        if (!(path = kzalloc(PATH_MAX)))
242
                return -ENOMEM;
243
 
244
        memset(&args, 0, sizeof(args));
245
        memset(&env, 0, sizeof(env));
246
 
247
        /* Copy the executable path string */
248
        if ((ret = copy_user_string(sender, path,
249
                                    pathname, PATH_MAX)) < 0)
250
                return ret;
251
 
252
        /* Copy the args */
253
        if (argv && ((ret = copy_user_args(sender, &args,
254
                                           argv, ARGS_MAX)) < 0))
255
                goto out1;
256
 
257
        /* Copy the env */
258
        if (envp && ((ret = copy_user_args(sender, &env, envp,
259
                                           ARGS_MAX - args.size))
260
                     < 0))
261
                goto out2;
262
 
263
        ret = do_execve(sender, path, &args, &env);
264
 
265
        if (env.argv)
266
                kfree(env.argv);
267
out2:
268
        if (args.argv)
269
                kfree(args.argv);
270
out1:
271
        kfree(path);
272
        return ret;
273
}
274
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.