Hella ABI changes for ELF dynamic linking
authorAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Wed, 10 Feb 2010 08:44:38 +0000 (00:44 -0800)
committerKevin Klues <klueska@ros-dev.(none)>
Wed, 24 Mar 2010 19:09:50 +0000 (12:09 -0700)
  1) sys_exec now takes a filename, not a binary blob

  2) load_elf does the grunt work of mmap()ing a program.
     it's hella fast!

  3) added some cruft to tell the dynamic linker about the
     program it's supposed to operate on (entry point,
     elf headers, etc.)

17 files changed:
.gitignore
kern/include/elf.h
kern/include/ros/mman.h
kern/include/ros/procinfo.h
kern/include/ros/syscall.h
kern/include/syscall.h
kern/src/Makefrag
kern/src/elf.c [new file with mode: 0644]
kern/src/kfs.c
kern/src/manager.c
kern/src/mm.c
kern/src/syscall.c
user/apps/parlib/run_binary.c
user/parlib/inc/parlib.h
user/parlib/src/parlibmain.c
user/parlib/src/sparc/newlib_backend.c
user/parlib/src/syscall.c

index ccb6dc2..9563c36 100644 (file)
@@ -22,6 +22,7 @@ kern/include/arch
 kern/src/arch
 Documentation/doxygen/rosdoc
 sim/
+fs
 tools/.*
 tools/syscall_server/syscall_server_*
 tools/syscall_server/sandbox/
index d2ac247..56f95c1 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef ROS_INC_ELF_H
 #define ROS_INC_ELF_H
 
+#include <process.h>
 #include <ros/common.h>
 
 #if defined(LITTLE_ENDIAN)
@@ -53,8 +54,12 @@ typedef struct Secthdr {
        uint32_t sh_entsize;
 } secthdr_t;
 
+typedef long elf_aux_t[2];
+
 // Values for Proghdr::p_type
 #define ELF_PROG_LOAD          1
+#define ELF_PROG_INTERP                3
+#define ELF_PROG_PHDR          6
 
 // Flag bits for Proghdr::p_flags
 #define ELF_PROG_FLAG_EXEC     1
@@ -70,4 +75,12 @@ typedef struct Secthdr {
 // Values for Secthdr::sh_name
 #define ELF_SHN_UNDEF          0
 
+// Values for auxiliary fields
+#define ELF_AUX_PHDR           3
+#define ELF_AUX_PHENT          4
+#define ELF_AUX_PHNUM          5
+#define ELF_AUX_ENTRY          9
+
+int load_elf(struct proc* p, const char* fn);
+
 #endif /* !ROS_INC_ELF_H */
index 8da4bb1..26dd516 100644 (file)
@@ -37,6 +37,8 @@
 #define MAP_NONBLOCK   0x10000
 #define MAP_STACK              0x20000
 
+#define MAP_FAILED             ((void*)-1)
+
 /* Other mmap flags, which we probably won't support
 #define MAP_32BIT
 */
index 02baf32..ee6216d 100644 (file)
@@ -6,8 +6,8 @@
 #include <ros/memlayout.h>
 #include <ros/common.h>
 
-#define PROCINFO_MAX_ARGV_SIZE 1024
-#define PROCINFO_MAX_ENV_SIZE 1024
+#define PROCINFO_MAX_ARGP 32
+#define PROCINFO_ARGBUF_SIZE 3072
 
 typedef struct procinfo {
        pid_t pid;
@@ -15,9 +15,45 @@ typedef struct procinfo {
        size_t max_harts;
        uint64_t tsc_freq;
 
-       char argv_buf[PROCINFO_MAX_ARGV_SIZE];
-       char env_buf[PROCINFO_MAX_ENV_SIZE];
+       char* argp[PROCINFO_MAX_ARGP];
+       char argbuf[PROCINFO_ARGBUF_SIZE];
 } procinfo_t;
 #define PROCINFO_NUM_PAGES  ((sizeof(procinfo_t)-1)/PGSIZE + 1)        
 
+static int
+procinfo_pack_args(procinfo_t* p, char* const* argv, char* const* envp)
+{
+       int nargv = 0, nenvp = 0;
+       if(argv) while(argv[nargv]) nargv++;
+       if(envp) while(envp[nenvp]) nenvp++;
+
+       if(nargv+nenvp+2 > PROCINFO_MAX_ARGP)
+               return -1;
+
+       int pos = 0;
+       for(int i = 0; i < nargv; i++)
+       {
+               int len = strlen(argv[i])+1;
+               if(pos+len > PROCINFO_ARGBUF_SIZE)
+                       return -1;
+               p->argp[i] = ((procinfo_t*)UINFO)->argbuf+pos;
+               memcpy(p->argbuf+pos,argv[i],len);
+               pos += len;
+       }
+       p->argp[nargv] = 0;
+
+       for(int i = 0; i < nenvp; i++)
+       {
+               int len = strlen(envp[i])+1;
+               if(pos+len > PROCINFO_ARGBUF_SIZE)
+                       return -1;
+               p->argp[nargv+1+i] = ((procinfo_t*)UINFO)->argbuf+pos;
+               memcpy(p->argbuf+pos,envp[i],len);
+               pos += len;
+       }
+       p->argp[nargv+nenvp+1] = 0;
+       
+       return 0;
+}   
+
 #endif // !ROS_PROCDATA_H
index b5b0447..1c5e5b0 100644 (file)
@@ -68,4 +68,7 @@
 #define BUSTER_PRINT_TICKS             0x0008
 #define BUSTER_JUST_LOCKS              0x0010 // unimplemented
 
+// for system calls that pass filenames
+#define MAX_PATH_LEN 256
+
 #endif /* !ROS_INCLUDE_SYSCALL_H */
index 459aa90..4d22e31 100644 (file)
@@ -38,5 +38,5 @@ intreg_t sys_getcwd(struct proc* p, char* pwd, int size);
 intreg_t sys_gettimeofday(struct proc* p, int* buf);
 intreg_t sys_tcsetattr(struct proc* p, int fd, int optional_actions, const void* termios_p);
 intreg_t sys_tcgetattr(struct proc* p, int fd, void* termios_p);
-
+intreg_t sys_exec(struct proc* p, const char fn[MAX_PATH_LEN], procinfo_t* pi);
 #endif /* !ROS_KERN_SYSCALL_H */
index 42d707d..0b5f04a 100644 (file)
@@ -38,16 +38,17 @@ KERN_SRCFILES := $(KERN_ARCH_SRCFILES) \
                  $(KERN_SRC_DIR)/mm.c \
                  $(KERN_SRC_DIR)/resource.c \
                  $(KERN_SRC_DIR)/slab.c \
+                 $(KERN_SRC_DIR)/elf.c \
                  $(KERN_SRC_DIR)/testing.c
 
 # Only build files if they exist.
 KERN_SRCFILES := $(wildcard $(KERN_SRCFILES))
 
 KERN_APPFILES := \
-                 $(USER_APPS_PARLIB_DIR)/matrix
 
 ifeq ($(TARGET_ARCH),i386)
 KERN_APPFILES += \
+                 $(USER_APPS_PARLIB_DIR)/matrix \
                  $(USER_APPS_ROSLIB_DIR)/proctests \
                  $(USER_APPS_ROSLIB_DIR)/fptest \
                  $(USER_APPS_ROSLIB_DIR)/null \
diff --git a/kern/src/elf.c b/kern/src/elf.c
new file mode 100644 (file)
index 0000000..ee0e48f
--- /dev/null
@@ -0,0 +1,164 @@
+#include <mm.h>
+#include <ros/mman.h>
+#include <kmalloc.h>
+#include <syscall.h>
+#include <elf.h>
+#include <pmap.h>
+
+struct elf_info
+{
+       long entry;
+       long phdr;
+       int phnum;
+       int dynamic;
+       char interp[256];
+};
+
+int load_one_elf(struct proc* p, int fd, struct elf_info* ei)
+{
+       int ret = -1;
+       ei->phdr = -1;
+       ei->dynamic = 0;
+
+       char* elf = (char*)kmalloc(PGSIZE,0);
+       if(!elf || read_page(p,fd,PADDR(elf),0) == -1)
+               goto fail;
+
+       elf_t* elfhdr = (elf_t*)elf;
+       proghdr_t* proghdrs = (proghdr_t*)(elf+elfhdr->e_phoff);
+       if(elfhdr->e_phoff+elfhdr->e_phnum*sizeof(proghdr_t) > PGSIZE)
+               goto fail;
+       if(elfhdr->e_phentsize != sizeof(proghdr_t))
+               goto fail;
+
+       for(int i = 0; i < elfhdr->e_phnum; i++)
+       {
+               proghdr_t* ph = proghdrs+i;
+               if(ph->p_type == ELF_PROG_PHDR)
+                       ei->phdr = ph->p_va;
+               if(ph->p_type == ELF_PROG_INTERP)
+               {
+                       int maxlen = MIN(PGSIZE-ph->p_offset,sizeof(ei->interp));
+                       int len = strnlen(elf+ph->p_offset,maxlen);
+                       if(len < maxlen)
+                       {
+                               memcpy(ei->interp,elf+ph->p_offset,maxlen+1);
+                               ei->dynamic = 1;
+                       }
+                       else
+                               goto fail;
+               }
+
+               if(ph->p_type == ELF_PROG_LOAD && ph->p_memsz)
+               {
+                       if(ph->p_align % PGSIZE)
+                               goto fail;
+                       if(ph->p_offset % PGSIZE != ph->p_va % PGSIZE)
+                               goto fail;
+
+                       uintptr_t filestart = ROUNDDOWN(ph->p_offset,PGSIZE);
+                       uintptr_t fileend = ph->p_offset+ph->p_filesz;
+                       uintptr_t filesz = fileend-filestart;
+
+                       uintptr_t memstart = ROUNDDOWN(ph->p_va,PGSIZE);
+                       uintptr_t memend = ROUNDUP(ph->p_va + ph->p_memsz,PGSIZE);
+                       uintptr_t memsz = memend-memstart;
+
+                       // mmap will zero the rest of the page if filesz % PGSIZE != 0
+                       if(filesz)
+                               if(mmap(p, memstart, filesz,
+                                       PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED,
+                                       fd, filestart/PGSIZE) == MAP_FAILED)
+                                       goto fail;
+
+                       filesz = ROUNDUP(filesz,PGSIZE);
+                       if(filesz < memsz)
+                               if(mmap(p, memstart+filesz, memsz-filesz,
+                                       PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_ANON,
+                                       -1, 0) == MAP_FAILED)
+                                       goto fail;
+               }
+       }
+
+       ei->entry = elfhdr->e_entry;
+       ei->phnum = elfhdr->e_phnum;
+
+       ret = 0;
+fail:
+       kfree(elf);
+       return ret;
+}
+
+int load_elf(struct proc* p, const char* fn)
+{
+       struct elf_info ei,interp_ei;
+       int fd = open_file(p,fn,0,0);
+       if(fd == -1 || load_one_elf(p,fd,&ei))
+               return -1;
+       close_file(p,fd);
+
+       if(ei.dynamic)
+       {
+               int fd2 = open_file(p,ei.interp,0,0);
+               if(fd2 == -1 || load_one_elf(p,fd2,&interp_ei))
+                       return -1;
+               close_file(p,fd2);
+
+               // fill in info for dynamic linker
+               elf_aux_t auxp[] = {{ELF_AUX_PHDR,ei.phdr},
+                                   {ELF_AUX_PHENT,sizeof(proghdr_t)},
+                                   {ELF_AUX_PHNUM,ei.phnum},
+                                   {ELF_AUX_ENTRY,ei.entry},
+                                   {0,0}};
+
+               // put auxp after argv, envp in procinfo
+               int auxp_pos = -1;
+               for(int i = 0, zeros = 0; i < PROCINFO_MAX_ARGP; i++)
+                       if(p->env_procinfo->argp[i] == NULL)
+                               if(++zeros == 2)
+                                       auxp_pos = i+1;
+               if(auxp_pos == -1 ||
+                  auxp_pos+sizeof(auxp)/sizeof(char*) >= PROCINFO_MAX_ARGP)
+                       return -1;
+               memcpy(p->env_procinfo->argp+auxp_pos,auxp,sizeof(auxp));
+       }
+
+       p->env_entry = ei.dynamic ? interp_ei.entry : ei.entry;
+       proc_set_program_counter(&p->env_tf,p->env_entry);
+
+       uintptr_t stacksz = USTACK_NUM_PAGES*PGSIZE;
+       if(mmap(p,USTACKTOP-stacksz,stacksz,PROT_READ|PROT_WRITE,
+               MAP_FIXED|MAP_ANON,-1,0) == MAP_FAILED)
+               return -1;
+
+       return 0;
+}
+
+intreg_t sys_exec(struct proc* p, const char fn[MAX_PATH_LEN], procinfo_t* pi)
+{
+       if(p->state != PROC_RUNNING_S)
+               return -1;
+
+       char kfn[PGSIZE];
+       if(memcpy_from_user(p,kfn,fn,PGSIZE))
+               return -1;
+
+       if(memcpy_from_user(p,p->env_procinfo,pi,sizeof(procinfo_t)))
+       {
+               proc_destroy(p);
+               return -1;
+       }
+       proc_init_procinfo(p);
+
+       env_segment_free(p,0,USTACKTOP);
+       proc_init_trapframe(current_tf,0);
+
+       if(load_elf(p,kfn))
+       {
+               proc_destroy(p);
+               return -1;
+       }
+
+       return 0;
+}
+
index 08e09b9..4e02d08 100644 (file)
@@ -28,8 +28,8 @@
  * userapps in kern/src/Makefrag.
  * Make sure to declare it, and add an entry.  Keep MAX_KFS_FILES big enough too
  */
-DECL_PROG(parlib_matrix);
 #ifdef __i386__
+DECL_PROG(parlib_matrix);
 DECL_PROG(roslib_proctests);
 DECL_PROG(roslib_fptest);
 DECL_PROG(roslib_null);
@@ -49,8 +49,8 @@ DECL_PROG(parlib_lock_test);
 #endif
 
 struct kfs_entry kfs[MAX_KFS_FILES] = {
-       KFS_ENTRY(parlib_matrix)
 #ifdef __i386__
+       KFS_ENTRY(parlib_matrix)
        KFS_ENTRY(roslib_proctests)
        KFS_ENTRY(roslib_fptest)
        KFS_ENTRY(roslib_null)
index 78876c1..5d3265d 100644 (file)
@@ -12,7 +12,9 @@
 #include <smp.h>
 #include <arch/init.h>
 #include <mm.h>
+#include <elf.h>
 
+#include <kmalloc.h>
 #include <assert.h>
 #include <manager.h>
 #include <process.h>
@@ -193,6 +195,15 @@ void manager_klueska()
        panic("DON'T PANIC");
 }
 
+struct elf_info
+{
+       long entry;
+       long phdr;
+       int phnum;
+       int dynamic;
+       char interp[256];
+};
+
 void manager_waterman()
 {
 #ifndef __i386__
@@ -201,47 +212,13 @@ void manager_waterman()
        {
                init = 1;
                struct proc* p = proc_create(NULL,0);
-               int fd = open_file(p,"/lib/ld.so.1",0,0);
-
-               const int MAX_LDSO_PAGES = 256;
-               static int buf[PGSIZE*MAX_LDSO_PAGES/sizeof(int)];
-               for(int i = 0; read_page(p,fd,PADDR((char*)buf+PGSIZE*i),i) == PGSIZE; i++);
-               close_file(p,fd);
-
-               env_load_icode(p,NULL,(void*)buf,MAX_LDSO_PAGES*PGSIZE);
-
-               int pack(struct proc* p, uintptr_t base, int sz, char** args)
-               {
-                       int argc = 0;
-                       while(args[argc])
-                               argc++;
-
-                       uintptr_t* argv = (uintptr_t*)((uintptr_t)p->env_procinfo+base);
-                       int pos = (argc+1)*sizeof(char*);
-                       if(pos > sz)
-                               return -1;
-
-                       argv[0] = UINFO+base+(argc+1)*sizeof(char*);
-                       for(int i = 0; i < argc; i++)
-                       {
-                               int len = strlen(args[i])+1;
-                               if(pos+len > sz)
-                                       return -1;
-
-                               memcpy((char*)argv+pos,args[i],len);
-                               pos += len;
-                               argv[i+1] = argv[i]+len;
-                       }
-                       argv[argc] = 0;
-
-                       return 0;
-               }
-
-               char* argv[] = {"/lib/ld.so.1","/bin/sh","-l",0};
-               char* env[] = {"LD_LIBRARY_PATH=/lib",0};
-
-               pack(p,offsetof(procinfo_t,argv_buf),PROCINFO_MAX_ARGV_SIZE,argv);
-               pack(p,offsetof(procinfo_t,env_buf),PROCINFO_MAX_ENV_SIZE,env);
+
+               char* argv[] = {"/bin/sh","-l",0};
+               char* envp[] = {"LD_LIBRARY_PATH=/lib",0};
+               procinfo_pack_args(p->env_procinfo,argv,envp);
+
+               assert(load_elf(p,"/bin/busybox") == 0);
+
                __proc_set_state(p, PROC_RUNNABLE_S);
                proc_run(p);
        }
index f1ff912..75e6c14 100644 (file)
@@ -70,8 +70,14 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                // This is dumb--should not read until faulted in.
                // This is just to get it correct at first
                if(!(flags & MAP_ANON))
+               {
                        if(read_page(p,fd,page2pa(a_page),offset+i) < 0)
                                goto mmap_abort;
+
+                       // zero-fill end of last page
+                       if(len % PGSIZE && i == num_pages-1)
+                               memset(page2kva(a_page)+len%PGSIZE,0,PGSIZE-len%PGSIZE);
+               }
                #endif
 
                // TODO: TLB shootdown if replacing an old mapping
index 7108a3e..76004ad 100644 (file)
@@ -192,7 +192,6 @@ static pid_t sys_getpid(struct proc *p)
  */
 static int sys_proc_create(struct proc *p, const char *DANGEROUS path)
 {
-       #define MAX_PATH_LEN 256 // totally arbitrary
        int pid = 0;
        char tpath[MAX_PATH_LEN];
        /*
@@ -279,14 +278,14 @@ static int sys_proc_yield(struct proc *p)
 }
 
 static ssize_t sys_run_binary(env_t* e, void *DANGEROUS binary_buf, size_t len,
-                              void*DANGEROUS arg, size_t num_colors)
+                              procinfo_t*DANGEROUS procinfo, size_t num_colors)
 {
        env_t* env = proc_create(NULL,0);
        assert(env != NULL);
 
-       static_assert(PROCINFO_NUM_PAGES == 1);
-       assert(memcpy_from_user(e,env->env_procinfo->argv_buf,arg,PROCINFO_MAX_ARGV_SIZE) == ESUCCESS);
-       *(intptr_t*)env->env_procinfo->env_buf = 0;
+       if(memcpy_from_user(e,e->env_procinfo,procinfo,sizeof(*procinfo)))
+               return -1;
+       proc_init_procinfo(e);
 
        env_load_icode(env,e,binary_buf,len);
        __proc_set_state(env, PROC_RUNNABLE_S);
@@ -358,35 +357,6 @@ static ssize_t sys_fork(env_t* e)
        return env->pid;
 }
 
-static ssize_t sys_exec(env_t* e, void *DANGEROUS binary_buf, size_t len,
-                        procinfo_t*DANGEROUS procinfo)
-{
-       // TODO: right now we only support exec for single-core processes
-       if(e->state != PROC_RUNNING_S)
-               return -1;
-
-       if(memcpy_from_user(e,e->env_procinfo,procinfo,sizeof(*procinfo)))
-               return -1;
-       proc_init_procinfo(e);
-
-       void* binary = kmalloc(len,0);
-       if(binary == NULL)
-               return -1;
-       if(memcpy_from_user(e,binary,binary_buf,len))
-       {
-               kfree(binary);
-               return -1;
-       }
-
-       env_segment_free(e,0,USTACKTOP);
-
-       proc_init_trapframe(current_tf,0);
-       env_load_icode(e,NULL,binary,len);
-
-       kfree(binary);
-       return 0;
-}
-
 static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
 {
        struct proc* p = pid2proc(pid);
index e46c4e6..b25c9dd 100644 (file)
@@ -16,6 +16,7 @@ int shell_exec(const char* cmdline)
        #define MY_MAX_ARGV 16
        char* argv[MY_MAX_ARGV+1] = {0};
        char* p0 = strdup(cmdline);
+       assert(p0);
        char* p = p0;
        for(int i = 0; i < MY_MAX_ARGV; i++)
        {
@@ -95,12 +96,13 @@ extern char * readline(const char *prompt);
 #define MALLOC_SIZE     1048576
 #define READ_SIZE       1024
 
+#if 0
 int run_binary_filename(const char* cmdline, size_t colors)
 {
        int ret = 0;
 
        const char* cmdptr = cmdline;
-       char argv_buf[PROCINFO_MAX_ARGV_SIZE] = {0};
+       char argv_buf[PROCINFO_ARGBUF_SIZE] = {0};
        intreg_t* argv = (intreg_t*)argv_buf;
        argv[0] = 0;
        int argc;
@@ -186,6 +188,7 @@ realloc_error:
 open_error:
        return ret;
 }
+#endif
 
 void run_binary(size_t colors)
 {
@@ -194,6 +197,6 @@ void run_binary(size_t colors)
                printf("Error reading from console.\n");
                return;
        }
-       run_binary_filename(readline_result, colors);
+       shell_exec(readline_result);
+       //run_binary_filename(readline_result, colors);
 }
-
index b7a83e9..6735977 100644 (file)
@@ -41,7 +41,7 @@ ssize_t     sys_eth_read(void *COUNT(len) buf);
 ssize_t     sys_eth_get_mac_addr(void* buf);
 int         sys_eth_recv_check();
 ssize_t     sys_run_binary(void* binary_buf, size_t len,
-                           char arg[PROCINFO_MAX_ARGV_SIZE], size_t num_colors);
+                           procinfo_t* procinfo, size_t num_colors);
 int         sys_getpid(void);
 size_t      sys_getcpuid(void);
 void *      sys_brk(void* addr);
index 2276833..8c9c7fc 100644 (file)
@@ -37,24 +37,6 @@ void parlib_ctors()
                ((ctor*)__CTOR_LIST__)[nctor-i-1]();
 }
 
-// build argv from procinfo.argv_buf
-char** parlib_build_argc_argv(char* buf, int* argc)
-{
-       char** offset = (char**)buf;
-       for(*argc = 0; offset[*argc]; (*argc)++)
-               ;
-
-       char** argv = (char**)malloc((*argc+1)*sizeof(char*));
-       assert(argv);
-       for(int i = 0; i < *argc; i++)
-       {
-               argv[i] = strdup(offset[i]);
-               assert(argv[i]);
-       }
-       argv[*argc] = 0;
-       return argv;
-}
-
 struct timeval timeval_start;
 
 // the first time any thread enters, it calls this function
@@ -96,9 +78,14 @@ void parlib_main()
        atexit(&parlib_dtors);
 
        // set up argc/argv/envp
-       int argc,envc;
-       char** argv = parlib_build_argc_argv(procinfo.argv_buf,&argc);
-       environ = parlib_build_argc_argv(procinfo.env_buf,&envc);
+       int argc = 0;
+       while(procinfo.argp[argc])
+               argc++;
+       char** argv = (char**)alloca(sizeof(char*)*(argc+1));
+       for(int i = 0; i < argc; i++)
+               argv[i] = strdup(procinfo.argp[i]);
+       argv[argc] = 0;
+       environ = procinfo.argp+argc+1;
 
        // call user main routine
        extern int main(int argc, char * NTS * COUNT(argc) NT argv,
index 81f612c..10aa100 100644 (file)
@@ -422,94 +422,17 @@ fork(void)
        return ret;
 }
 
-static int
-pack_argv(const char* const argv[], void* base, char* buf, size_t bufsz)
-{
-       int argc = 0, size = sizeof(intreg_t);
-       while(argv[argc])
-       {
-               size += sizeof(intreg_t)+strlen(argv[argc])+1;
-               argc++;
-       }
-
-       if(size > bufsz)
-               return -1;
-
-       intreg_t* offset = (intreg_t*)buf;
-       offset[0] = (argc+1)*sizeof(intreg_t)+(intreg_t)base;
-       for(int i = 0; i < argc; i++)
-       {
-               int len = strlen(argv[i])+1;
-               memcpy(buf+offset[i]-(intreg_t)base,argv[i],len);
-               offset[i+1] = offset[i]+len;
-       }
-       offset[argc] = 0;
-
-       return 0;
-}
-
-static int
-readfile(const char* filename, void** binary, int* size)
-{
-       int fd = open(filename,O_RDONLY,0);
-       if(fd == -1)
-               return -1;
-
-       *size = 0;
-       *binary = NULL;
-       int bytes_read = 0;
-       int bufsz = 0;
-
-       int READ_SIZE = 1024;
-       int MALLOC_SIZE = 1024*1024;
-
-       while(1)
-       {
-               if(*size+READ_SIZE > bufsz)
-               {
-                       void* temp_buf = realloc(*binary,bufsz+MALLOC_SIZE);
-                       if(temp_buf == NULL)
-                       {
-                               close(fd);
-                               free(*binary);
-                               errno = ENOMEM;
-                               return -1;
-                       }
-
-                       *binary = temp_buf;
-                       bufsz += MALLOC_SIZE;
-               }
-
-               bytes_read = read(fd, *binary+*size, READ_SIZE);
-               *size += bytes_read;
-               if(bytes_read <= 0)
-               {
-                       close(fd);
-                       if(bytes_read < 0)
-                               free(*binary);
-                       return bytes_read;
-               }
-       }
-}
-
 int
 execve(const char* name, char* const argv[], char* const env[])
 {
        procinfo_t pi;
-       if(pack_argv(argv,procinfo.argv_buf,pi.argv_buf,PROCINFO_MAX_ARGV_SIZE)
-          || pack_argv(env,procinfo.env_buf,pi.env_buf,PROCINFO_MAX_ENV_SIZE))
-       {
-               errno = ENOMEM;
-               return -1;
-       }
+       procinfo_pack_args(&pi,argv,env);
 
-       void* binary;
-       size_t binarysz;
-       if(readfile(name,&binary,&binarysz))
+       char name2[MAX_PATH_LEN];
+       if(strncpy(name2,name,MAX_PATH_LEN) == MAX_PATH_LEN)
                return -1;
-
-       return syscall(SYS_exec,(intreg_t)binary,(intreg_t)binarysz,
-                       (intreg_t)&pi,0,0);
+       
+       return syscall(SYS_exec,(intreg_t)name,(intreg_t)&pi,0,0,0);
 }
 
 int
index cc51adc..ab52e0c 100644 (file)
@@ -59,10 +59,10 @@ ssize_t sys_serial_read(void* buf, size_t len)
 
 //Run a binary loaded at the specificed address with the specified arguments
 ssize_t sys_run_binary(void* binary_buf, size_t len,
-                       char arg[PROCINFO_MAX_ARGV_SIZE], size_t num_colors) 
+                       procinfo_t* procinfo, size_t num_colors) 
 {
        return syscall(SYS_run_binary, (intreg_t)binary_buf, (intreg_t)len,
-                                       (intreg_t)arg,(intreg_t)num_colors,0);
+                                   (intreg_t)procinfo,(intreg_t)num_colors, 0);
 }
 
 //Write a buffer over ethernet